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 #include "GLClientState.h"
17 #include "GLESTextureUtils.h"
18 #include "ErrorLog.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "glUtils.h"
23
24 #if PLATFORM_SDK_VERSION < 26
25 #include <cutils/log.h>
26 #else
27 #include <log/log.h>
28 #endif
29
30 #ifndef MAX
31 #define MAX(a, b) ((a) < (b) ? (b) : (a))
32 #endif
33
34 // Don't include these in the .h file, or we get weird compile errors.
35 #include <GLES3/gl3.h>
36 #include <GLES3/gl31.h>
37
init()38 void GLClientState::init() {
39 m_initialized = false;
40 m_nLocations = CODEC_MAX_VERTEX_ATTRIBUTES;
41
42 m_arrayBuffer = 0;
43 m_arrayBuffer_lastEncode = 0;
44
45 m_attribEnableCache = 0;
46 m_vaoAttribBindingCacheInvalid = 0xffff;
47 m_vaoAttribBindingHasClientArrayCache = 0;
48 m_vaoAttribBindingHasVboCache = 0;
49 m_noClientArraysCache = 0;
50
51 m_max_vertex_attrib_bindings = m_nLocations;
52 addVertexArrayObject(0);
53 setVertexArrayObject(0);
54 // init gl constans;
55 m_currVaoState[VERTEX_LOCATION].glConst = GL_VERTEX_ARRAY;
56 m_currVaoState[NORMAL_LOCATION].glConst = GL_NORMAL_ARRAY;
57 m_currVaoState[COLOR_LOCATION].glConst = GL_COLOR_ARRAY;
58 m_currVaoState[POINTSIZE_LOCATION].glConst = GL_POINT_SIZE_ARRAY_OES;
59 m_currVaoState[TEXCOORD0_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
60 m_currVaoState[TEXCOORD1_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
61 m_currVaoState[TEXCOORD2_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
62 m_currVaoState[TEXCOORD3_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
63 m_currVaoState[TEXCOORD4_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
64 m_currVaoState[TEXCOORD5_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
65 m_currVaoState[TEXCOORD6_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
66 m_currVaoState[TEXCOORD7_LOCATION].glConst = GL_TEXTURE_COORD_ARRAY;
67 m_currVaoState[MATRIXINDEX_LOCATION].glConst = GL_MATRIX_INDEX_ARRAY_OES;
68 m_currVaoState[WEIGHT_LOCATION].glConst = GL_WEIGHT_ARRAY_OES;
69
70 m_copyReadBuffer = 0;
71 m_copyWriteBuffer = 0;
72 m_pixelPackBuffer = 0;
73 m_pixelUnpackBuffer = 0;
74 m_transformFeedbackBuffer = 0;
75 m_uniformBuffer = 0;
76 m_atomicCounterBuffer = 0;
77 m_dispatchIndirectBuffer = 0;
78 m_drawIndirectBuffer = 0;
79 m_shaderStorageBuffer = 0;
80
81 m_transformFeedbackActiveUnpaused = false;
82
83 // to be modified later when these are queried from host.
84 m_max_transform_feedback_separate_attribs = 0;
85 m_max_uniform_buffer_bindings = 0;
86 m_max_atomic_counter_buffer_bindings = 0;
87 m_max_shader_storage_buffer_bindings = 0;
88
89 m_activeTexture = 0;
90 m_currentProgram = 0;
91 m_currentShaderProgram = 0;
92
93 m_pixelStore.unpack_alignment = 4;
94 m_pixelStore.pack_alignment = 4;
95
96 m_pixelStore.unpack_row_length = 0;
97 m_pixelStore.unpack_image_height = 0;
98 m_pixelStore.unpack_skip_pixels = 0;
99 m_pixelStore.unpack_skip_rows = 0;
100 m_pixelStore.unpack_skip_images = 0;
101
102 m_pixelStore.pack_row_length = 0;
103 m_pixelStore.pack_skip_pixels = 0;
104 m_pixelStore.pack_skip_rows = 0;
105
106 memset(m_tex.unit, 0, sizeof(m_tex.unit));
107 m_tex.activeUnit = &m_tex.unit[0];
108 m_tex.textureRecs = NULL;
109
110 mRboState.boundRenderbuffer = 0;
111 mRboState.boundRenderbufferIndex = 0;
112
113 mFboState.boundDrawFramebuffer = 0;
114 mFboState.boundReadFramebuffer = 0;
115 mFboState.drawFboCheckStatus = GL_NONE;
116 mFboState.readFboCheckStatus = GL_NONE;
117
118 m_maxVertexAttribsDirty = true;
119 }
120
GLClientState()121 GLClientState::GLClientState()
122 {
123 init();
124 }
125
GLClientState(int majorVersion,int minorVersion)126 GLClientState::GLClientState(int majorVersion, int minorVersion) :
127 m_glesMajorVersion(majorVersion),
128 m_glesMinorVersion(minorVersion) {
129 init();
130 }
131
~GLClientState()132 GLClientState::~GLClientState()
133 {
134 }
135
enable(int location,int state)136 void GLClientState::enable(int location, int state)
137 {
138 m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
139 m_currVaoState[location].enabled = state;
140 if (state) {
141 m_attribEnableCache |= (1 << location);
142 m_noClientArraysCache = 0;
143 } else {
144 m_attribEnableCache &= ~(1 << location);
145 }
146 }
147
setVertexAttribState(int location,int size,GLenum type,GLboolean normalized,GLsizei stride,const void * data,bool isInt)148 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
149 {
150 m_currVaoState[location].size = size;
151 m_currVaoState[location].type = type;
152 m_currVaoState[location].stride = stride;
153 m_currVaoState[location].data = (void*)data;
154 m_currVaoState[location].bufferObject = m_arrayBuffer;
155 m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
156 switch (type) {
157 case GL_INT_2_10_10_10_REV:
158 case GL_UNSIGNED_INT_2_10_10_10_REV:
159 m_currVaoState[location].elementSize =
160 m_currVaoState[location].elementSize / 4;
161 break;
162 default:
163 break;
164 }
165 m_currVaoState[location].normalized = normalized;
166 m_currVaoState[location].isInt = isInt;
167 }
168
setVertexBindingDivisor(int bindingindex,GLuint divisor)169 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
170 m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
171 }
172
getCurrAttributeBindingInfo(int attribindex)173 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
174 return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
175 }
176
setVertexAttribBinding(int attribindex,int bindingindex)177 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
178 m_currVaoState[attribindex].bindingindex = bindingindex;
179 m_currVaoState.bufferBinding(bindingindex).vertexAttribLoc = attribindex;
180 m_vaoAttribBindingCacheInvalid |= (1 << attribindex);
181 m_noClientArraysCache = 0;
182 }
183
setVertexAttribFormat(int location,int size,GLenum type,GLboolean normalized,GLuint reloffset,bool isInt)184 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
185 m_currVaoState[location].size = size;
186 m_currVaoState[location].type = type;
187 m_currVaoState[location].normalized = normalized;
188 m_currVaoState[location].reloffset = reloffset;
189 m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
190 switch (type) {
191 case GL_INT_2_10_10_10_REV:
192 case GL_UNSIGNED_INT_2_10_10_10_REV:
193 m_currVaoState[location].elementSize =
194 m_currVaoState[location].elementSize / 4;
195 break;
196 default:
197 break;
198 }
199 m_currVaoState[location].isInt = isInt;
200 }
201
addVertexArrayObjects(GLsizei n,GLuint * arrays)202 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
203 for (GLsizei i = 0; i < n; i++) {
204 addVertexArrayObject(arrays[i]);
205 }
206 }
207
removeVertexArrayObjects(GLsizei n,const GLuint * arrays)208 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
209 for (GLsizei i = 0; i < n; i++) {
210 if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
211 setVertexArrayObject(0);
212 }
213 removeVertexArrayObject(arrays[i]);
214 }
215 }
216
addVertexArrayObject(GLuint name)217 void GLClientState::addVertexArrayObject(GLuint name) {
218 if (m_vaoMap.find(name) !=
219 m_vaoMap.end()) {
220 ALOGE("%s: ERROR: %u already part of current VAO state!",
221 __FUNCTION__, name);
222 return;
223 }
224
225 m_vaoMap.insert(
226 VAOStateMap::value_type(
227 name,
228 VAOState(0, m_nLocations, std::max(m_nLocations, m_max_vertex_attrib_bindings))));
229 VertexAttribStateVector& attribState =
230 m_vaoMap.find(name)->second.attribState;
231 for (int i = 0; i < m_nLocations; i++) {
232 attribState[i].enabled = 0;
233 attribState[i].enableDirty = false;
234 attribState[i].data = 0;
235 attribState[i].reloffset = 0;
236 attribState[i].bindingindex = i;
237 attribState[i].divisor = 0;
238 attribState[i].size = 4; // 4 is the default size
239 attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
240 }
241
242 VertexAttribBindingVector& bindingState =
243 m_vaoMap.find(name)->second.bindingState;
244 for (int i = 0; i < bindingState.size(); i++) {
245 bindingState[i].effectiveStride = 16;
246 }
247 }
248
removeVertexArrayObject(GLuint name)249 void GLClientState::removeVertexArrayObject(GLuint name) {
250 if (name == 0) {
251 ALOGE("%s: ERROR: cannot delete VAO 0!",
252 __FUNCTION__);
253 return;
254 }
255 if (m_vaoMap.find(name) ==
256 m_vaoMap.end()) {
257 ALOGE("%s: ERROR: %u not found in VAO state!",
258 __FUNCTION__, name);
259 return;
260 }
261 m_vaoMap.erase(name);
262 }
263
setVertexArrayObject(GLuint name)264 void GLClientState::setVertexArrayObject(GLuint name) {
265 if (m_vaoMap.find(name) ==
266 m_vaoMap.end()) {
267 ALOGE("%s: ERROR: %u not found in VAO state!",
268 __FUNCTION__, name);
269 return;
270 }
271
272 if (name && m_currVaoState.vaoId() == name) {
273 ALOGV("%s: set vao to self, no-op (%u)",
274 __FUNCTION__, name);
275 return;
276 }
277
278 m_currVaoState =
279 VAOStateRef(m_vaoMap.find(name));
280 }
281
isVertexArrayObject(GLuint vao) const282 bool GLClientState::isVertexArrayObject(GLuint vao) const {
283 return m_vaoMap.find(vao) != m_vaoMap.end();
284 }
285
getVBOUsage(bool * hasClientArrays,bool * hasVBOs)286 void GLClientState::getVBOUsage(bool* hasClientArrays, bool* hasVBOs) {
287 uint8_t todo_count = 0;
288 uint8_t todo[CODEC_MAX_VERTEX_ATTRIBUTES];
289
290 if (m_noClientArraysCache) {
291 *hasClientArrays = false;
292 *hasVBOs = true;
293 return;
294 }
295
296 for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; i++) {
297 if ((1 << i) & (m_attribEnableCache)) {
298 if (!((1 << i) & m_vaoAttribBindingCacheInvalid)) {
299 if ((1 << i) & m_vaoAttribBindingHasClientArrayCache) {
300 *hasClientArrays = true;
301 }
302 if ((1 << i) & m_vaoAttribBindingHasVboCache) {
303 *hasVBOs = true;
304 }
305 if (*hasClientArrays && *hasVBOs) return;
306 } else {
307 todo[todo_count] = i;
308 ++todo_count;
309 }
310 }
311 }
312
313 if (todo_count == 0 &&
314 !(*hasClientArrays) &&
315 *hasVBOs) {
316 m_noClientArraysCache = 1;
317 }
318
319 for (int k = 0; k < todo_count; ++k) {
320 int i = todo[k];
321 const GLClientState::BufferBinding& curr_binding =
322 m_currVaoState.bufferBindings_const()[
323 m_currVaoState[i].bindingindex];
324 GLuint bufferObject = curr_binding.buffer;
325 if (bufferObject == 0 && curr_binding.offset && hasClientArrays) {
326 *hasClientArrays = true;
327 m_vaoAttribBindingHasClientArrayCache |= (1 << i);
328 } else {
329 m_vaoAttribBindingHasClientArrayCache &= ~(1 << i);
330 }
331 if (bufferObject != 0 && hasVBOs) {
332 *hasVBOs = true;
333 m_vaoAttribBindingHasVboCache |= (1 << i);
334 } else {
335 m_vaoAttribBindingHasVboCache &= ~(1 << i);
336 }
337 m_vaoAttribBindingCacheInvalid &= ~(1 << i);
338 if (*hasClientArrays && *hasVBOs) return;
339 }
340
341 if (!(*hasClientArrays) &&
342 *hasVBOs) {
343 m_noClientArraysCache = 1;
344 }
345 }
346
getState(int location)347 const GLClientState::VertexAttribState& GLClientState::getState(int location) {
348 return m_currVaoState[location];
349 }
350
getStateAndEnableDirty(int location,bool * enableChanged)351 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
352 {
353 if (enableChanged) {
354 *enableChanged = m_currVaoState[location].enableDirty;
355 }
356
357 m_currVaoState[location].enableDirty = false;
358 return m_currVaoState[location];
359 }
360
updateEnableDirtyArrayForDraw()361 void GLClientState::updateEnableDirtyArrayForDraw() {
362 bool enableChanged;
363 VAOState& vaoState = m_currVaoState.vaoState();
364
365 int k = 0;
366 for (int i = 0; i < CODEC_MAX_VERTEX_ATTRIBUTES; ++i) {
367 const VertexAttribState &state = getStateAndEnableDirty(i, &enableChanged);
368 if (enableChanged || state.enabled) {
369 vaoState.attributesNeedingUpdateForDraw[k] = i;
370 ++k;
371 }
372 }
373 vaoState.numAttributesNeedingUpdateForDraw = k;
374 }
375
currentVaoState()376 GLClientState::VAOState& GLClientState::currentVaoState() {
377 return m_currVaoState.vaoState();
378 }
379
getLocation(GLenum loc)380 int GLClientState::getLocation(GLenum loc)
381 {
382 int retval;
383
384 switch(loc) {
385 case GL_VERTEX_ARRAY:
386 retval = int(VERTEX_LOCATION);
387 break;
388 case GL_NORMAL_ARRAY:
389 retval = int(NORMAL_LOCATION);
390 break;
391 case GL_COLOR_ARRAY:
392 retval = int(COLOR_LOCATION);
393 break;
394 case GL_POINT_SIZE_ARRAY_OES:
395 retval = int(POINTSIZE_LOCATION);
396 break;
397 case GL_TEXTURE_COORD_ARRAY:
398 retval = int (TEXCOORD0_LOCATION + m_activeTexture);
399 break;
400 case GL_MATRIX_INDEX_ARRAY_OES:
401 retval = int (MATRIXINDEX_LOCATION);
402 break;
403 case GL_WEIGHT_ARRAY_OES:
404 retval = int (WEIGHT_LOCATION);
405 break;
406 default:
407 retval = loc;
408 }
409 return retval;
410 }
411
sClearIndexedBufferBinding(GLuint id,std::vector<GLClientState::BufferBinding> & bindings)412 static void sClearIndexedBufferBinding(GLuint id, std::vector<GLClientState::BufferBinding>& bindings) {
413 for (size_t i = 0; i < bindings.size(); i++) {
414 if (bindings[i].buffer == id) {
415 bindings[i].offset = 0;
416 bindings[i].stride = 0;
417 bindings[i].effectiveStride = 16;
418 bindings[i].size = 0;
419 bindings[i].buffer = 0;
420 }
421 }
422 }
423
addBuffer(GLuint id)424 void GLClientState::addBuffer(GLuint id) {
425 mBufferIds.insert(id);
426 }
427
removeBuffer(GLuint id)428 void GLClientState::removeBuffer(GLuint id) {
429 mBufferIds.erase(id);
430 }
431
bufferIdExists(GLuint id) const432 bool GLClientState::bufferIdExists(GLuint id) const {
433 return mBufferIds.find(id) != mBufferIds.end();
434 }
435
unBindBuffer(GLuint id)436 void GLClientState::unBindBuffer(GLuint id) {
437 if (m_arrayBuffer == id) {
438 m_arrayBuffer = 0;
439 m_arrayBuffer_lastEncode = 0;
440 }
441
442 if (m_currVaoState.iboId() == id) {
443 m_currVaoState.iboId() = 0;
444 m_currVaoState.iboIdLastEncode() = 0;
445 }
446
447 if (m_copyReadBuffer == id)
448 m_copyReadBuffer = 0;
449 if (m_copyWriteBuffer == id)
450 m_copyWriteBuffer = 0;
451 if (m_pixelPackBuffer == id)
452 m_pixelPackBuffer = 0;
453 if (m_pixelUnpackBuffer == id)
454 m_pixelUnpackBuffer = 0;
455 if (m_transformFeedbackBuffer == id)
456 m_transformFeedbackBuffer = 0;
457 if (m_uniformBuffer == id)
458 m_uniformBuffer = 0;
459 if (m_atomicCounterBuffer == id)
460 m_atomicCounterBuffer = 0;
461 if (m_dispatchIndirectBuffer == id)
462 m_dispatchIndirectBuffer = 0;
463 if (m_drawIndirectBuffer == id)
464 m_drawIndirectBuffer = 0;
465 if (m_shaderStorageBuffer == id)
466 m_shaderStorageBuffer = 0;
467
468 sClearIndexedBufferBinding(id, m_indexedTransformFeedbackBuffers);
469 sClearIndexedBufferBinding(id, m_indexedUniformBuffers);
470 sClearIndexedBufferBinding(id, m_indexedAtomicCounterBuffers);
471 sClearIndexedBufferBinding(id, m_indexedShaderStorageBuffers);
472 sClearIndexedBufferBinding(id, m_currVaoState.bufferBindings());
473 m_vaoAttribBindingCacheInvalid = 0xffff;
474 m_noClientArraysCache = 0;
475 }
476
bindBuffer(GLenum target,GLuint id)477 int GLClientState::bindBuffer(GLenum target, GLuint id)
478 {
479 int err = 0;
480 switch(target) {
481 case GL_ARRAY_BUFFER:
482 m_arrayBuffer = id;
483 break;
484 case GL_ELEMENT_ARRAY_BUFFER:
485 m_currVaoState.iboId() = id;
486 break;
487 case GL_COPY_READ_BUFFER:
488 m_copyReadBuffer = id;
489 break;
490 case GL_COPY_WRITE_BUFFER:
491 m_copyWriteBuffer = id;
492 break;
493 case GL_PIXEL_PACK_BUFFER:
494 m_pixelPackBuffer = id;
495 break;
496 case GL_PIXEL_UNPACK_BUFFER:
497 m_pixelUnpackBuffer = id;
498 break;
499 case GL_TRANSFORM_FEEDBACK_BUFFER:
500 m_transformFeedbackBuffer = id;
501 break;
502 case GL_UNIFORM_BUFFER:
503 m_uniformBuffer = id;
504 break;
505 case GL_ATOMIC_COUNTER_BUFFER:
506 m_atomicCounterBuffer = id;
507 break;
508 case GL_DISPATCH_INDIRECT_BUFFER:
509 m_dispatchIndirectBuffer = id;
510 break;
511 case GL_DRAW_INDIRECT_BUFFER:
512 m_drawIndirectBuffer = id;
513 break;
514 case GL_SHADER_STORAGE_BUFFER:
515 m_shaderStorageBuffer = id;
516 break;
517 default:
518 err = -1;
519 }
520 return err;
521 }
522
bindIndexedBuffer(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)523 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
524 switch (target) {
525 case GL_TRANSFORM_FEEDBACK_BUFFER:
526 m_indexedTransformFeedbackBuffers[index].buffer = buffer;
527 m_indexedTransformFeedbackBuffers[index].offset = offset;
528 m_indexedTransformFeedbackBuffers[index].size = size;
529 m_indexedTransformFeedbackBuffers[index].stride = stride;
530 break;
531 case GL_UNIFORM_BUFFER:
532 m_indexedUniformBuffers[index].buffer = buffer;
533 m_indexedUniformBuffers[index].offset = offset;
534 m_indexedUniformBuffers[index].size = size;
535 m_indexedUniformBuffers[index].stride = stride;
536 break;
537 case GL_ATOMIC_COUNTER_BUFFER:
538 m_indexedAtomicCounterBuffers[index].buffer = buffer;
539 m_indexedAtomicCounterBuffers[index].offset = offset;
540 m_indexedAtomicCounterBuffers[index].size = size;
541 m_indexedAtomicCounterBuffers[index].stride = stride;
542 break;
543 case GL_SHADER_STORAGE_BUFFER:
544 m_indexedShaderStorageBuffers[index].buffer = buffer;
545 m_indexedShaderStorageBuffers[index].offset = offset;
546 m_indexedShaderStorageBuffers[index].size = size;
547 m_indexedShaderStorageBuffers[index].stride = stride;
548 break;
549 default:
550 m_currVaoState.bufferBinding(index).buffer = buffer;
551 m_currVaoState.bufferBinding(index).offset = offset;
552 m_currVaoState.bufferBinding(index).size = size;
553 m_currVaoState.bufferBinding(index).stride = stride;
554 m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
555 m_vaoAttribBindingCacheInvalid |= (1 << m_currVaoState.bufferBinding(index).vertexAttribLoc);
556 return;
557 }
558 }
559
getMaxIndexedBufferBindings(GLenum target) const560 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
561 switch (target) {
562 case GL_TRANSFORM_FEEDBACK_BUFFER:
563 return m_indexedTransformFeedbackBuffers.size();
564 case GL_UNIFORM_BUFFER:
565 return m_indexedUniformBuffers.size();
566 case GL_ATOMIC_COUNTER_BUFFER:
567 return m_indexedAtomicCounterBuffers.size();
568 case GL_SHADER_STORAGE_BUFFER:
569 return m_indexedShaderStorageBuffers.size();
570 default:
571 return m_currVaoState.bufferBindings_const().size();
572 }
573 }
574
isNonIndexedBindNoOp(GLenum target,GLuint buffer)575 bool GLClientState::isNonIndexedBindNoOp(GLenum target, GLuint buffer) {
576 if (buffer != !getLastEncodedBufferBind(target)) return false;
577
578 int idOrError = getBuffer(target);
579 if (idOrError < 0) {
580 return false;
581 } else {
582 return buffer == (GLuint)idOrError;
583 }
584 }
585
isIndexedBindNoOp(GLenum target,GLuint index,GLuint buffer,GLintptr offset,GLsizeiptr size,GLintptr stride,GLintptr effectiveStride)586 bool GLClientState::isIndexedBindNoOp(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
587
588 if (target == GL_TRANSFORM_FEEDBACK_BUFFER) return false;
589
590 if (buffer != getLastEncodedBufferBind(target)) return false;
591
592 switch (target) {
593 case GL_TRANSFORM_FEEDBACK_BUFFER:
594 return m_indexedTransformFeedbackBuffers[index].buffer == buffer &&
595 m_indexedTransformFeedbackBuffers[index].offset == offset &&
596 m_indexedTransformFeedbackBuffers[index].size == size &&
597 m_indexedTransformFeedbackBuffers[index].stride == stride;
598 case GL_UNIFORM_BUFFER:
599 return m_indexedUniformBuffers[index].buffer == buffer &&
600 m_indexedUniformBuffers[index].offset == offset &&
601 m_indexedUniformBuffers[index].size == size &&
602 m_indexedUniformBuffers[index].stride == stride;
603 case GL_ATOMIC_COUNTER_BUFFER:
604 return m_indexedAtomicCounterBuffers[index].buffer == buffer &&
605 m_indexedAtomicCounterBuffers[index].offset == offset &&
606 m_indexedAtomicCounterBuffers[index].size == size &&
607 m_indexedAtomicCounterBuffers[index].stride == stride;
608 case GL_SHADER_STORAGE_BUFFER:
609 return m_indexedShaderStorageBuffers[index].buffer == buffer &&
610 m_indexedShaderStorageBuffers[index].offset == offset &&
611 m_indexedShaderStorageBuffers[index].size == size &&
612 m_indexedShaderStorageBuffers[index].stride == stride;
613 default:
614 return m_currVaoState.bufferBinding(index).buffer == buffer &&
615 m_currVaoState.bufferBinding(index).offset == offset &&
616 m_currVaoState.bufferBinding(index).size == size &&
617 m_currVaoState.bufferBinding(index).stride == stride &&
618 m_currVaoState.bufferBinding(index).effectiveStride == effectiveStride;
619 }
620 }
621
getBuffer(GLenum target)622 int GLClientState::getBuffer(GLenum target) {
623 int ret=0;
624 switch (target) {
625 case GL_ARRAY_BUFFER:
626 ret = m_arrayBuffer;
627 break;
628 case GL_ELEMENT_ARRAY_BUFFER:
629 ret = m_currVaoState.iboId();
630 break;
631 case GL_COPY_READ_BUFFER:
632 ret = m_copyReadBuffer;
633 break;
634 case GL_COPY_WRITE_BUFFER:
635 ret = m_copyWriteBuffer;
636 break;
637 case GL_PIXEL_PACK_BUFFER:
638 ret = m_pixelPackBuffer;
639 break;
640 case GL_PIXEL_UNPACK_BUFFER:
641 ret = m_pixelUnpackBuffer;
642 break;
643 case GL_TRANSFORM_FEEDBACK_BUFFER:
644 ret = m_transformFeedbackBuffer;
645 break;
646 case GL_UNIFORM_BUFFER:
647 ret = m_uniformBuffer;
648 break;
649 case GL_ATOMIC_COUNTER_BUFFER:
650 ret = m_atomicCounterBuffer;
651 break;
652 case GL_DISPATCH_INDIRECT_BUFFER:
653 ret = m_dispatchIndirectBuffer;
654 break;
655 case GL_DRAW_INDIRECT_BUFFER:
656 ret = m_drawIndirectBuffer;
657 break;
658 case GL_SHADER_STORAGE_BUFFER:
659 ret = m_shaderStorageBuffer;
660 break;
661 default:
662 ret = -1;
663 }
664 return ret;
665 }
666
getLastEncodedBufferBind(GLenum target)667 GLuint GLClientState::getLastEncodedBufferBind(GLenum target) {
668 GLuint ret;
669 switch (target)
670 {
671 case GL_ARRAY_BUFFER:
672 ret = m_arrayBuffer_lastEncode;
673 break;
674 case GL_ELEMENT_ARRAY_BUFFER:
675 ret = m_currVaoState.iboIdLastEncode();
676 break;
677 default:
678 {
679 int idOrError = getBuffer(target);
680 ret = (idOrError < 0) ? 0 : (GLuint)idOrError;
681 }
682 }
683
684 return ret;
685 }
686
setLastEncodedBufferBind(GLenum target,GLuint id)687 void GLClientState::setLastEncodedBufferBind(GLenum target, GLuint id)
688 {
689 switch (target)
690 {
691 case GL_ARRAY_BUFFER:
692 m_arrayBuffer_lastEncode = id;
693 break;
694 case GL_ELEMENT_ARRAY_BUFFER:
695 m_currVaoState.iboIdLastEncode() = id;
696 break;
697 default:
698 break;
699 }
700 }
701
getClientStatePointer(GLenum pname,GLvoid ** params)702 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
703 {
704 GLenum which_state = -1;
705 switch (pname) {
706 case GL_VERTEX_ARRAY_POINTER: {
707 which_state = GLClientState::VERTEX_LOCATION;
708 break;
709 }
710 case GL_NORMAL_ARRAY_POINTER: {
711 which_state = GLClientState::NORMAL_LOCATION;
712 break;
713 }
714 case GL_COLOR_ARRAY_POINTER: {
715 which_state = GLClientState::COLOR_LOCATION;
716 break;
717 }
718 case GL_TEXTURE_COORD_ARRAY_POINTER: {
719 which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
720 break;
721 }
722 case GL_POINT_SIZE_ARRAY_POINTER_OES: {
723 which_state = GLClientState::POINTSIZE_LOCATION;
724 break;
725 }
726 case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
727 which_state = GLClientState::MATRIXINDEX_LOCATION;
728 break;
729 }
730 case GL_WEIGHT_ARRAY_POINTER_OES: {
731 which_state = GLClientState::WEIGHT_LOCATION;
732 break;
733 }
734 }
735 if (which_state != -1)
736 *params = m_currVaoState[which_state].data;
737 }
738
setPixelStore(GLenum param,GLint value)739 int GLClientState::setPixelStore(GLenum param, GLint value)
740 {
741 int retval = 0;
742 switch(param) {
743 case GL_UNPACK_ALIGNMENT:
744 m_pixelStore.unpack_alignment = value;
745 break;
746 case GL_PACK_ALIGNMENT:
747 m_pixelStore.pack_alignment = value;
748 break;
749 case GL_UNPACK_ROW_LENGTH:
750 m_pixelStore.unpack_row_length = value;
751 break;
752 case GL_UNPACK_IMAGE_HEIGHT:
753 m_pixelStore.unpack_image_height = value;
754 break;
755 case GL_UNPACK_SKIP_PIXELS:
756 m_pixelStore.unpack_skip_pixels = value;
757 break;
758 case GL_UNPACK_SKIP_ROWS:
759 m_pixelStore.unpack_skip_rows = value;
760 break;
761 case GL_UNPACK_SKIP_IMAGES:
762 m_pixelStore.unpack_skip_images = value;
763 break;
764 case GL_PACK_ROW_LENGTH:
765 m_pixelStore.pack_row_length = value;
766 break;
767 case GL_PACK_SKIP_PIXELS:
768 m_pixelStore.pack_skip_pixels = value;
769 break;
770 case GL_PACK_SKIP_ROWS:
771 m_pixelStore.pack_skip_rows = value;
772 break;
773 default:
774 retval = GL_INVALID_ENUM;
775 }
776 return retval;
777 }
778
779
pixelDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const780 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
781 {
782 if (width <= 0 || height <= 0 || depth <= 0) return 0;
783
784 ALOGV("%s: pack? %d", __FUNCTION__, pack);
785 if (pack) {
786 ALOGV("%s: pack stats", __FUNCTION__);
787 ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
788 ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
789 ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
790 ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
791 } else {
792 ALOGV("%s: unpack stats", __FUNCTION__);
793 ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
794 ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
795 ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
796 ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
797 ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
798 ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
799 }
800 return GLESTextureUtils::computeTotalImageSize(
801 width, height, depth,
802 format, type,
803 pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
804 pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
805 pack ? 0 : m_pixelStore.unpack_image_height,
806 pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
807 pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
808 pack ? 0 : m_pixelStore.unpack_skip_images);
809 }
810
pboNeededDataSize(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int pack) const811 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
812 {
813 if (width <= 0 || height <= 0 || depth <= 0) return 0;
814
815 ALOGV("%s: pack? %d", __FUNCTION__, pack);
816 if (pack) {
817 ALOGV("%s: pack stats", __FUNCTION__);
818 ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
819 ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
820 ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
821 ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
822 } else {
823 ALOGV("%s: unpack stats", __FUNCTION__);
824 ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
825 ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
826 ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
827 ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
828 ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
829 ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
830 }
831 return GLESTextureUtils::computeNeededBufferSize(
832 width, height, depth,
833 format, type,
834 pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
835 pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
836 pack ? 0 : m_pixelStore.unpack_image_height,
837 pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
838 pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
839 pack ? 0 : m_pixelStore.unpack_skip_images);
840 }
841
842
clearBufferNumElts(GLenum buffer) const843 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
844 {
845 switch (buffer) {
846 case GL_COLOR:
847 return 4;
848 case GL_DEPTH:
849 case GL_STENCIL:
850 return 1;
851 }
852 return 1;
853 }
854
getPackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const855 void GLClientState::getPackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
856 {
857 if (width <= 0 || height <= 0) {
858 *startOffset = 0;
859 *pixelRowSize = 0;
860 *totalRowSize = 0;
861 return;
862 }
863
864 GLESTextureUtils::computePackingOffsets2D(
865 width, height,
866 format, type,
867 m_pixelStore.pack_alignment,
868 m_pixelStore.pack_row_length,
869 m_pixelStore.pack_skip_pixels,
870 m_pixelStore.pack_skip_rows,
871 bpp,
872 startOffset,
873 pixelRowSize,
874 totalRowSize);
875
876 *skipRows = m_pixelStore.pack_skip_rows;
877 }
878
getUnpackingOffsets2D(GLsizei width,GLsizei height,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * skipRows) const879 void GLClientState::getUnpackingOffsets2D(GLsizei width, GLsizei height, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* skipRows) const
880 {
881 if (width <= 0 || height <= 0) {
882 *startOffset = 0;
883 *pixelRowSize = 0;
884 *totalRowSize = 0;
885 return;
886 }
887
888 GLESTextureUtils::computePackingOffsets2D(
889 width, height,
890 format, type,
891 m_pixelStore.unpack_alignment,
892 m_pixelStore.unpack_row_length,
893 m_pixelStore.unpack_skip_pixels,
894 m_pixelStore.unpack_skip_rows,
895 bpp,
896 startOffset,
897 pixelRowSize,
898 totalRowSize);
899
900 *skipRows = m_pixelStore.unpack_skip_rows;
901 }
902
getUnpackingOffsets3D(GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,int * bpp,int * startOffset,int * pixelRowSize,int * totalRowSize,int * pixelImageSize,int * totalImageSize,int * skipRows,int * skipImages) const903 void GLClientState::getUnpackingOffsets3D(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int* bpp, int* startOffset, int* pixelRowSize, int* totalRowSize, int* pixelImageSize, int* totalImageSize, int* skipRows, int* skipImages) const
904 {
905 if (width <= 0 || height <= 0) {
906 *startOffset = 0;
907 *pixelRowSize = 0;
908 *totalRowSize = 0;
909 return;
910 }
911
912 GLESTextureUtils::computePackingOffsets3D(
913 width, height, depth,
914 format, type,
915 m_pixelStore.unpack_alignment,
916 m_pixelStore.unpack_row_length,
917 m_pixelStore.unpack_image_height,
918 m_pixelStore.unpack_skip_pixels,
919 m_pixelStore.unpack_skip_rows,
920 m_pixelStore.unpack_skip_images,
921 bpp,
922 startOffset,
923 pixelRowSize,
924 totalRowSize,
925 pixelImageSize,
926 totalImageSize);
927
928 *skipRows = m_pixelStore.unpack_skip_rows;
929 *skipImages = m_pixelStore.unpack_skip_images;
930 }
931
setNumActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex,GLint numActiveUniforms)932 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
933 UniformBlockInfoKey key;
934 key.program = program;
935 key.uniformBlockIndex = uniformBlockIndex;
936
937 UniformBlockUniformInfo info;
938 info.numActiveUniforms = (size_t)numActiveUniforms;
939
940 m_uniformBlockInfoMap[key] = info;
941 }
942
numActiveUniformsInUniformBlock(GLuint program,GLuint uniformBlockIndex) const943 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
944 UniformBlockInfoKey key;
945 key.program = program;
946 key.uniformBlockIndex = uniformBlockIndex;
947 UniformBlockInfoMap::const_iterator it =
948 m_uniformBlockInfoMap.find(key);
949 if (it == m_uniformBlockInfoMap.end()) return 0;
950 return it->second.numActiveUniforms;
951 }
952
associateProgramWithPipeline(GLuint program,GLuint pipeline)953 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
954 m_programPipelines[program] = pipeline;
955 }
956
programPipelineBegin()957 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
958 return m_programPipelines.begin();
959 }
960
programPipelineEnd()961 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
962 return m_programPipelines.end();
963 }
964
setActiveTextureUnit(GLenum texture)965 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
966 {
967 GLuint unit = texture - GL_TEXTURE0;
968 if (unit >= MAX_TEXTURE_UNITS) {
969 return GL_INVALID_ENUM;
970 }
971 m_tex.activeUnit = &m_tex.unit[unit];
972 return GL_NO_ERROR;
973 }
974
getActiveTextureUnit() const975 GLenum GLClientState::getActiveTextureUnit() const
976 {
977 return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
978 }
979
enableTextureTarget(GLenum target)980 void GLClientState::enableTextureTarget(GLenum target)
981 {
982 switch (target) {
983 case GL_TEXTURE_2D:
984 m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
985 break;
986 case GL_TEXTURE_EXTERNAL_OES:
987 m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
988 break;
989 }
990 }
991
disableTextureTarget(GLenum target)992 void GLClientState::disableTextureTarget(GLenum target)
993 {
994 switch (target) {
995 case GL_TEXTURE_2D:
996 m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
997 break;
998 case GL_TEXTURE_EXTERNAL_OES:
999 m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
1000 break;
1001 }
1002 }
1003
bindSampler(GLuint unit,GLuint sampler)1004 void GLClientState::bindSampler(GLuint unit, GLuint sampler) {
1005 m_tex.unit[unit].boundSampler = sampler;
1006 }
1007
isSamplerBindNoOp(GLuint unit,GLuint sampler)1008 bool GLClientState::isSamplerBindNoOp(GLuint unit, GLuint sampler) {
1009 return m_tex.unit[unit].boundSampler == sampler;
1010 }
1011
onDeleteSamplers(GLsizei n,const GLuint * samplers)1012 void GLClientState::onDeleteSamplers(GLsizei n, const GLuint* samplers) {
1013 for (uint32_t i = 0; i < n; ++i) {
1014 for (uint32_t j = 0; j < MAX_TEXTURE_UNITS; ++j) {
1015 uint32_t currentSampler = m_tex.unit[j].boundSampler;
1016 if (currentSampler == samplers[i]) {
1017 m_tex.unit[j].boundSampler = 0;
1018 }
1019 }
1020 }
1021 }
1022
getPriorityEnabledTarget(GLenum allDisabled) const1023 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
1024 {
1025 unsigned int enables = m_tex.activeUnit->enables;
1026 if (enables & (1u << TEXTURE_EXTERNAL)) {
1027 return GL_TEXTURE_EXTERNAL_OES;
1028 } else if (enables & (1u << TEXTURE_2D)) {
1029 return GL_TEXTURE_2D;
1030 } else {
1031 return allDisabled;
1032 }
1033 }
1034
compareTexId(const void * pid,const void * prec)1035 int GLClientState::compareTexId(const void* pid, const void* prec)
1036 {
1037 const GLuint* id = (const GLuint*)pid;
1038 const TextureRec* rec = (const TextureRec*)prec;
1039 return (GLint)(*id) - (GLint)rec->id;
1040 }
1041
bindTexture(GLenum target,GLuint texture,GLboolean * firstUse)1042 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
1043 GLboolean* firstUse)
1044 {
1045 GLboolean first = GL_FALSE;
1046
1047 TextureRec* texrec = getTextureRec(texture);
1048 if (!texrec) {
1049 texrec = addTextureRec(texture, target);
1050 }
1051
1052 if (texture && target != texrec->target &&
1053 (target != GL_TEXTURE_EXTERNAL_OES &&
1054 texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
1055 ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
1056 }
1057
1058 switch (target) {
1059 case GL_TEXTURE_2D:
1060 m_tex.activeUnit->texture[TEXTURE_2D] = texture;
1061 break;
1062 case GL_TEXTURE_EXTERNAL_OES:
1063 m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
1064 break;
1065 case GL_TEXTURE_CUBE_MAP:
1066 m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
1067 break;
1068 case GL_TEXTURE_2D_ARRAY:
1069 m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
1070 break;
1071 case GL_TEXTURE_3D:
1072 m_tex.activeUnit->texture[TEXTURE_3D] = texture;
1073 break;
1074 case GL_TEXTURE_2D_MULTISAMPLE:
1075 m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
1076 break;
1077 }
1078
1079 if (firstUse) {
1080 *firstUse = first;
1081 }
1082
1083 return GL_NO_ERROR;
1084 }
1085
setBoundEGLImage(GLenum target,GLeglImageOES image)1086 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
1087 (void)image;
1088
1089 GLuint texture = getBoundTexture(target);
1090 TextureRec* texrec = getTextureRec(texture);
1091 if (!texrec) return;
1092 texrec->boundEGLImage = true;
1093 }
1094
addTextureRec(GLuint id,GLenum target)1095 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
1096 {
1097 TextureRec* tex = new TextureRec;
1098 tex->id = id;
1099 tex->target = target;
1100 tex->format = -1;
1101 tex->multisamples = 0;
1102 tex->immutable = false;
1103 tex->boundEGLImage = false;
1104 tex->dims = new TextureDims;
1105
1106 (*(m_tex.textureRecs))[id] = tex;
1107 return tex;
1108 }
1109
getTextureRec(GLuint id) const1110 TextureRec* GLClientState::getTextureRec(GLuint id) const {
1111 SharedTextureDataMap::const_iterator it =
1112 m_tex.textureRecs->find(id);
1113 if (it == m_tex.textureRecs->end()) {
1114 return NULL;
1115 }
1116 return it->second;
1117 }
1118
setBoundTextureInternalFormat(GLenum target,GLint internalformat)1119 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
1120 GLuint texture = getBoundTexture(target);
1121 TextureRec* texrec = getTextureRec(texture);
1122 if (!texrec) return;
1123 texrec->internalformat = internalformat;
1124 }
1125
setBoundTextureFormat(GLenum target,GLenum format)1126 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
1127 GLuint texture = getBoundTexture(target);
1128 TextureRec* texrec = getTextureRec(texture);
1129 if (!texrec) return;
1130 texrec->format = format;
1131 }
1132
setBoundTextureType(GLenum target,GLenum type)1133 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
1134 GLuint texture = getBoundTexture(target);
1135 TextureRec* texrec = getTextureRec(texture);
1136 if (!texrec) return;
1137 texrec->type = type;
1138 }
1139
setBoundTextureDims(GLenum target,GLsizei level,GLsizei width,GLsizei height,GLsizei depth)1140 void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
1141 GLuint texture = getBoundTexture(target);
1142 TextureRec* texrec = getTextureRec(texture);
1143 if (!texrec) {
1144 return;
1145 }
1146
1147 if (level == -1) {
1148 GLsizei curr_width = width;
1149 GLsizei curr_height = height;
1150 GLsizei curr_depth = depth;
1151 GLsizei curr_level = 0;
1152
1153 while (true) {
1154 texrec->dims->widths[curr_level] = curr_width;
1155 texrec->dims->heights[curr_level] = curr_height;
1156 texrec->dims->depths[curr_level] = curr_depth;
1157 if (curr_width >> 1 == 0 &&
1158 curr_height >> 1 == 0 &&
1159 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
1160 true)) {
1161 break;
1162 }
1163 curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
1164 curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
1165 if (target == GL_TEXTURE_3D) {
1166 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
1167 }
1168 curr_level++;
1169 }
1170
1171 } else {
1172 texrec->dims->widths[level] = width;
1173 texrec->dims->heights[level] = height;
1174 texrec->dims->depths[level] = depth;
1175 }
1176 }
1177
setBoundTextureSamples(GLenum target,GLsizei samples)1178 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
1179 GLuint texture = getBoundTexture(target);
1180 TextureRec* texrec = getTextureRec(texture);
1181 if (!texrec) return;
1182 texrec->multisamples = samples;
1183 }
1184
setBoundTextureImmutableFormat(GLenum target)1185 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
1186 GLuint texture = getBoundTexture(target);
1187 TextureRec* texrec = getTextureRec(texture);
1188 if (!texrec) return;
1189 texrec->immutable = true;
1190 }
1191
isBoundTextureImmutableFormat(GLenum target) const1192 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
1193 GLuint texture = getBoundTexture(target);
1194 TextureRec* texrec = getTextureRec(texture);
1195 if (!texrec) return false;
1196 return texrec->immutable;
1197 }
1198
getBoundTexture(GLenum target) const1199 GLuint GLClientState::getBoundTexture(GLenum target) const
1200 {
1201 switch (target) {
1202 case GL_TEXTURE_2D:
1203 return m_tex.activeUnit->texture[TEXTURE_2D];
1204 case GL_TEXTURE_EXTERNAL_OES:
1205 return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
1206 case GL_TEXTURE_CUBE_MAP:
1207 return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
1208 case GL_TEXTURE_2D_ARRAY:
1209 return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
1210 case GL_TEXTURE_3D:
1211 return m_tex.activeUnit->texture[TEXTURE_3D];
1212 case GL_TEXTURE_2D_MULTISAMPLE:
1213 return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
1214 default:
1215 return 0;
1216 }
1217 }
1218
1219 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1220 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1221
unreliableInternalFormat(GLenum internalformat)1222 static bool unreliableInternalFormat(GLenum internalformat) {
1223 switch (internalformat) {
1224 case GL_LUMINANCE:
1225 return true;
1226 default:
1227 return false;
1228 }
1229 }
1230
writeCopyTexImageState(GLenum target,GLint level,GLenum internalformat)1231 void GLClientState::writeCopyTexImageState
1232 (GLenum target, GLint level, GLenum internalformat) {
1233 if (unreliableInternalFormat(internalformat)) {
1234 CubeMapDef entry;
1235 entry.id = getBoundTexture(GL_TEXTURE_2D);
1236 entry.target = target;
1237 entry.level = level;
1238 entry.internalformat = internalformat;
1239 m_cubeMapDefs.insert(entry);
1240 }
1241 }
1242
identifyPositiveCubeMapComponent(GLenum target)1243 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
1244 switch (target) {
1245 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1246 return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1247 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1248 return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
1249 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1250 return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
1251 default:
1252 return 0;
1253 }
1254 }
1255
copyTexImageNeededTarget(GLenum target,GLint level,GLenum internalformat)1256 GLenum GLClientState::copyTexImageNeededTarget
1257 (GLenum target, GLint level, GLenum internalformat) {
1258 if (unreliableInternalFormat(internalformat)) {
1259 GLenum positiveComponent =
1260 identifyPositiveCubeMapComponent(target);
1261 if (positiveComponent) {
1262 CubeMapDef query;
1263 query.id = getBoundTexture(GL_TEXTURE_2D);
1264 query.target = positiveComponent;
1265 query.level = level;
1266 query.internalformat = internalformat;
1267 if (m_cubeMapDefs.find(query) ==
1268 m_cubeMapDefs.end()) {
1269 return positiveComponent;
1270 }
1271 }
1272 }
1273 return 0;
1274 }
1275
copyTexImageLuminanceCubeMapAMDWorkaround(GLenum target,GLint level,GLenum internalformat)1276 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
1277 (GLenum target, GLint level, GLenum internalformat) {
1278 writeCopyTexImageState(target, level, internalformat);
1279 return copyTexImageNeededTarget(target, level, internalformat);
1280 }
1281
1282 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
1283 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
1284
deleteTextures(GLsizei n,const GLuint * textures)1285 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
1286 {
1287 // Updating the textures array could be made more efficient when deleting
1288 // several textures:
1289 // - compacting the array could be done in a single pass once the deleted
1290 // textures are marked, or
1291 // - could swap deleted textures to the end and re-sort.
1292 TextureRec* texrec;
1293 for (const GLuint* texture = textures; texture != textures + n; texture++) {
1294 texrec = getTextureRec(*texture);
1295 if (texrec && texrec->dims) {
1296 delete texrec->dims;
1297 }
1298 if (texrec) {
1299 m_tex.textureRecs->erase(*texture);
1300 delete texrec;
1301 for (TextureUnit* unit = m_tex.unit;
1302 unit != m_tex.unit + MAX_TEXTURE_UNITS;
1303 unit++)
1304 {
1305 if (unit->texture[TEXTURE_2D] == *texture) {
1306 unit->texture[TEXTURE_2D] = 0;
1307 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
1308 unit->texture[TEXTURE_EXTERNAL] = 0;
1309 }
1310 }
1311 }
1312 }
1313 }
1314
1315 // RBO//////////////////////////////////////////////////////////////////////////
1316
addFreshRenderbuffer(GLuint name)1317 void GLClientState::addFreshRenderbuffer(GLuint name) {
1318 // if underlying opengl says these are fresh names,
1319 // but we are keeping a stale one, reset it.
1320 RboProps props;
1321 props.target = GL_RENDERBUFFER;
1322 props.name = name;
1323 props.format = GL_NONE;
1324 props.multisamples = 0;
1325 props.previouslyBound = false;
1326
1327 if (usedRenderbufferName(name)) {
1328 mRboState.rboData[getRboIndex(name)] = props;
1329 } else {
1330 mRboState.rboData.push_back(props);
1331 }
1332 }
1333
addRenderbuffers(GLsizei n,GLuint * renderbuffers)1334 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
1335 for (size_t i = 0; i < n; i++) {
1336 addFreshRenderbuffer(renderbuffers[i]);
1337 }
1338 }
1339
getRboIndex(GLuint name) const1340 size_t GLClientState::getRboIndex(GLuint name) const {
1341 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1342 if (mRboState.rboData[i].name == name) {
1343 return i;
1344 }
1345 }
1346 return -1;
1347 }
1348
removeRenderbuffers(GLsizei n,const GLuint * renderbuffers)1349 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
1350 size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
1351
1352 std::vector<GLuint> to_remove;
1353 for (size_t i = 0; i < n; i++) {
1354 if (renderbuffers[i] != 0) { // Never remove the zero rb.
1355 to_remove.push_back(getRboIndex(renderbuffers[i]));
1356 }
1357 }
1358
1359 for (size_t i = 0; i < to_remove.size(); i++) {
1360 mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
1361 mRboState.rboData.pop_back();
1362 }
1363
1364 // If we just deleted the currently bound rb,
1365 // bind the zero rb
1366 if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
1367 bindRenderbuffer(GL_RENDERBUFFER, 0);
1368 }
1369 }
1370
usedRenderbufferName(GLuint name) const1371 bool GLClientState::usedRenderbufferName(GLuint name) const {
1372 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1373 if (mRboState.rboData[i].name == name) {
1374 return true;
1375 }
1376 }
1377 return false;
1378 }
1379
setBoundRenderbufferIndex()1380 void GLClientState::setBoundRenderbufferIndex() {
1381 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1382 if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
1383 mRboState.boundRenderbufferIndex = i;
1384 break;
1385 }
1386 }
1387 }
1388
boundRboProps()1389 RboProps& GLClientState::boundRboProps() {
1390 return mRboState.rboData[mRboState.boundRenderbufferIndex];
1391 }
1392
boundRboProps_const() const1393 const RboProps& GLClientState::boundRboProps_const() const {
1394 return mRboState.rboData[mRboState.boundRenderbufferIndex];
1395 }
1396
bindRenderbuffer(GLenum target,GLuint name)1397 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
1398 // If unused, add it.
1399 if (!usedRenderbufferName(name)) {
1400 addFreshRenderbuffer(name);
1401 }
1402 mRboState.boundRenderbuffer = name;
1403 setBoundRenderbufferIndex();
1404 boundRboProps().target = target;
1405 boundRboProps().previouslyBound = true;
1406 }
1407
boundRenderbuffer() const1408 GLuint GLClientState::boundRenderbuffer() const {
1409 return boundRboProps_const().name;
1410 }
1411
setBoundRenderbufferFormat(GLenum format)1412 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
1413 boundRboProps().format = format;
1414 }
1415
setBoundRenderbufferSamples(GLsizei samples)1416 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
1417 boundRboProps().multisamples = samples;
1418 }
1419
1420 // FBO//////////////////////////////////////////////////////////////////////////
1421
1422 // Format querying
1423
queryRboFormat(GLuint rbo_name) const1424 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
1425 return mRboState.rboData[getRboIndex(rbo_name)].format;
1426 }
1427
queryRboSamples(GLuint rbo_name) const1428 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
1429 return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
1430 }
1431
queryTexInternalFormat(GLuint tex_name) const1432 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
1433 TextureRec* texrec = getTextureRec(tex_name);
1434 if (!texrec) return -1;
1435 return texrec->internalformat;
1436 }
1437
queryTexWidth(GLsizei level,GLuint tex_name) const1438 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
1439 TextureRec* texrec = getTextureRec(tex_name);
1440 if (!texrec) {
1441 return 0;
1442 }
1443 return texrec->dims->widths[level];
1444 }
1445
queryTexHeight(GLsizei level,GLuint tex_name) const1446 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
1447 TextureRec* texrec = getTextureRec(tex_name);
1448 if (!texrec) return 0;
1449 return texrec->dims->heights[level];
1450 }
1451
queryTexDepth(GLsizei level,GLuint tex_name) const1452 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
1453 TextureRec* texrec = getTextureRec(tex_name);
1454 if (!texrec) return 0;
1455 return texrec->dims->depths[level];
1456 }
1457
queryTexEGLImageBacked(GLuint tex_name) const1458 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
1459 TextureRec* texrec = getTextureRec(tex_name);
1460 if (!texrec) return false;
1461 return texrec->boundEGLImage;
1462 }
1463
queryTexFormat(GLuint tex_name) const1464 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
1465 TextureRec* texrec = getTextureRec(tex_name);
1466 if (!texrec) return -1;
1467 return texrec->format;
1468 }
1469
queryTexType(GLuint tex_name) const1470 GLenum GLClientState::queryTexType(GLuint tex_name) const {
1471 TextureRec* texrec = getTextureRec(tex_name);
1472 if (!texrec) return -1;
1473 return texrec->type;
1474 }
1475
queryTexSamples(GLuint tex_name) const1476 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
1477 TextureRec* texrec = getTextureRec(tex_name);
1478 if (!texrec) return 0;
1479 return texrec->multisamples;
1480 }
1481
queryTexLastBoundTarget(GLuint tex_name) const1482 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
1483 TextureRec* texrec = getTextureRec(tex_name);
1484 if (!texrec) return GL_NONE;
1485 return texrec->target;
1486 }
1487
getBoundFramebufferFormat(GLenum target,GLenum attachment,FboFormatInfo * res_info) const1488 void GLClientState::getBoundFramebufferFormat(
1489 GLenum target,
1490 GLenum attachment, FboFormatInfo* res_info) const {
1491 const FboProps& props = boundFboProps_const(target);
1492
1493 res_info->type = FBO_ATTACHMENT_NONE;
1494 res_info->rb_format = GL_NONE;
1495 res_info->rb_multisamples = 0;
1496 res_info->tex_internalformat = -1;
1497 res_info->tex_format = GL_NONE;
1498 res_info->tex_type = GL_NONE;
1499 res_info->tex_multisamples = 0;
1500
1501 int colorAttachmentIndex =
1502 glUtilsColorAttachmentIndex(attachment);
1503
1504 if (colorAttachmentIndex != -1) {
1505 if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1506 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1507 res_info->rb_format =
1508 queryRboFormat(
1509 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1510 res_info->rb_multisamples =
1511 queryRboSamples(
1512 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1513 } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1514 res_info->type = FBO_ATTACHMENT_TEXTURE;
1515 res_info->tex_internalformat =
1516 queryTexInternalFormat(
1517 props.colorAttachmenti_textures[colorAttachmentIndex]);
1518 res_info->tex_format =
1519 queryTexFormat(
1520 props.colorAttachmenti_textures[colorAttachmentIndex]);
1521 res_info->tex_type =
1522 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
1523 res_info->tex_multisamples =
1524 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1525 } else {
1526 res_info->type = FBO_ATTACHMENT_NONE;
1527 }
1528 }
1529
1530 switch (attachment) {
1531 case GL_DEPTH_ATTACHMENT:
1532 if (props.depthAttachment_hasRbo) {
1533 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1534 res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
1535 res_info->rb_multisamples =
1536 queryRboSamples(
1537 props.depthAttachment_rbo);
1538 } else if (props.depthAttachment_hasTexObj) {
1539 res_info->type = FBO_ATTACHMENT_TEXTURE;
1540 res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
1541 res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
1542 res_info->tex_type = queryTexType(props.depthAttachment_texture);
1543 res_info->tex_multisamples =
1544 queryTexSamples(props.depthAttachment_texture);
1545 } else {
1546 res_info->type = FBO_ATTACHMENT_NONE;
1547 }
1548 break;
1549 case GL_STENCIL_ATTACHMENT:
1550 if (props.stencilAttachment_hasRbo) {
1551 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1552 res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
1553 res_info->rb_multisamples =
1554 queryRboSamples(
1555 props.stencilAttachment_rbo);
1556 } else if (props.stencilAttachment_hasTexObj) {
1557 res_info->type = FBO_ATTACHMENT_TEXTURE;
1558 res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
1559 res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
1560 res_info->tex_type = queryTexType(props.stencilAttachment_texture);
1561 res_info->tex_multisamples =
1562 queryTexSamples(props.stencilAttachment_texture);
1563 } else {
1564 res_info->type = FBO_ATTACHMENT_NONE;
1565 }
1566 break;
1567 case GL_DEPTH_STENCIL_ATTACHMENT:
1568 if (props.depthstencilAttachment_hasRbo) {
1569 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1570 res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
1571 res_info->rb_multisamples =
1572 queryRboSamples(
1573 props.depthstencilAttachment_rbo);
1574 } else if (props.depthstencilAttachment_hasTexObj) {
1575 res_info->type = FBO_ATTACHMENT_TEXTURE;
1576 res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
1577 res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
1578 res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
1579 res_info->tex_multisamples =
1580 queryTexSamples(props.depthstencilAttachment_texture);
1581 } else {
1582 res_info->type = FBO_ATTACHMENT_NONE;
1583 }
1584 break;
1585 }
1586 }
1587
getBoundFramebufferAttachmentType(GLenum target,GLenum attachment) const1588 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
1589 FboFormatInfo info;
1590 getBoundFramebufferFormat(target, attachment, &info);
1591 return info.type;
1592 }
1593
1594
getMaxColorAttachments() const1595 int GLClientState::getMaxColorAttachments() const {
1596 return m_max_color_attachments;
1597 }
1598
getMaxDrawBuffers() const1599 int GLClientState::getMaxDrawBuffers() const {
1600 return m_max_draw_buffers;
1601 }
1602
addFreshFramebuffer(GLuint name)1603 void GLClientState::addFreshFramebuffer(GLuint name) {
1604 FboProps props;
1605 props.name = name;
1606 props.previouslyBound = false;
1607
1608 props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
1609 props.depthAttachment_texture = 0;
1610 props.stencilAttachment_texture = 0;
1611 props.depthstencilAttachment_texture = 0;
1612
1613 props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
1614 props.depthAttachment_hasTexObj = false;
1615 props.stencilAttachment_hasTexObj = false;
1616 props.depthstencilAttachment_hasTexObj = false;
1617
1618 props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
1619 props.depthAttachment_rbo = 0;
1620 props.stencilAttachment_rbo = 0;
1621 props.depthstencilAttachment_rbo = 0;
1622
1623 props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
1624 props.depthAttachment_hasRbo = false;
1625 props.stencilAttachment_hasRbo = false;
1626 props.depthstencilAttachment_hasRbo = false;
1627 mFboState.fboData[name] = props;
1628 }
1629
addFramebuffers(GLsizei n,GLuint * framebuffers)1630 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
1631 for (size_t i = 0; i < n; i++) {
1632 addFreshFramebuffer(framebuffers[i]);
1633 }
1634 }
1635
removeFramebuffers(GLsizei n,const GLuint * framebuffers)1636 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
1637 for (size_t i = 0; i < n; i++) {
1638 if (framebuffers[i] != 0) { // Never remove the zero fb.
1639 if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
1640 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1641 }
1642 if (framebuffers[i] == mFboState.boundReadFramebuffer) {
1643 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1644 }
1645 mFboState.fboData.erase(framebuffers[i]);
1646 }
1647 }
1648 }
1649
usedFramebufferName(GLuint name) const1650 bool GLClientState::usedFramebufferName(GLuint name) const {
1651 return mFboState.fboData.find(name) != mFboState.fboData.end();
1652 }
1653
boundFboProps(GLenum target)1654 FboProps& GLClientState::boundFboProps(GLenum target) {
1655 switch (target) {
1656 case GL_DRAW_FRAMEBUFFER:
1657 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1658 case GL_READ_FRAMEBUFFER:
1659 return mFboState.fboData[mFboState.boundReadFramebuffer];
1660 case GL_FRAMEBUFFER:
1661 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1662 }
1663 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1664 }
1665
boundFboProps_const(GLenum target) const1666 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
1667 switch (target) {
1668 case GL_DRAW_FRAMEBUFFER:
1669 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1670 case GL_READ_FRAMEBUFFER:
1671 return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
1672 case GL_FRAMEBUFFER:
1673 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1674 }
1675 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1676 }
1677
bindFramebuffer(GLenum target,GLuint name)1678 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
1679 // If unused, add it.
1680 if (!usedFramebufferName(name)) {
1681 addFreshFramebuffer(name);
1682 }
1683 switch (target) {
1684 case GL_DRAW_FRAMEBUFFER:
1685 mFboState.boundDrawFramebuffer = name;
1686 break;
1687 case GL_READ_FRAMEBUFFER:
1688 mFboState.boundReadFramebuffer = name;
1689 break;
1690 default: // case GL_FRAMEBUFFER:
1691 mFboState.boundDrawFramebuffer = name;
1692 mFboState.boundReadFramebuffer = name;
1693 break;
1694 }
1695 boundFboProps(target).previouslyBound = true;
1696 }
1697
setCheckFramebufferStatus(GLenum target,GLenum status)1698 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
1699 switch (target) {
1700 case GL_DRAW_FRAMEBUFFER:
1701 mFboState.drawFboCheckStatus = status;
1702 break;
1703 case GL_READ_FRAMEBUFFER:
1704 mFboState.readFboCheckStatus = status;
1705 break;
1706 case GL_FRAMEBUFFER:
1707 mFboState.drawFboCheckStatus = status;
1708 break;
1709 }
1710 }
1711
getCheckFramebufferStatus(GLenum target) const1712 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
1713 switch (target) {
1714 case GL_DRAW_FRAMEBUFFER:
1715 return mFboState.drawFboCheckStatus;
1716 case GL_READ_FRAMEBUFFER:
1717 return mFboState.readFboCheckStatus;
1718 case GL_FRAMEBUFFER:
1719 return mFboState.drawFboCheckStatus;
1720 }
1721 return mFboState.drawFboCheckStatus;
1722 }
1723
boundFramebuffer(GLenum target) const1724 GLuint GLClientState::boundFramebuffer(GLenum target) const {
1725 return boundFboProps_const(target).name;
1726 }
1727
1728 // Texture objects for FBOs/////////////////////////////////////////////////////
1729
attachTextureObject(GLenum target,GLenum attachment,GLuint texture)1730 void GLClientState::attachTextureObject(
1731 GLenum target,
1732 GLenum attachment, GLuint texture) {
1733
1734 int colorAttachmentIndex =
1735 glUtilsColorAttachmentIndex(attachment);
1736
1737 if (colorAttachmentIndex != -1) {
1738 boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
1739 boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
1740 }
1741
1742 switch (attachment) {
1743 case GL_DEPTH_ATTACHMENT:
1744 boundFboProps(target).depthAttachment_texture = texture;
1745 boundFboProps(target).depthAttachment_hasTexObj = true;
1746 break;
1747 case GL_STENCIL_ATTACHMENT:
1748 boundFboProps(target).stencilAttachment_texture = texture;
1749 boundFboProps(target).stencilAttachment_hasTexObj = true;
1750 break;
1751 case GL_DEPTH_STENCIL_ATTACHMENT:
1752 boundFboProps(target).depthstencilAttachment_texture = texture;
1753 boundFboProps(target).depthstencilAttachment_hasTexObj = true;
1754 boundFboProps(target).stencilAttachment_texture = texture;
1755 boundFboProps(target).stencilAttachment_hasTexObj = true;
1756 boundFboProps(target).depthAttachment_texture = texture;
1757 boundFboProps(target).depthAttachment_hasTexObj = true;
1758 break;
1759 }
1760 }
1761
getFboAttachmentTextureId(GLenum target,GLenum attachment) const1762 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
1763 GLuint res = 0; // conservative
1764
1765 int colorAttachmentIndex =
1766 glUtilsColorAttachmentIndex(attachment);
1767
1768 if (colorAttachmentIndex != -1) {
1769 res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
1770 }
1771
1772 switch (attachment) {
1773 case GL_DEPTH_ATTACHMENT:
1774 res = boundFboProps_const(target).depthAttachment_texture;
1775 break;
1776 case GL_STENCIL_ATTACHMENT:
1777 res = boundFboProps_const(target).stencilAttachment_texture;
1778 break;
1779 case GL_DEPTH_STENCIL_ATTACHMENT:
1780 res = boundFboProps_const(target).depthstencilAttachment_texture;
1781 break;
1782 }
1783 return res;
1784 }
1785
1786 // RBOs for FBOs////////////////////////////////////////////////////////////////
1787
detachRbo(GLuint renderbuffer)1788 void GLClientState::detachRbo(GLuint renderbuffer) {
1789 for (int i = 0; i < m_max_color_attachments; i++) {
1790 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1791 detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1792 }
1793
1794 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1795 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1796
1797 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1798 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1799
1800 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1801 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1802 }
1803
detachRboFromFbo(GLenum target,GLenum attachment,GLuint renderbuffer)1804 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1805 int colorAttachmentIndex =
1806 glUtilsColorAttachmentIndex(attachment);
1807
1808 if (colorAttachmentIndex != -1) {
1809 if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
1810 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
1811 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
1812 boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
1813 }
1814 }
1815
1816 switch (attachment) {
1817 case GL_DEPTH_ATTACHMENT:
1818 if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1819 boundFboProps(target).depthAttachment_hasRbo) {
1820 boundFboProps(target).depthAttachment_rbo = 0;
1821 boundFboProps(target).depthAttachment_hasRbo = false;
1822 }
1823 break;
1824 case GL_STENCIL_ATTACHMENT:
1825 if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1826 boundFboProps(target).stencilAttachment_hasRbo) {
1827 boundFboProps(target).stencilAttachment_rbo = 0;
1828 boundFboProps(target).stencilAttachment_hasRbo = false;
1829 }
1830 break;
1831 case GL_DEPTH_STENCIL_ATTACHMENT:
1832 if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1833 boundFboProps(target).depthAttachment_hasRbo) {
1834 boundFboProps(target).depthAttachment_rbo = 0;
1835 boundFboProps(target).depthAttachment_hasRbo = false;
1836 }
1837 if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1838 boundFboProps(target).stencilAttachment_hasRbo) {
1839 boundFboProps(target).stencilAttachment_rbo = 0;
1840 boundFboProps(target).stencilAttachment_hasRbo = false;
1841 }
1842 if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
1843 boundFboProps(target).depthstencilAttachment_hasRbo) {
1844 boundFboProps(target).depthstencilAttachment_rbo = 0;
1845 boundFboProps(target).depthstencilAttachment_hasRbo = false;
1846 }
1847 break;
1848 }
1849 }
1850
attachRbo(GLenum target,GLenum attachment,GLuint renderbuffer)1851 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1852
1853 int colorAttachmentIndex =
1854 glUtilsColorAttachmentIndex(attachment);
1855
1856 if (colorAttachmentIndex != -1) {
1857 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
1858 boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
1859 }
1860
1861 switch (attachment) {
1862 case GL_DEPTH_ATTACHMENT:
1863 boundFboProps(target).depthAttachment_rbo = renderbuffer;
1864 boundFboProps(target).depthAttachment_hasRbo = true;
1865 break;
1866 case GL_STENCIL_ATTACHMENT:
1867 boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1868 boundFboProps(target).stencilAttachment_hasRbo = true;
1869 break;
1870 case GL_DEPTH_STENCIL_ATTACHMENT:
1871 boundFboProps(target).depthAttachment_rbo = renderbuffer;
1872 boundFboProps(target).depthAttachment_hasRbo = true;
1873 boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1874 boundFboProps(target).stencilAttachment_hasRbo = true;
1875 boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
1876 boundFboProps(target).depthstencilAttachment_hasRbo = true;
1877 break;
1878 }
1879 }
1880
getFboAttachmentRboId(GLenum target,GLenum attachment) const1881 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
1882 GLuint res = 0; // conservative
1883
1884 int colorAttachmentIndex =
1885 glUtilsColorAttachmentIndex(attachment);
1886
1887 if (colorAttachmentIndex != -1) {
1888 res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
1889 }
1890
1891 switch (attachment) {
1892 case GL_DEPTH_ATTACHMENT:
1893 res = boundFboProps_const(target).depthAttachment_rbo;
1894 break;
1895 case GL_STENCIL_ATTACHMENT:
1896 res = boundFboProps_const(target).stencilAttachment_rbo;
1897 break;
1898 case GL_DEPTH_STENCIL_ATTACHMENT:
1899 res = boundFboProps_const(target).depthstencilAttachment_rbo;
1900 break;
1901 }
1902 return res;
1903 }
1904
attachmentHasObject(GLenum target,GLenum attachment) const1905 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
1906 bool res = true; // liberal
1907
1908 int colorAttachmentIndex =
1909 glUtilsColorAttachmentIndex(attachment);
1910
1911 if (colorAttachmentIndex != -1) {
1912 res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
1913 boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
1914 }
1915
1916 switch (attachment) {
1917 case GL_DEPTH_ATTACHMENT:
1918 res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
1919 (boundFboProps_const(target).depthAttachment_hasRbo);
1920 break;
1921 case GL_STENCIL_ATTACHMENT:
1922 res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
1923 (boundFboProps_const(target).stencilAttachment_hasRbo);
1924 break;
1925 case GL_DEPTH_STENCIL_ATTACHMENT:
1926 res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
1927 (boundFboProps_const(target).depthstencilAttachment_hasRbo);
1928 break;
1929 }
1930 return res;
1931 }
1932
objectOfAttachment(GLenum target,GLenum attachment) const1933 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
1934 const FboProps& props = boundFboProps_const(target);
1935
1936 int colorAttachmentIndex =
1937 glUtilsColorAttachmentIndex(attachment);
1938
1939 if (colorAttachmentIndex != -1) {
1940 if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1941 return props.colorAttachmenti_textures[colorAttachmentIndex];
1942 } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1943 return props.colorAttachmenti_rbos[colorAttachmentIndex];
1944 } else {
1945 return 0;
1946 }
1947 }
1948
1949 switch (attachment) {
1950 case GL_DEPTH_ATTACHMENT:
1951 if (props.depthAttachment_hasTexObj) {
1952 return props.depthAttachment_texture;
1953 } else if (props.depthAttachment_hasRbo) {
1954 return props.depthAttachment_rbo;
1955 } else {
1956 return 0;
1957 }
1958 break;
1959 case GL_STENCIL_ATTACHMENT:
1960 if (props.stencilAttachment_hasTexObj) {
1961 return props.stencilAttachment_texture;
1962 } else if (props.stencilAttachment_hasRbo) {
1963 return props.stencilAttachment_rbo;
1964 } else {
1965 return 0;
1966 }
1967 case GL_DEPTH_STENCIL_ATTACHMENT:
1968 if (props.depthstencilAttachment_hasTexObj) {
1969 return props.depthstencilAttachment_texture;
1970 } else if (props.depthstencilAttachment_hasRbo) {
1971 return props.depthstencilAttachment_rbo;
1972 } else {
1973 return 0;
1974 }
1975 break;
1976 }
1977 return 0;
1978 }
1979
setTransformFeedbackActiveUnpaused(bool activeUnpaused)1980 void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
1981 m_transformFeedbackActiveUnpaused = activeUnpaused;
1982 }
1983
getTransformFeedbackActiveUnpaused() const1984 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
1985 return m_transformFeedbackActiveUnpaused;
1986 }
1987
setTextureData(SharedTextureDataMap * sharedTexData)1988 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
1989 m_tex.textureRecs = sharedTexData;
1990 }
1991
fromMakeCurrent()1992 void GLClientState::fromMakeCurrent() {
1993 if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
1994 addFreshFramebuffer(0);
1995 }
1996 FboProps& default_fb_props = mFboState.fboData[0];
1997 default_fb_props.colorAttachmenti_hasRbo[0] = true;
1998 default_fb_props.depthAttachment_hasRbo = true;
1999 default_fb_props.stencilAttachment_hasRbo = true;
2000 default_fb_props.depthstencilAttachment_hasRbo = true;
2001 }
2002
initFromCaps(int max_transform_feedback_separate_attribs,int max_uniform_buffer_bindings,int max_atomic_counter_buffer_bindings,int max_shader_storage_buffer_bindings,int max_vertex_attrib_bindings,int max_color_attachments,int max_draw_buffers)2003 void GLClientState::initFromCaps(
2004 int max_transform_feedback_separate_attribs,
2005 int max_uniform_buffer_bindings,
2006 int max_atomic_counter_buffer_bindings,
2007 int max_shader_storage_buffer_bindings,
2008 int max_vertex_attrib_bindings,
2009 int max_color_attachments,
2010 int max_draw_buffers) {
2011
2012 m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
2013
2014 if (m_glesMajorVersion >= 3) {
2015 m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
2016 m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
2017 m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
2018 m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
2019
2020 if (m_max_transform_feedback_separate_attribs)
2021 m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
2022 if (m_max_uniform_buffer_bindings)
2023 m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
2024 if (m_max_atomic_counter_buffer_bindings)
2025 m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
2026 if (m_max_shader_storage_buffer_bindings)
2027 m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
2028
2029 BufferBinding buf0Binding;
2030 buf0Binding.buffer = 0;
2031 buf0Binding.offset = 0;
2032 buf0Binding.size = 0;
2033 buf0Binding.stride = 0;
2034 buf0Binding.effectiveStride = 0;
2035
2036 for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
2037 m_indexedTransformFeedbackBuffers[i] = buf0Binding;
2038 for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
2039 m_indexedUniformBuffers[i] = buf0Binding;
2040 for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
2041 m_indexedAtomicCounterBuffers[i] = buf0Binding;
2042 for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
2043 m_indexedShaderStorageBuffers[i] = buf0Binding;
2044 }
2045
2046 m_max_color_attachments = max_color_attachments;
2047 m_max_draw_buffers = max_draw_buffers;
2048
2049 addFreshRenderbuffer(0);
2050 addFreshFramebuffer(0);
2051
2052 m_initialized = true;
2053 }
2054
needsInitFromCaps() const2055 bool GLClientState::needsInitFromCaps() const {
2056 return !m_initialized;
2057 }
2058