TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / android / opengl / shared / OpenglCodecCommon / GLSharedGroup.cpp
diff --git a/src/type3_AndroidCloud/anbox-master/android/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/src/type3_AndroidCloud/anbox-master/android/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
new file mode 100644 (file)
index 0000000..b079b6d
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+* 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"
+
+/**** KeyedVector utilities ****/
+
+template <typename T>
+static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) {
+    for (size_t i = 0; i < v.size(); i++)
+        delete v.valueAt(i);
+    v.clear();
+}
+
+/**** BufferData ****/
+
+BufferData::BufferData() : m_size(0) {};
+BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
+{
+    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_TEXTURE_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;
+        }
+    }
+    // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
+    // due to the default parameters. This is the desired insertAt() overload.
+    m_shaders.insertAt(shader, m_shaders.size(), 1);
+    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.removeAt(i);
+            return true;
+        }
+    }
+    return false;
+}
+
+/***** GLSharedGroup ****/
+
+GLSharedGroup::GLSharedGroup() :
+    m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
+    m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
+    m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
+{
+}
+
+GLSharedGroup::~GLSharedGroup()
+{
+    m_buffers.clear();
+    m_programs.clear();
+    clearObjectMap(m_buffers);
+    clearObjectMap(m_programs);
+    clearObjectMap(m_shaders);
+}
+
+bool GLSharedGroup::isObject(GLuint obj)
+{
+    android::AutoMutex _lock(m_lock);
+    return ((m_shaders.valueFor(obj)!=NULL) || (m_programs.valueFor(obj)!=NULL));
+}
+
+BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
+{
+    android::AutoMutex _lock(m_lock);
+    return m_buffers.valueFor(bufferId);
+}
+
+void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
+{
+    android::AutoMutex _lock(m_lock);
+    m_buffers.add(bufferId, new BufferData(size, data));
+}
+
+void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
+{
+    android::AutoMutex _lock(m_lock);
+    ssize_t idx = m_buffers.indexOfKey(bufferId);
+    if (idx >= 0) {
+        delete m_buffers.valueAt(idx);
+        m_buffers.editValueAt(idx) = new BufferData(size, data);
+    } else {
+        m_buffers.add(bufferId, new BufferData(size, data));
+    }
+}
+
+GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
+{
+    android::AutoMutex _lock(m_lock);
+    BufferData * buf = m_buffers.valueFor(bufferId);
+    if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
+
+    //it's safe to update now
+    memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
+    return GL_NO_ERROR;
+}
+
+void GLSharedGroup::deleteBufferData(GLuint bufferId)
+{
+    android::AutoMutex _lock(m_lock);
+    ssize_t idx = m_buffers.indexOfKey(bufferId);
+    if (idx >= 0) {
+        delete m_buffers.valueAt(idx);
+        m_buffers.removeItemsAt(idx);
+    }
+}
+
+void GLSharedGroup::addProgramData(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData *pData = m_programs.valueFor(program);
+    if (pData)
+    {
+        m_programs.removeItem(program);
+        delete pData;
+    }
+
+    m_programs.add(program,new ProgramData());
+}
+
+void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData *pData = m_programs.valueFor(program);
+    if (pData)
+    {
+        pData->initProgramData(numIndexes);
+    }
+}
+
+bool GLSharedGroup::isProgramInitialized(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    if (pData)
+    {
+        return pData->isInitialized();
+    }
+    return false;
+}
+
+void GLSharedGroup::deleteProgramData(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData *pData = m_programs.valueFor(program);
+    if (pData)
+        delete pData;
+    m_programs.removeItem(program);
+}
+
+void GLSharedGroup::attachShader(GLuint program, GLuint shader)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* programData = m_programs.valueFor(program);
+    ssize_t idx = m_shaders.indexOfKey(shader);
+    if (programData && idx >= 0) {
+        if (programData->attachShader(shader)) {
+            refShaderDataLocked(idx);
+        }
+    }
+}
+
+void GLSharedGroup::detachShader(GLuint program, GLuint shader)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* programData = m_programs.valueFor(program);
+    ssize_t idx = m_shaders.indexOfKey(shader);
+    if (programData && idx >= 0) {
+        if (programData->detachShader(shader)) {
+            unrefShaderDataLocked(idx);
+        }
+    }
+}
+
+void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(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 = m_shaders.valueFor(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 = m_programs.valueFor(program);
+    GLenum type=0;
+    if (pData)
+    {
+        type = pData->getTypeForLocation(location);
+    }
+    return type;
+}
+
+bool  GLSharedGroup::isProgram(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    return (pData!=NULL);
+}
+
+void GLSharedGroup::setupLocationShiftWAR(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    if (pData) pData->setupLocationShiftWAR();
+}
+
+GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
+    else return hostLoc;
+}
+
+GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    if (pData) return pData->locationWARAppToHost(appLoc);
+    else return appLoc;
+}
+
+bool GLSharedGroup::needUniformLocationWAR(GLuint program)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    if (pData) return pData->needUniformLocationWAR();
+    return false;
+}
+
+GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
+}
+
+bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
+{
+    android::AutoMutex _lock(m_lock);
+    ProgramData* pData = m_programs.valueFor(program);
+    return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
+}
+
+bool GLSharedGroup::addShaderData(GLuint shader)
+{
+    android::AutoMutex _lock(m_lock);
+    ShaderData* data = new ShaderData;
+    if (data) {
+        if (m_shaders.add(shader, data) < 0) {
+            delete data;
+            data = NULL;
+        }
+        data->refcount = 1;
+    }
+    return data != NULL;
+}
+
+ShaderData* GLSharedGroup::getShaderData(GLuint shader)
+{
+    android::AutoMutex _lock(m_lock);
+    return m_shaders.valueFor(shader);
+}
+
+void GLSharedGroup::unrefShaderData(GLuint shader)
+{
+    android::AutoMutex _lock(m_lock);
+    ssize_t idx = m_shaders.indexOfKey(shader);
+    if (idx >= 0) {
+        unrefShaderDataLocked(idx);
+    }
+}
+
+void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
+{
+    assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
+    ShaderData* data = m_shaders.valueAt(shaderIdx);
+    data->refcount++;
+}
+
+void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
+{
+    assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
+    ShaderData* data = m_shaders.valueAt(shaderIdx);
+    if (--data->refcount == 0) {
+        delete data;
+        m_shaders.removeItemsAt(shaderIdx);
+    }
+}