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