blob: 59f2be98317f30fa6fbba2f0d33a372c29697e48 [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
8#include "GrGLVertexArray.h"
cdaltone2e71c22016-04-07 18:13:29 -07009#include "GrGLBuffer.h"
jvanverth39edf762014-12-22 11:44:19 -080010#include "GrGLGpu.h"
bsalomon@google.com6918d482013-03-07 19:09:11 +000011
cdalton793dc262016-02-08 10:11:47 -080012struct AttribLayout {
csmartdaltonb37cb232017-02-08 14:56:27 -050013 bool fNormalized; // Only used by floating point types.
14 uint8_t fCount;
15 uint16_t fType;
cdalton793dc262016-02-08 10:11:47 -080016};
bsalomon@google.com6918d482013-03-07 19:09:11 +000017
csmartdaltonb37cb232017-02-08 14:56:27 -050018GR_STATIC_ASSERT(4 == sizeof(AttribLayout));
cdalton793dc262016-02-08 10:11:47 -080019
csmartdaltonb37cb232017-02-08 14:56:27 -050020static AttribLayout attrib_layout(GrVertexAttribType type) {
21 switch (type) {
22 case kFloat_GrVertexAttribType:
23 return {false, 1, GR_GL_FLOAT};
24 case kVec2f_GrVertexAttribType:
25 return {false, 2, GR_GL_FLOAT};
26 case kVec3f_GrVertexAttribType:
27 return {false, 3, GR_GL_FLOAT};
28 case kVec4f_GrVertexAttribType:
29 return {false, 4, GR_GL_FLOAT};
30 case kVec2i_GrVertexAttribType:
31 return {false, 2, GR_GL_INT};
32 case kVec3i_GrVertexAttribType:
33 return {false, 3, GR_GL_INT};
34 case kVec4i_GrVertexAttribType:
35 return {false, 4, GR_GL_INT};
36 case kUByte_GrVertexAttribType:
37 return {true, 1, GR_GL_UNSIGNED_BYTE};
38 case kVec4ub_GrVertexAttribType:
39 return {true, 4, GR_GL_UNSIGNED_BYTE};
40 case kVec2us_GrVertexAttribType:
41 return {true, 2, GR_GL_UNSIGNED_SHORT};
42 case kInt_GrVertexAttribType:
43 return {false, 1, GR_GL_INT};
44 case kUint_GrVertexAttribType:
45 return {false, 1, GR_GL_UNSIGNED_INT};
46 }
47 SkFAIL("Unknown vertex attrib type");
48 return {false, 0, 0};
49};
bsalomon6df86402015-06-01 10:41:49 -070050
51void GrGLAttribArrayState::set(GrGLGpu* gpu,
bsalomon@google.com6918d482013-03-07 19:09:11 +000052 int index,
csmartdalton485a1202016-07-13 10:16:32 -070053 const GrBuffer* vertexBuffer,
cdalton793dc262016-02-08 10:11:47 -080054 GrVertexAttribType type,
bsalomon@google.com6918d482013-03-07 19:09:11 +000055 GrGLsizei stride,
Chris Dalton1d616352017-05-31 12:51:23 -060056 size_t offsetInBytes,
57 int divisor) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000058 SkASSERT(index >= 0 && index < fAttribArrayStates.count());
Chris Dalton1d616352017-05-31 12:51:23 -060059 SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
bsalomon@google.com6918d482013-03-07 19:09:11 +000060 AttribArrayState* array = &fAttribArrayStates[index];
robertphillips8abb3702016-08-31 14:04:06 -070061 if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
cdalton793dc262016-02-08 10:11:47 -080062 array->fType != type ||
bsalomon@google.com6918d482013-03-07 19:09:11 +000063 array->fStride != stride ||
Chris Dalton8e45b4f2017-05-05 14:00:56 -040064 array->fOffset != offsetInBytes) {
cdaltone2e71c22016-04-07 18:13:29 -070065 gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
csmartdaltonb37cb232017-02-08 14:56:27 -050066 const AttribLayout& layout = attrib_layout(type);
Chris Dalton8e45b4f2017-05-05 14:00:56 -040067 const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes);
cdalton793dc262016-02-08 10:11:47 -080068 if (!GrVertexAttribTypeIsIntType(type)) {
69 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
70 layout.fCount,
71 layout.fType,
72 layout.fNormalized,
73 stride,
Chris Dalton8e45b4f2017-05-05 14:00:56 -040074 offsetAsPtr));
cdalton793dc262016-02-08 10:11:47 -080075 } else {
76 SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
77 SkASSERT(!layout.fNormalized);
78 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
79 layout.fCount,
80 layout.fType,
81 stride,
Chris Dalton8e45b4f2017-05-05 14:00:56 -040082 offsetAsPtr));
cdalton793dc262016-02-08 10:11:47 -080083 }
robertphillips8abb3702016-08-31 14:04:06 -070084 array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
cdalton793dc262016-02-08 10:11:47 -080085 array->fType = type;
dchengc4d196c2016-02-06 15:08:54 -080086 array->fStride = stride;
Chris Dalton8e45b4f2017-05-05 14:00:56 -040087 array->fOffset = offsetInBytes;
bsalomon@google.com6918d482013-03-07 19:09:11 +000088 }
Chris Dalton1d616352017-05-31 12:51:23 -060089 if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
90 SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
91 GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
92 array->fDivisor = divisor;
93 }
bsalomon@google.com6918d482013-03-07 19:09:11 +000094}
95
Chris Dalton8e45b4f2017-05-05 14:00:56 -040096void GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount) {
97 SkASSERT(enabledCount <= fAttribArrayStates.count());
Chris Dalton1d616352017-05-31 12:51:23 -060098 if (fEnabledCountIsValid && enabledCount == fNumEnabledArrays) {
99 return;
100 }
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400101
102 int firstIdxToEnable = fEnabledCountIsValid ? fNumEnabledArrays : 0;
103 for (int i = firstIdxToEnable; i < enabledCount; ++i) {
104 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
bsalomon@google.com6918d482013-03-07 19:09:11 +0000105 }
Chris Dalton8e45b4f2017-05-05 14:00:56 -0400106
107 int endIdxToDisable = fEnabledCountIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
108 for (int i = enabledCount; i < endIdxToDisable; ++i) {
109 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
110 }
111
112 fNumEnabledArrays = enabledCount;
113 fEnabledCountIsValid = true;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000114}
115
116///////////////////////////////////////////////////////////////////////////////////////////////////
117
bsalomon8780bc62015-05-13 09:56:37 -0700118GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
119 : fID(id)
bsalomon@google.com6918d482013-03-07 19:09:11 +0000120 , fAttribArrays(attribCount)
cdaltone2e71c22016-04-07 18:13:29 -0700121 , fIndexBufferUniqueID(SK_InvalidUniqueID) {
bsalomon@google.com6918d482013-03-07 19:09:11 +0000122}
123
bsalomon8780bc62015-05-13 09:56:37 -0700124GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
bsalomon@google.com6918d482013-03-07 19:09:11 +0000125 if (0 == fID) {
halcanary96fcdcc2015-08-27 07:41:13 -0700126 return nullptr;
bsalomon@google.com6918d482013-03-07 19:09:11 +0000127 }
bsalomon8780bc62015-05-13 09:56:37 -0700128 gpu->bindVertexArray(fID);
bsalomon@google.com6918d482013-03-07 19:09:11 +0000129 return &fAttribArrays;
130}
skia.committer@gmail.com754a3eb2013-03-08 07:01:25 +0000131
csmartdalton485a1202016-07-13 10:16:32 -0700132GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
bsalomon8780bc62015-05-13 09:56:37 -0700133 GrGLAttribArrayState* state = this->bind(gpu);
robertphillips8abb3702016-08-31 14:04:06 -0700134 if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
csmartdalton485a1202016-07-13 10:16:32 -0700135 if (ibuff->isCPUBacked()) {
136 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
137 } else {
138 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
139 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
140 glBuffer->bufferID()));
141 }
robertphillips8abb3702016-08-31 14:04:06 -0700142 fIndexBufferUniqueID = ibuff->uniqueID();
bsalomon@google.com6918d482013-03-07 19:09:11 +0000143 }
144 return state;
145}
146
bsalomon@google.com6918d482013-03-07 19:09:11 +0000147void GrGLVertexArray::invalidateCachedState() {
commit-bot@chromium.orgce6da4d2013-09-09 14:55:37 +0000148 fAttribArrays.invalidate();
Robert Phillips294870f2016-11-11 12:38:40 -0500149 fIndexBufferUniqueID.makeInvalid();
bsalomon@google.com6918d482013-03-07 19:09:11 +0000150}