blob: a41eb2c43a3bc4db1e31b22605a0d697999a45cd [file] [log] [blame]
keunyoungb85b2752013-03-08 12:28:03 -08001/*
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
Jesse Hall4169f3f2013-11-09 15:28:21 -080019/**** KeyedVector utilities ****/
20
21template <typename T>
22static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) {
23 for (size_t i = 0; i < v.size(); i++)
24 delete v.valueAt(i);
25 v.clear();
26}
27
keunyoungb85b2752013-03-08 12:28:03 -080028/**** BufferData ****/
29
Lingfeng Yangf654f3f2017-01-09 13:12:33 -080030BufferData::BufferData() : m_size(0), m_usage(0), m_mapped(false) {};
31BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size), m_usage(0), m_mapped(false)
keunyoungb85b2752013-03-08 12:28:03 -080032{
33 void * buffer = NULL;
34 if (size>0) buffer = m_fixedBuffer.alloc(size);
35 if (data) memcpy(buffer, data, size);
36}
37
38/**** ProgramData ****/
39ProgramData::ProgramData() : m_numIndexes(0),
40 m_initialized(false),
41 m_locShiftWAR(false)
42{
43 m_Indexes = NULL;
44}
45
46void ProgramData::initProgramData(GLuint numIndexes)
47{
48 m_initialized = true;
49 m_numIndexes = numIndexes;
50 delete[] m_Indexes;
51 m_Indexes = new IndexInfo[numIndexes];
52 m_locShiftWAR = false;
53}
54
55bool ProgramData::isInitialized()
56{
57 return m_initialized;
58}
59
60ProgramData::~ProgramData()
61{
62 delete[] m_Indexes;
63 m_Indexes = NULL;
64}
65
66void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type)
Jesse Hall4169f3f2013-11-09 15:28:21 -080067{
keunyoungb85b2752013-03-08 12:28:03 -080068 if (index>=m_numIndexes)
69 return;
70 m_Indexes[index].base = base;
71 m_Indexes[index].size = size;
72 m_Indexes[index].type = type;
73 if (index > 0) {
74 m_Indexes[index].appBase = m_Indexes[index-1].appBase +
75 m_Indexes[index-1].size;
76 }
77 else {
78 m_Indexes[index].appBase = 0;
79 }
80 m_Indexes[index].hostLocsPerElement = 1;
81 m_Indexes[index].flags = 0;
82 m_Indexes[index].samplerValue = 0;
83}
84
85void ProgramData::setIndexFlags(GLuint index, GLuint flags)
86{
87 if (index >= m_numIndexes)
88 return;
89 m_Indexes[index].flags |= flags;
90}
91
92GLuint ProgramData::getIndexForLocation(GLint location)
93{
94 GLuint index = m_numIndexes;
95 GLint minDist = -1;
96 for (GLuint i=0;i<m_numIndexes;++i)
97 {
98 GLint dist = location - m_Indexes[i].base;
Jesse Hall4169f3f2013-11-09 15:28:21 -080099 if (dist >= 0 &&
keunyoungb85b2752013-03-08 12:28:03 -0800100 (minDist < 0 || dist < minDist)) {
101 index = i;
102 minDist = dist;
103 }
104 }
105 return index;
106}
107
108GLenum ProgramData::getTypeForLocation(GLint location)
109{
110 GLuint index = getIndexForLocation(location);
111 if (index<m_numIndexes) {
112 return m_Indexes[index].type;
113 }
114 return 0;
115}
116
117void ProgramData::setupLocationShiftWAR()
118{
119 m_locShiftWAR = false;
120 for (GLuint i=0; i<m_numIndexes; i++) {
121 if (0 != (m_Indexes[i].base & 0xffff)) {
122 return;
123 }
124 }
125 // if we have one uniform at location 0, we do not need the WAR.
126 if (m_numIndexes > 1) {
127 m_locShiftWAR = true;
128 }
129}
130
131GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex)
132{
133 if (!m_locShiftWAR) return hostLoc;
134
135 GLuint index = getIndexForLocation(hostLoc);
136 if (index<m_numIndexes) {
137 if (arrIndex > 0) {
Jesse Hall4169f3f2013-11-09 15:28:21 -0800138 m_Indexes[index].hostLocsPerElement =
keunyoungb85b2752013-03-08 12:28:03 -0800139 (hostLoc - m_Indexes[index].base) / arrIndex;
140 }
141 return m_Indexes[index].appBase + arrIndex;
142 }
143 return -1;
144}
145
146GLint ProgramData::locationWARAppToHost(GLint appLoc)
147{
148 if (!m_locShiftWAR) return appLoc;
149
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;
155 }
156 }
157 return -1;
158}
159
160GLint ProgramData::getNextSamplerUniform(GLint index, GLint* val, GLenum* target)
161{
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;
165 if (target) {
166 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
167 *target = GL_TEXTURE_EXTERNAL_OES;
168 } else {
169 *target = GL_TEXTURE_2D;
170 }
171 }
172 return i;
173 }
174 }
175 return -1;
176}
177
178bool ProgramData::setSamplerUniform(GLint appLoc, GLint val, GLenum* target)
179{
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;
185 if (target) {
186 if (m_Indexes[i].flags & INDEX_FLAG_SAMPLER_EXTERNAL) {
187 *target = GL_TEXTURE_EXTERNAL_OES;
188 } else {
189 *target = GL_TEXTURE_2D;
190 }
191 }
192 return true;
193 }
194 }
195 }
196 return false;
197}
198
199bool ProgramData::attachShader(GLuint shader)
200{
201 size_t n = m_shaders.size();
202 for (size_t i = 0; i < n; i++) {
203 if (m_shaders[i] == shader) {
204 return false;
205 }
206 }
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);
210 return true;
211}
212
213bool ProgramData::detachShader(GLuint shader)
214{
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);
219 return true;
220 }
221 }
222 return false;
223}
224
225/***** GLSharedGroup ****/
226
227GLSharedGroup::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))
231{
232}
233
234GLSharedGroup::~GLSharedGroup()
235{
236 m_buffers.clear();
237 m_programs.clear();
Jesse Hall4169f3f2013-11-09 15:28:21 -0800238 clearObjectMap(m_buffers);
239 clearObjectMap(m_programs);
240 clearObjectMap(m_shaders);
keunyoungb85b2752013-03-08 12:28:03 -0800241}
242
Tina Zhang7a84f652014-12-04 12:37:30 +0800243bool GLSharedGroup::isObject(GLuint obj)
244{
245 android::AutoMutex _lock(m_lock);
246 return ((m_shaders.valueFor(obj)!=NULL) || (m_programs.valueFor(obj)!=NULL));
247}
248
keunyoungb85b2752013-03-08 12:28:03 -0800249BufferData * GLSharedGroup::getBufferData(GLuint bufferId)
250{
251 android::AutoMutex _lock(m_lock);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800252 return m_buffers.valueFor(bufferId);
keunyoungb85b2752013-03-08 12:28:03 -0800253}
254
Lingfeng Yang74e29292017-01-10 14:54:38 -0800255SharedTextureDataMap* GLSharedGroup::getTextureData() {
256 return &m_textureRecs;
257}
258
keunyoungb85b2752013-03-08 12:28:03 -0800259void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data)
260{
261 android::AutoMutex _lock(m_lock);
262 m_buffers.add(bufferId, new BufferData(size, data));
263}
264
265void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data)
266{
267 android::AutoMutex _lock(m_lock);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800268 ssize_t idx = m_buffers.indexOfKey(bufferId);
269 if (idx >= 0) {
270 delete m_buffers.valueAt(idx);
271 m_buffers.editValueAt(idx) = new BufferData(size, data);
272 } else {
273 m_buffers.add(bufferId, new BufferData(size, data));
274 }
keunyoungb85b2752013-03-08 12:28:03 -0800275}
276
Lingfeng Yangf654f3f2017-01-09 13:12:33 -0800277void GLSharedGroup::setBufferUsage(GLuint bufferId, GLenum usage) {
278 android::AutoMutex _lock(m_lock);
279 ssize_t idx = m_buffers.indexOfKey(bufferId);
280 if (idx >= 0) {
281 m_buffers.editValueAt(idx)->m_usage = usage;
282 }
283}
284
285void GLSharedGroup::setBufferMapped(GLuint bufferId, bool mapped) {
286 BufferData * buf = m_buffers.valueFor(bufferId);
287 if (!buf) return;
288 buf->m_mapped = mapped;
289}
290
291GLenum GLSharedGroup::getBufferUsage(GLuint bufferId) {
292 BufferData * buf = m_buffers.valueFor(bufferId);
293 if (!buf) return 0;
294 return buf->m_usage;
295}
296
297bool GLSharedGroup::isBufferMapped(GLuint bufferId) {
298 BufferData * buf = m_buffers.valueFor(bufferId);
299 if (!buf) return false;
300 return buf->m_mapped;
301}
302
keunyoungb85b2752013-03-08 12:28:03 -0800303GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data)
304{
305 android::AutoMutex _lock(m_lock);
306 BufferData * buf = m_buffers.valueFor(bufferId);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800307 if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE;
keunyoungb85b2752013-03-08 12:28:03 -0800308
309 //it's safe to update now
310 memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size);
Lingfeng Yang8e2b6e02016-10-14 11:20:45 -0700311
312 buf->m_indexRangeCache.invalidateRange((size_t)offset, (size_t)size);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800313 return GL_NO_ERROR;
keunyoungb85b2752013-03-08 12:28:03 -0800314}
315
316void GLSharedGroup::deleteBufferData(GLuint bufferId)
317{
318 android::AutoMutex _lock(m_lock);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800319 ssize_t idx = m_buffers.indexOfKey(bufferId);
320 if (idx >= 0) {
321 delete m_buffers.valueAt(idx);
322 m_buffers.removeItemsAt(idx);
323 }
keunyoungb85b2752013-03-08 12:28:03 -0800324}
325
326void GLSharedGroup::addProgramData(GLuint program)
327{
328 android::AutoMutex _lock(m_lock);
329 ProgramData *pData = m_programs.valueFor(program);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800330 if (pData)
331 {
keunyoungb85b2752013-03-08 12:28:03 -0800332 m_programs.removeItem(program);
333 delete pData;
334 }
335
336 m_programs.add(program,new ProgramData());
337}
338
339void GLSharedGroup::initProgramData(GLuint program, GLuint numIndexes)
340{
341 android::AutoMutex _lock(m_lock);
342 ProgramData *pData = m_programs.valueFor(program);
343 if (pData)
344 {
345 pData->initProgramData(numIndexes);
346 }
347}
348
349bool GLSharedGroup::isProgramInitialized(GLuint program)
350{
351 android::AutoMutex _lock(m_lock);
352 ProgramData* pData = m_programs.valueFor(program);
Jesse Hall4169f3f2013-11-09 15:28:21 -0800353 if (pData)
keunyoungb85b2752013-03-08 12:28:03 -0800354 {
355 return pData->isInitialized();
356 }
357 return false;
358}
359
360void GLSharedGroup::deleteProgramData(GLuint program)
361{
362 android::AutoMutex _lock(m_lock);
363 ProgramData *pData = m_programs.valueFor(program);
364 if (pData)
365 delete pData;
Jesse Hall4169f3f2013-11-09 15:28:21 -0800366 m_programs.removeItem(program);
keunyoungb85b2752013-03-08 12:28:03 -0800367}
368
369void GLSharedGroup::attachShader(GLuint program, GLuint shader)
370{
371 android::AutoMutex _lock(m_lock);
372 ProgramData* programData = m_programs.valueFor(program);
373 ssize_t idx = m_shaders.indexOfKey(shader);
374 if (programData && idx >= 0) {
375 if (programData->attachShader(shader)) {
376 refShaderDataLocked(idx);
377 }
378 }
379}
380
381void GLSharedGroup::detachShader(GLuint program, GLuint shader)
382{
383 android::AutoMutex _lock(m_lock);
384 ProgramData* programData = m_programs.valueFor(program);
385 ssize_t idx = m_shaders.indexOfKey(shader);
386 if (programData && idx >= 0) {
387 if (programData->detachShader(shader)) {
388 unrefShaderDataLocked(idx);
389 }
390 }
391}
392
393void GLSharedGroup::setProgramIndexInfo(GLuint program, GLuint index, GLint base, GLint size, GLenum type, const char* name)
394{
395 android::AutoMutex _lock(m_lock);
396 ProgramData* pData = m_programs.valueFor(program);
397 if (pData)
398 {
399 pData->setIndexInfo(index,base,size,type);
400
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 = m_shaders.valueFor(shaderId);
406 if (!shader) continue;
407 ShaderData::StringList::iterator nameIter = shader->samplerExternalNames.begin();
408 ShaderData::StringList::iterator nameEnd = shader->samplerExternalNames.end();
409 while (nameIter != nameEnd) {
410 if (*nameIter == name) {
411 pData->setIndexFlags(index, ProgramData::INDEX_FLAG_SAMPLER_EXTERNAL);
412 break;
413 }
414 ++nameIter;
415 }
416 }
417 }
418 }
419}
420
421GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location)
422{
423 android::AutoMutex _lock(m_lock);
424 ProgramData* pData = m_programs.valueFor(program);
425 GLenum type=0;
Jesse Hall4169f3f2013-11-09 15:28:21 -0800426 if (pData)
keunyoungb85b2752013-03-08 12:28:03 -0800427 {
428 type = pData->getTypeForLocation(location);
429 }
430 return type;
431}
432
433bool GLSharedGroup::isProgram(GLuint program)
434{
435 android::AutoMutex _lock(m_lock);
436 ProgramData* pData = m_programs.valueFor(program);
437 return (pData!=NULL);
438}
439
440void GLSharedGroup::setupLocationShiftWAR(GLuint program)
441{
442 android::AutoMutex _lock(m_lock);
443 ProgramData* pData = m_programs.valueFor(program);
444 if (pData) pData->setupLocationShiftWAR();
445}
446
447GLint GLSharedGroup::locationWARHostToApp(GLuint program, GLint hostLoc, GLint arrIndex)
448{
449 android::AutoMutex _lock(m_lock);
450 ProgramData* pData = m_programs.valueFor(program);
451 if (pData) return pData->locationWARHostToApp(hostLoc, arrIndex);
452 else return hostLoc;
453}
454
455GLint GLSharedGroup::locationWARAppToHost(GLuint program, GLint appLoc)
456{
457 android::AutoMutex _lock(m_lock);
458 ProgramData* pData = m_programs.valueFor(program);
459 if (pData) return pData->locationWARAppToHost(appLoc);
460 else return appLoc;
461}
462
463bool GLSharedGroup::needUniformLocationWAR(GLuint program)
464{
465 android::AutoMutex _lock(m_lock);
466 ProgramData* pData = m_programs.valueFor(program);
467 if (pData) return pData->needUniformLocationWAR();
468 return false;
469}
470
471GLint GLSharedGroup::getNextSamplerUniform(GLuint program, GLint index, GLint* val, GLenum* target) const
472{
473 android::AutoMutex _lock(m_lock);
474 ProgramData* pData = m_programs.valueFor(program);
475 return pData ? pData->getNextSamplerUniform(index, val, target) : -1;
476}
477
478bool GLSharedGroup::setSamplerUniform(GLuint program, GLint appLoc, GLint val, GLenum* target)
479{
480 android::AutoMutex _lock(m_lock);
481 ProgramData* pData = m_programs.valueFor(program);
482 return pData ? pData->setSamplerUniform(appLoc, val, target) : false;
483}
484
Yahan Zhoub99406c2016-11-22 14:03:56 -0800485bool GLSharedGroup::isShader(GLuint shader)
486{
487 android::AutoMutex _lock(m_lock);
488 ShaderData* pData = m_shaders.valueFor(shader);
489 return (pData!=NULL);
490}
491
keunyoungb85b2752013-03-08 12:28:03 -0800492bool GLSharedGroup::addShaderData(GLuint shader)
493{
494 android::AutoMutex _lock(m_lock);
495 ShaderData* data = new ShaderData;
496 if (data) {
497 if (m_shaders.add(shader, data) < 0) {
498 delete data;
499 data = NULL;
500 }
501 data->refcount = 1;
502 }
503 return data != NULL;
504}
505
506ShaderData* GLSharedGroup::getShaderData(GLuint shader)
507{
508 android::AutoMutex _lock(m_lock);
509 return m_shaders.valueFor(shader);
510}
511
512void GLSharedGroup::unrefShaderData(GLuint shader)
513{
514 android::AutoMutex _lock(m_lock);
515 ssize_t idx = m_shaders.indexOfKey(shader);
516 if (idx >= 0) {
517 unrefShaderDataLocked(idx);
518 }
519}
520
521void GLSharedGroup::refShaderDataLocked(ssize_t shaderIdx)
522{
523 assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
524 ShaderData* data = m_shaders.valueAt(shaderIdx);
525 data->refcount++;
526}
527
528void GLSharedGroup::unrefShaderDataLocked(ssize_t shaderIdx)
529{
530 assert(shaderIdx >= 0 && shaderIdx <= m_shaders.size());
531 ShaderData* data = m_shaders.valueAt(shaderIdx);
532 if (--data->refcount == 0) {
533 delete data;
534 m_shaders.removeItemsAt(shaderIdx);
535 }
536}