/*
* 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"
#include "glUtils.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) {

    if (size > 0) {
        m_fixedBuffer.resize(size);
    }

    if (data) {
        memcpy(m_fixedBuffer.data(), data, size);
    }
}

/**** ProgramData ****/
ProgramData::ProgramData() : m_numIndexes(0),
                             m_numAttributes(0),
                             m_initialized(false) {
    m_Indexes = NULL;
    m_attribIndexes = NULL;
    m_refcount = 1;
    m_linkStatus = 0;
    m_activeUniformBlockCount = 0;
    m_transformFeedbackVaryingsCount = 0;
}

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

    delete [] m_Indexes;
    delete [] m_attribIndexes;

    m_Indexes = new IndexInfo[numIndexes];
    m_attribIndexes = new AttribInfo[m_numAttributes];
}

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

ProgramData::~ProgramData() {

    delete [] m_Indexes;
    delete [] m_attribIndexes;

    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;
    m_Indexes[index].hostLocsPerElement = 1;
    m_Indexes[index].flags = 0;
    m_Indexes[index].samplerValue = 0;
}

void ProgramData::setAttribInfo(
    GLuint index, GLint attribLoc, GLint size, GLenum type) {

    if (index >= m_numAttributes) return;

    m_attribIndexes[index].attribLoc = attribLoc;
    m_attribIndexes[index].size = size;
    m_attribIndexes[index].type = type;
}

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

bool ProgramData::isValidUniformLocation(GLint location) {
    for (GLuint i = 0; i < m_numIndexes; ++i) {
        if (location >= m_Indexes[i].base &&
            location < m_Indexes[i].base + m_Indexes[i].size)
            return true;
    }

    return false;
}

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].base;

        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, GLenum shaderType) {
    size_t n = m_shaders.size();

    for (size_t i = 0; i < n; i++) {
        if (m_shaders[i] == shader) {
            return false;
        } else if (m_shaderTypes[i] == shaderType) {
            return false;
        }
    }
    m_shaders.push_back(shader);
    m_shaderTypes.push_back(shaderType);
    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);
            m_shaderTypes.erase(m_shaderTypes.begin() + i);
            return true;
        }
    }

    return false;
}

UniformValidationInfo ProgramData::compileValidationInfo(bool* error) const {
    UniformValidationInfo res;
    if (!m_Indexes) {
        *error = true;
        return res;
    }

    for (GLuint i = 0; i < m_numIndexes; ++i) {
        if (m_Indexes[i].base < 0) continue;

        UniformLocationInfo info = {
            .valid = true,
            .columns = getColumnsOfType(m_Indexes[i].type),
            .rows = getRowsOfType(m_Indexes[i].type),
            .isSampler = isSamplerType(m_Indexes[i].type),
            .isInt = isIntegerType(m_Indexes[i].type),
            .isArray = m_Indexes[i].size > 1,
            .isUnsigned = isUnsignedIntType(m_Indexes[i].type),
            .isBool = isBoolType(m_Indexes[i].type),
        };
        for (GLuint j = 0; j < m_Indexes[i].size; ++j) {
            res.add(m_Indexes[i].base + j, info);
        }
    }

    return res;
}

AttribValidationInfo ProgramData::compileAttribValidationInfo(bool* error) const {
    AttribValidationInfo res;
    if (!m_attribIndexes) {
        *error = true;
        return res;
    }

    for (GLuint i = 0; i < m_numAttributes; ++i) {
        if (m_attribIndexes[i].attribLoc < 0) continue;

        AttribIndexInfo info = {
            .validInProgram = true,
        };

        for (GLuint j = 0; j < getAttributeCountOfType(m_attribIndexes[i].type) * m_attribIndexes[i].size ; ++j) {
            res.add(m_attribIndexes[i].attribLoc + j, info);
        }
    }

    return res;
}
/***** 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) {

    AutoLock<Lock> _lock(m_lock);

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

BufferData* GLSharedGroup::getBufferData(GLuint bufferId) {

    AutoLock<Lock> _lock(m_lock);

    return findObjectOrDefault(m_buffers, bufferId);
}

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

RenderbufferInfo* GLSharedGroup::getRenderbufferInfo() {
    return &m_renderbufferInfo;
}

SamplerInfo* GLSharedGroup::getSamplerInfo() {
    return &m_samplerInfo;
}

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

    AutoLock<Lock> _lock(m_lock);

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

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

    AutoLock<Lock> _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) {

    AutoLock<Lock> _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) {

    AutoLock<Lock> _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(&buf->m_fixedBuffer[offset], data, size);

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

void GLSharedGroup::deleteBufferData(GLuint bufferId) {

    AutoLock<Lock> _lock(m_lock);

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

void GLSharedGroup::addProgramData(GLuint program) {

    AutoLock<Lock> _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, GLuint numAttributes) {

    AutoLock<Lock> _lock(m_lock);

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

void GLSharedGroup::refProgramData(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData = findObjectOrDefault(m_programs, program);
    if (!pData) return;
    pData->incRef();
}

void GLSharedGroup::onUseProgram(GLuint previous, GLuint next) {
    if (previous == next) return;

    AutoLock<Lock> _lock(m_lock);

    if (previous) {
        deleteProgramDataLocked(previous);
    }

    ProgramData* pData = findObjectOrDefault(m_programs, next);
    if (!pData) return;
    pData->incRef();
}

bool GLSharedGroup::isProgramInitialized(GLuint program) {

    AutoLock<Lock> _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) {
    AutoLock<Lock> _lock(m_lock);
    deleteProgramDataLocked(program);
}

void GLSharedGroup::deleteProgramDataLocked(GLuint program) {

    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData && pData->decRef()) {
        size_t numShaders = pData->getNumShaders();
        for (size_t i = 0; i < numShaders; ++i) {
            // changes the first one
            detachShaderLocked(program, pData->getShader(0));
        }
        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.
bool GLSharedGroup::attachShader(GLuint program, GLuint shader) {
    AutoLock<Lock> _lock(m_lock);

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

    bool res = false;

    if (pData && sData) {
        res = pData->attachShader(shader, sData->shaderType);
        if (res) {
            refShaderDataLocked(shader);
        }
    }

    return res;
}

bool GLSharedGroup::detachShader(GLuint program, GLuint shader) {
    AutoLock<Lock> _lock(m_lock);
    return detachShaderLocked(program, shader);
}

bool GLSharedGroup::detachShaderLocked(GLuint program, GLuint shader) {
    ProgramData* pData = findObjectOrDefault(m_programs, program);
    ShaderData* sData = findObjectOrDefault(m_shaders, shader);

    bool res = false;

    if (pData && sData) {
        res = pData->detachShader(shader);
        if (res) {
            unrefShaderDataLocked(shader);
        }
    }

    return res;
}

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

    AutoLock<Lock> _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 || *nameIter + "[0]" == name) {
                        pData->setIndexFlags(
                            index,
                            ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
                        break;
                    }
                    ++nameIter;
                }
            }
        }
    }
}

void GLSharedGroup::setProgramAttribInfo(
    GLuint program, GLuint index, GLint attribLoc,
    GLint size, GLenum type, __attribute__((unused)) const char* name) {

    AutoLock<Lock> _lock(m_lock);

    ProgramData* pData = getProgramDataLocked(program);

    if (pData) {
        pData->setAttribInfo(index,attribLoc,size,type);
    }
}

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

    AutoLock<Lock> _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) {

    AutoLock<Lock> _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;
}

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

    AutoLock<Lock> _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) {

    AutoLock<Lock> _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::isProgramUniformLocationValid(GLuint program, GLint location) {
    if (location < 0) return false;

    AutoLock<Lock> _lock(m_lock);

    ProgramData* pData =
        findObjectOrDefault(m_programs, program);

    if (!pData) return false;

    return pData->isValidUniformLocation(location);
}

bool GLSharedGroup::isShader(GLuint shader) {

    AutoLock<Lock> _lock(m_lock);

    ShaderData* pData = findObjectOrDefault(m_shaders, shader);

    return pData != NULL;
}

bool GLSharedGroup::addShaderData(GLuint shader, GLenum shaderType) {

    AutoLock<Lock> _lock(m_lock);

    ShaderData* data = new ShaderData;

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

    return data != NULL;
}

ShaderData* GLSharedGroup::getShaderData(GLuint shader) {

    AutoLock<Lock> _lock(m_lock);

    return findObjectOrDefault(m_shaders, shader);
}

void GLSharedGroup::unrefShaderData(GLuint shader) {

    AutoLock<Lock> _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);
    }
}

ProgramData* GLSharedGroup::getProgramDataLocked(GLuint program) {
    // Check the space of normal programs, then separable ones
    ProgramData* pData = findObjectOrDefault(m_programs, program);

    if (pData) return pData;

    std::map<GLuint, uint32_t>::const_iterator it =
        m_shaderProgramIdMap.find(program);
    if (it == m_shaderProgramIdMap.end()) return NULL;

    ShaderProgramData* spData = findObjectOrDefault(m_shaderPrograms, it->second);
    if (!spData) return NULL;
    return &spData->programData;
}

uint32_t GLSharedGroup::addNewShaderProgramData() {

    AutoLock<Lock> _lock(m_lock);

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

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

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

    AutoLock<Lock> _lock(m_lock);

    m_shaderProgramIdMap[shaderProgramName] = shaderProgramId;
}

ShaderProgramData* GLSharedGroup::getShaderProgramDataById(uint32_t id) {

    AutoLock<Lock> _lock(m_lock);

    ShaderProgramData* res = findObjectOrDefault(m_shaderPrograms, id);

    return res;
}

ShaderProgramData* GLSharedGroup::getShaderProgramData(
    GLuint shaderProgramName) {

    AutoLock<Lock> _lock(m_lock);

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

void GLSharedGroup::deleteShaderProgramDataById(uint32_t id) {

    AutoLock<Lock> _lock(m_lock);

    ShaderProgramData* data =
        findObjectOrDefault(m_shaderPrograms, id);

    delete data;

    m_shaderPrograms.erase(id);
}


void GLSharedGroup::deleteShaderProgramData(GLuint shaderProgramName) {

    AutoLock<Lock> _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, GLuint numAttributes) {
    ShaderProgramData* spData = getShaderProgramData(shaderProgram);
    spData->programData.initProgramData(numIndices, numAttributes);
}

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

UniformValidationInfo GLSharedGroup::getUniformValidationInfo(GLuint program) {
    UniformValidationInfo res;

    AutoLock<Lock> _lock(m_lock);

    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return res;

    bool error; (void)error;
    return pData->compileValidationInfo(&error);
}

AttribValidationInfo GLSharedGroup::getAttribValidationInfo(GLuint program) {
    AttribValidationInfo res;

    AutoLock<Lock> _lock(m_lock);

    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return res;

    bool error; (void)error;
    return pData->compileAttribValidationInfo(&error);
}

void GLSharedGroup::setProgramLinkStatus(GLuint program, GLint linkStatus) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData =
        getProgramDataLocked(program);
    if (!pData) return;
    pData->setLinkStatus(linkStatus);
}

GLint GLSharedGroup::getProgramLinkStatus(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData = getProgramDataLocked(program);
    if (!pData) return 0;
    return pData->getLinkStatus();
}

void GLSharedGroup::setActiveUniformBlockCountForProgram(GLuint program, GLint count) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return;

    pData->setActiveUniformBlockCount(count);
}

GLint GLSharedGroup::getActiveUniformBlockCount(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return 0;

    return pData->getActiveUniformBlockCount();
}

void GLSharedGroup::setTransformFeedbackVaryingsCountForProgram(GLuint program, GLint count) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData = getProgramDataLocked(program);
    if (!pData) return;
    pData->setTransformFeedbackVaryingsCount(count);
}

GLint GLSharedGroup::getTransformFeedbackVaryingsCountForProgram(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData = getProgramDataLocked(program);
    if (!pData) return 0;
    return pData->getTransformFeedbackVaryingsCount();
}

int GLSharedGroup::getActiveUniformsCountForProgram(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return 0;

    return pData->getActiveUniformsCount();
}

int GLSharedGroup::getActiveAttributesCountForProgram(GLuint program) {
    AutoLock<Lock> _lock(m_lock);
    ProgramData* pData =
        getProgramDataLocked(program);

    if (!pData) return 0;

    return pData->getActiveAttributesCount();
}

