xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLVertexArray.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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