teximage.c revision 1873b567b28a3e3f4d94d0eacb27ffd235ec9529
1/* $Id: teximage.c,v 1.52 2000/10/16 23:43:12 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28#ifdef PC_HEADER 29#include "all.h" 30#else 31#include "glheader.h" 32#include "context.h" 33#include "convolve.h" 34#include "image.h" 35#include "mem.h" 36#include "mmath.h" 37#include "span.h" 38#include "state.h" 39#include "teximage.h" 40#include "texstate.h" 41#include "types.h" 42#endif 43 44 45/* 46 * NOTES: 47 * 48 * Mesa's native texture datatype is GLubyte. Native formats are 49 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, 50 * and GL_COLOR_INDEX. 51 * Device drivers are free to implement any internal format they want. 52 */ 53 54 55#ifdef DEBUG 56static void PrintTexture(const struct gl_texture_image *img) 57{ 58 int i, j, c; 59 GLubyte *data = img->Data; 60 61 if (!data) { 62 printf("No texture data\n"); 63 return; 64 } 65 66 switch (img->Format) { 67 case GL_ALPHA: 68 case GL_LUMINANCE: 69 case GL_INTENSITY: 70 case GL_COLOR_INDEX: 71 c = 1; 72 break; 73 case GL_LUMINANCE_ALPHA: 74 c = 2; 75 break; 76 case GL_RGB: 77 c = 3; 78 break; 79 case GL_RGBA: 80 c = 4; 81 break; 82 default: 83 gl_problem(NULL, "error in PrintTexture\n"); 84 return; 85 } 86 87 88 for (i = 0; i < img->Height; i++) { 89 for (j = 0; j < img->Width; j++) { 90 if (c==1) 91 printf("%02x ", data[0]); 92 else if (c==2) 93 printf("%02x%02x ", data[0], data[1]); 94 else if (c==3) 95 printf("%02x%02x%02x ", data[0], data[1], data[2]); 96 else if (c==4) 97 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 98 data += c; 99 } 100 printf("\n"); 101 } 102} 103#endif 104 105 106 107/* 108 * Compute log base 2 of n. 109 * If n isn't an exact power of two return -1. 110 * If n<0 return -1. 111 */ 112static int 113logbase2( int n ) 114{ 115 GLint i = 1; 116 GLint log2 = 0; 117 118 if (n<0) { 119 return -1; 120 } 121 122 while ( n > i ) { 123 i *= 2; 124 log2++; 125 } 126 if (i != n) { 127 return -1; 128 } 129 else { 130 return log2; 131 } 132} 133 134 135 136/* 137 * Given an internal texture format enum or 1, 2, 3, 4 return the 138 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 139 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. 140 * Return -1 if invalid enum. 141 */ 142GLint 143_mesa_base_tex_format( GLcontext *ctx, GLint format ) 144{ 145 /* 146 * Ask the driver for the base format, if it doesn't 147 * know, it will return -1; 148 */ 149 if (ctx->Driver.BaseCompressedTexFormat) { 150 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format); 151 if (ifmt >= 0) { 152 return ifmt; 153 } 154 } 155 switch (format) { 156 case GL_ALPHA: 157 case GL_ALPHA4: 158 case GL_ALPHA8: 159 case GL_ALPHA12: 160 case GL_ALPHA16: 161 return GL_ALPHA; 162 case 1: 163 case GL_LUMINANCE: 164 case GL_LUMINANCE4: 165 case GL_LUMINANCE8: 166 case GL_LUMINANCE12: 167 case GL_LUMINANCE16: 168 return GL_LUMINANCE; 169 case 2: 170 case GL_LUMINANCE_ALPHA: 171 case GL_LUMINANCE4_ALPHA4: 172 case GL_LUMINANCE6_ALPHA2: 173 case GL_LUMINANCE8_ALPHA8: 174 case GL_LUMINANCE12_ALPHA4: 175 case GL_LUMINANCE12_ALPHA12: 176 case GL_LUMINANCE16_ALPHA16: 177 return GL_LUMINANCE_ALPHA; 178 case GL_INTENSITY: 179 case GL_INTENSITY4: 180 case GL_INTENSITY8: 181 case GL_INTENSITY12: 182 case GL_INTENSITY16: 183 return GL_INTENSITY; 184 case 3: 185 case GL_RGB: 186 case GL_R3_G3_B2: 187 case GL_RGB4: 188 case GL_RGB5: 189 case GL_RGB8: 190 case GL_RGB10: 191 case GL_RGB12: 192 case GL_RGB16: 193 return GL_RGB; 194 case 4: 195 case GL_RGBA: 196 case GL_RGBA2: 197 case GL_RGBA4: 198 case GL_RGB5_A1: 199 case GL_RGBA8: 200 case GL_RGB10_A2: 201 case GL_RGBA12: 202 case GL_RGBA16: 203 return GL_RGBA; 204 case GL_COLOR_INDEX: 205 case GL_COLOR_INDEX1_EXT: 206 case GL_COLOR_INDEX2_EXT: 207 case GL_COLOR_INDEX4_EXT: 208 case GL_COLOR_INDEX8_EXT: 209 case GL_COLOR_INDEX12_EXT: 210 case GL_COLOR_INDEX16_EXT: 211 return GL_COLOR_INDEX; 212 default: 213 return -1; /* error */ 214 } 215} 216 217 218 219/* 220 * Given an internal texture format enum or 1, 2, 3, 4 return the 221 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 222 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the 223 * number of components for the format. Return -1 if invalid enum. 224 */ 225static GLint 226components_in_intformat( GLint format ) 227{ 228 switch (format) { 229 case GL_ALPHA: 230 case GL_ALPHA4: 231 case GL_ALPHA8: 232 case GL_ALPHA12: 233 case GL_ALPHA16: 234 return 1; 235 case 1: 236 case GL_LUMINANCE: 237 case GL_LUMINANCE4: 238 case GL_LUMINANCE8: 239 case GL_LUMINANCE12: 240 case GL_LUMINANCE16: 241 return 1; 242 case 2: 243 case GL_LUMINANCE_ALPHA: 244 case GL_LUMINANCE4_ALPHA4: 245 case GL_LUMINANCE6_ALPHA2: 246 case GL_LUMINANCE8_ALPHA8: 247 case GL_LUMINANCE12_ALPHA4: 248 case GL_LUMINANCE12_ALPHA12: 249 case GL_LUMINANCE16_ALPHA16: 250 return 2; 251 case GL_INTENSITY: 252 case GL_INTENSITY4: 253 case GL_INTENSITY8: 254 case GL_INTENSITY12: 255 case GL_INTENSITY16: 256 return 1; 257 case 3: 258 case GL_RGB: 259 case GL_R3_G3_B2: 260 case GL_RGB4: 261 case GL_RGB5: 262 case GL_RGB8: 263 case GL_RGB10: 264 case GL_RGB12: 265 case GL_RGB16: 266 return 3; 267 case 4: 268 case GL_RGBA: 269 case GL_RGBA2: 270 case GL_RGBA4: 271 case GL_RGB5_A1: 272 case GL_RGBA8: 273 case GL_RGB10_A2: 274 case GL_RGBA12: 275 case GL_RGBA16: 276 return 4; 277 case GL_COLOR_INDEX: 278 case GL_COLOR_INDEX1_EXT: 279 case GL_COLOR_INDEX2_EXT: 280 case GL_COLOR_INDEX4_EXT: 281 case GL_COLOR_INDEX8_EXT: 282 case GL_COLOR_INDEX12_EXT: 283 case GL_COLOR_INDEX16_EXT: 284 return 1; 285 default: 286 return -1; /* error */ 287 } 288} 289 290 291/* 292 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE 293 * otherwise. 294 */ 295static GLboolean 296is_compressed_format(GLcontext *ctx, GLenum internalFormat) 297{ 298 if (ctx->Driver.IsCompressedFormat) { 299 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat); 300 } 301 return GL_FALSE; 302} 303 304 305 306/* 307 * Examine the texImage->Format field and set the Red, Green, Blue, etc 308 * texel component sizes to default values. 309 * These fields are set only here by core Mesa but device drivers may 310 * overwritting these fields to indicate true texel resolution. 311 */ 312static void 313set_teximage_component_sizes( struct gl_texture_image *texImage ) 314{ 315 switch (texImage->Format) { 316 case GL_ALPHA: 317 texImage->RedBits = 0; 318 texImage->GreenBits = 0; 319 texImage->BlueBits = 0; 320 texImage->AlphaBits = 8; 321 texImage->IntensityBits = 0; 322 texImage->LuminanceBits = 0; 323 texImage->IndexBits = 0; 324 break; 325 case GL_LUMINANCE: 326 texImage->RedBits = 0; 327 texImage->GreenBits = 0; 328 texImage->BlueBits = 0; 329 texImage->AlphaBits = 0; 330 texImage->IntensityBits = 0; 331 texImage->LuminanceBits = 8; 332 texImage->IndexBits = 0; 333 break; 334 case GL_LUMINANCE_ALPHA: 335 texImage->RedBits = 0; 336 texImage->GreenBits = 0; 337 texImage->BlueBits = 0; 338 texImage->AlphaBits = 8; 339 texImage->IntensityBits = 0; 340 texImage->LuminanceBits = 8; 341 texImage->IndexBits = 0; 342 break; 343 case GL_INTENSITY: 344 texImage->RedBits = 0; 345 texImage->GreenBits = 0; 346 texImage->BlueBits = 0; 347 texImage->AlphaBits = 0; 348 texImage->IntensityBits = 8; 349 texImage->LuminanceBits = 0; 350 texImage->IndexBits = 0; 351 break; 352 case GL_RED: 353 texImage->RedBits = 8; 354 texImage->GreenBits = 0; 355 texImage->BlueBits = 0; 356 texImage->AlphaBits = 0; 357 texImage->IntensityBits = 0; 358 texImage->LuminanceBits = 0; 359 texImage->IndexBits = 0; 360 break; 361 case GL_GREEN: 362 texImage->RedBits = 0; 363 texImage->GreenBits = 8; 364 texImage->BlueBits = 0; 365 texImage->AlphaBits = 0; 366 texImage->IntensityBits = 0; 367 texImage->LuminanceBits = 0; 368 texImage->IndexBits = 0; 369 break; 370 case GL_BLUE: 371 texImage->RedBits = 0; 372 texImage->GreenBits = 0; 373 texImage->BlueBits = 8; 374 texImage->AlphaBits = 0; 375 texImage->IntensityBits = 0; 376 texImage->LuminanceBits = 0; 377 texImage->IndexBits = 0; 378 break; 379 case GL_RGB: 380 case GL_BGR: 381 texImage->RedBits = 8; 382 texImage->GreenBits = 8; 383 texImage->BlueBits = 8; 384 texImage->AlphaBits = 0; 385 texImage->IntensityBits = 0; 386 texImage->LuminanceBits = 0; 387 texImage->IndexBits = 0; 388 break; 389 case GL_RGBA: 390 case GL_BGRA: 391 case GL_ABGR_EXT: 392 texImage->RedBits = 8; 393 texImage->GreenBits = 8; 394 texImage->BlueBits = 8; 395 texImage->AlphaBits = 8; 396 texImage->IntensityBits = 0; 397 texImage->LuminanceBits = 0; 398 texImage->IndexBits = 0; 399 break; 400 case GL_COLOR_INDEX: 401 texImage->RedBits = 0; 402 texImage->GreenBits = 0; 403 texImage->BlueBits = 0; 404 texImage->AlphaBits = 0; 405 texImage->IntensityBits = 0; 406 texImage->LuminanceBits = 0; 407 texImage->IndexBits = 8; 408 break; 409 default: 410 gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); 411 } 412} 413 414 415static void 416set_tex_image(struct gl_texture_object *tObj, 417 GLenum target, GLint level, 418 struct gl_texture_image *texImage) 419{ 420 ASSERT(tObj); 421 ASSERT(texImage); 422 switch (target) { 423 case GL_TEXTURE_2D: 424 tObj->Image[level] = texImage; 425 return; 426 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 427 tObj->Image[level] = texImage; 428 return; 429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 430 tObj->NegX[level] = texImage; 431 return; 432 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 433 tObj->PosY[level] = texImage; 434 return; 435 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 436 tObj->NegY[level] = texImage; 437 return; 438 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 439 tObj->PosZ[level] = texImage; 440 return; 441 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 442 tObj->NegZ[level] = texImage; 443 return; 444 default: 445 gl_problem(NULL, "bad target in set_tex_image()"); 446 return; 447 } 448} 449 450 451/* 452 * Return new gl_texture_image struct with all fields initialized to zero. 453 */ 454struct gl_texture_image * 455_mesa_alloc_texture_image( void ) 456{ 457 return CALLOC_STRUCT(gl_texture_image); 458} 459 460 461 462/* 463 * Initialize most fields of a gl_texture_image struct. 464 */ 465static void 466init_texture_image( GLcontext *ctx, 467 struct gl_texture_image *img, 468 GLsizei width, GLsizei height, GLsizei depth, 469 GLint border, GLenum internalFormat ) 470{ 471 ASSERT(img); 472 ASSERT(!img->Data); 473 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat); 474 set_teximage_component_sizes( img ); 475 img->IntFormat = (GLenum) internalFormat; 476 img->Border = border; 477 img->Width = width; 478 img->Height = height; 479 img->Depth = depth; 480 img->WidthLog2 = logbase2(width - 2 * border); 481 if (height == 1) /* 1-D texture */ 482 img->HeightLog2 = 0; 483 else 484 img->HeightLog2 = logbase2(height - 2 * border); 485 if (depth == 1) /* 2-D texture */ 486 img->DepthLog2 = 0; 487 else 488 img->DepthLog2 = logbase2(depth - 2 * border); 489 img->Width2 = 1 << img->WidthLog2; 490 img->Height2 = 1 << img->HeightLog2; 491 img->Depth2 = 1 << img->DepthLog2; 492 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 493 img->IsCompressed = is_compressed_format(ctx, internalFormat); 494} 495 496 497 498void 499_mesa_free_texture_image( struct gl_texture_image *teximage ) 500{ 501 if (teximage->Data) { 502 FREE( teximage->Data ); 503 teximage->Data = NULL; 504 } 505 FREE( teximage ); 506} 507 508 509 510/* 511 * Return number of bytes of storage needed to store a compressed texture 512 * image. Only the driver knows for sure. If the driver can't help us, 513 * we must return 0. 514 */ 515GLuint 516_mesa_compressed_image_size(GLcontext *ctx, 517 GLenum internalFormat, 518 GLint numDimensions, 519 GLint width, 520 GLint height, 521 GLint depth) 522{ 523 if (ctx->Driver.CompressedImageSize) { 524 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat, 525 numDimensions, 526 width, height, depth); 527 } 528 else { 529 /* Shouldn't this be an internal error of some sort? */ 530 return 0; 531 } 532} 533 534 535 536/* 537 * Given a texture unit and a texture target, return the corresponding 538 * texture object. 539 */ 540struct gl_texture_object * 541_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 542 GLenum target) 543{ 544 switch (target) { 545 case GL_TEXTURE_1D: 546 return texUnit->CurrentD[1]; 547 case GL_PROXY_TEXTURE_1D: 548 return ctx->Texture.Proxy1D; 549 case GL_TEXTURE_2D: 550 return texUnit->CurrentD[2]; 551 case GL_PROXY_TEXTURE_2D: 552 return ctx->Texture.Proxy2D; 553 case GL_TEXTURE_3D: 554 return texUnit->CurrentD[3]; 555 case GL_PROXY_TEXTURE_3D: 556 return ctx->Texture.Proxy3D; 557 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 558 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 559 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 560 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 561 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 562 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 563 return ctx->Extensions.HaveTextureCubeMap 564 ? texUnit->CurrentCubeMap : NULL; 565 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 566 return ctx->Extensions.HaveTextureCubeMap 567 ? ctx->Texture.ProxyCubeMap : NULL; 568 default: 569 gl_problem(NULL, "bad target in _mesa_select_tex_object()"); 570 return NULL; 571 } 572} 573 574 575/* 576 * Return the texture image struct which corresponds to target and level 577 * for the given texture unit. 578 */ 579struct gl_texture_image * 580_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, 581 GLenum target, GLint level) 582{ 583 ASSERT(texUnit); 584 switch (target) { 585 case GL_TEXTURE_1D: 586 return texUnit->CurrentD[1]->Image[level]; 587 case GL_PROXY_TEXTURE_1D: 588 return ctx->Texture.Proxy1D->Image[level]; 589 case GL_TEXTURE_2D: 590 return texUnit->CurrentD[2]->Image[level]; 591 case GL_PROXY_TEXTURE_2D: 592 return ctx->Texture.Proxy2D->Image[level]; 593 case GL_TEXTURE_3D: 594 return texUnit->CurrentD[3]->Image[level]; 595 case GL_PROXY_TEXTURE_3D: 596 return ctx->Texture.Proxy3D->Image[level]; 597 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 598 if (ctx->Extensions.HaveTextureCubeMap) 599 return texUnit->CurrentCubeMap->Image[level]; 600 else 601 return NULL; 602 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 603 if (ctx->Extensions.HaveTextureCubeMap) 604 return texUnit->CurrentCubeMap->NegX[level]; 605 else 606 return NULL; 607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 608 if (ctx->Extensions.HaveTextureCubeMap) 609 return texUnit->CurrentCubeMap->PosY[level]; 610 else 611 return NULL; 612 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 613 if (ctx->Extensions.HaveTextureCubeMap) 614 return texUnit->CurrentCubeMap->NegY[level]; 615 else 616 return NULL; 617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 618 if (ctx->Extensions.HaveTextureCubeMap) 619 return texUnit->CurrentCubeMap->PosZ[level]; 620 else 621 return NULL; 622 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 623 if (ctx->Extensions.HaveTextureCubeMap) 624 return texUnit->CurrentCubeMap->NegZ[level]; 625 else 626 return NULL; 627 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 628 if (ctx->Extensions.HaveTextureCubeMap) 629 return ctx->Texture.ProxyCubeMap->Image[level]; 630 else 631 return NULL; 632 default: 633 gl_problem(ctx, "bad target in _mesa_select_tex_image()"); 634 return NULL; 635 } 636} 637 638 639 640/* 641 * Calling glTexImage and related functions when convolution is enabled 642 * with GL_REDUCE border mode causes some complications. 643 * The incoming image must be extra large so that the post-convolution 644 * image size is reduced to a power of two size (plus 2 * border). 645 * This function adjusts a texture width and height accordingly if 646 * convolution with GL_REDUCE is enabled. 647 */ 648static void 649adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions, 650 GLsizei *width, GLsizei *height) 651{ 652 if (ctx->Pixel.Convolution1DEnabled 653 && dimensions == 1 654 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) { 655 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1); 656 } 657 else if (ctx->Pixel.Convolution2DEnabled 658 && dimensions > 1 659 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) { 660 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1); 661 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1); 662 } 663 else if (ctx->Pixel.Separable2DEnabled 664 && dimensions > 1 665 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) { 666 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1); 667 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1); 668 } 669} 670 671 672 673/* 674 * This function is used to move user image data into a texture image. 675 * We handle full texture images and subtexture images. We also take 676 * care of all image transfer operations here, including convolution. 677 * Input: 678 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels 679 * dstRowStride, dstImageStride - strides in bytes 680 */ 681static void 682fill_texture_image( GLcontext *ctx, GLuint dimensions, 683 GLenum texFormat, GLubyte *texAddr, 684 GLint srcWidth, GLint srcHeight, GLint srcDepth, 685 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, 686 GLint dstRowStride, GLint dstImageStride, 687 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr, 688 const struct gl_pixelstore_attrib *srcPacking) 689{ 690 GLint texComponents; 691 692 ASSERT(ctx); 693 ASSERT(dimensions >= 1 && dimensions <= 3); 694 ASSERT(texAddr); 695 ASSERT(srcWidth >= 1); 696 ASSERT(srcHeight >= 1); 697 ASSERT(srcDepth >= 1); 698 ASSERT(dstXoffset >= 0); 699 ASSERT(dstYoffset >= 0); 700 ASSERT(dstZoffset >= 0); 701 ASSERT(dstRowStride >= 0); 702 ASSERT(dstImageStride >= 0); 703 ASSERT(srcAddr); 704 ASSERT(srcPacking); 705 706 texComponents = components_in_intformat(texFormat); 707 708 /* try common 2D texture cases first */ 709 if (!ctx->ImageTransferState && dimensions == 2 710 && srcType == GL_UNSIGNED_BYTE) { 711 712 if (srcFormat == texFormat) { 713 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, 714 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy(). 715 */ 716 const GLubyte *src = (const GLubyte *) _mesa_image_address( 717 srcPacking, srcAddr, srcWidth, srcHeight, 718 srcFormat, srcType, 0, 0, 0); 719 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 720 srcWidth, srcFormat, srcType); 721 const GLint widthInBytes = srcWidth * texComponents; 722 GLubyte *dst = texAddr + dstYoffset * dstRowStride 723 + dstXoffset * texComponents * sizeof(GLubyte); 724 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) { 725 MEMCPY(dst, src, srcHeight * widthInBytes); 726 } 727 else { 728 GLint i; 729 for (i = 0; i < srcHeight; i++) { 730 MEMCPY(dst, src, widthInBytes); 731 src += srcRowStride; 732 dst += dstRowStride; 733 } 734 } 735 return; /* all done */ 736 } 737 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) { 738 /* commonly used by Quake */ 739 const GLubyte *src = (const GLubyte *) _mesa_image_address( 740 srcPacking, srcAddr, srcWidth, srcHeight, 741 srcFormat, srcType, 0, 0, 0); 742 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 743 srcWidth, srcFormat, srcType); 744 GLubyte *dst = texAddr + dstYoffset * dstRowStride 745 + dstXoffset * texComponents * sizeof(GLubyte); 746 GLint i, j; 747 for (i = 0; i < srcHeight; i++) { 748 const GLubyte *s = src; 749 GLubyte *d = dst; 750 for (j = 0; j < srcWidth; j++) { 751 *d++ = *s++; /*red*/ 752 *d++ = *s++; /*green*/ 753 *d++ = *s++; /*blue*/ 754 s++; /*alpha*/ 755 } 756 src += srcRowStride; 757 dst += dstRowStride; 758 } 759 return; /* all done */ 760 } 761 } 762 763 /* 764 * General case solutions 765 */ 766 if (texFormat == GL_COLOR_INDEX) { 767 /* color index texture */ 768 const GLenum texType = GL_UNSIGNED_BYTE; 769 GLint img, row; 770 GLubyte *dest = texAddr + dstZoffset * dstImageStride 771 + dstYoffset * dstRowStride 772 + dstXoffset * texComponents * sizeof(GLubyte); 773 for (img = 0; img < srcDepth; img++) { 774 GLubyte *destRow = dest; 775 for (row = 0; row < srcHeight; row++) { 776 const GLvoid *src = _mesa_image_address(srcPacking, 777 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 778 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow, 779 srcType, src, srcPacking, 780 ctx->ImageTransferState); 781 destRow += dstRowStride; 782 } 783 dest += dstImageStride; 784 } 785 } 786 else { 787 /* regular, color texture */ 788 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) || 789 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) || 790 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) { 791 /* 792 * Fill texture image with convolution 793 */ 794 GLint img, row; 795 GLint convWidth = srcWidth, convHeight = srcHeight; 796 GLfloat *tmpImage, *convImage; 797 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); 798 if (!tmpImage) { 799 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 800 return; 801 } 802 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat)); 803 if (!convImage) { 804 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); 805 FREE(tmpImage); 806 return; 807 } 808 809 for (img = 0; img < srcDepth; img++) { 810 const GLfloat *srcf; 811 GLfloat *dstf = tmpImage; 812 GLubyte *dest; 813 814 /* unpack and do transfer ops up to convolution */ 815 for (row = 0; row < srcHeight; row++) { 816 const GLvoid *src = _mesa_image_address(srcPacking, 817 srcAddr, srcWidth, srcHeight, 818 srcFormat, srcType, img, row, 0); 819 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf, 820 srcFormat, srcType, src, srcPacking, 821 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS, 822 GL_TRUE); 823 dstf += srcWidth * 4; 824 } 825 826 /* convolve */ 827 if (dimensions == 1) { 828 ASSERT(ctx->Pixel.Convolution1DEnabled); 829 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage); 830 } 831 else { 832 if (ctx->Pixel.Convolution2DEnabled) { 833 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, 834 tmpImage, convImage); 835 } 836 else { 837 ASSERT(ctx->Pixel.Separable2DEnabled); 838 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, 839 tmpImage, convImage); 840 } 841 } 842 843 /* packing and transfer ops after convolution */ 844 srcf = convImage; 845 dest = texAddr + (dstZoffset + img) * dstImageStride 846 + dstYoffset * dstRowStride; 847 for (row = 0; row < convHeight; row++) { 848 _mesa_pack_float_rgba_span(ctx, convWidth, 849 (const GLfloat (*)[4]) srcf, 850 texFormat, GL_UNSIGNED_BYTE, 851 dest, &_mesa_native_packing, 852 ctx->ImageTransferState 853 & IMAGE_POST_CONVOLUTION_BITS); 854 srcf += convWidth * 4; 855 dest += dstRowStride; 856 } 857 } 858 859 FREE(convImage); 860 FREE(tmpImage); 861 } 862 else { 863 /* 864 * no convolution 865 */ 866 GLint img, row; 867 GLubyte *dest = texAddr + dstZoffset * dstImageStride 868 + dstYoffset * dstRowStride 869 + dstXoffset * texComponents * sizeof(GLubyte); 870 for (img = 0; img < srcDepth; img++) { 871 GLubyte *destRow = dest; 872 for (row = 0; row < srcHeight; row++) { 873 const GLvoid *srcRow = _mesa_image_address(srcPacking, 874 srcAddr, srcWidth, srcHeight, 875 srcFormat, srcType, img, row, 0); 876 _mesa_unpack_ubyte_color_span(ctx, srcWidth, texFormat, destRow, 877 srcFormat, srcType, srcRow, srcPacking, 878 ctx->ImageTransferState); 879 destRow += dstRowStride; 880 } 881 dest += dstImageStride; 882 } 883 } 884 } 885} 886 887 888 889/* Need this to prevent an out-of-bounds memory access when using 890 * X86 optimized code. 891 */ 892#ifdef USE_X86_ASM 893# define EXTRA_BYTE 1 894#else 895# define EXTRA_BYTE 0 896#endif 897 898 899 900/* 901 * Called by glTexImage[123]D. Fill in a texture image with data given 902 * by the client. All pixel transfer and unpack modes are handled here. 903 * Input: dimensions (1, 2, or 3) 904 * texImage - destination texture image (we'll malloc the memory) 905 * width, height, depth - size of source image 906 * srcFormat, srcType - source image format and type 907 * pixels - source image data 908 * srcPacking - source image packing parameters 909 * 910 * NOTE: All texture image parameters should have already been error checked. 911 * 912 * NOTE: the texImage dimensions and source image dimensions must be correct 913 * with respect to convolution with border mode = reduce. 914 */ 915static void 916make_texture_image( GLcontext *ctx, GLuint dimensions, 917 struct gl_texture_image *texImage, 918 GLint width, GLint height, GLint depth, 919 GLenum srcFormat, GLenum srcType, const GLvoid *pixels, 920 const struct gl_pixelstore_attrib *srcPacking) 921{ 922 const GLint internalFormat = texImage->IntFormat; 923 const GLint components = components_in_intformat(internalFormat); 924 GLint convWidth = width, convHeight = height; 925 926 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) { 927 _mesa_update_image_transfer_state(ctx); 928 } 929 930 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) { 931 adjust_texture_size_for_convolution(ctx, dimensions, 932 &convWidth, &convHeight); 933 } 934 935 texImage->Data = (GLubyte *) MALLOC(convWidth * convHeight * depth 936 * components + EXTRA_BYTE); 937 if (!texImage->Data) 938 return; /* out of memory */ 939 940 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data, 941 width, height, depth, 0, 0, 0, 942 convWidth * components * sizeof(GLubyte), 943 convWidth * convHeight * components * sizeof(GLubyte), 944 srcFormat, srcType, pixels, srcPacking); 945} 946 947 948 949/* 950 * glTexImage[123]D can accept a NULL image pointer. In this case we 951 * create a texture image with unspecified image contents per the OpenGL 952 * spec. This function creates an empty image for the given texture image. 953 */ 954static void 955make_null_texture( struct gl_texture_image *texImage ) 956{ 957 GLint components; 958 GLint numPixels; 959 960 ASSERT(texImage); 961 ASSERT(!texImage->Data); 962 963 components = components_in_intformat(texImage->IntFormat); 964 numPixels = texImage->Width * texImage->Height * texImage->Depth; 965 966 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE ); 967 968 /* 969 * Let's see if anyone finds this. If glTexImage2D() is called with 970 * a NULL image pointer then load the texture image with something 971 * interesting instead of leaving it indeterminate. 972 */ 973 if (texImage->Data) { 974 static const char message[8][32] = { 975 " X X XXXXX XXX X ", 976 " XX XX X X X X X ", 977 " X X X X X X X ", 978 " X X XXXX XXX XXXXX ", 979 " X X X X X X ", 980 " X X X X X X X ", 981 " X X XXXXX XXX X X ", 982 " " 983 }; 984 985 GLubyte *imgPtr = texImage->Data; 986 GLint i, j, k; 987 for (i = 0; i < texImage->Height; i++) { 988 GLint srcRow = 7 - i % 8; 989 for (j = 0; j < texImage->Width; j++) { 990 GLint srcCol = j % 32; 991 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 992 for (k=0;k<components;k++) { 993 *imgPtr++ = (GLubyte) texel; 994 } 995 } 996 } 997 } 998} 999 1000 1001 1002/* 1003 * This is called when a proxy texture test fails, we set all the 1004 * image members (except DriverData) to zero. 1005 */ 1006static void 1007clear_proxy_teximage(struct gl_texture_image *img) 1008{ 1009 ASSERT(img); 1010 img->Format = 0; 1011 img->IntFormat = 0; 1012 img->RedBits = 0; 1013 img->GreenBits = 0; 1014 img->BlueBits = 0; 1015 img->AlphaBits = 0; 1016 img->IntensityBits = 0; 1017 img->LuminanceBits = 0; 1018 img->IndexBits = 0; 1019 img->Border = 0; 1020 img->Width = 0; 1021 img->Height = 0; 1022 img->Depth = 0; 1023 img->Width2 = 0; 1024 img->Height2 = 0; 1025 img->Depth2 = 0; 1026 img->WidthLog2 = 0; 1027 img->HeightLog2 = 0; 1028 img->DepthLog2 = 0; 1029 img->Data = NULL; 1030 img->IsCompressed = 0; 1031 img->CompressedSize = 0; 1032} 1033 1034 1035 1036/* 1037 * Test glTexImage[123]D() parameters for errors. 1038 * Input: 1039 * dimensions - must be 1 or 2 or 3 1040 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 1041 */ 1042static GLboolean 1043texture_error_check( GLcontext *ctx, GLenum target, 1044 GLint level, GLint internalFormat, 1045 GLenum format, GLenum type, 1046 GLuint dimensions, 1047 GLint width, GLint height, 1048 GLint depth, GLint border ) 1049{ 1050 GLboolean isProxy; 1051 GLint iformat; 1052 1053 if (dimensions == 1) { 1054 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D); 1055 if (target != GL_TEXTURE_1D && !isProxy) { 1056 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1057 return GL_TRUE; 1058 } 1059 } 1060 else if (dimensions == 2) { 1061 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D); 1062 if (target != GL_TEXTURE_2D && !isProxy && 1063 !(ctx->Extensions.HaveTextureCubeMap && 1064 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1065 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1066 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 1067 return GL_TRUE; 1068 } 1069 } 1070 else if (dimensions == 3) { 1071 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D); 1072 if (target != GL_TEXTURE_3D && !isProxy) { 1073 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1074 return GL_TRUE; 1075 } 1076 } 1077 else { 1078 gl_problem( ctx, "bad dims in texture_error_check" ); 1079 return GL_TRUE; 1080 } 1081 1082 /* Border */ 1083 if (border != 0 && border != 1) { 1084 if (!isProxy) { 1085 char message[100]; 1086 sprintf(message, "glTexImage%dD(border)", dimensions); 1087 gl_error(ctx, GL_INVALID_VALUE, message); 1088 } 1089 return GL_TRUE; 1090 } 1091 1092 /* Width */ 1093 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize 1094 || logbase2( width - 2 * border ) < 0) { 1095 if (!isProxy) { 1096 char message[100]; 1097 sprintf(message, "glTexImage%dD(width)", dimensions); 1098 gl_error(ctx, GL_INVALID_VALUE, message); 1099 } 1100 return GL_TRUE; 1101 } 1102 1103 /* Height */ 1104 if (dimensions >= 2) { 1105 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize 1106 || logbase2( height - 2 * border ) < 0) { 1107 if (!isProxy) { 1108 char message[100]; 1109 sprintf(message, "glTexImage%dD(height)", dimensions); 1110 gl_error(ctx, GL_INVALID_VALUE, message); 1111 } 1112 return GL_TRUE; 1113 } 1114 } 1115 1116 /* For cube map, width must equal height */ 1117 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1118 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1119 if (width != height) { 1120 if (!isProxy) { 1121 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); 1122 } 1123 return GL_TRUE; 1124 } 1125 } 1126 1127 /* Depth */ 1128 if (dimensions >= 3) { 1129 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize 1130 || logbase2( depth - 2 * border ) < 0) { 1131 if (!isProxy) { 1132 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" ); 1133 } 1134 return GL_TRUE; 1135 } 1136 } 1137 1138 /* Level */ 1139 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 1140 if (!isProxy) { 1141 char message[100]; 1142 sprintf(message, "glTexImage%dD(level)", dimensions); 1143 gl_error(ctx, GL_INVALID_VALUE, message); 1144 } 1145 return GL_TRUE; 1146 } 1147 1148 iformat = _mesa_base_tex_format( ctx, internalFormat ); 1149 if (iformat < 0) { 1150 if (!isProxy) { 1151 char message[100]; 1152 sprintf(message, "glTexImage%dD(internalFormat)", dimensions); 1153 gl_error(ctx, GL_INVALID_VALUE, message); 1154 } 1155 return GL_TRUE; 1156 } 1157 1158 if (!is_compressed_format(ctx, internalFormat)) { 1159 if (!_mesa_is_legal_format_and_type( format, type )) { 1160 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 1161 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 1162 */ 1163 if (!isProxy) { 1164 char message[100]; 1165 sprintf(message, "glTexImage%dD(format or type)", dimensions); 1166 gl_error(ctx, GL_INVALID_OPERATION, message); 1167 } 1168 return GL_TRUE; 1169 } 1170 } 1171 1172 /* if we get here, the parameters are OK */ 1173 return GL_FALSE; 1174} 1175 1176 1177 1178/* 1179 * Test glTexSubImage[123]D() parameters for errors. 1180 * Input: 1181 * dimensions - must be 1 or 2 or 3 1182 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 1183 */ 1184static GLboolean 1185subtexture_error_check( GLcontext *ctx, GLuint dimensions, 1186 GLenum target, GLint level, 1187 GLint xoffset, GLint yoffset, GLint zoffset, 1188 GLint width, GLint height, GLint depth, 1189 GLenum format, GLenum type ) 1190{ 1191 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1192 struct gl_texture_image *destTex; 1193 1194 if (dimensions == 1) { 1195 if (target != GL_TEXTURE_1D) { 1196 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 1197 return GL_TRUE; 1198 } 1199 } 1200 else if (dimensions == 2) { 1201 if (ctx->Extensions.HaveTextureCubeMap) { 1202 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 1203 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 1204 target != GL_TEXTURE_2D) { 1205 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1206 return GL_TRUE; 1207 } 1208 } 1209 else if (target != GL_TEXTURE_2D) { 1210 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1211 return GL_TRUE; 1212 } 1213 } 1214 else if (dimensions == 3) { 1215 if (target != GL_TEXTURE_3D) { 1216 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1217 return GL_TRUE; 1218 } 1219 } 1220 else { 1221 gl_problem( ctx, "bad dims in texture_error_check" ); 1222 return GL_TRUE; 1223 } 1224 1225 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 1226 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)"); 1227 return GL_TRUE; 1228 } 1229 1230 if (width < 0) { 1231 char message[100]; 1232 sprintf(message, "glTexSubImage%dD(width)", dimensions); 1233 gl_error(ctx, GL_INVALID_VALUE, message); 1234 return GL_TRUE; 1235 } 1236 if (height < 0 && dimensions > 1) { 1237 char message[100]; 1238 sprintf(message, "glTexSubImage%dD(height)", dimensions); 1239 gl_error(ctx, GL_INVALID_VALUE, message); 1240 return GL_TRUE; 1241 } 1242 if (depth < 0 && dimensions > 2) { 1243 char message[100]; 1244 sprintf(message, "glTexSubImage%dD(depth)", dimensions); 1245 gl_error(ctx, GL_INVALID_VALUE, message); 1246 return GL_TRUE; 1247 } 1248 1249 destTex = texUnit->CurrentD[2]->Image[level]; 1250 if (!destTex) { 1251 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); 1252 return GL_TRUE; 1253 } 1254 1255 if (xoffset < -((GLint)destTex->Border)) { 1256 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); 1257 return GL_TRUE; 1258 } 1259 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1260 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); 1261 return GL_TRUE; 1262 } 1263 if (dimensions > 1) { 1264 if (yoffset < -((GLint)destTex->Border)) { 1265 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); 1266 return GL_TRUE; 1267 } 1268 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 1269 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); 1270 return GL_TRUE; 1271 } 1272 } 1273 if (dimensions > 2) { 1274 if (zoffset < -((GLint)destTex->Border)) { 1275 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 1276 return GL_TRUE; 1277 } 1278 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { 1279 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 1280 return GL_TRUE; 1281 } 1282 } 1283 1284 if (!is_compressed_format(ctx, destTex->IntFormat)) { 1285 if (!_mesa_is_legal_format_and_type(format, type)) { 1286 char message[100]; 1287 sprintf(message, "glTexSubImage%dD(format or type)", dimensions); 1288 gl_error(ctx, GL_INVALID_ENUM, message); 1289 return GL_TRUE; 1290 } 1291 } 1292 1293 return GL_FALSE; 1294} 1295 1296 1297/* 1298 * Test glCopyTexImage[12]D() parameters for errors. 1299 * Input: dimensions - must be 1 or 2 or 3 1300 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 1301 */ 1302static GLboolean 1303copytexture_error_check( GLcontext *ctx, GLuint dimensions, 1304 GLenum target, GLint level, GLint internalFormat, 1305 GLint width, GLint height, GLint border ) 1306{ 1307 GLint iformat; 1308 1309 if (dimensions == 1) { 1310 if (target != GL_TEXTURE_1D) { 1311 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 1312 return GL_TRUE; 1313 } 1314 } 1315 else if (dimensions == 2) { 1316 if (ctx->Extensions.HaveTextureCubeMap) { 1317 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 1318 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 1319 target != GL_TEXTURE_2D) { 1320 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1321 return GL_TRUE; 1322 } 1323 } 1324 else if (target != GL_TEXTURE_2D) { 1325 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1326 return GL_TRUE; 1327 } 1328 } 1329 1330 /* Border */ 1331 if (border!=0 && border!=1) { 1332 char message[100]; 1333 sprintf(message, "glCopyTexImage%dD(border)", dimensions); 1334 gl_error(ctx, GL_INVALID_VALUE, message); 1335 return GL_TRUE; 1336 } 1337 1338 /* Width */ 1339 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize 1340 || logbase2( width - 2 * border ) < 0) { 1341 char message[100]; 1342 sprintf(message, "glCopyTexImage%dD(width)", dimensions); 1343 gl_error(ctx, GL_INVALID_VALUE, message); 1344 return GL_TRUE; 1345 } 1346 1347 /* Height */ 1348 if (dimensions >= 2) { 1349 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize 1350 || logbase2( height - 2 * border ) < 0) { 1351 char message[100]; 1352 sprintf(message, "glCopyTexImage%dD(height)", dimensions); 1353 gl_error(ctx, GL_INVALID_VALUE, message); 1354 return GL_TRUE; 1355 } 1356 } 1357 1358 /* For cube map, width must equal height */ 1359 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1360 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1361 if (width != height) { 1362 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)"); 1363 return GL_TRUE; 1364 } 1365 } 1366 1367 /* Level */ 1368 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1369 char message[100]; 1370 sprintf(message, "glCopyTexImage%dD(level)", dimensions); 1371 gl_error(ctx, GL_INVALID_VALUE, message); 1372 return GL_TRUE; 1373 } 1374 1375 iformat = _mesa_base_tex_format( ctx, internalFormat ); 1376 if (iformat < 0) { 1377 char message[100]; 1378 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); 1379 gl_error(ctx, GL_INVALID_VALUE, message); 1380 return GL_TRUE; 1381 } 1382 1383 /* if we get here, the parameters are OK */ 1384 return GL_FALSE; 1385} 1386 1387 1388static GLboolean 1389copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, 1390 GLenum target, GLint level, 1391 GLint xoffset, GLint yoffset, GLint zoffset, 1392 GLsizei width, GLsizei height ) 1393{ 1394 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1395 struct gl_texture_image *teximage; 1396 1397 if (dimensions == 1) { 1398 if (target != GL_TEXTURE_1D) { 1399 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 1400 return GL_TRUE; 1401 } 1402 } 1403 else if (dimensions == 2) { 1404 if (ctx->Extensions.HaveTextureCubeMap) { 1405 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 1406 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 1407 target != GL_TEXTURE_2D) { 1408 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1409 return GL_TRUE; 1410 } 1411 } 1412 else if (target != GL_TEXTURE_2D) { 1413 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1414 return GL_TRUE; 1415 } 1416 } 1417 else if (dimensions == 3) { 1418 if (target != GL_TEXTURE_3D) { 1419 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 1420 return GL_TRUE; 1421 } 1422 } 1423 1424 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 1425 char message[100]; 1426 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions); 1427 gl_error(ctx, GL_INVALID_VALUE, message); 1428 return GL_TRUE; 1429 } 1430 1431 if (width < 0) { 1432 char message[100]; 1433 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions ); 1434 gl_error(ctx, GL_INVALID_VALUE, message); 1435 return GL_TRUE; 1436 } 1437 if (dimensions > 1 && height < 0) { 1438 char message[100]; 1439 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions ); 1440 gl_error(ctx, GL_INVALID_VALUE, message); 1441 return GL_TRUE; 1442 } 1443 1444 teximage = texUnit->CurrentD[dimensions]->Image[level]; 1445 if (!teximage) { 1446 char message[100]; 1447 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions); 1448 gl_error(ctx, GL_INVALID_OPERATION, message); 1449 return GL_TRUE; 1450 } 1451 1452 if (xoffset < -((GLint)teximage->Border)) { 1453 char message[100]; 1454 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions); 1455 gl_error(ctx, GL_INVALID_VALUE, message); 1456 return GL_TRUE; 1457 } 1458 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { 1459 char message[100]; 1460 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions); 1461 gl_error(ctx, GL_INVALID_VALUE, message); 1462 return GL_TRUE; 1463 } 1464 if (dimensions > 1) { 1465 if (yoffset < -((GLint)teximage->Border)) { 1466 char message[100]; 1467 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions); 1468 gl_error(ctx, GL_INVALID_VALUE, message); 1469 return GL_TRUE; 1470 } 1471 /* NOTE: we're adding the border here, not subtracting! */ 1472 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { 1473 char message[100]; 1474 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions); 1475 gl_error(ctx, GL_INVALID_VALUE, message); 1476 return GL_TRUE; 1477 } 1478 } 1479 1480 if (dimensions > 2) { 1481 if (zoffset < -((GLint)teximage->Border)) { 1482 char message[100]; 1483 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions); 1484 gl_error(ctx, GL_INVALID_VALUE, message); 1485 return GL_TRUE; 1486 } 1487 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { 1488 char message[100]; 1489 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 1490 gl_error(ctx, GL_INVALID_VALUE, message); 1491 return GL_TRUE; 1492 } 1493 } 1494 1495 /* if we get here, the parameters are OK */ 1496 return GL_FALSE; 1497} 1498 1499 1500 1501 1502/* 1503 * Turn generic compressed formats into specific compressed format. 1504 * Some of the compressed formats we don't support, so we 1505 * fall back to the uncompressed format. (See issue 15 of 1506 * the GL_ARB_texture_compression specification.) 1507 */ 1508static GLint 1509get_specific_compressed_tex_format(GLcontext *ctx, 1510 GLint ifmt, GLint numDimensions, 1511 GLint *levelp, 1512 GLsizei *widthp, 1513 GLsizei *heightp, 1514 GLsizei *depthp, 1515 GLint *borderp, 1516 GLenum *formatp, 1517 GLenum *typep) 1518{ 1519 char message[100]; 1520 GLint internalFormat = ifmt; 1521 1522 if (ctx->Extensions.HaveTextureCompression 1523 && ctx->Driver.SpecificCompressedTexFormat) { 1524 /* 1525 * First, ask the driver for the specific format. 1526 * We do this for all formats, since we may want to 1527 * fake one compressed format for another. 1528 */ 1529 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat) 1530 (ctx, internalFormat, numDimensions, 1531 levelp, 1532 widthp, heightp, depthp, 1533 borderp, formatp, typep); 1534 } 1535 1536 /* 1537 * Now, convert any generic format left to an uncompressed 1538 * specific format. If the driver does not support compression 1539 * of the format, we must drop back to the uncompressed format. 1540 * See issue 15 of the GL_ARB_texture_compression specification. 1541 */ 1542 switch (internalFormat) { 1543 case GL_COMPRESSED_ALPHA_ARB: 1544 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1545 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1546 gl_error(ctx, GL_INVALID_VALUE, message); 1547 return -1; 1548 } 1549 internalFormat = GL_ALPHA; 1550 break; 1551 case GL_COMPRESSED_LUMINANCE_ARB: 1552 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1553 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1554 gl_error(ctx, GL_INVALID_VALUE, message); 1555 return -1; 1556 } 1557 internalFormat = GL_LUMINANCE; 1558 break; 1559 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 1560 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1561 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1562 gl_error(ctx, GL_INVALID_VALUE, message); 1563 return -1; 1564 } 1565 internalFormat = GL_LUMINANCE_ALPHA; 1566 break; 1567 case GL_COMPRESSED_INTENSITY_ARB: 1568 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1569 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1570 gl_error(ctx, GL_INVALID_VALUE, message); 1571 return -1; 1572 } 1573 internalFormat = GL_INTENSITY; 1574 break; 1575 case GL_COMPRESSED_RGB_ARB: 1576 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1577 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1578 gl_error(ctx, GL_INVALID_VALUE, message); 1579 return -1; 1580 } 1581 internalFormat = GL_RGB; 1582 break; 1583 case GL_COMPRESSED_RGBA_ARB: 1584 if (ctx && !ctx->Extensions.HaveTextureCompression) { 1585 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions); 1586 gl_error(ctx, GL_INVALID_VALUE, message); 1587 return -1; 1588 } 1589 internalFormat = GL_RGBA; 1590 break; 1591 default: 1592 /* silence compiler warning */ 1593 ; 1594 } 1595 return internalFormat; 1596} 1597 1598 1599/* 1600 * Called from the API. Note that width includes the border. 1601 */ 1602void 1603_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 1604 GLsizei width, GLint border, GLenum format, 1605 GLenum type, const GLvoid *pixels ) 1606{ 1607 GLsizei postConvWidth; 1608 GET_CURRENT_CONTEXT(ctx); 1609 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); 1610 1611 postConvWidth = width; 1612 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL); 1613 1614 if (target==GL_TEXTURE_1D) { 1615 struct gl_texture_unit *texUnit; 1616 struct gl_texture_object *texObj; 1617 struct gl_texture_image *texImage; 1618 GLint ifmt; 1619 1620 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1, 1621 &level, 1622 &width, 0, 0, 1623 &border, &format, &type); 1624 if (ifmt < 0) { 1625 /* 1626 * The error here is that we were sent a generic compressed 1627 * format, but the extension is not supported. 1628 */ 1629 return; 1630 } 1631 else { 1632 internalFormat = ifmt; 1633 } 1634 1635 if (texture_error_check(ctx, target, level, internalFormat, 1636 format, type, 1, postConvWidth, 1, 1, border)) { 1637 return; /* error in texture image was detected */ 1638 } 1639 1640 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1641 texObj = texUnit->CurrentD[1]; 1642 texImage = texObj->Image[level]; 1643 1644 if (!texImage) { 1645 texImage = _mesa_alloc_texture_image(); 1646 texObj->Image[level] = texImage; 1647 if (!texImage) { 1648 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 1649 return; 1650 } 1651 } 1652 else if (texImage->Data) { 1653 FREE(texImage->Data); 1654 texImage->Data = NULL; 1655 } 1656 1657 /* setup the teximage struct's fields */ 1658 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat); 1659 1660 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 1661 _mesa_update_image_transfer_state(ctx); 1662 1663 /* process the texture image */ 1664 if (pixels) { 1665 GLboolean retain = GL_TRUE; 1666 GLboolean success = GL_FALSE; 1667 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) { 1668 /* let device driver try to use raw image */ 1669 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format, 1670 type, pixels, &ctx->Unpack, 1671 texObj, texImage, &retain); 1672 } 1673 if (retain || !success) { 1674 /* make internal copy of the texture image */ 1675 make_texture_image(ctx, 1, texImage, width, 1, 1, 1676 format, type, pixels, &ctx->Unpack); 1677 if (!success && ctx->Driver.TexImage1D) { 1678 /* let device driver try to use unpacked image */ 1679 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 1680 GL_UNSIGNED_BYTE, texImage->Data, 1681 &_mesa_native_packing, 1682 texObj, texImage, &retain); 1683 } 1684 } 1685 if (!retain && texImage->Data) { 1686 FREE(texImage->Data); 1687 texImage->Data = NULL; 1688 } 1689 } 1690 else { 1691 make_null_texture(texImage); 1692 if (ctx->Driver.TexImage1D) { 1693 GLboolean retain; 1694 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 1695 GL_UNSIGNED_BYTE, texImage->Data, 1696 &_mesa_native_packing, 1697 texObj, texImage, &retain); 1698 } 1699 } 1700 1701 /* state update */ 1702 gl_put_texobj_on_dirty_list( ctx, texObj ); 1703 ctx->NewState |= NEW_TEXTURING; 1704 } 1705 else if (target == GL_PROXY_TEXTURE_1D) { 1706 /* Proxy texture: check for errors and update proxy state */ 1707 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1708 format, type, 1, width, 1, 1, border); 1709 if (!error && ctx->Driver.TestProxyTexImage) { 1710 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1711 internalFormat, format, type, 1712 width, 1, 1, border); 1713 } 1714 if (error) { 1715 /* if error, clear all proxy texture image parameters */ 1716 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1717 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]); 1718 } 1719 } 1720 else { 1721 /* if no error, update proxy texture image parameters */ 1722 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level], 1723 width, 1, 1, border, internalFormat); 1724 } 1725 } 1726 else { 1727 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1728 return; 1729 } 1730} 1731 1732 1733void 1734_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 1735 GLsizei width, GLsizei height, GLint border, 1736 GLenum format, GLenum type, 1737 const GLvoid *pixels ) 1738{ 1739 GLsizei postConvWidth, postConvHeight; 1740 GET_CURRENT_CONTEXT(ctx); 1741 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); 1742 1743 postConvWidth = width; 1744 postConvHeight = height; 1745 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight); 1746 1747 if (target==GL_TEXTURE_2D || 1748 (ctx->Extensions.HaveTextureCubeMap && 1749 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1750 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1751 struct gl_texture_unit *texUnit; 1752 struct gl_texture_object *texObj; 1753 struct gl_texture_image *texImage; 1754 GLint ifmt; 1755 1756 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2, 1757 &level, 1758 &width, &height, 0, 1759 &border, &format, &type); 1760 if (ifmt < 0) { 1761 /* 1762 * The error here is that we were sent a generic compressed 1763 * format, but the extension is not supported. 1764 */ 1765 return; 1766 } 1767 else { 1768 internalFormat = ifmt; 1769 } 1770 1771 if (texture_error_check(ctx, target, level, internalFormat, 1772 format, type, 2, postConvWidth, postConvHeight, 1773 1, border)) { 1774 return; /* error in texture image was detected */ 1775 } 1776 1777 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1778 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1779 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1780 1781 if (!texImage) { 1782 texImage = _mesa_alloc_texture_image(); 1783 set_tex_image(texObj, target, level, texImage); 1784 /*texObj->Image[level] = texImage;*/ 1785 if (!texImage) { 1786 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 1787 return; 1788 } 1789 } 1790 else if (texImage->Data) { 1791 FREE(texImage->Data); 1792 texImage->Data = NULL; 1793 } 1794 1795 /* setup the teximage struct's fields */ 1796 init_texture_image(ctx, texImage, postConvWidth, postConvHeight, 1797 1, border, internalFormat); 1798 1799 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 1800 _mesa_update_image_transfer_state(ctx); 1801 1802 /* process the texture image */ 1803 if (pixels) { 1804 GLboolean retain = GL_TRUE; 1805 GLboolean success = GL_FALSE; 1806 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) { 1807 /* let device driver try to use raw image */ 1808 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format, 1809 type, pixels, &ctx->Unpack, 1810 texObj, texImage, &retain); 1811 } 1812 if (retain || !success) { 1813 /* make internal copy of the texture image */ 1814 make_texture_image(ctx, 2, texImage, width, height, 1, 1815 format, type, pixels, &ctx->Unpack); 1816 if (!success && ctx->Driver.TexImage2D) { 1817 /* let device driver try to use unpacked image */ 1818 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, 1819 GL_UNSIGNED_BYTE, texImage->Data, 1820 &_mesa_native_packing, 1821 texObj, texImage, &retain); 1822 } 1823 } 1824 if (!retain && texImage->Data) { 1825 FREE(texImage->Data); 1826 texImage->Data = NULL; 1827 } 1828 } 1829 else { 1830 make_null_texture(texImage); 1831 if (ctx->Driver.TexImage2D) { 1832 GLboolean retain; 1833 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, 1834 GL_UNSIGNED_BYTE, texImage->Data, 1835 &_mesa_native_packing, 1836 texObj, texImage, &retain); 1837 } 1838 } 1839 1840#define OLD_DD_TEXTURE 1841#ifdef OLD_DD_TEXTURE 1842 /* XXX this will be removed in the future */ 1843 if (ctx->Driver.TexImage) { 1844 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat, 1845 texImage ); 1846 } 1847#endif 1848 1849 /* state update */ 1850 gl_put_texobj_on_dirty_list( ctx, texObj ); 1851 ctx->NewState |= NEW_TEXTURING; 1852 } 1853 else if (target == GL_PROXY_TEXTURE_2D) { 1854 /* Proxy texture: check for errors and update proxy state */ 1855 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1856 format, type, 2, width, height, 1, border); 1857 if (!error && ctx->Driver.TestProxyTexImage) { 1858 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1859 internalFormat, format, type, 1860 width, height, 1, border); 1861 } 1862 if (error) { 1863 /* if error, clear all proxy texture image parameters */ 1864 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1865 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]); 1866 } 1867 } 1868 else { 1869 /* if no error, update proxy texture image parameters */ 1870 init_texture_image(ctx, 1871 ctx->Texture.Proxy2D->Image[level], 1872 width, height, 1, border, internalFormat); 1873 } 1874 } 1875 else { 1876 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 1877 return; 1878 } 1879} 1880 1881 1882/* 1883 * Called by the API or display list executor. 1884 * Note that width and height include the border. 1885 */ 1886void 1887_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 1888 GLsizei width, GLsizei height, GLsizei depth, 1889 GLint border, GLenum format, GLenum type, 1890 const GLvoid *pixels ) 1891{ 1892 GET_CURRENT_CONTEXT(ctx); 1893 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D"); 1894 1895 if (target==GL_TEXTURE_3D_EXT) { 1896 struct gl_texture_unit *texUnit; 1897 struct gl_texture_object *texObj; 1898 struct gl_texture_image *texImage; 1899 GLint ifmt; 1900 1901 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3, 1902 &level, 1903 &width, &height, &depth, 1904 &border, &format, &type); 1905 if (ifmt < 0) { 1906 /* 1907 * The error here is that we were sent a generic compressed 1908 * format, but the extension is not supported. 1909 */ 1910 return; 1911 } 1912 else { 1913 internalFormat = ifmt; 1914 } 1915 1916 if (texture_error_check(ctx, target, level, internalFormat, 1917 format, type, 3, width, height, depth, border)) { 1918 return; /* error in texture image was detected */ 1919 } 1920 1921 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1922 texObj = texUnit->CurrentD[3]; 1923 texImage = texObj->Image[level]; 1924 1925 if (!texImage) { 1926 texImage = _mesa_alloc_texture_image(); 1927 texObj->Image[level] = texImage; 1928 if (!texImage) { 1929 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 1930 return; 1931 } 1932 } 1933 else if (texImage->Data) { 1934 FREE(texImage->Data); 1935 texImage->Data = NULL; 1936 } 1937 1938 /* setup the teximage struct's fields */ 1939 init_texture_image(ctx, texImage, width, height, depth, 1940 border, internalFormat); 1941 1942 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 1943 _mesa_update_image_transfer_state(ctx); 1944 1945 /* process the texture image */ 1946 if (pixels) { 1947 GLboolean retain = GL_TRUE; 1948 GLboolean success = GL_FALSE; 1949 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) { 1950 /* let device driver try to use raw image */ 1951 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format, 1952 type, pixels, &ctx->Unpack, 1953 texObj, texImage, &retain); 1954 } 1955 if (retain || !success) { 1956 /* make internal copy of the texture image */ 1957 make_texture_image(ctx, 3, texImage, width, height, depth, 1958 format, type, pixels, &ctx->Unpack); 1959 if (!success && ctx->Driver.TexImage3D) { 1960 /* let device driver try to use unpacked image */ 1961 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, 1962 GL_UNSIGNED_BYTE, texImage->Data, 1963 &_mesa_native_packing, 1964 texObj, texImage, &retain); 1965 } 1966 } 1967 if (!retain && texImage->Data) { 1968 FREE(texImage->Data); 1969 texImage->Data = NULL; 1970 } 1971 } 1972 else { 1973 make_null_texture(texImage); 1974 if (ctx->Driver.TexImage3D) { 1975 GLboolean retain; 1976 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, 1977 GL_UNSIGNED_BYTE, texImage->Data, 1978 &_mesa_native_packing, 1979 texObj, texImage, &retain); 1980 } 1981 } 1982 1983 /* state update */ 1984 gl_put_texobj_on_dirty_list( ctx, texObj ); 1985 ctx->NewState |= NEW_TEXTURING; 1986 } 1987 else if (target == GL_PROXY_TEXTURE_3D) { 1988 /* Proxy texture: check for errors and update proxy state */ 1989 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1990 format, type, 3, width, height, depth, border); 1991 if (!error && ctx->Driver.TestProxyTexImage) { 1992 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1993 internalFormat, format, type, 1994 width, height, depth, border); 1995 } 1996 if (error) { 1997 /* if error, clear all proxy texture image parameters */ 1998 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1999 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]); 2000 } 2001 } 2002 else { 2003 /* if no error, update proxy texture image parameters */ 2004 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level], 2005 width, height, depth, border, internalFormat); 2006 } 2007 } 2008 else { 2009 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 2010 return; 2011 } 2012} 2013 2014 2015void 2016_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2017 GLsizei width, GLsizei height, GLsizei depth, 2018 GLint border, GLenum format, GLenum type, 2019 const GLvoid *pixels ) 2020{ 2021 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2022 depth, border, format, type, pixels); 2023} 2024 2025 2026/* 2027 * Fetch a texture image from the device driver. 2028 * Store the results in the given texture object at the given mipmap level. 2029 */ 2030void 2031_mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level, 2032 const struct gl_texture_object *texObj ) 2033{ 2034 GLvoid *image; 2035 GLenum imgFormat, imgType; 2036 GLboolean freeImage; 2037 struct gl_texture_image *texImage; 2038 GLint destComponents, numPixels, srcBytesPerTexel; 2039 2040 if (!ctx->Driver.GetTexImage) 2041 return; 2042 2043 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj, 2044 &imgFormat, &imgType, &freeImage); 2045 if (!image) 2046 return; 2047 2048 texImage = texObj->Image[level]; 2049 ASSERT(texImage); 2050 if (!texImage) 2051 return; 2052 2053 destComponents = components_in_intformat(texImage->Format); 2054 assert(destComponents > 0); 2055 numPixels = texImage->Width * texImage->Height * texImage->Depth; 2056 assert(numPixels > 0); 2057 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType); 2058 assert(srcBytesPerTexel > 0); 2059 2060 if (!texImage->Data) { 2061 /* Allocate memory for the texture image data */ 2062 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE); 2063 } 2064 2065 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) { 2066 /* We got lucky! The driver's format and type match Mesa's format. */ 2067 if (texImage->Data) { 2068 MEMCPY(texImage->Data, image, numPixels * destComponents); 2069 } 2070 } 2071 else { 2072 /* Convert the texture image from the driver's format to Mesa's 2073 * internal format. 2074 */ 2075 const GLint width = texImage->Width; 2076 const GLint height = texImage->Height; 2077 const GLint depth = texImage->Depth; 2078 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan); 2079 const GLint srcBytesPerRow = width * srcBytesPerTexel; 2080 const GLenum dstType = GL_UNSIGNED_BYTE; 2081 const GLenum dstFormat = texImage->Format; 2082 const GLubyte *srcPtr = (const GLubyte *) image; 2083 GLubyte *destPtr = texImage->Data; 2084 2085 if (texImage->Format == GL_COLOR_INDEX) { 2086 /* color index texture */ 2087 GLint img, row; 2088 assert(imgFormat == GL_COLOR_INDEX); 2089 for (img = 0; img < depth; img++) { 2090 for (row = 0; row < height; row++) { 2091 _mesa_unpack_index_span(ctx, width, dstType, destPtr, 2092 imgType, srcPtr, &_mesa_native_packing, GL_FALSE); 2093 destPtr += destBytesPerRow; 2094 srcPtr += srcBytesPerRow; 2095 } 2096 } 2097 } 2098 else { 2099 /* color texture */ 2100 GLint img, row; 2101 for (img = 0; img < depth; img++) { 2102 for (row = 0; row < height; row++) { 2103 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr, 2104 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE); 2105 destPtr += destBytesPerRow; 2106 srcPtr += srcBytesPerRow; 2107 } 2108 } 2109 } 2110 } 2111 2112 if (freeImage) 2113 FREE(image); 2114} 2115 2116 2117/* 2118 * Get all the mipmap images for a texture object from the device driver. 2119 * Actually, only get mipmap images if we're using a mipmap filter. 2120 */ 2121GLboolean 2122_mesa_get_teximages_from_driver(GLcontext *ctx, 2123 struct gl_texture_object *texObj) 2124{ 2125 if (ctx->Driver.GetTexImage) { 2126 static const GLenum targets[] = { 2127 GL_TEXTURE_1D, 2128 GL_TEXTURE_2D, 2129 GL_TEXTURE_3D, 2130 GL_TEXTURE_CUBE_MAP_ARB, 2131 GL_TEXTURE_CUBE_MAP_ARB, 2132 GL_TEXTURE_CUBE_MAP_ARB 2133 }; 2134 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter); 2135 GLenum target = targets[texObj->Dimensions - 1]; 2136 if (needLambda) { 2137 GLint level; 2138 /* Get images for all mipmap levels. We might not need them 2139 * all but this is easier. We're on a (slow) software path 2140 * anyway. 2141 */ 2142 for (level = 0; level <= texObj->P; level++) { 2143 struct gl_texture_image *texImg = texObj->Image[level]; 2144 if (texImg && !texImg->Data) { 2145 _mesa_get_teximage_from_driver(ctx, target, level, texObj); 2146 if (!texImg->Data) 2147 return GL_FALSE; /* out of memory */ 2148 } 2149 } 2150 } 2151 else { 2152 GLint level = texObj->BaseLevel; 2153 struct gl_texture_image *texImg = texObj->Image[level]; 2154 if (texImg && !texImg->Data) { 2155 _mesa_get_teximage_from_driver(ctx, target, level, texObj); 2156 if (!texImg->Data) 2157 return GL_FALSE; /* out of memory */ 2158 } 2159 } 2160 return GL_TRUE; 2161 } 2162 return GL_FALSE; 2163} 2164 2165 2166 2167void 2168_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 2169 GLenum type, GLvoid *pixels ) 2170{ 2171 GET_CURRENT_CONTEXT(ctx); 2172 const struct gl_texture_unit *texUnit; 2173 const struct gl_texture_object *texObj; 2174 struct gl_texture_image *texImage; 2175 GLboolean discardImage; 2176 2177 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage"); 2178 2179 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 2180 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 2181 return; 2182 } 2183 2184 if (_mesa_sizeof_type(type) <= 0) { 2185 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 2186 return; 2187 } 2188 2189 if (_mesa_components_in_format(format) <= 0) { 2190 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 2191 return; 2192 } 2193 2194 if (!pixels) 2195 return; 2196 2197 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 2198 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2199 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2200 if (!texObj || !texImage || 2201 target == GL_PROXY_TEXTURE_1D || 2202 target == GL_PROXY_TEXTURE_2D || 2203 target == GL_PROXY_TEXTURE_3D) { 2204 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 2205 return; 2206 } 2207 2208 if (!texImage) { 2209 /* invalid mipmap level */ 2210 return; 2211 } 2212 2213 if (!texImage->Data) { 2214 /* try to get the texture image from the device driver */ 2215 _mesa_get_teximage_from_driver(ctx, target, level, texObj); 2216 discardImage = GL_TRUE; 2217 } 2218 else { 2219 discardImage = GL_FALSE; 2220 } 2221 2222 if (texImage->Data) { 2223 GLint width = texImage->Width; 2224 GLint height = texImage->Height; 2225 GLint depth = texImage->Depth; 2226 GLint img, row; 2227 2228 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2229 _mesa_update_image_transfer_state(ctx); 2230 2231 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) { 2232 /* convert texture image to GL_RGBA, GL_FLOAT */ 2233 GLfloat *tmpImage, *convImage; 2234 const GLint comps = components_in_intformat(texImage->Format); 2235 2236 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 2237 if (!tmpImage) { 2238 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 2239 return; 2240 } 2241 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); 2242 if (!convImage) { 2243 FREE(tmpImage); 2244 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 2245 return; 2246 } 2247 2248 for (img = 0; img < depth; img++) { 2249 GLint convWidth, convHeight; 2250 2251 /* convert to GL_RGBA */ 2252 for (row = 0; row < height; row++) { 2253 const GLubyte *src = texImage->Data 2254 + (img * height + row ) * width * comps; 2255 GLfloat *dst = tmpImage + row * width * 4; 2256 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst, 2257 texImage->Format, GL_UNSIGNED_BYTE, 2258 src, &_mesa_native_packing, 2259 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS, 2260 GL_FALSE); 2261 } 2262 2263 convWidth = width; 2264 convHeight = height; 2265 2266 /* convolve */ 2267 if (target == GL_TEXTURE_1D) { 2268 if (ctx->Pixel.Convolution1DEnabled) { 2269 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage); 2270 } 2271 } 2272 else { 2273 if (ctx->Pixel.Convolution2DEnabled) { 2274 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, 2275 tmpImage, convImage); 2276 } 2277 else if (ctx->Pixel.Separable2DEnabled) { 2278 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, 2279 tmpImage, convImage); 2280 } 2281 } 2282 2283 /* pack convolved image */ 2284 for (row = 0; row < convHeight; row++) { 2285 const GLfloat *src = convImage + row * convWidth * 4; 2286 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels, 2287 convWidth, convHeight, 2288 format, type, img, row, 0); 2289 _mesa_pack_float_rgba_span(ctx, convWidth, 2290 (const GLfloat(*)[4]) src, 2291 format, type, dest, &ctx->Pack, 2292 ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS); 2293 } 2294 } 2295 2296 FREE(tmpImage); 2297 FREE(convImage); 2298 } 2299 else { 2300 /* no convolution */ 2301 for (img = 0; img < depth; img++) { 2302 for (row = 0; row < height; row++) { 2303 /* compute destination address in client memory */ 2304 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels, 2305 width, height, format, type, img, row, 0); 2306 assert(dest); 2307 if (texImage->Format == GL_RGBA) { 2308 /* simple case */ 2309 const GLubyte *src = texImage->Data 2310 + (img * height + row ) * width * 4; 2311 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src, 2312 format, type, dest, &ctx->Pack, 2313 ctx->ImageTransferState ); 2314 } 2315 else { 2316 /* general case: convert row to RGBA format */ 2317 GLubyte rgba[MAX_WIDTH][4]; 2318 GLint i; 2319 const GLubyte *src; 2320 switch (texImage->Format) { 2321 case GL_ALPHA: 2322 src = texImage->Data + row * width * sizeof(GLubyte); 2323 for (i = 0; i < width; i++) { 2324 rgba[i][RCOMP] = 255; 2325 rgba[i][GCOMP] = 255; 2326 rgba[i][BCOMP] = 255; 2327 rgba[i][ACOMP] = src[i]; 2328 } 2329 break; 2330 case GL_LUMINANCE: 2331 src = texImage->Data + row * width * sizeof(GLubyte); 2332 for (i = 0; i < width; i++) { 2333 rgba[i][RCOMP] = src[i]; 2334 rgba[i][GCOMP] = src[i]; 2335 rgba[i][BCOMP] = src[i]; 2336 rgba[i][ACOMP] = 255; 2337 } 2338 break; 2339 case GL_LUMINANCE_ALPHA: 2340 src = texImage->Data + row * 2 * width * sizeof(GLubyte); 2341 for (i = 0; i < width; i++) { 2342 rgba[i][RCOMP] = src[i*2+0]; 2343 rgba[i][GCOMP] = src[i*2+0]; 2344 rgba[i][BCOMP] = src[i*2+0]; 2345 rgba[i][ACOMP] = src[i*2+1]; 2346 } 2347 break; 2348 case GL_INTENSITY: 2349 src = texImage->Data + row * width * sizeof(GLubyte); 2350 for (i = 0; i < width; i++) { 2351 rgba[i][RCOMP] = src[i]; 2352 rgba[i][GCOMP] = src[i]; 2353 rgba[i][BCOMP] = src[i]; 2354 rgba[i][ACOMP] = 255; 2355 } 2356 break; 2357 case GL_RGB: 2358 src = texImage->Data + row * 3 * width * sizeof(GLubyte); 2359 for (i = 0; i < width; i++) { 2360 rgba[i][RCOMP] = src[i*3+0]; 2361 rgba[i][GCOMP] = src[i*3+1]; 2362 rgba[i][BCOMP] = src[i*3+2]; 2363 rgba[i][ACOMP] = 255; 2364 } 2365 break; 2366 case GL_COLOR_INDEX: 2367 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" ); 2368 break; 2369 case GL_RGBA: 2370 default: 2371 gl_problem( ctx, "bad format in gl_GetTexImage" ); 2372 } 2373 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba, 2374 format, type, dest, &ctx->Pack, 2375 ctx->ImageTransferState ); 2376 } /* format */ 2377 } /* row */ 2378 } /* img */ 2379 } /* convolution */ 2380 2381 /* if we got the teximage from the device driver we'll discard it now */ 2382 if (discardImage) { 2383 FREE(texImage->Data); 2384 texImage->Data = NULL; 2385 } 2386 } 2387} 2388 2389 2390 2391void 2392_mesa_TexSubImage1D( GLenum target, GLint level, 2393 GLint xoffset, GLsizei width, 2394 GLenum format, GLenum type, 2395 const GLvoid *pixels ) 2396{ 2397 GET_CURRENT_CONTEXT(ctx); 2398 struct gl_texture_unit *texUnit; 2399 struct gl_texture_object *texObj; 2400 struct gl_texture_image *texImage; 2401 GLboolean success = GL_FALSE; 2402 GLsizei postConvWidth; 2403 2404 postConvWidth = width; 2405 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL); 2406 2407 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2408 postConvWidth, 1, 1, format, type)) { 2409 return; /* error was detected */ 2410 } 2411 2412 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2413 texObj = texUnit->CurrentD[1]; 2414 texImage = texObj->Image[level]; 2415 assert(texImage); 2416 2417 if (width == 0 || !pixels) 2418 return; /* no-op, not an error */ 2419 2420 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2421 _mesa_update_image_transfer_state(ctx); 2422 2423 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) { 2424 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset, 2425 width, format, type, pixels, 2426 &ctx->Unpack, texObj, texImage ); 2427 } 2428 if (!success) { 2429 /* XXX if Driver.TexSubImage1D, unpack image and try again? */ 2430 GLboolean retain = GL_TRUE; 2431 if (!texImage->Data) { 2432 _mesa_get_teximage_from_driver( ctx, target, level, texObj ); 2433 if (!texImage->Data) { 2434 make_null_texture(texImage); 2435 } 2436 if (!texImage->Data) 2437 return; /* we're really out of luck! */ 2438 } 2439 2440 fill_texture_image(ctx, 1, texImage->Format, texImage->Data, 2441 width, 1, 1, xoffset, 0, 0, /* size and offsets */ 2442 0, 0, /* strides */ 2443 format, type, pixels, &ctx->Unpack); 2444 2445 if (ctx->Driver.TexImage1D) { 2446 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 2447 GL_UNSIGNED_BYTE, texImage->Data, 2448 &_mesa_native_packing, texObj, texImage, 2449 &retain ); 2450 } 2451 2452 if (!retain && texImage->Data) { 2453 FREE(texImage->Data); 2454 texImage->Data = NULL; 2455 } 2456 } 2457} 2458 2459 2460void 2461_mesa_TexSubImage2D( GLenum target, GLint level, 2462 GLint xoffset, GLint yoffset, 2463 GLsizei width, GLsizei height, 2464 GLenum format, GLenum type, 2465 const GLvoid *pixels ) 2466{ 2467 GET_CURRENT_CONTEXT(ctx); 2468 struct gl_texture_unit *texUnit; 2469 struct gl_texture_object *texObj; 2470 struct gl_texture_image *texImage; 2471 GLboolean success = GL_FALSE; 2472 GLsizei postConvWidth, postConvHeight; 2473 2474 postConvWidth = width; 2475 postConvHeight = height; 2476 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight); 2477 2478 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2479 postConvWidth, postConvHeight, 1, format, type)) { 2480 return; /* error was detected */ 2481 } 2482 2483 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2484 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2485 texImage = texObj->Image[level]; 2486 assert(texImage); 2487 2488 if (width == 0 || height == 0 || !pixels) 2489 return; /* no-op, not an error */ 2490 2491 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2492 _mesa_update_image_transfer_state(ctx); 2493 2494 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) { 2495 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset, 2496 yoffset, width, height, format, type, 2497 pixels, &ctx->Unpack, texObj, texImage ); 2498 } 2499 if (!success) { 2500 /* XXX if Driver.TexSubImage2D, unpack image and try again? */ 2501 const GLint texComps = components_in_intformat(texImage->Format); 2502 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); 2503 GLboolean retain = GL_TRUE; 2504 2505 if (!texImage->Data) { 2506 _mesa_get_teximage_from_driver( ctx, target, level, texObj ); 2507 if (!texImage->Data) { 2508 make_null_texture(texImage); 2509 } 2510 if (!texImage->Data) 2511 return; /* we're really out of luck! */ 2512 } 2513 2514 fill_texture_image(ctx, 2, texImage->Format, texImage->Data, 2515 width, height, 1, xoffset, yoffset, 0, 2516 texRowStride, 0, 2517 format, type, pixels, &ctx->Unpack); 2518 2519 if (ctx->Driver.TexImage2D) { 2520 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format, 2521 GL_UNSIGNED_BYTE, texImage->Data, 2522 &_mesa_native_packing, texObj, texImage, 2523 &retain); 2524 } 2525 2526 if (!retain && texImage->Data) { 2527 FREE(texImage->Data); 2528 texImage->Data = NULL; 2529 } 2530 2531#ifdef OLD_DD_TEXTURE 2532 /* XXX this will be removed in the future */ 2533 if (ctx->Driver.TexSubImage) { 2534 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level, 2535 xoffset, yoffset, width, height, 2536 texImage->IntFormat, texImage); 2537 } 2538 else if (ctx->Driver.TexImage) { 2539 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj, 2540 level, texImage->IntFormat, texImage ); 2541 } 2542#endif 2543 } 2544} 2545 2546 2547 2548void 2549_mesa_TexSubImage3D( GLenum target, GLint level, 2550 GLint xoffset, GLint yoffset, GLint zoffset, 2551 GLsizei width, GLsizei height, GLsizei depth, 2552 GLenum format, GLenum type, 2553 const GLvoid *pixels ) 2554{ 2555 GET_CURRENT_CONTEXT(ctx); 2556 struct gl_texture_unit *texUnit; 2557 struct gl_texture_object *texObj; 2558 struct gl_texture_image *texImage; 2559 GLboolean success = GL_FALSE; 2560 2561 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2562 width, height, depth, format, type)) { 2563 return; /* error was detected */ 2564 } 2565 2566 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2567 texObj = texUnit->CurrentD[3]; 2568 texImage = texObj->Image[level]; 2569 assert(texImage); 2570 2571 if (width == 0 || height == 0 || height == 0 || !pixels) 2572 return; /* no-op, not an error */ 2573 2574 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2575 _mesa_update_image_transfer_state(ctx); 2576 2577 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) { 2578 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset, 2579 yoffset, zoffset, width, height, depth, format, 2580 type, pixels, &ctx->Unpack, texObj, texImage ); 2581 } 2582 if (!success) { 2583 /* XXX if Driver.TexSubImage3D, unpack image and try again? */ 2584 const GLint texComps = components_in_intformat(texImage->Format); 2585 const GLint texRowStride = texImage->Width * texComps * sizeof(GLubyte); 2586 const GLint texImgStride = texRowStride * texImage->Height; 2587 GLboolean retain = GL_TRUE; 2588 2589 if (!texImage->Data) { 2590 _mesa_get_teximage_from_driver( ctx, target, level, texObj ); 2591 if (!texImage->Data) { 2592 make_null_texture(texImage); 2593 } 2594 if (!texImage->Data) 2595 return; /* we're really out of luck! */ 2596 } 2597 2598 fill_texture_image(ctx, 3, texImage->Format, texImage->Data, 2599 width, height, depth, xoffset, yoffset, zoffset, 2600 texRowStride, texImgStride, 2601 format, type, pixels, &ctx->Unpack); 2602 2603 if (ctx->Driver.TexImage3D) { 2604 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format, 2605 GL_UNSIGNED_BYTE, texImage->Data, 2606 &_mesa_native_packing, texObj, texImage, 2607 &retain); 2608 } 2609 2610 if (!retain && texImage->Data) { 2611 FREE(texImage->Data); 2612 texImage->Data = NULL; 2613 } 2614 } 2615} 2616 2617 2618 2619/* 2620 * Read an RGBA image from the frame buffer. 2621 * This is used by glCopyTex[Sub]Image[12]D(). 2622 * Input: ctx - the context 2623 * x, y - lower left corner 2624 * width, height - size of region to read 2625 * Return: pointer to block of GL_RGBA, GLubyte data. 2626 */ 2627static GLubyte * 2628read_color_image( GLcontext *ctx, GLint x, GLint y, 2629 GLsizei width, GLsizei height ) 2630{ 2631 GLint stride, i; 2632 GLubyte *image, *dst; 2633 2634 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte)); 2635 if (!image) 2636 return NULL; 2637 2638 /* Select buffer to read from */ 2639 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, 2640 ctx->Pixel.DriverReadBuffer ); 2641 2642 dst = image; 2643 stride = width * 4 * sizeof(GLubyte); 2644 for (i = 0; i < height; i++) { 2645 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i, 2646 (GLubyte (*)[4]) dst ); 2647 dst += stride; 2648 } 2649 2650 /* Read from draw buffer (the default) */ 2651 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, 2652 ctx->Color.DriverDrawBuffer ); 2653 2654 return image; 2655} 2656 2657 2658 2659void 2660_mesa_CopyTexImage1D( GLenum target, GLint level, 2661 GLenum internalFormat, 2662 GLint x, GLint y, 2663 GLsizei width, GLint border ) 2664{ 2665 GET_CURRENT_CONTEXT(ctx); 2666 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); 2667 2668 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 2669 width, 1, border)) 2670 return; 2671 2672 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2673 _mesa_update_image_transfer_state(ctx); 2674 2675 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D 2676 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level, 2677 internalFormat, x, y, width, border)) { 2678 struct gl_pixelstore_attrib unpackSave; 2679 2680 /* get image from framebuffer */ 2681 GLubyte *image = read_color_image( ctx, x, y, width, 1 ); 2682 if (!image) { 2683 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); 2684 return; 2685 } 2686 2687 /* call glTexImage1D to redefine the texture */ 2688 unpackSave = ctx->Unpack; 2689 ctx->Unpack = _mesa_native_packing; 2690 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width, 2691 border, GL_RGBA, GL_UNSIGNED_BYTE, image ); 2692 ctx->Unpack = unpackSave; 2693 2694 FREE(image); 2695 } 2696} 2697 2698 2699 2700void 2701_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 2702 GLint x, GLint y, GLsizei width, GLsizei height, 2703 GLint border ) 2704{ 2705 GET_CURRENT_CONTEXT(ctx); 2706 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); 2707 2708 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 2709 width, height, border)) 2710 return; 2711 2712 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2713 _mesa_update_image_transfer_state(ctx); 2714 2715 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D 2716 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level, 2717 internalFormat, x, y, width, height, border)) { 2718 struct gl_pixelstore_attrib unpackSave; 2719 2720 /* get image from framebuffer */ 2721 GLubyte *image = read_color_image( ctx, x, y, width, height ); 2722 if (!image) { 2723 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); 2724 return; 2725 } 2726 2727 /* call glTexImage2D to redefine the texture */ 2728 unpackSave = ctx->Unpack; 2729 ctx->Unpack = _mesa_native_packing; 2730 (ctx->Exec->TexImage2D)( target, level, internalFormat, width, 2731 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image ); 2732 ctx->Unpack = unpackSave; 2733 2734 FREE(image); 2735 } 2736} 2737 2738 2739 2740void 2741_mesa_CopyTexSubImage1D( GLenum target, GLint level, 2742 GLint xoffset, GLint x, GLint y, GLsizei width ) 2743{ 2744 GET_CURRENT_CONTEXT(ctx); 2745 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); 2746 2747 if (copytexsubimage_error_check(ctx, 1, target, level, 2748 xoffset, 0, 0, width, 1)) 2749 return; 2750 2751 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2752 _mesa_update_image_transfer_state(ctx); 2753 2754 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D 2755 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, 2756 xoffset, x, y, width)) { 2757 struct gl_texture_unit *texUnit; 2758 struct gl_texture_image *teximage; 2759 struct gl_pixelstore_attrib unpackSave; 2760 GLubyte *image; 2761 2762 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2763 teximage = texUnit->CurrentD[1]->Image[level]; 2764 assert(teximage); 2765 2766 /* get image from frame buffer */ 2767 image = read_color_image(ctx, x, y, width, 1); 2768 if (!image) { 2769 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); 2770 return; 2771 } 2772 2773 /* now call glTexSubImage1D to do the real work */ 2774 unpackSave = ctx->Unpack; 2775 ctx->Unpack = _mesa_native_packing; 2776 _mesa_TexSubImage1D(target, level, xoffset, width, 2777 GL_RGBA, GL_UNSIGNED_BYTE, image); 2778 ctx->Unpack = unpackSave; 2779 2780 FREE(image); 2781 } 2782} 2783 2784 2785 2786void 2787_mesa_CopyTexSubImage2D( GLenum target, GLint level, 2788 GLint xoffset, GLint yoffset, 2789 GLint x, GLint y, GLsizei width, GLsizei height ) 2790{ 2791 GET_CURRENT_CONTEXT(ctx); 2792 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); 2793 2794 if (copytexsubimage_error_check(ctx, 2, target, level, 2795 xoffset, yoffset, 0, width, height)) 2796 return; 2797 2798 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2799 _mesa_update_image_transfer_state(ctx); 2800 2801 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D 2802 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, 2803 xoffset, yoffset, x, y, width, height )) { 2804 struct gl_texture_unit *texUnit; 2805 struct gl_texture_image *teximage; 2806 struct gl_pixelstore_attrib unpackSave; 2807 GLubyte *image; 2808 2809 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2810 teximage = texUnit->CurrentD[2]->Image[level]; 2811 assert(teximage); 2812 2813 /* get image from frame buffer */ 2814 image = read_color_image(ctx, x, y, width, height); 2815 if (!image) { 2816 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); 2817 return; 2818 } 2819 2820 /* now call glTexSubImage2D to do the real work */ 2821 unpackSave = ctx->Unpack; 2822 ctx->Unpack = _mesa_native_packing; 2823 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height, 2824 GL_RGBA, GL_UNSIGNED_BYTE, image); 2825 ctx->Unpack = unpackSave; 2826 2827 FREE(image); 2828 } 2829} 2830 2831 2832 2833void 2834_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2835 GLint xoffset, GLint yoffset, GLint zoffset, 2836 GLint x, GLint y, GLsizei width, GLsizei height ) 2837{ 2838 GET_CURRENT_CONTEXT(ctx); 2839 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D"); 2840 2841 if (copytexsubimage_error_check(ctx, 3, target, level, 2842 xoffset, yoffset, zoffset, width, height)) 2843 return; 2844 2845 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) 2846 _mesa_update_image_transfer_state(ctx); 2847 2848 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D 2849 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, 2850 xoffset, yoffset, zoffset, x, y, width, height )) { 2851 struct gl_texture_unit *texUnit; 2852 struct gl_texture_image *teximage; 2853 struct gl_pixelstore_attrib unpackSave; 2854 GLubyte *image; 2855 2856 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2857 teximage = texUnit->CurrentD[3]->Image[level]; 2858 assert(teximage); 2859 2860 /* get image from frame buffer */ 2861 image = read_color_image(ctx, x, y, width, height); 2862 if (!image) { 2863 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" ); 2864 return; 2865 } 2866 2867 /* now call glTexSubImage2D to do the real work */ 2868 unpackSave = ctx->Unpack; 2869 ctx->Unpack = _mesa_native_packing; 2870 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset, 2871 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image); 2872 ctx->Unpack = unpackSave; 2873 2874 FREE(image); 2875 } 2876} 2877 2878 2879 2880void 2881_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 2882 GLenum internalFormat, GLsizei width, 2883 GLint border, GLsizei imageSize, 2884 const GLvoid *data) 2885{ 2886 GET_CURRENT_CONTEXT(ctx); 2887 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB"); 2888 2889 switch (internalFormat) { 2890 case GL_COMPRESSED_ALPHA_ARB: 2891 case GL_COMPRESSED_LUMINANCE_ARB: 2892 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 2893 case GL_COMPRESSED_INTENSITY_ARB: 2894 case GL_COMPRESSED_RGB_ARB: 2895 case GL_COMPRESSED_RGBA_ARB: 2896 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB"); 2897 return; 2898 default: 2899 /* silence compiler warning */ 2900 ; 2901 } 2902 2903 if (target == GL_TEXTURE_1D) { 2904 struct gl_texture_unit *texUnit; 2905 struct gl_texture_object *texObj; 2906 struct gl_texture_image *texImage; 2907 GLsizei computedImageSize; 2908 2909 if (texture_error_check(ctx, target, level, internalFormat, 2910 GL_NONE, GL_NONE, 1, width, 1, 1, border)) { 2911 return; /* error in texture image was detected */ 2912 } 2913 2914 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2915 texObj = texUnit->CurrentD[1]; 2916 texImage = texObj->Image[level]; 2917 2918 if (!texImage) { 2919 texImage = _mesa_alloc_texture_image(); 2920 texObj->Image[level] = texImage; 2921 if (!texImage) { 2922 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); 2923 return; 2924 } 2925 } 2926 else if (texImage->Data) { 2927 FREE(texImage->Data); 2928 texImage->Data = NULL; 2929 } 2930 2931 /* setup the teximage struct's fields */ 2932 init_texture_image(ctx, texImage, width, 1, 1, 2933 border, internalFormat); 2934 2935 /* process the texture image */ 2936 if (data) { 2937 GLboolean retain = GL_TRUE; 2938 GLboolean success = GL_FALSE; 2939 if (ctx->Driver.CompressedTexImage1D) { 2940 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 2941 imageSize, data, texObj, texImage, &retain); 2942 } 2943 if (retain || !success) { 2944 /* make internal copy of the texture image */ 2945 computedImageSize = _mesa_compressed_image_size(ctx, 2946 internalFormat, 2947 1, /* num dims */ 2948 width, 2949 1, /* height */ 2950 1); /* depth */ 2951 if (computedImageSize != imageSize) { 2952 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)"); 2953 return; 2954 } 2955 texImage->Data = MALLOC(computedImageSize); 2956 if (texImage->Data) { 2957 MEMCPY(texImage->Data, data, computedImageSize); 2958 } 2959 } 2960 if (!retain && texImage->Data) { 2961 FREE(texImage->Data); 2962 texImage->Data = NULL; 2963 } 2964 } 2965 else { 2966 make_null_texture(texImage); 2967 if (ctx->Driver.CompressedTexImage1D) { 2968 GLboolean retain; 2969 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0, 2970 texImage->Data, texObj, 2971 texImage, &retain); 2972 } 2973 } 2974 2975 /* state update */ 2976 gl_put_texobj_on_dirty_list( ctx, texObj ); 2977 ctx->NewState |= NEW_TEXTURING; 2978 } 2979 else if (target == GL_PROXY_TEXTURE_1D) { 2980 /* Proxy texture: check for errors and update proxy state */ 2981 GLenum error = texture_error_check(ctx, target, level, internalFormat, 2982 GL_NONE, GL_NONE, 1, width, 1, 1, border); 2983 if (!error && ctx->Driver.TestProxyTexImage) { 2984 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 2985 internalFormat, GL_NONE, GL_NONE, 2986 width, 1, 1, border); 2987 } 2988 if (error) { 2989 /* if error, clear all proxy texture image parameters */ 2990 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 2991 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]); 2992 } 2993 } 2994 else { 2995 /* if no error, update proxy texture image parameters */ 2996 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level], 2997 width, 1, 1, border, internalFormat); 2998 } 2999 } 3000 else { 3001 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" ); 3002 return; 3003 } 3004} 3005 3006 3007void 3008_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3009 GLenum internalFormat, GLsizei width, 3010 GLsizei height, GLint border, GLsizei imageSize, 3011 const GLvoid *data) 3012{ 3013 GET_CURRENT_CONTEXT(ctx); 3014 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB"); 3015 3016 switch (internalFormat) { 3017 case GL_COMPRESSED_ALPHA_ARB: 3018 case GL_COMPRESSED_LUMINANCE_ARB: 3019 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 3020 case GL_COMPRESSED_INTENSITY_ARB: 3021 case GL_COMPRESSED_RGB_ARB: 3022 case GL_COMPRESSED_RGBA_ARB: 3023 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB"); 3024 return; 3025 default: 3026 /* silence compiler warning */ 3027 ; 3028 } 3029 3030 if (target==GL_TEXTURE_2D || 3031 (ctx->Extensions.HaveTextureCubeMap && 3032 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3033 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 3034 struct gl_texture_unit *texUnit; 3035 struct gl_texture_object *texObj; 3036 struct gl_texture_image *texImage; 3037 GLsizei computedImageSize; 3038 3039 if (texture_error_check(ctx, target, level, internalFormat, 3040 GL_NONE, GL_NONE, 1, width, height, 1, border)) { 3041 return; /* error in texture image was detected */ 3042 } 3043 3044 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3045 texObj = texUnit->CurrentD[2]; 3046 texImage = texObj->Image[level]; 3047 3048 if (!texImage) { 3049 texImage = _mesa_alloc_texture_image(); 3050 texObj->Image[level] = texImage; 3051 if (!texImage) { 3052 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); 3053 return; 3054 } 3055 } 3056 else if (texImage->Data) { 3057 FREE(texImage->Data); 3058 texImage->Data = NULL; 3059 } 3060 3061 /* setup the teximage struct's fields */ 3062 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat); 3063 3064 /* process the texture image */ 3065 if (data) { 3066 GLboolean retain = GL_TRUE; 3067 GLboolean success = GL_FALSE; 3068 if (ctx->Driver.CompressedTexImage2D) { 3069 success = (*ctx->Driver.CompressedTexImage2D)( ctx, 3070 target, 3071 level, 3072 imageSize, 3073 data, 3074 texObj, 3075 texImage, 3076 &retain); 3077 } 3078 if (retain || !success) { 3079 /* make internal copy of the texture image */ 3080 computedImageSize = _mesa_compressed_image_size(ctx, 3081 internalFormat, 3082 2, /* num dims */ 3083 width, 3084 height, 3085 1); /* depth */ 3086 if (computedImageSize != imageSize) { 3087 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)"); 3088 return; 3089 } 3090 texImage->Data = MALLOC(computedImageSize); 3091 if (texImage->Data) { 3092 MEMCPY(texImage->Data, data, computedImageSize); 3093 } 3094 } 3095 if (!retain && texImage->Data) { 3096 FREE(texImage->Data); 3097 texImage->Data = NULL; 3098 } 3099 } 3100 else { 3101 make_null_texture(texImage); 3102 if (ctx->Driver.CompressedTexImage2D) { 3103 GLboolean retain; 3104 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0, 3105 texImage->Data, texObj, 3106 texImage, &retain); 3107 } 3108 } 3109 3110 /* state update */ 3111 gl_put_texobj_on_dirty_list( ctx, texObj ); 3112 ctx->NewState |= NEW_TEXTURING; 3113 } 3114 else if (target == GL_PROXY_TEXTURE_2D) { 3115 /* Proxy texture: check for errors and update proxy state */ 3116 GLenum error = texture_error_check(ctx, target, level, internalFormat, 3117 GL_NONE, GL_NONE, 2, width, height, 1, border); 3118 if (!error && ctx->Driver.TestProxyTexImage) { 3119 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3120 internalFormat, GL_NONE, GL_NONE, 3121 width, height, 1, border); 3122 } 3123 if (error) { 3124 /* if error, clear all proxy texture image parameters */ 3125 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 3126 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]); 3127 } 3128 } 3129 else { 3130 /* if no error, update proxy texture image parameters */ 3131 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level], 3132 width, 1, 1, border, internalFormat); 3133 } 3134 } 3135 else { 3136 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" ); 3137 return; 3138 } 3139} 3140 3141 3142void 3143_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3144 GLenum internalFormat, GLsizei width, 3145 GLsizei height, GLsizei depth, GLint border, 3146 GLsizei imageSize, const GLvoid *data) 3147{ 3148 GET_CURRENT_CONTEXT(ctx); 3149 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB"); 3150 3151 switch (internalFormat) { 3152 case GL_COMPRESSED_ALPHA_ARB: 3153 case GL_COMPRESSED_LUMINANCE_ARB: 3154 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 3155 case GL_COMPRESSED_INTENSITY_ARB: 3156 case GL_COMPRESSED_RGB_ARB: 3157 case GL_COMPRESSED_RGBA_ARB: 3158 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB"); 3159 return; 3160 default: 3161 /* silence compiler warning */ 3162 ; 3163 } 3164 3165 if (target == GL_TEXTURE_3D) { 3166 struct gl_texture_unit *texUnit; 3167 struct gl_texture_object *texObj; 3168 struct gl_texture_image *texImage; 3169 GLsizei computedImageSize; 3170 3171 if (texture_error_check(ctx, target, level, internalFormat, 3172 GL_NONE, GL_NONE, 1, width, height, depth, border)) { 3173 return; /* error in texture image was detected */ 3174 } 3175 3176 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3177 texObj = texUnit->CurrentD[3]; 3178 texImage = texObj->Image[level]; 3179 3180 if (!texImage) { 3181 texImage = _mesa_alloc_texture_image(); 3182 texObj->Image[level] = texImage; 3183 if (!texImage) { 3184 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); 3185 return; 3186 } 3187 } 3188 else if (texImage->Data) { 3189 FREE(texImage->Data); 3190 texImage->Data = NULL; 3191 } 3192 3193 /* setup the teximage struct's fields */ 3194 init_texture_image(ctx, texImage, width, height, depth, 3195 border, internalFormat); 3196 3197 /* process the texture image */ 3198 if (data) { 3199 GLboolean retain = GL_TRUE; 3200 GLboolean success = GL_FALSE; 3201 if (ctx->Driver.CompressedTexImage3D) { 3202 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 3203 imageSize, data, 3204 texObj, texImage, 3205 &retain); 3206 } 3207 if (retain || !success) { 3208 /* make internal copy of the texture image */ 3209 computedImageSize = _mesa_compressed_image_size(ctx, 3210 internalFormat, 3211 3, /* num dims */ 3212 width, 3213 height, 3214 depth); 3215 if (computedImageSize != imageSize) { 3216 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)"); 3217 return; 3218 } 3219 texImage->Data = MALLOC(computedImageSize); 3220 if (texImage->Data) { 3221 MEMCPY(texImage->Data, data, computedImageSize); 3222 } 3223 } 3224 if (!retain && texImage->Data) { 3225 FREE(texImage->Data); 3226 texImage->Data = NULL; 3227 } 3228 } 3229 else { 3230 make_null_texture(texImage); 3231 if (ctx->Driver.CompressedTexImage3D) { 3232 GLboolean retain; 3233 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0, 3234 texImage->Data, texObj, 3235 texImage, &retain); 3236 } 3237 } 3238 3239 /* state update */ 3240 gl_put_texobj_on_dirty_list( ctx, texObj ); 3241 ctx->NewState |= NEW_TEXTURING; 3242 } 3243 else if (target == GL_PROXY_TEXTURE_3D) { 3244 /* Proxy texture: check for errors and update proxy state */ 3245 GLenum error = texture_error_check(ctx, target, level, internalFormat, 3246 GL_NONE, GL_NONE, 1, width, height, depth, border); 3247 if (!error && ctx->Driver.TestProxyTexImage) { 3248 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3249 internalFormat, GL_NONE, GL_NONE, 3250 width, height, depth, border); 3251 } 3252 if (error) { 3253 /* if error, clear all proxy texture image parameters */ 3254 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 3255 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]); 3256 } 3257 } 3258 else { 3259 /* if no error, update proxy texture image parameters */ 3260 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level], 3261 width, 1, 1, border, internalFormat); 3262 } 3263 } 3264 else { 3265 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" ); 3266 return; 3267 } 3268} 3269 3270 3271void 3272_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3273 GLsizei width, GLenum format, 3274 GLsizei imageSize, const GLvoid *data) 3275{ 3276 GET_CURRENT_CONTEXT(ctx); 3277 struct gl_texture_unit *texUnit; 3278 struct gl_texture_object *texObj; 3279 struct gl_texture_image *texImage; 3280 GLboolean success = GL_FALSE; 3281 3282 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 3283 width, 1, 1, format, GL_NONE)) { 3284 return; /* error was detected */ 3285 } 3286 3287 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3288 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3289 texImage = texObj->Image[level]; 3290 assert(texImage); 3291 3292 if (width == 0 || !data) 3293 return; /* no-op, not an error */ 3294 3295 if (ctx->Driver.CompressedTexSubImage1D) { 3296 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 3297 xoffset, width, format, imageSize, data, texObj, texImage); 3298 } 3299 if (!success) { 3300 /* XXX what else can we do? */ 3301 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!"); 3302 return; 3303 } 3304} 3305 3306 3307void 3308_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3309 GLint yoffset, GLsizei width, GLsizei height, 3310 GLenum format, GLsizei imageSize, 3311 const GLvoid *data) 3312{ 3313 GET_CURRENT_CONTEXT(ctx); 3314 struct gl_texture_unit *texUnit; 3315 struct gl_texture_object *texObj; 3316 struct gl_texture_image *texImage; 3317 GLboolean success = GL_FALSE; 3318 3319 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 3320 width, height, 1, format, GL_NONE)) { 3321 return; /* error was detected */ 3322 } 3323 3324 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3325 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3326 texImage = texObj->Image[level]; 3327 assert(texImage); 3328 3329 if (width == 0 || height == 0 || !data) 3330 return; /* no-op, not an error */ 3331 3332 if (ctx->Driver.CompressedTexSubImage2D) { 3333 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 3334 xoffset, yoffset, width, height, format, 3335 imageSize, data, texObj, texImage); 3336 } 3337 if (!success) { 3338 /* XXX what else can we do? */ 3339 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!"); 3340 return; 3341 } 3342} 3343 3344 3345void 3346_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3347 GLint yoffset, GLint zoffset, GLsizei width, 3348 GLsizei height, GLsizei depth, GLenum format, 3349 GLsizei imageSize, const GLvoid *data) 3350{ 3351 GET_CURRENT_CONTEXT(ctx); 3352 struct gl_texture_unit *texUnit; 3353 struct gl_texture_object *texObj; 3354 struct gl_texture_image *texImage; 3355 GLboolean success = GL_FALSE; 3356 3357 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 3358 width, height, depth, format, GL_NONE)) { 3359 return; /* error was detected */ 3360 } 3361 3362 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3363 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3364 texImage = texObj->Image[level]; 3365 assert(texImage); 3366 3367 if (width == 0 || height == 0 || depth == 0 || !data) 3368 return; /* no-op, not an error */ 3369 3370 if (ctx->Driver.CompressedTexSubImage3D) { 3371 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 3372 xoffset, yoffset, zoffset, width, height, depth, 3373 format, imageSize, data, texObj, texImage); 3374 } 3375 if (!success) { 3376 /* XXX what else can we do? */ 3377 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!"); 3378 return; 3379 } 3380} 3381 3382 3383void 3384_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 3385{ 3386 GET_CURRENT_CONTEXT(ctx); 3387 const struct gl_texture_object *texObj; 3388 struct gl_texture_image *texImage; 3389 3390 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB"); 3391 3392 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 3393 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" ); 3394 return; 3395 } 3396 3397 switch (target) { 3398 case GL_TEXTURE_1D: 3399 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; 3400 texImage = texObj->Image[level]; 3401 break; 3402 case GL_TEXTURE_2D: 3403 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; 3404 texImage = texObj->Image[level]; 3405 break; 3406 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 3407 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3408 texImage = texObj->Image[level]; 3409 break; 3410 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 3411 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3412 texImage = texObj->NegX[level]; 3413 break; 3414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 3415 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3416 texImage = texObj->PosY[level]; 3417 break; 3418 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 3419 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3420 texImage = texObj->NegY[level]; 3421 break; 3422 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 3423 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3424 texImage = texObj->PosZ[level]; 3425 break; 3426 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 3427 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap; 3428 texImage = texObj->NegZ[level]; 3429 break; 3430 case GL_TEXTURE_3D: 3431 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; 3432 texImage = texObj->Image[level]; 3433 break; 3434 default: 3435 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 3436 return; 3437 } 3438 3439 if (!texImage) { 3440 /* invalid mipmap level */ 3441 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 3442 return; 3443 } 3444 3445 if (!texImage->IsCompressed) { 3446 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); 3447 return; 3448 } 3449 3450 if (!img) 3451 return; 3452 3453 if (ctx->Driver.GetCompressedTexImage) { 3454 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj, 3455 texImage); 3456 } 3457 else { 3458 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage"); 3459 } 3460} 3461