teximage.c revision b23f5b5a5ccf5910f1d11d749c2e440e6a46259b
1/* $Id: teximage.c,v 1.99 2001/07/13 15:44:21 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.5 6 * 7 * Copyright (C) 1999-2001 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 "macros.h" 36#include "mem.h" 37#include "mmath.h" 38#include "state.h" 39#include "texformat.h" 40#include "teximage.h" 41#include "texstate.h" 42#include "texstore.h" 43#include "mtypes.h" 44#include "swrast/s_span.h" /* XXX SWRAST hack */ 45#endif 46 47 48/* 49 * NOTES: 50 * 51 * Mesa's native texture datatype is GLchan. Native formats are 52 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, 53 * and GL_COLOR_INDEX. 54 * Device drivers are free to implement any internal format they want. 55 */ 56 57 58#ifdef DEBUG 59static void PrintTexture(const struct gl_texture_image *img) 60{ 61 GLuint i, j, c; 62 const GLchan *data = (const GLchan *) img->Data; 63 64 if (!data) { 65 printf("No texture data\n"); 66 return; 67 } 68 69 switch (img->Format) { 70 case GL_ALPHA: 71 case GL_LUMINANCE: 72 case GL_INTENSITY: 73 case GL_COLOR_INDEX: 74 c = 1; 75 break; 76 case GL_LUMINANCE_ALPHA: 77 c = 2; 78 break; 79 case GL_RGB: 80 c = 3; 81 break; 82 case GL_RGBA: 83 c = 4; 84 break; 85 default: 86 _mesa_problem(NULL, "error in PrintTexture\n"); 87 return; 88 } 89 90 for (i = 0; i < img->Height; i++) { 91 for (j = 0; j < img->Width; j++) { 92 if (c==1) 93 printf("%02x ", data[0]); 94 else if (c==2) 95 printf("%02x%02x ", data[0], data[1]); 96 else if (c==3) 97 printf("%02x%02x%02x ", data[0], data[1], data[2]); 98 else if (c==4) 99 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 100 data += c; 101 } 102 printf("\n"); 103 } 104} 105#endif 106 107 108 109/* 110 * Compute log base 2 of n. 111 * If n isn't an exact power of two return -1. 112 * If n < 0 return -1. 113 */ 114static int 115logbase2( int n ) 116{ 117 GLint i = 1; 118 GLint log2 = 0; 119 120 if (n < 0) { 121 return -1; 122 } 123 124 while ( n > i ) { 125 i *= 2; 126 log2++; 127 } 128 if (i != n) { 129 return -1; 130 } 131 else { 132 return log2; 133 } 134} 135 136 137 138/* 139 * Given an internal texture format enum or 1, 2, 3, 4 return the 140 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 141 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. 142 * Return -1 if invalid enum. 143 */ 144GLint 145_mesa_base_tex_format( GLcontext *ctx, GLint format ) 146{ 147 /* 148 * Ask the driver for the base format, if it doesn't 149 * know, it will return -1; 150 */ 151 if (ctx->Driver.BaseCompressedTexFormat) { 152 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format); 153 if (ifmt >= 0) { 154 return ifmt; 155 } 156 } 157 switch (format) { 158 case GL_ALPHA: 159 case GL_ALPHA4: 160 case GL_ALPHA8: 161 case GL_ALPHA12: 162 case GL_ALPHA16: 163 return GL_ALPHA; 164 case 1: 165 case GL_LUMINANCE: 166 case GL_LUMINANCE4: 167 case GL_LUMINANCE8: 168 case GL_LUMINANCE12: 169 case GL_LUMINANCE16: 170 return GL_LUMINANCE; 171 case 2: 172 case GL_LUMINANCE_ALPHA: 173 case GL_LUMINANCE4_ALPHA4: 174 case GL_LUMINANCE6_ALPHA2: 175 case GL_LUMINANCE8_ALPHA8: 176 case GL_LUMINANCE12_ALPHA4: 177 case GL_LUMINANCE12_ALPHA12: 178 case GL_LUMINANCE16_ALPHA16: 179 return GL_LUMINANCE_ALPHA; 180 case GL_INTENSITY: 181 case GL_INTENSITY4: 182 case GL_INTENSITY8: 183 case GL_INTENSITY12: 184 case GL_INTENSITY16: 185 return GL_INTENSITY; 186 case 3: 187 case GL_RGB: 188 case GL_R3_G3_B2: 189 case GL_RGB4: 190 case GL_RGB5: 191 case GL_RGB8: 192 case GL_RGB10: 193 case GL_RGB12: 194 case GL_RGB16: 195 return GL_RGB; 196 case 4: 197 case GL_RGBA: 198 case GL_RGBA2: 199 case GL_RGBA4: 200 case GL_RGB5_A1: 201 case GL_RGBA8: 202 case GL_RGB10_A2: 203 case GL_RGBA12: 204 case GL_RGBA16: 205 return GL_RGBA; 206 case GL_COLOR_INDEX: 207 case GL_COLOR_INDEX1_EXT: 208 case GL_COLOR_INDEX2_EXT: 209 case GL_COLOR_INDEX4_EXT: 210 case GL_COLOR_INDEX8_EXT: 211 case GL_COLOR_INDEX12_EXT: 212 case GL_COLOR_INDEX16_EXT: 213 return GL_COLOR_INDEX; 214 case GL_DEPTH_COMPONENT: 215 case GL_DEPTH_COMPONENT16_SGIX: 216 case GL_DEPTH_COMPONENT24_SGIX: 217 case GL_DEPTH_COMPONENT32_SGIX: 218 if (ctx->Extensions.SGIX_depth_texture) 219 return GL_DEPTH_COMPONENT; 220 else 221 return -1; 222 default: 223 return -1; /* error */ 224 } 225} 226 227 228/* 229 * Test if the given image format is a color/rgba format. That is, 230 * not color index, depth, stencil, etc. 231 */ 232static GLboolean 233is_color_format(GLenum format) 234{ 235 switch (format) { 236 case GL_ALPHA: 237 case GL_ALPHA4: 238 case GL_ALPHA8: 239 case GL_ALPHA12: 240 case GL_ALPHA16: 241 case 1: 242 case GL_LUMINANCE: 243 case GL_LUMINANCE4: 244 case GL_LUMINANCE8: 245 case GL_LUMINANCE12: 246 case GL_LUMINANCE16: 247 case 2: 248 case GL_LUMINANCE_ALPHA: 249 case GL_LUMINANCE4_ALPHA4: 250 case GL_LUMINANCE6_ALPHA2: 251 case GL_LUMINANCE8_ALPHA8: 252 case GL_LUMINANCE12_ALPHA4: 253 case GL_LUMINANCE12_ALPHA12: 254 case GL_LUMINANCE16_ALPHA16: 255 case GL_INTENSITY: 256 case GL_INTENSITY4: 257 case GL_INTENSITY8: 258 case GL_INTENSITY12: 259 case GL_INTENSITY16: 260 case 3: 261 case GL_RGB: 262 case GL_R3_G3_B2: 263 case GL_RGB4: 264 case GL_RGB5: 265 case GL_RGB8: 266 case GL_RGB10: 267 case GL_RGB12: 268 case GL_RGB16: 269 case 4: 270 case GL_RGBA: 271 case GL_RGBA2: 272 case GL_RGBA4: 273 case GL_RGB5_A1: 274 case GL_RGBA8: 275 case GL_RGB10_A2: 276 case GL_RGBA12: 277 case GL_RGBA16: 278 return GL_TRUE; 279 default: 280 return GL_FALSE; 281 } 282} 283 284 285static GLboolean 286is_index_format(GLenum format) 287{ 288 switch (format) { 289 case GL_COLOR_INDEX: 290 case GL_COLOR_INDEX1_EXT: 291 case GL_COLOR_INDEX2_EXT: 292 case GL_COLOR_INDEX4_EXT: 293 case GL_COLOR_INDEX8_EXT: 294 case GL_COLOR_INDEX12_EXT: 295 case GL_COLOR_INDEX16_EXT: 296 return GL_TRUE; 297 default: 298 return GL_FALSE; 299 } 300} 301 302 303/* 304 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE 305 * otherwise. 306 */ 307static GLboolean 308is_compressed_format(GLcontext *ctx, GLenum internalFormat) 309{ 310 if (ctx->Driver.BaseCompressedTexFormat) { 311 GLint b = (*ctx->Driver.BaseCompressedTexFormat)(ctx, internalFormat); 312 if (b > 0) 313 return GL_TRUE; 314 else 315 return GL_FALSE; 316 } 317 return GL_FALSE; 318} 319 320 321 322/* 323 * Store a gl_texture_image pointer in a gl_texture_object structure 324 * according to the target and level parameters. 325 * This was basically prompted by the introduction of cube maps. 326 */ 327void 328_mesa_set_tex_image(struct gl_texture_object *tObj, 329 GLenum target, GLint level, 330 struct gl_texture_image *texImage) 331{ 332 ASSERT(tObj); 333 ASSERT(texImage); 334 switch (target) { 335 case GL_TEXTURE_1D: 336 case GL_TEXTURE_2D: 337 case GL_TEXTURE_3D: 338 tObj->Image[level] = texImage; 339 return; 340 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 341 tObj->Image[level] = texImage; 342 return; 343 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 344 tObj->NegX[level] = texImage; 345 return; 346 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 347 tObj->PosY[level] = texImage; 348 return; 349 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 350 tObj->NegY[level] = texImage; 351 return; 352 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 353 tObj->PosZ[level] = texImage; 354 return; 355 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 356 tObj->NegZ[level] = texImage; 357 return; 358 default: 359 _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); 360 return; 361 } 362} 363 364 365 366/* 367 * Return new gl_texture_image struct with all fields initialized to zero. 368 */ 369struct gl_texture_image * 370_mesa_alloc_texture_image( void ) 371{ 372 return CALLOC_STRUCT(gl_texture_image); 373} 374 375 376 377void 378_mesa_free_texture_image( struct gl_texture_image *teximage ) 379{ 380 if (teximage->Data) { 381 FREE( teximage->Data ); 382 teximage->Data = NULL; 383 } 384 FREE( teximage ); 385} 386 387 388/* 389 * Return GL_TRUE if the target is a proxy target. 390 */ 391static GLboolean 392is_proxy_target(GLenum target) 393{ 394 return (target == GL_PROXY_TEXTURE_1D || 395 target == GL_PROXY_TEXTURE_2D || 396 target == GL_PROXY_TEXTURE_3D || 397 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB); 398} 399 400 401/* 402 * Given a texture unit and a texture target, return the corresponding 403 * texture object. 404 */ 405struct gl_texture_object * 406_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 407 GLenum target) 408{ 409 switch (target) { 410 case GL_TEXTURE_1D: 411 return texUnit->Current1D; 412 case GL_PROXY_TEXTURE_1D: 413 return ctx->Texture.Proxy1D; 414 case GL_TEXTURE_2D: 415 return texUnit->Current2D; 416 case GL_PROXY_TEXTURE_2D: 417 return ctx->Texture.Proxy2D; 418 case GL_TEXTURE_3D: 419 return texUnit->Current3D; 420 case GL_PROXY_TEXTURE_3D: 421 return ctx->Texture.Proxy3D; 422 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 423 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 424 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 425 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 426 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 427 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 428 case GL_TEXTURE_CUBE_MAP_ARB: 429 return ctx->Extensions.ARB_texture_cube_map 430 ? texUnit->CurrentCubeMap : NULL; 431 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 432 return ctx->Extensions.ARB_texture_cube_map 433 ? ctx->Texture.ProxyCubeMap : NULL; 434 default: 435 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 436 return NULL; 437 } 438} 439 440 441/* 442 * Return the texture image struct which corresponds to target and level 443 * for the given texture unit. 444 */ 445struct gl_texture_image * 446_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit, 447 GLenum target, GLint level) 448{ 449 ASSERT(texUnit); 450 ASSERT(level < MAX_TEXTURE_LEVELS); 451 switch (target) { 452 case GL_TEXTURE_1D: 453 return texUnit->Current1D->Image[level]; 454 case GL_PROXY_TEXTURE_1D: 455 return ctx->Texture.Proxy1D->Image[level]; 456 case GL_TEXTURE_2D: 457 return texUnit->Current2D->Image[level]; 458 case GL_PROXY_TEXTURE_2D: 459 return ctx->Texture.Proxy2D->Image[level]; 460 case GL_TEXTURE_3D: 461 return texUnit->Current3D->Image[level]; 462 case GL_PROXY_TEXTURE_3D: 463 return ctx->Texture.Proxy3D->Image[level]; 464 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 465 if (ctx->Extensions.ARB_texture_cube_map) 466 return texUnit->CurrentCubeMap->Image[level]; 467 else 468 return NULL; 469 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 470 if (ctx->Extensions.ARB_texture_cube_map) 471 return texUnit->CurrentCubeMap->NegX[level]; 472 else 473 return NULL; 474 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 475 if (ctx->Extensions.ARB_texture_cube_map) 476 return texUnit->CurrentCubeMap->PosY[level]; 477 else 478 return NULL; 479 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 480 if (ctx->Extensions.ARB_texture_cube_map) 481 return texUnit->CurrentCubeMap->NegY[level]; 482 else 483 return NULL; 484 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 485 if (ctx->Extensions.ARB_texture_cube_map) 486 return texUnit->CurrentCubeMap->PosZ[level]; 487 else 488 return NULL; 489 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 490 if (ctx->Extensions.ARB_texture_cube_map) 491 return texUnit->CurrentCubeMap->NegZ[level]; 492 else 493 return NULL; 494 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 495 if (ctx->Extensions.ARB_texture_cube_map) 496 return ctx->Texture.ProxyCubeMap->Image[level]; 497 else 498 return NULL; 499 default: 500 _mesa_problem(ctx, "bad target in _mesa_select_tex_image()"); 501 return NULL; 502 } 503} 504 505 506 507/* 508 * glTexImage[123]D can accept a NULL image pointer. In this case we 509 * create a texture image with unspecified image contents per the OpenGL 510 * spec. 511 */ 512static GLubyte * 513make_null_texture(GLint width, GLint height, GLint depth, GLenum format) 514{ 515 const GLint components = _mesa_components_in_format(format); 516 const GLint numPixels = width * height * depth; 517 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 518 519 /* 520 * Let's see if anyone finds this. If glTexImage2D() is called with 521 * a NULL image pointer then load the texture image with something 522 * interesting instead of leaving it indeterminate. 523 */ 524 if (data) { 525 static const char message[8][32] = { 526 " X X XXXXX XXX X ", 527 " XX XX X X X X X ", 528 " X X X X X X X ", 529 " X X XXXX XXX XXXXX ", 530 " X X X X X X ", 531 " X X X X X X X ", 532 " X X XXXXX XXX X X ", 533 " " 534 }; 535 536 GLubyte *imgPtr = data; 537 GLint h, i, j, k; 538 for (h = 0; h < depth; h++) { 539 for (i = 0; i < height; i++) { 540 GLint srcRow = 7 - (i % 8); 541 for (j = 0; j < width; j++) { 542 GLint srcCol = j % 32; 543 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 544 for (k = 0; k < components; k++) { 545 *imgPtr++ = texel; 546 } 547 } 548 } 549 } 550 } 551 552 return data; 553} 554 555 556 557/* 558 * Reset the fields of a gl_texture_image struct to zero. 559 * This is called when a proxy texture test fails, we set all the 560 * image members (except DriverData) to zero. 561 * It's also used in glTexImage[123]D as a safeguard to be sure all 562 * required fields get initialized properly by the Driver.TexImage[123]D 563 * functions. 564 */ 565static void 566clear_teximage_fields(struct gl_texture_image *img) 567{ 568 ASSERT(img); 569 img->Format = 0; 570 img->IntFormat = 0; 571 img->Border = 0; 572 img->Width = 0; 573 img->Height = 0; 574 img->Depth = 0; 575 img->Width2 = 0; 576 img->Height2 = 0; 577 img->Depth2 = 0; 578 img->WidthLog2 = 0; 579 img->HeightLog2 = 0; 580 img->DepthLog2 = 0; 581 img->Data = NULL; 582 img->TexFormat = &_mesa_null_texformat; 583 img->FetchTexel = NULL; 584 img->IsCompressed = 0; 585 img->CompressedSize = 0; 586} 587 588 589/* 590 * Initialize basic fields of the gl_texture_image struct. 591 */ 592void 593_mesa_init_teximage_fields(GLcontext *ctx, 594 struct gl_texture_image *img, 595 GLsizei width, GLsizei height, GLsizei depth, 596 GLint border, GLenum internalFormat) 597{ 598 ASSERT(img); 599 img->Format = _mesa_base_tex_format( ctx, internalFormat ); 600 ASSERT(img->Format > 0); 601 img->IntFormat = internalFormat; 602 img->Border = border; 603 img->Width = width; 604 img->Height = height; 605 img->Depth = depth; 606 img->WidthLog2 = logbase2(width - 2 * border); 607 if (height == 1) /* 1-D texture */ 608 img->HeightLog2 = 0; 609 else 610 img->HeightLog2 = logbase2(height - 2 * border); 611 if (depth == 1) /* 2-D texture */ 612 img->DepthLog2 = 0; 613 else 614 img->DepthLog2 = logbase2(depth - 2 * border); 615 img->Width2 = 1 << img->WidthLog2; 616 img->Height2 = 1 << img->HeightLog2; 617 img->Depth2 = 1 << img->DepthLog2; 618 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 619 img->IsCompressed = is_compressed_format(ctx, internalFormat); 620} 621 622 623 624/* 625 * Test glTexImage[123]D() parameters for errors. 626 * Input: 627 * dimensions - must be 1 or 2 or 3 628 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 629 */ 630static GLboolean 631texture_error_check( GLcontext *ctx, GLenum target, 632 GLint level, GLint internalFormat, 633 GLenum format, GLenum type, 634 GLuint dimensions, 635 GLint width, GLint height, 636 GLint depth, GLint border ) 637{ 638 GLboolean isProxy; 639 GLint iformat; 640 GLint maxLevels = 0, maxTextureSize; 641 642 if (dimensions == 1) { 643 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D); 644 if (target != GL_TEXTURE_1D && !isProxy) { 645 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 646 return GL_TRUE; 647 } 648 maxLevels = ctx->Const.MaxTextureLevels; 649 } 650 else if (dimensions == 2) { 651 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D || 652 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB); 653 if (target != GL_TEXTURE_2D && !isProxy && 654 !(ctx->Extensions.ARB_texture_cube_map && 655 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 656 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 657 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 658 return GL_TRUE; 659 } 660 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) 661 maxLevels = ctx->Const.MaxTextureLevels; 662 else 663 maxLevels = ctx->Const.MaxCubeTextureLevels; 664 } 665 else if (dimensions == 3) { 666 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D); 667 if (target != GL_TEXTURE_3D && !isProxy) { 668 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 669 return GL_TRUE; 670 } 671 maxLevels = ctx->Const.Max3DTextureLevels; 672 } 673 else { 674 _mesa_problem( ctx, "bad dims in texture_error_check" ); 675 return GL_TRUE; 676 } 677 678 ASSERT(maxLevels > 0); 679 maxTextureSize = 1 << (maxLevels - 1); 680 681 /* Border */ 682 if (border != 0 && border != 1) { 683 if (!isProxy) { 684 char message[100]; 685 sprintf(message, "glTexImage%dD(border=%d)", dimensions, border); 686 _mesa_error(ctx, GL_INVALID_VALUE, message); 687 } 688 return GL_TRUE; 689 } 690 691 /* Width */ 692 if (width < 2 * border || width > 2 + maxTextureSize 693 || logbase2( width - 2 * border ) < 0) { 694 if (!isProxy) { 695 char message[100]; 696 sprintf(message, "glTexImage%dD(width=%d)", dimensions, width); 697 _mesa_error(ctx, GL_INVALID_VALUE, message); 698 } 699 return GL_TRUE; 700 } 701 702 /* Height */ 703 if (dimensions >= 2) { 704 if (height < 2 * border || height > 2 + maxTextureSize 705 || logbase2( height - 2 * border ) < 0) { 706 if (!isProxy) { 707 char message[100]; 708 sprintf(message, "glTexImage%dD(height=%d)", dimensions, height); 709 _mesa_error(ctx, GL_INVALID_VALUE, message); 710 } 711 return GL_TRUE; 712 } 713 } 714 715 /* For cube map, width must equal height */ 716 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 717 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 718 if (width != height) { 719 if (!isProxy) { 720 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); 721 } 722 return GL_TRUE; 723 } 724 } 725 726 /* Depth */ 727 if (dimensions >= 3) { 728 if (depth < 2 * border || depth > 2 + maxTextureSize 729 || logbase2( depth - 2 * border ) < 0) { 730 if (!isProxy) { 731 char message[100]; 732 sprintf(message, "glTexImage3D(depth=%d)", depth ); 733 _mesa_error( ctx, GL_INVALID_VALUE, message ); 734 } 735 return GL_TRUE; 736 } 737 } 738 739 /* Level */ 740 if (level < 0 || level >= maxLevels) { 741 if (!isProxy) { 742 char message[100]; 743 sprintf(message, "glTexImage%dD(level=%d)", dimensions, level); 744 _mesa_error(ctx, GL_INVALID_VALUE, message); 745 } 746 return GL_TRUE; 747 } 748 749 /* For cube map, width must equal height */ 750 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 751 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 752 if (width != height) { 753 _mesa_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)"); 754 return GL_TRUE; 755 } 756 } 757 758 iformat = _mesa_base_tex_format( ctx, internalFormat ); 759 if (iformat < 0) { 760 if (!isProxy) { 761 char message[100]; 762 sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions, 763 internalFormat); 764 _mesa_error(ctx, GL_INVALID_VALUE, message); 765 } 766 return GL_TRUE; 767 } 768 769 ASSERT(iformat > 0); 770 771 if (!is_compressed_format( ctx, internalFormat ) && 772 !_mesa_is_legal_format_and_type( format, type )) { 773 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 774 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 775 */ 776 if (!isProxy) { 777 char message[100]; 778 sprintf(message, "glTexImage%dD(format or type)", dimensions); 779 _mesa_error(ctx, GL_INVALID_OPERATION, message); 780 } 781 return GL_TRUE; 782 } 783 784 /* if we get here, the parameters are OK */ 785 return GL_FALSE; 786} 787 788 789 790/* 791 * Test glTexSubImage[123]D() parameters for errors. 792 * Input: 793 * dimensions - must be 1 or 2 or 3 794 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 795 */ 796static GLboolean 797subtexture_error_check( GLcontext *ctx, GLuint dimensions, 798 GLenum target, GLint level, 799 GLint xoffset, GLint yoffset, GLint zoffset, 800 GLint width, GLint height, GLint depth, 801 GLenum format, GLenum type ) 802{ 803 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 804 struct gl_texture_image *destTex; 805 GLint maxLevels = 0; 806 GLboolean compressed; 807 808 if (dimensions == 1) { 809 if (target != GL_TEXTURE_1D) { 810 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 811 return GL_TRUE; 812 } 813 maxLevels = ctx->Const.MaxTextureLevels; 814 } 815 else if (dimensions == 2) { 816 if (ctx->Extensions.ARB_texture_cube_map) { 817 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 818 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 819 target != GL_TEXTURE_2D) { 820 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 821 return GL_TRUE; 822 } 823 } 824 else if (target != GL_TEXTURE_2D) { 825 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 826 return GL_TRUE; 827 } 828 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) 829 maxLevels = ctx->Const.MaxTextureLevels; 830 else 831 maxLevels = ctx->Const.MaxCubeTextureLevels; 832 } 833 else if (dimensions == 3) { 834 if (target != GL_TEXTURE_3D) { 835 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 836 return GL_TRUE; 837 } 838 maxLevels = ctx->Const.Max3DTextureLevels; 839 } 840 else { 841 _mesa_problem( ctx, "bad dims in texture_error_check" ); 842 return GL_TRUE; 843 } 844 845 ASSERT(maxLevels > 0); 846 847 if (level < 0 || level >= maxLevels) { 848 char message[100]; 849 sprintf(message, "glTexSubImage2D(level=%d)", level); 850 _mesa_error(ctx, GL_INVALID_ENUM, message); 851 return GL_TRUE; 852 } 853 854 if (width < 0) { 855 char message[100]; 856 sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width); 857 _mesa_error(ctx, GL_INVALID_VALUE, message); 858 return GL_TRUE; 859 } 860 if (height < 0 && dimensions > 1) { 861 char message[100]; 862 sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height); 863 _mesa_error(ctx, GL_INVALID_VALUE, message); 864 return GL_TRUE; 865 } 866 if (depth < 0 && dimensions > 2) { 867 char message[100]; 868 sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth); 869 _mesa_error(ctx, GL_INVALID_VALUE, message); 870 return GL_TRUE; 871 } 872 873 destTex = _mesa_select_tex_image(ctx, texUnit, target, level); 874 875 if (!destTex) { 876 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); 877 return GL_TRUE; 878 } 879 880 if (xoffset < -((GLint)destTex->Border)) { 881 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); 882 return GL_TRUE; 883 } 884 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 885 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); 886 return GL_TRUE; 887 } 888 if (dimensions > 1) { 889 if (yoffset < -((GLint)destTex->Border)) { 890 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); 891 return GL_TRUE; 892 } 893 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 894 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); 895 return GL_TRUE; 896 } 897 } 898 if (dimensions > 2) { 899 if (zoffset < -((GLint)destTex->Border)) { 900 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 901 return GL_TRUE; 902 } 903 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 904 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 905 return GL_TRUE; 906 } 907 } 908 909 compressed = is_compressed_format(ctx, destTex->IntFormat); 910 911 if (!compressed && !_mesa_is_legal_format_and_type(format, type)) { 912 char message[100]; 913 sprintf(message, "glTexSubImage%dD(format or type)", dimensions); 914 _mesa_error(ctx, GL_INVALID_ENUM, message); 915 return GL_TRUE; 916 } 917 918 if (compressed) { 919 if (xoffset != -destTex->Border) { 920 _mesa_error(ctx, GL_INVALID_OPERATION, 921 "glTexSubImage1/2/3D(xoffset != -border"); 922 return GL_TRUE; 923 } 924 if (dimensions > 1 && yoffset != -destTex->Border) { 925 _mesa_error(ctx, GL_INVALID_OPERATION, 926 "glTexSubImage2/3D(yoffset != -border"); 927 return GL_TRUE; 928 } 929 if (dimensions > 2 && zoffset != -destTex->Border) { 930 _mesa_error(ctx, GL_INVALID_OPERATION, 931 "glTexSubImage3D(zoffset != -border"); 932 return GL_TRUE; 933 } 934 } 935 936 return GL_FALSE; 937} 938 939 940/* 941 * Test glCopyTexImage[12]D() parameters for errors. 942 * Input: dimensions - must be 1 or 2 or 3 943 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 944 */ 945static GLboolean 946copytexture_error_check( GLcontext *ctx, GLuint dimensions, 947 GLenum target, GLint level, GLint internalFormat, 948 GLint width, GLint height, GLint border ) 949{ 950 GLint iformat; 951 GLint maxLevels = 0, maxTextureSize; 952 953 if (dimensions == 1) { 954 if (target != GL_TEXTURE_1D) { 955 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 956 return GL_TRUE; 957 } 958 maxLevels = ctx->Const.MaxTextureLevels; 959 } 960 else if (dimensions == 2) { 961 if (ctx->Extensions.ARB_texture_cube_map) { 962 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 963 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 964 target != GL_TEXTURE_2D) { 965 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 966 return GL_TRUE; 967 } 968 } 969 else if (target != GL_TEXTURE_2D) { 970 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 971 return GL_TRUE; 972 } 973 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) 974 maxLevels = ctx->Const.MaxTextureLevels; 975 else 976 maxLevels = ctx->Const.MaxCubeTextureLevels; 977 } 978 979 ASSERT(maxLevels > 0); 980 maxTextureSize = 1 << (maxLevels - 1); 981 982 /* Border */ 983 if (border != 0 && border != 1) { 984 char message[100]; 985 sprintf(message, "glCopyTexImage%dD(border)", dimensions); 986 _mesa_error(ctx, GL_INVALID_VALUE, message); 987 return GL_TRUE; 988 } 989 990 /* Width */ 991 if (width < 2 * border || width > 2 + maxTextureSize 992 || logbase2( width - 2 * border ) < 0) { 993 char message[100]; 994 sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width); 995 _mesa_error(ctx, GL_INVALID_VALUE, message); 996 return GL_TRUE; 997 } 998 999 /* Height */ 1000 if (dimensions >= 2) { 1001 if (height < 2 * border || height > 2 + maxTextureSize 1002 || logbase2( height - 2 * border ) < 0) { 1003 char message[100]; 1004 sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height); 1005 _mesa_error(ctx, GL_INVALID_VALUE, message); 1006 return GL_TRUE; 1007 } 1008 } 1009 1010 /* For cube map, width must equal height */ 1011 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1012 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1013 if (width != height) { 1014 _mesa_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)"); 1015 return GL_TRUE; 1016 } 1017 } 1018 1019 /* Level */ 1020 if (level < 0 || level >= maxLevels) { 1021 char message[100]; 1022 sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level); 1023 _mesa_error(ctx, GL_INVALID_VALUE, message); 1024 return GL_TRUE; 1025 } 1026 1027 iformat = _mesa_base_tex_format(ctx, internalFormat); 1028 if (iformat < 0) { 1029 char message[100]; 1030 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); 1031 _mesa_error(ctx, GL_INVALID_VALUE, message); 1032 return GL_TRUE; 1033 } 1034 1035 /* if we get here, the parameters are OK */ 1036 return GL_FALSE; 1037} 1038 1039 1040static GLboolean 1041copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, 1042 GLenum target, GLint level, 1043 GLint xoffset, GLint yoffset, GLint zoffset, 1044 GLsizei width, GLsizei height ) 1045{ 1046 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1047 struct gl_texture_image *teximage; 1048 GLint maxLevels = 0; 1049 GLboolean compressed; 1050 1051 if (dimensions == 1) { 1052 if (target != GL_TEXTURE_1D) { 1053 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 1054 return GL_TRUE; 1055 } 1056 maxLevels = ctx->Const.MaxTextureLevels; 1057 } 1058 else if (dimensions == 2) { 1059 if (ctx->Extensions.ARB_texture_cube_map) { 1060 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || 1061 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) && 1062 target != GL_TEXTURE_2D) { 1063 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1064 return GL_TRUE; 1065 } 1066 } 1067 else if (target != GL_TEXTURE_2D) { 1068 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1069 return GL_TRUE; 1070 } 1071 if (target == GL_PROXY_TEXTURE_2D && target == GL_TEXTURE_2D) 1072 maxLevels = ctx->Const.MaxTextureLevels; 1073 else 1074 maxLevels = ctx->Const.MaxCubeTextureLevels; 1075 } 1076 else if (dimensions == 3) { 1077 if (target != GL_TEXTURE_3D) { 1078 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 1079 return GL_TRUE; 1080 } 1081 maxLevels = ctx->Const.Max3DTextureLevels; 1082 } 1083 1084 ASSERT(maxLevels > 0); 1085 1086 if (level < 0 || level >= maxLevels) { 1087 char message[100]; 1088 sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level); 1089 _mesa_error(ctx, GL_INVALID_VALUE, message); 1090 return GL_TRUE; 1091 } 1092 1093 if (width < 0) { 1094 char message[100]; 1095 sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width); 1096 _mesa_error(ctx, GL_INVALID_VALUE, message); 1097 return GL_TRUE; 1098 } 1099 if (dimensions > 1 && height < 0) { 1100 char message[100]; 1101 sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height); 1102 _mesa_error(ctx, GL_INVALID_VALUE, message); 1103 return GL_TRUE; 1104 } 1105 1106 teximage = _mesa_select_tex_image(ctx, texUnit, target, level); 1107 if (!teximage) { 1108 char message[100]; 1109 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions); 1110 _mesa_error(ctx, GL_INVALID_OPERATION, message); 1111 return GL_TRUE; 1112 } 1113 1114 if (xoffset < -((GLint)teximage->Border)) { 1115 char message[100]; 1116 sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 1117 _mesa_error(ctx, GL_INVALID_VALUE, message); 1118 return GL_TRUE; 1119 } 1120 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 1121 char message[100]; 1122 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions); 1123 _mesa_error(ctx, GL_INVALID_VALUE, message); 1124 return GL_TRUE; 1125 } 1126 if (dimensions > 1) { 1127 if (yoffset < -((GLint)teximage->Border)) { 1128 char message[100]; 1129 sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 1130 _mesa_error(ctx, GL_INVALID_VALUE, message); 1131 return GL_TRUE; 1132 } 1133 /* NOTE: we're adding the border here, not subtracting! */ 1134 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 1135 char message[100]; 1136 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions); 1137 _mesa_error(ctx, GL_INVALID_VALUE, message); 1138 return GL_TRUE; 1139 } 1140 } 1141 1142 if (dimensions > 2) { 1143 if (zoffset < -((GLint)teximage->Border)) { 1144 char message[100]; 1145 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions); 1146 _mesa_error(ctx, GL_INVALID_VALUE, message); 1147 return GL_TRUE; 1148 } 1149 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 1150 char message[100]; 1151 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 1152 _mesa_error(ctx, GL_INVALID_VALUE, message); 1153 return GL_TRUE; 1154 } 1155 } 1156 1157 compressed = is_compressed_format(ctx, teximage->IntFormat); 1158 if (compressed) { 1159 if (xoffset != -teximage->Border) { 1160 _mesa_error(ctx, GL_INVALID_OPERATION, 1161 "glCopyTexSubImage1/2/3D(xoffset != -border"); 1162 return GL_TRUE; 1163 } 1164 if (dimensions > 1 && yoffset != -teximage->Border) { 1165 _mesa_error(ctx, GL_INVALID_OPERATION, 1166 "glCopyTexSubImage2/3D(yoffset != -border"); 1167 return GL_TRUE; 1168 } 1169 if (dimensions > 2 && zoffset != -teximage->Border) { 1170 _mesa_error(ctx, GL_INVALID_OPERATION, 1171 "glCopyTexSubImage3D(zoffset != -border"); 1172 return GL_TRUE; 1173 } 1174 } 1175 1176 /* if we get here, the parameters are OK */ 1177 return GL_FALSE; 1178} 1179 1180 1181 1182void 1183_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 1184 GLenum type, GLvoid *pixels ) 1185{ 1186 const struct gl_texture_unit *texUnit; 1187 const struct gl_texture_object *texObj; 1188 struct gl_texture_image *texImage; 1189 GLint maxLevels = 0; 1190 GET_CURRENT_CONTEXT(ctx); 1191 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1192 1193 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 1194 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1195 if (!texObj || is_proxy_target(target)) { 1196 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 1197 return; 1198 } 1199 1200 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) { 1201 maxLevels = ctx->Const.MaxTextureLevels; 1202 } 1203 else if (target == GL_TEXTURE_3D) { 1204 maxLevels = ctx->Const.Max3DTextureLevels; 1205 } 1206 else { 1207 maxLevels = ctx->Const.MaxCubeTextureLevels; 1208 } 1209 1210 ASSERT(maxLevels > 0); 1211 1212 if (level < 0 || level >= maxLevels) { 1213 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 1214 return; 1215 } 1216 1217 if (_mesa_sizeof_type(type) <= 0) { 1218 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 1219 return; 1220 } 1221 1222 if (_mesa_components_in_format(format) <= 0 || 1223 format == GL_STENCIL_INDEX) { 1224 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 1225 return; 1226 } 1227 1228 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 1229 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 1230 } 1231 1232 if (!ctx->Extensions.SGIX_depth_texture && format == GL_DEPTH_COMPONENT) { 1233 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 1234 } 1235 1236 /* XXX what if format/type doesn't match texture format/type? */ 1237 1238 if (!pixels) 1239 return; 1240 1241 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1242 if (!texImage) { 1243 /* invalid mipmap level, not an error */ 1244 return; 1245 } 1246 1247 if (!texImage->Data) { 1248 /* no image data, not an error */ 1249 return; 1250 } 1251 1252 { 1253 const GLint width = texImage->Width; 1254 const GLint height = texImage->Height; 1255 const GLint depth = texImage->Depth; 1256 GLint img, row; 1257 for (img = 0; img < depth; img++) { 1258 for (row = 0; row < height; row++) { 1259 /* compute destination address in client memory */ 1260 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels, 1261 width, height, format, type, 1262 img, row, 0); 1263 assert(dest); 1264 1265 if (format == GL_COLOR_INDEX) { 1266 GLuint indexRow[MAX_WIDTH]; 1267 GLint col; 1268 for (col = 0; col < width; col++) { 1269 (*texImage->FetchTexel)(texImage, col, row, img, 1270 (GLvoid *) &indexRow[col]); 1271 } 1272 _mesa_pack_index_span(ctx, width, type, dest, 1273 indexRow, &ctx->Pack, 1274 0 /* no image transfer */); 1275 } 1276 else if (format == GL_DEPTH_COMPONENT) { 1277 GLfloat depthRow[MAX_WIDTH]; 1278 GLint col; 1279 for (col = 0; col < width; col++) { 1280 (*texImage->FetchTexel)(texImage, col, row, img, 1281 (GLvoid *) &depthRow[col]); 1282 } 1283 _mesa_pack_depth_span(ctx, width, dest, type, 1284 depthRow, &ctx->Pack); 1285 } 1286 else { 1287 /* general case: convert row to RGBA format */ 1288 GLchan rgba[MAX_WIDTH][4]; 1289 GLint col; 1290 for (col = 0; col < width; col++) { 1291 (*texImage->FetchTexel)(texImage, col, row, img, 1292 (GLvoid *) rgba[col]); 1293 } 1294 _mesa_pack_rgba_span(ctx, width, (const GLchan (*)[4])rgba, 1295 format, type, dest, &ctx->Pack, 1296 0 /* no image transfer */); 1297 } /* format */ 1298 } /* row */ 1299 } /* img */ 1300 } 1301} 1302 1303 1304 1305/* 1306 * Called from the API. Note that width includes the border. 1307 */ 1308void 1309_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 1310 GLsizei width, GLint border, GLenum format, 1311 GLenum type, const GLvoid *pixels ) 1312{ 1313 GLsizei postConvWidth = width; 1314 GET_CURRENT_CONTEXT(ctx); 1315 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1316 1317 if (is_color_format(internalFormat)) { 1318 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 1319 } 1320 1321 if (target == GL_TEXTURE_1D) { 1322 struct gl_texture_unit *texUnit; 1323 struct gl_texture_object *texObj; 1324 struct gl_texture_image *texImage; 1325 1326 if (texture_error_check(ctx, target, level, internalFormat, 1327 format, type, 1, postConvWidth, 1, 1, border)) { 1328 return; /* error was recorded */ 1329 } 1330 1331 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1332 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1333 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1334 1335 if (!texImage) { 1336 texImage = _mesa_alloc_texture_image(); 1337 texObj->Image[level] = texImage; 1338 if (!texImage) { 1339 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 1340 return; 1341 } 1342 } 1343 else if (texImage->Data) { 1344 /* free the old texture data */ 1345 FREE(texImage->Data); 1346 texImage->Data = NULL; 1347 } 1348 clear_teximage_fields(texImage); /* not really needed, but helpful */ 1349 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, 1350 border, internalFormat); 1351 1352 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1353 _mesa_update_state(ctx); 1354 1355 ASSERT(ctx->Driver.TexImage1D); 1356 if (pixels) { 1357 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 1358 width, border, format, type, pixels, 1359 &ctx->Unpack, texObj, texImage); 1360 } 1361 else { 1362 GLubyte *dummy = make_null_texture(width, 1, 1, format); 1363 if (dummy) { 1364 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 1365 width, border, 1366 format, GL_UNSIGNED_BYTE, dummy, 1367 &_mesa_native_packing, texObj, texImage); 1368 FREE(dummy); 1369 } 1370 } 1371 1372 ASSERT(texImage->TexFormat); 1373 if (!texImage->FetchTexel) { 1374 /* If driver didn't explicitly set this, use the default */ 1375 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D; 1376 } 1377 ASSERT(texImage->FetchTexel); 1378 1379 if (texImage->IsCompressed) { 1380 ASSERT(texImage->CompressedSize > 0); 1381 } 1382 1383 /* state update */ 1384 texObj->Complete = GL_FALSE; 1385 ctx->NewState |= _NEW_TEXTURE; 1386 } 1387 else if (target == GL_PROXY_TEXTURE_1D) { 1388 /* Proxy texture: check for errors and update proxy state */ 1389 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1390 format, type, 1, 1391 postConvWidth, 1, 1, border); 1392 if (!error) { 1393 struct gl_texture_unit *texUnit; 1394 struct gl_texture_image *texImage; 1395 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1396 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1397 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, 1398 border, internalFormat); 1399 ASSERT(ctx->Driver.TestProxyTexImage); 1400 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1401 internalFormat, format, type, 1402 postConvWidth, 1, 1, border); 1403 } 1404 if (error) { 1405 /* if error, clear all proxy texture image parameters */ 1406 if (level >= 0 && level < ctx->Const.MaxTextureLevels) { 1407 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); 1408 } 1409 } 1410 } 1411 else { 1412 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1413 return; 1414 } 1415} 1416 1417 1418void 1419_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 1420 GLsizei width, GLsizei height, GLint border, 1421 GLenum format, GLenum type, 1422 const GLvoid *pixels ) 1423{ 1424 GLsizei postConvWidth = width, postConvHeight = height; 1425 GET_CURRENT_CONTEXT(ctx); 1426 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1427 1428 if (is_color_format(internalFormat)) { 1429 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 1430 &postConvHeight); 1431 } 1432 1433 if (target == GL_TEXTURE_2D || 1434 (ctx->Extensions.ARB_texture_cube_map && 1435 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1436 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1437 /* non-proxy target */ 1438 struct gl_texture_unit *texUnit; 1439 struct gl_texture_object *texObj; 1440 struct gl_texture_image *texImage; 1441 1442 if (texture_error_check(ctx, target, level, internalFormat, 1443 format, type, 2, postConvWidth, postConvHeight, 1444 1, border)) { 1445 return; /* error was recorded */ 1446 } 1447 1448 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1449 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1450 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1451 1452 if (!texImage) { 1453 texImage = _mesa_alloc_texture_image(); 1454 _mesa_set_tex_image(texObj, target, level, texImage); 1455 if (!texImage) { 1456 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 1457 return; 1458 } 1459 } 1460 else if (texImage->Data) { 1461 /* free the old texture data */ 1462 FREE(texImage->Data); 1463 texImage->Data = NULL; 1464 } 1465 clear_teximage_fields(texImage); /* not really needed, but helpful */ 1466 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1467 1, border, internalFormat); 1468 1469 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1470 _mesa_update_state(ctx); 1471 1472 ASSERT(ctx->Driver.TexImage2D); 1473 if (pixels) { 1474 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 1475 width, height, border, format, type, pixels, 1476 &ctx->Unpack, texObj, texImage); 1477 } 1478 else { 1479 GLubyte *dummy = make_null_texture(width, height, 1, format); 1480 if (dummy) { 1481 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 1482 width, height, border, 1483 format, GL_UNSIGNED_BYTE, dummy, 1484 &_mesa_native_packing, texObj, texImage); 1485 FREE(dummy); 1486 } 1487 } 1488 1489 ASSERT(texImage->TexFormat); 1490 if (!texImage->FetchTexel) { 1491 /* If driver didn't explicitly set this, use the default */ 1492 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D; 1493 } 1494 ASSERT(texImage->FetchTexel); 1495 1496 if (texImage->IsCompressed) { 1497 ASSERT(texImage->CompressedSize > 0); 1498 } 1499 1500 /* state update */ 1501 texObj->Complete = GL_FALSE; 1502 ctx->NewState |= _NEW_TEXTURE; 1503 } 1504 else if (target == GL_PROXY_TEXTURE_2D) { 1505 /* Proxy texture: check for errors and update proxy state */ 1506 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1507 format, type, 2, 1508 postConvWidth, postConvHeight, 1, border); 1509 if (!error) { 1510 struct gl_texture_unit *texUnit; 1511 struct gl_texture_image *texImage; 1512 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1513 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1514 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1515 postConvHeight, 1, border, internalFormat); 1516 ASSERT(ctx->Driver.TestProxyTexImage); 1517 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1518 internalFormat, format, type, 1519 postConvWidth, postConvHeight, 1, border); 1520 } 1521 if (error) { 1522 /* if error, clear all proxy texture image parameters */ 1523 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? 1524 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; 1525 if (level >= 0 && level < maxLevels) { 1526 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); 1527 } 1528 } 1529 } 1530 else { 1531 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 1532 return; 1533 } 1534} 1535 1536 1537/* 1538 * Called by the API or display list executor. 1539 * Note that width and height include the border. 1540 */ 1541void 1542_mesa_TexImage3D( GLenum target, GLint level, GLenum internalFormat, 1543 GLsizei width, GLsizei height, GLsizei depth, 1544 GLint border, GLenum format, GLenum type, 1545 const GLvoid *pixels ) 1546{ 1547 GET_CURRENT_CONTEXT(ctx); 1548 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1549 1550 if (target == GL_TEXTURE_3D) { 1551 struct gl_texture_unit *texUnit; 1552 struct gl_texture_object *texObj; 1553 struct gl_texture_image *texImage; 1554 1555 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 1556 format, type, 3, width, height, depth, border)) { 1557 return; /* error was recorded */ 1558 } 1559 1560 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1561 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1562 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1563 1564 if (!texImage) { 1565 texImage = _mesa_alloc_texture_image(); 1566 texObj->Image[level] = texImage; 1567 if (!texImage) { 1568 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 1569 return; 1570 } 1571 } 1572 else if (texImage->Data) { 1573 FREE(texImage->Data); 1574 texImage->Data = NULL; 1575 } 1576 clear_teximage_fields(texImage); /* not really needed, but helpful */ 1577 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border, 1578 internalFormat); 1579 1580 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1581 _mesa_update_state(ctx); 1582 1583 ASSERT(ctx->Driver.TexImage3D); 1584 if (pixels) { 1585 (*ctx->Driver.TexImage3D)(ctx, target, level, (GLint) internalFormat, 1586 width, height, depth, border, 1587 format, type, pixels, 1588 &ctx->Unpack, texObj, texImage); 1589 } 1590 else { 1591 GLubyte *dummy = make_null_texture(width, height, depth, format); 1592 if (dummy) { 1593 (*ctx->Driver.TexImage3D)(ctx, target, level, 1594 (GLint) internalFormat, 1595 width, height, depth, border, 1596 format, GL_UNSIGNED_BYTE, dummy, 1597 &_mesa_native_packing, texObj, texImage); 1598 FREE(dummy); 1599 } 1600 } 1601 1602 ASSERT(texImage->TexFormat); 1603 if (!texImage->FetchTexel) { 1604 /* If driver didn't explicitly set this, use the default */ 1605 texImage->FetchTexel = texImage->TexFormat->FetchTexel3D; 1606 } 1607 ASSERT(texImage->FetchTexel); 1608 1609 if (texImage->IsCompressed) { 1610 ASSERT(texImage->CompressedSize > 0); 1611 } 1612 1613 /* state update */ 1614 texObj->Complete = GL_FALSE; 1615 ctx->NewState |= _NEW_TEXTURE; 1616 } 1617 else if (target == GL_PROXY_TEXTURE_3D) { 1618 /* Proxy texture: check for errors and update proxy state */ 1619 GLenum error = texture_error_check(ctx, target, level, internalFormat, 1620 format, type, 3, width, height, depth, border); 1621 if (!error) { 1622 struct gl_texture_unit *texUnit; 1623 struct gl_texture_image *texImage; 1624 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1625 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1626 _mesa_init_teximage_fields(ctx, texImage, width, height, 1, 1627 border, internalFormat); 1628 ASSERT(ctx->Driver.TestProxyTexImage); 1629 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 1630 internalFormat, format, type, 1631 width, height, depth, border); 1632 } 1633 if (error) { 1634 /* if error, clear all proxy texture image parameters */ 1635 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { 1636 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); 1637 } 1638 } 1639 } 1640 else { 1641 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1642 return; 1643 } 1644} 1645 1646 1647void 1648_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 1649 GLsizei width, GLsizei height, GLsizei depth, 1650 GLint border, GLenum format, GLenum type, 1651 const GLvoid *pixels ) 1652{ 1653 _mesa_TexImage3D(target, level, internalFormat, width, height, 1654 depth, border, format, type, pixels); 1655} 1656 1657 1658 1659void 1660_mesa_TexSubImage1D( GLenum target, GLint level, 1661 GLint xoffset, GLsizei width, 1662 GLenum format, GLenum type, 1663 const GLvoid *pixels ) 1664{ 1665 GLsizei postConvWidth = width; 1666 struct gl_texture_unit *texUnit; 1667 struct gl_texture_object *texObj; 1668 struct gl_texture_image *texImage; 1669 GET_CURRENT_CONTEXT(ctx); 1670 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1671 1672 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1673 _mesa_update_state(ctx); 1674 1675 /* XXX should test internal format */ 1676 if (is_color_format(format)) { 1677 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 1678 } 1679 1680 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 1681 postConvWidth, 1, 1, format, type)) { 1682 return; /* error was detected */ 1683 } 1684 1685 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1686 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1687 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1688 assert(texImage); 1689 1690 if (width == 0 || !pixels) 1691 return; /* no-op, not an error */ 1692 1693 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 1694 xoffset += texImage->Border; 1695 1696 ASSERT(ctx->Driver.TexSubImage1D); 1697 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 1698 format, type, pixels, &ctx->Unpack, 1699 texObj, texImage); 1700 ctx->NewState |= _NEW_TEXTURE; 1701} 1702 1703 1704void 1705_mesa_TexSubImage2D( GLenum target, GLint level, 1706 GLint xoffset, GLint yoffset, 1707 GLsizei width, GLsizei height, 1708 GLenum format, GLenum type, 1709 const GLvoid *pixels ) 1710{ 1711 GLsizei postConvWidth = width, postConvHeight = height; 1712 struct gl_texture_unit *texUnit; 1713 struct gl_texture_object *texObj; 1714 struct gl_texture_image *texImage; 1715 GET_CURRENT_CONTEXT(ctx); 1716 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1717 1718 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1719 _mesa_update_state(ctx); 1720 1721 /* XXX should test internal format */ 1722 if (is_color_format(format)) { 1723 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 1724 &postConvHeight); 1725 } 1726 1727 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 1728 postConvWidth, postConvHeight, 1, format, type)) { 1729 return; /* error was detected */ 1730 } 1731 1732 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1733 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1734 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1735 assert(texImage); 1736 1737 if (width == 0 || height == 0 || !pixels) 1738 return; /* no-op, not an error */ 1739 1740 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 1741 xoffset += texImage->Border; 1742 yoffset += texImage->Border; 1743 1744 ASSERT(ctx->Driver.TexSubImage2D); 1745 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 1746 width, height, format, type, pixels, 1747 &ctx->Unpack, texObj, texImage); 1748 ctx->NewState |= _NEW_TEXTURE; 1749} 1750 1751 1752 1753void 1754_mesa_TexSubImage3D( GLenum target, GLint level, 1755 GLint xoffset, GLint yoffset, GLint zoffset, 1756 GLsizei width, GLsizei height, GLsizei depth, 1757 GLenum format, GLenum type, 1758 const GLvoid *pixels ) 1759{ 1760 struct gl_texture_unit *texUnit; 1761 struct gl_texture_object *texObj; 1762 struct gl_texture_image *texImage; 1763 GET_CURRENT_CONTEXT(ctx); 1764 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1765 1766 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1767 _mesa_update_state(ctx); 1768 1769 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 1770 width, height, depth, format, type)) { 1771 return; /* error was detected */ 1772 } 1773 1774 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1775 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1776 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1777 assert(texImage); 1778 1779 if (width == 0 || height == 0 || height == 0 || !pixels) 1780 return; /* no-op, not an error */ 1781 1782 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 1783 xoffset += texImage->Border; 1784 yoffset += texImage->Border; 1785 zoffset += texImage->Border; 1786 1787 ASSERT(ctx->Driver.TexSubImage3D); 1788 (*ctx->Driver.TexSubImage3D)(ctx, target, level, 1789 xoffset, yoffset, zoffset, 1790 width, height, depth, 1791 format, type, pixels, 1792 &ctx->Unpack, texObj, texImage ); 1793 ctx->NewState |= _NEW_TEXTURE; 1794} 1795 1796 1797 1798void 1799_mesa_CopyTexImage1D( GLenum target, GLint level, 1800 GLenum internalFormat, 1801 GLint x, GLint y, 1802 GLsizei width, GLint border ) 1803{ 1804 struct gl_texture_unit *texUnit; 1805 struct gl_texture_object *texObj; 1806 struct gl_texture_image *texImage; 1807 GLsizei postConvWidth = width; 1808 GET_CURRENT_CONTEXT(ctx); 1809 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1810 1811 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1812 _mesa_update_state(ctx); 1813 1814 if (is_color_format(internalFormat)) { 1815 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 1816 } 1817 1818 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 1819 postConvWidth, 1, border)) 1820 return; 1821 1822 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1823 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1824 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1825 if (!texImage) { 1826 texImage = _mesa_alloc_texture_image(); 1827 _mesa_set_tex_image(texObj, target, level, texImage); 1828 if (!texImage) { 1829 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 1830 return; 1831 } 1832 } 1833 else if (texImage->Data) { 1834 /* free the old texture data */ 1835 FREE(texImage->Data); 1836 texImage->Data = NULL; 1837 } 1838 1839 clear_teximage_fields(texImage); /* not really needed, but helpful */ 1840 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, 1, 1, 1841 border, internalFormat); 1842 1843 1844 ASSERT(ctx->Driver.CopyTexImage1D); 1845 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 1846 x, y, width, border); 1847 1848 ASSERT(texImage->TexFormat); 1849 if (!texImage->FetchTexel) { 1850 /* If driver didn't explicitly set this, use the default */ 1851 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D; 1852 } 1853 ASSERT(texImage->FetchTexel); 1854 1855 /* state update */ 1856 texObj->Complete = GL_FALSE; 1857 ctx->NewState |= _NEW_TEXTURE; 1858} 1859 1860 1861 1862void 1863_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 1864 GLint x, GLint y, GLsizei width, GLsizei height, 1865 GLint border ) 1866{ 1867 struct gl_texture_unit *texUnit; 1868 struct gl_texture_object *texObj; 1869 struct gl_texture_image *texImage; 1870 GLsizei postConvWidth = width, postConvHeight = height; 1871 GET_CURRENT_CONTEXT(ctx); 1872 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1873 1874 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1875 _mesa_update_state(ctx); 1876 1877 if (is_color_format(internalFormat)) { 1878 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 1879 &postConvHeight); 1880 } 1881 1882 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 1883 postConvWidth, postConvHeight, border)) 1884 return; 1885 1886 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1887 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1888 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1889 if (!texImage) { 1890 texImage = _mesa_alloc_texture_image(); 1891 _mesa_set_tex_image(texObj, target, level, texImage); 1892 if (!texImage) { 1893 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 1894 return; 1895 } 1896 } 1897 else if (texImage->Data) { 1898 /* free the old texture data */ 1899 FREE(texImage->Data); 1900 texImage->Data = NULL; 1901 } 1902 1903 clear_teximage_fields(texImage); /* not really needed, but helpful */ 1904 _mesa_init_teximage_fields(ctx, texImage, postConvWidth, postConvHeight, 1, 1905 border, internalFormat); 1906 1907 ASSERT(ctx->Driver.CopyTexImage2D); 1908 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 1909 x, y, width, height, border); 1910 1911 ASSERT(texImage->TexFormat); 1912 if (!texImage->FetchTexel) { 1913 /* If driver didn't explicitly set this, use the default */ 1914 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D; 1915 } 1916 ASSERT(texImage->FetchTexel); 1917 1918 /* state update */ 1919 texObj->Complete = GL_FALSE; 1920 ctx->NewState |= _NEW_TEXTURE; 1921} 1922 1923 1924 1925void 1926_mesa_CopyTexSubImage1D( GLenum target, GLint level, 1927 GLint xoffset, GLint x, GLint y, GLsizei width ) 1928{ 1929 struct gl_texture_unit *texUnit; 1930 struct gl_texture_object *texObj; 1931 struct gl_texture_image *texImage; 1932 GLsizei postConvWidth = width; 1933 GET_CURRENT_CONTEXT(ctx); 1934 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1935 1936 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1937 _mesa_update_state(ctx); 1938 1939 /* XXX should test internal format */ 1940 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 1941 1942 if (copytexsubimage_error_check(ctx, 1, target, level, 1943 xoffset, 0, 0, postConvWidth, 1)) 1944 return; 1945 1946 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1947 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1948 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1949 1950 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 1951 xoffset += texImage->Border; 1952 1953 ASSERT(ctx->Driver.CopyTexSubImage1D); 1954 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width); 1955 ctx->NewState |= _NEW_TEXTURE; 1956} 1957 1958 1959 1960void 1961_mesa_CopyTexSubImage2D( GLenum target, GLint level, 1962 GLint xoffset, GLint yoffset, 1963 GLint x, GLint y, GLsizei width, GLsizei height ) 1964{ 1965 struct gl_texture_unit *texUnit; 1966 struct gl_texture_object *texObj; 1967 struct gl_texture_image *texImage; 1968 GLsizei postConvWidth = width, postConvHeight = height; 1969 GET_CURRENT_CONTEXT(ctx); 1970 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 1971 1972 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 1973 _mesa_update_state(ctx); 1974 1975 /* XXX should test internal format */ 1976 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 1977 1978 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 1979 postConvWidth, postConvHeight)) 1980 return; 1981 1982 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1983 texObj = _mesa_select_tex_object(ctx, texUnit, target); 1984 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 1985 1986 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 1987 xoffset += texImage->Border; 1988 yoffset += texImage->Border; 1989 1990 ASSERT(ctx->Driver.CopyTexSubImage2D); 1991 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, 1992 xoffset, yoffset, x, y, width, height); 1993 ctx->NewState |= _NEW_TEXTURE; 1994} 1995 1996 1997 1998void 1999_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2000 GLint xoffset, GLint yoffset, GLint zoffset, 2001 GLint x, GLint y, GLsizei width, GLsizei height ) 2002{ 2003 struct gl_texture_unit *texUnit; 2004 struct gl_texture_object *texObj; 2005 struct gl_texture_image *texImage; 2006 GLsizei postConvWidth = width, postConvHeight = height; 2007 GET_CURRENT_CONTEXT(ctx); 2008 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2009 2010 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2011 _mesa_update_state(ctx); 2012 2013 /* XXX should test internal format */ 2014 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 2015 2016 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, 2017 zoffset, postConvWidth, postConvHeight)) 2018 return; 2019 2020 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2021 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2022 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2023 2024 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2025 xoffset += texImage->Border; 2026 yoffset += texImage->Border; 2027 zoffset += texImage->Border; 2028 2029 ASSERT(ctx->Driver.CopyTexSubImage3D); 2030 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, 2031 xoffset, yoffset, zoffset, 2032 x, y, width, height); 2033 ctx->NewState |= _NEW_TEXTURE; 2034} 2035 2036 2037 2038void 2039_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 2040 GLenum internalFormat, GLsizei width, 2041 GLint border, GLsizei imageSize, 2042 const GLvoid *data) 2043{ 2044 GET_CURRENT_CONTEXT(ctx); 2045 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2046 2047 switch (internalFormat) { 2048 case GL_COMPRESSED_ALPHA_ARB: 2049 case GL_COMPRESSED_LUMINANCE_ARB: 2050 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 2051 case GL_COMPRESSED_INTENSITY_ARB: 2052 case GL_COMPRESSED_RGB_ARB: 2053 case GL_COMPRESSED_RGBA_ARB: 2054 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB"); 2055 return; 2056 default: 2057 /* silence compiler warning */ 2058 ; 2059 } 2060 2061 if (target == GL_TEXTURE_1D) { 2062 struct gl_texture_unit *texUnit; 2063 struct gl_texture_object *texObj; 2064 struct gl_texture_image *texImage; 2065 2066 if (texture_error_check(ctx, target, level, internalFormat, 2067 GL_NONE, GL_NONE, 1, width, 1, 1, border)) { 2068 return; /* error in texture image was detected */ 2069 } 2070 2071 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2072 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2073 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2074 2075 if (!texImage) { 2076 texImage = _mesa_alloc_texture_image(); 2077 texObj->Image[level] = texImage; 2078 if (!texImage) { 2079 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB"); 2080 return; 2081 } 2082 } 2083 else if (texImage->Data) { 2084 FREE(texImage->Data); 2085 texImage->Data = NULL; 2086 } 2087 2088 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1, 2089 border, internalFormat); 2090 2091 if (ctx->Extensions.ARB_texture_compression) { 2092 ASSERT(ctx->Driver.CompressedTexImage1D); 2093 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 2094 internalFormat, width, border, 2095 imageSize, data, 2096 texObj, texImage); 2097 ASSERT(texImage->CompressedSize > 0); /* sanity */ 2098 } 2099 2100 /* state update */ 2101 texObj->Complete = GL_FALSE; 2102 ctx->NewState |= _NEW_TEXTURE; 2103 } 2104 else if (target == GL_PROXY_TEXTURE_1D) { 2105 /* Proxy texture: check for errors and update proxy state */ 2106 GLenum error = texture_error_check(ctx, target, level, internalFormat, 2107 GL_NONE, GL_NONE, 1, width, 1, 1, border); 2108 if (!error) { 2109 struct gl_texture_unit *texUnit; 2110 struct gl_texture_image *texImage; 2111 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2112 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2113 _mesa_init_teximage_fields(ctx, texImage, width, 1, 1, 2114 border, internalFormat); 2115 ASSERT(ctx->Driver.TestProxyTexImage); 2116 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 2117 internalFormat, GL_NONE, GL_NONE, 2118 width, 1, 1, border); 2119 } 2120 if (error) { 2121 /* if error, clear all proxy texture image parameters */ 2122 if (level >= 0 && level < ctx->Const.MaxTextureLevels) { 2123 clear_teximage_fields(ctx->Texture.Proxy1D->Image[level]); 2124 } 2125 } 2126 } 2127 else { 2128 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)"); 2129 return; 2130 } 2131} 2132 2133 2134void 2135_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 2136 GLenum internalFormat, GLsizei width, 2137 GLsizei height, GLint border, GLsizei imageSize, 2138 const GLvoid *data) 2139{ 2140 GET_CURRENT_CONTEXT(ctx); 2141 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2142 2143 switch (internalFormat) { 2144 case GL_COMPRESSED_ALPHA_ARB: 2145 case GL_COMPRESSED_LUMINANCE_ARB: 2146 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 2147 case GL_COMPRESSED_INTENSITY_ARB: 2148 case GL_COMPRESSED_RGB_ARB: 2149 case GL_COMPRESSED_RGBA_ARB: 2150 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB"); 2151 return; 2152 default: 2153 /* silence compiler warning */ 2154 ; 2155 } 2156 2157 if (target == GL_TEXTURE_2D || 2158 (ctx->Extensions.ARB_texture_cube_map && 2159 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2160 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 2161 struct gl_texture_unit *texUnit; 2162 struct gl_texture_object *texObj; 2163 struct gl_texture_image *texImage; 2164 2165 if (texture_error_check(ctx, target, level, internalFormat, 2166 GL_NONE, GL_NONE, 1, width, height, 1, border)) { 2167 return; /* error in texture image was detected */ 2168 } 2169 2170 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2171 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2172 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2173 2174 if (!texImage) { 2175 texImage = _mesa_alloc_texture_image(); 2176 texObj->Image[level] = texImage; 2177 if (!texImage) { 2178 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); 2179 return; 2180 } 2181 } 2182 else if (texImage->Data) { 2183 FREE(texImage->Data); 2184 texImage->Data = NULL; 2185 } 2186 2187 _mesa_init_teximage_fields(ctx, texImage, width, height, 1, border, 2188 internalFormat); 2189 2190 if (ctx->Extensions.ARB_texture_compression) { 2191 ASSERT(ctx->Driver.CompressedTexImage2D); 2192 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 2193 internalFormat, width, height, 2194 border, imageSize, data, 2195 texObj, texImage); 2196 ASSERT(texImage->CompressedSize > 0); /* sanity */ 2197 } 2198 2199 /* state update */ 2200 texObj->Complete = GL_FALSE; 2201 ctx->NewState |= _NEW_TEXTURE; 2202 } 2203 else if (target == GL_PROXY_TEXTURE_2D) { 2204 /* Proxy texture: check for errors and update proxy state */ 2205 GLenum error = texture_error_check(ctx, target, level, internalFormat, 2206 GL_NONE, GL_NONE, 2, width, height, 1, border); 2207 if (!error) { 2208 struct gl_texture_unit *texUnit; 2209 struct gl_texture_image *texImage; 2210 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2211 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2212 _mesa_init_teximage_fields(ctx, texImage, width, height, 1, 2213 border, internalFormat); 2214 ASSERT(ctx->Driver.TestProxyTexImage); 2215 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 2216 internalFormat, GL_NONE, GL_NONE, 2217 width, height, 1, border); 2218 } 2219 if (error) { 2220 /* if error, clear all proxy texture image parameters */ 2221 const GLint maxLevels = (target == GL_PROXY_TEXTURE_2D) ? 2222 ctx->Const.MaxTextureLevels : ctx->Const.MaxCubeTextureLevels; 2223 if (level >= 0 && level < maxLevels) { 2224 clear_teximage_fields(ctx->Texture.Proxy2D->Image[level]); 2225 } 2226 } 2227 } 2228 else { 2229 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)"); 2230 return; 2231 } 2232} 2233 2234 2235void 2236_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 2237 GLenum internalFormat, GLsizei width, 2238 GLsizei height, GLsizei depth, GLint border, 2239 GLsizei imageSize, const GLvoid *data) 2240{ 2241 GET_CURRENT_CONTEXT(ctx); 2242 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2243 2244 switch (internalFormat) { 2245 case GL_COMPRESSED_ALPHA_ARB: 2246 case GL_COMPRESSED_LUMINANCE_ARB: 2247 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: 2248 case GL_COMPRESSED_INTENSITY_ARB: 2249 case GL_COMPRESSED_RGB_ARB: 2250 case GL_COMPRESSED_RGBA_ARB: 2251 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB"); 2252 return; 2253 default: 2254 /* silence compiler warning */ 2255 ; 2256 } 2257 2258 if (target == GL_TEXTURE_3D) { 2259 struct gl_texture_unit *texUnit; 2260 struct gl_texture_object *texObj; 2261 struct gl_texture_image *texImage; 2262 2263 if (texture_error_check(ctx, target, level, internalFormat, 2264 GL_NONE, GL_NONE, 1, width, height, depth, border)) { 2265 return; /* error in texture image was detected */ 2266 } 2267 2268 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2269 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2270 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2271 2272 if (!texImage) { 2273 texImage = _mesa_alloc_texture_image(); 2274 texObj->Image[level] = texImage; 2275 if (!texImage) { 2276 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB"); 2277 return; 2278 } 2279 } 2280 else if (texImage->Data) { 2281 FREE(texImage->Data); 2282 texImage->Data = NULL; 2283 } 2284 2285 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, border, 2286 internalFormat); 2287 2288 if (ctx->Extensions.ARB_texture_compression) { 2289 ASSERT(ctx->Driver.CompressedTexImage3D); 2290 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 2291 internalFormat, 2292 width, height, depth, 2293 border, imageSize, data, 2294 texObj, texImage); 2295 ASSERT(texImage->CompressedSize > 0); /* sanity */ 2296 } 2297 2298 /* state update */ 2299 texObj->Complete = GL_FALSE; 2300 ctx->NewState |= _NEW_TEXTURE; 2301 } 2302 else if (target == GL_PROXY_TEXTURE_3D) { 2303 /* Proxy texture: check for errors and update proxy state */ 2304 GLenum error = texture_error_check(ctx, target, level, internalFormat, 2305 GL_NONE, GL_NONE, 1, width, height, depth, border); 2306 if (!error) { 2307 struct gl_texture_unit *texUnit; 2308 struct gl_texture_image *texImage; 2309 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2310 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2311 _mesa_init_teximage_fields(ctx, texImage, width, height, depth, 2312 border, internalFormat); 2313 ASSERT(ctx->Driver.TestProxyTexImage); 2314 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 2315 internalFormat, GL_NONE, GL_NONE, 2316 width, height, depth, border); 2317 } 2318 if (error) { 2319 /* if error, clear all proxy texture image parameters */ 2320 if (level >= 0 && level < ctx->Const.Max3DTextureLevels) { 2321 clear_teximage_fields(ctx->Texture.Proxy3D->Image[level]); 2322 } 2323 } 2324 } 2325 else { 2326 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)"); 2327 return; 2328 } 2329} 2330 2331 2332void 2333_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 2334 GLsizei width, GLenum format, 2335 GLsizei imageSize, const GLvoid *data) 2336{ 2337 struct gl_texture_unit *texUnit; 2338 struct gl_texture_object *texObj; 2339 struct gl_texture_image *texImage; 2340 GET_CURRENT_CONTEXT(ctx); 2341 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2342 2343 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2344 width, 1, 1, format, GL_NONE)) { 2345 return; /* error was detected */ 2346 } 2347 2348 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2349 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2350 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2351 assert(texImage); 2352 2353 if (width == 0 || !data) 2354 return; /* no-op, not an error */ 2355 2356 if (ctx->Driver.CompressedTexSubImage1D) { 2357 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 2358 xoffset, width, 2359 format, imageSize, data, 2360 texObj, texImage); 2361 } 2362 ctx->NewState |= _NEW_TEXTURE; 2363} 2364 2365 2366void 2367_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 2368 GLint yoffset, GLsizei width, GLsizei height, 2369 GLenum format, GLsizei imageSize, 2370 const GLvoid *data) 2371{ 2372 struct gl_texture_unit *texUnit; 2373 struct gl_texture_object *texObj; 2374 struct gl_texture_image *texImage; 2375 GET_CURRENT_CONTEXT(ctx); 2376 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2377 2378 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2379 width, height, 1, format, GL_NONE)) { 2380 return; /* error was detected */ 2381 } 2382 2383 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2384 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2385 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2386 assert(texImage); 2387 2388 if (width == 0 || height == 0 || !data) 2389 return; /* no-op, not an error */ 2390 2391 if (ctx->Driver.CompressedTexSubImage2D) { 2392 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 2393 xoffset, yoffset, width, height, 2394 format, imageSize, data, 2395 texObj, texImage); 2396 } 2397 ctx->NewState |= _NEW_TEXTURE; 2398} 2399 2400 2401void 2402_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 2403 GLint yoffset, GLint zoffset, GLsizei width, 2404 GLsizei height, GLsizei depth, GLenum format, 2405 GLsizei imageSize, const GLvoid *data) 2406{ 2407 struct gl_texture_unit *texUnit; 2408 struct gl_texture_object *texObj; 2409 struct gl_texture_image *texImage; 2410 GET_CURRENT_CONTEXT(ctx); 2411 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2412 2413 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2414 width, height, depth, format, GL_NONE)) { 2415 return; /* error was detected */ 2416 } 2417 2418 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2419 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2420 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2421 assert(texImage); 2422 2423 if (width == 0 || height == 0 || depth == 0 || !data) 2424 return; /* no-op, not an error */ 2425 2426 if (ctx->Driver.CompressedTexSubImage3D) { 2427 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 2428 xoffset, yoffset, zoffset, 2429 width, height, depth, 2430 format, imageSize, data, 2431 texObj, texImage); 2432 } 2433 ctx->NewState |= _NEW_TEXTURE; 2434} 2435 2436 2437void 2438_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 2439{ 2440 const struct gl_texture_unit *texUnit; 2441 const struct gl_texture_object *texObj; 2442 struct gl_texture_image *texImage; 2443 GLint maxLevels; 2444 GET_CURRENT_CONTEXT(ctx); 2445 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2446 2447 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2448 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2449 if (!texObj) { 2450 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 2451 return; 2452 } 2453 2454 if (target == GL_TEXTURE_1D || target == GL_TEXTURE_2D) { 2455 maxLevels = ctx->Const.MaxTextureLevels; 2456 } 2457 else if (target == GL_TEXTURE_3D) { 2458 maxLevels = ctx->Const.Max3DTextureLevels; 2459 } 2460 else { 2461 maxLevels = ctx->Const.MaxCubeTextureLevels; 2462 } 2463 2464 ASSERT(maxLevels > 0); 2465 2466 if (level < 0 || level >= maxLevels) { 2467 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 2468 return; 2469 } 2470 2471 if (is_proxy_target(target)) { 2472 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 2473 return; 2474 } 2475 2476 texImage = _mesa_select_tex_image(ctx, texUnit, target, level); 2477 if (!texImage) { 2478 /* probably invalid mipmap level */ 2479 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 2480 return; 2481 } 2482 2483 if (!texImage->IsCompressed) { 2484 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); 2485 return; 2486 } 2487 2488 if (!img) 2489 return; 2490 2491 if (ctx->Extensions.ARB_texture_compression) { 2492 ASSERT(ctx->Driver.GetCompressedTexImage); 2493 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj, 2494 texImage); 2495 } 2496} 2497