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 #include "src/gpu/ganesh/gl/GrGLVertexArray.h"
8
9 #include "include/core/SkTypes.h"
10 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
11 #include "include/gpu/ganesh/gl/GrGLInterface.h"
12 #include "src/core/SkSLTypeShared.h"
13 #include "src/gpu/ganesh/GrBuffer.h"
14 #include "src/gpu/ganesh/GrCaps.h"
15 #include "src/gpu/ganesh/GrCpuBuffer.h"
16 #include "src/gpu/ganesh/GrGpuBuffer.h"
17 #include "src/gpu/ganesh/GrShaderCaps.h"
18 #include "src/gpu/ganesh/gl/GrGLBuffer.h"
19 #include "src/gpu/ganesh/gl/GrGLDefines.h"
20 #include "src/gpu/ganesh/gl/GrGLGpu.h"
21 #include "src/gpu/ganesh/gl/GrGLUtil.h"
22
23 #include <cstdint>
24
25 struct AttribLayout {
26 bool fNormalized; // Only used by floating point types.
27 uint8_t fCount;
28 uint16_t fType;
29 };
30
31 static_assert(4 == sizeof(AttribLayout));
32
attrib_layout(GrVertexAttribType type)33 static AttribLayout attrib_layout(GrVertexAttribType type) {
34 switch (type) {
35 case kFloat_GrVertexAttribType:
36 return {false, 1, GR_GL_FLOAT};
37 case kFloat2_GrVertexAttribType:
38 return {false, 2, GR_GL_FLOAT};
39 case kFloat3_GrVertexAttribType:
40 return {false, 3, GR_GL_FLOAT};
41 case kFloat4_GrVertexAttribType:
42 return {false, 4, GR_GL_FLOAT};
43 case kHalf_GrVertexAttribType:
44 return {false, 1, GR_GL_HALF_FLOAT};
45 case kHalf2_GrVertexAttribType:
46 return {false, 2, GR_GL_HALF_FLOAT};
47 case kHalf4_GrVertexAttribType:
48 return {false, 4, GR_GL_HALF_FLOAT};
49 case kInt2_GrVertexAttribType:
50 return {false, 2, GR_GL_INT};
51 case kInt3_GrVertexAttribType:
52 return {false, 3, GR_GL_INT};
53 case kInt4_GrVertexAttribType:
54 return {false, 4, GR_GL_INT};
55 case kByte_GrVertexAttribType:
56 return {false, 1, GR_GL_BYTE};
57 case kByte2_GrVertexAttribType:
58 return {false, 2, GR_GL_BYTE};
59 case kByte4_GrVertexAttribType:
60 return {false, 4, GR_GL_BYTE};
61 case kUByte_GrVertexAttribType:
62 return {false, 1, GR_GL_UNSIGNED_BYTE};
63 case kUByte2_GrVertexAttribType:
64 return {false, 2, GR_GL_UNSIGNED_BYTE};
65 case kUByte4_GrVertexAttribType:
66 return {false, 4, GR_GL_UNSIGNED_BYTE};
67 case kUByte_norm_GrVertexAttribType:
68 return {true, 1, GR_GL_UNSIGNED_BYTE};
69 case kUByte4_norm_GrVertexAttribType:
70 return {true, 4, GR_GL_UNSIGNED_BYTE};
71 case kShort2_GrVertexAttribType:
72 return {false, 2, GR_GL_SHORT};
73 case kShort4_GrVertexAttribType:
74 return {false, 4, GR_GL_SHORT};
75 case kUShort2_GrVertexAttribType:
76 return {false, 2, GR_GL_UNSIGNED_SHORT};
77 case kUShort2_norm_GrVertexAttribType:
78 return {true, 2, GR_GL_UNSIGNED_SHORT};
79 case kInt_GrVertexAttribType:
80 return {false, 1, GR_GL_INT};
81 case kUInt_GrVertexAttribType:
82 return {false, 1, GR_GL_UNSIGNED_INT};
83 case kUShort_norm_GrVertexAttribType:
84 return {true, 1, GR_GL_UNSIGNED_SHORT};
85 case kUShort4_norm_GrVertexAttribType:
86 return {true, 4, GR_GL_UNSIGNED_SHORT};
87 }
88 SK_ABORT("Unknown vertex attrib type");
89 }
90
set(GrGLGpu * gpu,int index,const GrBuffer * vertexBuffer,GrVertexAttribType cpuType,SkSLType gpuType,GrGLsizei stride,size_t offsetInBytes,int divisor)91 void GrGLAttribArrayState::set(GrGLGpu* gpu,
92 int index,
93 const GrBuffer* vertexBuffer,
94 GrVertexAttribType cpuType,
95 SkSLType gpuType,
96 GrGLsizei stride,
97 size_t offsetInBytes,
98 int divisor) {
99 SkASSERT(index >= 0 && index < fAttribArrayStates.size());
100 SkASSERT(0 == divisor || gpu->caps()->drawInstancedSupport());
101 AttribArrayState* array = &fAttribArrayStates[index];
102 const char* offsetAsPtr;
103 bool bufferChanged = false;
104 if (vertexBuffer->isCpuBuffer()) {
105 if (!array->fUsingCpuBuffer) {
106 bufferChanged = true;
107 array->fUsingCpuBuffer = true;
108 }
109 offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes;
110 } else {
111 auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
112 if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) {
113 bufferChanged = true;
114 array->fVertexBufferUniqueID = gpuBuffer->uniqueID();
115 }
116 offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes);
117 }
118 if (bufferChanged ||
119 array->fCPUType != cpuType ||
120 array->fGPUType != gpuType ||
121 array->fStride != stride ||
122 array->fOffset != offsetAsPtr) {
123 // We always have to call this if we're going to change the array pointer. 'array' is
124 // tracking the last buffer used to setup attrib pointers, not the last buffer bound.
125 // GrGLGpu will avoid redundant binds.
126 gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer);
127 const AttribLayout& layout = attrib_layout(cpuType);
128 if (SkSLTypeIsFloatType(gpuType)) {
129 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
130 layout.fCount,
131 layout.fType,
132 layout.fNormalized,
133 stride,
134 offsetAsPtr));
135 } else {
136 SkASSERT(gpu->caps()->shaderCaps()->fIntegerSupport);
137 SkASSERT(!layout.fNormalized);
138 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
139 layout.fCount,
140 layout.fType,
141 stride,
142 offsetAsPtr));
143 }
144 array->fCPUType = cpuType;
145 array->fGPUType = gpuType;
146 array->fStride = stride;
147 array->fOffset = offsetAsPtr;
148 }
149 if (gpu->caps()->drawInstancedSupport() && array->fDivisor != divisor) {
150 SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
151 GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
152 array->fDivisor = divisor;
153 }
154 }
155
enableVertexArrays(const GrGLGpu * gpu,int enabledCount,GrPrimitiveRestart enablePrimitiveRestart)156 void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount,
157 GrPrimitiveRestart enablePrimitiveRestart) {
158 SkASSERT(enabledCount <= fAttribArrayStates.size());
159
160 if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) {
161 int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0;
162 for (int i = firstIdxToEnable; i < enabledCount; ++i) {
163 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
164 }
165
166 int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.size();
167 for (int i = enabledCount; i < endIdxToDisable; ++i) {
168 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
169 }
170
171 fNumEnabledArrays = enabledCount;
172 }
173
174 SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart ||
175 gpu->caps()->usePrimitiveRestart());
176
177 if (gpu->caps()->usePrimitiveRestart() &&
178 (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) {
179 if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) {
180 GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
181 } else {
182 GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
183 }
184
185 fPrimitiveRestartEnabled = enablePrimitiveRestart;
186 }
187
188 fEnableStateIsValid = true;
189 }
190
191 ///////////////////////////////////////////////////////////////////////////////////////////////////
192
GrGLVertexArray(GrGLint id,int attribCount)193 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
194 : fID(id)
195 , fAttribArrays(attribCount)
196 , fIndexBufferUniqueID(SK_InvalidUniqueID) {
197 }
198
bind(GrGLGpu * gpu)199 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
200 if (0 == fID) {
201 return nullptr;
202 }
203 gpu->bindVertexArray(fID);
204 return &fAttribArrays;
205 }
206
bindWithIndexBuffer(GrGLGpu * gpu,const GrBuffer * ibuff)207 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
208 GrGLAttribArrayState* state = this->bind(gpu);
209 if (!state) {
210 return nullptr;
211 }
212 if (ibuff->isCpuBuffer()) {
213 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
214 } else {
215 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
216 if (fIndexBufferUniqueID != glBuffer->uniqueID()) {
217 GR_GL_CALL(gpu->glInterface(),
218 BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID()));
219 fIndexBufferUniqueID = glBuffer->uniqueID();
220 }
221 }
222 return state;
223 }
224
invalidateCachedState()225 void GrGLVertexArray::invalidateCachedState() {
226 fAttribArrays.invalidate();
227 fIndexBufferUniqueID.makeInvalid();
228 }
229