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_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
GrVertexAttribTypeIsIntType(const GrShaderCaps * shaderCaps,GrVertexAttribType type)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
set(GrGLGpu * gpu,int index,const GrBuffer * vertexBuffer,GrVertexAttribType type,GrGLsizei stride,size_t offsetInBytes,int divisor)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
enableVertexArrays(const GrGLGpu * gpu,int enabledCount,EnablePrimitiveRestart enablePrimitiveRestart)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
GrGLVertexArray(GrGLint id,int attribCount)189 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
190 : fID(id)
191 , fAttribArrays(attribCount)
192 , fIndexBufferUniqueID(SK_InvalidUniqueID) {
193 }
194
bind(GrGLGpu * gpu)195 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
196 if (0 == fID) {
197 return nullptr;
198 }
199 gpu->bindVertexArray(fID);
200 return &fAttribArrays;
201 }
202
bindWithIndexBuffer(GrGLGpu * gpu,const GrBuffer * ibuff)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
invalidateCachedState()218 void GrGLVertexArray::invalidateCachedState() {
219 fAttribArrays.invalidate();
220 fIndexBufferUniqueID.makeInvalid();
221 }
222