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