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