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 "GLEncoder.h" 17 #include "glUtils.h" 18 #include "FixedBuffer.h" 19 #include <cutils/log.h> 20 #include <assert.h> 21 22 #ifndef MIN 23 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 24 #endif 25 26 static GLubyte *gVendorString= (GLubyte *) "Android"; 27 static GLubyte *gRendererString= (GLubyte *) "Android HW-GLES 1.0"; 28 static GLubyte *gVersionString= (GLubyte *) "OpenGL ES-CM 1.0"; 29 static GLubyte *gExtensionsString= (GLubyte *) "GL_OES_EGL_image_external "; 30 31 #define SET_ERROR_IF(condition,err) if((condition)) { \ 32 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ 33 ctx->setError(err); \ 34 return; \ 35 } 36 37 38 #define RET_AND_SET_ERROR_IF(condition,err,ret) if((condition)) { \ 39 ALOGE("%s:%s:%d GL error 0x%x\n", __FILE__, __FUNCTION__, __LINE__, err); \ 40 ctx->setError(err); \ 41 return ret; \ 42 } 43 44 GLenum GLEncoder::s_glGetError(void * self) 45 { 46 GLEncoder *ctx = (GLEncoder *)self; 47 GLenum err = ctx->getError(); 48 if(err != GL_NO_ERROR) { 49 ctx->setError(GL_NO_ERROR); 50 return err; 51 } 52 53 return ctx->m_glGetError_enc(self); 54 55 } 56 57 GLint * GLEncoder::getCompressedTextureFormats() 58 { 59 if (m_compressedTextureFormats == NULL) { 60 this->glGetIntegerv(this, GL_NUM_COMPRESSED_TEXTURE_FORMATS, 61 &m_num_compressedTextureFormats); 62 if (m_num_compressedTextureFormats > 0) { 63 // get number of texture formats; 64 m_compressedTextureFormats = new GLint[m_num_compressedTextureFormats]; 65 this->glGetCompressedTextureFormats(this, m_num_compressedTextureFormats, m_compressedTextureFormats); 66 } 67 } 68 return m_compressedTextureFormats; 69 } 70 71 void GLEncoder::s_glGetIntegerv(void *self, GLenum param, GLint *ptr) 72 { 73 GLEncoder *ctx = (GLEncoder *)self; 74 assert(ctx->m_state != NULL); 75 GLClientState* state = ctx->m_state; 76 77 switch (param) { 78 case GL_COMPRESSED_TEXTURE_FORMATS: { 79 GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); 80 if (ctx->m_num_compressedTextureFormats > 0 && 81 compressedTextureFormats != NULL) { 82 memcpy(ptr, compressedTextureFormats, 83 ctx->m_num_compressedTextureFormats * sizeof(GLint)); 84 } 85 break; 86 } 87 88 case GL_MAX_TEXTURE_UNITS: 89 ctx->m_glGetIntegerv_enc(self, param, ptr); 90 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS); 91 break; 92 93 case GL_TEXTURE_BINDING_2D: 94 *ptr = state->getBoundTexture(GL_TEXTURE_2D); 95 break; 96 97 case GL_TEXTURE_BINDING_EXTERNAL_OES: 98 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); 99 break; 100 101 default: 102 if (!state->getClientStateParameter<GLint>(param,ptr)) { 103 ctx->m_glGetIntegerv_enc(self, param, ptr); 104 } 105 break; 106 } 107 } 108 109 void GLEncoder::s_glGetFloatv(void *self, GLenum param, GLfloat *ptr) 110 { 111 GLEncoder *ctx = (GLEncoder *)self; 112 assert(ctx->m_state != NULL); 113 GLClientState* state = ctx->m_state; 114 115 switch (param) { 116 case GL_COMPRESSED_TEXTURE_FORMATS: { 117 GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); 118 if (ctx->m_num_compressedTextureFormats > 0 && 119 compressedTextureFormats != NULL) { 120 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { 121 ptr[i] = (GLfloat) compressedTextureFormats[i]; 122 } 123 } 124 break; 125 } 126 127 case GL_MAX_TEXTURE_UNITS: 128 ctx->m_glGetFloatv_enc(self, param, ptr); 129 *ptr = MIN(*ptr, (GLfloat)GLClientState::MAX_TEXTURE_UNITS); 130 break; 131 132 case GL_TEXTURE_BINDING_2D: 133 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_2D); 134 break; 135 136 case GL_TEXTURE_BINDING_EXTERNAL_OES: 137 *ptr = (GLfloat)state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES); 138 break; 139 140 default: 141 if (!state->getClientStateParameter<GLfloat>(param,ptr)) { 142 ctx->m_glGetFloatv_enc(self, param, ptr); 143 } 144 break; 145 } 146 } 147 148 void GLEncoder::s_glGetFixedv(void *self, GLenum param, GLfixed *ptr) 149 { 150 GLEncoder *ctx = (GLEncoder *)self; 151 assert(ctx->m_state != NULL); 152 GLClientState* state = ctx->m_state; 153 154 switch (param) { 155 case GL_COMPRESSED_TEXTURE_FORMATS: { 156 GLint * compressedTextureFormats = ctx->getCompressedTextureFormats(); 157 if (ctx->m_num_compressedTextureFormats > 0 && 158 compressedTextureFormats != NULL) { 159 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { 160 ptr[i] = compressedTextureFormats[i] << 16; 161 } 162 } 163 break; 164 } 165 166 case GL_MAX_TEXTURE_UNITS: 167 ctx->m_glGetFixedv_enc(self, param, ptr); 168 *ptr = MIN(*ptr, GLClientState::MAX_TEXTURE_UNITS << 16); 169 break; 170 171 case GL_TEXTURE_BINDING_2D: 172 *ptr = state->getBoundTexture(GL_TEXTURE_2D) << 16; 173 break; 174 175 case GL_TEXTURE_BINDING_EXTERNAL_OES: 176 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) << 16; 177 break; 178 179 default: 180 if (!state->getClientStateParameter<GLfixed>(param,ptr)) { 181 ctx->m_glGetFixedv_enc(self, param, ptr); 182 } 183 break; 184 } 185 } 186 187 void GLEncoder::s_glGetBooleanv(void *self, GLenum param, GLboolean *ptr) 188 { 189 GLEncoder *ctx = (GLEncoder *)self; 190 assert(ctx->m_state != NULL); 191 GLClientState* state = ctx->m_state; 192 193 switch (param) { 194 case GL_COMPRESSED_TEXTURE_FORMATS: { 195 GLint* compressedTextureFormats = ctx->getCompressedTextureFormats(); 196 if (ctx->m_num_compressedTextureFormats > 0 && 197 compressedTextureFormats != NULL) { 198 for (int i = 0; i < ctx->m_num_compressedTextureFormats; i++) { 199 ptr[i] = compressedTextureFormats[i] != 0 ? GL_TRUE : GL_FALSE; 200 } 201 } 202 break; 203 } 204 205 case GL_TEXTURE_BINDING_2D: 206 *ptr = state->getBoundTexture(GL_TEXTURE_2D) != 0 ? GL_TRUE : GL_FALSE; 207 break; 208 209 case GL_TEXTURE_BINDING_EXTERNAL_OES: 210 *ptr = state->getBoundTexture(GL_TEXTURE_EXTERNAL_OES) != 0 211 ? GL_TRUE : GL_FALSE; 212 break; 213 214 default: 215 if (!state->getClientStateParameter<GLboolean>(param,ptr)) { 216 ctx->m_glGetBooleanv_enc(self, param, ptr); 217 } 218 break; 219 } 220 } 221 222 void GLEncoder::s_glGetPointerv(void * self, GLenum param, GLvoid **params) 223 { 224 GLEncoder * ctx = (GLEncoder *) self; 225 assert(ctx->m_state != NULL); 226 ctx->m_state->getClientStatePointer(param,params); 227 } 228 229 void GLEncoder::s_glFlush(void *self) 230 { 231 GLEncoder *ctx = (GLEncoder *)self; 232 ctx->m_glFlush_enc(self); 233 ctx->m_stream->flush(); 234 } 235 236 const GLubyte *GLEncoder::s_glGetString(void *self, GLenum name) 237 { 238 (void)self; 239 240 GLubyte *retval = (GLubyte *) ""; 241 switch(name) { 242 case GL_VENDOR: 243 retval = gVendorString; 244 break; 245 case GL_RENDERER: 246 retval = gRendererString; 247 break; 248 case GL_VERSION: 249 retval = gVersionString; 250 break; 251 case GL_EXTENSIONS: 252 retval = gExtensionsString; 253 break; 254 } 255 return retval; 256 } 257 258 void GLEncoder::s_glPixelStorei(void *self, GLenum param, GLint value) 259 { 260 GLEncoder *ctx = (GLEncoder *)self; 261 ctx->m_glPixelStorei_enc(ctx, param, value); 262 ALOG_ASSERT(ctx->m_state, "GLEncoder::s_glPixelStorei"); 263 ctx->m_state->setPixelStore(param, value); 264 } 265 266 void GLEncoder::s_glVertexPointer(void *self, int size, GLenum type, GLsizei stride, const void *data) 267 { 268 GLEncoder *ctx = (GLEncoder *)self; 269 assert(ctx->m_state != NULL); 270 ctx->m_state->setState(GLClientState::VERTEX_LOCATION, size, type, false, stride, data); 271 } 272 273 void GLEncoder::s_glNormalPointer(void *self, GLenum type, GLsizei stride, const void *data) 274 { 275 GLEncoder *ctx = (GLEncoder *)self; 276 assert(ctx->m_state != NULL); 277 ctx->m_state->setState(GLClientState::NORMAL_LOCATION, 3, type, false, stride, data); 278 } 279 280 void GLEncoder::s_glColorPointer(void *self, int size, GLenum type, GLsizei stride, const void *data) 281 { 282 GLEncoder *ctx = (GLEncoder *)self; 283 assert(ctx->m_state != NULL); 284 ctx->m_state->setState(GLClientState::COLOR_LOCATION, size, type, false, stride, data); 285 } 286 287 void GLEncoder::s_glPointSizePointerOES(void *self, GLenum type, GLsizei stride, const void *data) 288 { 289 GLEncoder *ctx = (GLEncoder *)self; 290 assert(ctx->m_state != NULL); 291 ctx->m_state->setState(GLClientState::POINTSIZE_LOCATION, 1, type, false, stride, data); 292 } 293 294 void GLEncoder::s_glClientActiveTexture(void *self, GLenum texture) 295 { 296 GLEncoder *ctx = (GLEncoder *)self; 297 assert(ctx->m_state != NULL); 298 ctx->m_state->setActiveTexture(texture - GL_TEXTURE0); 299 } 300 301 void GLEncoder::s_glTexCoordPointer(void *self, int size, GLenum type, GLsizei stride, const void *data) 302 { 303 GLEncoder *ctx = (GLEncoder *)self; 304 assert(ctx->m_state != NULL); 305 int loc = ctx->m_state->getLocation(GL_TEXTURE_COORD_ARRAY); 306 ctx->m_state->setState(loc, size, type, false, stride, data); 307 } 308 309 void GLEncoder::s_glMatrixIndexPointerOES(void *self, int size, GLenum type, GLsizei stride, const void * data) 310 { 311 GLEncoder *ctx = (GLEncoder *)self; 312 assert(ctx->m_state != NULL); 313 int loc = ctx->m_state->getLocation(GL_MATRIX_INDEX_ARRAY_OES); 314 ctx->m_state->setState(loc, size, type, false, stride, data); 315 } 316 317 void GLEncoder::s_glWeightPointerOES(void * self, int size, GLenum type, GLsizei stride, const void * data) 318 { 319 GLEncoder *ctx = (GLEncoder *)self; 320 assert(ctx->m_state != NULL); 321 int loc = ctx->m_state->getLocation(GL_WEIGHT_ARRAY_OES); 322 ctx->m_state->setState(loc, size, type, false, stride, data); 323 } 324 325 void GLEncoder::s_glEnableClientState(void *self, GLenum state) 326 { 327 GLEncoder *ctx = (GLEncoder *) self; 328 assert(ctx->m_state != NULL); 329 int loc = ctx->m_state->getLocation(state); 330 ctx->m_state->enable(loc, 1); 331 } 332 333 void GLEncoder::s_glDisableClientState(void *self, GLenum state) 334 { 335 GLEncoder *ctx = (GLEncoder *) self; 336 assert(ctx->m_state != NULL); 337 int loc = ctx->m_state->getLocation(state); 338 ctx->m_state->enable(loc, 0); 339 } 340 341 GLboolean GLEncoder::s_glIsEnabled(void *self, GLenum cap) 342 { 343 GLEncoder *ctx = (GLEncoder *) self; 344 assert(ctx->m_state != NULL); 345 int loc = ctx->m_state->getLocation(cap); 346 const GLClientState::VertexAttribState *state = ctx->m_state->getState(loc); 347 348 if (state!=NULL) 349 return state->enabled; 350 351 return ctx->m_glIsEnabled_enc(self,cap); 352 } 353 354 void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id) 355 { 356 GLEncoder *ctx = (GLEncoder *) self; 357 assert(ctx->m_state != NULL); 358 ctx->m_state->bindBuffer(target, id); 359 // TODO set error state if needed; 360 ctx->m_glBindBuffer_enc(self, target, id); 361 } 362 363 void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) 364 { 365 GLEncoder *ctx = (GLEncoder *) self; 366 GLuint bufferId = ctx->m_state->getBuffer(target); 367 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 368 SET_ERROR_IF(size<0, GL_INVALID_VALUE); 369 370 ctx->m_shared->updateBufferData(bufferId, size, (void*)data); 371 ctx->m_glBufferData_enc(self, target, size, data, usage); 372 } 373 374 void GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) 375 { 376 GLEncoder *ctx = (GLEncoder *) self; 377 GLuint bufferId = ctx->m_state->getBuffer(target); 378 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 379 380 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data); 381 SET_ERROR_IF(res, res); 382 383 ctx->m_glBufferSubData_enc(self, target, offset, size, data); 384 } 385 386 void GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers) 387 { 388 GLEncoder *ctx = (GLEncoder *) self; 389 SET_ERROR_IF(n<0, GL_INVALID_VALUE); 390 for (int i=0; i<n; i++) { 391 ctx->m_shared->deleteBufferData(buffers[i]); 392 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]); 393 } 394 } 395 396 void GLEncoder::sendVertexData(unsigned int first, unsigned int count) 397 { 398 assert(m_state != NULL); 399 GLenum prevActiveTexUnit = m_state->getActiveTextureUnit(); 400 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 401 bool enableDirty; 402 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty); 403 404 // do not process if state not valid 405 if (!state) continue; 406 407 // do not send disable state if state was already disabled 408 if (!enableDirty && !state->enabled) continue; 409 410 if ( i >= GLClientState::TEXCOORD0_LOCATION && 411 i <= GLClientState::TEXCOORD7_LOCATION ) { 412 m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION); 413 } 414 415 if (state->enabled) { 416 if (enableDirty) 417 m_glEnableClientState_enc(this, state->glConst); 418 419 unsigned int datalen = state->elementSize * count; 420 int stride = state->stride; 421 if (stride == 0) stride = state->elementSize; 422 int firstIndex = stride * first; 423 424 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject); 425 if (state->bufferObject == 0) { 426 427 switch(i) { 428 case GLClientState::VERTEX_LOCATION: 429 this->glVertexPointerData(this, state->size, state->type, state->stride, 430 (unsigned char *)state->data + firstIndex, datalen); 431 break; 432 case GLClientState::NORMAL_LOCATION: 433 this->glNormalPointerData(this, state->type, state->stride, 434 (unsigned char *)state->data + firstIndex, datalen); 435 break; 436 case GLClientState::COLOR_LOCATION: 437 this->glColorPointerData(this, state->size, state->type, state->stride, 438 (unsigned char *)state->data + firstIndex, datalen); 439 break; 440 case GLClientState::TEXCOORD0_LOCATION: 441 case GLClientState::TEXCOORD1_LOCATION: 442 case GLClientState::TEXCOORD2_LOCATION: 443 case GLClientState::TEXCOORD3_LOCATION: 444 case GLClientState::TEXCOORD4_LOCATION: 445 case GLClientState::TEXCOORD5_LOCATION: 446 case GLClientState::TEXCOORD6_LOCATION: 447 case GLClientState::TEXCOORD7_LOCATION: 448 m_state->setActiveTextureUnit(i - GLClientState::TEXCOORD0_LOCATION + GL_TEXTURE0); 449 if (m_state->getPriorityEnabledTarget(GL_INVALID_ENUM) != GL_INVALID_ENUM) { 450 this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state->size, state->type, state->stride, 451 (unsigned char *)state->data + firstIndex, datalen); 452 } 453 break; 454 case GLClientState::POINTSIZE_LOCATION: 455 this->glPointSizePointerData(this, state->type, state->stride, 456 (unsigned char *) state->data + firstIndex, datalen); 457 break; 458 case GLClientState::WEIGHT_LOCATION: 459 this->glWeightPointerData(this, state->size, state->type, state->stride, 460 (unsigned char * ) state->data + firstIndex, datalen); 461 break; 462 case GLClientState::MATRIXINDEX_LOCATION: 463 this->glMatrixIndexPointerData(this, state->size, state->type, state->stride, 464 (unsigned char *)state->data + firstIndex, datalen); 465 break; 466 } 467 } else { 468 469 switch(i) { 470 case GLClientState::VERTEX_LOCATION: 471 this->glVertexPointerOffset(this, state->size, state->type, state->stride, 472 (uintptr_t)state->data + firstIndex); 473 break; 474 case GLClientState::NORMAL_LOCATION: 475 this->glNormalPointerOffset(this, state->type, state->stride, 476 (uintptr_t)state->data + firstIndex); 477 break; 478 case GLClientState::POINTSIZE_LOCATION: 479 this->glPointSizePointerOffset(this, state->type, state->stride, 480 (uintptr_t)state->data + firstIndex); 481 break; 482 case GLClientState::COLOR_LOCATION: 483 this->glColorPointerOffset(this, state->size, state->type, state->stride, 484 (uintptr_t)state->data + firstIndex); 485 break; 486 case GLClientState::TEXCOORD0_LOCATION: 487 case GLClientState::TEXCOORD1_LOCATION: 488 case GLClientState::TEXCOORD2_LOCATION: 489 case GLClientState::TEXCOORD3_LOCATION: 490 case GLClientState::TEXCOORD4_LOCATION: 491 case GLClientState::TEXCOORD5_LOCATION: 492 case GLClientState::TEXCOORD6_LOCATION: 493 case GLClientState::TEXCOORD7_LOCATION: 494 this->glTexCoordPointerOffset(this, state->size, state->type, state->stride, 495 (uintptr_t)state->data + firstIndex); 496 break; 497 case GLClientState::WEIGHT_LOCATION: 498 this->glWeightPointerOffset(this,state->size,state->type,state->stride, 499 (uintptr_t)state->data+firstIndex); 500 break; 501 case GLClientState::MATRIXINDEX_LOCATION: 502 this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride, 503 (uintptr_t)state->data+firstIndex); 504 break; 505 } 506 } 507 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); 508 } else { 509 this->m_glDisableClientState_enc(this, state->glConst); 510 } 511 } 512 m_state->setActiveTextureUnit(prevActiveTexUnit); 513 } 514 515 void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count) 516 { 517 GLEncoder *ctx = (GLEncoder *)self; 518 519 bool has_arrays = false; 520 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 521 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i); 522 if (state->enabled) { 523 if (state->bufferObject || state->data) { 524 has_arrays = true; 525 } else { 526 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n"); 527 ctx->setError(GL_INVALID_OPERATION); 528 return; 529 } 530 } 531 } 532 if (!has_arrays) { 533 ALOGE("glDrawArrays: no data bound to the command - ignoring\n"); 534 return; 535 } 536 537 ctx->sendVertexData(first, count); 538 ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count); 539 ctx->m_stream->flush(); 540 } 541 542 void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices) 543 { 544 545 GLEncoder *ctx = (GLEncoder *)self; 546 assert(ctx->m_state != NULL); 547 SET_ERROR_IF(count<0, GL_INVALID_VALUE); 548 549 bool has_immediate_arrays = false; 550 bool has_indirect_arrays = false; 551 552 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 553 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i); 554 if (state->enabled) { 555 if (state->bufferObject != 0) { 556 has_indirect_arrays = true; 557 } else if (state->data) { 558 has_immediate_arrays = true; 559 } else { 560 ALOGE("glDrawElements: a vertex attribute array is enabled with no data bound\n"); 561 ctx->setError(GL_INVALID_OPERATION); 562 return; 563 } 564 } 565 } 566 567 if (!has_immediate_arrays && !has_indirect_arrays) { 568 ALOGE("glDrawElements: no data bound to the command - ignoring\n"); 569 return; 570 } 571 572 bool adjustIndices = true; 573 if (ctx->m_state->currentIndexVbo() != 0) { 574 if (!has_immediate_arrays) { 575 ctx->sendVertexData(0, count); 576 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); 577 ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices); 578 ctx->m_stream->flush(); 579 adjustIndices = false; 580 } else { 581 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); 582 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); 583 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); 584 } 585 } 586 if (adjustIndices) { 587 void *adjustedIndices = (void*)indices; 588 int minIndex = 0, maxIndex = 0; 589 590 switch(type) { 591 case GL_BYTE: 592 case GL_UNSIGNED_BYTE: 593 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex); 594 if (minIndex != 0) { 595 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 596 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices, 597 (unsigned char *)adjustedIndices, 598 count, -minIndex); 599 } 600 break; 601 case GL_SHORT: 602 case GL_UNSIGNED_SHORT: 603 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex); 604 if (minIndex != 0) { 605 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 606 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices, 607 (unsigned short *)adjustedIndices, 608 count, -minIndex); 609 } 610 break; 611 case GL_INT: 612 case GL_UNSIGNED_INT: 613 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex); 614 if (minIndex != 0) { 615 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 616 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices, 617 (unsigned int *)adjustedIndices, 618 count, -minIndex); 619 } 620 break; 621 default: 622 ALOGE("unsupported index buffer type %d\n", type); 623 } 624 if (has_indirect_arrays || 1) { 625 ctx->sendVertexData(minIndex, maxIndex - minIndex + 1); 626 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, 627 count * glSizeof(type)); 628 ctx->m_stream->flush(); 629 // XXX - OPTIMIZATION (see the other else branch) should be implemented 630 if(!has_indirect_arrays) { 631 //ALOGD("unoptimized drawelements !!!\n"); 632 } 633 } else { 634 // we are all direct arrays and immidate mode index array - 635 // rebuild the arrays and the index array; 636 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); 637 } 638 } 639 } 640 641 void GLEncoder::s_glActiveTexture(void* self, GLenum texture) 642 { 643 GLEncoder* ctx = (GLEncoder*)self; 644 GLClientState* state = ctx->m_state; 645 GLenum err; 646 647 if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) { 648 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 649 ctx->setError(err); 650 return; 651 } 652 653 ctx->m_glActiveTexture_enc(ctx, texture); 654 } 655 656 void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture) 657 { 658 GLEncoder* ctx = (GLEncoder*)self; 659 GLClientState* state = ctx->m_state; 660 GLenum err; 661 662 GLboolean firstUse; 663 if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) { 664 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 665 ctx->setError(err); 666 return; 667 } 668 669 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { 670 ctx->m_glBindTexture_enc(ctx, target, texture); 671 return; 672 } 673 674 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); 675 676 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { 677 // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D 678 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 679 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 680 GL_TEXTURE_MIN_FILTER, GL_LINEAR); 681 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 682 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 683 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 684 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 685 686 if (target != priorityTarget) { 687 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 688 state->getBoundTexture(GL_TEXTURE_2D)); 689 } 690 } 691 692 if (target == priorityTarget) { 693 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 694 } 695 } 696 697 void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) 698 { 699 GLEncoder* ctx = (GLEncoder*)self; 700 GLClientState* state = ctx->m_state; 701 702 state->deleteTextures(n, textures); 703 ctx->m_glDeleteTextures_enc(ctx, n, textures); 704 } 705 706 void GLEncoder::s_glDisable(void* self, GLenum cap) 707 { 708 GLEncoder* ctx = (GLEncoder*)self; 709 GLClientState* state = ctx->m_state; 710 711 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 712 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 713 state->disableTextureTarget(cap); 714 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 715 716 if (prevTarget != currTarget) { 717 if (currTarget == GL_INVALID_ENUM) { 718 ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D); 719 currTarget = GL_TEXTURE_2D; 720 } 721 // maintain the invariant that when TEXTURE_EXTERNAL_OES is 722 // disabled, the TEXTURE_2D binding is active, even if 723 // TEXTURE_2D is also disabled. 724 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 725 state->getBoundTexture(currTarget)); 726 } 727 728 } else { 729 ctx->m_glDisable_enc(ctx, cap); 730 } 731 } 732 733 void GLEncoder::s_glEnable(void* self, GLenum cap) 734 { 735 GLEncoder* ctx = (GLEncoder*)self; 736 GLClientState* state = ctx->m_state; 737 738 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 739 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 740 state->enableTextureTarget(cap); 741 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 742 743 if (prevTarget != currTarget) { 744 if (prevTarget == GL_INVALID_ENUM) { 745 ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D); 746 } 747 if (currTarget == GL_TEXTURE_EXTERNAL_OES) { 748 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 749 state->getBoundTexture(currTarget)); 750 } 751 } 752 753 } else { 754 ctx->m_glEnable_enc(ctx, cap); 755 } 756 } 757 758 void GLEncoder::s_glGetTexParameterfv(void* self, 759 GLenum target, GLenum pname, GLfloat* params) 760 { 761 GLEncoder* ctx = (GLEncoder*)self; 762 const GLClientState* state = ctx->m_state; 763 764 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 765 ctx->override2DTextureTarget(target); 766 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 767 ctx->restore2DTextureTarget(); 768 } else { 769 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); 770 } 771 } 772 773 void GLEncoder::s_glGetTexParameteriv(void* self, 774 GLenum target, GLenum pname, GLint* params) 775 { 776 GLEncoder* ctx = (GLEncoder*)self; 777 const GLClientState* state = ctx->m_state; 778 779 switch (pname) { 780 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 781 *params = 1; 782 break; 783 784 default: 785 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 786 ctx->override2DTextureTarget(target); 787 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 788 ctx->restore2DTextureTarget(); 789 } else { 790 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); 791 } 792 break; 793 } 794 } 795 796 void GLEncoder::s_glGetTexParameterxv(void* self, 797 GLenum target, GLenum pname, GLfixed* params) 798 { 799 GLEncoder* ctx = (GLEncoder*)self; 800 const GLClientState* state = ctx->m_state; 801 802 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 803 ctx->override2DTextureTarget(target); 804 ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 805 ctx->restore2DTextureTarget(); 806 } else { 807 ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params); 808 } 809 } 810 811 static bool isValidTextureExternalParam(GLenum pname, GLenum param) 812 { 813 switch (pname) { 814 case GL_TEXTURE_MIN_FILTER: 815 case GL_TEXTURE_MAG_FILTER: 816 return param == GL_NEAREST || param == GL_LINEAR; 817 818 case GL_TEXTURE_WRAP_S: 819 case GL_TEXTURE_WRAP_T: 820 return param == GL_CLAMP_TO_EDGE; 821 822 case GL_GENERATE_MIPMAP: 823 return param == GL_FALSE; 824 825 default: 826 return true; 827 } 828 } 829 830 void GLEncoder::s_glTexParameterf(void* self, 831 GLenum target, GLenum pname, GLfloat param) 832 { 833 GLEncoder* ctx = (GLEncoder*)self; 834 const GLClientState* state = ctx->m_state; 835 836 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 837 !isValidTextureExternalParam(pname, (GLenum)param)), 838 GL_INVALID_ENUM); 839 840 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 841 ctx->override2DTextureTarget(target); 842 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); 843 ctx->restore2DTextureTarget(); 844 } else { 845 ctx->m_glTexParameterf_enc(ctx, target, pname, param); 846 } 847 } 848 849 void GLEncoder::s_glTexParameterfv(void* self, 850 GLenum target, GLenum pname, const GLfloat* params) 851 { 852 GLEncoder* ctx = (GLEncoder*)self; 853 const GLClientState* state = ctx->m_state; 854 855 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 856 !isValidTextureExternalParam(pname, (GLenum)params[0])), 857 GL_INVALID_ENUM); 858 859 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 860 ctx->override2DTextureTarget(target); 861 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 862 ctx->restore2DTextureTarget(); 863 } else { 864 ctx->m_glTexParameterfv_enc(ctx, target, pname, params); 865 } 866 } 867 868 void GLEncoder::s_glTexParameteri(void* self, 869 GLenum target, GLenum pname, GLint param) 870 { 871 GLEncoder* ctx = (GLEncoder*)self; 872 const GLClientState* state = ctx->m_state; 873 874 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 875 !isValidTextureExternalParam(pname, (GLenum)param)), 876 GL_INVALID_ENUM); 877 878 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 879 ctx->override2DTextureTarget(target); 880 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); 881 ctx->restore2DTextureTarget(); 882 } else { 883 ctx->m_glTexParameteri_enc(ctx, target, pname, param); 884 } 885 } 886 887 void GLEncoder::s_glTexParameterx(void* self, 888 GLenum target, GLenum pname, GLfixed param) 889 { 890 GLEncoder* ctx = (GLEncoder*)self; 891 const GLClientState* state = ctx->m_state; 892 893 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 894 !isValidTextureExternalParam(pname, (GLenum)param)), 895 GL_INVALID_ENUM); 896 897 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 898 ctx->override2DTextureTarget(target); 899 ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param); 900 ctx->restore2DTextureTarget(); 901 } else { 902 ctx->m_glTexParameterx_enc(ctx, target, pname, param); 903 } 904 } 905 906 void GLEncoder::s_glTexParameteriv(void* self, 907 GLenum target, GLenum pname, const GLint* params) 908 { 909 GLEncoder* ctx = (GLEncoder*)self; 910 const GLClientState* state = ctx->m_state; 911 912 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 913 !isValidTextureExternalParam(pname, (GLenum)params[0])), 914 GL_INVALID_ENUM); 915 916 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 917 ctx->override2DTextureTarget(target); 918 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 919 ctx->restore2DTextureTarget(); 920 } else { 921 ctx->m_glTexParameteriv_enc(ctx, target, pname, params); 922 } 923 } 924 925 void GLEncoder::s_glTexParameterxv(void* self, 926 GLenum target, GLenum pname, const GLfixed* params) 927 { 928 GLEncoder* ctx = (GLEncoder*)self; 929 const GLClientState* state = ctx->m_state; 930 931 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 932 !isValidTextureExternalParam(pname, (GLenum)params[0])), 933 GL_INVALID_ENUM); 934 935 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 936 ctx->override2DTextureTarget(target); 937 ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 938 ctx->restore2DTextureTarget(); 939 } else { 940 ctx->m_glTexParameterxv_enc(ctx, target, pname, params); 941 } 942 } 943 944 void GLEncoder::override2DTextureTarget(GLenum target) 945 { 946 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && 947 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) { 948 m_glBindTexture_enc(this, GL_TEXTURE_2D, 949 m_state->getBoundTexture(target)); 950 } 951 } 952 953 void GLEncoder::restore2DTextureTarget() 954 { 955 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); 956 m_glBindTexture_enc(this, GL_TEXTURE_2D, 957 m_state->getBoundTexture(priorityTarget)); 958 } 959 960 void GLEncoder::s_glGenFramebuffersOES(void* self, 961 GLsizei n, GLuint* framebuffers) { 962 GLEncoder* ctx = (GLEncoder*)self; 963 GLClientState* state = ctx->m_state; 964 965 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 966 967 ctx->m_glGenFramebuffersOES_enc(self, n, framebuffers); 968 state->addFramebuffers(n, framebuffers); 969 } 970 971 void GLEncoder::s_glDeleteFramebuffersOES(void* self, 972 GLsizei n, const GLuint* framebuffers) { 973 GLEncoder* ctx = (GLEncoder*)self; 974 GLClientState* state = ctx->m_state; 975 976 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 977 978 ctx->m_glDeleteFramebuffersOES_enc(self, n, framebuffers); 979 state->removeFramebuffers(n, framebuffers); 980 } 981 982 void GLEncoder::s_glBindFramebufferOES(void* self, 983 GLenum target, GLuint framebuffer) { 984 GLEncoder* ctx = (GLEncoder*)self; 985 GLClientState* state = ctx->m_state; 986 987 SET_ERROR_IF((target != GL_FRAMEBUFFER), 988 GL_INVALID_ENUM); 989 990 state->bindFramebuffer(target, framebuffer); 991 992 ctx->m_glBindFramebufferOES_enc(self, target, framebuffer); 993 } 994 995 void GLEncoder::s_glFramebufferTexture2DOES(void*self, 996 GLenum target, GLenum attachment, 997 GLenum textarget, GLuint texture, GLint level) { 998 GLEncoder* ctx = (GLEncoder*)self; 999 GLClientState* state = ctx->m_state; 1000 1001 state->attachTextureObject(attachment, texture); 1002 1003 ctx->m_glFramebufferTexture2DOES_enc(self, target, attachment, textarget, texture, level); 1004 } 1005 1006 void GLEncoder::s_glFramebufferTexture2DMultisampleIMG(void* self, 1007 GLenum target, GLenum attachment, 1008 GLenum textarget, GLuint texture, GLint level, GLsizei samples) { 1009 GLEncoder* ctx = (GLEncoder*)self; 1010 GLClientState* state = ctx->m_state; 1011 1012 state->attachTextureObject(attachment, texture); 1013 1014 ctx->m_glFramebufferTexture2DMultisampleIMG_enc(self, target, attachment, textarget, texture, level, samples); 1015 } 1016 1017 void GLEncoder::s_glGetFramebufferAttachmentParameterivOES(void* self, 1018 GLenum target, GLenum attachment, GLenum pname, GLint* params) 1019 { 1020 GLEncoder* ctx = (GLEncoder*)self; 1021 const GLClientState* state = ctx->m_state; 1022 1023 SET_ERROR_IF(state->boundFramebuffer() == 0, 1024 GL_INVALID_OPERATION); 1025 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) && 1026 (!state->attachmentHasObject(attachment)), 1027 GL_INVALID_ENUM); 1028 1029 ctx->m_glGetFramebufferAttachmentParameterivOES_enc(self, target, attachment, pname, params); 1030 } 1031 1032 GLEncoder::GLEncoder(IOStream *stream, ChecksumCalculator *protocol) 1033 : gl_encoder_context_t(stream, protocol) 1034 { 1035 m_initialized = false; 1036 m_state = NULL; 1037 m_error = GL_NO_ERROR; 1038 m_num_compressedTextureFormats = 0; 1039 m_compressedTextureFormats = NULL; 1040 1041 // overrides; 1042 #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name 1043 1044 OVERRIDE(glFlush); 1045 OVERRIDE(glPixelStorei); 1046 OVERRIDE(glVertexPointer); 1047 OVERRIDE(glNormalPointer); 1048 OVERRIDE(glColorPointer); 1049 OVERRIDE(glPointSizePointerOES); 1050 OVERRIDE(glClientActiveTexture); 1051 OVERRIDE(glTexCoordPointer); 1052 OVERRIDE(glMatrixIndexPointerOES); 1053 OVERRIDE(glWeightPointerOES); 1054 1055 OVERRIDE(glGetIntegerv); 1056 OVERRIDE(glGetFloatv); 1057 OVERRIDE(glGetBooleanv); 1058 OVERRIDE(glGetFixedv); 1059 OVERRIDE(glGetPointerv); 1060 1061 OVERRIDE(glBindBuffer); 1062 OVERRIDE(glBufferData); 1063 OVERRIDE(glBufferSubData); 1064 OVERRIDE(glDeleteBuffers); 1065 1066 OVERRIDE(glEnableClientState); 1067 OVERRIDE(glDisableClientState); 1068 OVERRIDE(glIsEnabled); 1069 OVERRIDE(glDrawArrays); 1070 OVERRIDE(glDrawElements); 1071 1072 this->glGetString = s_glGetString; 1073 this->glFinish = s_glFinish; 1074 1075 OVERRIDE(glGetError); 1076 1077 OVERRIDE(glActiveTexture); 1078 OVERRIDE(glBindTexture); 1079 OVERRIDE(glDeleteTextures); 1080 OVERRIDE(glDisable); 1081 OVERRIDE(glEnable); 1082 OVERRIDE(glGetTexParameterfv); 1083 OVERRIDE(glGetTexParameteriv); 1084 OVERRIDE(glGetTexParameterxv); 1085 OVERRIDE(glTexParameterf); 1086 OVERRIDE(glTexParameterfv); 1087 OVERRIDE(glTexParameteri); 1088 OVERRIDE(glTexParameterx); 1089 OVERRIDE(glTexParameteriv); 1090 OVERRIDE(glTexParameterxv); 1091 1092 OVERRIDE(glGenFramebuffersOES); 1093 OVERRIDE(glDeleteFramebuffersOES); 1094 OVERRIDE(glBindFramebufferOES); 1095 OVERRIDE(glFramebufferTexture2DOES); 1096 OVERRIDE(glFramebufferTexture2DMultisampleIMG); 1097 OVERRIDE(glGetFramebufferAttachmentParameterivOES); 1098 } 1099 1100 GLEncoder::~GLEncoder() 1101 { 1102 delete [] m_compressedTextureFormats; 1103 } 1104 1105 size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) 1106 { 1107 assert(m_state != NULL); 1108 return m_state->pixelDataSize(width, height, format, type, pack); 1109 } 1110 1111 void GLEncoder::s_glFinish(void *self) 1112 { 1113 GLEncoder *ctx = (GLEncoder *)self; 1114 ctx->glFinishRoundTrip(self); 1115 } 1116