Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrGLVertexArray.h"
      9 #include "GrGLGpu.h"
     10 
     11 struct AttribLayout {
     12     GrGLint     fCount;
     13     GrGLenum    fType;
     14     GrGLboolean fNormalized;  // Only used by floating point types.
     15 };
     16 
     17 static const AttribLayout gLayouts[kGrVertexAttribTypeCount] = {
     18     {1, GR_GL_FLOAT, false},         // kFloat_GrVertexAttribType
     19     {2, GR_GL_FLOAT, false},         // kVec2f_GrVertexAttribType
     20     {3, GR_GL_FLOAT, false},         // kVec3f_GrVertexAttribType
     21     {4, GR_GL_FLOAT, false},         // kVec4f_GrVertexAttribType
     22     {1, GR_GL_UNSIGNED_BYTE, true},  // kUByte_GrVertexAttribType
     23     {4, GR_GL_UNSIGNED_BYTE, true},  // kVec4ub_GrVertexAttribType
     24     {2, GR_GL_UNSIGNED_SHORT, true}, // kVec2s_GrVertexAttribType
     25     {1, GR_GL_INT, false},           // kInt_GrVertexAttribType
     26     {1, GR_GL_UNSIGNED_INT, false},  // kUint_GrVertexAttribType
     27 };
     28 
     29 GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
     30 GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
     31 GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
     32 GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
     33 GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
     34 GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
     35 GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
     36 GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
     37 GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);
     38 
     39 void GrGLAttribArrayState::set(GrGLGpu* gpu,
     40                                int index,
     41                                GrGLuint vertexBufferID,
     42                                GrVertexAttribType type,
     43                                GrGLsizei stride,
     44                                GrGLvoid* offset) {
     45     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
     46     AttribArrayState* array = &fAttribArrayStates[index];
     47     if (!array->fEnableIsValid || !array->fEnabled) {
     48         GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
     49         array->fEnableIsValid = true;
     50         array->fEnabled = true;
     51     }
     52     if (!array->fAttribPointerIsValid ||
     53         array->fVertexBufferID != vertexBufferID ||
     54         array->fType != type ||
     55         array->fStride != stride ||
     56         array->fOffset != offset) {
     57 
     58         gpu->bindVertexBuffer(vertexBufferID);
     59         const AttribLayout& layout = gLayouts[type];
     60         if (!GrVertexAttribTypeIsIntType(type)) {
     61             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
     62                                                                layout.fCount,
     63                                                                layout.fType,
     64                                                                layout.fNormalized,
     65                                                                stride,
     66                                                                offset));
     67         } else {
     68             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
     69             SkASSERT(!layout.fNormalized);
     70             GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
     71                                                                 layout.fCount,
     72                                                                 layout.fType,
     73                                                                 stride,
     74                                                                 offset));
     75         }
     76         array->fAttribPointerIsValid = true;
     77         array->fVertexBufferID = vertexBufferID;
     78         array->fType = type;
     79         array->fStride = stride;
     80         array->fOffset = offset;
     81     }
     82 }
     83 
     84 void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
     85     int count = fAttribArrayStates.count();
     86     for (int i = 0; i < count; ++i) {
     87         if (!(usedMask & 0x1)) {
     88             if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
     89                 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
     90                 fAttribArrayStates[i].fEnableIsValid = true;
     91                 fAttribArrayStates[i].fEnabled = false;
     92             }
     93         } else {
     94             SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
     95         }
     96         // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
     97         usedMask >>= 1;
     98     }
     99 }
    100 
    101 ///////////////////////////////////////////////////////////////////////////////////////////////////
    102 
    103 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
    104     : fID(id)
    105     , fAttribArrays(attribCount)
    106     , fIndexBufferIDIsValid(false) {
    107 }
    108 
    109 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
    110     if (0 == fID) {
    111         return nullptr;
    112     }
    113     gpu->bindVertexArray(fID);
    114     return &fAttribArrays;
    115 }
    116 
    117 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, GrGLuint ibufferID) {
    118     GrGLAttribArrayState* state = this->bind(gpu);
    119     if (state) {
    120         if (!fIndexBufferIDIsValid || ibufferID != fIndexBufferID) {
    121             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibufferID));
    122             fIndexBufferIDIsValid = true;
    123             fIndexBufferID = ibufferID;
    124         }
    125     }
    126     return state;
    127 }
    128 
    129 void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) {
    130     if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) {
    131         fIndexBufferID = 0;
    132     }
    133  }
    134 
    135 void GrGLVertexArray::invalidateCachedState() {
    136     fAttribArrays.invalidate();
    137     fIndexBufferIDIsValid = false;
    138 }
    139