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