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
8 #include "GrGLVertexArray.h"
9 #include "GrGLBuffer.h"
10 #include "GrGLGpu.h"
11
12 struct AttribLayout {
13 bool fNormalized; // Only used by floating point types.
14 uint8_t fCount;
15 uint16_t fType;
16 };
17
18 GR_STATIC_ASSERT(4 == sizeof(AttribLayout));
19
attrib_layout(GrVertexAttribType type)20 static 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 };
50
set(GrGLGpu * gpu,int index,const GrBuffer * vertexBuffer,GrVertexAttribType type,GrGLsizei stride,GrGLvoid * offset)51 void GrGLAttribArrayState::set(GrGLGpu* gpu,
52 int index,
53 const GrBuffer* vertexBuffer,
54 GrVertexAttribType type,
55 GrGLsizei stride,
56 GrGLvoid* offset) {
57 SkASSERT(index >= 0 && index < fAttribArrayStates.count());
58 AttribArrayState* array = &fAttribArrayStates[index];
59 if (!array->fEnableIsValid || !array->fEnabled) {
60 GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
61 array->fEnableIsValid = true;
62 array->fEnabled = true;
63 }
64 if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
65 array->fType != type ||
66 array->fStride != stride ||
67 array->fOffset != offset) {
68 gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
69 const AttribLayout& layout = attrib_layout(type);
70 if (!GrVertexAttribTypeIsIntType(type)) {
71 GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
72 layout.fCount,
73 layout.fType,
74 layout.fNormalized,
75 stride,
76 offset));
77 } else {
78 SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
79 SkASSERT(!layout.fNormalized);
80 GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
81 layout.fCount,
82 layout.fType,
83 stride,
84 offset));
85 }
86 array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
87 array->fType = type;
88 array->fStride = stride;
89 array->fOffset = offset;
90 }
91 }
92
disableUnusedArrays(const GrGLGpu * gpu,uint64_t usedMask)93 void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
94 int count = fAttribArrayStates.count();
95 for (int i = 0; i < count; ++i) {
96 if (!(usedMask & 0x1)) {
97 if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
98 GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
99 fAttribArrayStates[i].fEnableIsValid = true;
100 fAttribArrayStates[i].fEnabled = false;
101 }
102 } else {
103 SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
104 }
105 // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
106 usedMask >>= 1;
107 }
108 }
109
110 ///////////////////////////////////////////////////////////////////////////////////////////////////
111
GrGLVertexArray(GrGLint id,int attribCount)112 GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
113 : fID(id)
114 , fAttribArrays(attribCount)
115 , fIndexBufferUniqueID(SK_InvalidUniqueID) {
116 }
117
bind(GrGLGpu * gpu)118 GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
119 if (0 == fID) {
120 return nullptr;
121 }
122 gpu->bindVertexArray(fID);
123 return &fAttribArrays;
124 }
125
bindWithIndexBuffer(GrGLGpu * gpu,const GrBuffer * ibuff)126 GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
127 GrGLAttribArrayState* state = this->bind(gpu);
128 if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
129 if (ibuff->isCPUBacked()) {
130 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
131 } else {
132 const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
133 GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
134 glBuffer->bufferID()));
135 }
136 fIndexBufferUniqueID = ibuff->uniqueID();
137 }
138 return state;
139 }
140
invalidateCachedState()141 void GrGLVertexArray::invalidateCachedState() {
142 fAttribArrays.invalidate();
143 fIndexBufferUniqueID.makeInvalid();
144 }
145