texture.cpp revision 58a79f47457e9cae2f6880653b581fe3170b0b1f
1/* libs/opengles/texture.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#include <stdio.h> 19#include <stdlib.h> 20#include "context.h" 21#include "fp.h" 22#include "state.h" 23#include "texture.h" 24#include "TextureObjectManager.h" 25 26#include <private/ui/android_natives_priv.h> 27 28#ifdef LIBAGL_USE_GRALLOC_COPYBITS 29#include "copybit.h" 30#include "gralloc_priv.h" 31#endif // LIBAGL_USE_GRALLOC_COPYBITS 32 33namespace android { 34 35// ---------------------------------------------------------------------------- 36 37static void bindTextureTmu( 38 ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex); 39 40static __attribute__((noinline)) 41void generateMipmap(ogles_context_t* c, GLint level); 42 43// ---------------------------------------------------------------------------- 44 45#if 0 46#pragma mark - 47#pragma mark Init 48#endif 49 50void ogles_init_texture(ogles_context_t* c) 51{ 52 c->textures.packAlignment = 4; 53 c->textures.unpackAlignment = 4; 54 55 // each context has a default named (0) texture (not shared) 56 c->textures.defaultTexture = new EGLTextureObject(); 57 c->textures.defaultTexture->incStrong(c); 58 59 // bind the default texture to each texture unit 60 for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 61 bindTextureTmu(c, i, 0, c->textures.defaultTexture); 62 memset(c->current.texture[i].v, 0, sizeof(vec4_t)); 63 c->current.texture[i].Q = 0x10000; 64 } 65} 66 67void ogles_uninit_texture(ogles_context_t* c) 68{ 69 if (c->textures.ggl) 70 gglUninit(c->textures.ggl); 71 c->textures.defaultTexture->decStrong(c); 72 for (int i=0; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 73 if (c->textures.tmu[i].texture) 74 c->textures.tmu[i].texture->decStrong(c); 75 } 76} 77 78static __attribute__((noinline)) 79void validate_tmu(ogles_context_t* c, int i) 80{ 81 texture_unit_t& u(c->textures.tmu[i]); 82 if (u.dirty) { 83 u.dirty = 0; 84 c->rasterizer.procs.activeTexture(c, i); 85 c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); 86 c->rasterizer.procs.texGeni(c, GGL_S, 87 GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); 88 c->rasterizer.procs.texGeni(c, GGL_T, 89 GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); 90 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 91 GGL_TEXTURE_WRAP_S, u.texture->wraps); 92 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 93 GGL_TEXTURE_WRAP_T, u.texture->wrapt); 94 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 95 GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); 96 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 97 GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); 98 99 // disable this texture unit if it's not complete 100 if (!u.texture->isComplete()) { 101 c->rasterizer.procs.disable(c, GGL_TEXTURE_2D); 102 } 103 } 104} 105 106void ogles_validate_texture(ogles_context_t* c) 107{ 108 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 109 if (c->rasterizer.state.texture[i].enable) 110 validate_tmu(c, i); 111 } 112 c->rasterizer.procs.activeTexture(c, c->textures.active); 113} 114 115static 116void invalidate_texture(ogles_context_t* c, int tmu, uint8_t flags = 0xFF) { 117 c->textures.tmu[tmu].dirty = flags; 118} 119 120/* 121 * If the active textures are EGLImage, they need to be locked before 122 * they can be used. 123 * 124 * FIXME: code below is far from being optimal 125 * 126 */ 127 128void ogles_lock_textures(ogles_context_t* c) 129{ 130 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 131 if (c->rasterizer.state.texture[i].enable) { 132 texture_unit_t& u(c->textures.tmu[i]); 133 android_native_buffer_t* native_buffer = u.texture->buffer; 134 if (native_buffer) { 135 c->rasterizer.procs.activeTexture(c, i); 136 hw_module_t const* pModule; 137 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) 138 continue; 139 140 gralloc_module_t const* module = 141 reinterpret_cast<gralloc_module_t const*>(pModule); 142 143 void* vaddr; 144 int err = module->lock(module, native_buffer->handle, 145 GRALLOC_USAGE_SW_READ_OFTEN, 146 0, 0, native_buffer->width, native_buffer->height, 147 &vaddr); 148 149 u.texture->setImageBits(vaddr); 150 c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); 151 } 152 } 153 } 154} 155 156void ogles_unlock_textures(ogles_context_t* c) 157{ 158 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 159 if (c->rasterizer.state.texture[i].enable) { 160 texture_unit_t& u(c->textures.tmu[i]); 161 android_native_buffer_t* native_buffer = u.texture->buffer; 162 if (native_buffer) { 163 c->rasterizer.procs.activeTexture(c, i); 164 hw_module_t const* pModule; 165 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &pModule)) 166 continue; 167 168 gralloc_module_t const* module = 169 reinterpret_cast<gralloc_module_t const*>(pModule); 170 171 module->unlock(module, native_buffer->handle); 172 u.texture->setImageBits(NULL); 173 c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); 174 } 175 } 176 } 177 c->rasterizer.procs.activeTexture(c, c->textures.active); 178} 179 180// ---------------------------------------------------------------------------- 181#if 0 182#pragma mark - 183#pragma mark Format conversion 184#endif 185 186static uint32_t gl2format_table[6][4] = { 187 // BYTE, 565, 4444, 5551 188 { GGL_PIXEL_FORMAT_A_8, 189 0, 0, 0 }, // GL_ALPHA 190 { GGL_PIXEL_FORMAT_RGB_888, 191 GGL_PIXEL_FORMAT_RGB_565, 192 0, 0 }, // GL_RGB 193 { GGL_PIXEL_FORMAT_RGBA_8888, 194 0, 195 GGL_PIXEL_FORMAT_RGBA_4444, 196 GGL_PIXEL_FORMAT_RGBA_5551 }, // GL_RGBA 197 { GGL_PIXEL_FORMAT_L_8, 198 0, 0, 0 }, // GL_LUMINANCE 199 { GGL_PIXEL_FORMAT_LA_88, 200 0, 0, 0 }, // GL_LUMINANCE_ALPHA 201}; 202 203static int32_t convertGLPixelFormat(GLint format, GLenum type) 204{ 205 int32_t fi = -1; 206 int32_t ti = -1; 207 switch (format) { 208 case GL_ALPHA: fi = 0; break; 209 case GL_RGB: fi = 1; break; 210 case GL_RGBA: fi = 2; break; 211 case GL_LUMINANCE: fi = 3; break; 212 case GL_LUMINANCE_ALPHA: fi = 4; break; 213 } 214 switch (type) { 215 case GL_UNSIGNED_BYTE: ti = 0; break; 216 case GL_UNSIGNED_SHORT_5_6_5: ti = 1; break; 217 case GL_UNSIGNED_SHORT_4_4_4_4: ti = 2; break; 218 case GL_UNSIGNED_SHORT_5_5_5_1: ti = 3; break; 219 } 220 if (fi==-1 || ti==-1) 221 return 0; 222 return gl2format_table[fi][ti]; 223} 224 225// ---------------------------------------------------------------------------- 226 227static GLenum validFormatType(ogles_context_t* c, GLenum format, GLenum type) 228{ 229 GLenum error = 0; 230 if (format<GL_ALPHA || format>GL_LUMINANCE_ALPHA) { 231 error = GL_INVALID_ENUM; 232 } 233 if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT_4_4_4_4 && 234 type != GL_UNSIGNED_SHORT_5_5_5_1 && type != GL_UNSIGNED_SHORT_5_6_5) { 235 error = GL_INVALID_ENUM; 236 } 237 if (type == GL_UNSIGNED_SHORT_5_6_5 && format != GL_RGB) { 238 error = GL_INVALID_OPERATION; 239 } 240 if ((type == GL_UNSIGNED_SHORT_4_4_4_4 || 241 type == GL_UNSIGNED_SHORT_5_5_5_1) && format != GL_RGBA) { 242 error = GL_INVALID_OPERATION; 243 } 244 if (error) { 245 ogles_error(c, error); 246 } 247 return error; 248} 249 250// ---------------------------------------------------------------------------- 251 252GGLContext* getRasterizer(ogles_context_t* c) 253{ 254 GGLContext* ggl = c->textures.ggl; 255 if (ggl_unlikely(!ggl)) { 256 // this is quite heavy the first time... 257 gglInit(&ggl); 258 if (!ggl) { 259 return 0; 260 } 261 GGLfixed colors[4] = { 0, 0, 0, 0x10000 }; 262 c->textures.ggl = ggl; 263 ggl->activeTexture(ggl, 0); 264 ggl->enable(ggl, GGL_TEXTURE_2D); 265 ggl->texEnvi(ggl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); 266 ggl->disable(ggl, GGL_DITHER); 267 ggl->shadeModel(ggl, GGL_FLAT); 268 ggl->color4xv(ggl, colors); 269 } 270 return ggl; 271} 272 273static __attribute__((noinline)) 274int copyPixels( 275 ogles_context_t* c, 276 const GGLSurface& dst, 277 GLint xoffset, GLint yoffset, 278 const GGLSurface& src, 279 GLint x, GLint y, GLsizei w, GLsizei h) 280{ 281 if ((dst.format == src.format) && 282 (dst.stride == src.stride) && 283 (dst.width == src.width) && 284 (dst.height == src.height) && 285 (dst.stride > 0) && 286 ((x|y) == 0) && 287 ((xoffset|yoffset) == 0)) 288 { 289 // this is a common case... 290 const GGLFormat& pixelFormat(c->rasterizer.formats[src.format]); 291 const size_t size = src.height * src.stride * pixelFormat.size; 292 memcpy(dst.data, src.data, size); 293 return 0; 294 } 295 296 // use pixel-flinger to handle all the conversions 297 GGLContext* ggl = getRasterizer(c); 298 if (!ggl) { 299 // the only reason this would fail is because we ran out of memory 300 return GL_OUT_OF_MEMORY; 301 } 302 303 ggl->colorBuffer(ggl, &dst); 304 ggl->bindTexture(ggl, &src); 305 ggl->texCoord2i(ggl, x-xoffset, y-yoffset); 306 ggl->recti(ggl, xoffset, yoffset, xoffset+w, yoffset+h); 307 return 0; 308} 309 310// ---------------------------------------------------------------------------- 311 312static __attribute__((noinline)) 313sp<EGLTextureObject> getAndBindActiveTextureObject(ogles_context_t* c) 314{ 315 sp<EGLTextureObject> tex; 316 const int active = c->textures.active; 317 const GLuint name = c->textures.tmu[active].name; 318 319 // free the reference to the previously bound object 320 texture_unit_t& u(c->textures.tmu[active]); 321 if (u.texture) 322 u.texture->decStrong(c); 323 324 if (name == 0) { 325 // 0 is our local texture object, not shared with anyone. 326 // But it affects all bound TMUs immediately. 327 // (we need to invalidate all units bound to this texture object) 328 tex = c->textures.defaultTexture; 329 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 330 if (c->textures.tmu[i].texture == tex.get()) 331 invalidate_texture(c, i); 332 } 333 } else { 334 // get a new texture object for that name 335 tex = c->surfaceManager->replaceTexture(name); 336 } 337 338 // bind this texture to the current active texture unit 339 // and add a reference to this texture object 340 u.texture = tex.get(); 341 u.texture->incStrong(c); 342 u.name = name; 343 invalidate_texture(c, active); 344 return tex; 345} 346 347void bindTextureTmu( 348 ogles_context_t* c, int tmu, GLuint texture, const sp<EGLTextureObject>& tex) 349{ 350 if (tex.get() == c->textures.tmu[tmu].texture) 351 return; 352 353 // free the reference to the previously bound object 354 texture_unit_t& u(c->textures.tmu[tmu]); 355 if (u.texture) 356 u.texture->decStrong(c); 357 358 // bind this texture to the current active texture unit 359 // and add a reference to this texture object 360 u.texture = tex.get(); 361 u.texture->incStrong(c); 362 u.name = texture; 363 invalidate_texture(c, tmu); 364} 365 366int createTextureSurface(ogles_context_t* c, 367 GGLSurface** outSurface, int32_t* outSize, GLint level, 368 GLenum format, GLenum type, GLsizei width, GLsizei height, 369 GLenum compressedFormat = 0) 370{ 371 // find out which texture is bound to the current unit 372 const int active = c->textures.active; 373 const GLuint name = c->textures.tmu[active].name; 374 375 // convert the pixelformat to one we can handle 376 const int32_t formatIdx = convertGLPixelFormat(format, type); 377 if (formatIdx == 0) { // we don't know what to do with this 378 return GL_INVALID_OPERATION; 379 } 380 381 // figure out the size we need as well as the stride 382 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 383 const int32_t align = c->textures.unpackAlignment-1; 384 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 385 const size_t size = bpr * height; 386 const int32_t stride = bpr / pixelFormat.size; 387 388 if (level > 0) { 389 const int active = c->textures.active; 390 EGLTextureObject* tex = c->textures.tmu[active].texture; 391 status_t err = tex->reallocate(level, 392 width, height, stride, formatIdx, compressedFormat, bpr); 393 if (err != NO_ERROR) 394 return GL_OUT_OF_MEMORY; 395 GGLSurface& surface = tex->editMip(level); 396 *outSurface = &surface; 397 *outSize = size; 398 return 0; 399 } 400 401 sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); 402 status_t err = tex->reallocate(level, 403 width, height, stride, formatIdx, compressedFormat, bpr); 404 if (err != NO_ERROR) 405 return GL_OUT_OF_MEMORY; 406 407 tex->internalformat = format; 408 *outSurface = &tex->surface; 409 *outSize = size; 410 return 0; 411} 412 413static void decodePalette4(const GLvoid *data, int level, int width, int height, 414 void *surface, int stride, int format) 415 416{ 417 int indexBits = 8; 418 int entrySize = 0; 419 switch (format) { 420 case GL_PALETTE4_RGB8_OES: 421 indexBits = 4; 422 /* FALLTHROUGH */ 423 case GL_PALETTE8_RGB8_OES: 424 entrySize = 3; 425 break; 426 427 case GL_PALETTE4_RGBA8_OES: 428 indexBits = 4; 429 /* FALLTHROUGH */ 430 case GL_PALETTE8_RGBA8_OES: 431 entrySize = 4; 432 break; 433 434 case GL_PALETTE4_R5_G6_B5_OES: 435 case GL_PALETTE4_RGBA4_OES: 436 case GL_PALETTE4_RGB5_A1_OES: 437 indexBits = 4; 438 /* FALLTHROUGH */ 439 case GL_PALETTE8_R5_G6_B5_OES: 440 case GL_PALETTE8_RGBA4_OES: 441 case GL_PALETTE8_RGB5_A1_OES: 442 entrySize = 2; 443 break; 444 } 445 446 const int paletteSize = (1 << indexBits) * entrySize; 447 uint8_t const* pixels = (uint8_t *)data + paletteSize; 448 for (int i=0 ; i<level ; i++) { 449 int w = (width >> i) ? : 1; 450 int h = (height >> i) ? : 1; 451 pixels += h * ((w * indexBits) / 8); 452 } 453 width = (width >> level) ? : 1; 454 height = (height >> level) ? : 1; 455 456 if (entrySize == 2) { 457 uint8_t const* const palette = (uint8_t*)data; 458 for (int y=0 ; y<height ; y++) { 459 uint8_t* p = (uint8_t*)surface + y*stride*2; 460 if (indexBits == 8) { 461 for (int x=0 ; x<width ; x++) { 462 int index = 2 * (*pixels++); 463 *p++ = palette[index + 0]; 464 *p++ = palette[index + 1]; 465 } 466 } else { 467 for (int x=0 ; x<width ; x+=2) { 468 int v = *pixels++; 469 int index = 2 * (v >> 4); 470 *p++ = palette[index + 0]; 471 *p++ = palette[index + 1]; 472 if (x+1 < width) { 473 index = 2 * (v & 0xF); 474 *p++ = palette[index + 0]; 475 *p++ = palette[index + 1]; 476 } 477 } 478 } 479 } 480 } else if (entrySize == 3) { 481 uint8_t const* const palette = (uint8_t*)data; 482 for (int y=0 ; y<height ; y++) { 483 uint8_t* p = (uint8_t*)surface + y*stride*3; 484 if (indexBits == 8) { 485 for (int x=0 ; x<width ; x++) { 486 int index = 3 * (*pixels++); 487 *p++ = palette[index + 0]; 488 *p++ = palette[index + 1]; 489 *p++ = palette[index + 2]; 490 } 491 } else { 492 for (int x=0 ; x<width ; x+=2) { 493 int v = *pixels++; 494 int index = 3 * (v >> 4); 495 *p++ = palette[index + 0]; 496 *p++ = palette[index + 1]; 497 *p++ = palette[index + 2]; 498 if (x+1 < width) { 499 index = 3 * (v & 0xF); 500 *p++ = palette[index + 0]; 501 *p++ = palette[index + 1]; 502 *p++ = palette[index + 2]; 503 } 504 } 505 } 506 } 507 } else if (entrySize == 4) { 508 uint8_t const* const palette = (uint8_t*)data; 509 for (int y=0 ; y<height ; y++) { 510 uint8_t* p = (uint8_t*)surface + y*stride*4; 511 if (indexBits == 8) { 512 for (int x=0 ; x<width ; x++) { 513 int index = 4 * (*pixels++); 514 *p++ = palette[index + 0]; 515 *p++ = palette[index + 1]; 516 *p++ = palette[index + 2]; 517 *p++ = palette[index + 3]; 518 } 519 } else { 520 for (int x=0 ; x<width ; x+=2) { 521 int v = *pixels++; 522 int index = 4 * (v >> 4); 523 *p++ = palette[index + 0]; 524 *p++ = palette[index + 1]; 525 *p++ = palette[index + 2]; 526 *p++ = palette[index + 3]; 527 if (x+1 < width) { 528 index = 4 * (v & 0xF); 529 *p++ = palette[index + 0]; 530 *p++ = palette[index + 1]; 531 *p++ = palette[index + 2]; 532 *p++ = palette[index + 3]; 533 } 534 } 535 } 536 } 537 } 538} 539 540 541 542static __attribute__((noinline)) 543void set_depth_and_fog(ogles_context_t* c, GLint z) 544{ 545 const uint32_t enables = c->rasterizer.state.enables; 546 // we need to compute Zw 547 int32_t iterators[3]; 548 iterators[1] = iterators[2] = 0; 549 GGLfixed Zw; 550 GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear); 551 GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar); 552 if (z<=0) Zw = n; 553 else if (z>=1) Zw = f; 554 else Zw = gglMulAddx(z, (f-n), n); 555 if (enables & GGL_ENABLE_FOG) { 556 // set up fog if needed... 557 iterators[0] = c->fog.fog(c, Zw); 558 c->rasterizer.procs.fogGrad3xv(c, iterators); 559 } 560 if (enables & GGL_ENABLE_DEPTH_TEST) { 561 // set up z-test if needed... 562 int32_t z = (Zw & ~(Zw>>31)); 563 if (z >= 0x10000) 564 z = 0xFFFF; 565 iterators[0] = (z << 16) | z; 566 c->rasterizer.procs.zGrad3xv(c, iterators); 567 } 568} 569 570// ---------------------------------------------------------------------------- 571#if 0 572#pragma mark - 573#pragma mark Generate mimaps 574#endif 575 576extern status_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex); 577 578void generateMipmap(ogles_context_t* c, GLint level) 579{ 580 if (level == 0) { 581 const int active = c->textures.active; 582 EGLTextureObject* tex = c->textures.tmu[active].texture; 583 if (tex->generate_mipmap) { 584 if (buildAPyramid(c, tex) != NO_ERROR) { 585 ogles_error(c, GL_OUT_OF_MEMORY); 586 return; 587 } 588 } 589 } 590} 591 592 593static void texParameterx( 594 GLenum target, GLenum pname, GLfixed param, ogles_context_t* c) 595{ 596 if (target != GL_TEXTURE_2D) { 597 ogles_error(c, GL_INVALID_ENUM); 598 return; 599 } 600 601 EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; 602 switch (pname) { 603 case GL_TEXTURE_WRAP_S: 604 if ((param == GL_REPEAT) || 605 (param == GL_CLAMP_TO_EDGE)) { 606 textureObject->wraps = param; 607 } else { 608 goto invalid_enum; 609 } 610 break; 611 case GL_TEXTURE_WRAP_T: 612 if ((param == GL_REPEAT) || 613 (param == GL_CLAMP_TO_EDGE)) { 614 textureObject->wrapt = param; 615 } else { 616 goto invalid_enum; 617 } 618 break; 619 case GL_TEXTURE_MIN_FILTER: 620 if ((param == GL_NEAREST) || 621 (param == GL_LINEAR) || 622 (param == GL_NEAREST_MIPMAP_NEAREST) || 623 (param == GL_LINEAR_MIPMAP_NEAREST) || 624 (param == GL_NEAREST_MIPMAP_LINEAR) || 625 (param == GL_LINEAR_MIPMAP_LINEAR)) { 626 textureObject->min_filter = param; 627 } else { 628 goto invalid_enum; 629 } 630 break; 631 case GL_TEXTURE_MAG_FILTER: 632 if ((param == GL_NEAREST) || 633 (param == GL_LINEAR)) { 634 textureObject->mag_filter = param; 635 } else { 636 goto invalid_enum; 637 } 638 break; 639 case GL_GENERATE_MIPMAP: 640 textureObject->generate_mipmap = param; 641 break; 642 default: 643invalid_enum: 644 ogles_error(c, GL_INVALID_ENUM); 645 return; 646 } 647 invalidate_texture(c, c->textures.active); 648} 649 650 651 652static void drawTexxOESImp(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, 653 ogles_context_t* c) 654{ 655 ogles_lock_textures(c); 656 657 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 658 y = gglIntToFixed(cbSurface.height) - (y + h); 659 w >>= FIXED_BITS; 660 h >>= FIXED_BITS; 661 662 // set up all texture units 663 for (int i=0 ; i<GGL_TEXTURE_UNIT_COUNT ; i++) { 664 if (!c->rasterizer.state.texture[i].enable) 665 continue; 666 667 int32_t texcoords[8]; 668 texture_unit_t& u(c->textures.tmu[i]); 669 670 // validate this tmu (bind, wrap, filter) 671 validate_tmu(c, i); 672 // we CLAMP here, which works with premultiplied (s,t) 673 c->rasterizer.procs.texParameteri(c, 674 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); 675 c->rasterizer.procs.texParameteri(c, 676 GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); 677 u.dirty = 0xFF; // XXX: should be more subtle 678 679 EGLTextureObject* textureObject = u.texture; 680 const GLint Ucr = textureObject->crop_rect[0] << 16; 681 const GLint Vcr = textureObject->crop_rect[1] << 16; 682 const GLint Wcr = textureObject->crop_rect[2] << 16; 683 const GLint Hcr = textureObject->crop_rect[3] << 16; 684 685 // computes texture coordinates (pre-multiplied) 686 int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt 687 int32_t dtdy =-Hcr / h; // dtdy = -((Hcr/h)/Ht)*Ht 688 int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx 689 int32_t t0 = (Vcr+Hcr) - gglMulx(dtdy, y); // t0 = (Vcr+Hcr) - y*dtdy 690 texcoords[0] = s0; 691 texcoords[1] = dsdx; 692 texcoords[2] = 0; 693 texcoords[3] = t0; 694 texcoords[4] = 0; 695 texcoords[5] = dtdy; 696 texcoords[6] = 0; 697 texcoords[7] = 0; 698 c->rasterizer.procs.texCoordGradScale8xv(c, i, texcoords); 699 } 700 701 const uint32_t enables = c->rasterizer.state.enables; 702 if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) 703 set_depth_and_fog(c, z); 704 705 c->rasterizer.procs.activeTexture(c, c->textures.active); 706 c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); 707 c->rasterizer.procs.disable(c, GGL_W_LERP); 708 c->rasterizer.procs.disable(c, GGL_AA); 709 c->rasterizer.procs.shadeModel(c, GL_FLAT); 710 c->rasterizer.procs.recti(c, 711 gglFixedToIntRound(x), 712 gglFixedToIntRound(y), 713 gglFixedToIntRound(x)+w, 714 gglFixedToIntRound(y)+h); 715 716 ogles_unlock_textures(c); 717} 718 719static void drawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h, 720 ogles_context_t* c) 721{ 722#ifdef LIBAGL_USE_GRALLOC_COPYBITS 723 if (drawTexiOESWithCopybit(gglFixedToIntRound(x), 724 gglFixedToIntRound(y), gglFixedToIntRound(z), 725 gglFixedToIntRound(w), gglFixedToIntRound(h), c)) { 726 return; 727 } 728#else 729 // quickly reject empty rects 730 if ((w|h) <= 0) 731 return; 732#endif 733 drawTexxOESImp(x, y, z, w, h, c); 734} 735 736static void drawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h, ogles_context_t* c) 737{ 738 // All coordinates are integer, so if we have only one 739 // texture unit active and no scaling is required 740 // THEN, we can use our special 1:1 mapping 741 // which is a lot faster. 742 743 if (ggl_likely(c->rasterizer.state.enabled_tmu == 1)) { 744#ifdef LIBAGL_USE_GRALLOC_COPYBITS 745 if (drawTexiOESWithCopybit(x, y, z, w, h, c)) { 746 return; 747 } 748#endif 749 const int tmu = 0; 750 texture_unit_t& u(c->textures.tmu[tmu]); 751 EGLTextureObject* textureObject = u.texture; 752 const GLint Wcr = textureObject->crop_rect[2]; 753 const GLint Hcr = textureObject->crop_rect[3]; 754 755 if ((w == Wcr) && (h == -Hcr)) { 756#ifndef LIBAGL_USE_GRALLOC_COPYBITS 757 if ((w|h) <= 0) return; // quickly reject empty rects 758#endif 759 760 if (u.dirty) { 761 c->rasterizer.procs.activeTexture(c, tmu); 762 c->rasterizer.procs.bindTexture(c, &(u.texture->surface)); 763 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 764 GGL_TEXTURE_MIN_FILTER, u.texture->min_filter); 765 c->rasterizer.procs.texParameteri(c, GGL_TEXTURE_2D, 766 GGL_TEXTURE_MAG_FILTER, u.texture->mag_filter); 767 } 768 c->rasterizer.procs.texGeni(c, GGL_S, 769 GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); 770 c->rasterizer.procs.texGeni(c, GGL_T, 771 GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); 772 u.dirty = 0xFF; // XXX: should be more subtle 773 c->rasterizer.procs.activeTexture(c, c->textures.active); 774 775 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 776 y = cbSurface.height - (y + h); 777 const GLint Ucr = textureObject->crop_rect[0]; 778 const GLint Vcr = textureObject->crop_rect[1]; 779 const GLint s0 = Ucr - x; 780 const GLint t0 = (Vcr + Hcr) - y; 781 782 const GLuint tw = textureObject->surface.width; 783 const GLuint th = textureObject->surface.height; 784 if ((uint32_t(s0+x+w) > tw) || (uint32_t(t0+y+h) > th)) { 785 // The GL spec is unclear about what should happen 786 // in this case, so we just use the slow case, which 787 // at least won't crash 788 goto slow_case; 789 } 790 791 ogles_lock_textures(c); 792 793 c->rasterizer.procs.texCoord2i(c, s0, t0); 794 const uint32_t enables = c->rasterizer.state.enables; 795 if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG))) 796 set_depth_and_fog(c, z); 797 798 c->rasterizer.procs.color4xv(c, c->currentColorClamped.v); 799 c->rasterizer.procs.disable(c, GGL_W_LERP); 800 c->rasterizer.procs.disable(c, GGL_AA); 801 c->rasterizer.procs.shadeModel(c, GL_FLAT); 802 c->rasterizer.procs.recti(c, x, y, x+w, y+h); 803 804 ogles_unlock_textures(c); 805 806 return; 807 } 808 } 809 810slow_case: 811 drawTexxOESImp( 812 gglIntToFixed(x), gglIntToFixed(y), gglIntToFixed(z), 813 gglIntToFixed(w), gglIntToFixed(h), 814 c); 815} 816 817 818}; // namespace android 819// ---------------------------------------------------------------------------- 820 821using namespace android; 822 823 824#if 0 825#pragma mark - 826#pragma mark Texture API 827#endif 828 829void glActiveTexture(GLenum texture) 830{ 831 ogles_context_t* c = ogles_context_t::get(); 832 if (uint32_t(texture-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { 833 ogles_error(c, GL_INVALID_ENUM); 834 return; 835 } 836 c->textures.active = texture - GL_TEXTURE0; 837 c->rasterizer.procs.activeTexture(c, c->textures.active); 838} 839 840void glBindTexture(GLenum target, GLuint texture) 841{ 842 ogles_context_t* c = ogles_context_t::get(); 843 if (target != GL_TEXTURE_2D) { 844 ogles_error(c, GL_INVALID_ENUM); 845 return; 846 } 847 848 // Bind or create a texture 849 sp<EGLTextureObject> tex; 850 if (texture == 0) { 851 // 0 is our local texture object 852 tex = c->textures.defaultTexture; 853 } else { 854 tex = c->surfaceManager->texture(texture); 855 if (ggl_unlikely(tex == 0)) { 856 tex = c->surfaceManager->createTexture(texture); 857 if (tex == 0) { 858 ogles_error(c, GL_OUT_OF_MEMORY); 859 return; 860 } 861 } 862 } 863 bindTextureTmu(c, c->textures.active, texture, tex); 864} 865 866void glGenTextures(GLsizei n, GLuint *textures) 867{ 868 ogles_context_t* c = ogles_context_t::get(); 869 if (n<0) { 870 ogles_error(c, GL_INVALID_VALUE); 871 return; 872 } 873 // generate unique (shared) texture names 874 c->surfaceManager->getToken(n, textures); 875} 876 877void glDeleteTextures(GLsizei n, const GLuint *textures) 878{ 879 ogles_context_t* c = ogles_context_t::get(); 880 if (n<0) { 881 ogles_error(c, GL_INVALID_VALUE); 882 return; 883 } 884 885 // If deleting a bound texture, bind this unit to 0 886 for (int t=0 ; t<GGL_TEXTURE_UNIT_COUNT ; t++) { 887 if (c->textures.tmu[t].name == 0) 888 continue; 889 for (int i=0 ; i<n ; i++) { 890 if (textures[i] && (textures[i] == c->textures.tmu[t].name)) { 891 // bind this tmu to texture 0 892 sp<EGLTextureObject> tex(c->textures.defaultTexture); 893 bindTextureTmu(c, t, 0, tex); 894 } 895 } 896 } 897 c->surfaceManager->deleteTextures(n, textures); 898 c->surfaceManager->recycleTokens(n, textures); 899} 900 901void glMultiTexCoord4f( 902 GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) 903{ 904 ogles_context_t* c = ogles_context_t::get(); 905 if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { 906 ogles_error(c, GL_INVALID_ENUM); 907 return; 908 } 909 const int tmu = target-GL_TEXTURE0; 910 c->current.texture[tmu].S = gglFloatToFixed(s); 911 c->current.texture[tmu].T = gglFloatToFixed(t); 912 c->current.texture[tmu].R = gglFloatToFixed(r); 913 c->current.texture[tmu].Q = gglFloatToFixed(q); 914} 915 916void glMultiTexCoord4x( 917 GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q) 918{ 919 ogles_context_t* c = ogles_context_t::get(); 920 if (uint32_t(target-GL_TEXTURE0) > uint32_t(GGL_TEXTURE_UNIT_COUNT)) { 921 ogles_error(c, GL_INVALID_ENUM); 922 return; 923 } 924 const int tmu = target-GL_TEXTURE0; 925 c->current.texture[tmu].S = s; 926 c->current.texture[tmu].T = t; 927 c->current.texture[tmu].R = r; 928 c->current.texture[tmu].Q = q; 929} 930 931void glPixelStorei(GLenum pname, GLint param) 932{ 933 ogles_context_t* c = ogles_context_t::get(); 934 if ((pname != GL_PACK_ALIGNMENT) && (pname != GL_UNPACK_ALIGNMENT)) { 935 ogles_error(c, GL_INVALID_ENUM); 936 return; 937 } 938 if ((param<=0 || param>8) || (param & (param-1))) { 939 ogles_error(c, GL_INVALID_VALUE); 940 return; 941 } 942 if (pname == GL_PACK_ALIGNMENT) 943 c->textures.packAlignment = param; 944 if (pname == GL_UNPACK_ALIGNMENT) 945 c->textures.unpackAlignment = param; 946} 947 948void glTexEnvf(GLenum target, GLenum pname, GLfloat param) 949{ 950 ogles_context_t* c = ogles_context_t::get(); 951 c->rasterizer.procs.texEnvi(c, target, pname, GLint(param)); 952} 953 954void glTexEnvfv( 955 GLenum target, GLenum pname, const GLfloat *params) 956{ 957 ogles_context_t* c = ogles_context_t::get(); 958 if (pname == GL_TEXTURE_ENV_MODE) { 959 c->rasterizer.procs.texEnvi(c, target, pname, GLint(*params)); 960 return; 961 } 962 if (pname == GL_TEXTURE_ENV_COLOR) { 963 GGLfixed fixed[4]; 964 for (int i=0 ; i<4 ; i++) 965 fixed[i] = gglFloatToFixed(params[i]); 966 c->rasterizer.procs.texEnvxv(c, target, pname, fixed); 967 return; 968 } 969 ogles_error(c, GL_INVALID_ENUM); 970} 971 972void glTexEnvx(GLenum target, GLenum pname, GLfixed param) 973{ 974 ogles_context_t* c = ogles_context_t::get(); 975 c->rasterizer.procs.texEnvi(c, target, pname, param); 976} 977 978void glTexEnvxv( 979 GLenum target, GLenum pname, const GLfixed *params) 980{ 981 ogles_context_t* c = ogles_context_t::get(); 982 c->rasterizer.procs.texEnvxv(c, target, pname, params); 983} 984 985void glTexParameteriv( 986 GLenum target, GLenum pname, const GLint* params) 987{ 988 ogles_context_t* c = ogles_context_t::get(); 989 if (target != GGL_TEXTURE_2D) { 990 ogles_error(c, GL_INVALID_ENUM); 991 return; 992 } 993 994 EGLTextureObject* textureObject = c->textures.tmu[c->textures.active].texture; 995 switch (pname) { 996 case GL_TEXTURE_CROP_RECT_OES: 997 memcpy(textureObject->crop_rect, params, 4*sizeof(GLint)); 998 break; 999 default: 1000 ogles_error(c, GL_INVALID_ENUM); 1001 return; 1002 } 1003} 1004 1005void glTexParameterf( 1006 GLenum target, GLenum pname, GLfloat param) 1007{ 1008 ogles_context_t* c = ogles_context_t::get(); 1009 texParameterx(target, pname, GLfixed(param), c); 1010} 1011 1012void glTexParameterx( 1013 GLenum target, GLenum pname, GLfixed param) 1014{ 1015 ogles_context_t* c = ogles_context_t::get(); 1016 texParameterx(target, pname, param, c); 1017} 1018 1019// ---------------------------------------------------------------------------- 1020#if 0 1021#pragma mark - 1022#endif 1023 1024void glCompressedTexImage2D( 1025 GLenum target, GLint level, GLenum internalformat, 1026 GLsizei width, GLsizei height, GLint border, 1027 GLsizei imageSize, const GLvoid *data) 1028{ 1029 ogles_context_t* c = ogles_context_t::get(); 1030 if (target != GL_TEXTURE_2D) { 1031 ogles_error(c, GL_INVALID_ENUM); 1032 return; 1033 } 1034 if ((internalformat < GL_PALETTE4_RGB8_OES || 1035 internalformat > GL_PALETTE8_RGB5_A1_OES)) { 1036 ogles_error(c, GL_INVALID_ENUM); 1037 return; 1038 } 1039 if (width<0 || height<0 || border!=0) { 1040 ogles_error(c, GL_INVALID_VALUE); 1041 return; 1042 } 1043 1044 // "uncompress" the texture since pixelflinger doesn't support 1045 // any compressed texture format natively. 1046 GLenum format; 1047 GLenum type; 1048 switch (internalformat) { 1049 case GL_PALETTE8_RGB8_OES: 1050 case GL_PALETTE4_RGB8_OES: 1051 format = GL_RGB; 1052 type = GL_UNSIGNED_BYTE; 1053 break; 1054 case GL_PALETTE8_RGBA8_OES: 1055 case GL_PALETTE4_RGBA8_OES: 1056 format = GL_RGBA; 1057 type = GL_UNSIGNED_BYTE; 1058 break; 1059 case GL_PALETTE8_R5_G6_B5_OES: 1060 case GL_PALETTE4_R5_G6_B5_OES: 1061 format = GL_RGB; 1062 type = GL_UNSIGNED_SHORT_5_6_5; 1063 break; 1064 case GL_PALETTE8_RGBA4_OES: 1065 case GL_PALETTE4_RGBA4_OES: 1066 format = GL_RGBA; 1067 type = GL_UNSIGNED_SHORT_4_4_4_4; 1068 break; 1069 case GL_PALETTE8_RGB5_A1_OES: 1070 case GL_PALETTE4_RGB5_A1_OES: 1071 format = GL_RGBA; 1072 type = GL_UNSIGNED_SHORT_5_5_5_1; 1073 break; 1074 default: 1075 ogles_error(c, GL_INVALID_ENUM); 1076 return; 1077 } 1078 1079 if (!data || !width || !height) { 1080 // unclear if this is an error or not... 1081 return; 1082 } 1083 1084 int32_t size; 1085 GGLSurface* surface; 1086 // all mipmap levels are specified at once. 1087 const int numLevels = level<0 ? -level : 1; 1088 for (int i=0 ; i<numLevels ; i++) { 1089 int lod_w = (width >> i) ? : 1; 1090 int lod_h = (height >> i) ? : 1; 1091 int error = createTextureSurface(c, &surface, &size, 1092 i, format, type, lod_w, lod_h); 1093 if (error) { 1094 ogles_error(c, error); 1095 return; 1096 } 1097 decodePalette4(data, i, width, height, 1098 surface->data, surface->stride, internalformat); 1099 } 1100} 1101 1102 1103void glTexImage2D( 1104 GLenum target, GLint level, GLint internalformat, 1105 GLsizei width, GLsizei height, GLint border, 1106 GLenum format, GLenum type, const GLvoid *pixels) 1107{ 1108 ogles_context_t* c = ogles_context_t::get(); 1109 if (target != GL_TEXTURE_2D) { 1110 ogles_error(c, GL_INVALID_ENUM); 1111 return; 1112 } 1113 if (width<0 || height<0 || border!=0 || level < 0) { 1114 ogles_error(c, GL_INVALID_VALUE); 1115 return; 1116 } 1117 if (format != (GLenum)internalformat) { 1118 ogles_error(c, GL_INVALID_OPERATION); 1119 return; 1120 } 1121 if (validFormatType(c, format, type)) { 1122 return; 1123 } 1124 1125 int32_t size = 0; 1126 GGLSurface* surface = 0; 1127 int error = createTextureSurface(c, &surface, &size, 1128 level, format, type, width, height); 1129 if (error) { 1130 ogles_error(c, error); 1131 return; 1132 } 1133 1134 if (pixels) { 1135 const int32_t formatIdx = convertGLPixelFormat(format, type); 1136 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 1137 const int32_t align = c->textures.unpackAlignment-1; 1138 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 1139 const size_t size = bpr * height; 1140 const int32_t stride = bpr / pixelFormat.size; 1141 1142 GGLSurface userSurface; 1143 userSurface.version = sizeof(userSurface); 1144 userSurface.width = width; 1145 userSurface.height = height; 1146 userSurface.stride = stride; 1147 userSurface.format = formatIdx; 1148 userSurface.compressedFormat = 0; 1149 userSurface.data = (GLubyte*)pixels; 1150 1151 int err = copyPixels(c, *surface, 0, 0, userSurface, 0, 0, width, height); 1152 if (err) { 1153 ogles_error(c, err); 1154 return; 1155 } 1156 generateMipmap(c, level); 1157 } 1158} 1159 1160// ---------------------------------------------------------------------------- 1161 1162void glCompressedTexSubImage2D( 1163 GLenum target, GLint level, GLint xoffset, 1164 GLint yoffset, GLsizei width, GLsizei height, 1165 GLenum format, GLsizei imageSize, 1166 const GLvoid *data) 1167{ 1168 ogles_context_t* c = ogles_context_t::get(); 1169 ogles_error(c, GL_INVALID_ENUM); 1170} 1171 1172void glTexSubImage2D( 1173 GLenum target, GLint level, GLint xoffset, 1174 GLint yoffset, GLsizei width, GLsizei height, 1175 GLenum format, GLenum type, const GLvoid *pixels) 1176{ 1177 ogles_context_t* c = ogles_context_t::get(); 1178 if (target != GL_TEXTURE_2D) { 1179 ogles_error(c, GL_INVALID_ENUM); 1180 return; 1181 } 1182 if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { 1183 ogles_error(c, GL_INVALID_VALUE); 1184 return; 1185 } 1186 if (validFormatType(c, format, type)) { 1187 return; 1188 } 1189 1190 // find out which texture is bound to the current unit 1191 const int active = c->textures.active; 1192 EGLTextureObject* tex = c->textures.tmu[active].texture; 1193 const GGLSurface& surface(tex->mip(level)); 1194 1195 if (!tex->internalformat || tex->direct) { 1196 ogles_error(c, GL_INVALID_OPERATION); 1197 return; 1198 } 1199 if ((xoffset + width > GLsizei(surface.width)) || 1200 (yoffset + height > GLsizei(surface.height))) { 1201 ogles_error(c, GL_INVALID_VALUE); 1202 return; 1203 } 1204 if (!width || !height) { 1205 return; // okay, but no-op. 1206 } 1207 1208 // figure out the size we need as well as the stride 1209 const int32_t formatIdx = convertGLPixelFormat(format, type); 1210 if (formatIdx == 0) { // we don't know what to do with this 1211 ogles_error(c, GL_INVALID_OPERATION); 1212 return; 1213 } 1214 1215 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 1216 const int32_t align = c->textures.unpackAlignment-1; 1217 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 1218 const size_t size = bpr * height; 1219 const int32_t stride = bpr / pixelFormat.size; 1220 GGLSurface userSurface; 1221 userSurface.version = sizeof(userSurface); 1222 userSurface.width = width; 1223 userSurface.height = height; 1224 userSurface.stride = stride; 1225 userSurface.format = formatIdx; 1226 userSurface.compressedFormat = 0; 1227 userSurface.data = (GLubyte*)pixels; 1228 1229 int err = copyPixels(c, 1230 surface, xoffset, yoffset, 1231 userSurface, 0, 0, width, height); 1232 if (err) { 1233 ogles_error(c, err); 1234 return; 1235 } 1236 1237 generateMipmap(c, level); 1238 1239 // since we only changed the content of the texture, we don't need 1240 // to call bindTexture on the main rasterizer. 1241} 1242 1243// ---------------------------------------------------------------------------- 1244 1245void glCopyTexImage2D( 1246 GLenum target, GLint level, GLenum internalformat, 1247 GLint x, GLint y, GLsizei width, GLsizei height, 1248 GLint border) 1249{ 1250 ogles_context_t* c = ogles_context_t::get(); 1251 if (target != GL_TEXTURE_2D) { 1252 ogles_error(c, GL_INVALID_ENUM); 1253 return; 1254 } 1255 if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) { 1256 ogles_error(c, GL_INVALID_ENUM); 1257 return; 1258 } 1259 if (width<0 || height<0 || border!=0 || level<0) { 1260 ogles_error(c, GL_INVALID_VALUE); 1261 return; 1262 } 1263 1264 GLenum format = 0; 1265 GLenum type = GL_UNSIGNED_BYTE; 1266 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 1267 const int cbFormatIdx = cbSurface.format; 1268 switch (cbFormatIdx) { 1269 case GGL_PIXEL_FORMAT_RGB_565: 1270 type = GL_UNSIGNED_SHORT_5_6_5; 1271 break; 1272 case GGL_PIXEL_FORMAT_RGBA_5551: 1273 type = GL_UNSIGNED_SHORT_5_5_5_1; 1274 break; 1275 case GGL_PIXEL_FORMAT_RGBA_4444: 1276 type = GL_UNSIGNED_SHORT_4_4_4_4; 1277 break; 1278 } 1279 switch (internalformat) { 1280 case GL_ALPHA: 1281 case GL_LUMINANCE_ALPHA: 1282 case GL_LUMINANCE: 1283 type = GL_UNSIGNED_BYTE; 1284 break; 1285 } 1286 1287 // figure out the format to use for the new texture 1288 switch (cbFormatIdx) { 1289 case GGL_PIXEL_FORMAT_RGBA_8888: 1290 case GGL_PIXEL_FORMAT_A_8: 1291 case GGL_PIXEL_FORMAT_RGBA_5551: 1292 case GGL_PIXEL_FORMAT_RGBA_4444: 1293 format = internalformat; 1294 break; 1295 case GGL_PIXEL_FORMAT_RGBX_8888: 1296 case GGL_PIXEL_FORMAT_RGB_888: 1297 case GGL_PIXEL_FORMAT_RGB_565: 1298 case GGL_PIXEL_FORMAT_L_8: 1299 switch (internalformat) { 1300 case GL_LUMINANCE: 1301 case GL_RGB: 1302 format = internalformat; 1303 break; 1304 } 1305 break; 1306 } 1307 1308 if (format == 0) { 1309 // invalid combination 1310 ogles_error(c, GL_INVALID_ENUM); 1311 return; 1312 } 1313 1314 // create the new texture... 1315 int32_t size; 1316 GGLSurface* surface; 1317 int error = createTextureSurface(c, &surface, &size, 1318 level, format, type, width, height); 1319 if (error) { 1320 ogles_error(c, error); 1321 return; 1322 } 1323 1324 // The bottom row is stored first in textures 1325 GGLSurface txSurface(*surface); 1326 txSurface.stride = -txSurface.stride; 1327 1328 // (x,y) is the lower-left corner of colorBuffer 1329 y = cbSurface.height - (y + height); 1330 1331 int err = copyPixels(c, 1332 txSurface, 0, 0, 1333 cbSurface, x, y, cbSurface.width, cbSurface.height); 1334 if (err) { 1335 ogles_error(c, err); 1336 } 1337 1338 generateMipmap(c, level); 1339} 1340 1341void glCopyTexSubImage2D( 1342 GLenum target, GLint level, GLint xoffset, GLint yoffset, 1343 GLint x, GLint y, GLsizei width, GLsizei height) 1344{ 1345 ogles_context_t* c = ogles_context_t::get(); 1346 if (target != GL_TEXTURE_2D) { 1347 ogles_error(c, GL_INVALID_ENUM); 1348 return; 1349 } 1350 if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { 1351 ogles_error(c, GL_INVALID_VALUE); 1352 return; 1353 } 1354 if (!width || !height) { 1355 return; // okay, but no-op. 1356 } 1357 1358 // find out which texture is bound to the current unit 1359 const int active = c->textures.active; 1360 EGLTextureObject* tex = c->textures.tmu[active].texture; 1361 const GGLSurface& surface(tex->mip(level)); 1362 1363 if (!tex->internalformat) { 1364 ogles_error(c, GL_INVALID_OPERATION); 1365 return; 1366 } 1367 if ((xoffset + width > GLsizei(surface.width)) || 1368 (yoffset + height > GLsizei(surface.height))) { 1369 ogles_error(c, GL_INVALID_VALUE); 1370 return; 1371 } 1372 1373 // The bottom row is stored first in textures 1374 GGLSurface txSurface(surface); 1375 txSurface.stride = -txSurface.stride; 1376 1377 // (x,y) is the lower-left corner of colorBuffer 1378 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 1379 y = cbSurface.height - (y + height); 1380 1381 int err = copyPixels(c, 1382 surface, xoffset, yoffset, 1383 cbSurface, x, y, width, height); 1384 if (err) { 1385 ogles_error(c, err); 1386 return; 1387 } 1388 1389 generateMipmap(c, level); 1390} 1391 1392void glReadPixels( 1393 GLint x, GLint y, GLsizei width, GLsizei height, 1394 GLenum format, GLenum type, GLvoid *pixels) 1395{ 1396 ogles_context_t* c = ogles_context_t::get(); 1397 if ((format != GL_RGBA) && (format != GL_RGB)) { 1398 ogles_error(c, GL_INVALID_ENUM); 1399 return; 1400 } 1401 if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) { 1402 ogles_error(c, GL_INVALID_ENUM); 1403 return; 1404 } 1405 if (width<0 || height<0) { 1406 ogles_error(c, GL_INVALID_VALUE); 1407 return; 1408 } 1409 if (x<0 || x<0) { 1410 ogles_error(c, GL_INVALID_VALUE); 1411 return; 1412 } 1413 1414 int32_t formatIdx = GGL_PIXEL_FORMAT_NONE; 1415 if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) { 1416 formatIdx = GGL_PIXEL_FORMAT_RGBA_8888; 1417 } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) { 1418 formatIdx = GGL_PIXEL_FORMAT_RGB_565; 1419 } else { 1420 ogles_error(c, GL_INVALID_OPERATION); 1421 return; 1422 } 1423 1424 const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s; 1425 if ((x+width > GLint(readSurface.width)) || 1426 (y+height > GLint(readSurface.height))) { 1427 ogles_error(c, GL_INVALID_VALUE); 1428 return; 1429 } 1430 1431 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 1432 const int32_t align = c->textures.packAlignment-1; 1433 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 1434 const int32_t stride = bpr / pixelFormat.size; 1435 1436 GGLSurface userSurface; 1437 userSurface.version = sizeof(userSurface); 1438 userSurface.width = width; 1439 userSurface.height = height; 1440 userSurface.stride = -stride; // bottom row is transfered first 1441 userSurface.format = formatIdx; 1442 userSurface.compressedFormat = 0; 1443 userSurface.data = (GLubyte*)pixels; 1444 1445 // use pixel-flinger to handle all the conversions 1446 GGLContext* ggl = getRasterizer(c); 1447 if (!ggl) { 1448 // the only reason this would fail is because we ran out of memory 1449 ogles_error(c, GL_OUT_OF_MEMORY); 1450 return; 1451 } 1452 1453 ggl->colorBuffer(ggl, &userSurface); // destination is user buffer 1454 ggl->bindTexture(ggl, &readSurface); // source is read-buffer 1455 ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); 1456 ggl->recti(ggl, 0, 0, width, height); 1457} 1458 1459// ---------------------------------------------------------------------------- 1460#if 0 1461#pragma mark - 1462#pragma mark DrawTexture Extension 1463#endif 1464 1465void glDrawTexsvOES(const GLshort* coords) { 1466 ogles_context_t* c = ogles_context_t::get(); 1467 drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1468} 1469void glDrawTexivOES(const GLint* coords) { 1470 ogles_context_t* c = ogles_context_t::get(); 1471 drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1472} 1473void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { 1474 ogles_context_t* c = ogles_context_t::get(); 1475 drawTexiOES(x, y, z, w, h, c); 1476} 1477void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) { 1478 ogles_context_t* c = ogles_context_t::get(); 1479 drawTexiOES(x, y, z, w, h, c); 1480} 1481 1482void glDrawTexfvOES(const GLfloat* coords) { 1483 ogles_context_t* c = ogles_context_t::get(); 1484 drawTexxOES( 1485 gglFloatToFixed(coords[0]), 1486 gglFloatToFixed(coords[1]), 1487 gglFloatToFixed(coords[2]), 1488 gglFloatToFixed(coords[3]), 1489 gglFloatToFixed(coords[4]), 1490 c); 1491} 1492void glDrawTexxvOES(const GLfixed* coords) { 1493 ogles_context_t* c = ogles_context_t::get(); 1494 drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1495} 1496void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){ 1497 ogles_context_t* c = ogles_context_t::get(); 1498 drawTexxOES( 1499 gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z), 1500 gglFloatToFixed(w), gglFloatToFixed(h), 1501 c); 1502} 1503void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { 1504 ogles_context_t* c = ogles_context_t::get(); 1505 drawTexxOES(x, y, z, w, h, c); 1506} 1507 1508// ---------------------------------------------------------------------------- 1509#if 0 1510#pragma mark - 1511#pragma mark EGL Image Extension 1512#endif 1513 1514void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) 1515{ 1516 ogles_context_t* c = ogles_context_t::get(); 1517 if (target != GL_TEXTURE_2D) { 1518 ogles_error(c, GL_INVALID_ENUM); 1519 return; 1520 } 1521 1522 android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; 1523 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { 1524 ogles_error(c, GL_INVALID_VALUE); 1525 return; 1526 } 1527 if (native_buffer->common.version != sizeof(android_native_buffer_t)) { 1528 ogles_error(c, GL_INVALID_VALUE); 1529 return; 1530 } 1531 1532 // bind it to the texture unit 1533 sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); 1534 tex->setImage(native_buffer); 1535 1536 /* 1537 * Here an implementation can retrieve the buffer_handle_t of this buffer 1538 * which gives it access to an arbitrary-defined kernel resource 1539 * (or anything else for that matter). 1540 * There needs to be an intimate knowledge between GLES and buffer_handle_t, 1541 * so make sure to validate the handle before using it. 1542 * Typically, buffer_handle_t comes from the gralloc HAL which is provided 1543 * by the implementor of GLES. 1544 * 1545 */ 1546#ifdef LIBAGL_USE_GRALLOC_COPYBITS 1547 tex->copybits_fd = -1; 1548 private_handle_t* hand; 1549 if ((hand = private_handle_t::dynamicCast(native_buffer->handle)) != NULL) { 1550 if (hand->usesPhysicallyContiguousMemory()) { 1551 tex->copybits_fd = hand->fd; 1552 } 1553 } 1554#endif // LIBAGL_USE_GRALLOC_COPYBITS 1555} 1556 1557void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) 1558{ 1559} 1560