• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
attrib_layout(GrVertexAttribType type)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 
set(GrGLGpu * gpu,int index,const GrBuffer * vertexBuffer,GrVertexAttribType type,GrGLsizei stride,size_t offsetInBytes,int divisor)51 void GrGLAttribArrayState::set(GrGLGpu* gpu,
52                                int index,
53                                const GrBuffer* vertexBuffer,
54                                GrVertexAttribType type,
55                                GrGLsizei stride,
56                                size_t offsetInBytes,
57                                int divisor) {
58     SkASSERT(index >= 0 && index < fAttribArrayStates.count());
59     SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
60     AttribArrayState* array = &fAttribArrayStates[index];
61     if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
62         array->fType != type ||
63         array->fStride != stride ||
64         array->fOffset != offsetInBytes) {
65         gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
66         const AttribLayout& layout = attrib_layout(type);
67         const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes);
68         if (!GrVertexAttribTypeIsIntType(type)) {
69             GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
70                                                                layout.fCount,
71                                                                layout.fType,
72                                                                layout.fNormalized,
73                                                                stride,
74                                                                offsetAsPtr));
75         } else {
76             SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
77             SkASSERT(!layout.fNormalized);
78             GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
79                                                                 layout.fCount,
80                                                                 layout.fType,
81                                                                 stride,
82                                                                 offsetAsPtr));
83         }
84         array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
85         array->fType = type;
86         array->fStride = stride;
87         array->fOffset = offsetInBytes;
88     }
89     if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
90         SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
91         GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
92         array->fDivisor = divisor;
93     }
94 }
95 
enableVertexArrays(const GrGLGpu * gpu,int enabledCount)96 void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount) {
97     SkASSERT(enabledCount <= fAttribArrayStates.count());
98     if (fEnabledCountIsValid && enabledCount == fNumEnabledArrays) {
99         return;
100     }
101 
102     int firstIdxToEnable = fEnabledCountIsValid ? fNumEnabledArrays : 0;
103     for (int i = firstIdxToEnable; i < enabledCount; ++i) {
104         GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
105     }
106 
107     int endIdxToDisable = fEnabledCountIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
108     for (int i = enabledCount; i < endIdxToDisable; ++i) {
109         GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
110     }
111 
112     fNumEnabledArrays = enabledCount;
113     fEnabledCountIsValid = true;
114 }
115 
116 ///////////////////////////////////////////////////////////////////////////////////////////////////
117 
GrGLVertexArray(GrGLint id,int attribCount)118 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
119     : fID(id)
120     , fAttribArrays(attribCount)
121     , fIndexBufferUniqueID(SK_InvalidUniqueID) {
122 }
123 
bind(GrGLGpu * gpu)124 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
125     if (0 == fID) {
126         return nullptr;
127     }
128     gpu->bindVertexArray(fID);
129     return &fAttribArrays;
130 }
131 
bindWithIndexBuffer(GrGLGpu * gpu,const GrBuffer * ibuff)132 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
133     GrGLAttribArrayState* state = this->bind(gpu);
134     if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
135         if (ibuff->isCPUBacked()) {
136             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
137         } else {
138             const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
139             GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
140                                                       glBuffer->bufferID()));
141         }
142         fIndexBufferUniqueID = ibuff->uniqueID();
143     }
144     return state;
145 }
146 
invalidateCachedState()147 void GrGLVertexArray::invalidateCachedState() {
148     fAttribArrays.invalidate();
149     fIndexBufferUniqueID.makeInvalid();
150 }
151