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 "GrGLBuffer.h"
     10 #include "GrGLGpu.h"
     11 
     12 struct AttribLayout {
     13     bool        fNormalized;  // Only used by floating point types.
     14     uint8_t     fCount;
     15     uint16_t    fType;
     16 };
     17 
     18 GR_STATIC_ASSERT(4 == sizeof(AttribLayout));
     19 
     20 static AttribLayout attrib_layout(GrVertexAttribType type) {
     21     switch (type) {
     22         case kFloat_GrVertexAttribType:
     23             return {false, 1, GR_GL_FLOAT};
     24         case kVec2f_GrVertexAttribType:
     25             return {false, 2, GR_GL_FLOAT};
     26         case kVec3f_GrVertexAttribType:
     27             return {false, 3, GR_GL_FLOAT};
     28         case kVec4f_GrVertexAttribType:
     29             return {false, 4, GR_GL_FLOAT};
     30         case kVec2i_GrVertexAttribType:
     31             return {false, 2, GR_GL_INT};
     32         case kVec3i_GrVertexAttribType:
     33             return {false, 3, GR_GL_INT};
     34         case kVec4i_GrVertexAttribType:
     35             return {false, 4, GR_GL_INT};
     36         case kUByte_GrVertexAttribType:
     37             return {true, 1, GR_GL_UNSIGNED_BYTE};
     38         case kVec4ub_GrVertexAttribType:
     39             return {true, 4, GR_GL_UNSIGNED_BYTE};
     40         case kVec2us_GrVertexAttribType:
     41             return {true, 2, GR_GL_UNSIGNED_SHORT};
     42         case kInt_GrVertexAttribType:
     43             return {false, 1, GR_GL_INT};
     44         case kUint_GrVertexAttribType:
     45             return {false, 1, GR_GL_UNSIGNED_INT};
     46     }
     47     SkFAIL("Unknown vertex attrib type");
     48     return {false, 0, 0};
     49 };
     50 
     51 void GrGLAttribArrayState::set(GrGLGpu* gpu,
     52                                int index,
     53                                const GrBuffer* vertexBuffer,
     54                                GrVertexAttribType type,
     55                                GrGLsizei stride,
     56                                GrGLvoid* offset) {
     57     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
     58     AttribArrayState* array = &fAttribArrayStates[index];
     59     if (!array->fEnableIsValid || !array->fEnabled) {
     60         GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
     61         array->fEnableIsValid = true;
     62         array->fEnabled = true;
     63     }
     64     if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
     65         array->fType != type ||
     66         array->fStride != stride ||
     67         array->fOffset != offset) {
     68         gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
     69         const AttribLayout& layout = attrib_layout(type);
     70         if (!GrVertexAttribTypeIsIntType(type)) {
     71             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
     72                                                                layout.fCount,
     73                                                                layout.fType,
     74                                                                layout.fNormalized,
     75                                                                stride,
     76                                                                offset));
     77         } else {
     78             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
     79             SkASSERT(!layout.fNormalized);
     80             GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
     81                                                                 layout.fCount,
     82                                                                 layout.fType,
     83                                                                 stride,
     84                                                                 offset));
     85         }
     86         array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
     87         array->fType = type;
     88         array->fStride = stride;
     89         array->fOffset = offset;
     90     }
     91 }
     92 
     93 void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
     94     int count = fAttribArrayStates.count();
     95     for (int i = 0; i < count; ++i) {
     96         if (!(usedMask & 0x1)) {
     97             if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
     98                 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
     99                 fAttribArrayStates[i].fEnableIsValid = true;
    100                 fAttribArrayStates[i].fEnabled = false;
    101             }
    102         } else {
    103             SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
    104         }
    105         // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
    106         usedMask >>= 1;
    107     }
    108 }
    109 
    110 ///////////////////////////////////////////////////////////////////////////////////////////////////
    111 
    112 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
    113     : fID(id)
    114     , fAttribArrays(attribCount)
    115     , fIndexBufferUniqueID(SK_InvalidUniqueID) {
    116 }
    117 
    118 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
    119     if (0 == fID) {
    120         return nullptr;
    121     }
    122     gpu->bindVertexArray(fID);
    123     return &fAttribArrays;
    124 }
    125 
    126 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
    127     GrGLAttribArrayState* state = this->bind(gpu);
    128     if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
    129         if (ibuff->isCPUBacked()) {
    130             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
    131         } else {
    132             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
    133             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
    134                                                       glBuffer->bufferID()));
    135         }
    136         fIndexBufferUniqueID = ibuff->uniqueID();
    137     }
    138     return state;
    139 }
    140 
    141 void GrGLVertexArray::invalidateCachedState() {
    142     fAttribArrays.invalidate();
    143     fIndexBufferUniqueID.makeInvalid();
    144 }
    145