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 kFloat2_GrVertexAttribType:
     25             return {false, 2, GR_GL_FLOAT};
     26         case kFloat3_GrVertexAttribType:
     27             return {false, 3, GR_GL_FLOAT};
     28         case kFloat4_GrVertexAttribType:
     29             return {false, 4, GR_GL_FLOAT};
     30         case kHalf_GrVertexAttribType:
     31             return {false, 1, GR_GL_FLOAT};
     32         case kHalf2_GrVertexAttribType:
     33             return {false, 2, GR_GL_FLOAT};
     34         case kHalf3_GrVertexAttribType:
     35             return {false, 3, GR_GL_FLOAT};
     36         case kHalf4_GrVertexAttribType:
     37             return {false, 4, GR_GL_FLOAT};
     38         case kInt2_GrVertexAttribType:
     39             return {false, 2, GR_GL_INT};
     40         case kInt3_GrVertexAttribType:
     41             return {false, 3, GR_GL_INT};
     42         case kInt4_GrVertexAttribType:
     43             return {false, 4, GR_GL_INT};
     44         case kUByte_norm_GrVertexAttribType:
     45             return {true, 1, GR_GL_UNSIGNED_BYTE};
     46         case kUByte4_norm_GrVertexAttribType:
     47             return {true, 4, GR_GL_UNSIGNED_BYTE};
     48         case kShort2_GrVertexAttribType:
     49             return {false, 2, GR_GL_SHORT};
     50         case kUShort2_GrVertexAttribType:
     51             return {false, 2, GR_GL_UNSIGNED_SHORT};
     52         case kUShort2_norm_GrVertexAttribType:
     53             return {true, 2, GR_GL_UNSIGNED_SHORT};
     54         case kInt_GrVertexAttribType:
     55             return {false, 1, GR_GL_INT};
     56         case kUint_GrVertexAttribType:
     57             return {false, 1, GR_GL_UNSIGNED_INT};
     58     }
     59     SK_ABORT("Unknown vertex attrib type");
     60     return {false, 0, 0};
     61 };
     62 
     63 static bool GrVertexAttribTypeIsIntType(const GrShaderCaps* shaderCaps,
     64                                         GrVertexAttribType type) {
     65     switch (type) {
     66         case kFloat_GrVertexAttribType:
     67             return false;
     68         case kFloat2_GrVertexAttribType:
     69             return false;
     70         case kFloat3_GrVertexAttribType:
     71             return false;
     72         case kFloat4_GrVertexAttribType:
     73             return false;
     74         case kHalf_GrVertexAttribType:
     75             return false;
     76         case kHalf2_GrVertexAttribType:
     77             return false;
     78         case kHalf3_GrVertexAttribType:
     79             return false;
     80         case kHalf4_GrVertexAttribType:
     81             return false;
     82         case kInt2_GrVertexAttribType:
     83             return true;
     84         case kInt3_GrVertexAttribType:
     85             return true;
     86         case kInt4_GrVertexAttribType:
     87             return true;
     88         case kUByte_norm_GrVertexAttribType:
     89             return false;
     90         case kUByte4_norm_GrVertexAttribType:
     91             return false;
     92         case kShort2_GrVertexAttribType:
     93             return true;
     94         case kUShort2_GrVertexAttribType:
     95             return shaderCaps->integerSupport(); // FIXME: caller should handle this.
     96         case kUShort2_norm_GrVertexAttribType:
     97             return false;
     98         case kInt_GrVertexAttribType:
     99             return true;
    100         case kUint_GrVertexAttribType:
    101             return true;
    102     }
    103     SK_ABORT("Unexpected attribute type");
    104     return false;
    105 }
    106 
    107 void GrGLAttribArrayState::set(GrGLGpu* gpu,
    108                                int index,
    109                                const GrBuffer* vertexBuffer,
    110                                GrVertexAttribType type,
    111                                GrGLsizei stride,
    112                                size_t offsetInBytes,
    113                                int divisor) {
    114     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
    115     SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
    116     AttribArrayState* array = &fAttribArrayStates[index];
    117     if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
    118         array->fType != type ||
    119         array->fStride != stride ||
    120         array->fOffset != offsetInBytes) {
    121         gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
    122         const AttribLayout& layout = attrib_layout(type);
    123         const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes);
    124         if (!GrVertexAttribTypeIsIntType(gpu->caps()->shaderCaps(), type)) {
    125             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
    126                                                                layout.fCount,
    127                                                                layout.fType,
    128                                                                layout.fNormalized,
    129                                                                stride,
    130                                                                offsetAsPtr));
    131         } else {
    132             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
    133             SkASSERT(!layout.fNormalized);
    134             GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
    135                                                                 layout.fCount,
    136                                                                 layout.fType,
    137                                                                 stride,
    138                                                                 offsetAsPtr));
    139         }
    140         array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
    141         array->fType = type;
    142         array->fStride = stride;
    143         array->fOffset = offsetInBytes;
    144     }
    145     if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
    146         SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
    147         GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
    148         array->fDivisor = divisor;
    149     }
    150 }
    151 
    152 void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount,
    153                                               EnablePrimitiveRestart enablePrimitiveRestart) {
    154     SkASSERT(enabledCount <= fAttribArrayStates.count());
    155 
    156     if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) {
    157         int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0;
    158         for (int i = firstIdxToEnable; i < enabledCount; ++i) {
    159             GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
    160         }
    161 
    162         int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
    163         for (int i = enabledCount; i < endIdxToDisable; ++i) {
    164             GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
    165         }
    166 
    167         fNumEnabledArrays = enabledCount;
    168     }
    169 
    170     SkASSERT(EnablePrimitiveRestart::kNo == enablePrimitiveRestart ||
    171              gpu->caps()->usePrimitiveRestart());
    172 
    173     if (gpu->caps()->usePrimitiveRestart() &&
    174         (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) {
    175         if (EnablePrimitiveRestart::kYes == enablePrimitiveRestart) {
    176             GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
    177         } else {
    178             GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
    179         }
    180 
    181         fPrimitiveRestartEnabled = enablePrimitiveRestart;
    182     }
    183 
    184     fEnableStateIsValid = true;
    185 }
    186 
    187 ///////////////////////////////////////////////////////////////////////////////////////////////////
    188 
    189 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
    190     : fID(id)
    191     , fAttribArrays(attribCount)
    192     , fIndexBufferUniqueID(SK_InvalidUniqueID) {
    193 }
    194 
    195 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
    196     if (0 == fID) {
    197         return nullptr;
    198     }
    199     gpu->bindVertexArray(fID);
    200     return &fAttribArrays;
    201 }
    202 
    203 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
    204     GrGLAttribArrayState* state = this->bind(gpu);
    205     if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
    206         if (ibuff->isCPUBacked()) {
    207             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
    208         } else {
    209             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
    210             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
    211                                                       glBuffer->bufferID()));
    212         }
    213         fIndexBufferUniqueID = ibuff->uniqueID();
    214     }
    215     return state;
    216 }
    217 
    218 void GrGLVertexArray::invalidateCachedState() {
    219     fAttribArrays.invalidate();
    220     fIndexBufferUniqueID.makeInvalid();
    221 }
    222