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