texture.cpp revision cfa316b9e759ca0e9ee80fd275f441666532f9b1
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 if ((xoffset + width > GLsizei(surface.width)) || 1256 (yoffset + height > GLsizei(surface.height))) { 1257 ogles_error(c, GL_INVALID_VALUE); 1258 return; 1259 } 1260 if (!width || !height) { 1261 return; // okay, but no-op. 1262 } 1263 1264 // figure out the size we need as well as the stride 1265 const int32_t formatIdx = convertGLPixelFormat(format, type); 1266 if (formatIdx == 0) { // we don't know what to do with this 1267 ogles_error(c, GL_INVALID_OPERATION); 1268 return; 1269 } 1270 1271 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 1272 const int32_t align = c->textures.unpackAlignment-1; 1273 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 1274 const size_t size = bpr * height; 1275 const int32_t stride = bpr / pixelFormat.size; 1276 GGLSurface userSurface; 1277 userSurface.version = sizeof(userSurface); 1278 userSurface.width = width; 1279 userSurface.height = height; 1280 userSurface.stride = stride; 1281 userSurface.format = formatIdx; 1282 userSurface.compressedFormat = 0; 1283 userSurface.data = (GLubyte*)pixels; 1284 1285 int err = copyPixels(c, 1286 surface, xoffset, yoffset, 1287 userSurface, 0, 0, width, height); 1288 if (err) { 1289 ogles_error(c, err); 1290 return; 1291 } 1292 1293 generateMipmap(c, level); 1294 1295 // since we only changed the content of the texture, we don't need 1296 // to call bindTexture on the main rasterizer. 1297} 1298 1299// ---------------------------------------------------------------------------- 1300 1301void glCopyTexImage2D( 1302 GLenum target, GLint level, GLenum internalformat, 1303 GLint x, GLint y, GLsizei width, GLsizei height, 1304 GLint border) 1305{ 1306 ogles_context_t* c = ogles_context_t::get(); 1307 if (target != GL_TEXTURE_2D) { 1308 ogles_error(c, GL_INVALID_ENUM); 1309 return; 1310 } 1311 if (internalformat<GL_ALPHA || internalformat>GL_LUMINANCE_ALPHA) { 1312 ogles_error(c, GL_INVALID_ENUM); 1313 return; 1314 } 1315 if (width<0 || height<0 || border!=0 || level<0) { 1316 ogles_error(c, GL_INVALID_VALUE); 1317 return; 1318 } 1319 1320 GLenum format = 0; 1321 GLenum type = GL_UNSIGNED_BYTE; 1322 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 1323 const int cbFormatIdx = cbSurface.format; 1324 switch (cbFormatIdx) { 1325 case GGL_PIXEL_FORMAT_RGB_565: 1326 type = GL_UNSIGNED_SHORT_5_6_5; 1327 break; 1328 case GGL_PIXEL_FORMAT_RGBA_5551: 1329 type = GL_UNSIGNED_SHORT_5_5_5_1; 1330 break; 1331 case GGL_PIXEL_FORMAT_RGBA_4444: 1332 type = GL_UNSIGNED_SHORT_4_4_4_4; 1333 break; 1334 } 1335 switch (internalformat) { 1336 case GL_ALPHA: 1337 case GL_LUMINANCE_ALPHA: 1338 case GL_LUMINANCE: 1339 type = GL_UNSIGNED_BYTE; 1340 break; 1341 } 1342 1343 // figure out the format to use for the new texture 1344 switch (cbFormatIdx) { 1345 case GGL_PIXEL_FORMAT_RGBA_8888: 1346 case GGL_PIXEL_FORMAT_A_8: 1347 case GGL_PIXEL_FORMAT_RGBA_5551: 1348 case GGL_PIXEL_FORMAT_RGBA_4444: 1349 format = internalformat; 1350 break; 1351 case GGL_PIXEL_FORMAT_RGBX_8888: 1352 case GGL_PIXEL_FORMAT_RGB_888: 1353 case GGL_PIXEL_FORMAT_RGB_565: 1354 case GGL_PIXEL_FORMAT_L_8: 1355 switch (internalformat) { 1356 case GL_LUMINANCE: 1357 case GL_RGB: 1358 format = internalformat; 1359 break; 1360 } 1361 break; 1362 } 1363 1364 if (format == 0) { 1365 // invalid combination 1366 ogles_error(c, GL_INVALID_ENUM); 1367 return; 1368 } 1369 1370 // create the new texture... 1371 int32_t size; 1372 GGLSurface* surface; 1373 int error = createTextureSurface(c, &surface, &size, 1374 level, format, type, width, height); 1375 if (error) { 1376 ogles_error(c, error); 1377 return; 1378 } 1379 1380 // The bottom row is stored first in textures 1381 GGLSurface txSurface(*surface); 1382 txSurface.stride = -txSurface.stride; 1383 1384 // (x,y) is the lower-left corner of colorBuffer 1385 y = cbSurface.height - (y + height); 1386 1387 int err = copyPixels(c, 1388 txSurface, 0, 0, 1389 cbSurface, x, y, cbSurface.width, cbSurface.height); 1390 if (err) { 1391 ogles_error(c, err); 1392 } 1393 1394 generateMipmap(c, level); 1395} 1396 1397void glCopyTexSubImage2D( 1398 GLenum target, GLint level, GLint xoffset, GLint yoffset, 1399 GLint x, GLint y, GLsizei width, GLsizei height) 1400{ 1401 ogles_context_t* c = ogles_context_t::get(); 1402 if (target != GL_TEXTURE_2D) { 1403 ogles_error(c, GL_INVALID_ENUM); 1404 return; 1405 } 1406 if (xoffset<0 || yoffset<0 || width<0 || height<0 || level<0) { 1407 ogles_error(c, GL_INVALID_VALUE); 1408 return; 1409 } 1410 if (!width || !height) { 1411 return; // okay, but no-op. 1412 } 1413 1414 // find out which texture is bound to the current unit 1415 const int active = c->textures.active; 1416 EGLTextureObject* tex = c->textures.tmu[active].texture; 1417 const GGLSurface& surface(tex->mip(level)); 1418 1419 if (!tex->internalformat) { 1420 ogles_error(c, GL_INVALID_OPERATION); 1421 return; 1422 } 1423 if ((xoffset + width > GLsizei(surface.width)) || 1424 (yoffset + height > GLsizei(surface.height))) { 1425 ogles_error(c, GL_INVALID_VALUE); 1426 return; 1427 } 1428 1429 // The bottom row is stored first in textures 1430 GGLSurface txSurface(surface); 1431 txSurface.stride = -txSurface.stride; 1432 1433 // (x,y) is the lower-left corner of colorBuffer 1434 const GGLSurface& cbSurface = c->rasterizer.state.buffers.color.s; 1435 y = cbSurface.height - (y + height); 1436 1437 int err = copyPixels(c, 1438 surface, xoffset, yoffset, 1439 cbSurface, x, y, width, height); 1440 if (err) { 1441 ogles_error(c, err); 1442 return; 1443 } 1444 1445 generateMipmap(c, level); 1446} 1447 1448void glReadPixels( 1449 GLint x, GLint y, GLsizei width, GLsizei height, 1450 GLenum format, GLenum type, GLvoid *pixels) 1451{ 1452 ogles_context_t* c = ogles_context_t::get(); 1453 if ((format != GL_RGBA) && (format != GL_RGB)) { 1454 ogles_error(c, GL_INVALID_ENUM); 1455 return; 1456 } 1457 if ((type != GL_UNSIGNED_BYTE) && (type != GL_UNSIGNED_SHORT_5_6_5)) { 1458 ogles_error(c, GL_INVALID_ENUM); 1459 return; 1460 } 1461 if (width<0 || height<0) { 1462 ogles_error(c, GL_INVALID_VALUE); 1463 return; 1464 } 1465 if (x<0 || x<0) { 1466 ogles_error(c, GL_INVALID_VALUE); 1467 return; 1468 } 1469 1470 int32_t formatIdx = GGL_PIXEL_FORMAT_NONE; 1471 if ((format == GL_RGBA) && (type == GL_UNSIGNED_BYTE)) { 1472 formatIdx = GGL_PIXEL_FORMAT_RGBA_8888; 1473 } else if ((format == GL_RGB) && (type == GL_UNSIGNED_SHORT_5_6_5)) { 1474 formatIdx = GGL_PIXEL_FORMAT_RGB_565; 1475 } else { 1476 ogles_error(c, GL_INVALID_OPERATION); 1477 return; 1478 } 1479 1480 const GGLSurface& readSurface = c->rasterizer.state.buffers.read.s; 1481 if ((x+width > GLint(readSurface.width)) || 1482 (y+height > GLint(readSurface.height))) { 1483 ogles_error(c, GL_INVALID_VALUE); 1484 return; 1485 } 1486 1487 const GGLFormat& pixelFormat(c->rasterizer.formats[formatIdx]); 1488 const int32_t align = c->textures.packAlignment-1; 1489 const int32_t bpr = ((width * pixelFormat.size) + align) & ~align; 1490 const int32_t stride = bpr / pixelFormat.size; 1491 1492 GGLSurface userSurface; 1493 userSurface.version = sizeof(userSurface); 1494 userSurface.width = width; 1495 userSurface.height = height; 1496 userSurface.stride = -stride; // bottom row is transfered first 1497 userSurface.format = formatIdx; 1498 userSurface.compressedFormat = 0; 1499 userSurface.data = (GLubyte*)pixels; 1500 1501 // use pixel-flinger to handle all the conversions 1502 GGLContext* ggl = getRasterizer(c); 1503 if (!ggl) { 1504 // the only reason this would fail is because we ran out of memory 1505 ogles_error(c, GL_OUT_OF_MEMORY); 1506 return; 1507 } 1508 1509 ggl->colorBuffer(ggl, &userSurface); // destination is user buffer 1510 ggl->bindTexture(ggl, &readSurface); // source is read-buffer 1511 ggl->texCoord2i(ggl, x, readSurface.height - (y + height)); 1512 ggl->recti(ggl, 0, 0, width, height); 1513} 1514 1515// ---------------------------------------------------------------------------- 1516#if 0 1517#pragma mark - 1518#pragma mark DrawTexture Extension 1519#endif 1520 1521void glDrawTexsvOES(const GLshort* coords) { 1522 ogles_context_t* c = ogles_context_t::get(); 1523 drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1524} 1525void glDrawTexivOES(const GLint* coords) { 1526 ogles_context_t* c = ogles_context_t::get(); 1527 drawTexiOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1528} 1529void glDrawTexsOES(GLshort x , GLshort y, GLshort z, GLshort w, GLshort h) { 1530 ogles_context_t* c = ogles_context_t::get(); 1531 drawTexiOES(x, y, z, w, h, c); 1532} 1533void glDrawTexiOES(GLint x, GLint y, GLint z, GLint w, GLint h) { 1534 ogles_context_t* c = ogles_context_t::get(); 1535 drawTexiOES(x, y, z, w, h, c); 1536} 1537 1538void glDrawTexfvOES(const GLfloat* coords) { 1539 ogles_context_t* c = ogles_context_t::get(); 1540 drawTexxOES( 1541 gglFloatToFixed(coords[0]), 1542 gglFloatToFixed(coords[1]), 1543 gglFloatToFixed(coords[2]), 1544 gglFloatToFixed(coords[3]), 1545 gglFloatToFixed(coords[4]), 1546 c); 1547} 1548void glDrawTexxvOES(const GLfixed* coords) { 1549 ogles_context_t* c = ogles_context_t::get(); 1550 drawTexxOES(coords[0], coords[1], coords[2], coords[3], coords[4], c); 1551} 1552void glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat w, GLfloat h){ 1553 ogles_context_t* c = ogles_context_t::get(); 1554 drawTexxOES( 1555 gglFloatToFixed(x), gglFloatToFixed(y), gglFloatToFixed(z), 1556 gglFloatToFixed(w), gglFloatToFixed(h), 1557 c); 1558} 1559void glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed w, GLfixed h) { 1560 ogles_context_t* c = ogles_context_t::get(); 1561 drawTexxOES(x, y, z, w, h, c); 1562} 1563 1564// ---------------------------------------------------------------------------- 1565#if 0 1566#pragma mark - 1567#pragma mark EGL Image Extension 1568#endif 1569 1570void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) 1571{ 1572 ogles_context_t* c = ogles_context_t::get(); 1573 if (target != GL_TEXTURE_2D) { 1574 ogles_error(c, GL_INVALID_ENUM); 1575 return; 1576 } 1577 1578 android_native_buffer_t* native_buffer = (android_native_buffer_t*)image; 1579 if (native_buffer->common.magic != ANDROID_NATIVE_BUFFER_MAGIC) { 1580 ogles_error(c, GL_INVALID_VALUE); 1581 return; 1582 } 1583 if (native_buffer->common.version != sizeof(android_native_buffer_t)) { 1584 ogles_error(c, GL_INVALID_VALUE); 1585 return; 1586 } 1587 1588 // bind it to the texture unit 1589 sp<EGLTextureObject> tex = getAndBindActiveTextureObject(c); 1590 tex->setImage(native_buffer); 1591 1592#ifdef LIBAGL_USE_GRALLOC_COPYBITS 1593 tex->try_copybit = false; 1594 if (c->copybits.blitEngine != NULL) { 1595 tex->try_copybit = true; 1596 } 1597#endif // LIBAGL_USE_GRALLOC_COPYBITS 1598} 1599 1600void glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) 1601{ 1602} 1603