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