Line data Source code
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 :
20 0 : static AttribLayout attrib_layout(GrVertexAttribType type) {
21 0 : switch (type) {
22 : case kFloat_GrVertexAttribType:
23 0 : return {false, 1, GR_GL_FLOAT};
24 : case kVec2f_GrVertexAttribType:
25 0 : return {false, 2, GR_GL_FLOAT};
26 : case kVec3f_GrVertexAttribType:
27 0 : return {false, 3, GR_GL_FLOAT};
28 : case kVec4f_GrVertexAttribType:
29 0 : return {false, 4, GR_GL_FLOAT};
30 : case kVec2i_GrVertexAttribType:
31 0 : return {false, 2, GR_GL_INT};
32 : case kVec3i_GrVertexAttribType:
33 0 : return {false, 3, GR_GL_INT};
34 : case kVec4i_GrVertexAttribType:
35 0 : return {false, 4, GR_GL_INT};
36 : case kUByte_GrVertexAttribType:
37 0 : return {true, 1, GR_GL_UNSIGNED_BYTE};
38 : case kVec4ub_GrVertexAttribType:
39 0 : return {true, 4, GR_GL_UNSIGNED_BYTE};
40 : case kVec2us_GrVertexAttribType:
41 0 : return {true, 2, GR_GL_UNSIGNED_SHORT};
42 : case kInt_GrVertexAttribType:
43 0 : return {false, 1, GR_GL_INT};
44 : case kUint_GrVertexAttribType:
45 0 : return {false, 1, GR_GL_UNSIGNED_INT};
46 : }
47 0 : SkFAIL("Unknown vertex attrib type");
48 0 : return {false, 0, 0};
49 : };
50 :
51 0 : void GrGLAttribArrayState::set(GrGLGpu* gpu,
52 : int index,
53 : const GrBuffer* vertexBuffer,
54 : GrVertexAttribType type,
55 : GrGLsizei stride,
56 : GrGLvoid* offset) {
57 0 : SkASSERT(index >= 0 && index < fAttribArrayStates.count());
58 0 : AttribArrayState* array = &fAttribArrayStates[index];
59 0 : if (!array->fEnableIsValid || !array->fEnabled) {
60 0 : GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
61 0 : array->fEnableIsValid = true;
62 0 : array->fEnabled = true;
63 : }
64 0 : if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
65 0 : array->fType != type ||
66 0 : array->fStride != stride ||
67 0 : array->fOffset != offset) {
68 0 : gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
69 0 : const AttribLayout& layout = attrib_layout(type);
70 0 : if (!GrVertexAttribTypeIsIntType(type)) {
71 0 : GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
72 : layout.fCount,
73 : layout.fType,
74 : layout.fNormalized,
75 : stride,
76 : offset));
77 : } else {
78 0 : SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
79 0 : SkASSERT(!layout.fNormalized);
80 0 : GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
81 : layout.fCount,
82 : layout.fType,
83 : stride,
84 : offset));
85 : }
86 0 : array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
87 0 : array->fType = type;
88 0 : array->fStride = stride;
89 0 : array->fOffset = offset;
90 : }
91 0 : }
92 :
93 0 : void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
94 0 : int count = fAttribArrayStates.count();
95 0 : for (int i = 0; i < count; ++i) {
96 0 : if (!(usedMask & 0x1)) {
97 0 : if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
98 0 : GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
99 0 : fAttribArrayStates[i].fEnableIsValid = true;
100 0 : fAttribArrayStates[i].fEnabled = false;
101 : }
102 : } else {
103 0 : 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 0 : usedMask >>= 1;
107 : }
108 0 : }
109 :
110 : ///////////////////////////////////////////////////////////////////////////////////////////////////
111 :
112 0 : GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
113 : : fID(id)
114 : , fAttribArrays(attribCount)
115 0 : , fIndexBufferUniqueID(SK_InvalidUniqueID) {
116 0 : }
117 :
118 0 : GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
119 0 : if (0 == fID) {
120 0 : return nullptr;
121 : }
122 0 : gpu->bindVertexArray(fID);
123 0 : return &fAttribArrays;
124 : }
125 :
126 0 : GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
127 0 : GrGLAttribArrayState* state = this->bind(gpu);
128 0 : if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
129 0 : if (ibuff->isCPUBacked()) {
130 0 : GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
131 : } else {
132 0 : const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
133 0 : GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
134 : glBuffer->bufferID()));
135 : }
136 0 : fIndexBufferUniqueID = ibuff->uniqueID();
137 : }
138 0 : return state;
139 : }
140 :
141 0 : void GrGLVertexArray::invalidateCachedState() {
142 0 : fAttribArrays.invalidate();
143 0 : fIndexBufferUniqueID.makeInvalid();
144 0 : }
|