• 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 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 
set(GrGLGpu * gpu,int index,const GrBuffer * vertexBuffer,GrVertexAttribType cpuType,GrSLType gpuType,GrGLsizei stride,size_t offsetInBytes,int divisor)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 
enableVertexArrays(const GrGLGpu * gpu,int enabledCount,GrPrimitiveRestart enablePrimitiveRestart)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 
GrGLVertexArray(GrGLint id,int attribCount)166 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
167     : fID(id)
168     , fAttribArrays(attribCount)
169     , fIndexBufferUniqueID(SK_InvalidUniqueID) {
170 }
171 
bind(GrGLGpu * gpu)172 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
173     if (0 == fID) {
174         return nullptr;
175     }
176     gpu->bindVertexArray(fID);
177     return &fAttribArrays;
178 }
179 
bindWithIndexBuffer(GrGLGpu * gpu,const GrBuffer * ibuff)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 
invalidateCachedState()195 void GrGLVertexArray::invalidateCachedState() {
196     fAttribArrays.invalidate();
197     fIndexBufferUniqueID.makeInvalid();
198 }
199