/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrGLVertexArray.h"
#include "GrGLGpu.h"

struct AttribLayout {
    GrGLint     fCount;
    GrGLenum    fType;
    GrGLboolean fNormalized;  // Only used by floating point types.
};

static const AttribLayout gLayouts[kGrVertexAttribTypeCount] = {
    {1, GR_GL_FLOAT, false},         // kFloat_GrVertexAttribType
    {2, GR_GL_FLOAT, false},         // kVec2f_GrVertexAttribType
    {3, GR_GL_FLOAT, false},         // kVec3f_GrVertexAttribType
    {4, GR_GL_FLOAT, false},         // kVec4f_GrVertexAttribType
    {1, GR_GL_UNSIGNED_BYTE, true},  // kUByte_GrVertexAttribType
    {4, GR_GL_UNSIGNED_BYTE, true},  // kVec4ub_GrVertexAttribType
    {2, GR_GL_UNSIGNED_SHORT, true}, // kVec2s_GrVertexAttribType
    {1, GR_GL_INT, false},           // kInt_GrVertexAttribType
    {1, GR_GL_UNSIGNED_INT, false},  // kUint_GrVertexAttribType
};

GR_STATIC_ASSERT(0 == kFloat_GrVertexAttribType);
GR_STATIC_ASSERT(1 == kVec2f_GrVertexAttribType);
GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);

void GrGLAttribArrayState::set(GrGLGpu* gpu,
                               int index,
                               GrGLuint vertexBufferID,
                               GrVertexAttribType type,
                               GrGLsizei stride,
                               GrGLvoid* offset) {
    SkASSERT(index >= 0 && index < fAttribArrayStates.count());
    AttribArrayState* array = &fAttribArrayStates[index];
    if (!array->fEnableIsValid || !array->fEnabled) {
        GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
        array->fEnableIsValid = true;
        array->fEnabled = true;
    }
    if (!array->fAttribPointerIsValid ||
        array->fVertexBufferID != vertexBufferID ||
        array->fType != type ||
        array->fStride != stride ||
        array->fOffset != offset) {

        gpu->bindVertexBuffer(vertexBufferID);
        const AttribLayout& layout = gLayouts[type];
        if (!GrVertexAttribTypeIsIntType(type)) {
            GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
                                                               layout.fCount,
                                                               layout.fType,
                                                               layout.fNormalized,
                                                               stride,
                                                               offset));
        } else {
            SkASSERT(gpu->caps()->shaderCaps()->integerSupport());
            SkASSERT(!layout.fNormalized);
            GR_GL_CALL(gpu->glInterface(), VertexAttribIPointer(index,
                                                                layout.fCount,
                                                                layout.fType,
                                                                stride,
                                                                offset));
        }
        array->fAttribPointerIsValid = true;
        array->fVertexBufferID = vertexBufferID;
        array->fType = type;
        array->fStride = stride;
        array->fOffset = offset;
    }
}

void GrGLAttribArrayState::disableUnusedArrays(const GrGLGpu* gpu, uint64_t usedMask) {
    int count = fAttribArrayStates.count();
    for (int i = 0; i < count; ++i) {
        if (!(usedMask & 0x1)) {
            if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) {
                GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i));
                fAttribArrayStates[i].fEnableIsValid = true;
                fAttribArrayStates[i].fEnabled = false;
            }
        } else {
            SkASSERT(fAttribArrayStates[i].fEnableIsValid && fAttribArrayStates[i].fEnabled);
        }
        // if the count is greater than 64 then this will become 0 and we will disable arrays 64+.
        usedMask >>= 1;
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////

GrGLVertexArray::GrGLVertexArray(GrGLint id, int attribCount)
    : fID(id)
    , fAttribArrays(attribCount)
    , fIndexBufferIDIsValid(false) {
}

GrGLAttribArrayState* GrGLVertexArray::bind(GrGLGpu* gpu) {
    if (0 == fID) {
        return nullptr;
    }
    gpu->bindVertexArray(fID);
    return &fAttribArrays;
}

GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(GrGLGpu* gpu, GrGLuint ibufferID) {
    GrGLAttribArrayState* state = this->bind(gpu);
    if (state) {
        if (!fIndexBufferIDIsValid || ibufferID != fIndexBufferID) {            
            GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibufferID));
            fIndexBufferIDIsValid = true;
            fIndexBufferID = ibufferID;
        }
    }
    return state;
}

void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) {
    if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) {
        fIndexBufferID = 0;
    }
 }

void GrGLVertexArray::invalidateCachedState() {
    fAttribArrays.invalidate();
    fIndexBufferIDIsValid = false;
}
