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