summaryrefslogtreecommitdiff
path: root/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp')
-rw-r--r--tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp205
1 files changed, 180 insertions, 25 deletions
diff --git a/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
index ff48c9d6a..8504f7f78 100644
--- a/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
+++ b/tools/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp
@@ -1,3 +1,19 @@
+/*
+* 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"
/**** BufferData ****/
@@ -53,6 +69,15 @@ void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type
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)
@@ -123,13 +148,77 @@ GLint ProgramData::locationWARAppToHost(GLint appLoc)
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::List<GLuint>())
+ m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
{
}
@@ -217,13 +306,55 @@ void GLSharedGroup::deleteProgramData(GLuint program)
m_programs.removeItem(program);
}
-void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type)
+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;
+ }
+ }
+ }
}
}
@@ -277,38 +408,62 @@ bool GLSharedGroup::needUniformLocationWAR(GLuint program)
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;
+}
-void GLSharedGroup::addShaderData(GLuint shader)
+bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
{
android::AutoMutex _lock(m_lock);
- m_shaders.push_front(shader);
-
+ ProgramData* pData = m_programs.valueFor(program);
+ return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
}
-bool GLSharedGroup::isShader(GLuint shader)
+
+bool GLSharedGroup::addShaderData(GLuint shader)
{
android::AutoMutex _lock(m_lock);
- android::List<GLuint>::iterator iter;
- iter = m_shaders.begin();
- while (iter!=m_shaders.end())
- {
- if (*iter==shader)
- return true;
- iter++;
+ ShaderData* data = new ShaderData;
+ if (data) {
+ if (m_shaders.add(shader, data) < 0) {
+ delete data;
+ data = NULL;
+ }
+ data->refcount = 1;
}
- return false;
+ return data != NULL;
}
-void GLSharedGroup::deleteShaderData(GLuint shader)
+
+ShaderData* GLSharedGroup::getShaderData(GLuint shader)
{
android::AutoMutex _lock(m_lock);
- android::List<GLuint>::iterator iter;
- iter = m_shaders.begin();
- while (iter!=m_shaders.end())
- {
- if (*iter==shader)
- {
- m_shaders.erase(iter);
- return;
- }
- iter++;
+ 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);
}
}