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 *) ""; // no extensions at this point; 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 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 400 bool enableDirty; 401 const GLClientState::VertexAttribState *state = m_state->getStateAndEnableDirty(i, &enableDirty); 402 403 // do not process if state not valid 404 if (!state) continue; 405 406 // do not send disable state if state was already disabled 407 if (!enableDirty && !state->enabled) continue; 408 409 if ( i >= GLClientState::TEXCOORD0_LOCATION && 410 i <= GLClientState::TEXCOORD7_LOCATION ) { 411 m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION); 412 } 413 414 if (state->enabled) { 415 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 if (state->bufferObject == 0) { 425 426 switch(i) { 427 case GLClientState::VERTEX_LOCATION: 428 this->glVertexPointerData(this, state->size, state->type, state->stride, 429 (unsigned char *)state->data + firstIndex, datalen); 430 break; 431 case GLClientState::NORMAL_LOCATION: 432 this->glNormalPointerData(this, state->type, state->stride, 433 (unsigned char *)state->data + firstIndex, datalen); 434 break; 435 case GLClientState::COLOR_LOCATION: 436 this->glColorPointerData(this, state->size, state->type, state->stride, 437 (unsigned char *)state->data + firstIndex, datalen); 438 break; 439 case GLClientState::TEXCOORD0_LOCATION: 440 case GLClientState::TEXCOORD1_LOCATION: 441 case GLClientState::TEXCOORD2_LOCATION: 442 case GLClientState::TEXCOORD3_LOCATION: 443 case GLClientState::TEXCOORD4_LOCATION: 444 case GLClientState::TEXCOORD5_LOCATION: 445 case GLClientState::TEXCOORD6_LOCATION: 446 case GLClientState::TEXCOORD7_LOCATION: 447 this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state->size, state->type, state->stride, 448 (unsigned char *)state->data + firstIndex, datalen); 449 break; 450 case GLClientState::POINTSIZE_LOCATION: 451 this->glPointSizePointerData(this, state->type, state->stride, 452 (unsigned char *) state->data + firstIndex, datalen); 453 break; 454 case GLClientState::WEIGHT_LOCATION: 455 this->glWeightPointerData(this, state->size, state->type, state->stride, 456 (unsigned char * ) state->data + firstIndex, datalen); 457 break; 458 case GLClientState::MATRIXINDEX_LOCATION: 459 this->glMatrixIndexPointerData(this, state->size, state->type, state->stride, 460 (unsigned char *)state->data + firstIndex, datalen); 461 break; 462 } 463 } else { 464 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state->bufferObject); 465 466 switch(i) { 467 case GLClientState::VERTEX_LOCATION: 468 this->glVertexPointerOffset(this, state->size, state->type, state->stride, 469 (uintptr_t)state->data + firstIndex); 470 break; 471 case GLClientState::NORMAL_LOCATION: 472 this->glNormalPointerOffset(this, state->type, state->stride, 473 (uintptr_t)state->data + firstIndex); 474 break; 475 case GLClientState::POINTSIZE_LOCATION: 476 this->glPointSizePointerOffset(this, state->type, state->stride, 477 (uintptr_t)state->data + firstIndex); 478 break; 479 case GLClientState::COLOR_LOCATION: 480 this->glColorPointerOffset(this, state->size, state->type, state->stride, 481 (uintptr_t)state->data + firstIndex); 482 break; 483 case GLClientState::TEXCOORD0_LOCATION: 484 case GLClientState::TEXCOORD1_LOCATION: 485 case GLClientState::TEXCOORD2_LOCATION: 486 case GLClientState::TEXCOORD3_LOCATION: 487 case GLClientState::TEXCOORD4_LOCATION: 488 case GLClientState::TEXCOORD5_LOCATION: 489 case GLClientState::TEXCOORD6_LOCATION: 490 case GLClientState::TEXCOORD7_LOCATION: 491 this->glTexCoordPointerOffset(this, state->size, state->type, state->stride, 492 (uintptr_t)state->data + firstIndex); 493 break; 494 case GLClientState::WEIGHT_LOCATION: 495 this->glWeightPointerOffset(this,state->size,state->type,state->stride, 496 (uintptr_t)state->data+firstIndex); 497 break; 498 case GLClientState::MATRIXINDEX_LOCATION: 499 this->glMatrixIndexPointerOffset(this,state->size,state->type,state->stride, 500 (uintptr_t)state->data+firstIndex); 501 break; 502 } 503 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); 504 } 505 } else { 506 this->m_glDisableClientState_enc(this, state->glConst); 507 } 508 } 509 } 510 511 void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count) 512 { 513 GLEncoder *ctx = (GLEncoder *)self; 514 515 ctx->sendVertexData(first, count); 516 ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count); 517 } 518 519 void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices) 520 { 521 522 GLEncoder *ctx = (GLEncoder *)self; 523 assert(ctx->m_state != NULL); 524 SET_ERROR_IF(count<0, GL_INVALID_VALUE); 525 526 bool has_immediate_arrays = false; 527 bool has_indirect_arrays = false; 528 529 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 530 const GLClientState::VertexAttribState *state = ctx->m_state->getState(i); 531 if (state->enabled) { 532 if (state->bufferObject != 0) { 533 has_indirect_arrays = true; 534 } else { 535 has_immediate_arrays = true; 536 } 537 } 538 } 539 540 if (!has_immediate_arrays && !has_indirect_arrays) { 541 ALOGE("glDrawElements: no data bound to the command - ignoring\n"); 542 return; 543 } 544 545 bool adjustIndices = true; 546 if (ctx->m_state->currentIndexVbo() != 0) { 547 if (!has_immediate_arrays) { 548 ctx->sendVertexData(0, count); 549 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); 550 ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices); 551 adjustIndices = false; 552 } else { 553 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); 554 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); 555 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); 556 } 557 } 558 if (adjustIndices) { 559 void *adjustedIndices = (void*)indices; 560 int minIndex = 0, maxIndex = 0; 561 562 switch(type) { 563 case GL_BYTE: 564 case GL_UNSIGNED_BYTE: 565 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex); 566 if (minIndex != 0) { 567 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 568 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices, 569 (unsigned char *)adjustedIndices, 570 count, -minIndex); 571 } 572 break; 573 case GL_SHORT: 574 case GL_UNSIGNED_SHORT: 575 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex); 576 if (minIndex != 0) { 577 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 578 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices, 579 (unsigned short *)adjustedIndices, 580 count, -minIndex); 581 } 582 break; 583 default: 584 ALOGE("unsupported index buffer type %d\n", type); 585 } 586 if (has_indirect_arrays || 1) { 587 ctx->sendVertexData(minIndex, maxIndex - minIndex + 1); 588 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, 589 count * glSizeof(type)); 590 // XXX - OPTIMIZATION (see the other else branch) should be implemented 591 if(!has_indirect_arrays) { 592 //ALOGD("unoptimized drawelements !!!\n"); 593 } 594 } else { 595 // we are all direct arrays and immidate mode index array - 596 // rebuild the arrays and the index array; 597 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); 598 } 599 } 600 } 601 602 void GLEncoder::s_glActiveTexture(void* self, GLenum texture) 603 { 604 GLEncoder* ctx = (GLEncoder*)self; 605 GLClientState* state = ctx->m_state; 606 GLenum err; 607 608 if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) { 609 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 610 ctx->setError(err); 611 return; 612 } 613 614 ctx->m_glActiveTexture_enc(ctx, texture); 615 } 616 617 void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture) 618 { 619 GLEncoder* ctx = (GLEncoder*)self; 620 GLClientState* state = ctx->m_state; 621 GLenum err; 622 623 GLboolean firstUse; 624 if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) { 625 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 626 ctx->setError(err); 627 return; 628 } 629 630 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { 631 ctx->m_glBindTexture_enc(ctx, target, texture); 632 return; 633 } 634 635 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); 636 637 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { 638 // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D 639 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 640 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 641 GL_TEXTURE_MIN_FILTER, GL_LINEAR); 642 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 643 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 644 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 645 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 646 647 if (target != priorityTarget) { 648 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 649 state->getBoundTexture(GL_TEXTURE_2D)); 650 } 651 } 652 653 if (target == priorityTarget) { 654 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 655 } 656 } 657 658 void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) 659 { 660 GLEncoder* ctx = (GLEncoder*)self; 661 GLClientState* state = ctx->m_state; 662 663 state->deleteTextures(n, textures); 664 ctx->m_glDeleteTextures_enc(ctx, n, textures); 665 } 666 667 void GLEncoder::s_glDisable(void* self, GLenum cap) 668 { 669 GLEncoder* ctx = (GLEncoder*)self; 670 GLClientState* state = ctx->m_state; 671 672 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 673 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 674 state->disableTextureTarget(cap); 675 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 676 677 if (prevTarget != currTarget) { 678 if (currTarget == GL_INVALID_ENUM) { 679 ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D); 680 currTarget = GL_TEXTURE_2D; 681 } 682 // maintain the invariant that when TEXTURE_EXTERNAL_OES is 683 // disabled, the TEXTURE_2D binding is active, even if 684 // TEXTURE_2D is also disabled. 685 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 686 state->getBoundTexture(currTarget)); 687 } 688 689 } else { 690 ctx->m_glDisable_enc(ctx, cap); 691 } 692 } 693 694 void GLEncoder::s_glEnable(void* self, GLenum cap) 695 { 696 GLEncoder* ctx = (GLEncoder*)self; 697 GLClientState* state = ctx->m_state; 698 699 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 700 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 701 state->enableTextureTarget(cap); 702 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 703 704 if (prevTarget != currTarget) { 705 if (prevTarget == GL_INVALID_ENUM) { 706 ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D); 707 } 708 if (currTarget == GL_TEXTURE_EXTERNAL_OES) { 709 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 710 state->getBoundTexture(currTarget)); 711 } 712 } 713 714 } else { 715 ctx->m_glEnable_enc(ctx, cap); 716 } 717 } 718 719 void GLEncoder::s_glGetTexParameterfv(void* self, 720 GLenum target, GLenum pname, GLfloat* params) 721 { 722 GLEncoder* ctx = (GLEncoder*)self; 723 const GLClientState* state = ctx->m_state; 724 725 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 726 ctx->override2DTextureTarget(target); 727 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 728 ctx->restore2DTextureTarget(); 729 } else { 730 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); 731 } 732 } 733 734 void GLEncoder::s_glGetTexParameteriv(void* self, 735 GLenum target, GLenum pname, GLint* params) 736 { 737 GLEncoder* ctx = (GLEncoder*)self; 738 const GLClientState* state = ctx->m_state; 739 740 switch (pname) { 741 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 742 *params = 1; 743 break; 744 745 default: 746 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 747 ctx->override2DTextureTarget(target); 748 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 749 ctx->restore2DTextureTarget(); 750 } else { 751 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); 752 } 753 break; 754 } 755 } 756 757 void GLEncoder::s_glGetTexParameterxv(void* self, 758 GLenum target, GLenum pname, GLfixed* params) 759 { 760 GLEncoder* ctx = (GLEncoder*)self; 761 const GLClientState* state = ctx->m_state; 762 763 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 764 ctx->override2DTextureTarget(target); 765 ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 766 ctx->restore2DTextureTarget(); 767 } else { 768 ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params); 769 } 770 } 771 772 static bool isValidTextureExternalParam(GLenum pname, GLenum param) 773 { 774 switch (pname) { 775 case GL_TEXTURE_MIN_FILTER: 776 case GL_TEXTURE_MAG_FILTER: 777 return param == GL_NEAREST || param == GL_LINEAR; 778 779 case GL_TEXTURE_WRAP_S: 780 case GL_TEXTURE_WRAP_T: 781 return param == GL_CLAMP_TO_EDGE; 782 783 case GL_GENERATE_MIPMAP: 784 return param == GL_FALSE; 785 786 default: 787 return true; 788 } 789 } 790 791 void GLEncoder::s_glTexParameterf(void* self, 792 GLenum target, GLenum pname, GLfloat param) 793 { 794 GLEncoder* ctx = (GLEncoder*)self; 795 const GLClientState* state = ctx->m_state; 796 797 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 798 !isValidTextureExternalParam(pname, (GLenum)param)), 799 GL_INVALID_ENUM); 800 801 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 802 ctx->override2DTextureTarget(target); 803 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); 804 ctx->restore2DTextureTarget(); 805 } else { 806 ctx->m_glTexParameterf_enc(ctx, target, pname, param); 807 } 808 } 809 810 void GLEncoder::s_glTexParameterfv(void* self, 811 GLenum target, GLenum pname, const GLfloat* params) 812 { 813 GLEncoder* ctx = (GLEncoder*)self; 814 const GLClientState* state = ctx->m_state; 815 816 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 817 !isValidTextureExternalParam(pname, (GLenum)params[0])), 818 GL_INVALID_ENUM); 819 820 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 821 ctx->override2DTextureTarget(target); 822 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 823 ctx->restore2DTextureTarget(); 824 } else { 825 ctx->m_glTexParameterfv_enc(ctx, target, pname, params); 826 } 827 } 828 829 void GLEncoder::s_glTexParameteri(void* self, 830 GLenum target, GLenum pname, GLint param) 831 { 832 GLEncoder* ctx = (GLEncoder*)self; 833 const GLClientState* state = ctx->m_state; 834 835 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 836 !isValidTextureExternalParam(pname, (GLenum)param)), 837 GL_INVALID_ENUM); 838 839 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 840 ctx->override2DTextureTarget(target); 841 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); 842 ctx->restore2DTextureTarget(); 843 } else { 844 ctx->m_glTexParameteri_enc(ctx, target, pname, param); 845 } 846 } 847 848 void GLEncoder::s_glTexParameterx(void* self, 849 GLenum target, GLenum pname, GLfixed param) 850 { 851 GLEncoder* ctx = (GLEncoder*)self; 852 const GLClientState* state = ctx->m_state; 853 854 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 855 !isValidTextureExternalParam(pname, (GLenum)param)), 856 GL_INVALID_ENUM); 857 858 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 859 ctx->override2DTextureTarget(target); 860 ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param); 861 ctx->restore2DTextureTarget(); 862 } else { 863 ctx->m_glTexParameterx_enc(ctx, target, pname, param); 864 } 865 } 866 867 void GLEncoder::s_glTexParameteriv(void* self, 868 GLenum target, GLenum pname, const GLint* params) 869 { 870 GLEncoder* ctx = (GLEncoder*)self; 871 const GLClientState* state = ctx->m_state; 872 873 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 874 !isValidTextureExternalParam(pname, (GLenum)params[0])), 875 GL_INVALID_ENUM); 876 877 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 878 ctx->override2DTextureTarget(target); 879 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 880 ctx->restore2DTextureTarget(); 881 } else { 882 ctx->m_glTexParameteriv_enc(ctx, target, pname, params); 883 } 884 } 885 886 void GLEncoder::s_glTexParameterxv(void* self, 887 GLenum target, GLenum pname, const GLfixed* params) 888 { 889 GLEncoder* ctx = (GLEncoder*)self; 890 const GLClientState* state = ctx->m_state; 891 892 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 893 !isValidTextureExternalParam(pname, (GLenum)params[0])), 894 GL_INVALID_ENUM); 895 896 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 897 ctx->override2DTextureTarget(target); 898 ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 899 ctx->restore2DTextureTarget(); 900 } else { 901 ctx->m_glTexParameterxv_enc(ctx, target, pname, params); 902 } 903 } 904 905 void GLEncoder::override2DTextureTarget(GLenum target) 906 { 907 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && 908 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) { 909 m_glBindTexture_enc(this, GL_TEXTURE_2D, 910 m_state->getBoundTexture(target)); 911 } 912 } 913 914 void GLEncoder::restore2DTextureTarget() 915 { 916 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); 917 m_glBindTexture_enc(this, GL_TEXTURE_2D, 918 m_state->getBoundTexture(priorityTarget)); 919 } 920 921 GLEncoder::GLEncoder(IOStream *stream) : gl_encoder_context_t(stream) 922 { 923 m_initialized = false; 924 m_state = NULL; 925 m_error = GL_NO_ERROR; 926 m_num_compressedTextureFormats = 0; 927 m_compressedTextureFormats = NULL; 928 929 // overrides; 930 #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name 931 932 OVERRIDE(glFlush); 933 OVERRIDE(glPixelStorei); 934 OVERRIDE(glVertexPointer); 935 OVERRIDE(glNormalPointer); 936 OVERRIDE(glColorPointer); 937 OVERRIDE(glPointSizePointerOES); 938 OVERRIDE(glClientActiveTexture); 939 OVERRIDE(glTexCoordPointer); 940 OVERRIDE(glMatrixIndexPointerOES); 941 OVERRIDE(glWeightPointerOES); 942 943 OVERRIDE(glGetIntegerv); 944 OVERRIDE(glGetFloatv); 945 OVERRIDE(glGetBooleanv); 946 OVERRIDE(glGetFixedv); 947 OVERRIDE(glGetPointerv); 948 949 OVERRIDE(glBindBuffer); 950 OVERRIDE(glBufferData); 951 OVERRIDE(glBufferSubData); 952 OVERRIDE(glDeleteBuffers); 953 954 OVERRIDE(glEnableClientState); 955 OVERRIDE(glDisableClientState); 956 OVERRIDE(glIsEnabled); 957 OVERRIDE(glDrawArrays); 958 OVERRIDE(glDrawElements); 959 960 this->glGetString = s_glGetString; 961 this->glFinish = s_glFinish; 962 963 OVERRIDE(glGetError); 964 965 OVERRIDE(glActiveTexture); 966 OVERRIDE(glBindTexture); 967 OVERRIDE(glDeleteTextures); 968 OVERRIDE(glDisable); 969 OVERRIDE(glEnable); 970 OVERRIDE(glGetTexParameterfv); 971 OVERRIDE(glGetTexParameteriv); 972 OVERRIDE(glGetTexParameterxv); 973 OVERRIDE(glTexParameterf); 974 OVERRIDE(glTexParameterfv); 975 OVERRIDE(glTexParameteri); 976 OVERRIDE(glTexParameterx); 977 OVERRIDE(glTexParameteriv); 978 OVERRIDE(glTexParameterxv); 979 } 980 981 GLEncoder::~GLEncoder() 982 { 983 delete [] m_compressedTextureFormats; 984 } 985 986 size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) 987 { 988 assert(m_state != NULL); 989 return m_state->pixelDataSize(width, height, format, type, pack); 990 } 991 992 void GLEncoder::s_glFinish(void *self) 993 { 994 GLEncoder *ctx = (GLEncoder *)self; 995 ctx->glFinishRoundTrip(self); 996 } 997