/*
 * Copyright (C) 2011 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 <GLES/gl.h>
#include <GLES2/gl2.h>
#include <GLES/glext.h>

#include <rs_hal.h>
#include <rsContext.h>
#include <rsMesh.h>

#include "rsdAllocation.h"
#include "rsdMeshObj.h"
#include "rsdGL.h"

#include <string>

using android::renderscript::Allocation;
using android::renderscript::Context;
using android::renderscript::Element;
using android::renderscript::Mesh;

RsdMeshObj::RsdMeshObj(const Context *rsc, const Mesh *rsMesh) {
    mRSMesh = rsMesh;

    mAttribs = nullptr;
    mAttribAllocationIndex = nullptr;
    mGLPrimitives = nullptr;

    mAttribCount = 0;
}

RsdMeshObj::~RsdMeshObj() {
    if (mAttribs) {
        delete[] mAttribs;
        delete[] mAttribAllocationIndex;
    }
    if (mGLPrimitives) {
        delete[] mGLPrimitives;
    }
}

bool RsdMeshObj::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
    // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
    // Filter rs types accordingly
    RsDataType dt = elem->mHal.state.fields[fieldIdx]->mHal.state.dataType;
    if (dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
        dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
        dt != RS_TYPE_SIGNED_16) {
        return false;
    }

    // Now make sure they are not arrays
    uint32_t arraySize = elem->mHal.state.fieldArraySizes[fieldIdx];
    if (arraySize != 1) {
        return false;
    }

    return true;
}

bool RsdMeshObj::init(const Context *rsc) {

    updateGLPrimitives(rsc);

    // Count the number of gl attrs to initialize
    mAttribCount = 0;
    for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
        const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
        for (uint32_t ct=0; ct < elem->mHal.state.fieldsCount; ct++) {
            if (isValidGLComponent(elem, ct)) {
                mAttribCount ++;
            }
        }
    }

    if (mAttribs) {
        delete [] mAttribs;
        delete [] mAttribAllocationIndex;
        mAttribs = nullptr;
        mAttribAllocationIndex = nullptr;
    }
    if (!mAttribCount) {
        return false;
    }

    mAttribs = new RsdVertexArray::Attrib[mAttribCount];
    mAttribAllocationIndex = new uint32_t[mAttribCount];

    uint32_t userNum = 0;
    for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
        const Element *elem = mRSMesh->mHal.state.vertexBuffers[ct]->getType()->getElement();
        uint32_t stride = elem->mHal.state.elementSizeBytes;
        for (uint32_t fieldI=0; fieldI < elem->mHal.state.fieldsCount; fieldI++) {
            const Element *f = elem->mHal.state.fields[fieldI];

            if (!isValidGLComponent(elem, fieldI)) {
                continue;
            }

            mAttribs[userNum].size = f->mHal.state.vectorSize;
            mAttribs[userNum].offset = elem->mHal.state.fieldOffsetBytes[fieldI];
            mAttribs[userNum].type = rsdTypeToGLType(f->mHal.state.dataType);
            mAttribs[userNum].normalized = f->mHal.state.dataType != RS_TYPE_FLOAT_32;
            mAttribs[userNum].stride = stride;
            std::string tmp(RS_SHADER_ATTR);
            tmp.append(elem->mHal.state.fieldNames[fieldI]);
            mAttribs[userNum].name = tmp;

            // Remember which allocation this attribute came from
            mAttribAllocationIndex[userNum] = ct;
            userNum ++;
        }
    }

    return true;
}

void RsdMeshObj::renderPrimitiveRange(const Context *rsc, uint32_t primIndex,
                                      size_t start, uint32_t len) const {
    if (len < 1 || primIndex >= mRSMesh->mHal.state.primitivesCount || mAttribCount == 0) {
        rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh or parameters");
        return;
    }

    for (uint32_t ct=0; ct < mRSMesh->mHal.state.vertexBuffersCount; ct++) {
        const Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[ct];
        DrvAllocation *drv = (DrvAllocation *)alloc->mHal.drv;
        if (drv->uploadDeferred) {
            rsdAllocationSyncAll(rsc, alloc, RS_ALLOCATION_USAGE_SCRIPT);
        }
    }

    // update attributes with either buffer information or data ptr based on their current state
    for (uint32_t ct=0; ct < mAttribCount; ct++) {
        uint32_t allocIndex = mAttribAllocationIndex[ct];
        Allocation *alloc = mRSMesh->mHal.state.vertexBuffers[allocIndex];
        DrvAllocation *drvAlloc = (DrvAllocation *)alloc->mHal.drv;

        if (drvAlloc->bufferID) {
            mAttribs[ct].buffer = drvAlloc->bufferID;
            mAttribs[ct].ptr = nullptr;
        } else {
            mAttribs[ct].buffer = 0;
            mAttribs[ct].ptr = (const uint8_t*)alloc->mHal.drvState.lod[0].mallocPtr;
        }
    }

    RsdVertexArray va(mAttribs, mAttribCount);
    va.setup(rsc);

    const Allocation *idxAlloc = mRSMesh->mHal.state.indexBuffers[primIndex];
    if (idxAlloc) {
        DrvAllocation *drvAlloc = (DrvAllocation *)idxAlloc->mHal.drv;
        if (drvAlloc->uploadDeferred) {
            rsdAllocationSyncAll(rsc, idxAlloc, RS_ALLOCATION_USAGE_SCRIPT);
        }

        if (drvAlloc->bufferID) {
            RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, drvAlloc->bufferID);
            RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
                        (uint16_t *)(start * 2));
        } else {
            RSD_CALL_GL(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER, 0);
            RSD_CALL_GL(glDrawElements, mGLPrimitives[primIndex], len, GL_UNSIGNED_SHORT,
                        idxAlloc->mHal.drvState.lod[0].mallocPtr);
        }
    } else {
        RSD_CALL_GL(glDrawArrays, mGLPrimitives[primIndex], start, len);
    }

    rsdGLCheckError(rsc, "Mesh::renderPrimitiveRange");
}

void RsdMeshObj::updateGLPrimitives(const Context *rsc) {
    mGLPrimitives = new uint32_t[mRSMesh->mHal.state.primitivesCount];
    for (uint32_t i = 0; i < mRSMesh->mHal.state.primitivesCount; i ++) {
        switch (mRSMesh->mHal.state.primitives[i]) {
            case RS_PRIMITIVE_POINT:          mGLPrimitives[i] = GL_POINTS; break;
            case RS_PRIMITIVE_LINE:           mGLPrimitives[i] = GL_LINES; break;
            case RS_PRIMITIVE_LINE_STRIP:     mGLPrimitives[i] = GL_LINE_STRIP; break;
            case RS_PRIMITIVE_TRIANGLE:       mGLPrimitives[i] = GL_TRIANGLES; break;
            case RS_PRIMITIVE_TRIANGLE_STRIP: mGLPrimitives[i] = GL_TRIANGLE_STRIP; break;
            case RS_PRIMITIVE_TRIANGLE_FAN:   mGLPrimitives[i] = GL_TRIANGLE_FAN; break;
            default: rsc->setError(RS_ERROR_FATAL_DRIVER, "Invalid mesh primitive"); break;
        }
    }
}
