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