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