• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 
17 #include "GLSharedGroup.h"
18 
19 /**** BufferData ****/
20 
BufferData()21 BufferData::BufferData() : m_size(0) {};
BufferData(GLsizeiptr size,void * data)22 BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size)
23 {
24     void * buffer = NULL;
25     if (size>0) buffer = m_fixedBuffer.alloc(size);
26     if (data) memcpy(buffer, data, size);
27 }
28 
29 /**** ProgramData ****/
ProgramData()30 ProgramData::ProgramData() : m_numIndexes(0),
31                              m_initialized(false),
32                              m_locShiftWAR(false)
33 {
34     m_Indexes = NULL;
35 }
36 
initProgramData(GLuint numIndexes)37 void ProgramData::initProgramData(GLuint numIndexes)
38 {
39     m_initialized = true;
40     m_numIndexes = numIndexes;
41     delete[] m_Indexes;
42     m_Indexes = new IndexInfo[numIndexes];
43     m_locShiftWAR = false;
44 }
45 
isInitialized()46 bool ProgramData::isInitialized()
47 {
48     return m_initialized;
49 }
50 
~ProgramData()51 ProgramData::~ProgramData()
52 {
53     delete[] m_Indexes;
54     m_Indexes = NULL;
55 }
56 
setIndexInfo(GLuint index,GLint base,GLint size,GLenum type)57 void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type)
58 {
59     if (index>=m_numIndexes)
60         return;
61     m_Indexes[index].base = base;
62     m_Indexes[index].size = size;
63     m_Indexes[index].type = type;
64     if (index > 0) {
65         m_Indexes[index].appBase = m_Indexes[index-1].appBase +
66                                    m_Indexes[index-1].size;
67     }
68     else {
69         m_Indexes[index].appBase = 0;
70     }
71     m_Indexes[index].hostLocsPerElement = 1;
72     m_Indexes[index].flags = 0;
73     m_Indexes[index].samplerValue = 0;
74 }
75 
setIndexFlags(GLuint index,GLuint flags)76 void ProgramData::setIndexFlags(GLuint index, GLuint flags)
77 {
78     if (index >= m_numIndexes)
79         return;
80     m_Indexes[index].flags |= flags;
81 }
82 
getIndexForLocation(GLint location)83 GLuint ProgramData::getIndexForLocation(GLint location)
84 {
85     GLuint index = m_numIndexes;
86     GLint minDist = -1;
87     for (GLuint i=0;i<m_numIndexes;++i)
88     {
89         GLint dist = location - m_Indexes[i].base;
90         if (dist >= 0 &&
91             (minDist < 0 || dist < minDist)) {
92             index = i;
93             minDist = dist;
94         }
95     }
96     return index;
97 }
98 
getTypeForLocation(GLint location)99 GLenum ProgramData::getTypeForLocation(GLint location)
100 {
101     GLuint index = getIndexForLocation(location);
102     if (index<m_numIndexes) {
103         return m_Indexes[index].type;
104     }
105     return 0;
106 }
107 
setupLocationShiftWAR()108 void ProgramData::setupLocationShiftWAR()
109 {
110     m_locShiftWAR = false;
111     for (GLuint i=0; i<m_numIndexes; i++) {
112         if (0 != (m_Indexes[i].base & 0xffff)) {
113             return;
114         }
115     }
116     // if we have one uniform at location 0, we do not need the WAR.
117     if (m_numIndexes > 1) {
118         m_locShiftWAR = true;
119     }
120 }
121 
locationWARHostToApp(GLint hostLoc,GLint arrIndex)122 GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex)
123 {
124     if (!m_locShiftWAR) return hostLoc;
125 
126     GLuint index = getIndexForLocation(hostLoc);
127     if (index<m_numIndexes) {
128         if (arrIndex > 0) {
129             m_Indexes[index].hostLocsPerElement =
130                               (hostLoc - m_Indexes[index].base) / arrIndex;
131         }
132         return m_Indexes[index].appBase + arrIndex;
133     }
134     return -1;
135 }
136 
locationWARAppToHost(GLint appLoc)137 GLint ProgramData::locationWARAppToHost(GLint appLoc)
138 {
139     if (!m_locShiftWAR) return appLoc;
140 
141     for(GLuint i=0; i<m_numIndexes; i++) {
142         GLint elemIndex = appLoc - m_Indexes[i].appBase;
143         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
144             return m_Indexes[i].base +
145                    elemIndex * m_Indexes[i].hostLocsPerElement;
146         }
147     }
148     return -1;
149 }
150 
getNextSamplerUniform(GLint index,GLint * val,GLenum * target)151 GLint ProgramData::getNextSamplerUniform(GLint index, GLint* val, GLenum* target)
152 {
153     for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {
154         if (m_Indexes[i].type == GL_SAMPLER_2D) {
155             if (val) *val = m_Indexes[i].samplerValue;
156             if (target) {
157                 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
158                     *target = GL_TEXTURE_EXTERNAL_OES;
159                 } else {
160                     *target = GL_TEXTURE_2D;
161                 }
162             }
163             return i;
164         }
165     }
166     return -1;
167 }
168 
setSamplerUniform(GLint appLoc,GLint val,GLenum * target)169 bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target)
170 {
171     for (GLuint i = 0; i < m_numIndexes; i++) {
172         GLint elemIndex = appLoc - m_Indexes[i].appBase;
173         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
174             if (m_Indexes[i].type == GL_TEXTURE_2D) {
175                 m_Indexes[i].samplerValue = val;
176                 if (target) {
177                     if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
178                         *target = GL_TEXTURE_EXTERNAL_OES;
179                     } else {
180                         *target = GL_TEXTURE_2D;
181                     }
182                 }
183                 return true;
184             }
185         }
186     }
187     return false;
188 }
189 
attachShader(GLuint shader)190 bool ProgramData::attachShader(GLuint shader)
191 {
192     size_t n = m_shaders.size();
193     for (size_t i = 0; i < n; i++) {
194         if (m_shaders[i] == shader) {
195             return false;
196         }
197     }
198     // AKA m_shaders.push_back(), but that has an ambiguous call to insertAt()
199     // due to the default parameters. This is the desired insertAt() overload.
200     m_shaders.insertAt(shader, m_shaders.size(), 1);
201     return true;
202 }
203 
detachShader(GLuint shader)204 bool ProgramData::detachShader(GLuint shader)
205 {
206     size_t n = m_shaders.size();
207     for (size_t i = 0; i < n; i++) {
208         if (m_shaders[i] == shader) {
209             m_shaders.removeAt(i);
210             return true;
211         }
212     }
213     return false;
214 }
215 
216 /***** GLSharedGroup ****/
217 
GLSharedGroup()218 GLSharedGroup::GLSharedGroup() :
219     m_buffers(android::DefaultKeyedVector<GLuint, BufferData*>(NULL)),
220     m_programs(android::DefaultKeyedVector<GLuint, ProgramData*>(NULL)),
221     m_shaders(android::DefaultKeyedVector<GLuint, ShaderData*>(NULL))
222 {
223 }
224 
~GLSharedGroup()225 GLSharedGroup::~GLSharedGroup()
226 {
227     m_buffers.clear();
228     m_programs.clear();
229 }
230 
getBufferData(GLuint bufferId)231 BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
232 {
233     android::AutoMutex _lock(m_lock);
234     return m_buffers.valueFor(bufferId);
235 }
236 
addBufferData(GLuint bufferId,GLsizeiptr size,void * data)237 void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
238 {
239     android::AutoMutex _lock(m_lock);
240     m_buffers.add(bufferId, new BufferData(size, data));
241 }
242 
updateBufferData(GLuint bufferId,GLsizeiptr size,void * data)243 void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
244 {
245     android::AutoMutex _lock(m_lock);
246     m_buffers.replaceValueFor(bufferId, new BufferData(size, data));
247 }
248 
subUpdateBufferData(GLuint bufferId,GLintptr offset,GLsizeiptr size,void * data)249 GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
250 {
251     android::AutoMutex _lock(m_lock);
252     BufferData * buf = m_buffers.valueFor(bufferId);
253     if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
254 
255     //it's safe to update now
256     memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
257     return GL_NO_ERROR;
258 }
259 
deleteBufferData(GLuint bufferId)260 void GLSharedGroup::deleteBufferData(GLuint bufferId)
261 {
262     android::AutoMutex _lock(m_lock);
263     m_buffers.removeItem(bufferId);
264 }
265 
addProgramData(GLuint program)266 void GLSharedGroup::addProgramData(GLuint program)
267 {
268     android::AutoMutex _lock(m_lock);
269     ProgramData *pData = m_programs.valueFor(program);
270     if (pData)
271     {
272         m_programs.removeItem(program);
273         delete pData;
274     }
275 
276     m_programs.add(program,new ProgramData());
277 }
278 
initProgramData(GLuint program,GLuint numIndexes)279 void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
280 {
281     android::AutoMutex _lock(m_lock);
282     ProgramData *pData = m_programs.valueFor(program);
283     if (pData)
284     {
285         pData->initProgramData(numIndexes);
286     }
287 }
288 
isProgramInitialized(GLuint program)289 bool GLSharedGroup::isProgramInitialized(GLuint program)
290 {
291     android::AutoMutex _lock(m_lock);
292     ProgramData* pData = m_programs.valueFor(program);
293     if (pData)
294     {
295         return pData->isInitialized();
296     }
297     return false;
298 }
299 
deleteProgramData(GLuint program)300 void GLSharedGroup::deleteProgramData(GLuint program)
301 {
302     android::AutoMutex _lock(m_lock);
303     ProgramData *pData = m_programs.valueFor(program);
304     if (pData)
305         delete pData;
306     m_programs.removeItem(program);
307 }
308 
attachShader(GLuint program,GLuint shader)309 void GLSharedGroup::attachShader(GLuint program, GLuint shader)
310 {
311     android::AutoMutex _lock(m_lock);
312     ProgramData* programData = m_programs.valueFor(program);
313     ssize_t idx = m_shaders.indexOfKey(shader);
314     if (programData && idx >= 0) {
315         if (programData->attachShader(shader)) {
316             refShaderDataLocked(idx);
317         }
318     }
319 }
320 
detachShader(GLuint program,GLuint shader)321 void GLSharedGroup::detachShader(GLuint program, GLuint shader)
322 {
323     android::AutoMutex _lock(m_lock);
324     ProgramData* programData = m_programs.valueFor(program);
325     ssize_t idx = m_shaders.indexOfKey(shader);
326     if (programData && idx >= 0) {
327         if (programData->detachShader(shader)) {
328             unrefShaderDataLocked(idx);
329         }
330     }
331 }
332 
setProgramIndexInfo(GLuint program,GLuint index,GLint base,GLint size,GLenum type,const char * name)333 void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
334 {
335     android::AutoMutex _lock(m_lock);
336     ProgramData* pData = m_programs.valueFor(program);
337     if (pData)
338     {
339         pData->setIndexInfo(index,base,size,type);
340 
341         if (type == GL_SAMPLER_2D) {
342             size_t n = pData->getNumShaders();
343             for (size_t i = 0; i < n; i++) {
344                 GLuint shaderId = pData->getShader(i);
345                 ShaderData* shader = m_shaders.valueFor(shaderId);
346                 if (!shader) continue;
347                 ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
348                 ShaderData::StringList::iterator nameEnd  = shader->samplerExternalNames.end();
349                 while (nameIter != nameEnd) {
350                     if (*nameIter == name) {
351                         pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
352                         break;
353                     }
354                     ++nameIter;
355                 }
356             }
357         }
358     }
359 }
360 
getProgramUniformType(GLuint program,GLint location)361 GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
362 {
363     android::AutoMutex _lock(m_lock);
364     ProgramData* pData = m_programs.valueFor(program);
365     GLenum type=0;
366     if (pData)
367     {
368         type = pData->getTypeForLocation(location);
369     }
370     return type;
371 }
372 
isProgram(GLuint program)373 bool  GLSharedGroup::isProgram(GLuint program)
374 {
375     android::AutoMutex _lock(m_lock);
376     ProgramData* pData = m_programs.valueFor(program);
377     return (pData!=NULL);
378 }
379 
setupLocationShiftWAR(GLuint program)380 void GLSharedGroup::setupLocationShiftWAR(GLuint program)
381 {
382     android::AutoMutex _lock(m_lock);
383     ProgramData* pData = m_programs.valueFor(program);
384     if (pData) pData->setupLocationShiftWAR();
385 }
386 
locationWARHostToApp(GLuint program,GLint hostLoc,GLint arrIndex)387 GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
388 {
389     android::AutoMutex _lock(m_lock);
390     ProgramData* pData = m_programs.valueFor(program);
391     if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
392     else return hostLoc;
393 }
394 
locationWARAppToHost(GLuint program,GLint appLoc)395 GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
396 {
397     android::AutoMutex _lock(m_lock);
398     ProgramData* pData = m_programs.valueFor(program);
399     if (pData) return pData->locationWARAppToHost(appLoc);
400     else return appLoc;
401 }
402 
needUniformLocationWAR(GLuint program)403 bool GLSharedGroup::needUniformLocationWAR(GLuint program)
404 {
405     android::AutoMutex _lock(m_lock);
406     ProgramData* pData = m_programs.valueFor(program);
407     if (pData) return pData->needUniformLocationWAR();
408     return false;
409 }
410 
getNextSamplerUniform(GLuint program,GLint index,GLint * val,GLenum * target) const411 GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
412 {
413     android::AutoMutex _lock(m_lock);
414     ProgramData* pData = m_programs.valueFor(program);
415     return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
416 }
417 
setSamplerUniform(GLuint program,GLint appLoc,GLint val,GLenum * target)418 bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
419 {
420     android::AutoMutex _lock(m_lock);
421     ProgramData* pData = m_programs.valueFor(program);
422     return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
423 }
424 
addShaderData(GLuint shader)425 bool GLSharedGroup::addShaderData(GLuint shader)
426 {
427     android::AutoMutex _lock(m_lock);
428     ShaderData* data = new ShaderData;
429     if (data) {
430         if (m_shaders.add(shader, data) < 0) {
431             delete data;
432             data = NULL;
433         }
434         data->refcount = 1;
435     }
436     return data != NULL;
437 }
438 
getShaderData(GLuint shader)439 ShaderData* GLSharedGroup::getShaderData(GLuint shader)
440 {
441     android::AutoMutex _lock(m_lock);
442     return m_shaders.valueFor(shader);
443 }
444 
unrefShaderData(GLuint shader)445 void GLSharedGroup::unrefShaderData(GLuint shader)
446 {
447     android::AutoMutex _lock(m_lock);
448     ssize_t idx = m_shaders.indexOfKey(shader);
449     if (idx >= 0) {
450         unrefShaderDataLocked(idx);
451     }
452 }
453 
refShaderDataLocked(ssize_t shaderIdx)454 void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
455 {
456     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
457     ShaderData* data = m_shaders.valueAt(shaderIdx);
458     data->refcount++;
459 }
460 
unrefShaderDataLocked(ssize_t shaderIdx)461 void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
462 {
463     assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
464     ShaderData* data = m_shaders.valueAt(shaderIdx);
465     if (--data->refcount == 0) {
466         delete data;
467         m_shaders.removeItemsAt(shaderIdx);
468     }
469 }
470