bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 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 | |
Mike Klein | c0bd9f9 | 2019-04-23 12:05:21 -0500 | [diff] [blame] | 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" |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 12 | |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 13 | struct AttribLayout { |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 14 | bool fNormalized; // Only used by floating point types. |
| 15 | uint8_t fCount; |
| 16 | uint16_t fType; |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 17 | }; |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 18 | |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 19 | GR_STATIC_ASSERT(4 == sizeof(AttribLayout)); |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 20 | |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 21 | static AttribLayout attrib_layout(GrVertexAttribType type) { |
| 22 | switch (type) { |
| 23 | case kFloat_GrVertexAttribType: |
| 24 | return {false, 1, GR_GL_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 25 | case kFloat2_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 26 | return {false, 2, GR_GL_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 27 | case kFloat3_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 28 | return {false, 3, GR_GL_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 29 | case kFloat4_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 30 | return {false, 4, GR_GL_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 31 | case kHalf_GrVertexAttribType: |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 32 | return {false, 1, GR_GL_HALF_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 33 | case kHalf2_GrVertexAttribType: |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 34 | return {false, 2, GR_GL_HALF_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 35 | case kHalf3_GrVertexAttribType: |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 36 | return {false, 3, GR_GL_HALF_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 37 | case kHalf4_GrVertexAttribType: |
Brian Osman | d4c2970 | 2018-09-14 16:16:55 -0400 | [diff] [blame] | 38 | return {false, 4, GR_GL_HALF_FLOAT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 39 | case kInt2_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 40 | return {false, 2, GR_GL_INT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 41 | case kInt3_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 42 | return {false, 3, GR_GL_INT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 43 | case kInt4_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 44 | return {false, 4, GR_GL_INT}; |
Ruiqi Mao | b609e6d | 2018-07-17 10:19:38 -0400 | [diff] [blame] | 45 | 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 Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 61 | case kUByte_norm_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 62 | return {true, 1, GR_GL_UNSIGNED_BYTE}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 63 | case kUByte4_norm_GrVertexAttribType: |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 64 | return {true, 4, GR_GL_UNSIGNED_BYTE}; |
Chris Dalton | a045eea | 2017-10-24 13:22:10 -0600 | [diff] [blame] | 65 | case kShort2_GrVertexAttribType: |
| 66 | return {false, 2, GR_GL_SHORT}; |
Brian Osman | a5c578f | 2018-09-19 14:19:02 -0400 | [diff] [blame] | 67 | case kShort4_GrVertexAttribType: |
| 68 | return {false, 4, GR_GL_SHORT}; |
Ethan Nicholas | fa7ee24 | 2017-09-25 09:52:04 -0400 | [diff] [blame] | 69 | case kUShort2_GrVertexAttribType: |
Robert Phillips | 8296e75 | 2017-08-25 08:45:21 -0400 | [diff] [blame] | 70 | return {false, 2, GR_GL_UNSIGNED_SHORT}; |
Chris Dalton | a045eea | 2017-10-24 13:22:10 -0600 | [diff] [blame] | 71 | case kUShort2_norm_GrVertexAttribType: |
| 72 | return {true, 2, GR_GL_UNSIGNED_SHORT}; |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 73 | case kInt_GrVertexAttribType: |
| 74 | return {false, 1, GR_GL_INT}; |
| 75 | case kUint_GrVertexAttribType: |
| 76 | return {false, 1, GR_GL_UNSIGNED_INT}; |
Robert Phillips | fe18de5 | 2019-06-06 17:21:50 -0400 | [diff] [blame] | 77 | case kUShort_norm_GrVertexAttribType: |
| 78 | return {true, 1, GR_GL_UNSIGNED_SHORT}; |
Robert Phillips | 66a4603 | 2019-06-18 08:00:42 -0400 | [diff] [blame] | 79 | case kUShort4_norm_GrVertexAttribType: |
| 80 | return {true, 4, GR_GL_UNSIGNED_SHORT}; |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 81 | } |
Ben Wagner | b4aab9a | 2017-08-16 10:53:04 -0400 | [diff] [blame] | 82 | SK_ABORT("Unknown vertex attrib type"); |
csmartdalton | b37cb23 | 2017-02-08 14:56:27 -0500 | [diff] [blame] | 83 | }; |
bsalomon | 6df8640 | 2015-06-01 10:41:49 -0700 | [diff] [blame] | 84 | |
| 85 | void GrGLAttribArrayState::set(GrGLGpu* gpu, |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 86 | int index, |
csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 87 | const GrBuffer* vertexBuffer, |
Brian Osman | 4a3f5c8 | 2018-09-18 16:16:38 -0400 | [diff] [blame] | 88 | GrVertexAttribType cpuType, |
| 89 | GrSLType gpuType, |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 90 | GrGLsizei stride, |
Chris Dalton | 1d61635 | 2017-05-31 12:51:23 -0600 | [diff] [blame] | 91 | size_t offsetInBytes, |
| 92 | int divisor) { |
tfarina@chromium.org | f6de475 | 2013-08-17 00:02:59 +0000 | [diff] [blame] | 93 | SkASSERT(index >= 0 && index < fAttribArrayStates.count()); |
Chris Dalton | 1d61635 | 2017-05-31 12:51:23 -0600 | [diff] [blame] | 94 | SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport()); |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 95 | AttribArrayState* array = &fAttribArrayStates[index]; |
Brian Salomon | dbf7072 | 2019-02-07 11:31:24 -0500 | [diff] [blame] | 96 | const char* offsetAsPtr; |
| 97 | bool bufferChanged = false; |
| 98 | if (vertexBuffer->isCpuBuffer()) { |
| 99 | if (!array->fUsingCpuBuffer) { |
| 100 | bufferChanged = true; |
| 101 | array->fUsingCpuBuffer = true; |
| 102 | } |
| 103 | offsetAsPtr = static_cast<const GrCpuBuffer*>(vertexBuffer)->data() + offsetInBytes; |
| 104 | } else { |
| 105 | auto gpuBuffer = static_cast<const GrGpuBuffer*>(vertexBuffer); |
| 106 | if (array->fUsingCpuBuffer || array->fVertexBufferUniqueID != gpuBuffer->uniqueID()) { |
| 107 | bufferChanged = true; |
| 108 | array->fVertexBufferUniqueID = gpuBuffer->uniqueID(); |
| 109 | } |
| 110 | offsetAsPtr = reinterpret_cast<const char*>(offsetInBytes); |
| 111 | } |
| 112 | if (bufferChanged || |
Brian Osman | 4a3f5c8 | 2018-09-18 16:16:38 -0400 | [diff] [blame] | 113 | array->fCPUType != cpuType || |
| 114 | array->fGPUType != gpuType || |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 115 | array->fStride != stride || |
Brian Salomon | dbf7072 | 2019-02-07 11:31:24 -0500 | [diff] [blame] | 116 | array->fOffset != offsetAsPtr) { |
| 117 | // We always have to call this if we're going to change the array pointer. 'array' is |
| 118 | // tracking the last buffer used to setup attrib pointers, not the last buffer bound. |
| 119 | // GrGLGpu will avoid redundant binds. |
Brian Salomon | ae64c19 | 2019-02-05 09:41:37 -0500 | [diff] [blame] | 120 | gpu->bindBuffer(GrGpuBufferType::kVertex, vertexBuffer); |
Brian Osman | 4a3f5c8 | 2018-09-18 16:16:38 -0400 | [diff] [blame] | 121 | const AttribLayout& layout = attrib_layout(cpuType); |
Brian Osman | 4a3f5c8 | 2018-09-18 16:16:38 -0400 | [diff] [blame] | 122 | if (GrSLTypeIsFloatType(gpuType)) { |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 123 | GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, |
| 124 | layout.fCount, |
| 125 | layout.fType, |
| 126 | layout.fNormalized, |
| 127 | stride, |
Chris Dalton | 8e45b4f | 2017-05-05 14:00:56 -0400 | [diff] [blame] | 128 | offsetAsPtr)); |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 129 | } else { |
| 130 | SkASSERT(gpu->caps()->shaderCaps()->integerSupport()); |
| 131 | SkASSERT(!layout.fNormalized); |
| 132 | GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index, |
| 133 | layout.fCount, |
| 134 | layout.fType, |
| 135 | stride, |
Chris Dalton | 8e45b4f | 2017-05-05 14:00:56 -0400 | [diff] [blame] | 136 | offsetAsPtr)); |
cdalton | 793dc26 | 2016-02-08 10:11:47 -0800 | [diff] [blame] | 137 | } |
Brian Osman | 4a3f5c8 | 2018-09-18 16:16:38 -0400 | [diff] [blame] | 138 | array->fCPUType = cpuType; |
| 139 | array->fGPUType = gpuType; |
dcheng | c4d196c | 2016-02-06 15:08:54 -0800 | [diff] [blame] | 140 | array->fStride = stride; |
Brian Salomon | dbf7072 | 2019-02-07 11:31:24 -0500 | [diff] [blame] | 141 | array->fOffset = offsetAsPtr; |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 142 | } |
Chris Dalton | 1d61635 | 2017-05-31 12:51:23 -0600 | [diff] [blame] | 143 | if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) { |
| 144 | SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect. |
| 145 | GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor)); |
| 146 | array->fDivisor = divisor; |
| 147 | } |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 148 | } |
| 149 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 150 | void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount, |
Brian Salomon | 802cb31 | 2018-06-08 18:05:20 -0400 | [diff] [blame] | 151 | GrPrimitiveRestart enablePrimitiveRestart) { |
Chris Dalton | 8e45b4f | 2017-05-05 14:00:56 -0400 | [diff] [blame] | 152 | SkASSERT(enabledCount <= fAttribArrayStates.count()); |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 153 | |
| 154 | if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) { |
| 155 | int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0; |
| 156 | for (int i = firstIdxToEnable; i < enabledCount; ++i) { |
| 157 | GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i)); |
| 158 | } |
| 159 | |
| 160 | int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count(); |
| 161 | for (int i = enabledCount; i < endIdxToDisable; ++i) { |
| 162 | GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); |
| 163 | } |
| 164 | |
| 165 | fNumEnabledArrays = enabledCount; |
Chris Dalton | 1d61635 | 2017-05-31 12:51:23 -0600 | [diff] [blame] | 166 | } |
Chris Dalton | 8e45b4f | 2017-05-05 14:00:56 -0400 | [diff] [blame] | 167 | |
Brian Salomon | 802cb31 | 2018-06-08 18:05:20 -0400 | [diff] [blame] | 168 | SkASSERT(GrPrimitiveRestart::kNo == enablePrimitiveRestart || |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 169 | gpu->caps()->usePrimitiveRestart()); |
| 170 | |
| 171 | if (gpu->caps()->usePrimitiveRestart() && |
| 172 | (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) { |
Brian Salomon | 802cb31 | 2018-06-08 18:05:20 -0400 | [diff] [blame] | 173 | if (GrPrimitiveRestart::kYes == enablePrimitiveRestart) { |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 174 | GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); |
| 175 | } else { |
| 176 | GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX)); |
| 177 | } |
| 178 | |
| 179 | fPrimitiveRestartEnabled = enablePrimitiveRestart; |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 180 | } |
Chris Dalton | 8e45b4f | 2017-05-05 14:00:56 -0400 | [diff] [blame] | 181 | |
Chris Dalton | 27059d3 | 2018-01-23 14:06:50 -0700 | [diff] [blame] | 182 | fEnableStateIsValid = true; |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 186 | |
bsalomon | 8780bc6 | 2015-05-13 09:56:37 -0700 | [diff] [blame] | 187 | GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount) |
| 188 | : fID(id) |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 189 | , fAttribArrays(attribCount) |
cdalton | e2e71c2 | 2016-04-07 18:13:29 -0700 | [diff] [blame] | 190 | , fIndexBufferUniqueID(SK_InvalidUniqueID) { |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 191 | } |
| 192 | |
bsalomon | 8780bc6 | 2015-05-13 09:56:37 -0700 | [diff] [blame] | 193 | GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) { |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 194 | if (0 == fID) { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 195 | return nullptr; |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 196 | } |
bsalomon | 8780bc6 | 2015-05-13 09:56:37 -0700 | [diff] [blame] | 197 | gpu->bindVertexArray(fID); |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 198 | return &fAttribArrays; |
| 199 | } |
skia.committer@gmail.com | 754a3eb | 2013-03-08 07:01:25 +0000 | [diff] [blame] | 200 | |
csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 201 | GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) { |
bsalomon | 8780bc6 | 2015-05-13 09:56:37 -0700 | [diff] [blame] | 202 | GrGLAttribArrayState* state = this->bind(gpu); |
Brian Salomon | dbf7072 | 2019-02-07 11:31:24 -0500 | [diff] [blame] | 203 | if (!state) { |
| 204 | return nullptr; |
| 205 | } |
| 206 | if (ibuff->isCpuBuffer()) { |
| 207 | GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0)); |
| 208 | } else { |
| 209 | const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); |
| 210 | if (fIndexBufferUniqueID != glBuffer->uniqueID()) { |
csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 211 | const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff); |
Brian Salomon | dbf7072 | 2019-02-07 11:31:24 -0500 | [diff] [blame] | 212 | GR_GL_CALL(gpu->glInterface(), |
| 213 | BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, glBuffer->bufferID())); |
| 214 | fIndexBufferUniqueID = glBuffer->uniqueID(); |
csmartdalton | 485a120 | 2016-07-13 10:16:32 -0700 | [diff] [blame] | 215 | } |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 216 | } |
| 217 | return state; |
| 218 | } |
| 219 | |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 220 | void GrGLVertexArray::invalidateCachedState() { |
commit-bot@chromium.org | ce6da4d | 2013-09-09 14:55:37 +0000 | [diff] [blame] | 221 | fAttribArrays.invalidate(); |
Robert Phillips | 294870f | 2016-11-11 12:38:40 -0500 | [diff] [blame] | 222 | fIndexBufferUniqueID.makeInvalid(); |
bsalomon@google.com | 6918d48 | 2013-03-07 19:09:11 +0000 | [diff] [blame] | 223 | } |