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