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