2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "GLSharedGroup.h"
19 /**** KeyedVector utilities ****/
22 static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) {
23 for (size_t i = 0; i < v.size(); i++)
28 /**** BufferData ****/
30 BufferData::BufferData() : m_size(0) {};
31 BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
34 if (size>0) buffer = m_fixedBuffer.alloc(size);
35 if (data) memcpy(buffer, data, size);
38 /**** ProgramData ****/
39 ProgramData::ProgramData() : m_numIndexes(0),
46 void ProgramData::initProgramData(GLuint numIndexes)
49 m_numIndexes = numIndexes;
51 m_Indexes = new IndexInfo[numIndexes];
52 m_locShiftWAR = false;
55 bool ProgramData::isInitialized()
60 ProgramData::~ProgramData()
66 void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type)
68 if (index>=m_numIndexes)
70 m_Indexes[index].base = base;
71 m_Indexes[index].size = size;
72 m_Indexes[index].type = type;
74 m_Indexes[index].appBase = m_Indexes[index-1].appBase +
75 m_Indexes[index-1].size;
78 m_Indexes[index].appBase = 0;
80 m_Indexes[index].hostLocsPerElement = 1;
81 m_Indexes[index].flags = 0;
82 m_Indexes[index].samplerValue = 0;
85 void ProgramData::setIndexFlags(GLuint index, GLuint flags)
87 if (index >= m_numIndexes)
89 m_Indexes[index].flags |= flags;
92 GLuint ProgramData::getIndexForLocation(GLint location)
94 GLuint index = m_numIndexes;
96 for (GLuint i=0;i<m_numIndexes;++i)
98 GLint dist = location - m_Indexes[i].base;
100 (minDist < 0 || dist < minDist)) {
108 GLenum ProgramData::getTypeForLocation(GLint location)
110 GLuint index = getIndexForLocation(location);
111 if (index<m_numIndexes) {
112 return m_Indexes[index].type;
117 void ProgramData::setupLocationShiftWAR()
119 m_locShiftWAR = false;
120 for (GLuint i=0; i<m_numIndexes; i++) {
121 if (0 != (m_Indexes[i].base & 0xffff)) {
125 // if we have one uniform at location 0, we do not need the WAR.
126 if (m_numIndexes > 1) {
127 m_locShiftWAR = true;
131 GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex)
133 if (!m_locShiftWAR) return hostLoc;
135 GLuint index = getIndexForLocation(hostLoc);
136 if (index<m_numIndexes) {
138 m_Indexes[index].hostLocsPerElement =
139 (hostLoc - m_Indexes[index].base) / arrIndex;
141 return m_Indexes[index].appBase + arrIndex;
146 GLint ProgramData::locationWARAppToHost(GLint appLoc)
148 if (!m_locShiftWAR) return appLoc;
150 for(GLuint i=0; i<m_numIndexes; i++) {
151 GLint elemIndex = appLoc - m_Indexes[i].appBase;
152 if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
153 return m_Indexes[i].base +
154 elemIndex * m_Indexes[i].hostLocsPerElement;
160 GLint ProgramData::getNextSamplerUniform(GLint index, GLint* val, GLenum* target)
162 for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {
163 if (m_Indexes[i].type == GL_SAMPLER_2D) {
164 if (val) *val = m_Indexes[i].samplerValue;
166 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
167 *target = GL_TEXTURE_EXTERNAL_OES;
169 *target = GL_TEXTURE_2D;
178 bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target)
180 for (GLuint i = 0; i < m_numIndexes; i++) {
181 GLint elemIndex = appLoc - m_Indexes[i].appBase;
182 if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
183 if (m_Indexes[i].type == GL_TEXTURE_2D) {
184 m_Indexes[i].samplerValue = val;
186 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
187 *target = GL_TEXTURE_EXTERNAL_OES;
189 *target = GL_TEXTURE_2D;
199 bool ProgramData::attachShader(GLuint shader)
201 size_t n = m_shaders.size();
202 for (size_t i = 0; i < n; i++) {
203 if (m_shaders[i] == shader) {
207 // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
208 // due to the default parameters. This is the desired insertAt() overload.
209 m_shaders.insertAt(shader, m_shaders.size(), 1);
213 bool ProgramData::detachShader(GLuint shader)
215 size_t n = m_shaders.size();
216 for (size_t i = 0; i < n; i++) {
217 if (m_shaders[i] == shader) {
218 m_shaders.removeAt(i);
225 /***** GLSharedGroup ****/
227 GLSharedGroup::GLSharedGroup() :
228 m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
229 m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
230 m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
234 GLSharedGroup::~GLSharedGroup()
238 clearObjectMap(m_buffers);
239 clearObjectMap(m_programs);
240 clearObjectMap(m_shaders);
243 bool GLSharedGroup::isObject(GLuint obj)
245 android::AutoMutex _lock(m_lock);
246 return ((m_shaders.valueFor(obj)!=NULL) || (m_programs.valueFor(obj)!=NULL));
249 BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
251 android::AutoMutex _lock(m_lock);
252 return m_buffers.valueFor(bufferId);
255 SharedTextureDataMap* GLSharedGroup::getTextureData() {
256 return &m_textureRecs;
259 void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
261 android::AutoMutex _lock(m_lock);
262 m_buffers.add(bufferId, new BufferData(size, data));
265 void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
267 android::AutoMutex _lock(m_lock);
268 ssize_t idx = m_buffers.indexOfKey(bufferId);
270 delete m_buffers.valueAt(idx);
271 m_buffers.editValueAt(idx) = new BufferData(size, data);
273 m_buffers.add(bufferId, new BufferData(size, data));
277 GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
279 android::AutoMutex _lock(m_lock);
280 BufferData * buf = m_buffers.valueFor(bufferId);
281 if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
283 //it's safe to update now
284 memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
286 buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
290 void GLSharedGroup::deleteBufferData(GLuint bufferId)
292 android::AutoMutex _lock(m_lock);
293 ssize_t idx = m_buffers.indexOfKey(bufferId);
295 delete m_buffers.valueAt(idx);
296 m_buffers.removeItemsAt(idx);
300 void GLSharedGroup::addProgramData(GLuint program)
302 android::AutoMutex _lock(m_lock);
303 ProgramData *pData = m_programs.valueFor(program);
306 m_programs.removeItem(program);
310 m_programs.add(program,new ProgramData());
313 void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
315 android::AutoMutex _lock(m_lock);
316 ProgramData *pData = m_programs.valueFor(program);
319 pData->initProgramData(numIndexes);
323 bool GLSharedGroup::isProgramInitialized(GLuint program)
325 android::AutoMutex _lock(m_lock);
326 ProgramData* pData = m_programs.valueFor(program);
329 return pData->isInitialized();
334 void GLSharedGroup::deleteProgramData(GLuint program)
336 android::AutoMutex _lock(m_lock);
337 ProgramData *pData = m_programs.valueFor(program);
340 m_programs.removeItem(program);
343 void GLSharedGroup::attachShader(GLuint program, GLuint shader)
345 android::AutoMutex _lock(m_lock);
346 ProgramData* programData = m_programs.valueFor(program);
347 ssize_t idx = m_shaders.indexOfKey(shader);
348 if (programData && idx >= 0) {
349 if (programData->attachShader(shader)) {
350 refShaderDataLocked(idx);
355 void GLSharedGroup::detachShader(GLuint program, GLuint shader)
357 android::AutoMutex _lock(m_lock);
358 ProgramData* programData = m_programs.valueFor(program);
359 ssize_t idx = m_shaders.indexOfKey(shader);
360 if (programData && idx >= 0) {
361 if (programData->detachShader(shader)) {
362 unrefShaderDataLocked(idx);
367 void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
369 android::AutoMutex _lock(m_lock);
370 ProgramData* pData = m_programs.valueFor(program);
373 pData->setIndexInfo(index,base,size,type);
375 if (type == GL_SAMPLER_2D) {
376 size_t n = pData->getNumShaders();
377 for (size_t i = 0; i < n; i++) {
378 GLuint shaderId = pData->getShader(i);
379 ShaderData* shader = m_shaders.valueFor(shaderId);
380 if (!shader) continue;
381 ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
382 ShaderData::StringList::iterator nameEnd = shader->samplerExternalNames.end();
383 while (nameIter != nameEnd) {
384 if (*nameIter == name) {
385 pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
395 GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
397 android::AutoMutex _lock(m_lock);
398 ProgramData* pData = m_programs.valueFor(program);
402 type = pData->getTypeForLocation(location);
407 bool GLSharedGroup::isProgram(GLuint program)
409 android::AutoMutex _lock(m_lock);
410 ProgramData* pData = m_programs.valueFor(program);
411 return (pData!=NULL);
414 void GLSharedGroup::setupLocationShiftWAR(GLuint program)
416 android::AutoMutex _lock(m_lock);
417 ProgramData* pData = m_programs.valueFor(program);
418 if (pData) pData->setupLocationShiftWAR();
421 GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
423 android::AutoMutex _lock(m_lock);
424 ProgramData* pData = m_programs.valueFor(program);
425 if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
429 GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
431 android::AutoMutex _lock(m_lock);
432 ProgramData* pData = m_programs.valueFor(program);
433 if (pData) return pData->locationWARAppToHost(appLoc);
437 bool GLSharedGroup::needUniformLocationWAR(GLuint program)
439 android::AutoMutex _lock(m_lock);
440 ProgramData* pData = m_programs.valueFor(program);
441 if (pData) return pData->needUniformLocationWAR();
445 GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
447 android::AutoMutex _lock(m_lock);
448 ProgramData* pData = m_programs.valueFor(program);
449 return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
452 bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
454 android::AutoMutex _lock(m_lock);
455 ProgramData* pData = m_programs.valueFor(program);
456 return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
459 bool GLSharedGroup::isShader(GLuint shader)
461 android::AutoMutex _lock(m_lock);
462 ShaderData* pData = m_shaders.valueFor(shader);
463 return (pData!=NULL);
466 bool GLSharedGroup::addShaderData(GLuint shader)
468 android::AutoMutex _lock(m_lock);
469 ShaderData* data = new ShaderData;
471 if (m_shaders.add(shader, data) < 0) {
480 ShaderData* GLSharedGroup::getShaderData(GLuint shader)
482 android::AutoMutex _lock(m_lock);
483 return m_shaders.valueFor(shader);
486 void GLSharedGroup::unrefShaderData(GLuint shader)
488 android::AutoMutex _lock(m_lock);
489 ssize_t idx = m_shaders.indexOfKey(shader);
491 unrefShaderDataLocked(idx);
495 void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
497 assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
498 ShaderData* data = m_shaders.valueAt(shaderIdx);
502 void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
504 assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
505 ShaderData* data = m_shaders.valueAt(shaderIdx);
506 if (--data->refcount == 0) {
508 m_shaders.removeItemsAt(shaderIdx);