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