/*
* 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 "GLSharedGroup.h"

#include "KeyedVectorUtils.h"

/**** BufferData ****/

BufferData::BufferData() : m_size(0), m_usage(0), m_mapped(false) {};

BufferData::BufferData(GLsizeiptr size, const void* data) :
    m_size(size), m_usage(0), m_mapped(false) {

    void * buffer = NULL;

    if (size>0) buffer = m_fixedBuffer.alloc(size);

    if (data) memcpy(buffer, data, size);
}

/**** ProgramData ****/
ProgramData::ProgramData() : m_numIndexes(0),
                             m_initialized(false),
                             m_locShiftWAR(false) {
    m_Indexes = NULL;
}

void ProgramData::initProgramData(GLuint numIndexes) {
    m_initialized = true;
    m_numIndexes = numIndexes;

    delete [] m_Indexes;

    m_Indexes = new IndexInfo[numIndexes];
    m_locShiftWAR = false;
}

bool ProgramData::isInitialized() {
    return m_initialized;
}

ProgramData::~ProgramData() {

    delete [] m_Indexes;

    m_Indexes = NULL;
}

void ProgramData::setIndexInfo(
    GLuint index, GLint base, GLint size, GLenum type) {

    if (index >= m_numIndexes) return;

    m_Indexes[index].base = base;
    m_Indexes[index].size = size;
    m_Indexes[index].type = type;

    if (index > 0) {
        m_Indexes[index].appBase = m_Indexes[index-1].appBase +
                                   m_Indexes[index-1].size;
    } else {
        m_Indexes[index].appBase = 0;
    }

    m_Indexes[index].hostLocsPerElement = 1;
    m_Indexes[index].flags = 0;
    m_Indexes[index].samplerValue = 0;
}

void ProgramData::setIndexFlags(GLuint index, GLuint flags) {

    if (index >= m_numIndexes) return;

    m_Indexes[index].flags |= flags;
}

GLuint ProgramData::getIndexForLocation(GLint location) {
    GLuint index = m_numIndexes;

    GLint minDist = -1;

    for (GLuint i = 0; i < m_numIndexes; ++i) {
        GLint dist = location - m_Indexes[i].base;
        if (dist >= 0 && (minDist < 0 || dist < minDist)) {
            index = i;
            minDist = dist;
        }
    }

    return index;
}

GLenum ProgramData::getTypeForLocation(GLint location) {
    GLuint index = getIndexForLocation(location);
    if (index < m_numIndexes) {
        return m_Indexes[index].type;
    }
    return 0;
}

void ProgramData::setupLocationShiftWAR() {
    m_locShiftWAR = false;
    for (GLuint  i= 0; i < m_numIndexes; i++) {
        if (0 != (m_Indexes[i].base & 0xffff)) {
            return;
        }
    }

    // if we have one uniform at location 0, we do not need the WAR.
    if (m_numIndexes > 1) m_locShiftWAR = true;
}

GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex) {

    if (!m_locShiftWAR) return hostLoc;

    GLuint index = getIndexForLocation(hostLoc);

    if (index < m_numIndexes) {
        if (arrIndex > 0) {
            m_Indexes[index].hostLocsPerElement =
                (hostLoc - m_Indexes[index].base) / arrIndex;
        }
        return m_Indexes[index].appBase + arrIndex;
    }

    return -1;
}

GLint ProgramData::locationWARAppToHost(GLint appLoc) {

    if (!m_locShiftWAR) return appLoc;

    for (GLuint i = 0; i < m_numIndexes; i++) {
        GLint elemIndex =
            appLoc - m_Indexes[i].appBase;

        if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
            return m_Indexes[i].base +
                   elemIndex * m_Indexes[i].hostLocsPerElement;
        }
    }

    return -1;
}

GLint ProgramData::getNextSamplerUniform(
    GLint index, GLint* val, GLenum* target) {

    for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {

        if (m_Indexes[i].type == GL_SAMPLER_2D) {

            if (val) *val = m_Indexes[i].samplerValue;

            if (target) {
                if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
                    *target = GL_TEXTURE_EXTERNAL_OES;
                } else {
                    *target = GL_TEXTURE_2D;
                }
            }

            return i;
        }

    }

    return -1;
}

bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target) {

    for (GLuint i = 0; i < m_numIndexes; i++) {

        GLint elemIndex = appLoc - m_Indexes[i].appBase;

        if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
            if (m_Indexes[i].type == GL_SAMPLER_2D) {
                m_Indexes[i].samplerValue = val;
                if (target) {
                    if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
                        *target = GL_TEXTURE_EXTERNAL_OES;
                    } else {
                        *target = GL_TEXTURE_2D;

                    }
                }
                return true;
            }
        }
    }

    return false;
}

bool ProgramData::attachShader(GLuint shader) {
    size_t n = m_shaders.size();

    for (size_t i = 0; i < n; i++) {
        if (m_shaders[i] == shader) {
            return false;
        }
    }
    m_shaders.push_back(shader);
    return true;
}

bool ProgramData::detachShader(GLuint shader) {
    size_t n = m_shaders.size();

    for (size_t i = 0; i < n; i++) {
        if (m_shaders[i] == shader) {
            m_shaders.erase(m_shaders.begin() + i);
            return true;
        }
    }

    return false;
}

/***** GLSharedGroup ****/

GLSharedGroup::GLSharedGroup() { }

GLSharedGroup::~GLSharedGroup() {
    m_buffers.clear();
    m_programs.clear();
    clearObjectMap(m_buffers);
    clearObjectMap(m_programs);
    clearObjectMap(m_shaders);
    clearObjectMap(m_shaderPrograms);
}

bool GLSharedGroup::isShaderOrProgramObject(GLuint obj) {

    android::AutoMutex _lock(m_lock);

    return (findObjectOrDefault(m_shaders, obj) ||
            findObjectOrDefault(m_programs, obj) ||
            findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[obj]));
}

BufferData* GLSharedGroup::getBufferData(GLuint bufferId) {

    android::AutoMutex _lock(m_lock);

    return findObjectOrDefault(m_buffers, bufferId);
}

SharedTextureDataMap* GLSharedGroup::getTextureData() {
    return &m_textureRecs;
}

void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, const void* data) {

    android::AutoMutex _lock(m_lock);

    m_buffers[bufferId] = new BufferData(size, data);
}

void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, const void* data) {

    android::AutoMutex _lock(m_lock);

    BufferData* currentBuffer = findObjectOrDefault(m_buffers, bufferId);

    if (currentBuffer) delete currentBuffer;

    m_buffers[bufferId] = new BufferData(size, data);
}

void GLSharedGroup::setBufferUsage(GLuint bufferId, GLenum usage) {

    android::AutoMutex _lock(m_lock);

    BufferData* data = findObjectOrDefault(m_buffers, bufferId);

    if (data) data->m_usage = usage;
}

void GLSharedGroup::setBufferMapped(GLuint bufferId, bool mapped) {
    BufferData* buf = findObjectOrDefault(m_buffers, bufferId);

    if (!buf) return;

    buf->m_mapped = mapped;
}

GLenum GLSharedGroup::getBufferUsage(GLuint bufferId) {
    BufferData* buf = findObjectOrDefault(m_buffers, bufferId);

    if (!buf) return 0;

    return buf->m_usage;
}

bool GLSharedGroup::isBufferMapped(GLuint bufferId) {
    BufferData* buf = findObjectOrDefault(m_buffers, bufferId);

    if (!buf) return false;

    return buf->m_mapped;
}

GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, const void* data) {

    android::AutoMutex _lock(m_lock);

    BufferData* buf = findObjectOrDefault(m_buffers, bufferId);

    if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) {
        return GL_INVALID_VALUE;
    }

    memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);

    buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
    return GL_NO_ERROR;
}

void GLSharedGroup::deleteBufferData(GLuint bufferId) {

    android::AutoMutex _lock(m_lock);

    BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
    if (buf) {
        delete buf;
        m_buffers.erase(bufferId);
    }
}

void GLSharedGroup::addProgramData(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);
    if (pData) {
        delete pData;
    }

    m_programs[program] = new ProgramData();
}

void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);
    if (pData) {
        pData->initProgramData(numIndexes);
    }
}

bool GLSharedGroup::isProgramInitialized(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) {
        return pData->isInitialized();
    }

    if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) {
        return false;
    }

    ShaderProgramData* shaderProgramData =
        findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (shaderProgramData) {
        return shaderProgramData->programData.isInitialized();
    }

    return false;
}

void GLSharedGroup::deleteProgramData(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) delete pData;

    m_programs.erase(program);

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return;

    ShaderProgramData* spData =
        findObjectOrDefault(
            m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) delete spData;

    m_shaderPrograms.erase(m_shaderProgramIdMap[program]);
    m_shaderProgramIdMap.erase(program);
}

// No such thing for separable shader programs.
void GLSharedGroup::attachShader(GLuint program, GLuint shader) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);
    ShaderData* sData = findObjectOrDefault(m_shaders, shader);

    if (pData && sData) {
        if (pData->attachShader(shader)) {
            refShaderDataLocked(shader);
        }
    }
}

void GLSharedGroup::detachShader(GLuint program, GLuint shader) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);
    ShaderData* sData = findObjectOrDefault(m_shaders, shader);
    if (pData && sData) {
        if (pData->detachShader(shader)) {
            unrefShaderDataLocked(shader);
        }
    }
}

// Not needed/used for separate shader programs.
void GLSharedGroup::setProgramIndexInfo(
    GLuint program, GLuint index, GLint base,
    GLint size, GLenum type, const char* name) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) {
        pData->setIndexInfo(index,base,size,type);
        if (type == GL_SAMPLER_2D) {
            size_t n = pData->getNumShaders();
            for (size_t i = 0; i < n; i++) {
                GLuint shaderId = pData->getShader(i);
                ShaderData* shader = findObjectOrDefault(m_shaders, shaderId);
                if (!shader) continue;
                ShaderData::StringList::iterator nameIter =
                    shader->samplerExternalNames.begin();
                ShaderData::StringList::iterator nameEnd =
                    shader->samplerExternalNames.end();
                while (nameIter != nameEnd) {
                    if (*nameIter == name) {
                        pData->setIndexFlags(
                            index,
                            ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
                        break;
                    }
                    ++nameIter;
                }
            }
        }
    }
}

GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);
    GLenum type = 0;

    if (pData) {
        type = pData->getTypeForLocation(location);
    }

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return type;

    ShaderProgramData* spData =
        findObjectOrDefault(
            m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) {
        type = spData->programData.getTypeForLocation(location);
    }

    return type;
}

bool GLSharedGroup::isProgram(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) return true;

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return false;

    ShaderProgramData* spData =
        findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) return true;

    return false;
}

void GLSharedGroup::setupLocationShiftWAR(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData =
        findObjectOrDefault(m_programs, program);

    if (pData) pData->setupLocationShiftWAR();
}

GLint GLSharedGroup::locationWARHostToApp(
    GLuint program, GLint hostLoc, GLint arrIndex) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return hostLoc;

    ShaderProgramData* spData =
        findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) return spData->programData.locationWARHostToApp(hostLoc, arrIndex);

    return hostLoc;
}

GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData =
        findObjectOrDefault(m_programs, program);

    if (pData) return pData->locationWARAppToHost(appLoc);

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return appLoc;

    ShaderProgramData* spData =
        findObjectOrDefault(
            m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) return spData->programData.locationWARAppToHost(appLoc);

    return appLoc;
}

bool GLSharedGroup::needUniformLocationWAR(GLuint program) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData =
        findObjectOrDefault(m_programs, program);

    if (pData) return pData->needUniformLocationWAR();

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return false;

    ShaderProgramData* spData =
        findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) return spData->programData.needUniformLocationWAR();

    return false;
}

GLint GLSharedGroup::getNextSamplerUniform(
    GLuint program, GLint index, GLint* val, GLenum* target) const {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) return pData->getNextSamplerUniform(index, val, target);

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return -1;

    ShaderProgramData* spData =
        findObjectOrDefault(
            m_shaderPrograms,
            findObjectOrDefault(m_shaderProgramIdMap, program));

    if (spData) return spData->programData.getNextSamplerUniform(index, val, target);

    return -1;
}

bool GLSharedGroup::setSamplerUniform(
    GLuint program, GLint appLoc, GLint val, GLenum* target) {

    android::AutoMutex _lock(m_lock);

    ProgramData* pData =
        findObjectOrDefault(m_programs, program);

    if (pData) return pData->setSamplerUniform(appLoc, val, target);

    if (m_shaderProgramIdMap.find(program) ==
        m_shaderProgramIdMap.end()) return false;

    ShaderProgramData* spData =
        findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);

    if (spData) return spData->programData.setSamplerUniform(appLoc, val, target);

    return false;
}

bool GLSharedGroup::isShader(GLuint shader) {

    android::AutoMutex _lock(m_lock);

    ShaderData* pData = findObjectOrDefault(m_shaders, shader);

    return pData != NULL;
}

bool GLSharedGroup::addShaderData(GLuint shader) {

    android::AutoMutex _lock(m_lock);

    ShaderData* data = new ShaderData;

    if (data) {
        m_shaders[shader] = data;
        data->refcount = 1;
    }

    return data != NULL;
}

ShaderData* GLSharedGroup::getShaderData(GLuint shader) {

    android::AutoMutex _lock(m_lock);

    return findObjectOrDefault(m_shaders, shader);
}

void GLSharedGroup::unrefShaderData(GLuint shader) {

    android::AutoMutex _lock(m_lock);

    unrefShaderDataLocked(shader);
}

void GLSharedGroup::refShaderDataLocked(GLuint shaderId) {
    ShaderData* data = findObjectOrDefault(m_shaders, shaderId);
    data->refcount++;
}

void GLSharedGroup::unrefShaderDataLocked(GLuint shaderId) {
    ShaderData* data = findObjectOrDefault(m_shaders, shaderId);

    if (data && --data->refcount == 0) {

        delete data;

        m_shaders.erase(shaderId);
    }
}

uint32_t GLSharedGroup::addNewShaderProgramData() {

    android::AutoMutex _lock(m_lock);

    ShaderProgramData* data = new ShaderProgramData;
    uint32_t currId = m_shaderProgramId;

    ALOGD("%s: new data %p id %u", __FUNCTION__, data, currId);

    m_shaderPrograms[currId] = data;
    m_shaderProgramId++;
    return currId;
}

void GLSharedGroup::associateGLShaderProgram(
    GLuint shaderProgramName, uint32_t shaderProgramId) {

    android::AutoMutex _lock(m_lock);

    m_shaderProgramIdMap[shaderProgramName] = shaderProgramId;
}

ShaderProgramData* GLSharedGroup::getShaderProgramDataById(uint32_t id) {

    android::AutoMutex _lock(m_lock);

    ShaderProgramData* res = findObjectOrDefault(m_shaderPrograms, id);

    ALOGD("%s: id=%u res=%p", __FUNCTION__, id, res);

    return res;
}

ShaderProgramData* GLSharedGroup::getShaderProgramData(
    GLuint shaderProgramName) {

    android::AutoMutex _lock(m_lock);

    return findObjectOrDefault(m_shaderPrograms,
                               m_shaderProgramIdMap[shaderProgramName]);
}

void GLSharedGroup::deleteShaderProgramDataById(uint32_t id) {

    android::AutoMutex _lock(m_lock);

    ShaderProgramData* data =
        findObjectOrDefault(m_shaderPrograms, id);

    delete data;

    m_shaderPrograms.erase(id);
}


void GLSharedGroup::deleteShaderProgramData(GLuint shaderProgramName) {

    android::AutoMutex _lock(m_lock);

    uint32_t id = m_shaderProgramIdMap[shaderProgramName];
    ShaderProgramData* data = findObjectOrDefault(m_shaderPrograms, id);

    delete data;

    m_shaderPrograms.erase(id);
    m_shaderProgramIdMap.erase(shaderProgramName);
}

void GLSharedGroup::initShaderProgramData(GLuint shaderProgram, GLuint numIndices) {
    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    spData->programData.initProgramData(numIndices);
}

void GLSharedGroup::setShaderProgramIndexInfo(
    GLuint shaderProgram, GLuint index, GLint base,
    GLint size, GLenum type, const char* name) {

    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    ProgramData& pData = spData->programData;
    ShaderData& sData = spData->shaderData;

    pData.setIndexInfo(index, base, size, type);

    if (type == GL_SAMPLER_2D) {

        ShaderData::StringList::iterator nameIter =
            sData.samplerExternalNames.begin();
        ShaderData::StringList::iterator nameEnd =
            sData.samplerExternalNames.end();

        while (nameIter != nameEnd) {
            if (*nameIter == name) {
                pData.setIndexFlags(
                    index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
                break;
            }
            ++nameIter;
        }
    }
}

void GLSharedGroup::setupShaderProgramLocationShiftWAR(GLuint shaderProgram) {
    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    spData->programData.setupLocationShiftWAR();
}
