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 #include "KeyedVectorUtils.h"
20 
21 /**** BufferData ****/
22 
BufferData()23 BufferData::BufferData() : m_size(0), m_usage(0), m_mapped(false) {};
24 
BufferData(GLsizeiptr size,const void * data)25 BufferData::BufferData(GLsizeiptr size, const void* data) :
26     m_size(size), m_usage(0), m_mapped(false) {
27 
28     if (size > 0) {
29         m_fixedBuffer.resize(size);
30     }
31 
32     if (data) {
33         memcpy(m_fixedBuffer.data(), data, size);
34     }
35 }
36 
37 /**** ProgramData ****/
ProgramData()38 ProgramData::ProgramData() : m_numIndexes(0),
39                              m_initialized(false) {
40     m_Indexes = NULL;
41 }
42 
initProgramData(GLuint numIndexes)43 void ProgramData::initProgramData(GLuint numIndexes) {
44     m_initialized = true;
45     m_numIndexes = numIndexes;
46 
47     delete [] m_Indexes;
48 
49     m_Indexes = new IndexInfo[numIndexes];
50 }
51 
isInitialized()52 bool ProgramData::isInitialized() {
53     return m_initialized;
54 }
55 
~ProgramData()56 ProgramData::~ProgramData() {
57 
58     delete [] m_Indexes;
59 
60     m_Indexes = NULL;
61 }
62 
setIndexInfo(GLuint index,GLint base,GLint size,GLenum type)63 void ProgramData::setIndexInfo(
64     GLuint index, GLint base, GLint size, GLenum type) {
65 
66     if (index >= m_numIndexes) return;
67 
68     m_Indexes[index].base = base;
69     m_Indexes[index].size = size;
70     m_Indexes[index].type = type;
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) return;
79 
80     m_Indexes[index].flags |= flags;
81 }
82 
getIndexForLocation(GLint location)83 GLuint ProgramData::getIndexForLocation(GLint location) {
84     GLuint index = m_numIndexes;
85 
86     GLint minDist = -1;
87 
88     for (GLuint i = 0; i < m_numIndexes; ++i) {
89         GLint dist = location - m_Indexes[i].base;
90         if (dist >= 0 && (minDist < 0 || dist < minDist)) {
91             index = i;
92             minDist = dist;
93         }
94     }
95 
96     return index;
97 }
98 
getTypeForLocation(GLint location)99 GLenum ProgramData::getTypeForLocation(GLint location) {
100     GLuint index = getIndexForLocation(location);
101     if (index < m_numIndexes) {
102         return m_Indexes[index].type;
103     }
104     return 0;
105 }
106 
getNextSamplerUniform(GLint index,GLint * val,GLenum * target)107 GLint ProgramData::getNextSamplerUniform(
108     GLint index, GLint* val, GLenum* target) {
109 
110     for (GLint i = index + 1; i >= 0 && i < (GLint)m_numIndexes; i++) {
111 
112         if (m_Indexes[i].type == GL_SAMPLER_2D) {
113 
114             if (val) *val = m_Indexes[i].samplerValue;
115 
116             if (target) {
117                 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
118                     *target = GL_TEXTURE_EXTERNAL_OES;
119                 } else {
120                     *target = GL_TEXTURE_2D;
121                 }
122             }
123 
124             return i;
125         }
126 
127     }
128 
129     return -1;
130 }
131 
setSamplerUniform(GLint appLoc,GLint val,GLenum * target)132 bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target) {
133 
134     for (GLuint i = 0; i < m_numIndexes; i++) {
135 
136         GLint elemIndex = appLoc - m_Indexes[i].base;
137 
138         if (elemIndex >= 0 && elemIndex < m_Indexes[i].size) {
139             if (m_Indexes[i].type == GL_SAMPLER_2D) {
140                 m_Indexes[i].samplerValue = val;
141                 if (target) {
142                     if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
143                         *target = GL_TEXTURE_EXTERNAL_OES;
144                     } else {
145                         *target = GL_TEXTURE_2D;
146 
147                     }
148                 }
149                 return true;
150             }
151         }
152     }
153 
154     return false;
155 }
156 
attachShader(GLuint shader)157 bool ProgramData::attachShader(GLuint shader) {
158     size_t n = m_shaders.size();
159 
160     for (size_t i = 0; i < n; i++) {
161         if (m_shaders[i] == shader) {
162             return false;
163         }
164     }
165     m_shaders.push_back(shader);
166     return true;
167 }
168 
detachShader(GLuint shader)169 bool ProgramData::detachShader(GLuint shader) {
170     size_t n = m_shaders.size();
171 
172     for (size_t i = 0; i < n; i++) {
173         if (m_shaders[i] == shader) {
174             m_shaders.erase(m_shaders.begin() + i);
175             return true;
176         }
177     }
178 
179     return false;
180 }
181 
182 /***** GLSharedGroup ****/
183 
GLSharedGroup()184 GLSharedGroup::GLSharedGroup() { }
185 
~GLSharedGroup()186 GLSharedGroup::~GLSharedGroup() {
187     m_buffers.clear();
188     m_programs.clear();
189     clearObjectMap(m_buffers);
190     clearObjectMap(m_programs);
191     clearObjectMap(m_shaders);
192     clearObjectMap(m_shaderPrograms);
193 }
194 
isShaderOrProgramObject(GLuint obj)195 bool GLSharedGroup::isShaderOrProgramObject(GLuint obj) {
196 
197     android::AutoMutex _lock(m_lock);
198 
199     return (findObjectOrDefault(m_shaders, obj) ||
200             findObjectOrDefault(m_programs, obj) ||
201             findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[obj]));
202 }
203 
getBufferData(GLuint bufferId)204 BufferData* GLSharedGroup::getBufferData(GLuint bufferId) {
205 
206     android::AutoMutex _lock(m_lock);
207 
208     return findObjectOrDefault(m_buffers, bufferId);
209 }
210 
getTextureData()211 SharedTextureDataMap* GLSharedGroup::getTextureData() {
212     return &m_textureRecs;
213 }
214 
addBufferData(GLuint bufferId,GLsizeiptr size,const void * data)215 void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, const void* data) {
216 
217     android::AutoMutex _lock(m_lock);
218 
219     m_buffers[bufferId] = new BufferData(size, data);
220 }
221 
updateBufferData(GLuint bufferId,GLsizeiptr size,const void * data)222 void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, const void* data) {
223 
224     android::AutoMutex _lock(m_lock);
225 
226     BufferData* currentBuffer = findObjectOrDefault(m_buffers, bufferId);
227 
228     if (currentBuffer) delete currentBuffer;
229 
230     m_buffers[bufferId] = new BufferData(size, data);
231 }
232 
setBufferUsage(GLuint bufferId,GLenum usage)233 void GLSharedGroup::setBufferUsage(GLuint bufferId, GLenum usage) {
234 
235     android::AutoMutex _lock(m_lock);
236 
237     BufferData* data = findObjectOrDefault(m_buffers, bufferId);
238 
239     if (data) data->m_usage = usage;
240 }
241 
setBufferMapped(GLuint bufferId,bool mapped)242 void GLSharedGroup::setBufferMapped(GLuint bufferId, bool mapped) {
243     BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
244 
245     if (!buf) return;
246 
247     buf->m_mapped = mapped;
248 }
249 
getBufferUsage(GLuint bufferId)250 GLenum GLSharedGroup::getBufferUsage(GLuint bufferId) {
251     BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
252 
253     if (!buf) return 0;
254 
255     return buf->m_usage;
256 }
257 
isBufferMapped(GLuint bufferId)258 bool GLSharedGroup::isBufferMapped(GLuint bufferId) {
259     BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
260 
261     if (!buf) return false;
262 
263     return buf->m_mapped;
264 }
265 
subUpdateBufferData(GLuint bufferId,GLintptr offset,GLsizeiptr size,const void * data)266 GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, const void* data) {
267 
268     android::AutoMutex _lock(m_lock);
269 
270     BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
271 
272     if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) {
273         return GL_INVALID_VALUE;
274     }
275 
276     memcpy(&buf->m_fixedBuffer[offset], data, size);
277 
278     buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
279     return GL_NO_ERROR;
280 }
281 
deleteBufferData(GLuint bufferId)282 void GLSharedGroup::deleteBufferData(GLuint bufferId) {
283 
284     android::AutoMutex _lock(m_lock);
285 
286     BufferData* buf = findObjectOrDefault(m_buffers, bufferId);
287     if (buf) {
288         delete buf;
289         m_buffers.erase(bufferId);
290     }
291 }
292 
addProgramData(GLuint program)293 void GLSharedGroup::addProgramData(GLuint program) {
294 
295     android::AutoMutex _lock(m_lock);
296 
297     ProgramData* pData = findObjectOrDefault(m_programs, program);
298     if (pData) {
299         delete pData;
300     }
301 
302     m_programs[program] = new ProgramData();
303 }
304 
initProgramData(GLuint program,GLuint numIndexes)305 void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes) {
306 
307     android::AutoMutex _lock(m_lock);
308 
309     ProgramData* pData = findObjectOrDefault(m_programs, program);
310     if (pData) {
311         pData->initProgramData(numIndexes);
312     }
313 }
314 
isProgramInitialized(GLuint program)315 bool GLSharedGroup::isProgramInitialized(GLuint program) {
316 
317     android::AutoMutex _lock(m_lock);
318 
319     ProgramData* pData = findObjectOrDefault(m_programs, program);
320 
321     if (pData) {
322         return pData->isInitialized();
323     }
324 
325     if (m_shaderProgramIdMap.find(program) == m_shaderProgramIdMap.end()) {
326         return false;
327     }
328 
329     ShaderProgramData* shaderProgramData =
330         findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);
331 
332     if (shaderProgramData) {
333         return shaderProgramData->programData.isInitialized();
334     }
335 
336     return false;
337 }
338 
deleteProgramData(GLuint program)339 void GLSharedGroup::deleteProgramData(GLuint program) {
340 
341     android::AutoMutex _lock(m_lock);
342 
343     ProgramData* pData = findObjectOrDefault(m_programs, program);
344 
345     if (pData) delete pData;
346 
347     m_programs.erase(program);
348 
349     if (m_shaderProgramIdMap.find(program) ==
350         m_shaderProgramIdMap.end()) return;
351 
352     ShaderProgramData* spData =
353         findObjectOrDefault(
354             m_shaderPrograms, m_shaderProgramIdMap[program]);
355 
356     if (spData) delete spData;
357 
358     m_shaderPrograms.erase(m_shaderProgramIdMap[program]);
359     m_shaderProgramIdMap.erase(program);
360 }
361 
362 // No such thing for separable shader programs.
attachShader(GLuint program,GLuint shader)363 void GLSharedGroup::attachShader(GLuint program, GLuint shader) {
364 
365     android::AutoMutex _lock(m_lock);
366 
367     ProgramData* pData = findObjectOrDefault(m_programs, program);
368     ShaderData* sData = findObjectOrDefault(m_shaders, shader);
369 
370     if (pData && sData) {
371         if (pData->attachShader(shader)) {
372             refShaderDataLocked(shader);
373         }
374     }
375 }
376 
detachShader(GLuint program,GLuint shader)377 void GLSharedGroup::detachShader(GLuint program, GLuint shader) {
378 
379     android::AutoMutex _lock(m_lock);
380 
381     ProgramData* pData = findObjectOrDefault(m_programs, program);
382     ShaderData* sData = findObjectOrDefault(m_shaders, shader);
383     if (pData && sData) {
384         if (pData->detachShader(shader)) {
385             unrefShaderDataLocked(shader);
386         }
387     }
388 }
389 
390 // Not needed/used for separate shader programs.
setProgramIndexInfo(GLuint program,GLuint index,GLint base,GLint size,GLenum type,const char * name)391 void GLSharedGroup::setProgramIndexInfo(
392     GLuint program, GLuint index, GLint base,
393     GLint size, GLenum type, const char* name) {
394 
395     android::AutoMutex _lock(m_lock);
396 
397     ProgramData* pData = findObjectOrDefault(m_programs, program);
398 
399     if (pData) {
400         pData->setIndexInfo(index,base,size,type);
401         if (type == GL_SAMPLER_2D) {
402             size_t n = pData->getNumShaders();
403             for (size_t i = 0; i < n; i++) {
404                 GLuint shaderId = pData->getShader(i);
405                 ShaderData* shader = findObjectOrDefault(m_shaders, shaderId);
406                 if (!shader) continue;
407                 ShaderData::StringList::iterator nameIter =
408                     shader->samplerExternalNames.begin();
409                 ShaderData::StringList::iterator nameEnd =
410                     shader->samplerExternalNames.end();
411                 while (nameIter != nameEnd) {
412                     if (*nameIter == name) {
413                         pData->setIndexFlags(
414                             index,
415                             ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
416                         break;
417                     }
418                     ++nameIter;
419                 }
420             }
421         }
422     }
423 }
424 
getProgramUniformType(GLuint program,GLint location)425 GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location) {
426 
427     android::AutoMutex _lock(m_lock);
428 
429     ProgramData* pData = findObjectOrDefault(m_programs, program);
430     GLenum type = 0;
431 
432     if (pData) {
433         type = pData->getTypeForLocation(location);
434     }
435 
436     if (m_shaderProgramIdMap.find(program) ==
437         m_shaderProgramIdMap.end()) return type;
438 
439     ShaderProgramData* spData =
440         findObjectOrDefault(
441             m_shaderPrograms, m_shaderProgramIdMap[program]);
442 
443     if (spData) {
444         type = spData->programData.getTypeForLocation(location);
445     }
446 
447     return type;
448 }
449 
isProgram(GLuint program)450 bool GLSharedGroup::isProgram(GLuint program) {
451 
452     android::AutoMutex _lock(m_lock);
453 
454     ProgramData* pData = findObjectOrDefault(m_programs, program);
455 
456     if (pData) return true;
457 
458     if (m_shaderProgramIdMap.find(program) ==
459         m_shaderProgramIdMap.end()) return false;
460 
461     ShaderProgramData* spData =
462         findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);
463 
464     if (spData) return true;
465 
466     return false;
467 }
468 
getNextSamplerUniform(GLuint program,GLint index,GLint * val,GLenum * target) const469 GLint GLSharedGroup::getNextSamplerUniform(
470     GLuint program, GLint index, GLint* val, GLenum* target) const {
471 
472     android::AutoMutex _lock(m_lock);
473 
474     ProgramData* pData = findObjectOrDefault(m_programs, program);
475 
476     if (pData) return pData->getNextSamplerUniform(index, val, target);
477 
478     if (m_shaderProgramIdMap.find(program) ==
479         m_shaderProgramIdMap.end()) return -1;
480 
481     ShaderProgramData* spData =
482         findObjectOrDefault(
483             m_shaderPrograms,
484             findObjectOrDefault(m_shaderProgramIdMap, program));
485 
486     if (spData) return spData->programData.getNextSamplerUniform(index, val, target);
487 
488     return -1;
489 }
490 
setSamplerUniform(GLuint program,GLint appLoc,GLint val,GLenum * target)491 bool GLSharedGroup::setSamplerUniform(
492     GLuint program, GLint appLoc, GLint val, GLenum* target) {
493 
494     android::AutoMutex _lock(m_lock);
495 
496     ProgramData* pData =
497         findObjectOrDefault(m_programs, program);
498 
499     if (pData) return pData->setSamplerUniform(appLoc, val, target);
500 
501     if (m_shaderProgramIdMap.find(program) ==
502         m_shaderProgramIdMap.end()) return false;
503 
504     ShaderProgramData* spData =
505         findObjectOrDefault(m_shaderPrograms, m_shaderProgramIdMap[program]);
506 
507     if (spData) return spData->programData.setSamplerUniform(appLoc, val, target);
508 
509     return false;
510 }
511 
isShader(GLuint shader)512 bool GLSharedGroup::isShader(GLuint shader) {
513 
514     android::AutoMutex _lock(m_lock);
515 
516     ShaderData* pData = findObjectOrDefault(m_shaders, shader);
517 
518     return pData != NULL;
519 }
520 
addShaderData(GLuint shader)521 bool GLSharedGroup::addShaderData(GLuint shader) {
522 
523     android::AutoMutex _lock(m_lock);
524 
525     ShaderData* data = new ShaderData;
526 
527     if (data) {
528         m_shaders[shader] = data;
529         data->refcount = 1;
530     }
531 
532     return data != NULL;
533 }
534 
getShaderData(GLuint shader)535 ShaderData* GLSharedGroup::getShaderData(GLuint shader) {
536 
537     android::AutoMutex _lock(m_lock);
538 
539     return findObjectOrDefault(m_shaders, shader);
540 }
541 
unrefShaderData(GLuint shader)542 void GLSharedGroup::unrefShaderData(GLuint shader) {
543 
544     android::AutoMutex _lock(m_lock);
545 
546     unrefShaderDataLocked(shader);
547 }
548 
refShaderDataLocked(GLuint shaderId)549 void GLSharedGroup::refShaderDataLocked(GLuint shaderId) {
550     ShaderData* data = findObjectOrDefault(m_shaders, shaderId);
551     data->refcount++;
552 }
553 
unrefShaderDataLocked(GLuint shaderId)554 void GLSharedGroup::unrefShaderDataLocked(GLuint shaderId) {
555     ShaderData* data = findObjectOrDefault(m_shaders, shaderId);
556 
557     if (data && --data->refcount == 0) {
558 
559         delete data;
560 
561         m_shaders.erase(shaderId);
562     }
563 }
564 
addNewShaderProgramData()565 uint32_t GLSharedGroup::addNewShaderProgramData() {
566 
567     android::AutoMutex _lock(m_lock);
568 
569     ShaderProgramData* data = new ShaderProgramData;
570     uint32_t currId = m_shaderProgramId;
571 
572     ALOGD("%s: new data %p id %u", __FUNCTION__, data, currId);
573 
574     m_shaderPrograms[currId] = data;
575     m_shaderProgramId++;
576     return currId;
577 }
578 
associateGLShaderProgram(GLuint shaderProgramName,uint32_t shaderProgramId)579 void GLSharedGroup::associateGLShaderProgram(
580     GLuint shaderProgramName, uint32_t shaderProgramId) {
581 
582     android::AutoMutex _lock(m_lock);
583 
584     m_shaderProgramIdMap[shaderProgramName] = shaderProgramId;
585 }
586 
getShaderProgramDataById(uint32_t id)587 ShaderProgramData* GLSharedGroup::getShaderProgramDataById(uint32_t id) {
588 
589     android::AutoMutex _lock(m_lock);
590 
591     ShaderProgramData* res = findObjectOrDefault(m_shaderPrograms, id);
592 
593     ALOGD("%s: id=%u res=%p", __FUNCTION__, id, res);
594 
595     return res;
596 }
597 
getShaderProgramData(GLuint shaderProgramName)598 ShaderProgramData* GLSharedGroup::getShaderProgramData(
599     GLuint shaderProgramName) {
600 
601     android::AutoMutex _lock(m_lock);
602 
603     return findObjectOrDefault(m_shaderPrograms,
604                                m_shaderProgramIdMap[shaderProgramName]);
605 }
606 
deleteShaderProgramDataById(uint32_t id)607 void GLSharedGroup::deleteShaderProgramDataById(uint32_t id) {
608 
609     android::AutoMutex _lock(m_lock);
610 
611     ShaderProgramData* data =
612         findObjectOrDefault(m_shaderPrograms, id);
613 
614     delete data;
615 
616     m_shaderPrograms.erase(id);
617 }
618 
619 
deleteShaderProgramData(GLuint shaderProgramName)620 void GLSharedGroup::deleteShaderProgramData(GLuint shaderProgramName) {
621 
622     android::AutoMutex _lock(m_lock);
623 
624     uint32_t id = m_shaderProgramIdMap[shaderProgramName];
625     ShaderProgramData* data = findObjectOrDefault(m_shaderPrograms, id);
626 
627     delete data;
628 
629     m_shaderPrograms.erase(id);
630     m_shaderProgramIdMap.erase(shaderProgramName);
631 }
632 
initShaderProgramData(GLuint shaderProgram,GLuint numIndices)633 void GLSharedGroup::initShaderProgramData(GLuint shaderProgram, GLuint numIndices) {
634     ShaderProgramData* spData = getShaderProgramData(shaderProgram);
635     spData->programData.initProgramData(numIndices);
636 }
637 
setShaderProgramIndexInfo(GLuint shaderProgram,GLuint index,GLint base,GLint size,GLenum type,const char * name)638 void GLSharedGroup::setShaderProgramIndexInfo(
639     GLuint shaderProgram, GLuint index, GLint base,
640     GLint size, GLenum type, const char* name) {
641 
642     ShaderProgramData* spData = getShaderProgramData(shaderProgram);
643     ProgramData& pData = spData->programData;
644     ShaderData& sData = spData->shaderData;
645 
646     pData.setIndexInfo(index, base, size, type);
647 
648     if (type == GL_SAMPLER_2D) {
649 
650         ShaderData::StringList::iterator nameIter =
651             sData.samplerExternalNames.begin();
652         ShaderData::StringList::iterator nameEnd =
653             sData.samplerExternalNames.end();
654 
655         while (nameIter != nameEnd) {
656             if (*nameIter == name) {
657                 pData.setIndexFlags(
658                     index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
659                 break;
660             }
661             ++nameIter;
662         }
663     }
664 }
665