/*
 * 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"

using namespace android;
using namespace android::renderscript;

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;
            String8 tmp(RS_SHADER_ATTR);
            tmp.append(elem->mHal.state.fieldNames[fieldI]);
            mAttribs[userNum].name = tmp.string();

            // 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;
        }
    }
}
