13f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com/*
23f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com * Copyright 2013 Google Inc.
33f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com *
43f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
53f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com * found in the LICENSE file.
63f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com */
73f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
83f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com#include "GrGLVertexArray.h"
93f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com#include "GrGpuGL.h"
103f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
113f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
123f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X);
133f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
143f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comvoid GrGLAttribArrayState::set(const GrGpuGL* gpu,
153f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               int index,
163f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLVertexBuffer* buffer,
173f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLint size,
183f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLenum type,
193f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLboolean normalized,
203f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLsizei stride,
213f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                               GrGLvoid* offset) {
22a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(index >= 0 && index < fAttribArrayStates.count());
233f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    AttribArrayState* array = &fAttribArrayStates[index];
243f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (!array->fEnableIsValid || !array->fEnabled) {
253f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
263f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fEnableIsValid = true;
273f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fEnabled = true;
283f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
293f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (!array->fAttribPointerIsValid ||
303f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fVertexBufferID != buffer->bufferID() ||
313f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fSize != size ||
323f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fNormalized != normalized ||
333f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fStride != stride ||
343f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fOffset != offset) {
353f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
363f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        buffer->bind();
373f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
383f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                                                           size,
393f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                                                           type,
403f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                                                           normalized,
413f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                                                           stride,
423f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                                                           offset));
433f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fAttribPointerIsValid = true;
443f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fVertexBufferID = buffer->bufferID();
453f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fSize = size;
463f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fNormalized = normalized;
473f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fStride = stride;
483f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        array->fOffset = offset;
493f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
503f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
513f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
520f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.orgvoid GrGLAttribArrayState::setFixedFunctionVertexArray(const GrGpuGL* gpu,
530f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                       GrGLVertexBuffer* buffer,
540f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                       GrGLint size,
550f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                       GrGLenum type,
560f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                       GrGLsizei stride,
570f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                       GrGLvoid* offset) {
580f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    SkASSERT(gpu->glCaps().fixedFunctionSupport());
590f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    AttribArrayState* array = &fFixedFunctionVertexArray;
600f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    if (!array->fEnableIsValid || !array->fEnabled) {
610f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        GR_GL_CALL(gpu->glInterface(), EnableClientState(GR_GL_VERTEX_ARRAY));
620f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fEnableIsValid = true;
630f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fEnabled = true;
640f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    }
650f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    if (!array->fAttribPointerIsValid ||
660f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fVertexBufferID != buffer->bufferID() ||
670f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fSize != size ||
680f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fStride != stride ||
690f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fOffset != offset) {
700f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org
710f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        buffer->bind();
720f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        GR_GL_CALL(gpu->glInterface(), VertexPointer(size,
730f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                     type,
740f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                     stride,
750f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                                                     offset));
760f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fAttribPointerIsValid = true;
770f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fVertexBufferID = buffer->bufferID();
780f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fSize = size;
790f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fStride = stride;
800f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        array->fOffset = offset;
810f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    }
820f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org}
830f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org
840f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.orgvoid GrGLAttribArrayState::disableUnusedArrays(const GrGpuGL* gpu, uint64_t usedMask, bool usingFFVertexArray) {
853f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    int count = fAttribArrayStates.count();
863f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    for (int i = 0; i < count; ++i) {
873f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        if (!(usedMask & 0x1)) {
883f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
893f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
903f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                fAttribArrayStates[i].fEnableIsValid = true;
913f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com                fAttribArrayStates[i].fEnabled = false;
923f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            }
930f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        } else {
940f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
953f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        }
963f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
973f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        usedMask >>= 1;
983f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
990f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org
1000f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    // Deal with fixed-function vertex arrays.
1010f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    if (gpu->glCaps().fixedFunctionSupport()) {
1020f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        if (!usingFFVertexArray) {
1030f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            if (!fFixedFunctionVertexArray.fEnableIsValid || fFixedFunctionVertexArray.fEnabled) {
1040f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_VERTEX_ARRAY));
1050f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                fFixedFunctionVertexArray.fEnableIsValid = true;
1060f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                fFixedFunctionVertexArray.fEnabled = false;
1070f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            }
1080f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        } else {
1090f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            SkASSERT(fFixedFunctionVertexArray.fEnableIsValid && fFixedFunctionVertexArray.fEnabled);
1100f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        }
1110f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        // When we use fixed function vertex processing we always use the vertex array and none of
1120f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        // the other arrays.
1130f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        if (!fUnusedFixedFunctionArraysDisabled) {
1140f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_NORMAL_ARRAY));
1150f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_COLOR_ARRAY));
1160f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_SECONDARY_COLOR_ARRAY));
1170f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_INDEX_ARRAY));
1180f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_EDGE_FLAG_ARRAY));
1190f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            for (int i = 0; i < gpu->glCaps().maxFixedFunctionTextureCoords(); ++i) {
1200f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                GR_GL_CALL(gpu->glInterface(), ClientActiveTexture(GR_GL_TEXTURE0 + i));
1210f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org                GR_GL_CALL(gpu->glInterface(), DisableClientState(GR_GL_TEXTURE_COORD_ARRAY));
1220f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            }
1230f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org            fUnusedFixedFunctionArraysDisabled = true;
1240f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        }
1250f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    } else {
1260f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org        SkASSERT(!usingFFVertexArray);
1270f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    }
1283f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
1293f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1303f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
1313f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1323f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comGrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount)
1333f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    : GrResource(gpu, false)
1343f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    , fID(id)
1353f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    , fAttribArrays(attribCount)
1363f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    , fIndexBufferIDIsValid(false) {
1373f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
1383f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1393f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comvoid GrGLVertexArray::onAbandon() {
1403f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    fID = 0;
1413f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    INHERITED::onAbandon();
1423f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
1433f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1443f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comvoid GrGLVertexArray::onRelease() {
1453f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (0 != fID) {
1463f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GL_CALL(DeleteVertexArrays(1, &fID));
1473f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GPUGL->notifyVertexArrayDelete(fID);
1483f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        fID = 0;
1493f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
1503f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    INHERITED::onRelease();
1513f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
1523f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1533f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comGrGLAttribArrayState* GrGLVertexArray::bind() {
1543f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (0 == fID) {
1553f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        return NULL;
1563f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
1573f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GPUGL->bindVertexArray(fID);
1583f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    return &fAttribArrays;
1593f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
16029b3cce7ba96f4a35037be9373e5a69a57e86336skia.committer@gmail.com
1613f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comGrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) {
1623f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    GrGLAttribArrayState* state = this->bind();
1633f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (NULL != state && NULL != buffer) {
1643f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        GrGLuint bufferID = buffer->bufferID();
1653f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) {
1663f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID));
1673f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            fIndexBufferIDIsValid = true;
1683f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com            fIndexBufferID = bufferID;
1693f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        }
1703f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
1713f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    return state;
1723f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
1733f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1743f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comvoid GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) {
1753f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) {
1763f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com        fIndexBufferID = 0;
1773f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    }
1783f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com }
1793f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com
1803f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.comvoid GrGLVertexArray::invalidateCachedState() {
1810f1951e72a0b0670c5cbdb22920bb49f6abe3d21commit-bot@chromium.org    fAttribArrays.invalidate();
1823f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com    fIndexBufferIDIsValid = false;
1833f177e9cbcd94d9fc9d969591cc939a81d16d111bsalomon@google.com}
184