16918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com/*
26918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com * Copyright 2013 Google Inc.
36918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com *
46918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
56918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com * found in the LICENSE file.
66918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com */
76918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
86918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com#include "GrGLVertexArray.h"
9e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton#include "GrGLBuffer.h"
1039edf7664f50b6c890b933b5bbed67a8735b349bjvanverth#include "GrGLGpu.h"
116918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
12793dc26ca6ba2543bf50e5215b858d1c265af50ccdaltonstruct AttribLayout {
13b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    bool        fNormalized;  // Only used by floating point types.
14b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    uint8_t     fCount;
15b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    uint16_t    fType;
16793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton};
176918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
18b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdaltonGR_STATIC_ASSERT(4 == sizeof(AttribLayout));
19793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton
20b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdaltonstatic AttribLayout attrib_layout(GrVertexAttribType type) {
21b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    switch (type) {
22b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kFloat_GrVertexAttribType:
23b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 1, GR_GL_FLOAT};
24b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec2f_GrVertexAttribType:
25b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 2, GR_GL_FLOAT};
26b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec3f_GrVertexAttribType:
27b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 3, GR_GL_FLOAT};
28b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec4f_GrVertexAttribType:
29b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 4, GR_GL_FLOAT};
30b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec2i_GrVertexAttribType:
31b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 2, GR_GL_INT};
32b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec3i_GrVertexAttribType:
33b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 3, GR_GL_INT};
34b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec4i_GrVertexAttribType:
35b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 4, GR_GL_INT};
36b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kUByte_GrVertexAttribType:
37b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {true, 1, GR_GL_UNSIGNED_BYTE};
38b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec4ub_GrVertexAttribType:
39b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {true, 4, GR_GL_UNSIGNED_BYTE};
40b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kVec2us_GrVertexAttribType:
41b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {true, 2, GR_GL_UNSIGNED_SHORT};
42b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kInt_GrVertexAttribType:
43b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 1, GR_GL_INT};
44b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        case kUint_GrVertexAttribType:
45b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton            return {false, 1, GR_GL_UNSIGNED_INT};
46b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    }
47b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    SkFAIL("Unknown vertex attrib type");
48b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton    return {false, 0, 0};
49b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton};
506df86409ca586c3cb34f616f03501bd96181f9e4bsalomon
516df86409ca586c3cb34f616f03501bd96181f9e4bsalomonvoid GrGLAttribArrayState::set(GrGLGpu* gpu,
526918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                               int index,
53485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton                               const GrBuffer* vertexBuffer,
54793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                               GrVertexAttribType type,
556918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                               GrGLsizei stride,
566918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                               GrGLvoid* offset) {
57f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(index >= 0 && index < fAttribArrayStates.count());
586918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    AttribArrayState* array = &fAttribArrayStates[index];
596918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    if (!array->fEnableIsValid || !array->fEnabled) {
606918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
616918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        array->fEnableIsValid = true;
626918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        array->fEnabled = true;
636918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    }
648abb370aca280516f4861c6c942ec453aad018farobertphillips    if (array->fVertexBufferUniqueID != vertexBuffer->uniqueID() ||
65793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton        array->fType != type ||
666918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        array->fStride != stride ||
676918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        array->fOffset != offset) {
68e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton        gpu->bindBuffer(kVertex_GrBufferType, vertexBuffer);
69b37cb236c3a698b45a7d0deca0df32bb70bbaaa6csmartdalton        const AttribLayout& layout = attrib_layout(type);
70793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton        if (!GrVertexAttribTypeIsIntType(type)) {
71793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton            GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
72793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                               layout.fCount,
73793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                               layout.fType,
74793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                               layout.fNormalized,
75793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                               stride,
76793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                               offset));
77793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton        } else {
78793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton            SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
79793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton            SkASSERT(!layout.fNormalized);
80793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton            GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
81793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                                layout.fCount,
82793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                                layout.fType,
83793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                                stride,
84793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton                                                                offset));
85793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton        }
868abb370aca280516f4861c6c942ec453aad018farobertphillips        array->fVertexBufferUniqueID = vertexBuffer->uniqueID();
87793dc26ca6ba2543bf50e5215b858d1c265af50ccdalton        array->fType = type;
88c4d196c9c87f226eb33b8091dc50053c45c4e752dcheng        array->fStride = stride;
896918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        array->fOffset = offset;
906918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    }
916918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
926918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
93861e1037017bbb7ac52ec5ebecab3a636a82a3e8bsalomonvoid GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
946918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    int count = fAttribArrayStates.count();
956918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    for (int i = 0; i < count; ++i) {
966918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        if (!(usedMask & 0x1)) {
976918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com            if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
986918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
996918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                fAttribArrayStates[i].fEnableIsValid = true;
1006918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com                fAttribArrayStates[i].fEnabled = false;
1016918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com            }
102ce6da4d96ae00a66c56c45a3b902224d8b3e6cf7commit-bot@chromium.org        } else {
103ce6da4d96ae00a66c56c45a3b902224d8b3e6cf7commit-bot@chromium.org            SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
1046918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        }
1056918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
1066918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com        usedMask >>= 1;
1076918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    }
1086918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
1096918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
1106918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
1116918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
1128780bc65bd5a53a38ac4b0a53a5fb283e066ec40bsalomonGrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
1138780bc65bd5a53a38ac4b0a53a5fb283e066ec40bsalomon    : fID(id)
1146918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    , fAttribArrays(attribCount)
115e2e71c2df4e72e897bbe745752be0444aee5c29fcdalton    , fIndexBufferUniqueID(SK_InvalidUniqueID) {
1166918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
1176918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
1188780bc65bd5a53a38ac4b0a53a5fb283e066ec40bsalomonGrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
1196918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    if (0 == fID) {
12096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        return nullptr;
1216918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    }
1228780bc65bd5a53a38ac4b0a53a5fb283e066ec40bsalomon    gpu->bindVertexArray(fID);
1236918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    return &fAttribArrays;
1246918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
125754a3eb73b796398062f09cc98eae224262a3bc8skia.committer@gmail.com
126485a12003ab48b54965d6f7172f3183358919d8ecsmartdaltonGrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, const GrBuffer* ibuff) {
1278780bc65bd5a53a38ac4b0a53a5fb283e066ec40bsalomon    GrGLAttribArrayState* state = this->bind(gpu);
1288abb370aca280516f4861c6c942ec453aad018farobertphillips    if (state && fIndexBufferUniqueID != ibuff->uniqueID()) {
129485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton        if (ibuff->isCPUBacked()) {
130485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton            GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, 0));
131485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton        } else {
132485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton            const GrGLBuffer* glBuffer = static_cast<const GrGLBuffer*>(ibuff);
133485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton            GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER,
134485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton                                                      glBuffer->bufferID()));
135485a12003ab48b54965d6f7172f3183358919d8ecsmartdalton        }
1368abb370aca280516f4861c6c942ec453aad018farobertphillips        fIndexBufferUniqueID = ibuff->uniqueID();
1376918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    }
1386918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com    return state;
1396918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
1406918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com
1416918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.comvoid GrGLVertexArray::invalidateCachedState() {
142ce6da4d96ae00a66c56c45a3b902224d8b3e6cf7commit-bot@chromium.org    fAttribArrays.invalidate();
143294870ff119b89fc902773643b054f14e5d1f554Robert Phillips    fIndexBufferUniqueID.makeInvalid();
1446918d482d64f045a4c980b2fb267bc939953638ebsalomon@google.com}
145