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 "GrCpuBuffer.h"
     10 #include "GrGLBuffer.h"
     11 #include "GrGLGpu.h"
     12 
     13 struct AttribLayout {
     14     bool        fNormalized;  // Only used by floating point types.
     15     uint8_t     fCount;
     16     uint16_t    fType;
     17 };
     18 
     19 GR_STATIC_ASSERT(4 == sizeof(AttribLayout));
     20 
     21 static AttribLayout attrib_layout(GrVertexAttribType type) {
     22     switch (type) {
     23         case kFloat_GrVertexAttribType:
     24             return {false, 1, GR_GL_FLOAT};
     25         case kFloat2_GrVertexAttribType:
     26             return {false, 2, GR_GL_FLOAT};
     27         case kFloat3_GrVertexAttribType:
     28             return {false, 3, GR_GL_FLOAT};
     29         case kFloat4_GrVertexAttribType:
     30             return {false, 4, GR_GL_FLOAT};
     31         case kHalf_GrVertexAttribType:
     32             return {false, 1, GR_GL_HALF_FLOAT};
     33         case kHalf2_GrVertexAttribType:
     34             return {false, 2, GR_GL_HALF_FLOAT};
     35         case kHalf3_GrVertexAttribType:
     36             return {false, 3, GR_GL_HALF_FLOAT};
     37         case kHalf4_GrVertexAttribType:
     38             return {false, 4, GR_GL_HALF_FLOAT};
     39         case kInt2_GrVertexAttribType:
     40             return {false, 2, GR_GL_INT};
     41         case kInt3_GrVertexAttribType:
     42             return {false, 3, GR_GL_INT};
     43         case kInt4_GrVertexAttribType:
     44             return {false, 4, GR_GL_INT};
     45         case kByte_GrVertexAttribType:
     46             return {false, 1, GR_GL_BYTE};
     47         case kByte2_GrVertexAttribType:
     48             return {false, 2, GR_GL_BYTE};
     49         case kByte3_GrVertexAttribType:
     50             return {false, 3, GR_GL_BYTE};
     51         case kByte4_GrVertexAttribType:
     52             return {false, 4, GR_GL_BYTE};
     53         case kUByte_GrVertexAttribType:
     54             return {false, 1, GR_GL_UNSIGNED_BYTE};
     55         case kUByte2_GrVertexAttribType:
     56             return {false, 2, GR_GL_UNSIGNED_BYTE};
     57         case kUByte3_GrVertexAttribType:
     58             return {false, 3, GR_GL_UNSIGNED_BYTE};
     59         case kUByte4_GrVertexAttribType:
     60             return {false, 4, GR_GL_UNSIGNED_BYTE};
     61         case kUByte_norm_GrVertexAttribType:
     62             return {true, 1, GR_GL_UNSIGNED_BYTE};
     63         case kUByte4_norm_GrVertexAttribType:
     64             return {true, 4, GR_GL_UNSIGNED_BYTE};
     65         case kShort2_GrVertexAttribType:
     66             return {false, 2, GR_GL_SHORT};
     67         case kShort4_GrVertexAttribType:
     68             return {false, 4, GR_GL_SHORT};
     69         case kUShort2_GrVertexAttribType:
     70             return {false, 2, GR_GL_UNSIGNED_SHORT};
     71         case kUShort2_norm_GrVertexAttribType:
     72             return {true, 2, GR_GL_UNSIGNED_SHORT};
     73         case kInt_GrVertexAttribType:
     74             return {false, 1, GR_GL_INT};
     75         case kUint_GrVertexAttribType:
     76             return {false, 1, GR_GL_UNSIGNED_INT};
     77     }
     78     SK_ABORT("Unknown vertex attrib type");
     79     return {false, 0, 0};
     80 };
     81 
     82 void GrGLAttribArrayState::set(GrGLGpu* gpu,
     83                                int index,
     84                                const GrBuffer* vertexBuffer,
     85                                GrVertexAttribType cpuType,
     86                                GrSLType gpuType,
     87                                GrGLsizei stride,
     88                                size_t offsetInBytes,
     89                                int divisor) {
     90     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
     91     SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
     92     AttribArrayState* array = &fAttribArrayStates[index];
     93     const char* offsetAsPtr;
     94     bool bufferChanged = false;
     95     if (vertexBuffer->isCpuBuffer()) {
     96         if (!array->fUsingCpuBuffer) {
     97             bufferChanged = true;
     98             array->fUsingCpuBuffer = true;
     99         }
    100         offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes;
    101     } else {
    102         auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
    103         if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) {
    104             bufferChanged = true;
    105             array->fVertexBufferUniqueID = gpuBuffer->uniqueID();
    106         }
    107         offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes);
    108     }
    109     if (bufferChanged ||
    110         array->fCPUType != cpuType ||
    111         array->fGPUType != gpuType ||
    112         array->fStride != stride ||
    113         array->fOffset != offsetAsPtr) {
    114         // We always have to call this if we're going to change the array pointer. 'array' is
    115         // tracking the last buffer used to setup attrib pointers, not the last buffer bound.
    116         // GrGLGpu will avoid redundant binds.
    117         gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer);
    118         const AttribLayout& layout = attrib_layout(cpuType);
    119         if (GrSLTypeIsFloatType(gpuType)) {
    120             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
    121                                                                layout.fCount,
    122                                                                layout.fType,
    123                                                                layout.fNormalized,
    124                                                                stride,
    125                                                                offsetAsPtr));
    126         } else {
    127             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
    128             SkASSERT(!layout.fNormalized);
    129             GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
    130                                                                 layout.fCount,
    131                                                                 layout.fType,
    132                                                                 stride,
    133                                                                 offsetAsPtr));
    134         }
    135         array->fCPUType = cpuType;
    136         array->fGPUType = gpuType;
    137         array->fStride = stride;
    138         array->fOffset = offsetAsPtr;
    139     }
    140     if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
    141         SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
    142         GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
    143         array->fDivisor = divisor;
    144     }
    145 }
    146 
    147 void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount,
    148                                               GrPrimitiveRestart enablePrimitiveRestart) {
    149     SkASSERT(enabledCount <= fAttribArrayStates.count());
    150 
    151     if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) {
    152         int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0;
    153         for (int i = firstIdxToEnable; i < enabledCount; ++i) {
    154             GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
    155         }
    156 
    157         int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
    158         for (int i = enabledCount; i < endIdxToDisable; ++i) {
    159             GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
    160         }
    161 
    162         fNumEnabledArrays = enabledCount;
    163     }
    164 
    165     SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart ||
    166              gpu->caps()->usePrimitiveRestart());
    167 
    168     if (gpu->caps()->usePrimitiveRestart() &&
    169         (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) {
    170         if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) {
    171             GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
    172         } else {
    173             GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
    174         }
    175 
    176         fPrimitiveRestartEnabled = enablePrimitiveRestart;
    177     }
    178 
    179     fEnableStateIsValid = true;
    180 }
    181 
    182 ///////////////////////////////////////////////////////////////////////////////////////////////////
    183 
    184 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
    185     : fID(id)
    186     , fAttribArrays(attribCount)
    187     , fIndexBufferUniqueID(SK_InvalidUniqueID) {
    188 }
    189 
    190 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
    191     if (0 == fID) {
    192         return nullptr;
    193     }
    194     gpu->bindVertexArray(fID);
    195     return &fAttribArrays;
    196 }
    197 
    198 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
    199     GrGLAttribArrayState* state = this->bind(gpu);
    200     if (!state) {
    201         return nullptr;
    202     }
    203     if (ibuff->isCpuBuffer()) {
    204         GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
    205     } else {
    206         const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
    207         if (fIndexBufferUniqueID != glBuffer->uniqueID()) {
    208             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
    209             GR_GL_CALL(gpu->glInterface(),
    210                        BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID()));
    211             fIndexBufferUniqueID = glBuffer->uniqueID();
    212         }
    213     }
    214     return state;
    215 }
    216 
    217 void GrGLVertexArray::invalidateCachedState() {
    218     fAttribArrays.invalidate();
    219     fIndexBufferUniqueID.makeInvalid();
    220 }
    221