/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "renderstate/MeshState.h"

#include "Program.h"

#include "ShadowTessellator.h"

namespace android {
namespace uirenderer {

MeshState::MeshState()
        : mCurrentIndicesBuffer(0)
        , mCurrentPixelBuffer(0)
        , mCurrentPositionPointer(this)
        , mCurrentPositionStride(0)
        , mCurrentTexCoordsPointer(this)
        , mCurrentTexCoordsStride(0)
        , mTexCoordsArrayEnabled(false)
        , mQuadListIndices(0) {
    glGenBuffers(1, &mUnitQuadBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, mUnitQuadBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(kUnitQuadVertices), kUnitQuadVertices, GL_STATIC_DRAW);

    mCurrentBuffer = mUnitQuadBuffer;

    std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]);
    for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
        uint16_t quad = i * 4;
        int index = i * 6;
        regionIndices[index    ] = quad;       // top-left
        regionIndices[index + 1] = quad + 1;   // top-right
        regionIndices[index + 2] = quad + 2;   // bottom-left
        regionIndices[index + 3] = quad + 2;   // bottom-left
        regionIndices[index + 4] = quad + 1;   // top-right
        regionIndices[index + 5] = quad + 3;   // bottom-right
    }
    glGenBuffers(1, &mQuadListIndices);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t),
            regionIndices.get(), GL_STATIC_DRAW);
    mCurrentIndicesBuffer = mQuadListIndices;

    // position attribute always enabled
    glEnableVertexAttribArray(Program::kBindingPosition);
}

MeshState::~MeshState() {
    glDeleteBuffers(1, &mUnitQuadBuffer);
    mCurrentBuffer = 0;

    glDeleteBuffers(1, &mQuadListIndices);
    mQuadListIndices = 0;
}

void MeshState::dump() {
    ALOGD("MeshState VBOs: unitQuad %d, current %d", mUnitQuadBuffer, mCurrentBuffer);
    ALOGD("MeshState vertices: vertex data %p, stride %d",
            mCurrentPositionPointer, mCurrentPositionStride);
    ALOGD("MeshState texCoord: data %p, stride %d",
            mCurrentTexCoordsPointer, mCurrentTexCoordsStride);
}

///////////////////////////////////////////////////////////////////////////////
// Buffer Objects
///////////////////////////////////////////////////////////////////////////////

bool MeshState::bindMeshBuffer() {
    return bindMeshBuffer(mUnitQuadBuffer);
}

bool MeshState::bindMeshBuffer(GLuint buffer) {
    if (!buffer) buffer = mUnitQuadBuffer;
    return bindMeshBufferInternal(buffer);
}

bool MeshState::unbindMeshBuffer() {
    return bindMeshBufferInternal(0);
}

bool MeshState::bindMeshBufferInternal(GLuint buffer) {
    if (mCurrentBuffer != buffer) {
        glBindBuffer(GL_ARRAY_BUFFER, buffer);
        mCurrentBuffer = buffer;
        return true;
    }
    return false;
}

///////////////////////////////////////////////////////////////////////////////
// Vertices
///////////////////////////////////////////////////////////////////////////////

void MeshState::bindPositionVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
    if (force || vertices != mCurrentPositionPointer || stride != mCurrentPositionStride) {
        glVertexAttribPointer(Program::kBindingPosition, 2, GL_FLOAT, GL_FALSE, stride, vertices);
        mCurrentPositionPointer = vertices;
        mCurrentPositionStride = stride;
    }
}

void MeshState::bindTexCoordsVertexPointer(bool force, const GLvoid* vertices, GLsizei stride) {
    if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
        glVertexAttribPointer(Program::kBindingTexCoords, 2, GL_FLOAT, GL_FALSE, stride, vertices);
        mCurrentTexCoordsPointer = vertices;
        mCurrentTexCoordsStride = stride;
    }
}

void MeshState::resetVertexPointers() {
    mCurrentPositionPointer = this;
    mCurrentTexCoordsPointer = this;
}

void MeshState::resetTexCoordsVertexPointer() {
    mCurrentTexCoordsPointer = this;
}

void MeshState::enableTexCoordsVertexArray() {
    if (!mTexCoordsArrayEnabled) {
        glEnableVertexAttribArray(Program::kBindingTexCoords);
        mCurrentTexCoordsPointer = this;
        mTexCoordsArrayEnabled = true;
    }
}

void MeshState::disableTexCoordsVertexArray() {
    if (mTexCoordsArrayEnabled) {
        glDisableVertexAttribArray(Program::kBindingTexCoords);
        mTexCoordsArrayEnabled = false;
    }
}

///////////////////////////////////////////////////////////////////////////////
// Indices
///////////////////////////////////////////////////////////////////////////////

bool MeshState::bindIndicesBufferInternal(const GLuint buffer) {
    if (mCurrentIndicesBuffer != buffer) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
        mCurrentIndicesBuffer = buffer;
        return true;
    }
    return false;
}

bool MeshState::bindQuadIndicesBuffer() {
    return bindIndicesBufferInternal(mQuadListIndices);
}

bool MeshState::unbindIndicesBuffer() {
    if (mCurrentIndicesBuffer) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        mCurrentIndicesBuffer = 0;
        return true;
    }
    return false;
}

} /* namespace uirenderer */
} /* namespace android */

