blob: 38c02545bc59a08cf54994d836215c802b51b113 [file] [log] [blame]
bsalomon@google.com6918d482013-03-07 19:09:11 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#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"
bsalomon@google.com6918d482013-03-07 19:09:11 +000012
cdalton793dc262016-02-08 10:11:47 -080013struct AttribLayout {
csmartdaltonb37cb232017-02-08 14:56:27 -050014 bool fNormalized; // Only used by floating point types.
15 uint8_t fCount;
16 uint16_t fType;
cdalton793dc262016-02-08 10:11:47 -080017};
bsalomon@google.com6918d482013-03-07 19:09:11 +000018
csmartdaltonb37cb232017-02-08 14:56:27 -050019GR_STATIC_ASSERT(4 == sizeof(AttribLayout));
cdalton793dc262016-02-08 10:11:47 -080020
csmartdaltonb37cb232017-02-08 14:56:27 -050021static AttribLayout attrib_layout(GrVertexAttribType type) {
22 switch (type) {
23 case kFloat_GrVertexAttribType:
24 return {false, 1, GR_GL_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040025 case kFloat2_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050026 return {false, 2, GR_GL_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040027 case kFloat3_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050028 return {false, 3, GR_GL_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040029 case kFloat4_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050030 return {false, 4, GR_GL_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040031 case kHalf_GrVertexAttribType:
Brian Osmand4c29702018-09-14 16:16:55 -040032 return {false, 1, GR_GL_HALF_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040033 case kHalf2_GrVertexAttribType:
Brian Osmand4c29702018-09-14 16:16:55 -040034 return {false, 2, GR_GL_HALF_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040035 case kHalf3_GrVertexAttribType:
Brian Osmand4c29702018-09-14 16:16:55 -040036 return {false, 3, GR_GL_HALF_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040037 case kHalf4_GrVertexAttribType:
Brian Osmand4c29702018-09-14 16:16:55 -040038 return {false, 4, GR_GL_HALF_FLOAT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040039 case kInt2_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050040 return {false, 2, GR_GL_INT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040041 case kInt3_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050042 return {false, 3, GR_GL_INT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040043 case kInt4_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050044 return {false, 4, GR_GL_INT};
Ruiqi Maob609e6d2018-07-17 10:19:38 -040045 case kByte_GrVertexAttribType:
46 return {false, 1, GR_GL_BYTE};
47 case kByte2_GrVertexAttribType:
48 return {false, 2, GR_GL_BYTE};
49 case kByte3_GrVertexAttribType:
50 return {false, 3, GR_GL_BYTE};
51 case kByte4_GrVertexAttribType:
52 return {false, 4, GR_GL_BYTE};
53 case kUByte_GrVertexAttribType:
54 return {false, 1, GR_GL_UNSIGNED_BYTE};
55 case kUByte2_GrVertexAttribType:
56 return {false, 2, GR_GL_UNSIGNED_BYTE};
57 case kUByte3_GrVertexAttribType:
58 return {false, 3, GR_GL_UNSIGNED_BYTE};
59 case kUByte4_GrVertexAttribType:
60 return {false, 4, GR_GL_UNSIGNED_BYTE};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040061 case kUByte_norm_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050062 return {true, 1, GR_GL_UNSIGNED_BYTE};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040063 case kUByte4_norm_GrVertexAttribType:
csmartdaltonb37cb232017-02-08 14:56:27 -050064 return {true, 4, GR_GL_UNSIGNED_BYTE};
Chris Daltona045eea2017-10-24 13:22:10 -060065 case kShort2_GrVertexAttribType:
66 return {false, 2, GR_GL_SHORT};
Brian Osmana5c578f2018-09-19 14:19:02 -040067 case kShort4_GrVertexAttribType:
68 return {false, 4, GR_GL_SHORT};
Ethan Nicholasfa7ee242017-09-25 09:52:04 -040069 case kUShort2_GrVertexAttribType:
Robert Phillips8296e752017-08-25 08:45:21 -040070 return {false, 2, GR_GL_UNSIGNED_SHORT};
Chris Daltona045eea2017-10-24 13:22:10 -060071 case kUShort2_norm_GrVertexAttribType:
72 return {true, 2, GR_GL_UNSIGNED_SHORT};
csmartdaltonb37cb232017-02-08 14:56:27 -050073 case kInt_GrVertexAttribType:
74 return {false, 1, GR_GL_INT};
75 case kUint_GrVertexAttribType:
76 return {false, 1, GR_GL_UNSIGNED_INT};
Robert Phillipsfe18de52019-06-06 17:21:50 -040077 case kUShort_norm_GrVertexAttribType:
78 return {true, 1, GR_GL_UNSIGNED_SHORT};
Robert Phillips66a46032019-06-18 08:00:42 -040079 case kUShort4_norm_GrVertexAttribType:
80 return {true, 4, GR_GL_UNSIGNED_SHORT};
csmartdaltonb37cb232017-02-08 14:56:27 -050081 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -040082 SK_ABORT("Unknown vertex attrib type");
csmartdaltonb37cb232017-02-08 14:56:27 -050083 return {false, 0, 0};
84};
bsalomon6df86402015-06-01 10:41:49 -070085
86void GrGLAttribArrayState::set(GrGLGpu* gpu,
bsalomon@google.com6918d482013-03-07 19:09:11 +000087 int index,
csmartdalton485a1202016-07-13 10:16:32 -070088 const GrBuffer* vertexBuffer,
Brian Osman4a3f5c82018-09-18 16:16:38 -040089 GrVertexAttribType cpuType,
90 GrSLType gpuType,
bsalomon@google.com6918d482013-03-07 19:09:11 +000091 GrGLsizei stride,
Chris Dalton1d616352017-05-31 12:51:23 -060092 size_t offsetInBytes,
93 int divisor) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000094 SkASSERT(index >= 0 && index < fAttribArrayStates.count());
Chris Dalton1d616352017-05-31 12:51:23 -060095 SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
bsalomon@google.com6918d482013-03-07 19:09:11 +000096 AttribArrayState* array = &fAttribArrayStates[index];
Brian Salomondbf70722019-02-07 11:31:24 -050097 const char* offsetAsPtr;
98 bool bufferChanged = false;
99 if (vertexBuffer->isCpuBuffer()) {
100 if (!array->fUsingCpuBuffer) {
101 bufferChanged = true;
102 array->fUsingCpuBuffer = true;
103 }
104 offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes;
105 } else {
106 auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer);
107 if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) {
108 bufferChanged = true;
109 array->fVertexBufferUniqueID = gpuBuffer->uniqueID();
110 }
111 offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes);
112 }
113 if (bufferChanged ||
Brian Osman4a3f5c82018-09-18 16:16:38 -0400114 array->fCPUType != cpuType ||
115 array->fGPUType != gpuType ||
bsalomon@google.com6918d482013-03-07 19:09:11 +0000116 array->fStride != stride ||
Brian Salomondbf70722019-02-07 11:31:24 -0500117 array->fOffset != offsetAsPtr) {
118 // We always have to call this if we're going to change the array pointer. 'array' is
119 // tracking the last buffer used to setup attrib pointers, not the last buffer bound.
120 // GrGLGpu will avoid redundant binds.
Brian Salomonae64c192019-02-05 09:41:37 -0500121 gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer);
Brian Osman4a3f5c82018-09-18 16:16:38 -0400122 const AttribLayout& layout = attrib_layout(cpuType);
Brian Osman4a3f5c82018-09-18 16:16:38 -0400123 if (GrSLTypeIsFloatType(gpuType)) {
cdalton793dc262016-02-08 10:11:47 -0800124 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
125 layout.fCount,
126 layout.fType,
127 layout.fNormalized,
128 stride,
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400129 offsetAsPtr));
cdalton793dc262016-02-08 10:11:47 -0800130 } else {
131 SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
132 SkASSERT(!layout.fNormalized);
133 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
134 layout.fCount,
135 layout.fType,
136 stride,
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400137 offsetAsPtr));
cdalton793dc262016-02-08 10:11:47 -0800138 }
Brian Osman4a3f5c82018-09-18 16:16:38 -0400139 array->fCPUType = cpuType;
140 array->fGPUType = gpuType;
dchengc4d196c2016-02-06 15:08:54 -0800141 array->fStride = stride;
Brian Salomondbf70722019-02-07 11:31:24 -0500142 array->fOffset = offsetAsPtr;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000143 }
Chris Dalton1d616352017-05-31 12:51:23 -0600144 if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
145 SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
146 GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
147 array->fDivisor = divisor;
148 }
bsalomon@google.com6918d482013-03-07 19:09:11 +0000149}
150
Chris Dalton27059d32018-01-23 14:06:50 -0700151void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount,
Brian Salomon802cb312018-06-08 18:05:20 -0400152 GrPrimitiveRestart enablePrimitiveRestart) {
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400153 SkASSERT(enabledCount <= fAttribArrayStates.count());
Chris Dalton27059d32018-01-23 14:06:50 -0700154
155 if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) {
156 int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0;
157 for (int i = firstIdxToEnable; i < enabledCount; ++i) {
158 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
159 }
160
161 int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
162 for (int i = enabledCount; i < endIdxToDisable; ++i) {
163 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
164 }
165
166 fNumEnabledArrays = enabledCount;
Chris Dalton1d616352017-05-31 12:51:23 -0600167 }
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400168
Brian Salomon802cb312018-06-08 18:05:20 -0400169 SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart ||
Chris Dalton27059d32018-01-23 14:06:50 -0700170 gpu->caps()->usePrimitiveRestart());
171
172 if (gpu->caps()->usePrimitiveRestart() &&
173 (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) {
Brian Salomon802cb312018-06-08 18:05:20 -0400174 if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) {
Chris Dalton27059d32018-01-23 14:06:50 -0700175 GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
176 } else {
177 GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
178 }
179
180 fPrimitiveRestartEnabled = enablePrimitiveRestart;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000181 }
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400182
Chris Dalton27059d32018-01-23 14:06:50 -0700183 fEnableStateIsValid = true;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000184}
185
186///////////////////////////////////////////////////////////////////////////////////////////////////
187
bsalomon8780bc62015-05-13 09:56:37 -0700188GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
189 : fID(id)
bsalomon@google.com6918d482013-03-07 19:09:11 +0000190 , fAttribArrays(attribCount)
cdaltone2e71c22016-04-07 18:13:29 -0700191 , fIndexBufferUniqueID(SK_InvalidUniqueID) {
bsalomon@google.com6918d482013-03-07 19:09:11 +0000192}
193
bsalomon8780bc62015-05-13 09:56:37 -0700194GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
bsalomon@google.com6918d482013-03-07 19:09:11 +0000195 if (0 == fID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700196 return nullptr;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000197 }
bsalomon8780bc62015-05-13 09:56:37 -0700198 gpu->bindVertexArray(fID);
bsalomon@google.com6918d482013-03-07 19:09:11 +0000199 return &fAttribArrays;
200}
skia.committer@gmail.com754a3eb2013-03-08 07:01:25 +0000201
csmartdalton485a1202016-07-13 10:16:32 -0700202GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
bsalomon8780bc62015-05-13 09:56:37 -0700203 GrGLAttribArrayState* state = this->bind(gpu);
Brian Salomondbf70722019-02-07 11:31:24 -0500204 if (!state) {
205 return nullptr;
206 }
207 if (ibuff->isCpuBuffer()) {
208 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
209 } else {
210 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
211 if (fIndexBufferUniqueID != glBuffer->uniqueID()) {
csmartdalton485a1202016-07-13 10:16:32 -0700212 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
Brian Salomondbf70722019-02-07 11:31:24 -0500213 GR_GL_CALL(gpu->glInterface(),
214 BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID()));
215 fIndexBufferUniqueID = glBuffer->uniqueID();
csmartdalton485a1202016-07-13 10:16:32 -0700216 }
bsalomon@google.com6918d482013-03-07 19:09:11 +0000217 }
218 return state;
219}
220
bsalomon@google.com6918d482013-03-07 19:09:11 +0000221void GrGLVertexArray::invalidateCachedState() {
commit-bot@chromium.orgce6da4d2013-09-09 14:55:37 +0000222 fAttribArrays.invalidate();
Robert Phillips294870f2016-11-11 12:38:40 -0500223 fIndexBufferUniqueID.makeInvalid();
bsalomon@google.com6918d482013-03-07 19:09:11 +0000224}