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