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 17 #include "GL2Encoder.h" 18 #include <assert.h> 19 #include <ctype.h> 20 21 #include <GLES2/gl2.h> 22 #include <GLES2/gl2ext.h> 23 #include <GLES2/gl2platform.h> 24 25 #include <GLES3/gl3.h> 26 27 #ifndef MIN 28 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 29 #endif 30 31 static GLubyte *gVendorString= (GLubyte *) "Android"; 32 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 2.0"; 33 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES 2.0"; 34 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external "; 35 36 #define SET_ERROR_IF(condition,err) if((condition)) { \ 37 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ 38 ctx->setError(err); \ 39 return; \ 40 } 41 42 43 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \ 44 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ 45 ctx->setError(err); \ 46 return ret; \ 47 } 48 49 50 GL2Encoder::GL2Encoder(IOStream *stream, ChecksumCalculator *protocol) 51 : gl2_encoder_context_t(stream, protocol) 52 { 53 m_initialized = false; 54 m_state = NULL; 55 m_error = GL_NO_ERROR; 56 m_num_compressedTextureFormats = 0; 57 m_max_cubeMapTextureSize = 0; 58 m_max_renderBufferSize = 0; 59 m_max_textureSize = 0; 60 m_compressedTextureFormats = NULL; 61 62 //overrides 63 #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name 64 65 OVERRIDE(glFlush); 66 OVERRIDE(glPixelStorei); 67 OVERRIDE(glGetString); 68 OVERRIDE(glBindBuffer); 69 OVERRIDE(glBufferData); 70 OVERRIDE(glBufferSubData); 71 OVERRIDE(glDeleteBuffers); 72 OVERRIDE(glDrawArrays); 73 OVERRIDE(glDrawElements); 74 OVERRIDE(glGetIntegerv); 75 OVERRIDE(glGetFloatv); 76 OVERRIDE(glGetBooleanv); 77 OVERRIDE(glVertexAttribPointer); 78 OVERRIDE(glEnableVertexAttribArray); 79 OVERRIDE(glDisableVertexAttribArray); 80 OVERRIDE(glGetVertexAttribiv); 81 OVERRIDE(glGetVertexAttribfv); 82 OVERRIDE(glGetVertexAttribPointerv); 83 84 this->glShaderBinary = &s_glShaderBinary; 85 this->glShaderSource = &s_glShaderSource; 86 this->glFinish = &s_glFinish; 87 88 OVERRIDE(glGetError); 89 OVERRIDE(glLinkProgram); 90 OVERRIDE(glDeleteProgram); 91 OVERRIDE(glGetUniformiv); 92 OVERRIDE(glGetUniformfv); 93 OVERRIDE(glCreateProgram); 94 OVERRIDE(glCreateShader); 95 OVERRIDE(glDeleteShader); 96 OVERRIDE(glAttachShader); 97 OVERRIDE(glDetachShader); 98 OVERRIDE(glGetAttachedShaders); 99 OVERRIDE(glGetShaderSource); 100 OVERRIDE(glGetShaderInfoLog); 101 OVERRIDE(glGetProgramInfoLog); 102 103 OVERRIDE(glGetUniformLocation); 104 OVERRIDE(glUseProgram); 105 106 OVERRIDE(glUniform1f); 107 OVERRIDE(glUniform1fv); 108 OVERRIDE(glUniform1i); 109 OVERRIDE(glUniform1iv); 110 OVERRIDE(glUniform2f); 111 OVERRIDE(glUniform2fv); 112 OVERRIDE(glUniform2i); 113 OVERRIDE(glUniform2iv); 114 OVERRIDE(glUniform3f); 115 OVERRIDE(glUniform3fv); 116 OVERRIDE(glUniform3i); 117 OVERRIDE(glUniform3iv); 118 OVERRIDE(glUniform4f); 119 OVERRIDE(glUniform4fv); 120 OVERRIDE(glUniform4i); 121 OVERRIDE(glUniform4iv); 122 OVERRIDE(glUniformMatrix2fv); 123 OVERRIDE(glUniformMatrix3fv); 124 OVERRIDE(glUniformMatrix4fv); 125 126 OVERRIDE(glActiveTexture); 127 OVERRIDE(glBindTexture); 128 OVERRIDE(glDeleteTextures); 129 OVERRIDE(glGetTexParameterfv); 130 OVERRIDE(glGetTexParameteriv); 131 OVERRIDE(glTexParameterf); 132 OVERRIDE(glTexParameterfv); 133 OVERRIDE(glTexParameteri); 134 OVERRIDE(glTexParameteriv); 135 OVERRIDE(glTexImage2D); 136 OVERRIDE(glTexSubImage2D); 137 OVERRIDE(glCopyTexImage2D); 138 139 OVERRIDE(glGenRenderbuffers); 140 OVERRIDE(glDeleteRenderbuffers); 141 OVERRIDE(glBindRenderbuffer); 142 OVERRIDE(glRenderbufferStorage); 143 OVERRIDE(glFramebufferRenderbuffer); 144 145 OVERRIDE(glGenFramebuffers); 146 OVERRIDE(glDeleteFramebuffers); 147 OVERRIDE(glBindFramebuffer); 148 OVERRIDE(glFramebufferTexture2D); 149 OVERRIDE(glFramebufferTexture3DOES); 150 OVERRIDE(glGetFramebufferAttachmentParameteriv); 151 152 OVERRIDE(glCheckFramebufferStatus); 153 } 154 155 GL2Encoder::~GL2Encoder() 156 { 157 delete m_compressedTextureFormats; 158 } 159 160 GLenum GL2Encoder::s_glGetError(void * self) 161 { 162 GL2Encoder *ctx = (GL2Encoder *)self; 163 GLenum err = ctx->getError(); 164 if(err != GL_NO_ERROR) { 165 ctx->setError(GL_NO_ERROR); 166 return err; 167 } 168 169 return ctx->m_glGetError_enc(self); 170 171 } 172 173 void GL2Encoder::s_glFlush(void *self) 174 { 175 GL2Encoder *ctx = (GL2Encoder *) self; 176 ctx->m_glFlush_enc(self); 177 ctx->m_stream->flush(); 178 } 179 180 const GLubyte *GL2Encoder::s_glGetString(void *self, GLenum name) 181 { 182 (void)self; 183 184 GLubyte *retval = (GLubyte *) ""; 185 switch(name) { 186 case GL_VENDOR: 187 retval = gVendorString; 188 break; 189 case GL_RENDERER: 190 retval = gRendererString; 191 break; 192 case GL_VERSION: 193 retval = gVersionString; 194 break; 195 case GL_EXTENSIONS: 196 retval = gExtensionsString; 197 break; 198 } 199 return retval; 200 } 201 202 void GL2Encoder::s_glPixelStorei(void *self, GLenum param, GLint value) 203 { 204 GL2Encoder *ctx = (GL2Encoder *)self; 205 ctx->m_glPixelStorei_enc(ctx, param, value); 206 assert(ctx->m_state != NULL); 207 ctx->m_state->setPixelStore(param, value); 208 } 209 210 211 void GL2Encoder::s_glBindBuffer(void *self, GLenum target, GLuint id) 212 { 213 GL2Encoder *ctx = (GL2Encoder *) self; 214 assert(ctx->m_state != NULL); 215 ctx->m_state->bindBuffer(target, id); 216 // TODO set error state if needed; 217 ctx->m_glBindBuffer_enc(self, target, id); 218 } 219 220 void GL2Encoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) 221 { 222 GL2Encoder *ctx = (GL2Encoder *) self; 223 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM); 224 GLuint bufferId = ctx->m_state->getBuffer(target); 225 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 226 SET_ERROR_IF(size<0, GL_INVALID_VALUE); 227 228 ctx->m_shared->updateBufferData(bufferId, size, (void*)data); 229 ctx->m_glBufferData_enc(self, target, size, data, usage); 230 } 231 232 void GL2Encoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) 233 { 234 GL2Encoder *ctx = (GL2Encoder *) self; 235 SET_ERROR_IF(!(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER), GL_INVALID_ENUM); 236 GLuint bufferId = ctx->m_state->getBuffer(target); 237 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 238 239 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data); 240 SET_ERROR_IF(res, res); 241 242 ctx->m_glBufferSubData_enc(self, target, offset, size, data); 243 } 244 245 void GL2Encoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers) 246 { 247 GL2Encoder *ctx = (GL2Encoder *) self; 248 SET_ERROR_IF(n<0, GL_INVALID_VALUE); 249 for (int i=0; i<n; i++) { 250 ctx->m_shared->deleteBufferData(buffers[i]); 251 ctx->m_state->unBindBuffer(buffers[i]); 252 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]); 253 } 254 } 255 256 static bool isValidVertexAttribIndex(void *self, GLuint indx) 257 { 258 GL2Encoder *ctx = (GL2Encoder *) self; 259 GLint maxIndex; 260 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); 261 return indx < maxIndex; 262 } 263 264 static bool isValidVertexAttribType(GLenum type) 265 { 266 bool retval = false; 267 switch (type) { 268 case GL_BYTE: 269 case GL_UNSIGNED_BYTE: 270 case GL_SHORT: 271 case GL_UNSIGNED_SHORT: 272 case GL_FIXED: 273 case GL_FLOAT: 274 // The following are technically only available if certain GLES2 extensions are. 275 // However, they are supported by desktop GL3, which is a reasonable requirement 276 // for the desktop GL version. Therefore, consider them valid. 277 case GL_INT: 278 case GL_UNSIGNED_INT: 279 case GL_HALF_FLOAT_OES: 280 retval = true; 281 break; 282 } 283 return retval; 284 } 285 286 void GL2Encoder::s_glVertexAttribPointer(void *self, GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * ptr) 287 { 288 GL2Encoder *ctx = (GL2Encoder *)self; 289 assert(ctx->m_state != NULL); 290 SET_ERROR_IF(!isValidVertexAttribIndex(self, indx), GL_INVALID_VALUE); 291 SET_ERROR_IF((size < 1 || size > 4), GL_INVALID_VALUE); 292 SET_ERROR_IF(!isValidVertexAttribType(type), GL_INVALID_ENUM); 293 SET_ERROR_IF(stride < 0, GL_INVALID_VALUE); 294 ctx->m_state->setState(indx, size, type, normalized, stride, ptr); 295 } 296 297 void GL2Encoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr) 298 { 299 GL2Encoder *ctx = (GL2Encoder *) self; 300 assert(ctx->m_state != NULL); 301 GLClientState* state = ctx->m_state; 302 303 switch (param) { 304 case GL_NUM_SHADER_BINARY_FORMATS: 305 *ptr = 0; 306 break; 307 case GL_SHADER_BINARY_FORMATS: 308 // do nothing 309 break; 310 311 case GL_COMPRESSED_TEXTURE_FORMATS: { 312 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); 313 if (ctx->m_num_compressedTextureFormats > 0 && 314 compressedTextureFormats != NULL) { 315 memcpy(ptr, compressedTextureFormats, 316 ctx->m_num_compressedTextureFormats * sizeof(GLint)); 317 } 318 break; 319 } 320 321 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 322 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 323 case GL_MAX_TEXTURE_IMAGE_UNITS: 324 ctx->m_glGetIntegerv_enc(self, param, ptr); 325 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS); 326 break; 327 328 case GL_TEXTURE_BINDING_2D: 329 *ptr = state->getBoundTexture(GL_TEXTURE_2D); 330 break; 331 case GL_TEXTURE_BINDING_EXTERNAL_OES: 332 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); 333 break; 334 335 case GL_MAX_VERTEX_ATTRIBS: 336 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) { 337 ctx->m_glGetIntegerv_enc(self, param, ptr); 338 ctx->m_state->setMaxVertexAttribs(*ptr); 339 } 340 break; 341 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: 342 if (ctx->m_max_cubeMapTextureSize != 0) { 343 *ptr = ctx->m_max_cubeMapTextureSize; 344 } else { 345 ctx->m_glGetIntegerv_enc(self, param, ptr); 346 ctx->m_max_cubeMapTextureSize = *ptr; 347 } 348 break; 349 case GL_MAX_RENDERBUFFER_SIZE: 350 if (ctx->m_max_renderBufferSize != 0) { 351 *ptr = ctx->m_max_renderBufferSize; 352 } else { 353 ctx->m_glGetIntegerv_enc(self, param, ptr); 354 ctx->m_max_renderBufferSize = *ptr; 355 } 356 break; 357 case GL_MAX_TEXTURE_SIZE: 358 if (ctx->m_max_textureSize != 0) { 359 *ptr = ctx->m_max_textureSize; 360 } else { 361 ctx->m_glGetIntegerv_enc(self, param, ptr); 362 ctx->m_max_textureSize = *ptr; 363 } 364 break; 365 default: 366 if (!ctx->m_state->getClientStateParameter<GLint>(param, ptr)) { 367 ctx->m_glGetIntegerv_enc(self, param, ptr); 368 } 369 break; 370 } 371 } 372 373 374 void GL2Encoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr) 375 { 376 GL2Encoder *ctx = (GL2Encoder *)self; 377 assert(ctx->m_state != NULL); 378 GLClientState* state = ctx->m_state; 379 380 switch (param) { 381 case GL_NUM_SHADER_BINARY_FORMATS: 382 *ptr = 0; 383 break; 384 case GL_SHADER_BINARY_FORMATS: 385 // do nothing 386 break; 387 388 case GL_COMPRESSED_TEXTURE_FORMATS: { 389 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); 390 if (ctx->m_num_compressedTextureFormats > 0 && 391 compressedTextureFormats != NULL) { 392 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { 393 ptr[i] = (GLfloat) compressedTextureFormats[i]; 394 } 395 } 396 break; 397 } 398 399 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: 400 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: 401 case GL_MAX_TEXTURE_IMAGE_UNITS: 402 ctx->m_glGetFloatv_enc(self, param, ptr); 403 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS); 404 break; 405 406 case GL_TEXTURE_BINDING_2D: 407 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D); 408 break; 409 case GL_TEXTURE_BINDING_EXTERNAL_OES: 410 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); 411 break; 412 413 default: 414 if (!ctx->m_state->getClientStateParameter<GLfloat>(param, ptr)) { 415 ctx->m_glGetFloatv_enc(self, param, ptr); 416 } 417 break; 418 } 419 } 420 421 422 void GL2Encoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr) 423 { 424 GL2Encoder *ctx = (GL2Encoder *)self; 425 assert(ctx->m_state != NULL); 426 GLClientState* state = ctx->m_state; 427 428 switch (param) { 429 case GL_NUM_SHADER_BINARY_FORMATS: 430 *ptr = GL_FALSE; 431 break; 432 case GL_SHADER_BINARY_FORMATS: 433 // do nothing 434 break; 435 436 case GL_COMPRESSED_TEXTURE_FORMATS: { 437 GLint *compressedTextureFormats = ctx->getCompressedTextureFormats(); 438 if (ctx->m_num_compressedTextureFormats > 0 && 439 compressedTextureFormats != NULL) { 440 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { 441 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE; 442 } 443 } 444 break; 445 } 446 447 case GL_TEXTURE_BINDING_2D: 448 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE; 449 break; 450 case GL_TEXTURE_BINDING_EXTERNAL_OES: 451 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0 452 ? GL_TRUE : GL_FALSE; 453 break; 454 455 default: 456 if (!ctx->m_state->getClientStateParameter<GLboolean>(param, ptr)) { 457 ctx->m_glGetBooleanv_enc(self, param, ptr); 458 } 459 *ptr = (*ptr != 0) ? GL_TRUE : GL_FALSE; 460 break; 461 } 462 } 463 464 465 void GL2Encoder::s_glEnableVertexAttribArray(void *self, GLuint index) 466 { 467 GL2Encoder *ctx = (GL2Encoder *)self; 468 assert(ctx->m_state); 469 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE); 470 ctx->m_state->enable(index, 1); 471 } 472 473 void GL2Encoder::s_glDisableVertexAttribArray(void *self, GLuint index) 474 { 475 GL2Encoder *ctx = (GL2Encoder *)self; 476 assert(ctx->m_state); 477 SET_ERROR_IF(!isValidVertexAttribIndex(self, index), GL_INVALID_VALUE); 478 ctx->m_state->enable(index, 0); 479 } 480 481 482 void GL2Encoder::s_glGetVertexAttribiv(void *self, GLuint index, GLenum pname, GLint *params) 483 { 484 GL2Encoder *ctx = (GL2Encoder *)self; 485 assert(ctx->m_state); 486 GLint maxIndex; 487 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); 488 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); 489 490 if (!ctx->m_state->getVertexAttribParameter<GLint>(index, pname, params)) { 491 ctx->m_glGetVertexAttribiv_enc(self, index, pname, params); 492 } 493 } 494 495 void GL2Encoder::s_glGetVertexAttribfv(void *self, GLuint index, GLenum pname, GLfloat *params) 496 { 497 GL2Encoder *ctx = (GL2Encoder *)self; 498 assert(ctx->m_state); 499 GLint maxIndex; 500 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); 501 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); 502 503 if (!ctx->m_state->getVertexAttribParameter<GLfloat>(index, pname, params)) { 504 ctx->m_glGetVertexAttribfv_enc(self, index, pname, params); 505 } 506 } 507 508 void GL2Encoder::s_glGetVertexAttribPointerv(void *self, GLuint index, GLenum pname, GLvoid **pointer) 509 { 510 GL2Encoder *ctx = (GL2Encoder *)self; 511 if (ctx->m_state == NULL) return; 512 GLint maxIndex; 513 ctx->glGetIntegerv(self, GL_MAX_VERTEX_ATTRIBS, &maxIndex); 514 SET_ERROR_IF(!(index < maxIndex), GL_INVALID_VALUE); 515 SET_ERROR_IF(pname != GL_VERTEX_ATTRIB_ARRAY_POINTER, GL_INVALID_ENUM); 516 (void)pname; 517 518 const GLClientState::VertexAttribState *va_state = ctx->m_state->getState(index); 519 if (va_state != NULL) { 520 *pointer = va_state->data; 521 } 522 } 523 524 525 void GL2Encoder::sendVertexAttributes(GLint first, GLsizei count) 526 { 527 assert(m_state); 528 529 GLuint lastBoundVbo = m_state->currentArrayVbo(); 530 for (int i = 0; i < m_state->nLocations(); i++) { 531 bool enableDirty; 532 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty); 533 534 if (!state) { 535 continue; 536 } 537 538 if (!enableDirty && !state->enabled) { 539 continue; 540 } 541 542 if (state->enabled) { 543 if (lastBoundVbo != state->bufferObject) { 544 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject); 545 lastBoundVbo = state->bufferObject; 546 } 547 548 unsigned int datalen = state->elementSize * count; 549 int stride = state->stride == 0 ? state->elementSize : state->stride; 550 int firstIndex = stride * first; 551 552 if (state->bufferObject == 0) { 553 m_glEnableVertexAttribArray_enc(this, i); 554 this->glVertexAttribPointerData(this, i, state->size, state->type, state->normalized, state->stride, 555 (unsigned char *)state->data + firstIndex, datalen); 556 } else { 557 const BufferData* buf = m_shared->getBufferData(state->bufferObject); 558 // The following expression actually means bufLen = stride*count; 559 // But the last element doesn't have to fill up the whole stride. 560 // So it becomes the current form. 561 unsigned int bufLen = stride * (count - 1) + state->elementSize; 562 if (buf && firstIndex >= 0 && firstIndex + bufLen <= buf->m_size) { 563 m_glEnableVertexAttribArray_enc(this, i); 564 this->glVertexAttribPointerOffset(this, i, state->size, state->type, state->normalized, state->stride, 565 (uintptr_t) state->data + firstIndex); 566 } else { 567 ALOGE("a vertex attribute index out of boundary is detected. Skipping corresponding vertex attribute."); 568 m_glDisableVertexAttribArray_enc(this, i); 569 } 570 } 571 } else { 572 this->m_glDisableVertexAttribArray_enc(this, i); 573 } 574 } 575 576 if (lastBoundVbo != m_state->currentArrayVbo()) { 577 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); 578 } 579 } 580 581 static bool isValidDrawMode(GLenum mode) 582 { 583 bool retval = false; 584 switch (mode) { 585 case GL_POINTS: 586 case GL_LINE_STRIP: 587 case GL_LINE_LOOP: 588 case GL_LINES: 589 case GL_TRIANGLE_STRIP: 590 case GL_TRIANGLE_FAN: 591 case GL_TRIANGLES: 592 retval = true; 593 } 594 return retval; 595 } 596 597 void GL2Encoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count) 598 { 599 GL2Encoder *ctx = (GL2Encoder *)self; 600 assert(ctx->m_state != NULL); 601 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); 602 SET_ERROR_IF(count < 0, GL_INVALID_VALUE); 603 604 bool has_arrays = false; 605 int nLocations = ctx->m_state->nLocations(); 606 for (int i = 0; i < nLocations; i++) { 607 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i); 608 if (state->enabled) { 609 if (state->bufferObject || state->data) { 610 has_arrays = true; 611 } 612 else { 613 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n"); 614 ctx->setError(GL_INVALID_OPERATION); 615 return; 616 } 617 } 618 } 619 620 ctx->sendVertexAttributes(first, count); 621 ctx->m_glDrawArrays_enc(ctx, mode, 0, count); 622 ctx->m_stream->flush(); 623 } 624 625 626 void GL2Encoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices) 627 { 628 629 GL2Encoder *ctx = (GL2Encoder *)self; 630 assert(ctx->m_state != NULL); 631 SET_ERROR_IF(!isValidDrawMode(mode), GL_INVALID_ENUM); 632 SET_ERROR_IF(count < 0, GL_INVALID_VALUE); 633 SET_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT), GL_INVALID_ENUM); 634 635 bool has_immediate_arrays = false; 636 bool has_indirect_arrays = false; 637 int nLocations = ctx->m_state->nLocations(); 638 GLintptr offset = 0; 639 640 for (int i = 0; i < nLocations; i++) { 641 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i); 642 if (state->enabled) { 643 if (state->bufferObject != 0) { 644 has_indirect_arrays = true; 645 } else if (state->data) { 646 has_immediate_arrays = true; 647 } else { 648 ALOGW("glDrawElements: a vertex attribute array is enabled with no data bound\n"); 649 ctx->setError(GL_INVALID_OPERATION); 650 return; 651 } 652 } 653 } 654 655 if (!has_immediate_arrays && !has_indirect_arrays) { 656 ALOGE("glDrawElements: no data bound to the command - ignoring\n"); 657 GLenum status = ctx->m_glCheckFramebufferStatus_enc(self, GL_FRAMEBUFFER); 658 SET_ERROR_IF(status != GL_FRAMEBUFFER_COMPLETE, GL_INVALID_FRAMEBUFFER_OPERATION); 659 return; 660 } 661 662 if (ctx->m_state->currentIndexVbo() != 0) { 663 offset = (GLintptr)indices; 664 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); 665 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + offset); 666 } 667 int minIndex = 0, maxIndex = 0; 668 switch(type) { 669 case GL_BYTE: 670 case GL_UNSIGNED_BYTE: 671 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex); 672 break; 673 case GL_SHORT: 674 case GL_UNSIGNED_SHORT: 675 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex); 676 break; 677 case GL_INT: 678 case GL_UNSIGNED_INT: 679 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex); 680 break; 681 default: 682 ALOGE("unsupported index buffer type %d\n", type); 683 } 684 685 bool adjustIndices = true; 686 if (ctx->m_state->currentIndexVbo() != 0) { 687 if (!has_immediate_arrays) { 688 ctx->sendVertexAttributes(0, maxIndex + 1); 689 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); 690 ctx->glDrawElementsOffset(ctx, mode, count, type, offset); 691 ctx->m_stream->flush(); 692 adjustIndices = false; 693 } else { 694 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); 695 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); 696 } 697 } 698 if (adjustIndices) { 699 void *adjustedIndices = (void*)indices; 700 701 if (minIndex != 0) { 702 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 703 switch(type) { 704 case GL_BYTE: 705 case GL_UNSIGNED_BYTE: 706 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices, 707 (unsigned char *)adjustedIndices, 708 count, -minIndex); 709 break; 710 case GL_SHORT: 711 case GL_UNSIGNED_SHORT: 712 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices, 713 (unsigned short *)adjustedIndices, 714 count, -minIndex); 715 break; 716 case GL_INT: 717 case GL_UNSIGNED_INT: 718 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices, 719 (unsigned int *)adjustedIndices, 720 count, -minIndex); 721 break; 722 default: 723 ALOGE("unsupported index buffer type %d\n", type); 724 } 725 } 726 if (has_indirect_arrays || 1) { 727 ctx->sendVertexAttributes(minIndex, maxIndex - minIndex + 1); 728 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, 729 count * glSizeof(type)); 730 ctx->m_stream->flush(); 731 // XXX - OPTIMIZATION (see the other else branch) should be implemented 732 if(!has_indirect_arrays) { 733 //ALOGD("unoptimized drawelements !!!\n"); 734 } 735 } else { 736 // we are all direct arrays and immidate mode index array - 737 // rebuild the arrays and the index array; 738 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); 739 } 740 } 741 } 742 743 744 GLint * GL2Encoder::getCompressedTextureFormats() 745 { 746 if (m_compressedTextureFormats == NULL) { 747 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS, 748 &m_num_compressedTextureFormats); 749 if (m_num_compressedTextureFormats > 0) { 750 // get number of texture formats; 751 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats]; 752 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats); 753 } 754 } 755 return m_compressedTextureFormats; 756 } 757 758 // Replace uses of samplerExternalOES with sampler2D, recording the names of 759 // modified shaders in data. Also remove 760 // #extension GL_OES_EGL_image_external : require 761 // statements. 762 // 763 // This implementation assumes the input has already been pre-processed. If not, 764 // a few cases will be mishandled: 765 // 766 // 1. "mySampler" will be incorrectly recorded as being a samplerExternalOES in 767 // the following code: 768 // #if 1 769 // uniform sampler2D mySampler; 770 // #else 771 // uniform samplerExternalOES mySampler; 772 // #endif 773 // 774 // 2. Comments that look like sampler declarations will be incorrectly modified 775 // and recorded: 776 // // samplerExternalOES hahaFooledYou 777 // 778 // 3. However, GLSL ES does not have a concatentation operator, so things like 779 // this (valid in C) are invalid and not a problem: 780 // #define SAMPLER(TYPE, NAME) uniform sampler#TYPE NAME 781 // SAMPLER(ExternalOES, mySampler); 782 // 783 static bool replaceSamplerExternalWith2D(char* const str, ShaderData* const data) 784 { 785 static const char STR_HASH_EXTENSION[] = "#extension"; 786 static const char STR_GL_OES_EGL_IMAGE_EXTERNAL[] = "GL_OES_EGL_image_external"; 787 static const char STR_SAMPLER_EXTERNAL_OES[] = "samplerExternalOES"; 788 static const char STR_SAMPLER2D_SPACE[] = "sampler2D "; 789 790 // -- overwrite all "#extension GL_OES_EGL_image_external : xxx" statements 791 char* c = str; 792 while ((c = strstr(c, STR_HASH_EXTENSION))) { 793 char* start = c; 794 c += sizeof(STR_HASH_EXTENSION)-1; 795 while (isspace(*c) && *c != '\0') { 796 c++; 797 } 798 if (strncmp(c, STR_GL_OES_EGL_IMAGE_EXTERNAL, 799 sizeof(STR_GL_OES_EGL_IMAGE_EXTERNAL)-1) == 0) 800 { 801 // #extension statements are terminated by end of line 802 c = start; 803 while (*c != '\0' && *c != '\r' && *c != '\n') { 804 *c++ = ' '; 805 } 806 } 807 } 808 809 // -- replace "samplerExternalOES" with "sampler2D" and record name 810 c = str; 811 while ((c = strstr(c, STR_SAMPLER_EXTERNAL_OES))) { 812 // Make sure "samplerExternalOES" isn't a substring of a larger token 813 if (c == str || !isspace(*(c-1))) { 814 c++; 815 continue; 816 } 817 char* sampler_start = c; 818 c += sizeof(STR_SAMPLER_EXTERNAL_OES)-1; 819 if (!isspace(*c) && *c != '\0') { 820 continue; 821 } 822 823 // capture sampler name 824 while (isspace(*c) && *c != '\0') { 825 c++; 826 } 827 if (!isalpha(*c) && *c != '_') { 828 // not an identifier 829 return false; 830 } 831 char* name_start = c; 832 do { 833 c++; 834 } while (isalnum(*c) || *c == '_'); 835 data->samplerExternalNames.push_back( 836 android::String8(name_start, c - name_start)); 837 838 // memcpy instead of strcpy since we don't want the NUL terminator 839 memcpy(sampler_start, STR_SAMPLER2D_SPACE, sizeof(STR_SAMPLER2D_SPACE)-1); 840 } 841 842 return true; 843 } 844 845 void GL2Encoder::s_glShaderBinary(void *self, GLsizei n, const GLuint *shaders, GLenum binaryformat, const void* binary, GLsizei length) 846 { 847 GL2Encoder* ctx = (GL2Encoder*)self; 848 // Although it is not supported, need to set proper error code. 849 SET_ERROR_IF(1, GL_INVALID_ENUM); 850 } 851 852 void GL2Encoder::s_glShaderSource(void *self, GLuint shader, GLsizei count, const GLchar * const *string, const GLint *length) 853 { 854 GL2Encoder* ctx = (GL2Encoder*)self; 855 ShaderData* shaderData = ctx->m_shared->getShaderData(shader); 856 SET_ERROR_IF(!ctx->m_shared->isObject(shader), GL_INVALID_VALUE); 857 SET_ERROR_IF(!shaderData, GL_INVALID_OPERATION); 858 SET_ERROR_IF((count<0), GL_INVALID_VALUE); 859 860 int len = glUtilsCalcShaderSourceLen((char**)string, (GLint*)length, count); 861 char *str = new char[len + 1]; 862 glUtilsPackStrings(str, (char**)string, (GLint*)length, count); 863 864 // TODO: pre-process str before calling replaceSamplerExternalWith2D(). 865 // Perhaps we can borrow Mesa's pre-processor? 866 867 if (!replaceSamplerExternalWith2D(str, shaderData)) { 868 delete[] str; 869 ctx->setError(GL_OUT_OF_MEMORY); 870 return; 871 } 872 873 ctx->glShaderString(ctx, shader, str, len + 1); 874 delete[] str; 875 } 876 877 void GL2Encoder::s_glFinish(void *self) 878 { 879 GL2Encoder *ctx = (GL2Encoder *)self; 880 ctx->glFinishRoundTrip(self); 881 } 882 883 void GL2Encoder::s_glLinkProgram(void * self, GLuint program) 884 { 885 GL2Encoder *ctx = (GL2Encoder *)self; 886 ctx->m_glLinkProgram_enc(self, program); 887 888 GLint linkStatus = 0; 889 ctx->glGetProgramiv(self,program,GL_LINK_STATUS,&linkStatus); 890 if (!linkStatus) 891 return; 892 893 //get number of active uniforms in the program 894 GLint numUniforms=0; 895 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORMS, &numUniforms); 896 ctx->m_shared->initProgramData(program,numUniforms); 897 898 //get the length of the longest uniform name 899 GLint maxLength=0; 900 ctx->glGetProgramiv(self, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); 901 902 GLint size; 903 GLenum type; 904 GLchar *name = new GLchar[maxLength+1]; 905 GLint location; 906 //for each active uniform, get its size and starting location. 907 for (GLint i=0 ; i<numUniforms ; ++i) 908 { 909 ctx->glGetActiveUniform(self, program, i, maxLength, NULL, &size, &type, name); 910 location = ctx->m_glGetUniformLocation_enc(self, program, name); 911 ctx->m_shared->setProgramIndexInfo(program, i, location, size, type, name); 912 } 913 ctx->m_shared->setupLocationShiftWAR(program); 914 915 delete[] name; 916 } 917 918 void GL2Encoder::s_glDeleteProgram(void *self, GLuint program) 919 { 920 GL2Encoder *ctx = (GL2Encoder*)self; 921 ctx->m_glDeleteProgram_enc(self, program); 922 923 ctx->m_shared->deleteProgramData(program); 924 } 925 926 void GL2Encoder::s_glGetUniformiv(void *self, GLuint program, GLint location, GLint* params) 927 { 928 GL2Encoder *ctx = (GL2Encoder*)self; 929 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE); 930 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); 931 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION); 932 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program, location); 933 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION); 934 ctx->m_glGetUniformiv_enc(self, program, hostLoc, params); 935 } 936 void GL2Encoder::s_glGetUniformfv(void *self, GLuint program, GLint location, GLfloat* params) 937 { 938 GL2Encoder *ctx = (GL2Encoder*)self; 939 SET_ERROR_IF(!ctx->m_shared->isObject(program), GL_INVALID_VALUE); 940 SET_ERROR_IF(!ctx->m_shared->isProgram(program), GL_INVALID_OPERATION); 941 SET_ERROR_IF(!ctx->m_shared->isProgramInitialized(program), GL_INVALID_OPERATION); 942 GLint hostLoc = ctx->m_shared->locationWARAppToHost(program,location); 943 SET_ERROR_IF(ctx->m_shared->getProgramUniformType(program,hostLoc)==0, GL_INVALID_OPERATION); 944 ctx->m_glGetUniformfv_enc(self, program, hostLoc, params); 945 } 946 947 GLuint GL2Encoder::s_glCreateProgram(void * self) 948 { 949 GL2Encoder *ctx = (GL2Encoder*)self; 950 GLuint program = ctx->m_glCreateProgram_enc(self); 951 if (program!=0) 952 ctx->m_shared->addProgramData(program); 953 return program; 954 } 955 956 GLuint GL2Encoder::s_glCreateShader(void *self, GLenum shaderType) 957 { 958 GL2Encoder *ctx = (GL2Encoder*)self; 959 RET_AND_SET_ERROR_IF(((shaderType != GL_VERTEX_SHADER) && (shaderType != GL_FRAGMENT_SHADER)), 960 GL_INVALID_ENUM, 0); 961 GLuint shader = ctx->m_glCreateShader_enc(self, shaderType); 962 if (shader != 0) { 963 if (!ctx->m_shared->addShaderData(shader)) { 964 ctx->m_glDeleteShader_enc(self, shader); 965 return 0; 966 } 967 } 968 return shader; 969 } 970 971 void GL2Encoder::s_glGetAttachedShaders(void *self, GLuint program, GLsizei maxCount, 972 GLsizei* count, GLuint* shaders) 973 { 974 GL2Encoder *ctx = (GL2Encoder*)self; 975 SET_ERROR_IF(maxCount < 0, GL_INVALID_VALUE); 976 ctx->m_glGetAttachedShaders_enc(self, program, maxCount, count, shaders); 977 } 978 979 void GL2Encoder::s_glGetShaderSource(void *self, GLuint shader, GLsizei bufsize, 980 GLsizei* length, GLchar* source) 981 { 982 GL2Encoder *ctx = (GL2Encoder*)self; 983 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); 984 ctx->m_glGetShaderSource_enc(self, shader, bufsize, length, source); 985 } 986 987 void GL2Encoder::s_glGetShaderInfoLog(void *self, GLuint shader, GLsizei bufsize, 988 GLsizei* length, GLchar* infolog) 989 { 990 GL2Encoder *ctx = (GL2Encoder*)self; 991 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); 992 ctx->m_glGetShaderInfoLog_enc(self, shader, bufsize, length, infolog); 993 } 994 995 void GL2Encoder::s_glGetProgramInfoLog(void *self, GLuint program, GLsizei bufsize, 996 GLsizei* length, GLchar* infolog) 997 { 998 GL2Encoder *ctx = (GL2Encoder*)self; 999 SET_ERROR_IF(bufsize < 0, GL_INVALID_VALUE); 1000 ctx->m_glGetProgramInfoLog_enc(self, program, bufsize, length, infolog); 1001 } 1002 1003 void GL2Encoder::s_glDeleteShader(void *self, GLenum shader) 1004 { 1005 GL2Encoder *ctx = (GL2Encoder*)self; 1006 ctx->m_glDeleteShader_enc(self,shader); 1007 ctx->m_shared->unrefShaderData(shader); 1008 } 1009 1010 void GL2Encoder::s_glAttachShader(void *self, GLuint program, GLuint shader) 1011 { 1012 GL2Encoder *ctx = (GL2Encoder*)self; 1013 ctx->m_glAttachShader_enc(self, program, shader); 1014 ctx->m_shared->attachShader(program, shader); 1015 } 1016 1017 void GL2Encoder::s_glDetachShader(void *self, GLuint program, GLuint shader) 1018 { 1019 GL2Encoder *ctx = (GL2Encoder*)self; 1020 ctx->m_glDetachShader_enc(self, program, shader); 1021 ctx->m_shared->detachShader(program, shader); 1022 } 1023 1024 int GL2Encoder::s_glGetUniformLocation(void *self, GLuint program, const GLchar *name) 1025 { 1026 if (!name) return -1; 1027 1028 GL2Encoder *ctx = (GL2Encoder*)self; 1029 1030 // if we need the uniform location WAR 1031 // parse array index from the end of the name string 1032 int arrIndex = 0; 1033 bool needLocationWAR = ctx->m_shared->needUniformLocationWAR(program); 1034 if (needLocationWAR) { 1035 int namelen = strlen(name); 1036 if (name[namelen-1] == ']') { 1037 const char *brace = strrchr(name,'['); 1038 if (!brace || sscanf(brace+1,"%d",&arrIndex) != 1) { 1039 return -1; 1040 } 1041 1042 } 1043 } 1044 1045 int hostLoc = ctx->m_glGetUniformLocation_enc(self, program, name); 1046 if (hostLoc >= 0 && needLocationWAR) { 1047 return ctx->m_shared->locationWARHostToApp(program, hostLoc, arrIndex); 1048 } 1049 return hostLoc; 1050 } 1051 1052 bool GL2Encoder::updateHostTexture2DBinding(GLenum texUnit, GLenum newTarget) 1053 { 1054 if (newTarget != GL_TEXTURE_2D && newTarget != GL_TEXTURE_EXTERNAL_OES) 1055 return false; 1056 1057 m_state->setActiveTextureUnit(texUnit); 1058 1059 GLenum oldTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); 1060 if (newTarget != oldTarget) { 1061 if (newTarget == GL_TEXTURE_EXTERNAL_OES) { 1062 m_state->disableTextureTarget(GL_TEXTURE_2D); 1063 m_state->enableTextureTarget(GL_TEXTURE_EXTERNAL_OES); 1064 } else { 1065 m_state->disableTextureTarget(GL_TEXTURE_EXTERNAL_OES); 1066 m_state->enableTextureTarget(GL_TEXTURE_2D); 1067 } 1068 m_glActiveTexture_enc(this, texUnit); 1069 m_glBindTexture_enc(this, GL_TEXTURE_2D, 1070 m_state->getBoundTexture(newTarget)); 1071 return true; 1072 } 1073 1074 return false; 1075 } 1076 1077 void GL2Encoder::s_glUseProgram(void *self, GLuint program) 1078 { 1079 GL2Encoder *ctx = (GL2Encoder*)self; 1080 GLClientState* state = ctx->m_state; 1081 GLSharedGroupPtr shared = ctx->m_shared; 1082 1083 SET_ERROR_IF(program && !shared->isObject(program), GL_INVALID_VALUE); 1084 SET_ERROR_IF(program && !shared->isProgram(program), GL_INVALID_OPERATION); 1085 1086 ctx->m_glUseProgram_enc(self, program); 1087 ctx->m_state->setCurrentProgram(program); 1088 1089 GLenum origActiveTexture = state->getActiveTextureUnit(); 1090 GLenum hostActiveTexture = origActiveTexture; 1091 GLint samplerIdx = -1; 1092 GLint samplerVal; 1093 GLenum samplerTarget; 1094 while ((samplerIdx = shared->getNextSamplerUniform(program, samplerIdx, &samplerVal, &samplerTarget)) != -1) { 1095 if (samplerVal < 0 || samplerVal >= GLClientState::MAX_TEXTURE_UNITS) 1096 continue; 1097 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + samplerVal, 1098 samplerTarget)) 1099 { 1100 hostActiveTexture = GL_TEXTURE0 + samplerVal; 1101 } 1102 } 1103 state->setActiveTextureUnit(origActiveTexture); 1104 if (hostActiveTexture != origActiveTexture) { 1105 ctx->m_glActiveTexture_enc(self, origActiveTexture); 1106 } 1107 } 1108 1109 void GL2Encoder::s_glUniform1f(void *self , GLint location, GLfloat x) 1110 { 1111 GL2Encoder *ctx = (GL2Encoder*)self; 1112 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1113 ctx->m_glUniform1f_enc(self, hostLoc, x); 1114 } 1115 1116 void GL2Encoder::s_glUniform1fv(void *self , GLint location, GLsizei count, const GLfloat* v) 1117 { 1118 GL2Encoder *ctx = (GL2Encoder*)self; 1119 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1120 ctx->m_glUniform1fv_enc(self, hostLoc, count, v); 1121 } 1122 1123 void GL2Encoder::s_glUniform1i(void *self , GLint location, GLint x) 1124 { 1125 GL2Encoder *ctx = (GL2Encoder*)self; 1126 GLClientState* state = ctx->m_state; 1127 GLSharedGroupPtr shared = ctx->m_shared; 1128 1129 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1130 ctx->m_glUniform1i_enc(self, hostLoc, x); 1131 1132 GLenum target; 1133 if (shared->setSamplerUniform(state->currentProgram(), location, x, &target)) { 1134 GLenum origActiveTexture = state->getActiveTextureUnit(); 1135 if (ctx->updateHostTexture2DBinding(GL_TEXTURE0 + x, target)) { 1136 ctx->m_glActiveTexture_enc(self, origActiveTexture); 1137 } 1138 state->setActiveTextureUnit(origActiveTexture); 1139 } 1140 } 1141 1142 void GL2Encoder::s_glUniform1iv(void *self , GLint location, GLsizei count, const GLint* v) 1143 { 1144 GL2Encoder *ctx = (GL2Encoder*)self; 1145 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1146 ctx->m_glUniform1iv_enc(self, hostLoc, count, v); 1147 } 1148 1149 void GL2Encoder::s_glUniform2f(void *self , GLint location, GLfloat x, GLfloat y) 1150 { 1151 GL2Encoder *ctx = (GL2Encoder*)self; 1152 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1153 ctx->m_glUniform2f_enc(self, hostLoc, x, y); 1154 } 1155 1156 void GL2Encoder::s_glUniform2fv(void *self , GLint location, GLsizei count, const GLfloat* v) 1157 { 1158 GL2Encoder *ctx = (GL2Encoder*)self; 1159 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1160 ctx->m_glUniform2fv_enc(self, hostLoc, count, v); 1161 } 1162 1163 void GL2Encoder::s_glUniform2i(void *self , GLint location, GLint x, GLint y) 1164 { 1165 GL2Encoder *ctx = (GL2Encoder*)self; 1166 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1167 ctx->m_glUniform2i_enc(self, hostLoc, x, y); 1168 } 1169 1170 void GL2Encoder::s_glUniform2iv(void *self , GLint location, GLsizei count, const GLint* v) 1171 { 1172 GL2Encoder *ctx = (GL2Encoder*)self; 1173 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1174 ctx->m_glUniform2iv_enc(self, hostLoc, count, v); 1175 } 1176 1177 void GL2Encoder::s_glUniform3f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z) 1178 { 1179 GL2Encoder *ctx = (GL2Encoder*)self; 1180 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1181 ctx->m_glUniform3f_enc(self, hostLoc, x, y, z); 1182 } 1183 1184 void GL2Encoder::s_glUniform3fv(void *self , GLint location, GLsizei count, const GLfloat* v) 1185 { 1186 GL2Encoder *ctx = (GL2Encoder*)self; 1187 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1188 ctx->m_glUniform3fv_enc(self, hostLoc, count, v); 1189 } 1190 1191 void GL2Encoder::s_glUniform3i(void *self , GLint location, GLint x, GLint y, GLint z) 1192 { 1193 GL2Encoder *ctx = (GL2Encoder*)self; 1194 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1195 ctx->m_glUniform3i_enc(self, hostLoc, x, y, z); 1196 } 1197 1198 void GL2Encoder::s_glUniform3iv(void *self , GLint location, GLsizei count, const GLint* v) 1199 { 1200 GL2Encoder *ctx = (GL2Encoder*)self; 1201 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1202 ctx->m_glUniform3iv_enc(self, hostLoc, count, v); 1203 } 1204 1205 void GL2Encoder::s_glUniform4f(void *self , GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) 1206 { 1207 GL2Encoder *ctx = (GL2Encoder*)self; 1208 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1209 ctx->m_glUniform4f_enc(self, hostLoc, x, y, z, w); 1210 } 1211 1212 void GL2Encoder::s_glUniform4fv(void *self , GLint location, GLsizei count, const GLfloat* v) 1213 { 1214 GL2Encoder *ctx = (GL2Encoder*)self; 1215 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1216 ctx->m_glUniform4fv_enc(self, hostLoc, count, v); 1217 } 1218 1219 void GL2Encoder::s_glUniform4i(void *self , GLint location, GLint x, GLint y, GLint z, GLint w) 1220 { 1221 GL2Encoder *ctx = (GL2Encoder*)self; 1222 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1223 ctx->m_glUniform4i_enc(self, hostLoc, x, y, z, w); 1224 } 1225 1226 void GL2Encoder::s_glUniform4iv(void *self , GLint location, GLsizei count, const GLint* v) 1227 { 1228 GL2Encoder *ctx = (GL2Encoder*)self; 1229 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1230 ctx->m_glUniform4iv_enc(self, hostLoc, count, v); 1231 } 1232 1233 void GL2Encoder::s_glUniformMatrix2fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) 1234 { 1235 GL2Encoder *ctx = (GL2Encoder*)self; 1236 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1237 ctx->m_glUniformMatrix2fv_enc(self, hostLoc, count, transpose, value); 1238 } 1239 1240 void GL2Encoder::s_glUniformMatrix3fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) 1241 { 1242 GL2Encoder *ctx = (GL2Encoder*)self; 1243 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1244 ctx->m_glUniformMatrix3fv_enc(self, hostLoc, count, transpose, value); 1245 } 1246 1247 void GL2Encoder::s_glUniformMatrix4fv(void *self , GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) 1248 { 1249 GL2Encoder *ctx = (GL2Encoder*)self; 1250 GLint hostLoc = ctx->m_shared->locationWARAppToHost(ctx->m_state->currentProgram(),location); 1251 ctx->m_glUniformMatrix4fv_enc(self, hostLoc, count, transpose, value); 1252 } 1253 1254 void GL2Encoder::s_glActiveTexture(void* self, GLenum texture) 1255 { 1256 GL2Encoder* ctx = (GL2Encoder*)self; 1257 GLClientState* state = ctx->m_state; 1258 GLenum err; 1259 1260 SET_ERROR_IF((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR, err); 1261 1262 ctx->m_glActiveTexture_enc(ctx, texture); 1263 } 1264 1265 void GL2Encoder::s_glBindTexture(void* self, GLenum target, GLuint texture) 1266 { 1267 GL2Encoder* ctx = (GL2Encoder*)self; 1268 GLClientState* state = ctx->m_state; 1269 GLenum err; 1270 GLboolean firstUse; 1271 1272 SET_ERROR_IF((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR, err); 1273 1274 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { 1275 ctx->m_glBindTexture_enc(ctx, target, texture); 1276 return; 1277 } 1278 1279 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); 1280 1281 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { 1282 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 1283 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 1284 GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1285 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 1286 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1287 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 1288 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1289 1290 if (target != priorityTarget) { 1291 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 1292 state->getBoundTexture(GL_TEXTURE_2D)); 1293 } 1294 } 1295 1296 if (target == priorityTarget) { 1297 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 1298 } 1299 } 1300 1301 void GL2Encoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) 1302 { 1303 GL2Encoder* ctx = (GL2Encoder*)self; 1304 GLClientState* state = ctx->m_state; 1305 1306 state->deleteTextures(n, textures); 1307 ctx->m_glDeleteTextures_enc(ctx, n, textures); 1308 } 1309 1310 void GL2Encoder::s_glGetTexParameterfv(void* self, 1311 GLenum target, GLenum pname, GLfloat* params) 1312 { 1313 GL2Encoder* ctx = (GL2Encoder*)self; 1314 const GLClientState* state = ctx->m_state; 1315 1316 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1317 ctx->override2DTextureTarget(target); 1318 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 1319 ctx->restore2DTextureTarget(target); 1320 } else { 1321 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); 1322 } 1323 } 1324 1325 void GL2Encoder::s_glGetTexParameteriv(void* self, 1326 GLenum target, GLenum pname, GLint* params) 1327 { 1328 GL2Encoder* ctx = (GL2Encoder*)self; 1329 const GLClientState* state = ctx->m_state; 1330 1331 switch (pname) { 1332 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 1333 *params = 1; 1334 break; 1335 1336 default: 1337 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1338 ctx->override2DTextureTarget(target); 1339 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 1340 ctx->restore2DTextureTarget(target); 1341 } else { 1342 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); 1343 } 1344 break; 1345 } 1346 } 1347 1348 static bool isValidTextureExternalParam(GLenum pname, GLenum param) 1349 { 1350 switch (pname) { 1351 case GL_TEXTURE_MIN_FILTER: 1352 case GL_TEXTURE_MAG_FILTER: 1353 return param == GL_NEAREST || param == GL_LINEAR; 1354 1355 case GL_TEXTURE_WRAP_S: 1356 case GL_TEXTURE_WRAP_T: 1357 return param == GL_CLAMP_TO_EDGE; 1358 1359 default: 1360 return true; 1361 } 1362 } 1363 1364 void GL2Encoder::s_glTexParameterf(void* self, 1365 GLenum target, GLenum pname, GLfloat param) 1366 { 1367 GL2Encoder* ctx = (GL2Encoder*)self; 1368 const GLClientState* state = ctx->m_state; 1369 1370 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 1371 !isValidTextureExternalParam(pname, (GLenum)param)), 1372 GL_INVALID_ENUM); 1373 1374 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1375 ctx->override2DTextureTarget(target); 1376 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); 1377 ctx->restore2DTextureTarget(target); 1378 } else { 1379 ctx->m_glTexParameterf_enc(ctx, target, pname, param); 1380 } 1381 } 1382 1383 void GL2Encoder::s_glTexParameterfv(void* self, 1384 GLenum target, GLenum pname, const GLfloat* params) 1385 { 1386 GL2Encoder* ctx = (GL2Encoder*)self; 1387 const GLClientState* state = ctx->m_state; 1388 1389 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 1390 !isValidTextureExternalParam(pname, (GLenum)params[0])), 1391 GL_INVALID_ENUM); 1392 1393 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1394 ctx->override2DTextureTarget(target); 1395 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 1396 ctx->restore2DTextureTarget(target); 1397 } else { 1398 ctx->m_glTexParameterfv_enc(ctx, target, pname, params); 1399 } 1400 } 1401 1402 void GL2Encoder::s_glTexParameteri(void* self, 1403 GLenum target, GLenum pname, GLint param) 1404 { 1405 GL2Encoder* ctx = (GL2Encoder*)self; 1406 const GLClientState* state = ctx->m_state; 1407 1408 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 1409 !isValidTextureExternalParam(pname, (GLenum)param)), 1410 GL_INVALID_ENUM); 1411 1412 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1413 ctx->override2DTextureTarget(target); 1414 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); 1415 ctx->restore2DTextureTarget(target); 1416 } else { 1417 ctx->m_glTexParameteri_enc(ctx, target, pname, param); 1418 } 1419 } 1420 1421 void GL2Encoder::s_glTexImage2D(void* self, GLenum target, GLint level, 1422 GLint internalformat, GLsizei width, GLsizei height, GLint border, 1423 GLenum format, GLenum type, const GLvoid* pixels) 1424 { 1425 GL2Encoder* ctx = (GL2Encoder*)self; 1426 GLClientState* state = ctx->m_state; 1427 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1428 ctx->override2DTextureTarget(target); 1429 state->setBoundTextureInternalFormat(target, internalformat); 1430 state->setBoundTextureFormat(target, format); 1431 state->setBoundTextureType(target, type); 1432 1433 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width, 1434 height, border, format, type, pixels); 1435 ctx->restore2DTextureTarget(target); 1436 } else { 1437 ctx->m_glTexImage2D_enc(ctx, target, level, internalformat, width, 1438 height, border, format, type, pixels); 1439 } 1440 } 1441 1442 void GL2Encoder::s_glTexSubImage2D(void* self, GLenum target, GLint level, 1443 GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, 1444 GLenum type, const GLvoid* pixels) 1445 { 1446 GL2Encoder* ctx = (GL2Encoder*)self; 1447 1448 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1449 ctx->override2DTextureTarget(target); 1450 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width, 1451 height, format, type, pixels); 1452 ctx->restore2DTextureTarget(target); 1453 } else { 1454 ctx->m_glTexSubImage2D_enc(ctx, target, level, xoffset, yoffset, width, 1455 height, format, type, pixels); 1456 } 1457 } 1458 1459 void GL2Encoder::s_glCopyTexImage2D(void* self, GLenum target, GLint level, 1460 GLenum internalformat, GLint x, GLint y, 1461 GLsizei width, GLsizei height, GLint border) 1462 { 1463 GL2Encoder* ctx = (GL2Encoder*)self; 1464 GLClientState* state = ctx->m_state; 1465 1466 // This is needed to work around underlying OpenGL drivers 1467 // (such as those feeding some some AMD GPUs) that expect 1468 // positive components of cube maps to be defined _before_ 1469 // the negative components (otherwise a segfault occurs). 1470 GLenum extraTarget = 1471 state->copyTexImageLuminanceCubeMapAMDWorkaround 1472 (target, level, internalformat); 1473 1474 if (extraTarget) { 1475 ctx->m_glCopyTexImage2D_enc(ctx, extraTarget, level, internalformat, 1476 x, y, width, height, border); 1477 } 1478 1479 ctx->m_glCopyTexImage2D_enc(ctx, target, level, internalformat, 1480 x, y, width, height, border); 1481 } 1482 1483 void GL2Encoder::s_glTexParameteriv(void* self, 1484 GLenum target, GLenum pname, const GLint* params) 1485 { 1486 GL2Encoder* ctx = (GL2Encoder*)self; 1487 const GLClientState* state = ctx->m_state; 1488 1489 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 1490 !isValidTextureExternalParam(pname, (GLenum)params[0])), 1491 GL_INVALID_ENUM); 1492 1493 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 1494 ctx->override2DTextureTarget(target); 1495 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 1496 ctx->restore2DTextureTarget(target); 1497 } else { 1498 ctx->m_glTexParameteriv_enc(ctx, target, pname, params); 1499 } 1500 } 1501 1502 bool GL2Encoder::texture2DNeedsOverride(GLenum target) const { 1503 return (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && 1504 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); 1505 } 1506 1507 void GL2Encoder::override2DTextureTarget(GLenum target) 1508 { 1509 if (texture2DNeedsOverride(target)) { 1510 m_glBindTexture_enc(this, GL_TEXTURE_2D, 1511 m_state->getBoundTexture(target)); 1512 } 1513 } 1514 1515 void GL2Encoder::restore2DTextureTarget(GLenum target) 1516 { 1517 if (texture2DNeedsOverride(target)) { 1518 m_glBindTexture_enc(this, GL_TEXTURE_2D, 1519 m_state->getBoundTexture( 1520 m_state->getPriorityEnabledTarget(GL_TEXTURE_2D))); 1521 } 1522 } 1523 1524 void GL2Encoder::s_glGenRenderbuffers(void* self, 1525 GLsizei n, GLuint* renderbuffers) { 1526 GL2Encoder* ctx = (GL2Encoder*)self; 1527 GLClientState* state = ctx->m_state; 1528 1529 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 1530 1531 ctx->m_glGenFramebuffers_enc(self, n, renderbuffers); 1532 state->addRenderbuffers(n, renderbuffers); 1533 } 1534 1535 void GL2Encoder::s_glDeleteRenderbuffers(void* self, 1536 GLsizei n, const GLuint* renderbuffers) { 1537 GL2Encoder* ctx = (GL2Encoder*)self; 1538 GLClientState* state = ctx->m_state; 1539 1540 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 1541 1542 ctx->m_glDeleteRenderbuffers_enc(self, n, renderbuffers); 1543 state->removeRenderbuffers(n, renderbuffers); 1544 } 1545 1546 void GL2Encoder::s_glBindRenderbuffer(void* self, 1547 GLenum target, GLuint renderbuffer) { 1548 GL2Encoder* ctx = (GL2Encoder*)self; 1549 GLClientState* state = ctx->m_state; 1550 1551 SET_ERROR_IF((target != GL_RENDERBUFFER), 1552 GL_INVALID_ENUM); 1553 1554 ctx->m_glBindRenderbuffer_enc(self, target, renderbuffer); 1555 state->bindRenderbuffer(target, renderbuffer); 1556 } 1557 1558 void GL2Encoder::s_glRenderbufferStorage(void* self, 1559 GLenum target, GLenum internalformat, 1560 GLsizei width, GLsizei height) { 1561 GL2Encoder* ctx = (GL2Encoder*) self; 1562 GLClientState* state = ctx->m_state; 1563 1564 SET_ERROR_IF(target != GL_RENDERBUFFER, GL_INVALID_ENUM); 1565 switch (internalformat) { 1566 // Funny internal formats 1567 // that will cause an incomplete framebuffer 1568 // attachment error. For dEQP, 1569 // we can also just abort early here in 1570 // RenderbufferStorage with a GL_INVALID_ENUM. 1571 case GL_DEPTH_COMPONENT32F: 1572 case GL_R8: 1573 case GL_R8UI: 1574 case GL_R8I: 1575 case GL_R16UI: 1576 case GL_R16I: 1577 case GL_R32UI: 1578 case GL_R32I: 1579 case GL_RG8: 1580 case GL_RG8UI: 1581 case GL_RG8I: 1582 case GL_RG16UI: 1583 case GL_RG16I: 1584 case GL_RG32UI: 1585 case GL_RG32I: 1586 case GL_SRGB8_ALPHA8: 1587 case GL_RGBA8UI: 1588 case GL_RGBA8I: 1589 case GL_RGB10_A2UI: 1590 case GL_RGBA16UI: 1591 case GL_RGBA16I: 1592 case GL_RGBA32I: 1593 case GL_RGBA32UI: 1594 case GL_R11F_G11F_B10F: 1595 case GL_R32F: 1596 case GL_RG32F: 1597 case GL_RGB32F: 1598 case GL_RGBA32F: 1599 SET_ERROR_IF(true, GL_INVALID_ENUM); 1600 break; 1601 // These 4 formats are still not OK, 1602 // but dEQP expects GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT or 1603 // GL_FRAMEBUFFER_UNSUPPORTED, 1604 // not a GL_INVALID_ENUM from earlier on. 1605 // So let's forward these to the rest of 1606 // FBO initialization 1607 case GL_R16F: 1608 case GL_RG16F: 1609 case GL_RGB16F: 1610 case GL_RGBA16F: 1611 // dEQP expects GL_FRAMEBUFFER_UNSUPPORTED or GL_FRAMEBUFFER_COMPLETE 1612 // for this format 1613 case GL_RGB10_A2: 1614 // These formats are OK 1615 case GL_DEPTH_COMPONENT16: 1616 case GL_DEPTH_COMPONENT24: 1617 case GL_DEPTH_COMPONENT32_OES: 1618 case GL_RGBA4: 1619 case GL_RGB5_A1: 1620 case GL_RGB565: 1621 case GL_RGB8_OES: 1622 case GL_RGBA8_OES: 1623 case GL_STENCIL_INDEX8: 1624 case GL_DEPTH32F_STENCIL8: 1625 case GL_DEPTH24_STENCIL8_OES: 1626 break; 1627 // Everything else: still not OK, 1628 // and they need the GL_INVALID_ENUM 1629 default: 1630 SET_ERROR_IF(true, GL_INVALID_ENUM); 1631 } 1632 1633 state->setBoundRenderbufferFormat(internalformat); 1634 ctx->m_glRenderbufferStorage_enc(self, target, internalformat, 1635 width, height); 1636 } 1637 1638 void GL2Encoder::s_glFramebufferRenderbuffer(void* self, 1639 GLenum target, GLenum attachment, 1640 GLenum renderbuffertarget, GLuint renderbuffer) { 1641 GL2Encoder* ctx = (GL2Encoder*)self; 1642 GLClientState* state = ctx->m_state; 1643 1644 state->attachRbo(attachment, renderbuffer); 1645 1646 ctx->m_glFramebufferRenderbuffer_enc(self, target, attachment, renderbuffertarget, renderbuffer); 1647 } 1648 1649 void GL2Encoder::s_glGenFramebuffers(void* self, 1650 GLsizei n, GLuint* framebuffers) { 1651 GL2Encoder* ctx = (GL2Encoder*)self; 1652 GLClientState* state = ctx->m_state; 1653 1654 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 1655 1656 ctx->m_glGenFramebuffers_enc(self, n, framebuffers); 1657 state->addFramebuffers(n, framebuffers); 1658 } 1659 1660 void GL2Encoder::s_glDeleteFramebuffers(void* self, 1661 GLsizei n, const GLuint* framebuffers) { 1662 GL2Encoder* ctx = (GL2Encoder*)self; 1663 GLClientState* state = ctx->m_state; 1664 1665 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 1666 1667 ctx->m_glDeleteFramebuffers_enc(self, n, framebuffers); 1668 state->removeFramebuffers(n, framebuffers); 1669 } 1670 1671 void GL2Encoder::s_glBindFramebuffer(void* self, 1672 GLenum target, GLuint framebuffer) { 1673 GL2Encoder* ctx = (GL2Encoder*)self; 1674 GLClientState* state = ctx->m_state; 1675 1676 SET_ERROR_IF((target != GL_FRAMEBUFFER), 1677 GL_INVALID_ENUM); 1678 1679 state->bindFramebuffer(target, framebuffer); 1680 1681 ctx->m_glBindFramebuffer_enc(self, target, framebuffer); 1682 } 1683 1684 void GL2Encoder::s_glFramebufferTexture2D(void* self, 1685 GLenum target, GLenum attachment, 1686 GLenum textarget, GLuint texture, GLint level) { 1687 GL2Encoder* ctx = (GL2Encoder*)self; 1688 GLClientState* state = ctx->m_state; 1689 1690 state->attachTextureObject(attachment, texture); 1691 1692 ctx->m_glFramebufferTexture2D_enc(self, target, attachment, textarget, texture, level); 1693 } 1694 1695 void GL2Encoder::s_glFramebufferTexture3DOES(void* self, 1696 GLenum target, GLenum attachment, 1697 GLenum textarget, GLuint texture, GLint level, GLint zoffset) { 1698 GL2Encoder* ctx = (GL2Encoder*)self; 1699 GLClientState* state = ctx->m_state; 1700 1701 state->attachTextureObject(attachment, texture); 1702 1703 ctx->m_glFramebufferTexture3DOES_enc(self, target, attachment, textarget, texture, level, zoffset); 1704 } 1705 1706 void GL2Encoder::s_glGetFramebufferAttachmentParameteriv(void* self, 1707 GLenum target, GLenum attachment, GLenum pname, GLint* params) { 1708 GL2Encoder* ctx = (GL2Encoder*)self; 1709 const GLClientState* state = ctx->m_state; 1710 1711 SET_ERROR_IF(state->boundFramebuffer() == 0, 1712 GL_INVALID_OPERATION); 1713 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) && 1714 (!state->attachmentHasObject(attachment)), 1715 GL_INVALID_ENUM); 1716 1717 ctx->m_glGetFramebufferAttachmentParameteriv_enc(self, target, attachment, pname, params); 1718 } 1719 1720 bool GL2Encoder::isCompleteFbo(const GLClientState* state, 1721 GLenum attachment) const { 1722 FboFormatInfo fbo_format_info; 1723 state->getBoundFramebufferFormat(attachment, &fbo_format_info); 1724 1725 bool res; 1726 switch (fbo_format_info.type) { 1727 case FBO_ATTACHMENT_RENDERBUFFER: 1728 switch (fbo_format_info.rb_format) { 1729 case GL_R16F: 1730 case GL_RG16F: 1731 case GL_RGB16F: 1732 case GL_RGBA16F: 1733 res = false; 1734 break; 1735 case GL_STENCIL_INDEX8: 1736 if (attachment == GL_STENCIL_ATTACHMENT) { 1737 res = true; 1738 } else { 1739 res = false; 1740 } 1741 break; 1742 default: 1743 res = true; 1744 } 1745 break; 1746 case FBO_ATTACHMENT_TEXTURE: 1747 switch (fbo_format_info.tex_internalformat) { 1748 case GL_RED: 1749 case GL_RG: 1750 case GL_R16F: 1751 case GL_RG16F: 1752 case GL_RGBA16F: 1753 case GL_RGB16F: 1754 case GL_R11F_G11F_B10F: 1755 res = false; 1756 break; 1757 // No float/half-float formats allowed for RGB(A) 1758 case GL_RGB: 1759 case GL_RGBA: 1760 switch (fbo_format_info.tex_type) { 1761 case GL_FLOAT: 1762 case GL_HALF_FLOAT_OES: 1763 case GL_UNSIGNED_INT_10F_11F_11F_REV: 1764 res = false; 1765 break; 1766 default: 1767 res = true; 1768 } 1769 break; 1770 default: 1771 res = true; 1772 } 1773 break; 1774 case FBO_ATTACHMENT_NONE: 1775 res = true; 1776 break; 1777 default: 1778 res = true; 1779 } 1780 return res; 1781 } 1782 1783 GLenum GL2Encoder::s_glCheckFramebufferStatus(void* self, GLenum target) { 1784 GL2Encoder* ctx = (GL2Encoder*)self; 1785 GLClientState* state = ctx->m_state; 1786 1787 bool complete = ctx->isCompleteFbo(state, GL_COLOR_ATTACHMENT0) && 1788 ctx->isCompleteFbo(state, GL_DEPTH_ATTACHMENT) && 1789 ctx->isCompleteFbo(state, GL_STENCIL_ATTACHMENT); 1790 if (!complete) { 1791 state->setCheckFramebufferStatus(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT); 1792 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 1793 } else { 1794 GLenum host_checkstatus = ctx->m_glCheckFramebufferStatus_enc(self, target); 1795 state->setCheckFramebufferStatus(host_checkstatus); 1796 return host_checkstatus; 1797 } 1798 } 1799