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