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->setVertexAttribState(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->setVertexAttribState(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->setVertexAttribState(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->setVertexAttribState(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->setVertexAttribState(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->setVertexAttribState(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->setVertexAttribState(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 return state.enabled; 348 } 349 350 void GLEncoder::s_glBindBuffer(void *self, GLenum target, GLuint id) 351 { 352 GLEncoder *ctx = (GLEncoder *) self; 353 assert(ctx->m_state != NULL); 354 ctx->m_state->bindBuffer(target, id); 355 // TODO set error state if needed; 356 ctx->m_glBindBuffer_enc(self, target, id); 357 } 358 359 void GLEncoder::s_glBufferData(void * self, GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) 360 { 361 GLEncoder *ctx = (GLEncoder *) self; 362 GLuint bufferId = ctx->m_state->getBuffer(target); 363 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 364 SET_ERROR_IF(size<0, GL_INVALID_VALUE); 365 366 ctx->m_shared->updateBufferData(bufferId, size, (void*)data); 367 ctx->m_glBufferData_enc(self, target, size, data, usage); 368 } 369 370 void GLEncoder::s_glBufferSubData(void * self, GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) 371 { 372 GLEncoder *ctx = (GLEncoder *) self; 373 GLuint bufferId = ctx->m_state->getBuffer(target); 374 SET_ERROR_IF(bufferId==0, GL_INVALID_OPERATION); 375 376 GLenum res = ctx->m_shared->subUpdateBufferData(bufferId, offset, size, (void*)data); 377 SET_ERROR_IF(res, res); 378 379 ctx->m_glBufferSubData_enc(self, target, offset, size, data); 380 } 381 382 void GLEncoder::s_glDeleteBuffers(void * self, GLsizei n, const GLuint * buffers) 383 { 384 GLEncoder *ctx = (GLEncoder *) self; 385 SET_ERROR_IF(n<0, GL_INVALID_VALUE); 386 for (int i=0; i<n; i++) { 387 ctx->m_shared->deleteBufferData(buffers[i]); 388 ctx->m_glDeleteBuffers_enc(self,1,&buffers[i]); 389 } 390 } 391 392 void GLEncoder::sendVertexData(unsigned int first, unsigned int count) 393 { 394 assert(m_state != NULL); 395 GLenum prevActiveTexUnit = m_state->getActiveTextureUnit(); 396 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 397 bool enableDirty; 398 const GLClientState::VertexAttribState& state = m_state->getStateAndEnableDirty(i, &enableDirty); 399 400 // do not send disable state if state was already disabled 401 if (!enableDirty && !state.enabled) continue; 402 403 if ( i >= GLClientState::TEXCOORD0_LOCATION && 404 i <= GLClientState::TEXCOORD7_LOCATION ) { 405 m_glClientActiveTexture_enc(this, GL_TEXTURE0 + i - GLClientState::TEXCOORD0_LOCATION); 406 } 407 408 if (state.enabled) { 409 if (enableDirty) 410 m_glEnableClientState_enc(this, state.glConst); 411 412 unsigned int datalen = state.elementSize * count; 413 int stride = state.stride; 414 if (stride == 0) stride = state.elementSize; 415 int firstIndex = stride * first; 416 417 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, state.bufferObject); 418 if (state.bufferObject == 0) { 419 420 switch(i) { 421 case GLClientState::VERTEX_LOCATION: 422 this->glVertexPointerData(this, state.size, state.type, state.stride, 423 (unsigned char *)state.data + firstIndex, datalen); 424 break; 425 case GLClientState::NORMAL_LOCATION: 426 this->glNormalPointerData(this, state.type, state.stride, 427 (unsigned char *)state.data + firstIndex, datalen); 428 break; 429 case GLClientState::COLOR_LOCATION: 430 this->glColorPointerData(this, state.size, state.type, state.stride, 431 (unsigned char *)state.data + firstIndex, datalen); 432 break; 433 case GLClientState::TEXCOORD0_LOCATION: 434 case GLClientState::TEXCOORD1_LOCATION: 435 case GLClientState::TEXCOORD2_LOCATION: 436 case GLClientState::TEXCOORD3_LOCATION: 437 case GLClientState::TEXCOORD4_LOCATION: 438 case GLClientState::TEXCOORD5_LOCATION: 439 case GLClientState::TEXCOORD6_LOCATION: 440 case GLClientState::TEXCOORD7_LOCATION: 441 m_state->setActiveTextureUnit(i - GLClientState::TEXCOORD0_LOCATION + GL_TEXTURE0); 442 if (m_state->getPriorityEnabledTarget(GL_INVALID_ENUM) != GL_INVALID_ENUM) { 443 this->glTexCoordPointerData(this, i - GLClientState::TEXCOORD0_LOCATION, state.size, state.type, state.stride, 444 (unsigned char *)state.data + firstIndex, datalen); 445 } 446 break; 447 case GLClientState::POINTSIZE_LOCATION: 448 this->glPointSizePointerData(this, state.type, state.stride, 449 (unsigned char *) state.data + firstIndex, datalen); 450 break; 451 case GLClientState::WEIGHT_LOCATION: 452 this->glWeightPointerData(this, state.size, state.type, state.stride, 453 (unsigned char * ) state.data + firstIndex, datalen); 454 break; 455 case GLClientState::MATRIXINDEX_LOCATION: 456 this->glMatrixIndexPointerData(this, state.size, state.type, state.stride, 457 (unsigned char *)state.data + firstIndex, datalen); 458 break; 459 } 460 } else { 461 462 switch(i) { 463 case GLClientState::VERTEX_LOCATION: 464 this->glVertexPointerOffset(this, state.size, state.type, state.stride, 465 (uintptr_t)state.data + firstIndex); 466 break; 467 case GLClientState::NORMAL_LOCATION: 468 this->glNormalPointerOffset(this, state.type, state.stride, 469 (uintptr_t)state.data + firstIndex); 470 break; 471 case GLClientState::POINTSIZE_LOCATION: 472 this->glPointSizePointerOffset(this, state.type, state.stride, 473 (uintptr_t)state.data + firstIndex); 474 break; 475 case GLClientState::COLOR_LOCATION: 476 this->glColorPointerOffset(this, state.size, state.type, state.stride, 477 (uintptr_t)state.data + firstIndex); 478 break; 479 case GLClientState::TEXCOORD0_LOCATION: 480 case GLClientState::TEXCOORD1_LOCATION: 481 case GLClientState::TEXCOORD2_LOCATION: 482 case GLClientState::TEXCOORD3_LOCATION: 483 case GLClientState::TEXCOORD4_LOCATION: 484 case GLClientState::TEXCOORD5_LOCATION: 485 case GLClientState::TEXCOORD6_LOCATION: 486 case GLClientState::TEXCOORD7_LOCATION: 487 this->glTexCoordPointerOffset(this, state.size, state.type, state.stride, 488 (uintptr_t)state.data + firstIndex); 489 break; 490 case GLClientState::WEIGHT_LOCATION: 491 this->glWeightPointerOffset(this,state.size,state.type,state.stride, 492 (uintptr_t)state.data+firstIndex); 493 break; 494 case GLClientState::MATRIXINDEX_LOCATION: 495 this->glMatrixIndexPointerOffset(this,state.size,state.type,state.stride, 496 (uintptr_t)state.data+firstIndex); 497 break; 498 } 499 } 500 this->m_glBindBuffer_enc(this, GL_ARRAY_BUFFER, m_state->currentArrayVbo()); 501 } else { 502 this->m_glDisableClientState_enc(this, state.glConst); 503 } 504 } 505 m_state->setActiveTextureUnit(prevActiveTexUnit); 506 } 507 508 void GLEncoder::s_glDrawArrays(void *self, GLenum mode, GLint first, GLsizei count) 509 { 510 GLEncoder *ctx = (GLEncoder *)self; 511 512 bool has_arrays = false; 513 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 514 const GLClientState::VertexAttribState& state = ctx->m_state->getState(i); 515 if (state.enabled) { 516 if (state.bufferObject || state.data) { 517 has_arrays = true; 518 } else { 519 ALOGE("glDrawArrays: a vertex attribute array is enabled with no data bound\n"); 520 ctx->setError(GL_INVALID_OPERATION); 521 return; 522 } 523 } 524 } 525 if (!has_arrays) { 526 ALOGE("glDrawArrays: no data bound to the command - ignoring\n"); 527 return; 528 } 529 530 ctx->sendVertexData(first, count); 531 ctx->m_glDrawArrays_enc(ctx, mode, /*first*/ 0, count); 532 ctx->m_stream->flush(); 533 } 534 535 void GLEncoder::s_glDrawElements(void *self, GLenum mode, GLsizei count, GLenum type, const void *indices) 536 { 537 538 GLEncoder *ctx = (GLEncoder *)self; 539 assert(ctx->m_state != NULL); 540 SET_ERROR_IF(count<0, GL_INVALID_VALUE); 541 542 bool has_immediate_arrays = false; 543 bool has_indirect_arrays = false; 544 545 for (int i = 0; i < GLClientState::LAST_LOCATION; i++) { 546 const GLClientState::VertexAttribState& state = ctx->m_state->getState(i); 547 if (state.enabled) { 548 if (state.bufferObject != 0) { 549 has_indirect_arrays = true; 550 } else if (state.data) { 551 has_immediate_arrays = true; 552 } else { 553 ALOGE("glDrawElements: a vertex attribute array is enabled with no data bound\n"); 554 ctx->setError(GL_INVALID_OPERATION); 555 return; 556 } 557 } 558 } 559 560 if (!has_immediate_arrays && !has_indirect_arrays) { 561 ALOGE("glDrawElements: no data bound to the command - ignoring\n"); 562 return; 563 } 564 565 bool adjustIndices = true; 566 if (ctx->m_state->currentIndexVbo() != 0) { 567 if (!has_immediate_arrays) { 568 ctx->sendVertexData(0, count); 569 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, ctx->m_state->currentIndexVbo()); 570 ctx->glDrawElementsOffset(ctx, mode, count, type, (uintptr_t)indices); 571 ctx->m_stream->flush(); 572 adjustIndices = false; 573 } else { 574 BufferData * buf = ctx->m_shared->getBufferData(ctx->m_state->currentIndexVbo()); 575 ctx->m_glBindBuffer_enc(self, GL_ELEMENT_ARRAY_BUFFER, 0); 576 indices = (void*)((GLintptr)buf->m_fixedBuffer.ptr() + (GLintptr)indices); 577 } 578 } 579 if (adjustIndices) { 580 void *adjustedIndices = (void*)indices; 581 int minIndex = 0, maxIndex = 0; 582 583 switch(type) { 584 case GL_BYTE: 585 case GL_UNSIGNED_BYTE: 586 GLUtils::minmax<unsigned char>((unsigned char *)indices, count, &minIndex, &maxIndex); 587 if (minIndex != 0) { 588 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 589 GLUtils::shiftIndices<unsigned char>((unsigned char *)indices, 590 (unsigned char *)adjustedIndices, 591 count, -minIndex); 592 } 593 break; 594 case GL_SHORT: 595 case GL_UNSIGNED_SHORT: 596 GLUtils::minmax<unsigned short>((unsigned short *)indices, count, &minIndex, &maxIndex); 597 if (minIndex != 0) { 598 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 599 GLUtils::shiftIndices<unsigned short>((unsigned short *)indices, 600 (unsigned short *)adjustedIndices, 601 count, -minIndex); 602 } 603 break; 604 case GL_INT: 605 case GL_UNSIGNED_INT: 606 GLUtils::minmax<unsigned int>((unsigned int *)indices, count, &minIndex, &maxIndex); 607 if (minIndex != 0) { 608 adjustedIndices = ctx->m_fixedBuffer.alloc(glSizeof(type) * count); 609 GLUtils::shiftIndices<unsigned int>((unsigned int *)indices, 610 (unsigned int *)adjustedIndices, 611 count, -minIndex); 612 } 613 break; 614 default: 615 ALOGE("unsupported index buffer type %d\n", type); 616 } 617 if (has_indirect_arrays || 1) { 618 ctx->sendVertexData(minIndex, maxIndex - minIndex + 1); 619 ctx->glDrawElementsData(ctx, mode, count, type, adjustedIndices, 620 count * glSizeof(type)); 621 ctx->m_stream->flush(); 622 // XXX - OPTIMIZATION (see the other else branch) should be implemented 623 if(!has_indirect_arrays) { 624 //ALOGD("unoptimized drawelements !!!\n"); 625 } 626 } else { 627 // we are all direct arrays and immidate mode index array - 628 // rebuild the arrays and the index array; 629 ALOGE("glDrawElements: direct index & direct buffer data - will be implemented in later versions;\n"); 630 } 631 } 632 } 633 634 void GLEncoder::s_glActiveTexture(void* self, GLenum texture) 635 { 636 GLEncoder* ctx = (GLEncoder*)self; 637 GLClientState* state = ctx->m_state; 638 GLenum err; 639 640 if ((err = state->setActiveTextureUnit(texture)) != GL_NO_ERROR) { 641 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 642 ctx->setError(err); 643 return; 644 } 645 646 ctx->m_glActiveTexture_enc(ctx, texture); 647 } 648 649 void GLEncoder::s_glBindTexture(void* self, GLenum target, GLuint texture) 650 { 651 GLEncoder* ctx = (GLEncoder*)self; 652 GLClientState* state = ctx->m_state; 653 GLenum err; 654 655 GLboolean firstUse; 656 if ((err = state->bindTexture(target, texture, &firstUse)) != GL_NO_ERROR) { 657 ALOGE("%s:%s:%d GL error %#x\n", __FILE__, __FUNCTION__, __LINE__, err); 658 ctx->setError(err); 659 return; 660 } 661 662 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_EXTERNAL_OES) { 663 ctx->m_glBindTexture_enc(ctx, target, texture); 664 return; 665 } 666 667 GLenum priorityTarget = state->getPriorityEnabledTarget(GL_TEXTURE_2D); 668 669 if (target == GL_TEXTURE_EXTERNAL_OES && firstUse) { 670 // set TEXTURE_EXTERNAL_OES default states which differ from TEXTURE_2D 671 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 672 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 673 GL_TEXTURE_MIN_FILTER, GL_LINEAR); 674 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 675 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 676 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, 677 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 678 679 if (target != priorityTarget) { 680 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 681 state->getBoundTexture(GL_TEXTURE_2D)); 682 } 683 } 684 685 if (target == priorityTarget) { 686 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, texture); 687 } 688 } 689 690 void GLEncoder::s_glDeleteTextures(void* self, GLsizei n, const GLuint* textures) 691 { 692 GLEncoder* ctx = (GLEncoder*)self; 693 GLClientState* state = ctx->m_state; 694 695 state->deleteTextures(n, textures); 696 ctx->m_glDeleteTextures_enc(ctx, n, textures); 697 } 698 699 void GLEncoder::s_glDisable(void* self, GLenum cap) 700 { 701 GLEncoder* ctx = (GLEncoder*)self; 702 GLClientState* state = ctx->m_state; 703 704 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 705 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 706 state->disableTextureTarget(cap); 707 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 708 709 if (prevTarget != currTarget) { 710 if (currTarget == GL_INVALID_ENUM) { 711 ctx->m_glDisable_enc(ctx, GL_TEXTURE_2D); 712 currTarget = GL_TEXTURE_2D; 713 } 714 // maintain the invariant that when TEXTURE_EXTERNAL_OES is 715 // disabled, the TEXTURE_2D binding is active, even if 716 // TEXTURE_2D is also disabled. 717 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 718 state->getBoundTexture(currTarget)); 719 } 720 721 } else { 722 ctx->m_glDisable_enc(ctx, cap); 723 } 724 } 725 726 void GLEncoder::s_glEnable(void* self, GLenum cap) 727 { 728 GLEncoder* ctx = (GLEncoder*)self; 729 GLClientState* state = ctx->m_state; 730 731 if (cap == GL_TEXTURE_2D || cap == GL_TEXTURE_EXTERNAL_OES) { 732 GLenum prevTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 733 state->enableTextureTarget(cap); 734 GLenum currTarget = state->getPriorityEnabledTarget(GL_INVALID_ENUM); 735 736 if (prevTarget != currTarget) { 737 if (prevTarget == GL_INVALID_ENUM) { 738 ctx->m_glEnable_enc(ctx, GL_TEXTURE_2D); 739 } 740 if (currTarget == GL_TEXTURE_EXTERNAL_OES) { 741 ctx->m_glBindTexture_enc(ctx, GL_TEXTURE_2D, 742 state->getBoundTexture(currTarget)); 743 } 744 } 745 746 } else { 747 ctx->m_glEnable_enc(ctx, cap); 748 } 749 } 750 751 void GLEncoder::s_glGetTexParameterfv(void* self, 752 GLenum target, GLenum pname, GLfloat* params) 753 { 754 GLEncoder* ctx = (GLEncoder*)self; 755 const GLClientState* state = ctx->m_state; 756 757 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 758 ctx->override2DTextureTarget(target); 759 ctx->m_glGetTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 760 ctx->restore2DTextureTarget(); 761 } else { 762 ctx->m_glGetTexParameterfv_enc(ctx, target, pname, params); 763 } 764 } 765 766 void GLEncoder::s_glGetTexParameteriv(void* self, 767 GLenum target, GLenum pname, GLint* params) 768 { 769 GLEncoder* ctx = (GLEncoder*)self; 770 const GLClientState* state = ctx->m_state; 771 772 switch (pname) { 773 case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES: 774 *params = 1; 775 break; 776 777 default: 778 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 779 ctx->override2DTextureTarget(target); 780 ctx->m_glGetTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 781 ctx->restore2DTextureTarget(); 782 } else { 783 ctx->m_glGetTexParameteriv_enc(ctx, target, pname, params); 784 } 785 break; 786 } 787 } 788 789 void GLEncoder::s_glGetTexParameterxv(void* self, 790 GLenum target, GLenum pname, GLfixed* params) 791 { 792 GLEncoder* ctx = (GLEncoder*)self; 793 const GLClientState* state = ctx->m_state; 794 795 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 796 ctx->override2DTextureTarget(target); 797 ctx->m_glGetTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 798 ctx->restore2DTextureTarget(); 799 } else { 800 ctx->m_glGetTexParameterxv_enc(ctx, target, pname, params); 801 } 802 } 803 804 static bool isValidTextureExternalParam(GLenum pname, GLenum param) 805 { 806 switch (pname) { 807 case GL_TEXTURE_MIN_FILTER: 808 case GL_TEXTURE_MAG_FILTER: 809 return param == GL_NEAREST || param == GL_LINEAR; 810 811 case GL_TEXTURE_WRAP_S: 812 case GL_TEXTURE_WRAP_T: 813 return param == GL_CLAMP_TO_EDGE; 814 815 case GL_GENERATE_MIPMAP: 816 return param == GL_FALSE; 817 818 default: 819 return true; 820 } 821 } 822 823 void GLEncoder::s_glTexParameterf(void* self, 824 GLenum target, GLenum pname, GLfloat param) 825 { 826 GLEncoder* ctx = (GLEncoder*)self; 827 const GLClientState* state = ctx->m_state; 828 829 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 830 !isValidTextureExternalParam(pname, (GLenum)param)), 831 GL_INVALID_ENUM); 832 833 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 834 ctx->override2DTextureTarget(target); 835 ctx->m_glTexParameterf_enc(ctx, GL_TEXTURE_2D, pname, param); 836 ctx->restore2DTextureTarget(); 837 } else { 838 ctx->m_glTexParameterf_enc(ctx, target, pname, param); 839 } 840 } 841 842 void GLEncoder::s_glTexParameterfv(void* self, 843 GLenum target, GLenum pname, const GLfloat* params) 844 { 845 GLEncoder* ctx = (GLEncoder*)self; 846 const GLClientState* state = ctx->m_state; 847 848 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 849 !isValidTextureExternalParam(pname, (GLenum)params[0])), 850 GL_INVALID_ENUM); 851 852 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 853 ctx->override2DTextureTarget(target); 854 ctx->m_glTexParameterfv_enc(ctx, GL_TEXTURE_2D, pname, params); 855 ctx->restore2DTextureTarget(); 856 } else { 857 ctx->m_glTexParameterfv_enc(ctx, target, pname, params); 858 } 859 } 860 861 void GLEncoder::s_glTexParameteri(void* self, 862 GLenum target, GLenum pname, GLint param) 863 { 864 GLEncoder* ctx = (GLEncoder*)self; 865 const GLClientState* state = ctx->m_state; 866 867 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 868 !isValidTextureExternalParam(pname, (GLenum)param)), 869 GL_INVALID_ENUM); 870 871 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 872 ctx->override2DTextureTarget(target); 873 ctx->m_glTexParameteri_enc(ctx, GL_TEXTURE_2D, pname, param); 874 ctx->restore2DTextureTarget(); 875 } else { 876 ctx->m_glTexParameteri_enc(ctx, target, pname, param); 877 } 878 } 879 880 void GLEncoder::s_glTexParameterx(void* self, 881 GLenum target, GLenum pname, GLfixed param) 882 { 883 GLEncoder* ctx = (GLEncoder*)self; 884 const GLClientState* state = ctx->m_state; 885 886 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 887 !isValidTextureExternalParam(pname, (GLenum)param)), 888 GL_INVALID_ENUM); 889 890 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 891 ctx->override2DTextureTarget(target); 892 ctx->m_glTexParameterx_enc(ctx, GL_TEXTURE_2D, pname, param); 893 ctx->restore2DTextureTarget(); 894 } else { 895 ctx->m_glTexParameterx_enc(ctx, target, pname, param); 896 } 897 } 898 899 void GLEncoder::s_glTexParameteriv(void* self, 900 GLenum target, GLenum pname, const GLint* params) 901 { 902 GLEncoder* ctx = (GLEncoder*)self; 903 const GLClientState* state = ctx->m_state; 904 905 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 906 !isValidTextureExternalParam(pname, (GLenum)params[0])), 907 GL_INVALID_ENUM); 908 909 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 910 ctx->override2DTextureTarget(target); 911 ctx->m_glTexParameteriv_enc(ctx, GL_TEXTURE_2D, pname, params); 912 ctx->restore2DTextureTarget(); 913 } else { 914 ctx->m_glTexParameteriv_enc(ctx, target, pname, params); 915 } 916 } 917 918 void GLEncoder::s_glTexParameterxv(void* self, 919 GLenum target, GLenum pname, const GLfixed* params) 920 { 921 GLEncoder* ctx = (GLEncoder*)self; 922 const GLClientState* state = ctx->m_state; 923 924 SET_ERROR_IF((target == GL_TEXTURE_EXTERNAL_OES && 925 !isValidTextureExternalParam(pname, (GLenum)params[0])), 926 GL_INVALID_ENUM); 927 928 if (target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) { 929 ctx->override2DTextureTarget(target); 930 ctx->m_glTexParameterxv_enc(ctx, GL_TEXTURE_2D, pname, params); 931 ctx->restore2DTextureTarget(); 932 } else { 933 ctx->m_glTexParameterxv_enc(ctx, target, pname, params); 934 } 935 } 936 937 void GLEncoder::override2DTextureTarget(GLenum target) 938 { 939 if ((target == GL_TEXTURE_2D || target == GL_TEXTURE_EXTERNAL_OES) && 940 target != m_state->getPriorityEnabledTarget(GL_TEXTURE_2D)) { 941 m_glBindTexture_enc(this, GL_TEXTURE_2D, 942 m_state->getBoundTexture(target)); 943 } 944 } 945 946 void GLEncoder::restore2DTextureTarget() 947 { 948 GLenum priorityTarget = m_state->getPriorityEnabledTarget(GL_TEXTURE_2D); 949 m_glBindTexture_enc(this, GL_TEXTURE_2D, 950 m_state->getBoundTexture(priorityTarget)); 951 } 952 953 void GLEncoder::s_glGenFramebuffersOES(void* self, 954 GLsizei n, GLuint* framebuffers) { 955 GLEncoder* ctx = (GLEncoder*)self; 956 GLClientState* state = ctx->m_state; 957 958 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 959 960 ctx->m_glGenFramebuffersOES_enc(self, n, framebuffers); 961 state->addFramebuffers(n, framebuffers); 962 } 963 964 void GLEncoder::s_glDeleteFramebuffersOES(void* self, 965 GLsizei n, const GLuint* framebuffers) { 966 GLEncoder* ctx = (GLEncoder*)self; 967 GLClientState* state = ctx->m_state; 968 969 SET_ERROR_IF(n < 0, GL_INVALID_VALUE); 970 971 ctx->m_glDeleteFramebuffersOES_enc(self, n, framebuffers); 972 state->removeFramebuffers(n, framebuffers); 973 } 974 975 void GLEncoder::s_glBindFramebufferOES(void* self, 976 GLenum target, GLuint framebuffer) { 977 GLEncoder* ctx = (GLEncoder*)self; 978 GLClientState* state = ctx->m_state; 979 980 SET_ERROR_IF((target != GL_FRAMEBUFFER), 981 GL_INVALID_ENUM); 982 983 state->bindFramebuffer(target, framebuffer); 984 985 ctx->m_glBindFramebufferOES_enc(self, target, framebuffer); 986 } 987 988 void GLEncoder::s_glFramebufferTexture2DOES(void*self, 989 GLenum target, GLenum attachment, 990 GLenum textarget, GLuint texture, GLint level) { 991 GLEncoder* ctx = (GLEncoder*)self; 992 GLClientState* state = ctx->m_state; 993 994 state->attachTextureObject(target, attachment, texture); 995 996 ctx->m_glFramebufferTexture2DOES_enc(self, target, attachment, textarget, texture, level); 997 } 998 999 void GLEncoder::s_glFramebufferTexture2DMultisampleIMG(void* self, 1000 GLenum target, GLenum attachment, 1001 GLenum textarget, GLuint texture, GLint level, GLsizei samples) { 1002 GLEncoder* ctx = (GLEncoder*)self; 1003 GLClientState* state = ctx->m_state; 1004 1005 state->attachTextureObject(target, attachment, texture); 1006 1007 ctx->m_glFramebufferTexture2DMultisampleIMG_enc(self, target, attachment, textarget, texture, level, samples); 1008 } 1009 1010 void GLEncoder::s_glGetFramebufferAttachmentParameterivOES(void* self, 1011 GLenum target, GLenum attachment, GLenum pname, GLint* params) 1012 { 1013 GLEncoder* ctx = (GLEncoder*)self; 1014 const GLClientState* state = ctx->m_state; 1015 1016 SET_ERROR_IF(state->boundFramebuffer(GL_FRAMEBUFFER) == 0, 1017 GL_INVALID_OPERATION); 1018 SET_ERROR_IF((pname != GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) && 1019 (!state->attachmentHasObject(GL_FRAMEBUFFER, attachment)), 1020 GL_INVALID_ENUM); 1021 1022 ctx->m_glGetFramebufferAttachmentParameterivOES_enc(self, target, attachment, pname, params); 1023 } 1024 1025 GLEncoder::GLEncoder(IOStream *stream, ChecksumCalculator *protocol) 1026 : gl_encoder_context_t(stream, protocol) 1027 { 1028 m_initialized = false; 1029 m_state = NULL; 1030 m_error = GL_NO_ERROR; 1031 m_num_compressedTextureFormats = 0; 1032 m_compressedTextureFormats = NULL; 1033 1034 // overrides; 1035 #define OVERRIDE(name) m_##name##_enc = this-> name ; this-> name = &s_##name 1036 1037 OVERRIDE(glFlush); 1038 OVERRIDE(glPixelStorei); 1039 OVERRIDE(glVertexPointer); 1040 OVERRIDE(glNormalPointer); 1041 OVERRIDE(glColorPointer); 1042 OVERRIDE(glPointSizePointerOES); 1043 OVERRIDE(glClientActiveTexture); 1044 OVERRIDE(glTexCoordPointer); 1045 OVERRIDE(glMatrixIndexPointerOES); 1046 OVERRIDE(glWeightPointerOES); 1047 1048 OVERRIDE(glGetIntegerv); 1049 OVERRIDE(glGetFloatv); 1050 OVERRIDE(glGetBooleanv); 1051 OVERRIDE(glGetFixedv); 1052 OVERRIDE(glGetPointerv); 1053 1054 OVERRIDE(glBindBuffer); 1055 OVERRIDE(glBufferData); 1056 OVERRIDE(glBufferSubData); 1057 OVERRIDE(glDeleteBuffers); 1058 1059 OVERRIDE(glEnableClientState); 1060 OVERRIDE(glDisableClientState); 1061 OVERRIDE(glIsEnabled); 1062 OVERRIDE(glDrawArrays); 1063 OVERRIDE(glDrawElements); 1064 1065 this->glGetString = s_glGetString; 1066 this->glFinish = s_glFinish; 1067 1068 OVERRIDE(glGetError); 1069 1070 OVERRIDE(glActiveTexture); 1071 OVERRIDE(glBindTexture); 1072 OVERRIDE(glDeleteTextures); 1073 OVERRIDE(glDisable); 1074 OVERRIDE(glEnable); 1075 OVERRIDE(glGetTexParameterfv); 1076 OVERRIDE(glGetTexParameteriv); 1077 OVERRIDE(glGetTexParameterxv); 1078 OVERRIDE(glTexParameterf); 1079 OVERRIDE(glTexParameterfv); 1080 OVERRIDE(glTexParameteri); 1081 OVERRIDE(glTexParameterx); 1082 OVERRIDE(glTexParameteriv); 1083 OVERRIDE(glTexParameterxv); 1084 1085 OVERRIDE(glGenFramebuffersOES); 1086 OVERRIDE(glDeleteFramebuffersOES); 1087 OVERRIDE(glBindFramebufferOES); 1088 OVERRIDE(glFramebufferTexture2DOES); 1089 OVERRIDE(glFramebufferTexture2DMultisampleIMG); 1090 OVERRIDE(glGetFramebufferAttachmentParameterivOES); 1091 } 1092 1093 GLEncoder::~GLEncoder() 1094 { 1095 delete [] m_compressedTextureFormats; 1096 } 1097 1098 size_t GLEncoder::pixelDataSize(GLsizei width, GLsizei height, GLenum format, GLenum type, int pack) 1099 { 1100 assert(m_state != NULL); 1101 return m_state->pixelDataSize(width, height, 1, format, type, pack); 1102 } 1103 1104 void GLEncoder::s_glFinish(void *self) 1105 { 1106 GLEncoder *ctx = (GLEncoder *)self; 1107 ctx->glFinishRoundTrip(self); 1108 } 1109