2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "GLClientState.h"
17 #include "GLESTextureUtils.h"
23 #include <cutils/log.h>
26 #define MAX(a, b) ((a) < (b) ? (b) : (a))
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>
33 void GLClientState::init() {
34 m_initialized = false;
35 m_nLocations = CODEC_MAX_VERTEX_ATTRIBUTES;
38 m_max_vertex_attrib_bindings = m_nLocations;
39 addVertexArrayObject(0);
40 setVertexArrayObject(0);
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;
58 m_copyWriteBuffer = 0;
59 m_pixelPackBuffer = 0;
60 m_pixelUnpackBuffer = 0;
61 m_transformFeedbackBuffer = 0;
63 m_atomicCounterBuffer = 0;
64 m_dispatchIndirectBuffer = 0;
65 m_drawIndirectBuffer = 0;
66 m_shaderStorageBuffer = 0;
68 m_transformFeedbackActiveUnpaused = false;
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;
79 m_pixelStore.unpack_alignment = 4;
80 m_pixelStore.pack_alignment = 4;
82 m_pixelStore.unpack_row_length = 0;
83 m_pixelStore.unpack_image_height = 0;
84 m_pixelStore.unpack_skip_pixels = 0;
85 m_pixelStore.unpack_skip_rows = 0;
86 m_pixelStore.unpack_skip_images = 0;
88 m_pixelStore.pack_row_length = 0;
89 m_pixelStore.pack_skip_pixels = 0;
90 m_pixelStore.pack_skip_rows = 0;
92 memset(m_tex.unit, 0, sizeof(m_tex.unit));
93 m_tex.activeUnit = &m_tex.unit[0];
94 m_tex.textureRecs = NULL;
96 mRboState.boundRenderbuffer = 0;
97 mRboState.boundRenderbufferIndex = 0;
99 mFboState.boundDrawFramebuffer = 0;
100 mFboState.boundReadFramebuffer = 0;
101 mFboState.drawFboCheckStatus = GL_NONE;
102 mFboState.readFboCheckStatus = GL_NONE;
104 m_maxVertexAttribsDirty = true;
107 GLClientState::GLClientState()
112 GLClientState::GLClientState(int majorVersion, int minorVersion) :
113 m_glesMajorVersion(majorVersion),
114 m_glesMinorVersion(minorVersion) {
118 GLClientState::~GLClientState()
122 void GLClientState::enable(int location, int state)
124 m_currVaoState[location].enableDirty |= (state != m_currVaoState[location].enabled);
125 m_currVaoState[location].enabled = state;
128 void GLClientState::setVertexAttribState(int location, int size, GLenum type, GLboolean normalized, GLsizei stride, const void *data, bool isInt)
130 m_currVaoState[location].size = size;
131 m_currVaoState[location].type = type;
132 m_currVaoState[location].stride = stride;
133 m_currVaoState[location].data = (void*)data;
134 m_currVaoState[location].bufferObject = m_arrayBuffer;
135 m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
137 case GL_INT_2_10_10_10_REV:
138 case GL_UNSIGNED_INT_2_10_10_10_REV:
139 m_currVaoState[location].elementSize =
140 m_currVaoState[location].elementSize / 4;
145 m_currVaoState[location].normalized = normalized;
146 m_currVaoState[location].isInt = isInt;
149 void GLClientState::setVertexBindingDivisor(int bindingindex, GLuint divisor) {
150 m_currVaoState.bufferBinding(bindingindex).divisor = divisor;
153 const GLClientState::BufferBinding& GLClientState::getCurrAttributeBindingInfo(int attribindex) {
154 return m_currVaoState.bufferBindings_const()[m_currVaoState[attribindex].bindingindex];
157 void GLClientState::setVertexAttribBinding(int attribindex, int bindingindex) {
158 m_currVaoState[attribindex].bindingindex = bindingindex;
161 void GLClientState::setVertexAttribFormat(int location, int size, GLenum type, GLboolean normalized, GLuint reloffset, bool isInt) {
162 m_currVaoState[location].size = size;
163 m_currVaoState[location].type = type;
164 m_currVaoState[location].normalized = normalized;
165 m_currVaoState[location].reloffset = reloffset;
166 m_currVaoState[location].elementSize = size ? (glSizeof(type) * size) : 0;
168 case GL_INT_2_10_10_10_REV:
169 case GL_UNSIGNED_INT_2_10_10_10_REV:
170 m_currVaoState[location].elementSize =
171 m_currVaoState[location].elementSize / 4;
176 m_currVaoState[location].isInt = isInt;
179 void GLClientState::addVertexArrayObjects(GLsizei n, GLuint* arrays) {
180 for (GLsizei i = 0; i < n; i++) {
181 addVertexArrayObject(arrays[i]);
185 void GLClientState::removeVertexArrayObjects(GLsizei n, const GLuint* arrays) {
186 for (GLsizei i = 0; i < n; i++) {
187 if (arrays[i] && m_currVaoState.vaoId() == arrays[i]) {
188 setVertexArrayObject(0);
190 removeVertexArrayObject(arrays[i]);
194 void GLClientState::addVertexArrayObject(GLuint name) {
195 if (m_vaoMap.find(name) !=
197 ALOGE("%s: ERROR: %u already part of current VAO state!",
203 VAOStateMap::value_type(
205 VAOState(0, m_nLocations, std::max(m_nLocations, m_max_vertex_attrib_bindings))));
206 VertexAttribStateVector& attribState =
207 m_vaoMap.find(name)->second.attribState;
208 for (int i = 0; i < m_nLocations; i++) {
209 attribState[i].enabled = 0;
210 attribState[i].enableDirty = false;
211 attribState[i].data = 0;
212 attribState[i].reloffset = 0;
213 attribState[i].bindingindex = i;
214 attribState[i].divisor = 0;
215 attribState[i].size = 4; // 4 is the default size
216 attribState[i].type = GL_FLOAT; // GL_FLOAT is the default type
220 void GLClientState::removeVertexArrayObject(GLuint name) {
222 ALOGE("%s: ERROR: cannot delete VAO 0!",
226 if (m_vaoMap.find(name) ==
228 ALOGE("%s: ERROR: %u not found in VAO state!",
232 m_vaoMap.erase(name);
235 void GLClientState::setVertexArrayObject(GLuint name) {
236 if (m_vaoMap.find(name) ==
238 ALOGE("%s: ERROR: %u not found in VAO state!",
243 if (name && m_currVaoState.vaoId() == name) {
244 ALOGV("%s: set vao to self, no-op (%u)",
250 VAOStateRef(m_vaoMap.find(name));
251 ALOGV("%s: set vao to %u (%u) %u %u", __FUNCTION__,
253 m_currVaoState.vaoId(),
255 m_currVaoState.iboId());
258 bool GLClientState::isVertexArrayObject(GLuint vao) const {
259 return m_vaoMap.find(vao) != m_vaoMap.end();
262 const GLClientState::VertexAttribState& GLClientState::getState(int location)
264 return m_currVaoState[location];
267 const GLClientState::VertexAttribState& GLClientState::getStateAndEnableDirty(int location, bool *enableChanged)
270 *enableChanged = m_currVaoState[location].enableDirty;
273 m_currVaoState[location].enableDirty = false;
274 return m_currVaoState[location];
277 int GLClientState::getLocation(GLenum loc)
282 case GL_VERTEX_ARRAY:
283 retval = int(VERTEX_LOCATION);
285 case GL_NORMAL_ARRAY:
286 retval = int(NORMAL_LOCATION);
289 retval = int(COLOR_LOCATION);
291 case GL_POINT_SIZE_ARRAY_OES:
292 retval = int(POINTSIZE_LOCATION);
294 case GL_TEXTURE_COORD_ARRAY:
295 retval = int (TEXCOORD0_LOCATION + m_activeTexture);
297 case GL_MATRIX_INDEX_ARRAY_OES:
298 retval = int (MATRIXINDEX_LOCATION);
300 case GL_WEIGHT_ARRAY_OES:
301 retval = int (WEIGHT_LOCATION);
309 void GLClientState::unBindBuffer(GLuint id) {
310 if (m_arrayBuffer == id) m_arrayBuffer = 0;
311 if (m_currVaoState.iboId() == id) m_currVaoState.iboId() = 0;
312 if (m_copyReadBuffer == id)
313 m_copyReadBuffer = 0;
314 if (m_copyWriteBuffer == id)
315 m_copyWriteBuffer = 0;
316 if (m_pixelPackBuffer == id)
317 m_pixelPackBuffer = 0;
318 if (m_pixelUnpackBuffer == id)
319 m_pixelUnpackBuffer = 0;
320 if (m_transformFeedbackBuffer == id)
321 m_transformFeedbackBuffer = 0;
322 if (m_uniformBuffer == id)
324 if (m_atomicCounterBuffer == id)
325 m_atomicCounterBuffer = 0;
326 if (m_dispatchIndirectBuffer == id)
327 m_dispatchIndirectBuffer = 0;
328 if (m_drawIndirectBuffer == id)
329 m_drawIndirectBuffer = 0;
330 if (m_shaderStorageBuffer == id)
331 m_shaderStorageBuffer = 0;
334 int GLClientState::bindBuffer(GLenum target, GLuint id)
338 case GL_ARRAY_BUFFER:
341 case GL_ELEMENT_ARRAY_BUFFER:
342 m_currVaoState.iboId() = id;
344 case GL_COPY_READ_BUFFER:
345 m_copyReadBuffer = id;
347 case GL_COPY_WRITE_BUFFER:
348 m_copyWriteBuffer = id;
350 case GL_PIXEL_PACK_BUFFER:
351 m_pixelPackBuffer = id;
353 case GL_PIXEL_UNPACK_BUFFER:
354 m_pixelUnpackBuffer = id;
356 case GL_TRANSFORM_FEEDBACK_BUFFER:
357 m_transformFeedbackBuffer = id;
359 case GL_UNIFORM_BUFFER:
360 m_uniformBuffer = id;
362 case GL_ATOMIC_COUNTER_BUFFER:
363 m_atomicCounterBuffer = id;
365 case GL_DISPATCH_INDIRECT_BUFFER:
366 m_dispatchIndirectBuffer = id;
368 case GL_DRAW_INDIRECT_BUFFER:
369 m_drawIndirectBuffer = id;
371 case GL_SHADER_STORAGE_BUFFER:
372 m_shaderStorageBuffer = id;
380 void GLClientState::bindIndexedBuffer(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size, GLintptr stride, GLintptr effectiveStride) {
382 case GL_TRANSFORM_FEEDBACK_BUFFER:
383 m_indexedTransformFeedbackBuffers[index].buffer = buffer;
384 m_indexedTransformFeedbackBuffers[index].offset = offset;
385 m_indexedTransformFeedbackBuffers[index].size = size;
386 m_indexedTransformFeedbackBuffers[index].stride = stride;
388 case GL_UNIFORM_BUFFER:
389 m_indexedUniformBuffers[index].buffer = buffer;
390 m_indexedUniformBuffers[index].offset = offset;
391 m_indexedUniformBuffers[index].size = size;
392 m_indexedUniformBuffers[index].stride = stride;
394 case GL_ATOMIC_COUNTER_BUFFER:
395 m_indexedAtomicCounterBuffers[index].buffer = buffer;
396 m_indexedAtomicCounterBuffers[index].offset = offset;
397 m_indexedAtomicCounterBuffers[index].size = size;
398 m_indexedAtomicCounterBuffers[index].stride = stride;
400 case GL_SHADER_STORAGE_BUFFER:
401 m_indexedShaderStorageBuffers[index].buffer = buffer;
402 m_indexedShaderStorageBuffers[index].offset = offset;
403 m_indexedShaderStorageBuffers[index].size = size;
404 m_indexedShaderStorageBuffers[index].stride = stride;
407 m_currVaoState.bufferBinding(index).buffer = buffer;
408 m_currVaoState.bufferBinding(index).offset = offset;
409 m_currVaoState.bufferBinding(index).size = size;
410 m_currVaoState.bufferBinding(index).stride = stride;
411 m_currVaoState.bufferBinding(index).effectiveStride = effectiveStride;
416 int GLClientState::getMaxIndexedBufferBindings(GLenum target) const {
418 case GL_TRANSFORM_FEEDBACK_BUFFER:
419 return m_indexedTransformFeedbackBuffers.size();
420 case GL_UNIFORM_BUFFER:
421 return m_indexedUniformBuffers.size();
422 case GL_ATOMIC_COUNTER_BUFFER:
423 return m_indexedAtomicCounterBuffers.size();
424 case GL_SHADER_STORAGE_BUFFER:
425 return m_indexedShaderStorageBuffers.size();
427 return m_currVaoState.bufferBindings_const().size();
431 int GLClientState::getBuffer(GLenum target) {
434 case GL_ARRAY_BUFFER:
437 case GL_ELEMENT_ARRAY_BUFFER:
438 ret = m_currVaoState.iboId();
440 case GL_COPY_READ_BUFFER:
441 ret = m_copyReadBuffer;
443 case GL_COPY_WRITE_BUFFER:
444 ret = m_copyWriteBuffer;
446 case GL_PIXEL_PACK_BUFFER:
447 ret = m_pixelPackBuffer;
449 case GL_PIXEL_UNPACK_BUFFER:
450 ret = m_pixelUnpackBuffer;
452 case GL_TRANSFORM_FEEDBACK_BUFFER:
453 ret = m_transformFeedbackBuffer;
455 case GL_UNIFORM_BUFFER:
456 ret = m_uniformBuffer;
458 case GL_ATOMIC_COUNTER_BUFFER:
459 ret = m_atomicCounterBuffer;
461 case GL_DISPATCH_INDIRECT_BUFFER:
462 ret = m_dispatchIndirectBuffer;
464 case GL_DRAW_INDIRECT_BUFFER:
465 ret = m_drawIndirectBuffer;
467 case GL_SHADER_STORAGE_BUFFER:
468 ret = m_shaderStorageBuffer;
476 void GLClientState::getClientStatePointer(GLenum pname, GLvoid** params)
478 GLenum which_state = -1;
480 case GL_VERTEX_ARRAY_POINTER: {
481 which_state = GLClientState::VERTEX_LOCATION;
484 case GL_NORMAL_ARRAY_POINTER: {
485 which_state = GLClientState::NORMAL_LOCATION;
488 case GL_COLOR_ARRAY_POINTER: {
489 which_state = GLClientState::COLOR_LOCATION;
492 case GL_TEXTURE_COORD_ARRAY_POINTER: {
493 which_state = getActiveTexture() + GLClientState::TEXCOORD0_LOCATION;
496 case GL_POINT_SIZE_ARRAY_POINTER_OES: {
497 which_state = GLClientState::POINTSIZE_LOCATION;
500 case GL_MATRIX_INDEX_ARRAY_POINTER_OES: {
501 which_state = GLClientState::MATRIXINDEX_LOCATION;
504 case GL_WEIGHT_ARRAY_POINTER_OES: {
505 which_state = GLClientState::WEIGHT_LOCATION;
509 if (which_state != -1)
510 *params = getState(which_state).data;
513 int GLClientState::setPixelStore(GLenum param, GLint value)
517 case GL_UNPACK_ALIGNMENT:
518 m_pixelStore.unpack_alignment = value;
520 case GL_PACK_ALIGNMENT:
521 m_pixelStore.pack_alignment = value;
523 case GL_UNPACK_ROW_LENGTH:
524 m_pixelStore.unpack_row_length = value;
526 case GL_UNPACK_IMAGE_HEIGHT:
527 m_pixelStore.unpack_image_height = value;
529 case GL_UNPACK_SKIP_PIXELS:
530 m_pixelStore.unpack_skip_pixels = value;
532 case GL_UNPACK_SKIP_ROWS:
533 m_pixelStore.unpack_skip_rows = value;
535 case GL_UNPACK_SKIP_IMAGES:
536 m_pixelStore.unpack_skip_images = value;
538 case GL_PACK_ROW_LENGTH:
539 m_pixelStore.pack_row_length = value;
541 case GL_PACK_SKIP_PIXELS:
542 m_pixelStore.pack_skip_pixels = value;
544 case GL_PACK_SKIP_ROWS:
545 m_pixelStore.pack_skip_rows = value;
548 retval = GL_INVALID_ENUM;
554 size_t GLClientState::pixelDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
556 if (width <= 0 || height <= 0 || depth <= 0) return 0;
558 ALOGV("%s: pack? %d", __FUNCTION__, pack);
560 ALOGV("%s: pack stats", __FUNCTION__);
561 ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
562 ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
563 ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
564 ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
566 ALOGV("%s: unpack stats", __FUNCTION__);
567 ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
568 ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
569 ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
570 ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
571 ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
572 ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
574 return GLESTextureUtils::computeTotalImageSize(
575 width, height, depth,
577 pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
578 pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
579 pack ? 0 : m_pixelStore.unpack_image_height,
580 pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
581 pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
582 pack ? 0 : m_pixelStore.unpack_skip_images);
585 size_t GLClientState::pboNeededDataSize(GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, int pack) const
587 if (width <= 0 || height <= 0 || depth <= 0) return 0;
589 ALOGV("%s: pack? %d", __FUNCTION__, pack);
591 ALOGV("%s: pack stats", __FUNCTION__);
592 ALOGV("%s: pack align %d", __FUNCTION__, m_pixelStore.pack_alignment);
593 ALOGV("%s: pack rowlen %d", __FUNCTION__, m_pixelStore.pack_row_length);
594 ALOGV("%s: pack skippixels %d", __FUNCTION__, m_pixelStore.pack_skip_pixels);
595 ALOGV("%s: pack skiprows %d", __FUNCTION__, m_pixelStore.pack_skip_rows);
597 ALOGV("%s: unpack stats", __FUNCTION__);
598 ALOGV("%s: unpack align %d", __FUNCTION__, m_pixelStore.unpack_alignment);
599 ALOGV("%s: unpack rowlen %d", __FUNCTION__, m_pixelStore.unpack_row_length);
600 ALOGV("%s: unpack imgheight %d", __FUNCTION__, m_pixelStore.unpack_image_height);
601 ALOGV("%s: unpack skippixels %d", __FUNCTION__, m_pixelStore.unpack_skip_pixels);
602 ALOGV("%s: unpack skiprows %d", __FUNCTION__, m_pixelStore.unpack_skip_rows);
603 ALOGV("%s: unpack skipimages %d", __FUNCTION__, m_pixelStore.unpack_skip_images);
605 return GLESTextureUtils::computeNeededBufferSize(
606 width, height, depth,
608 pack ? m_pixelStore.pack_alignment : m_pixelStore.unpack_alignment,
609 pack ? m_pixelStore.pack_row_length : m_pixelStore.unpack_row_length,
610 pack ? 0 : m_pixelStore.unpack_image_height,
611 pack ? m_pixelStore.pack_skip_pixels : m_pixelStore.unpack_skip_pixels,
612 pack ? m_pixelStore.pack_skip_rows : m_pixelStore.unpack_skip_rows,
613 pack ? 0 : m_pixelStore.unpack_skip_images);
617 size_t GLClientState::clearBufferNumElts(GLenum buffer) const
629 void GLClientState::setNumActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex, GLint numActiveUniforms) {
630 UniformBlockInfoKey key;
631 key.program = program;
632 key.uniformBlockIndex = uniformBlockIndex;
634 UniformBlockUniformInfo info;
635 info.numActiveUniforms = (size_t)numActiveUniforms;
637 m_uniformBlockInfoMap[key] = info;
640 size_t GLClientState::numActiveUniformsInUniformBlock(GLuint program, GLuint uniformBlockIndex) const {
641 UniformBlockInfoKey key;
642 key.program = program;
643 key.uniformBlockIndex = uniformBlockIndex;
644 UniformBlockInfoMap::const_iterator it =
645 m_uniformBlockInfoMap.find(key);
646 if (it == m_uniformBlockInfoMap.end()) return 0;
647 return it->second.numActiveUniforms;
650 void GLClientState::associateProgramWithPipeline(GLuint program, GLuint pipeline) {
651 m_programPipelines[program] = pipeline;
654 GLClientState::ProgramPipelineIterator GLClientState::programPipelineBegin() {
655 return m_programPipelines.begin();
658 GLClientState::ProgramPipelineIterator GLClientState::programPipelineEnd() {
659 return m_programPipelines.end();
662 GLenum GLClientState::setActiveTextureUnit(GLenum texture)
664 GLuint unit = texture - GL_TEXTURE0;
665 if (unit >= MAX_TEXTURE_UNITS) {
666 return GL_INVALID_ENUM;
668 m_tex.activeUnit = &m_tex.unit[unit];
672 GLenum GLClientState::getActiveTextureUnit() const
674 return GL_TEXTURE0 + (m_tex.activeUnit - &m_tex.unit[0]);
677 void GLClientState::enableTextureTarget(GLenum target)
681 m_tex.activeUnit->enables |= (1u << TEXTURE_2D);
683 case GL_TEXTURE_EXTERNAL_OES:
684 m_tex.activeUnit->enables |= (1u << TEXTURE_EXTERNAL);
689 void GLClientState::disableTextureTarget(GLenum target)
693 m_tex.activeUnit->enables &= ~(1u << TEXTURE_2D);
695 case GL_TEXTURE_EXTERNAL_OES:
696 m_tex.activeUnit->enables &= ~(1u << TEXTURE_EXTERNAL);
701 GLenum GLClientState::getPriorityEnabledTarget(GLenum allDisabled) const
703 unsigned int enables = m_tex.activeUnit->enables;
704 if (enables & (1u << TEXTURE_EXTERNAL)) {
705 return GL_TEXTURE_EXTERNAL_OES;
706 } else if (enables & (1u << TEXTURE_2D)) {
707 return GL_TEXTURE_2D;
713 int GLClientState::compareTexId(const void* pid, const void* prec)
715 const GLuint* id = (const GLuint*)pid;
716 const TextureRec* rec = (const TextureRec*)prec;
717 return (GLint)(*id) - (GLint)rec->id;
720 GLenum GLClientState::bindTexture(GLenum target, GLuint texture,
723 GLboolean first = GL_FALSE;
725 TextureRec* texrec = getTextureRec(texture);
727 texrec = addTextureRec(texture, target);
730 if (texture && target != texrec->target &&
731 (target != GL_TEXTURE_EXTERNAL_OES &&
732 texrec->target != GL_TEXTURE_EXTERNAL_OES)) {
733 ALOGD("%s: issue GL_INVALID_OPERATION: target 0x%x texrectarget 0x%x texture %u", __FUNCTION__, target, texrec->target, texture);
738 m_tex.activeUnit->texture[TEXTURE_2D] = texture;
740 case GL_TEXTURE_EXTERNAL_OES:
741 m_tex.activeUnit->texture[TEXTURE_EXTERNAL] = texture;
743 case GL_TEXTURE_CUBE_MAP:
744 m_tex.activeUnit->texture[TEXTURE_CUBE_MAP] = texture;
746 case GL_TEXTURE_2D_ARRAY:
747 m_tex.activeUnit->texture[TEXTURE_2D_ARRAY] = texture;
750 m_tex.activeUnit->texture[TEXTURE_3D] = texture;
752 case GL_TEXTURE_2D_MULTISAMPLE:
753 m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE] = texture;
764 void GLClientState::setBoundEGLImage(GLenum target, GLeglImageOES image) {
765 GLuint texture = getBoundTexture(target);
766 TextureRec* texrec = getTextureRec(texture);
768 texrec->boundEGLImage = true;
771 TextureRec* GLClientState::addTextureRec(GLuint id, GLenum target)
773 TextureRec* tex = new TextureRec;
775 tex->target = target;
777 tex->multisamples = 0;
778 tex->immutable = false;
779 tex->boundEGLImage = false;
780 tex->dims = new TextureDims;
782 (*(m_tex.textureRecs))[id] = tex;
786 TextureRec* GLClientState::getTextureRec(GLuint id) const {
787 SharedTextureDataMap::const_iterator it =
788 m_tex.textureRecs->find(id);
789 if (it == m_tex.textureRecs->end()) {
795 void GLClientState::setBoundTextureInternalFormat(GLenum target, GLint internalformat) {
796 GLuint texture = getBoundTexture(target);
797 TextureRec* texrec = getTextureRec(texture);
799 texrec->internalformat = internalformat;
802 void GLClientState::setBoundTextureFormat(GLenum target, GLenum format) {
803 GLuint texture = getBoundTexture(target);
804 TextureRec* texrec = getTextureRec(texture);
806 texrec->format = format;
809 void GLClientState::setBoundTextureType(GLenum target, GLenum type) {
810 GLuint texture = getBoundTexture(target);
811 TextureRec* texrec = getTextureRec(texture);
816 void GLClientState::setBoundTextureDims(GLenum target, GLsizei level, GLsizei width, GLsizei height, GLsizei depth) {
817 GLuint texture = getBoundTexture(target);
818 TextureRec* texrec = getTextureRec(texture);
824 GLsizei curr_width = width;
825 GLsizei curr_height = height;
826 GLsizei curr_depth = depth;
827 GLsizei curr_level = 0;
830 texrec->dims->widths[curr_level] = curr_width;
831 texrec->dims->heights[curr_level] = curr_height;
832 texrec->dims->depths[curr_level] = curr_depth;
833 if (curr_width >> 1 == 0 &&
834 curr_height >> 1 == 0 &&
835 ((target == GL_TEXTURE_3D && curr_depth == 0) ||
839 curr_width = (curr_width >> 1) ? (curr_width >> 1) : 1;
840 curr_height = (curr_height >> 1) ? (curr_height >> 1) : 1;
841 if (target == GL_TEXTURE_3D) {
842 curr_depth = (curr_depth >> 1) ? (curr_depth >> 1) : 1;
848 texrec->dims->widths[level] = width;
849 texrec->dims->heights[level] = height;
850 texrec->dims->depths[level] = depth;
854 void GLClientState::setBoundTextureSamples(GLenum target, GLsizei samples) {
855 GLuint texture = getBoundTexture(target);
856 TextureRec* texrec = getTextureRec(texture);
858 texrec->multisamples = samples;
861 void GLClientState::setBoundTextureImmutableFormat(GLenum target) {
862 GLuint texture = getBoundTexture(target);
863 TextureRec* texrec = getTextureRec(texture);
865 texrec->immutable = true;
868 bool GLClientState::isBoundTextureImmutableFormat(GLenum target) const {
869 GLuint texture = getBoundTexture(target);
870 TextureRec* texrec = getTextureRec(texture);
871 if (!texrec) return false;
872 return texrec->immutable;
875 GLuint GLClientState::getBoundTexture(GLenum target) const
879 return m_tex.activeUnit->texture[TEXTURE_2D];
880 case GL_TEXTURE_EXTERNAL_OES:
881 return m_tex.activeUnit->texture[TEXTURE_EXTERNAL];
882 case GL_TEXTURE_CUBE_MAP:
883 return m_tex.activeUnit->texture[TEXTURE_CUBE_MAP];
884 case GL_TEXTURE_2D_ARRAY:
885 return m_tex.activeUnit->texture[TEXTURE_2D_ARRAY];
887 return m_tex.activeUnit->texture[TEXTURE_3D];
888 case GL_TEXTURE_2D_MULTISAMPLE:
889 return m_tex.activeUnit->texture[TEXTURE_2D_MULTISAMPLE];
895 // BEGIN driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
896 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
898 static bool unreliableInternalFormat(GLenum internalformat) {
899 switch (internalformat) {
907 void GLClientState::writeCopyTexImageState
908 (GLenum target, GLint level, GLenum internalformat) {
909 if (unreliableInternalFormat(internalformat)) {
911 entry.id = getBoundTexture(GL_TEXTURE_2D);
912 entry.target = target;
914 entry.internalformat = internalformat;
915 m_cubeMapDefs.insert(entry);
919 static GLenum identifyPositiveCubeMapComponent(GLenum target) {
921 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
922 return GL_TEXTURE_CUBE_MAP_POSITIVE_X;
923 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
924 return GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
925 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
926 return GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
932 GLenum GLClientState::copyTexImageNeededTarget
933 (GLenum target, GLint level, GLenum internalformat) {
934 if (unreliableInternalFormat(internalformat)) {
935 GLenum positiveComponent =
936 identifyPositiveCubeMapComponent(target);
937 if (positiveComponent) {
939 query.id = getBoundTexture(GL_TEXTURE_2D);
940 query.target = positiveComponent;
942 query.internalformat = internalformat;
943 if (m_cubeMapDefs.find(query) ==
944 m_cubeMapDefs.end()) {
945 return positiveComponent;
952 GLenum GLClientState::copyTexImageLuminanceCubeMapAMDWorkaround
953 (GLenum target, GLint level, GLenum internalformat) {
954 writeCopyTexImageState(target, level, internalformat);
955 return copyTexImageNeededTarget(target, level, internalformat);
958 // (>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')><(' '<)(>' ')>
959 // END driver workarounds-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
961 void GLClientState::deleteTextures(GLsizei n, const GLuint* textures)
963 // Updating the textures array could be made more efficient when deleting
965 // - compacting the array could be done in a single pass once the deleted
966 // textures are marked, or
967 // - could swap deleted textures to the end and re-sort.
969 for (const GLuint* texture = textures; texture != textures + n; texture++) {
970 texrec = getTextureRec(*texture);
971 if (texrec && texrec->dims) {
975 m_tex.textureRecs->erase(*texture);
977 for (TextureUnit* unit = m_tex.unit;
978 unit != m_tex.unit + MAX_TEXTURE_UNITS;
981 if (unit->texture[TEXTURE_2D] == *texture) {
982 unit->texture[TEXTURE_2D] = 0;
983 } else if (unit->texture[TEXTURE_EXTERNAL] == *texture) {
984 unit->texture[TEXTURE_EXTERNAL] = 0;
991 // RBO//////////////////////////////////////////////////////////////////////////
993 void GLClientState::addFreshRenderbuffer(GLuint name) {
994 // if underlying opengl says these are fresh names,
995 // but we are keeping a stale one, reset it.
997 props.target = GL_RENDERBUFFER;
999 props.format = GL_NONE;
1000 props.multisamples = 0;
1001 props.previouslyBound = false;
1003 if (usedRenderbufferName(name)) {
1004 mRboState.rboData[getRboIndex(name)] = props;
1006 mRboState.rboData.push_back(props);
1010 void GLClientState::addRenderbuffers(GLsizei n, GLuint* renderbuffers) {
1011 for (size_t i = 0; i < n; i++) {
1012 addFreshRenderbuffer(renderbuffers[i]);
1016 size_t GLClientState::getRboIndex(GLuint name) const {
1017 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1018 if (mRboState.rboData[i].name == name) {
1025 void GLClientState::removeRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
1026 size_t bound_rbo_idx = getRboIndex(boundRboProps_const().name);
1028 std::vector<GLuint> to_remove;
1029 for (size_t i = 0; i < n; i++) {
1030 if (renderbuffers[i] != 0) { // Never remove the zero rb.
1031 to_remove.push_back(getRboIndex(renderbuffers[i]));
1035 for (size_t i = 0; i < to_remove.size(); i++) {
1036 mRboState.rboData[to_remove[i]] = mRboState.rboData.back();
1037 mRboState.rboData.pop_back();
1040 // If we just deleted the currently bound rb,
1042 if (getRboIndex(boundRboProps_const().name) != bound_rbo_idx) {
1043 bindRenderbuffer(GL_RENDERBUFFER, 0);
1047 bool GLClientState::usedRenderbufferName(GLuint name) const {
1048 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1049 if (mRboState.rboData[i].name == name) {
1056 void GLClientState::setBoundRenderbufferIndex() {
1057 for (size_t i = 0; i < mRboState.rboData.size(); i++) {
1058 if (mRboState.rboData[i].name == mRboState.boundRenderbuffer) {
1059 mRboState.boundRenderbufferIndex = i;
1065 RboProps& GLClientState::boundRboProps() {
1066 return mRboState.rboData[mRboState.boundRenderbufferIndex];
1069 const RboProps& GLClientState::boundRboProps_const() const {
1070 return mRboState.rboData[mRboState.boundRenderbufferIndex];
1073 void GLClientState::bindRenderbuffer(GLenum target, GLuint name) {
1074 // If unused, add it.
1075 if (!usedRenderbufferName(name)) {
1076 addFreshRenderbuffer(name);
1078 mRboState.boundRenderbuffer = name;
1079 setBoundRenderbufferIndex();
1080 boundRboProps().target = target;
1081 boundRboProps().previouslyBound = true;
1084 GLuint GLClientState::boundRenderbuffer() const {
1085 return boundRboProps_const().name;
1088 void GLClientState::setBoundRenderbufferFormat(GLenum format) {
1089 boundRboProps().format = format;
1092 void GLClientState::setBoundRenderbufferSamples(GLsizei samples) {
1093 boundRboProps().multisamples = samples;
1096 // FBO//////////////////////////////////////////////////////////////////////////
1100 GLenum GLClientState::queryRboFormat(GLuint rbo_name) const {
1101 return mRboState.rboData[getRboIndex(rbo_name)].format;
1104 GLsizei GLClientState::queryRboSamples(GLuint rbo_name) const {
1105 return mRboState.rboData[getRboIndex(rbo_name)].multisamples;
1108 GLint GLClientState::queryTexInternalFormat(GLuint tex_name) const {
1109 TextureRec* texrec = getTextureRec(tex_name);
1110 if (!texrec) return -1;
1111 return texrec->internalformat;
1114 GLsizei GLClientState::queryTexWidth(GLsizei level, GLuint tex_name) const {
1115 TextureRec* texrec = getTextureRec(tex_name);
1119 return texrec->dims->widths[level];
1122 GLsizei GLClientState::queryTexHeight(GLsizei level, GLuint tex_name) const {
1123 TextureRec* texrec = getTextureRec(tex_name);
1124 if (!texrec) return 0;
1125 return texrec->dims->heights[level];
1128 GLsizei GLClientState::queryTexDepth(GLsizei level, GLuint tex_name) const {
1129 TextureRec* texrec = getTextureRec(tex_name);
1130 if (!texrec) return 0;
1131 return texrec->dims->depths[level];
1134 bool GLClientState::queryTexEGLImageBacked(GLuint tex_name) const {
1135 TextureRec* texrec = getTextureRec(tex_name);
1136 if (!texrec) return false;
1137 return texrec->boundEGLImage;
1140 GLenum GLClientState::queryTexFormat(GLuint tex_name) const {
1141 TextureRec* texrec = getTextureRec(tex_name);
1142 if (!texrec) return -1;
1143 return texrec->format;
1146 GLenum GLClientState::queryTexType(GLuint tex_name) const {
1147 TextureRec* texrec = getTextureRec(tex_name);
1148 if (!texrec) return -1;
1149 return texrec->type;
1152 GLsizei GLClientState::queryTexSamples(GLuint tex_name) const {
1153 TextureRec* texrec = getTextureRec(tex_name);
1154 if (!texrec) return 0;
1155 return texrec->multisamples;
1158 GLenum GLClientState::queryTexLastBoundTarget(GLuint tex_name) const {
1159 TextureRec* texrec = getTextureRec(tex_name);
1160 if (!texrec) return GL_NONE;
1161 return texrec->target;
1164 void GLClientState::getBoundFramebufferFormat(
1166 GLenum attachment, FboFormatInfo* res_info) const {
1167 const FboProps& props = boundFboProps_const(target);
1169 res_info->type = FBO_ATTACHMENT_NONE;
1170 res_info->rb_format = GL_NONE;
1171 res_info->rb_multisamples = 0;
1172 res_info->tex_internalformat = -1;
1173 res_info->tex_format = GL_NONE;
1174 res_info->tex_type = GL_NONE;
1175 res_info->tex_multisamples = 0;
1177 int colorAttachmentIndex =
1178 glUtilsColorAttachmentIndex(attachment);
1180 if (colorAttachmentIndex != -1) {
1181 if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1182 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1183 res_info->rb_format =
1185 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1186 res_info->rb_multisamples =
1188 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1189 } else if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1190 res_info->type = FBO_ATTACHMENT_TEXTURE;
1191 res_info->tex_internalformat =
1192 queryTexInternalFormat(
1193 props.colorAttachmenti_textures[colorAttachmentIndex]);
1194 res_info->tex_format =
1196 props.colorAttachmenti_textures[colorAttachmentIndex]);
1197 res_info->tex_type =
1198 queryTexType(props.colorAttachmenti_textures[colorAttachmentIndex]);
1199 res_info->tex_multisamples =
1200 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1202 res_info->type = FBO_ATTACHMENT_NONE;
1206 switch (attachment) {
1207 case GL_DEPTH_ATTACHMENT:
1208 if (props.depthAttachment_hasRbo) {
1209 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1210 res_info->rb_format = queryRboFormat(props.depthAttachment_rbo);
1211 res_info->rb_multisamples =
1213 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1214 } else if (props.depthAttachment_hasTexObj) {
1215 res_info->type = FBO_ATTACHMENT_TEXTURE;
1216 res_info->tex_internalformat = queryTexInternalFormat(props.depthAttachment_texture);
1217 res_info->tex_format = queryTexFormat(props.depthAttachment_texture);
1218 res_info->tex_type = queryTexType(props.depthAttachment_texture);
1219 res_info->tex_multisamples =
1220 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1222 res_info->type = FBO_ATTACHMENT_NONE;
1225 case GL_STENCIL_ATTACHMENT:
1226 if (props.stencilAttachment_hasRbo) {
1227 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1228 res_info->rb_format = queryRboFormat(props.stencilAttachment_rbo);
1229 res_info->rb_multisamples =
1231 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1232 } else if (props.stencilAttachment_hasTexObj) {
1233 res_info->type = FBO_ATTACHMENT_TEXTURE;
1234 res_info->tex_internalformat = queryTexInternalFormat(props.stencilAttachment_texture);
1235 res_info->tex_format = queryTexFormat(props.stencilAttachment_texture);
1236 res_info->tex_type = queryTexType(props.stencilAttachment_texture);
1237 res_info->tex_multisamples =
1238 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1240 res_info->type = FBO_ATTACHMENT_NONE;
1243 case GL_DEPTH_STENCIL_ATTACHMENT:
1244 if (props.depthstencilAttachment_hasRbo) {
1245 res_info->type = FBO_ATTACHMENT_RENDERBUFFER;
1246 res_info->rb_format = queryRboFormat(props.depthstencilAttachment_rbo);
1247 res_info->rb_multisamples =
1249 props.colorAttachmenti_rbos[colorAttachmentIndex]);
1250 } else if (props.depthstencilAttachment_hasTexObj) {
1251 res_info->type = FBO_ATTACHMENT_TEXTURE;
1252 res_info->tex_internalformat = queryTexInternalFormat(props.depthstencilAttachment_texture);
1253 res_info->tex_format = queryTexFormat(props.depthstencilAttachment_texture);
1254 res_info->tex_type = queryTexType(props.depthstencilAttachment_texture);
1255 res_info->tex_multisamples =
1256 queryTexSamples(props.colorAttachmenti_textures[colorAttachmentIndex]);
1258 res_info->type = FBO_ATTACHMENT_NONE;
1264 FboAttachmentType GLClientState::getBoundFramebufferAttachmentType(GLenum target, GLenum attachment) const {
1266 getBoundFramebufferFormat(target, attachment, &info);
1271 int GLClientState::getMaxColorAttachments() const {
1272 return m_max_color_attachments;
1275 int GLClientState::getMaxDrawBuffers() const {
1276 return m_max_draw_buffers;
1279 void GLClientState::addFreshFramebuffer(GLuint name) {
1282 props.previouslyBound = false;
1284 props.colorAttachmenti_textures.resize(m_max_color_attachments, 0);
1285 props.depthAttachment_texture = 0;
1286 props.stencilAttachment_texture = 0;
1287 props.depthstencilAttachment_texture = 0;
1289 props.colorAttachmenti_hasTex.resize(m_max_color_attachments, false);
1290 props.depthAttachment_hasTexObj = false;
1291 props.stencilAttachment_hasTexObj = false;
1292 props.depthstencilAttachment_hasTexObj = false;
1294 props.colorAttachmenti_rbos.resize(m_max_color_attachments, 0);
1295 props.depthAttachment_rbo = 0;
1296 props.stencilAttachment_rbo = 0;
1297 props.depthstencilAttachment_rbo = 0;
1299 props.colorAttachmenti_hasRbo.resize(m_max_color_attachments, false);
1300 props.depthAttachment_hasRbo = false;
1301 props.stencilAttachment_hasRbo = false;
1302 props.depthstencilAttachment_hasRbo = false;
1303 mFboState.fboData[name] = props;
1306 void GLClientState::addFramebuffers(GLsizei n, GLuint* framebuffers) {
1307 for (size_t i = 0; i < n; i++) {
1308 addFreshFramebuffer(framebuffers[i]);
1312 void GLClientState::removeFramebuffers(GLsizei n, const GLuint* framebuffers) {
1313 for (size_t i = 0; i < n; i++) {
1314 if (framebuffers[i] != 0) { // Never remove the zero fb.
1315 if (framebuffers[i] == mFboState.boundDrawFramebuffer) {
1316 bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1318 if (framebuffers[i] == mFboState.boundReadFramebuffer) {
1319 bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1321 mFboState.fboData.erase(framebuffers[i]);
1326 bool GLClientState::usedFramebufferName(GLuint name) const {
1327 return mFboState.fboData.find(name) != mFboState.fboData.end();
1330 FboProps& GLClientState::boundFboProps(GLenum target) {
1332 case GL_DRAW_FRAMEBUFFER:
1333 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1334 case GL_READ_FRAMEBUFFER:
1335 return mFboState.fboData[mFboState.boundReadFramebuffer];
1336 case GL_FRAMEBUFFER:
1337 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1339 return mFboState.fboData[mFboState.boundDrawFramebuffer];
1342 const FboProps& GLClientState::boundFboProps_const(GLenum target) const {
1344 case GL_DRAW_FRAMEBUFFER:
1345 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1346 case GL_READ_FRAMEBUFFER:
1347 return mFboState.fboData.find(mFboState.boundReadFramebuffer)->second;
1348 case GL_FRAMEBUFFER:
1349 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1351 return mFboState.fboData.find(mFboState.boundDrawFramebuffer)->second;
1354 void GLClientState::bindFramebuffer(GLenum target, GLuint name) {
1355 // If unused, add it.
1356 if (!usedFramebufferName(name)) {
1357 addFreshFramebuffer(name);
1360 case GL_DRAW_FRAMEBUFFER:
1361 mFboState.boundDrawFramebuffer = name;
1363 case GL_READ_FRAMEBUFFER:
1364 mFboState.boundReadFramebuffer = name;
1366 default: // case GL_FRAMEBUFFER:
1367 mFboState.boundDrawFramebuffer = name;
1368 mFboState.boundReadFramebuffer = name;
1371 boundFboProps(target).previouslyBound = true;
1374 void GLClientState::setCheckFramebufferStatus(GLenum target, GLenum status) {
1376 case GL_DRAW_FRAMEBUFFER:
1377 mFboState.drawFboCheckStatus = status;
1379 case GL_READ_FRAMEBUFFER:
1380 mFboState.readFboCheckStatus = status;
1382 case GL_FRAMEBUFFER:
1383 mFboState.drawFboCheckStatus = status;
1388 GLenum GLClientState::getCheckFramebufferStatus(GLenum target) const {
1390 case GL_DRAW_FRAMEBUFFER:
1391 return mFboState.drawFboCheckStatus;
1392 case GL_READ_FRAMEBUFFER:
1393 return mFboState.readFboCheckStatus;
1394 case GL_FRAMEBUFFER:
1395 return mFboState.drawFboCheckStatus;
1397 return mFboState.drawFboCheckStatus;
1400 GLuint GLClientState::boundFramebuffer(GLenum target) const {
1401 return boundFboProps_const(target).name;
1404 // Texture objects for FBOs/////////////////////////////////////////////////////
1406 void GLClientState::attachTextureObject(
1408 GLenum attachment, GLuint texture) {
1410 int colorAttachmentIndex =
1411 glUtilsColorAttachmentIndex(attachment);
1413 if (colorAttachmentIndex != -1) {
1414 boundFboProps(target).colorAttachmenti_textures[colorAttachmentIndex] = texture;
1415 boundFboProps(target).colorAttachmenti_hasTex[colorAttachmentIndex] = true;
1418 switch (attachment) {
1419 case GL_DEPTH_ATTACHMENT:
1420 boundFboProps(target).depthAttachment_texture = texture;
1421 boundFboProps(target).depthAttachment_hasTexObj = true;
1423 case GL_STENCIL_ATTACHMENT:
1424 boundFboProps(target).stencilAttachment_texture = texture;
1425 boundFboProps(target).stencilAttachment_hasTexObj = true;
1427 case GL_DEPTH_STENCIL_ATTACHMENT:
1428 boundFboProps(target).depthstencilAttachment_texture = texture;
1429 boundFboProps(target).depthstencilAttachment_hasTexObj = true;
1430 boundFboProps(target).stencilAttachment_texture = texture;
1431 boundFboProps(target).stencilAttachment_hasTexObj = true;
1432 boundFboProps(target).depthAttachment_texture = texture;
1433 boundFboProps(target).depthAttachment_hasTexObj = true;
1438 GLuint GLClientState::getFboAttachmentTextureId(GLenum target, GLenum attachment) const {
1439 GLuint res = 0; // conservative
1441 int colorAttachmentIndex =
1442 glUtilsColorAttachmentIndex(attachment);
1444 if (colorAttachmentIndex != -1) {
1445 res = boundFboProps_const(target).colorAttachmenti_textures[colorAttachmentIndex];
1448 switch (attachment) {
1449 case GL_DEPTH_ATTACHMENT:
1450 res = boundFboProps_const(target).depthAttachment_texture;
1452 case GL_STENCIL_ATTACHMENT:
1453 res = boundFboProps_const(target).stencilAttachment_texture;
1455 case GL_DEPTH_STENCIL_ATTACHMENT:
1456 res = boundFboProps_const(target).depthstencilAttachment_texture;
1462 // RBOs for FBOs////////////////////////////////////////////////////////////////
1464 void GLClientState::detachRbo(GLuint renderbuffer) {
1465 for (int i = 0; i < m_max_color_attachments; i++) {
1466 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1467 detachRboFromFbo(GL_READ_FRAMEBUFFER, glUtilsColorAttachmentName(i), renderbuffer);
1470 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1471 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, renderbuffer);
1473 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1474 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, renderbuffer);
1476 detachRboFromFbo(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1477 detachRboFromFbo(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, renderbuffer);
1480 void GLClientState::detachRboFromFbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1481 int colorAttachmentIndex =
1482 glUtilsColorAttachmentIndex(attachment);
1484 if (colorAttachmentIndex != -1) {
1485 if (boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] &&
1486 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] == renderbuffer) {
1487 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = 0;
1488 boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = false;
1492 switch (attachment) {
1493 case GL_DEPTH_ATTACHMENT:
1494 if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1495 boundFboProps(target).depthAttachment_hasRbo) {
1496 boundFboProps(target).depthAttachment_rbo = 0;
1497 boundFboProps(target).depthAttachment_hasRbo = false;
1500 case GL_STENCIL_ATTACHMENT:
1501 if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1502 boundFboProps(target).stencilAttachment_hasRbo) {
1503 boundFboProps(target).stencilAttachment_rbo = 0;
1504 boundFboProps(target).stencilAttachment_hasRbo = false;
1507 case GL_DEPTH_STENCIL_ATTACHMENT:
1508 if (boundFboProps(target).depthAttachment_rbo == renderbuffer &&
1509 boundFboProps(target).depthAttachment_hasRbo) {
1510 boundFboProps(target).depthAttachment_rbo = 0;
1511 boundFboProps(target).depthAttachment_hasRbo = false;
1513 if (boundFboProps(target).stencilAttachment_rbo == renderbuffer &&
1514 boundFboProps(target).stencilAttachment_hasRbo) {
1515 boundFboProps(target).stencilAttachment_rbo = 0;
1516 boundFboProps(target).stencilAttachment_hasRbo = false;
1518 if (boundFboProps(target).depthstencilAttachment_rbo == renderbuffer &&
1519 boundFboProps(target).depthstencilAttachment_hasRbo) {
1520 boundFboProps(target).depthstencilAttachment_rbo = 0;
1521 boundFboProps(target).depthstencilAttachment_hasRbo = false;
1527 void GLClientState::attachRbo(GLenum target, GLenum attachment, GLuint renderbuffer) {
1529 int colorAttachmentIndex =
1530 glUtilsColorAttachmentIndex(attachment);
1532 if (colorAttachmentIndex != -1) {
1533 boundFboProps(target).colorAttachmenti_rbos[colorAttachmentIndex] = renderbuffer;
1534 boundFboProps(target).colorAttachmenti_hasRbo[colorAttachmentIndex] = true;
1537 switch (attachment) {
1538 case GL_DEPTH_ATTACHMENT:
1539 boundFboProps(target).depthAttachment_rbo = renderbuffer;
1540 boundFboProps(target).depthAttachment_hasRbo = true;
1542 case GL_STENCIL_ATTACHMENT:
1543 boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1544 boundFboProps(target).stencilAttachment_hasRbo = true;
1546 case GL_DEPTH_STENCIL_ATTACHMENT:
1547 boundFboProps(target).depthAttachment_rbo = renderbuffer;
1548 boundFboProps(target).depthAttachment_hasRbo = true;
1549 boundFboProps(target).stencilAttachment_rbo = renderbuffer;
1550 boundFboProps(target).stencilAttachment_hasRbo = true;
1551 boundFboProps(target).depthstencilAttachment_rbo = renderbuffer;
1552 boundFboProps(target).depthstencilAttachment_hasRbo = true;
1557 GLuint GLClientState::getFboAttachmentRboId(GLenum target, GLenum attachment) const {
1558 GLuint res = 0; // conservative
1560 int colorAttachmentIndex =
1561 glUtilsColorAttachmentIndex(attachment);
1563 if (colorAttachmentIndex != -1) {
1564 res = boundFboProps_const(target).colorAttachmenti_rbos[colorAttachmentIndex];
1567 switch (attachment) {
1568 case GL_DEPTH_ATTACHMENT:
1569 res = boundFboProps_const(target).depthAttachment_rbo;
1571 case GL_STENCIL_ATTACHMENT:
1572 res = boundFboProps_const(target).stencilAttachment_rbo;
1574 case GL_DEPTH_STENCIL_ATTACHMENT:
1575 res = boundFboProps_const(target).depthstencilAttachment_rbo;
1581 bool GLClientState::attachmentHasObject(GLenum target, GLenum attachment) const {
1582 bool res = true; // liberal
1584 int colorAttachmentIndex =
1585 glUtilsColorAttachmentIndex(attachment);
1587 if (colorAttachmentIndex != -1) {
1588 res = boundFboProps_const(target).colorAttachmenti_hasTex[colorAttachmentIndex] ||
1589 boundFboProps_const(target).colorAttachmenti_hasRbo[colorAttachmentIndex];
1592 switch (attachment) {
1593 case GL_DEPTH_ATTACHMENT:
1594 res = (boundFboProps_const(target).depthAttachment_hasTexObj) ||
1595 (boundFboProps_const(target).depthAttachment_hasRbo);
1597 case GL_STENCIL_ATTACHMENT:
1598 res = (boundFboProps_const(target).stencilAttachment_hasTexObj) ||
1599 (boundFboProps_const(target).stencilAttachment_hasRbo);
1601 case GL_DEPTH_STENCIL_ATTACHMENT:
1602 res = (boundFboProps_const(target).depthstencilAttachment_hasTexObj) ||
1603 (boundFboProps_const(target).depthstencilAttachment_hasRbo);
1609 GLuint GLClientState::objectOfAttachment(GLenum target, GLenum attachment) const {
1610 const FboProps& props = boundFboProps_const(target);
1612 int colorAttachmentIndex =
1613 glUtilsColorAttachmentIndex(attachment);
1615 if (colorAttachmentIndex != -1) {
1616 if (props.colorAttachmenti_hasTex[colorAttachmentIndex]) {
1617 return props.colorAttachmenti_textures[colorAttachmentIndex];
1618 } else if (props.colorAttachmenti_hasRbo[colorAttachmentIndex]) {
1619 return props.colorAttachmenti_rbos[colorAttachmentIndex];
1625 switch (attachment) {
1626 case GL_DEPTH_ATTACHMENT:
1627 if (props.depthAttachment_hasTexObj) {
1628 return props.depthAttachment_texture;
1629 } else if (props.depthAttachment_hasRbo) {
1630 return props.depthAttachment_rbo;
1635 case GL_STENCIL_ATTACHMENT:
1636 if (props.stencilAttachment_hasTexObj) {
1637 return props.stencilAttachment_texture;
1638 } else if (props.stencilAttachment_hasRbo) {
1639 return props.stencilAttachment_rbo;
1643 case GL_DEPTH_STENCIL_ATTACHMENT:
1644 if (props.depthstencilAttachment_hasTexObj) {
1645 return props.depthstencilAttachment_texture;
1646 } else if (props.depthstencilAttachment_hasRbo) {
1647 return props.depthstencilAttachment_rbo;
1656 void GLClientState::setTransformFeedbackActiveUnpaused(bool activeUnpaused) {
1657 m_transformFeedbackActiveUnpaused = activeUnpaused;
1660 bool GLClientState::getTransformFeedbackActiveUnpaused() const {
1661 return m_transformFeedbackActiveUnpaused;
1664 void GLClientState::setTextureData(SharedTextureDataMap* sharedTexData) {
1665 m_tex.textureRecs = sharedTexData;
1668 void GLClientState::fromMakeCurrent() {
1669 if (mFboState.fboData.find(0) == mFboState.fboData.end()) {
1670 addFreshFramebuffer(0);
1672 FboProps& default_fb_props = mFboState.fboData[0];
1673 default_fb_props.colorAttachmenti_hasRbo[0] = true;
1674 default_fb_props.depthAttachment_hasRbo = true;
1675 default_fb_props.stencilAttachment_hasRbo = true;
1676 default_fb_props.depthstencilAttachment_hasRbo = true;
1679 void GLClientState::initFromCaps(
1680 int max_transform_feedback_separate_attribs,
1681 int max_uniform_buffer_bindings,
1682 int max_atomic_counter_buffer_bindings,
1683 int max_shader_storage_buffer_bindings,
1684 int max_vertex_attrib_bindings,
1685 int max_color_attachments,
1686 int max_draw_buffers) {
1688 m_max_vertex_attrib_bindings = max_vertex_attrib_bindings;
1690 if (m_glesMajorVersion >= 3) {
1691 m_max_transform_feedback_separate_attribs = max_transform_feedback_separate_attribs;
1692 m_max_uniform_buffer_bindings = max_uniform_buffer_bindings;
1693 m_max_atomic_counter_buffer_bindings = max_atomic_counter_buffer_bindings;
1694 m_max_shader_storage_buffer_bindings = max_shader_storage_buffer_bindings;
1696 if (m_max_transform_feedback_separate_attribs)
1697 m_indexedTransformFeedbackBuffers.resize(m_max_transform_feedback_separate_attribs);
1698 if (m_max_uniform_buffer_bindings)
1699 m_indexedUniformBuffers.resize(m_max_uniform_buffer_bindings);
1700 if (m_max_atomic_counter_buffer_bindings)
1701 m_indexedAtomicCounterBuffers.resize(m_max_atomic_counter_buffer_bindings);
1702 if (m_max_shader_storage_buffer_bindings)
1703 m_indexedShaderStorageBuffers.resize(m_max_shader_storage_buffer_bindings);
1705 BufferBinding buf0Binding;
1706 buf0Binding.buffer = 0;
1707 buf0Binding.offset = 0;
1708 buf0Binding.size = 0;
1709 buf0Binding.stride = 0;
1710 buf0Binding.effectiveStride = 0;
1712 for (size_t i = 0; i < m_indexedTransformFeedbackBuffers.size(); ++i)
1713 m_indexedTransformFeedbackBuffers[i] = buf0Binding;
1714 for (size_t i = 0; i < m_indexedUniformBuffers.size(); ++i)
1715 m_indexedUniformBuffers[i] = buf0Binding;
1716 for (size_t i = 0; i < m_indexedAtomicCounterBuffers.size(); ++i)
1717 m_indexedAtomicCounterBuffers[i] = buf0Binding;
1718 for (size_t i = 0; i < m_indexedShaderStorageBuffers.size(); ++i)
1719 m_indexedShaderStorageBuffers[i] = buf0Binding;
1722 m_max_color_attachments = max_color_attachments;
1723 m_max_draw_buffers = max_draw_buffers;
1725 addFreshRenderbuffer(0);
1726 addFreshFramebuffer(0);
1728 m_initialized = true;
1731 bool GLClientState::needsInitFromCaps() const {
1732 return !m_initialized;