1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2013 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGLVertexArray.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGLBuffer.h"
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrGLGpu.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct AttribLayout {
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool        fNormalized;  // Only used by floating point types.
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint8_t     fCount;
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uint16_t    fType;
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGR_STATIC_ASSERT(4 == sizeof(AttribLayout));
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic AttribLayout attrib_layout(GrVertexAttribType type) {
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (type) {
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat_GrVertexAttribType:
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 1, GR_GL_FLOAT};
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat2_GrVertexAttribType:
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 2, GR_GL_FLOAT};
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat3_GrVertexAttribType:
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 3, GR_GL_FLOAT};
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat4_GrVertexAttribType:
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 4, GR_GL_FLOAT};
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf_GrVertexAttribType:
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 1, GR_GL_FLOAT};
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf2_GrVertexAttribType:
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 2, GR_GL_FLOAT};
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf3_GrVertexAttribType:
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 3, GR_GL_FLOAT};
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf4_GrVertexAttribType:
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 4, GR_GL_FLOAT};
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt2_GrVertexAttribType:
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 2, GR_GL_INT};
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt3_GrVertexAttribType:
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 3, GR_GL_INT};
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt4_GrVertexAttribType:
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 4, GR_GL_INT};
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUByte_norm_GrVertexAttribType:
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {true, 1, GR_GL_UNSIGNED_BYTE};
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUByte4_norm_GrVertexAttribType:
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {true, 4, GR_GL_UNSIGNED_BYTE};
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kShort2_GrVertexAttribType:
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 2, GR_GL_SHORT};
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUShort2_GrVertexAttribType:
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 2, GR_GL_UNSIGNED_SHORT};
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUShort2_norm_GrVertexAttribType:
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {true, 2, GR_GL_UNSIGNED_SHORT};
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt_GrVertexAttribType:
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 1, GR_GL_INT};
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUint_GrVertexAttribType:
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return {false, 1, GR_GL_UNSIGNED_INT};
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ABORT("Unknown vertex attrib type");
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return {false, 0, 0};
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool GrVertexAttribTypeIsIntType(const GrShaderCaps* shaderCaps,
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        GrVertexAttribType type) {
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    switch (type) {
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat_GrVertexAttribType:
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat2_GrVertexAttribType:
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat3_GrVertexAttribType:
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kFloat4_GrVertexAttribType:
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf_GrVertexAttribType:
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf2_GrVertexAttribType:
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf3_GrVertexAttribType:
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kHalf4_GrVertexAttribType:
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt2_GrVertexAttribType:
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt3_GrVertexAttribType:
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt4_GrVertexAttribType:
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUByte_norm_GrVertexAttribType:
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUByte4_norm_GrVertexAttribType:
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kShort2_GrVertexAttribType:
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUShort2_GrVertexAttribType:
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return shaderCaps->integerSupport(); // FIXME: caller should handle this.
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUShort2_norm_GrVertexAttribType:
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return false;
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kInt_GrVertexAttribType:
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        case kUint_GrVertexAttribType:
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            return true;
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SK_ABORT("Unexpected attribute type");
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return false;
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLAttribArrayState::set(GrGLGpu* gpu,
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               int index,
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               const GrBuffer* vertexBuffer,
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               GrVertexAttribType type,
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               GrGLsizei stride,
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               size_t offsetInBytes,
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                               int divisor) {
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(index >= 0 && index < fAttribArrayStates.count());
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 == divisor || gpu->caps()->instanceAttribSupport());
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    AttribArrayState* array = &fAttribArrayStates[index];
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fType != type ||
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fStride != stride ||
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fOffset != offsetInBytes) {
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const AttribLayout& layout = attrib_layout(type);
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        const GrGLvoid* offsetAsPtr = reinterpret_cast<const GrGLvoid*>(offsetInBytes);
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (!GrVertexAttribTypeIsIntType(gpu->caps()->shaderCaps(), type)) {
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               layout.fCount,
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               layout.fType,
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               layout.fNormalized,
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               stride,
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                               offsetAsPtr));
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            SkASSERT(!layout.fNormalized);
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                layout.fCount,
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                layout.fType,
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                stride,
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                offsetAsPtr));
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fType = type;
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fStride = stride;
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fOffset = offsetInBytes;
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (gpu->caps()->instanceAttribSupport() && array->fDivisor != divisor) {
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        SkASSERT(0 == divisor || 1 == divisor); // not necessarily a requirement but what we expect.
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        GR_GL_CALL(gpu->glInterface(), VertexAttribDivisor(index, divisor));
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        array->fDivisor = divisor;
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLAttribArrayState::enableVertexArrays(const GrGLGpu* gpu, int enabledCount,
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                              EnablePrimitiveRestart enablePrimitiveRestart) {
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(enabledCount <= fAttribArrayStates.count());
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!fEnableStateIsValid || enabledCount != fNumEnabledArrays) {
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int firstIdxToEnable = fEnableStateIsValid ? fNumEnabledArrays : 0;
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = firstIdxToEnable; i < enabledCount; ++i) {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(i));
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int endIdxToDisable = fEnableStateIsValid ? fNumEnabledArrays : fAttribArrayStates.count();
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = enabledCount; i < endIdxToDisable; ++i) {
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fNumEnabledArrays = enabledCount;
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(EnablePrimitiveRestart::kNo == enablePrimitiveRestart ||
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot             gpu->caps()->usePrimitiveRestart());
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (gpu->caps()->usePrimitiveRestart() &&
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        (!fEnableStateIsValid || enablePrimitiveRestart != fPrimitiveRestartEnabled)) {
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (EnablePrimitiveRestart::kYes == enablePrimitiveRestart) {
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), Enable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), Disable(GR_GL_PRIMITIVE_RESTART_FIXED_INDEX));
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fPrimitiveRestartEnabled = enablePrimitiveRestart;
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fEnableStateIsValid = true;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot///////////////////////////////////////////////////////////////////////////////////////////////////
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    : fID(id)
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    , fAttribArrays(attribCount)
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    , fIndexBufferUniqueID(SK_InvalidUniqueID) {
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (0 == fID) {
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return nullptr;
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    gpu->bindVertexArray(fID);
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return &fAttribArrays;
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLAttribArrayState* state = this->bind(gpu);
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (ibuff->isCPUBacked()) {
207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        } else {
209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                      glBuffer->bufferID()));
212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fIndexBufferUniqueID = ibuff->uniqueID();
214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return state;
216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLVertexArray::invalidateCachedState() {
219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fAttribArrays.invalidate();
220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fIndexBufferUniqueID.makeInvalid();
221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
222