teximage.c revision 7117f1b4
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.0.3 4 * 5 * Copyright (C) 1999-2008 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_UNSIGNED_BYTE 77 _mesa_problem(NULL, "PrintTexture not supported"); 78#else 79 GLuint i, j, c; 80 const GLubyte *data = (const GLubyte *) 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 * Note that width, height, depth == 0 is not an error. However, a 1211 * texture with zero width/height/depth will be considered "incomplete" 1212 * and texturing will effectively be disabled. 1213 * 1214 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 1215 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 1216 * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 1217 * \param level as passed to glTexImage 1218 * \param internalFormat as passed to glTexImage 1219 * \param format as passed to glTexImage 1220 * \param type as passed to glTexImage 1221 * \param width as passed to glTexImage 1222 * \param height as passed to glTexImage 1223 * \param depth as passed to glTexImage 1224 * \param border as passed to glTexImage 1225 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1226 */ 1227GLboolean 1228_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 1229 GLint internalFormat, GLenum format, GLenum type, 1230 GLint width, GLint height, GLint depth, GLint border) 1231{ 1232 GLint maxSize; 1233 1234 (void) internalFormat; 1235 (void) format; 1236 (void) type; 1237 1238 switch (target) { 1239 case GL_PROXY_TEXTURE_1D: 1240 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1241 if (width < 2 * border || width > 2 + maxSize || 1242 (!ctx->Extensions.ARB_texture_non_power_of_two && 1243 width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 1244 level >= ctx->Const.MaxTextureLevels) { 1245 /* bad width or level */ 1246 return GL_FALSE; 1247 } 1248 return GL_TRUE; 1249 case GL_PROXY_TEXTURE_2D: 1250 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1251 if (width < 2 * border || width > 2 + maxSize || 1252 (!ctx->Extensions.ARB_texture_non_power_of_two && 1253 width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 1254 height < 2 * border || height > 2 + maxSize || 1255 (!ctx->Extensions.ARB_texture_non_power_of_two && 1256 height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 1257 level >= ctx->Const.MaxTextureLevels) { 1258 /* bad width or height or level */ 1259 return GL_FALSE; 1260 } 1261 return GL_TRUE; 1262 case GL_PROXY_TEXTURE_3D: 1263 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1264 if (width < 2 * border || width > 2 + maxSize || 1265 (!ctx->Extensions.ARB_texture_non_power_of_two && 1266 width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 1267 height < 2 * border || height > 2 + maxSize || 1268 (!ctx->Extensions.ARB_texture_non_power_of_two && 1269 height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 1270 depth < 2 * border || depth > 2 + maxSize || 1271 (!ctx->Extensions.ARB_texture_non_power_of_two && 1272 depth > 0 && _mesa_bitcount(depth - 2 * border) != 1) || 1273 level >= ctx->Const.Max3DTextureLevels) { 1274 /* bad width or height or depth or level */ 1275 return GL_FALSE; 1276 } 1277 return GL_TRUE; 1278 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1279 if (width < 0 || width > ctx->Const.MaxTextureRectSize || 1280 height < 0 || height > ctx->Const.MaxTextureRectSize || 1281 level != 0) { 1282 /* bad width or height or level */ 1283 return GL_FALSE; 1284 } 1285 return GL_TRUE; 1286 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 1287 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1288 if (width < 2 * border || width > 2 + maxSize || 1289 (!ctx->Extensions.ARB_texture_non_power_of_two && 1290 width > 0 && _mesa_bitcount(width - 2 * border) != 1) || 1291 height < 2 * border || height > 2 + maxSize || 1292 (!ctx->Extensions.ARB_texture_non_power_of_two && 1293 height > 0 && _mesa_bitcount(height - 2 * border) != 1) || 1294 level >= ctx->Const.MaxCubeTextureLevels) { 1295 /* bad width or height */ 1296 return GL_FALSE; 1297 } 1298 return GL_TRUE; 1299 default: 1300 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 1301 return GL_FALSE; 1302 } 1303} 1304 1305 1306/** 1307 * Helper function to determine whether a target supports compressed textures 1308 */ 1309static GLboolean 1310target_can_be_compressed(GLcontext *ctx, GLenum target) 1311{ 1312 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 1313 || ((ctx->Extensions.ARB_texture_cube_map && 1314 (target == GL_PROXY_TEXTURE_CUBE_MAP || 1315 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 1316 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))); 1317} 1318 1319 1320/** 1321 * Test the glTexImage[123]D() parameters for errors. 1322 * 1323 * \param ctx GL context. 1324 * \param target texture target given by the user. 1325 * \param level image level given by the user. 1326 * \param internalFormat internal format given by the user. 1327 * \param format pixel data format given by the user. 1328 * \param type pixel data type given by the user. 1329 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1330 * \param width image width given by the user. 1331 * \param height image height given by the user. 1332 * \param depth image depth given by the user. 1333 * \param border image border given by the user. 1334 * 1335 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1336 * 1337 * Verifies each of the parameters against the constants specified in 1338 * __GLcontextRec::Const and the supported extensions, and according to the 1339 * OpenGL specification. 1340 */ 1341static GLboolean 1342texture_error_check( GLcontext *ctx, GLenum target, 1343 GLint level, GLint internalFormat, 1344 GLenum format, GLenum type, 1345 GLuint dimensions, 1346 GLint width, GLint height, 1347 GLint depth, GLint border ) 1348{ 1349 const GLboolean isProxy = _mesa_is_proxy_texture(target); 1350 GLboolean sizeOK = GL_TRUE; 1351 GLboolean colorFormat, indexFormat; 1352 GLenum proxy_target; 1353 1354 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1355 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1356 if (!isProxy) { 1357 _mesa_error(ctx, GL_INVALID_VALUE, 1358 "glTexImage%dD(level=%d)", dimensions, level); 1359 } 1360 return GL_TRUE; 1361 } 1362 1363 /* Check border */ 1364 if (border < 0 || border > 1 || 1365 ((target == GL_TEXTURE_RECTANGLE_NV || 1366 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1367 if (!isProxy) { 1368 _mesa_error(ctx, GL_INVALID_VALUE, 1369 "glTexImage%dD(border=%d)", dimensions, border); 1370 } 1371 return GL_TRUE; 1372 } 1373 1374 if (width < 0 || height < 0 || depth < 0) { 1375 if (!isProxy) { 1376 _mesa_error(ctx, GL_INVALID_VALUE, 1377 "glTexImage%dD(width, height or depth < 0)", dimensions); 1378 } 1379 return GL_TRUE; 1380 } 1381 1382 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1383 * level, width, height and depth. 1384 */ 1385 if (dimensions == 1) { 1386 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 1387 proxy_target = GL_PROXY_TEXTURE_1D; 1388 height = 1; 1389 depth = 1; 1390 } 1391 else { 1392 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1393 return GL_TRUE; 1394 } 1395 } 1396 else if (dimensions == 2) { 1397 depth = 1; 1398 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 1399 proxy_target = GL_PROXY_TEXTURE_2D; 1400 } 1401 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 1402 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1403 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1404 if (!ctx->Extensions.ARB_texture_cube_map) { 1405 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1406 return GL_TRUE; 1407 } 1408 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 1409 sizeOK = (width == height); 1410 } 1411 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 1412 target == GL_TEXTURE_RECTANGLE_NV) { 1413 if (!ctx->Extensions.NV_texture_rectangle) { 1414 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1415 return GL_TRUE; 1416 } 1417 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 1418 } 1419 else { 1420 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1421 return GL_TRUE; 1422 } 1423 } 1424 else if (dimensions == 3) { 1425 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 1426 proxy_target = GL_PROXY_TEXTURE_3D; 1427 } 1428 else { 1429 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1430 return GL_TRUE; 1431 } 1432 } 1433 else { 1434 _mesa_problem( ctx, "bad dims in texture_error_check" ); 1435 return GL_TRUE; 1436 } 1437 1438 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 1439 internalFormat, format, 1440 type, width, height, 1441 depth, border); 1442 if (!sizeOK) { 1443 if (!isProxy) { 1444 _mesa_error(ctx, GL_INVALID_VALUE, 1445 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 1446 dimensions, level, width, height, depth); 1447 } 1448 return GL_TRUE; 1449 } 1450 1451 /* Check internalFormat */ 1452 if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1453 if (!isProxy) { 1454 _mesa_error(ctx, GL_INVALID_VALUE, 1455 "glTexImage%dD(internalFormat=0x%x)", 1456 dimensions, internalFormat); 1457 } 1458 return GL_TRUE; 1459 } 1460 1461 /* Check incoming image format and type */ 1462 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1463 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 1464 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 1465 */ 1466 if (!isProxy) { 1467 _mesa_error(ctx, GL_INVALID_OPERATION, 1468 "glTexImage%dD(format or type)", dimensions); 1469 } 1470 return GL_TRUE; 1471 } 1472 1473 /* make sure internal format and format basically agree */ 1474 colorFormat = is_color_format(format); 1475 indexFormat = is_index_format(format); 1476 if ((is_color_format(internalFormat) && !colorFormat && !indexFormat) || 1477 (is_index_format(internalFormat) && !indexFormat) || 1478 (is_depth_format(internalFormat) != is_depth_format(format)) || 1479 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 1480 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) { 1481 if (!isProxy) 1482 _mesa_error(ctx, GL_INVALID_OPERATION, 1483 "glTexImage(internalFormat/format)"); 1484 return GL_TRUE; 1485 } 1486 1487 /* additional checks for ycbcr textures */ 1488 if (internalFormat == GL_YCBCR_MESA) { 1489 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 1490 if (type != GL_UNSIGNED_SHORT_8_8_MESA && 1491 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 1492 char message[100]; 1493 _mesa_sprintf(message, 1494 "glTexImage%d(format/type YCBCR mismatch", dimensions); 1495 _mesa_error(ctx, GL_INVALID_ENUM, message); 1496 return GL_TRUE; /* error */ 1497 } 1498 if (target != GL_TEXTURE_2D && 1499 target != GL_PROXY_TEXTURE_2D && 1500 target != GL_TEXTURE_RECTANGLE_NV && 1501 target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1502 if (!isProxy) 1503 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 1504 return GL_TRUE; 1505 } 1506 if (border != 0) { 1507 if (!isProxy) { 1508 char message[100]; 1509 _mesa_sprintf(message, 1510 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 1511 dimensions, border); 1512 _mesa_error(ctx, GL_INVALID_VALUE, message); 1513 } 1514 return GL_TRUE; 1515 } 1516 } 1517 1518 /* additional checks for depth textures */ 1519 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 1520 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 1521 if (target != GL_TEXTURE_1D && 1522 target != GL_PROXY_TEXTURE_1D && 1523 target != GL_TEXTURE_2D && 1524 target != GL_PROXY_TEXTURE_2D && 1525 target != GL_TEXTURE_RECTANGLE_ARB && 1526 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 1527 if (!isProxy) 1528 _mesa_error(ctx, GL_INVALID_ENUM, 1529 "glTexImage(target/internalFormat)"); 1530 return GL_TRUE; 1531 } 1532 } 1533 1534 /* additional checks for compressed textures */ 1535 if (is_compressed_format(ctx, internalFormat)) { 1536 if (!target_can_be_compressed(ctx, target) && !isProxy) { 1537 _mesa_error(ctx, GL_INVALID_ENUM, 1538 "glTexImage%d(target)", dimensions); 1539 return GL_TRUE; 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_can_be_compressed(ctx, target)) { 1715 _mesa_error(ctx, GL_INVALID_ENUM, 1716 "glTexSubImage%D(target)", dimensions); 1717 return GL_TRUE; 1718 } 1719 /* offset must be multiple of 4 */ 1720 if ((xoffset & 3) || (yoffset & 3)) { 1721 _mesa_error(ctx, GL_INVALID_OPERATION, 1722 "glTexSubImage%D(xoffset or yoffset)", dimensions); 1723 return GL_TRUE; 1724 } 1725 /* size must be multiple of 4 or equal to whole texture size */ 1726 if ((width & 3) && (GLuint) width != destTex->Width) { 1727 _mesa_error(ctx, GL_INVALID_OPERATION, 1728 "glTexSubImage%D(width)", dimensions); 1729 return GL_TRUE; 1730 } 1731 if ((height & 3) && (GLuint) height != destTex->Height) { 1732 _mesa_error(ctx, GL_INVALID_OPERATION, 1733 "glTexSubImage%D(width)", dimensions); 1734 return GL_TRUE; 1735 } 1736 } 1737 1738 return GL_FALSE; 1739} 1740 1741 1742/** 1743 * Test glCopyTexImage[12]D() parameters for errors. 1744 * 1745 * \param ctx GL context. 1746 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1747 * \param target texture target given by the user. 1748 * \param level image level given by the user. 1749 * \param internalFormat internal format given by the user. 1750 * \param width image width given by the user. 1751 * \param height image height given by the user. 1752 * \param depth image depth given by the user. 1753 * \param border texture border. 1754 * 1755 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1756 * 1757 * Verifies each of the parameters against the constants specified in 1758 * __GLcontextRec::Const and the supported extensions, and according to the 1759 * OpenGL specification. 1760 */ 1761static GLboolean 1762copytexture_error_check( GLcontext *ctx, GLuint dimensions, 1763 GLenum target, GLint level, GLint internalFormat, 1764 GLint width, GLint height, GLint border ) 1765{ 1766 GLenum type; 1767 GLboolean sizeOK; 1768 GLint format; 1769 1770 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1771 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1772 _mesa_error(ctx, GL_INVALID_VALUE, 1773 "glCopyTexImage%dD(level=%d)", dimensions, level); 1774 return GL_TRUE; 1775 } 1776 1777 /* Check that the source buffer is complete */ 1778 if (ctx->ReadBuffer->Name) { 1779 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1780 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1781 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1782 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1783 return GL_TRUE; 1784 } 1785 } 1786 1787 /* Check border */ 1788 if (border < 0 || border > 1 || 1789 ((target == GL_TEXTURE_RECTANGLE_NV || 1790 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1791 return GL_TRUE; 1792 } 1793 1794 format = _mesa_base_tex_format(ctx, internalFormat); 1795 if (format < 0) { 1796 _mesa_error(ctx, GL_INVALID_VALUE, 1797 "glCopyTexImage%dD(internalFormat)", dimensions); 1798 return GL_TRUE; 1799 } 1800 1801 /* NOTE: the format and type aren't really significant for 1802 * TestProxyTexImage(). Only the internalformat really matters. 1803 if (!_mesa_source_buffer_exists(ctx, format)) { 1804 _mesa_error(ctx, GL_INVALID_OPERATION, 1805 "glCopyTexImage%dD(missing readbuffer)", dimensions); 1806 return GL_TRUE; 1807 } 1808 1809 */ 1810 type = GL_FLOAT; 1811 1812 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1813 * level, width, height and depth. 1814 */ 1815 if (dimensions == 1) { 1816 if (target == GL_TEXTURE_1D) { 1817 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 1818 level, internalFormat, 1819 format, type, 1820 width, 1, 1, border); 1821 } 1822 else { 1823 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 1824 return GL_TRUE; 1825 } 1826 } 1827 else if (dimensions == 2) { 1828 if (target == GL_TEXTURE_2D) { 1829 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 1830 level, internalFormat, 1831 format, type, 1832 width, height, 1, border); 1833 } 1834 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1835 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1836 if (!ctx->Extensions.ARB_texture_cube_map) { 1837 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1838 return GL_TRUE; 1839 } 1840 sizeOK = (width == height) && 1841 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 1842 level, internalFormat, format, type, 1843 width, height, 1, border); 1844 } 1845 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1846 if (!ctx->Extensions.NV_texture_rectangle) { 1847 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1848 return GL_TRUE; 1849 } 1850 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1851 GL_PROXY_TEXTURE_RECTANGLE_NV, 1852 level, internalFormat, 1853 format, type, 1854 width, height, 1, border); 1855 } 1856 else { 1857 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1858 return GL_TRUE; 1859 } 1860 } 1861 else { 1862 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 1863 return GL_TRUE; 1864 } 1865 1866 if (!sizeOK) { 1867 if (dimensions == 1) { 1868 _mesa_error(ctx, GL_INVALID_VALUE, 1869 "glCopyTexImage1D(width=%d)", width); 1870 } 1871 else { 1872 ASSERT(dimensions == 2); 1873 _mesa_error(ctx, GL_INVALID_VALUE, 1874 "glCopyTexImage2D(width=%d, height=%d)", width, height); 1875 } 1876 return GL_TRUE; 1877 } 1878 1879 if (is_compressed_format(ctx, internalFormat)) { 1880 if (target != GL_TEXTURE_2D) { 1881 _mesa_error(ctx, GL_INVALID_ENUM, 1882 "glCopyTexImage%d(target)", dimensions); 1883 return GL_TRUE; 1884 } 1885 if (border != 0) { 1886 _mesa_error(ctx, GL_INVALID_OPERATION, 1887 "glCopyTexImage%D(border!=0)", dimensions); 1888 return GL_TRUE; 1889 } 1890 } 1891 else if (is_depth_format(internalFormat)) { 1892 /* make sure we have depth/stencil buffers */ 1893 if (!ctx->ReadBuffer->_DepthBuffer) { 1894 _mesa_error(ctx, GL_INVALID_OPERATION, 1895 "glCopyTexImage%D(no depth)", dimensions); 1896 return GL_TRUE; 1897 } 1898 } 1899 else if (is_depthstencil_format(internalFormat)) { 1900 /* make sure we have depth/stencil buffers */ 1901 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 1902 _mesa_error(ctx, GL_INVALID_OPERATION, 1903 "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 1904 return GL_TRUE; 1905 } 1906 } 1907 1908 /* if we get here, the parameters are OK */ 1909 return GL_FALSE; 1910} 1911 1912 1913/** 1914 * Test glCopyTexSubImage[12]D() parameters for errors. 1915 * 1916 * \param ctx GL context. 1917 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1918 * \param target texture target given by the user. 1919 * \param level image level given by the user. 1920 * \param xoffset sub-image x offset given by the user. 1921 * \param yoffset sub-image y offset given by the user. 1922 * \param zoffset sub-image z offset given by the user. 1923 * \param width image width given by the user. 1924 * \param height image height given by the user. 1925 * 1926 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1927 * 1928 * Verifies each of the parameters against the constants specified in 1929 * __GLcontextRec::Const and the supported extensions, and according to the 1930 * OpenGL specification. 1931 */ 1932static GLboolean 1933copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, 1934 GLenum target, GLint level, 1935 GLint xoffset, GLint yoffset, GLint zoffset, 1936 GLsizei width, GLsizei height) 1937{ 1938 /* Check target */ 1939 /* Check that the source buffer is complete */ 1940 if (ctx->ReadBuffer->Name) { 1941 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1942 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1943 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1944 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1945 return GL_TRUE; 1946 } 1947 } 1948 1949 if (dimensions == 1) { 1950 if (target != GL_TEXTURE_1D) { 1951 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 1952 return GL_TRUE; 1953 } 1954 } 1955 else if (dimensions == 2) { 1956 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1957 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1958 if (!ctx->Extensions.ARB_texture_cube_map) { 1959 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1960 return GL_TRUE; 1961 } 1962 } 1963 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1964 if (!ctx->Extensions.NV_texture_rectangle) { 1965 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1966 return GL_TRUE; 1967 } 1968 } 1969 else if (target != GL_TEXTURE_2D) { 1970 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1971 return GL_TRUE; 1972 } 1973 } 1974 else if (dimensions == 3) { 1975 if (target != GL_TEXTURE_3D) { 1976 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 1977 return GL_TRUE; 1978 } 1979 } 1980 1981 /* Check level */ 1982 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1983 _mesa_error(ctx, GL_INVALID_VALUE, 1984 "glCopyTexSubImage%dD(level=%d)", dimensions, level); 1985 return GL_TRUE; 1986 } 1987 1988 /* Check size */ 1989 if (width < 0) { 1990 _mesa_error(ctx, GL_INVALID_VALUE, 1991 "glCopyTexSubImage%dD(width=%d)", dimensions, width); 1992 return GL_TRUE; 1993 } 1994 if (dimensions > 1 && height < 0) { 1995 _mesa_error(ctx, GL_INVALID_VALUE, 1996 "glCopyTexSubImage%dD(height=%d)", dimensions, height); 1997 return GL_TRUE; 1998 } 1999 2000 return GL_FALSE; 2001} 2002 2003static GLboolean 2004copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 2005 GLenum target, GLint level, 2006 GLint xoffset, GLint yoffset, GLint zoffset, 2007 GLsizei width, GLsizei height, 2008 const struct gl_texture_image *teximage ) 2009{ 2010 if (!teximage) { 2011 _mesa_error(ctx, GL_INVALID_OPERATION, 2012 "glCopyTexSubImage%dD(undefined texture level: %d)", 2013 dimensions, level); 2014 return GL_TRUE; 2015 } 2016 2017 if (xoffset < -((GLint)teximage->Border)) { 2018 _mesa_error(ctx, GL_INVALID_VALUE, 2019 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 2020 return GL_TRUE; 2021 } 2022 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 2023 _mesa_error(ctx, GL_INVALID_VALUE, 2024 "glCopyTexSubImage%dD(xoffset+width)", dimensions); 2025 return GL_TRUE; 2026 } 2027 if (dimensions > 1) { 2028 if (yoffset < -((GLint)teximage->Border)) { 2029 _mesa_error(ctx, GL_INVALID_VALUE, 2030 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 2031 return GL_TRUE; 2032 } 2033 /* NOTE: we're adding the border here, not subtracting! */ 2034 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 2035 _mesa_error(ctx, GL_INVALID_VALUE, 2036 "glCopyTexSubImage%dD(yoffset+height)", dimensions); 2037 return GL_TRUE; 2038 } 2039 } 2040 2041 if (dimensions > 2) { 2042 if (zoffset < -((GLint)teximage->Border)) { 2043 _mesa_error(ctx, GL_INVALID_VALUE, 2044 "glCopyTexSubImage%dD(zoffset)", dimensions); 2045 return GL_TRUE; 2046 } 2047 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 2048 _mesa_error(ctx, GL_INVALID_VALUE, 2049 "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 2050 return GL_TRUE; 2051 } 2052 } 2053 2054 if (teximage->IsCompressed) { 2055 if (target != GL_TEXTURE_2D) { 2056 _mesa_error(ctx, GL_INVALID_ENUM, 2057 "glCopyTexSubImage%d(target)", dimensions); 2058 return GL_TRUE; 2059 } 2060 /* offset must be multiple of 4 */ 2061 if ((xoffset & 3) || (yoffset & 3)) { 2062 _mesa_error(ctx, GL_INVALID_VALUE, 2063 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 2064 return GL_TRUE; 2065 } 2066 /* size must be multiple of 4 */ 2067 if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 2068 _mesa_error(ctx, GL_INVALID_VALUE, 2069 "glCopyTexSubImage%D(width)", dimensions); 2070 return GL_TRUE; 2071 } 2072 if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 2073 _mesa_error(ctx, GL_INVALID_VALUE, 2074 "glCopyTexSubImage%D(height)", dimensions); 2075 return GL_TRUE; 2076 } 2077 } 2078 2079 if (teximage->InternalFormat == GL_YCBCR_MESA) { 2080 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 2081 return GL_TRUE; 2082 } 2083 2084 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 2085 _mesa_error(ctx, GL_INVALID_OPERATION, 2086 "glCopyTexSubImage%dD(missing readbuffer)", dimensions); 2087 return GL_TRUE; 2088 } 2089 2090 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 2091 if (!ctx->ReadBuffer->_DepthBuffer) { 2092 _mesa_error(ctx, GL_INVALID_OPERATION, 2093 "glCopyTexSubImage%D(no depth buffer)", 2094 dimensions); 2095 return GL_TRUE; 2096 } 2097 } 2098 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 2099 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 2100 _mesa_error(ctx, GL_INVALID_OPERATION, 2101 "glCopyTexSubImage%D(no depth/stencil buffer)", 2102 dimensions); 2103 return GL_TRUE; 2104 } 2105 } 2106 2107 /* if we get here, the parameters are OK */ 2108 return GL_FALSE; 2109} 2110 2111 2112/** 2113 * Get texture image. Called by glGetTexImage. 2114 * 2115 * \param target texture target. 2116 * \param level image level. 2117 * \param format pixel data format for returned image. 2118 * \param type pixel data type for returned image. 2119 * \param pixels returned pixel data. 2120 */ 2121void GLAPIENTRY 2122_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 2123 GLenum type, GLvoid *pixels ) 2124{ 2125 const struct gl_texture_unit *texUnit; 2126 struct gl_texture_object *texObj; 2127 struct gl_texture_image *texImage; 2128 GLint maxLevels = 0; 2129 GET_CURRENT_CONTEXT(ctx); 2130 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2131 2132 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 2133 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2134 if (!texObj || _mesa_is_proxy_texture(target)) { 2135 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 2136 return; 2137 } 2138 2139 maxLevels = _mesa_max_texture_levels(ctx, target); 2140 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 2141 2142 if (level < 0 || level >= maxLevels) { 2143 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 2144 return; 2145 } 2146 2147 if (_mesa_sizeof_packed_type(type) <= 0) { 2148 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 2149 return; 2150 } 2151 2152 if (_mesa_components_in_format(format) <= 0 || 2153 format == GL_STENCIL_INDEX) { 2154 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 2155 return; 2156 } 2157 2158 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 2159 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2160 return; 2161 } 2162 2163 if (!ctx->Extensions.SGIX_depth_texture && 2164 !ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { 2165 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2166 return; 2167 } 2168 2169 if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { 2170 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2171 return; 2172 } 2173 2174 if (!ctx->Extensions.EXT_packed_depth_stencil 2175 && is_depthstencil_format(format)) { 2176 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2177 return; 2178 } 2179 2180 _mesa_lock_texture(ctx, texObj); 2181 { 2182 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2183 if (!texImage) { 2184 /* invalid mipmap level, not an error */ 2185 goto out; 2186 } 2187 2188 2189 /* Make sure the requested image format is compatible with the 2190 * texture's format. Note that a color index texture can be converted 2191 * to RGBA so that combo is allowed. 2192 */ 2193 if (is_color_format(format) 2194 && !is_color_format(texImage->TexFormat->BaseFormat) 2195 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2196 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2197 goto out; 2198 } 2199 else if (is_index_format(format) 2200 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2201 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2202 goto out; 2203 } 2204 else if (is_depth_format(format) 2205 && !is_depth_format(texImage->TexFormat->BaseFormat) 2206 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2207 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2208 goto out; 2209 } 2210 else if (is_ycbcr_format(format) 2211 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 2212 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2213 goto out; 2214 } 2215 else if (is_depthstencil_format(format) 2216 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2217 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2218 goto out; 2219 } 2220 2221 if (ctx->Pack.BufferObj->Name) { 2222 /* packing texture image into a PBO */ 2223 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 2224 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 2225 texImage->Height, texImage->Depth, 2226 format, type, pixels)) { 2227 _mesa_error(ctx, GL_INVALID_OPERATION, 2228 "glGetTexImage(invalid PBO access)"); 2229 goto out; 2230 } 2231 } 2232 2233 /* typically, this will call _mesa_get_teximage() */ 2234 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 2235 texObj, texImage); 2236 2237 } 2238 out: 2239 _mesa_unlock_texture(ctx, texObj); 2240} 2241 2242 2243 2244/** 2245 * Check if the given texture image is bound to any framebuffer objects 2246 * and update/invalidate them. 2247 * XXX We're only checking the currently bound framebuffer object for now. 2248 * In the future, perhaps struct gl_texture_image should have a pointer (or 2249 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to. 2250 */ 2251static void 2252update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 2253 GLuint face, GLuint level) 2254{ 2255 if (ctx->DrawBuffer->Name) { 2256 GLuint i; 2257 for (i = 0; i < BUFFER_COUNT; i++) { 2258 struct gl_renderbuffer_attachment *att = 2259 ctx->DrawBuffer->Attachment + i; 2260 if (att->Type == GL_TEXTURE && 2261 att->Texture == texObj && 2262 att->TextureLevel == level && 2263 att->CubeMapFace == face) { 2264 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 2265 /* Tell driver about the new renderbuffer texture */ 2266 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 2267 } 2268 } 2269 } 2270} 2271 2272 2273 2274/* 2275 * Called from the API. Note that width includes the border. 2276 */ 2277void GLAPIENTRY 2278_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 2279 GLsizei width, GLint border, GLenum format, 2280 GLenum type, const GLvoid *pixels ) 2281{ 2282 GLsizei postConvWidth = width; 2283 GET_CURRENT_CONTEXT(ctx); 2284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2285 2286 if (is_color_format(internalFormat)) { 2287 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2288 } 2289 2290 if (target == GL_TEXTURE_1D) { 2291 /* non-proxy target */ 2292 struct gl_texture_unit *texUnit; 2293 struct gl_texture_object *texObj; 2294 struct gl_texture_image *texImage; 2295 const GLuint face = texture_face(target); 2296 2297 if (texture_error_check(ctx, target, level, internalFormat, 2298 format, type, 1, postConvWidth, 1, 1, border)) { 2299 return; /* error was recorded */ 2300 } 2301 2302 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2303 _mesa_update_state(ctx); 2304 2305 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2306 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2307 _mesa_lock_texture(ctx, texObj); 2308 { 2309 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2310 if (!texImage) { 2311 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2312 goto out; 2313 } 2314 2315 if (texImage->Data) { 2316 ctx->Driver.FreeTexImageData( ctx, texImage ); 2317 } 2318 2319 ASSERT(texImage->Data == NULL); 2320 2321 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2322 _mesa_init_teximage_fields(ctx, target, texImage, 2323 postConvWidth, 1, 1, 2324 border, internalFormat); 2325 2326 ASSERT(ctx->Driver.TexImage1D); 2327 2328 /* Give the texture to the driver! <pixels> may be null! */ 2329 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 2330 width, border, format, type, pixels, 2331 &ctx->Unpack, texObj, texImage); 2332 2333 ASSERT(texImage->TexFormat); 2334 2335 update_fbo_texture(ctx, texObj, face, level); 2336 2337 /* state update */ 2338 texObj->Complete = GL_FALSE; 2339 ctx->NewState |= _NEW_TEXTURE; 2340 } 2341 out: 2342 _mesa_unlock_texture(ctx, texObj); 2343 } 2344 else if (target == GL_PROXY_TEXTURE_1D) { 2345 /* Proxy texture: check for errors and update proxy state */ 2346 struct gl_texture_image *texImage; 2347 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2348 if (texture_error_check(ctx, target, level, internalFormat, 2349 format, type, 1, postConvWidth, 1, 1, border)) { 2350 /* when error, clear all proxy texture image parameters */ 2351 if (texImage) 2352 clear_teximage_fields(texImage); 2353 } 2354 else { 2355 /* no error, set the tex image parameters */ 2356 ASSERT(texImage); 2357 _mesa_init_teximage_fields(ctx, target, texImage, 2358 postConvWidth, 1, 1, 2359 border, internalFormat); 2360 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2361 internalFormat, format, type); 2362 } 2363 } 2364 else { 2365 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 2366 return; 2367 } 2368} 2369 2370 2371void GLAPIENTRY 2372_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 2373 GLsizei width, GLsizei height, GLint border, 2374 GLenum format, GLenum type, 2375 const GLvoid *pixels ) 2376{ 2377 GLsizei postConvWidth = width, postConvHeight = height; 2378 GET_CURRENT_CONTEXT(ctx); 2379 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2380 2381 if (is_color_format(internalFormat)) { 2382 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2383 &postConvHeight); 2384 } 2385 2386 if (target == GL_TEXTURE_2D || 2387 (ctx->Extensions.ARB_texture_cube_map && 2388 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2389 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 2390 (ctx->Extensions.NV_texture_rectangle && 2391 target == GL_TEXTURE_RECTANGLE_NV)) { 2392 /* non-proxy target */ 2393 struct gl_texture_unit *texUnit; 2394 struct gl_texture_object *texObj; 2395 struct gl_texture_image *texImage; 2396 const GLuint face = texture_face(target); 2397 2398 if (texture_error_check(ctx, target, level, internalFormat, 2399 format, type, 2, postConvWidth, postConvHeight, 2400 1, border)) { 2401 return; /* error was recorded */ 2402 } 2403 2404 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2405 _mesa_update_state(ctx); 2406 2407 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2408 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2409 _mesa_lock_texture(ctx, texObj); 2410 { 2411 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2412 if (!texImage) { 2413 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2414 goto out; 2415 } 2416 2417 if (texImage->Data) { 2418 ctx->Driver.FreeTexImageData( ctx, texImage ); 2419 } 2420 2421 ASSERT(texImage->Data == NULL); 2422 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2423 _mesa_init_teximage_fields(ctx, target, texImage, 2424 postConvWidth, postConvHeight, 1, 2425 border, internalFormat); 2426 2427 ASSERT(ctx->Driver.TexImage2D); 2428 2429 /* Give the texture to the driver! <pixels> may be null! */ 2430 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 2431 width, height, border, format, type, pixels, 2432 &ctx->Unpack, texObj, texImage); 2433 2434 ASSERT(texImage->TexFormat); 2435 2436 update_fbo_texture(ctx, texObj, face, level); 2437 2438 /* state update */ 2439 texObj->Complete = GL_FALSE; 2440 ctx->NewState |= _NEW_TEXTURE; 2441 } 2442 out: 2443 _mesa_unlock_texture(ctx, texObj); 2444 } 2445 else if (target == GL_PROXY_TEXTURE_2D || 2446 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 2447 ctx->Extensions.ARB_texture_cube_map) || 2448 (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2449 ctx->Extensions.NV_texture_rectangle)) { 2450 /* Proxy texture: check for errors and update proxy state */ 2451 struct gl_texture_image *texImage; 2452 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2453 if (texture_error_check(ctx, target, level, internalFormat, 2454 format, type, 2, postConvWidth, postConvHeight, 2455 1, border)) { 2456 /* when error, clear all proxy texture image parameters */ 2457 if (texImage) 2458 clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]); 2459 } 2460 else { 2461 /* no error, set the tex image parameters */ 2462 _mesa_init_teximage_fields(ctx, target, texImage, 2463 postConvWidth, postConvHeight, 1, 2464 border, internalFormat); 2465 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2466 internalFormat, format, type); 2467 } 2468 } 2469 else { 2470 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 2471 return; 2472 } 2473} 2474 2475 2476/* 2477 * Called by the API or display list executor. 2478 * Note that width and height include the border. 2479 */ 2480void GLAPIENTRY 2481_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 2482 GLsizei width, GLsizei height, GLsizei depth, 2483 GLint border, GLenum format, GLenum type, 2484 const GLvoid *pixels ) 2485{ 2486 GET_CURRENT_CONTEXT(ctx); 2487 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2488 2489 if (target == GL_TEXTURE_3D) { 2490 /* non-proxy target */ 2491 struct gl_texture_unit *texUnit; 2492 struct gl_texture_object *texObj; 2493 struct gl_texture_image *texImage; 2494 const GLuint face = texture_face(target); 2495 2496 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 2497 format, type, 3, width, height, depth, border)) { 2498 return; /* error was recorded */ 2499 } 2500 2501 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2502 _mesa_update_state(ctx); 2503 2504 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2505 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2506 _mesa_lock_texture(ctx, texObj); 2507 { 2508 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2509 if (!texImage) { 2510 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2511 goto out; 2512 } 2513 2514 if (texImage->Data) { 2515 ctx->Driver.FreeTexImageData( ctx, texImage ); 2516 } 2517 2518 ASSERT(texImage->Data == NULL); 2519 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2520 _mesa_init_teximage_fields(ctx, target, texImage, 2521 width, height, depth, 2522 border, internalFormat); 2523 2524 ASSERT(ctx->Driver.TexImage3D); 2525 2526 /* Give the texture to the driver! <pixels> may be null! */ 2527 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 2528 width, height, depth, border, format, type, 2529 pixels, &ctx->Unpack, texObj, texImage); 2530 2531 ASSERT(texImage->TexFormat); 2532 2533 update_fbo_texture(ctx, texObj, face, level); 2534 2535 /* state update */ 2536 texObj->Complete = GL_FALSE; 2537 ctx->NewState |= _NEW_TEXTURE; 2538 } 2539 out: 2540 _mesa_unlock_texture(ctx, texObj); 2541 } 2542 else if (target == GL_PROXY_TEXTURE_3D) { 2543 /* Proxy texture: check for errors and update proxy state */ 2544 struct gl_texture_image *texImage; 2545 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2546 if (texture_error_check(ctx, target, level, internalFormat, 2547 format, type, 3, width, height, depth, border)) { 2548 /* when error, clear all proxy texture image parameters */ 2549 if (texImage) 2550 clear_teximage_fields(texImage); 2551 } 2552 else { 2553 /* no error, set the tex image parameters */ 2554 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 2555 depth, border, internalFormat); 2556 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2557 internalFormat, format, type); 2558 } 2559 } 2560 else { 2561 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 2562 return; 2563 } 2564} 2565 2566 2567void GLAPIENTRY 2568_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2569 GLsizei width, GLsizei height, GLsizei depth, 2570 GLint border, GLenum format, GLenum type, 2571 const GLvoid *pixels ) 2572{ 2573 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2574 depth, border, format, type, pixels); 2575} 2576 2577 2578 2579void GLAPIENTRY 2580_mesa_TexSubImage1D( GLenum target, GLint level, 2581 GLint xoffset, GLsizei width, 2582 GLenum format, GLenum type, 2583 const GLvoid *pixels ) 2584{ 2585 GLsizei postConvWidth = width; 2586 struct gl_texture_unit *texUnit; 2587 struct gl_texture_object *texObj; 2588 struct gl_texture_image *texImage = NULL; 2589 GET_CURRENT_CONTEXT(ctx); 2590 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2591 2592 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2593 _mesa_update_state(ctx); 2594 2595 /* XXX should test internal format */ 2596 if (is_color_format(format)) { 2597 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2598 } 2599 2600 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2601 postConvWidth, 1, 1, format, type)) { 2602 return; /* error was detected */ 2603 } 2604 2605 2606 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2607 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2608 assert(texObj); 2609 2610 _mesa_lock_texture(ctx, texObj); 2611 { 2612 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2613 2614 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 2615 postConvWidth, 1, 1, format, type, texImage)) { 2616 goto out; /* error was detected */ 2617 } 2618 2619 if (width == 0) 2620 goto out; /* no-op, not an error */ 2621 2622 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2623 xoffset += texImage->Border; 2624 2625 ASSERT(ctx->Driver.TexSubImage1D); 2626 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 2627 format, type, pixels, &ctx->Unpack, 2628 texObj, texImage); 2629 ctx->NewState |= _NEW_TEXTURE; 2630 } 2631 out: 2632 _mesa_unlock_texture(ctx, texObj); 2633} 2634 2635 2636void GLAPIENTRY 2637_mesa_TexSubImage2D( GLenum target, GLint level, 2638 GLint xoffset, GLint yoffset, 2639 GLsizei width, GLsizei height, 2640 GLenum format, GLenum type, 2641 const GLvoid *pixels ) 2642{ 2643 GLsizei postConvWidth = width, postConvHeight = height; 2644 struct gl_texture_unit *texUnit; 2645 struct gl_texture_object *texObj; 2646 struct gl_texture_image *texImage; 2647 GET_CURRENT_CONTEXT(ctx); 2648 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2649 2650 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2651 _mesa_update_state(ctx); 2652 2653 /* XXX should test internal format */ 2654 if (is_color_format(format)) { 2655 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2656 &postConvHeight); 2657 } 2658 2659 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2660 postConvWidth, postConvHeight, 1, format, type)) { 2661 return; /* error was detected */ 2662 } 2663 2664 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2665 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2666 _mesa_lock_texture(ctx, texObj); 2667 { 2668 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2669 2670 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 2671 postConvWidth, postConvHeight, 1, format, type, 2672 texImage)) { 2673 goto out; /* error was detected */ 2674 } 2675 2676 if (width == 0 || height == 0) 2677 goto out; /* no-op, not an error */ 2678 2679 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2680 xoffset += texImage->Border; 2681 yoffset += texImage->Border; 2682 2683 ASSERT(ctx->Driver.TexSubImage2D); 2684 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 2685 width, height, format, type, pixels, 2686 &ctx->Unpack, texObj, texImage); 2687 ctx->NewState |= _NEW_TEXTURE; 2688 } 2689 out: 2690 _mesa_unlock_texture(ctx, texObj); 2691} 2692 2693 2694 2695void GLAPIENTRY 2696_mesa_TexSubImage3D( GLenum target, GLint level, 2697 GLint xoffset, GLint yoffset, GLint zoffset, 2698 GLsizei width, GLsizei height, GLsizei depth, 2699 GLenum format, GLenum type, 2700 const GLvoid *pixels ) 2701{ 2702 struct gl_texture_unit *texUnit; 2703 struct gl_texture_object *texObj; 2704 struct gl_texture_image *texImage; 2705 GET_CURRENT_CONTEXT(ctx); 2706 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2707 2708 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2709 _mesa_update_state(ctx); 2710 2711 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2712 width, height, depth, format, type)) { 2713 return; /* error was detected */ 2714 } 2715 2716 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2717 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2718 2719 _mesa_lock_texture(ctx, texObj); 2720 { 2721 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2722 2723 if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 2724 width, height, depth, format, type, texImage)) { 2725 goto out; /* error was detected */ 2726 } 2727 2728 if (width == 0 || height == 0 || height == 0) 2729 goto out; /* no-op, not an error */ 2730 2731 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2732 xoffset += texImage->Border; 2733 yoffset += texImage->Border; 2734 zoffset += texImage->Border; 2735 2736 ASSERT(ctx->Driver.TexSubImage3D); 2737 (*ctx->Driver.TexSubImage3D)(ctx, target, level, 2738 xoffset, yoffset, zoffset, 2739 width, height, depth, 2740 format, type, pixels, 2741 &ctx->Unpack, texObj, texImage ); 2742 ctx->NewState |= _NEW_TEXTURE; 2743 } 2744 out: 2745 _mesa_unlock_texture(ctx, texObj); 2746} 2747 2748 2749 2750void GLAPIENTRY 2751_mesa_CopyTexImage1D( GLenum target, GLint level, 2752 GLenum internalFormat, 2753 GLint x, GLint y, 2754 GLsizei width, GLint border ) 2755{ 2756 struct gl_texture_unit *texUnit; 2757 struct gl_texture_object *texObj; 2758 struct gl_texture_image *texImage; 2759 GLsizei postConvWidth = width; 2760 const GLuint face = texture_face(target); 2761 GET_CURRENT_CONTEXT(ctx); 2762 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2763 2764 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2765 _mesa_update_state(ctx); 2766 2767 if (is_color_format(internalFormat)) { 2768 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2769 } 2770 2771 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 2772 postConvWidth, 1, border)) 2773 return; 2774 2775 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2776 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2777 _mesa_lock_texture(ctx, texObj); 2778 { 2779 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2780 if (!texImage) { 2781 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 2782 goto out; 2783 } 2784 2785 if (texImage->Data) { 2786 ctx->Driver.FreeTexImageData( ctx, texImage ); 2787 } 2788 2789 ASSERT(texImage->Data == NULL); 2790 2791 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2792 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 2793 border, internalFormat); 2794 2795 2796 ASSERT(ctx->Driver.CopyTexImage1D); 2797 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 2798 x, y, width, border); 2799 2800 ASSERT(texImage->TexFormat); 2801 2802 update_fbo_texture(ctx, texObj, face, level); 2803 2804 /* state update */ 2805 texObj->Complete = GL_FALSE; 2806 ctx->NewState |= _NEW_TEXTURE; 2807 } 2808 out: 2809 _mesa_unlock_texture(ctx, texObj); 2810} 2811 2812 2813 2814void GLAPIENTRY 2815_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 2816 GLint x, GLint y, GLsizei width, GLsizei height, 2817 GLint border ) 2818{ 2819 struct gl_texture_unit *texUnit; 2820 struct gl_texture_object *texObj; 2821 struct gl_texture_image *texImage; 2822 GLsizei postConvWidth = width, postConvHeight = height; 2823 const GLuint face = texture_face(target); 2824 GET_CURRENT_CONTEXT(ctx); 2825 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2826 2827 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2828 _mesa_update_state(ctx); 2829 2830 if (is_color_format(internalFormat)) { 2831 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2832 &postConvHeight); 2833 } 2834 2835 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 2836 postConvWidth, postConvHeight, border)) 2837 return; 2838 2839 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2840 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2841 2842 _mesa_lock_texture(ctx, texObj); 2843 { 2844 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2845 2846 if (!texImage) { 2847 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 2848 goto out; 2849 } 2850 2851 if (texImage->Data) { 2852 ctx->Driver.FreeTexImageData( ctx, texImage ); 2853 } 2854 2855 ASSERT(texImage->Data == NULL); 2856 2857 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2858 _mesa_init_teximage_fields(ctx, target, texImage, 2859 postConvWidth, postConvHeight, 1, 2860 border, internalFormat); 2861 2862 ASSERT(ctx->Driver.CopyTexImage2D); 2863 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 2864 x, y, width, height, border); 2865 2866 ASSERT(texImage->TexFormat); 2867 2868 update_fbo_texture(ctx, texObj, face, level); 2869 2870 /* state update */ 2871 texObj->Complete = GL_FALSE; 2872 ctx->NewState |= _NEW_TEXTURE; 2873 } 2874 out: 2875 _mesa_unlock_texture(ctx, texObj); 2876} 2877 2878 2879void GLAPIENTRY 2880_mesa_CopyTexSubImage1D( GLenum target, GLint level, 2881 GLint xoffset, GLint x, GLint y, GLsizei width ) 2882{ 2883 struct gl_texture_unit *texUnit; 2884 struct gl_texture_object *texObj; 2885 struct gl_texture_image *texImage; 2886 GLsizei postConvWidth = width; 2887 GET_CURRENT_CONTEXT(ctx); 2888 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2889 2890 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2891 _mesa_update_state(ctx); 2892 2893 /* XXX should test internal format */ 2894 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2895 2896 if (copytexsubimage_error_check(ctx, 1, target, level, 2897 xoffset, 0, 0, postConvWidth, 1)) 2898 return; 2899 2900 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2901 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2902 2903 _mesa_lock_texture(ctx, texObj); 2904 { 2905 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2906 2907 if (copytexsubimage_error_check2(ctx, 1, target, level, 2908 xoffset, 0, 0, postConvWidth, 1, 2909 texImage)) 2910 goto out; 2911 2912 2913 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2914 xoffset += texImage->Border; 2915 2916 ASSERT(ctx->Driver.CopyTexSubImage1D); 2917 (*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, xoffset, x, y, width); 2918 ctx->NewState |= _NEW_TEXTURE; 2919 } 2920 out: 2921 _mesa_unlock_texture(ctx, texObj); 2922} 2923 2924 2925 2926void GLAPIENTRY 2927_mesa_CopyTexSubImage2D( GLenum target, GLint level, 2928 GLint xoffset, GLint yoffset, 2929 GLint x, GLint y, GLsizei width, GLsizei height ) 2930{ 2931 struct gl_texture_unit *texUnit; 2932 struct gl_texture_object *texObj; 2933 struct gl_texture_image *texImage; 2934 GLsizei postConvWidth = width, postConvHeight = height; 2935 GET_CURRENT_CONTEXT(ctx); 2936 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2937 2938 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2939 _mesa_update_state(ctx); 2940 2941 /* XXX should test internal format */ 2942 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 2943 2944 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2945 postConvWidth, postConvHeight)) 2946 return; 2947 2948 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2949 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2950 2951 _mesa_lock_texture(ctx, texObj); 2952 { 2953 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2954 2955 if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 2956 postConvWidth, postConvHeight, texImage)) 2957 goto out; 2958 2959 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2960 xoffset += texImage->Border; 2961 yoffset += texImage->Border; 2962 2963 ASSERT(ctx->Driver.CopyTexSubImage2D); 2964 (*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, 2965 xoffset, yoffset, x, y, width, height); 2966 ctx->NewState |= _NEW_TEXTURE; 2967 } 2968 out: 2969 _mesa_unlock_texture(ctx, texObj); 2970} 2971 2972 2973 2974void GLAPIENTRY 2975_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2976 GLint xoffset, GLint yoffset, GLint zoffset, 2977 GLint x, GLint y, GLsizei width, GLsizei height ) 2978{ 2979 struct gl_texture_unit *texUnit; 2980 struct gl_texture_object *texObj; 2981 struct gl_texture_image *texImage; 2982 GLsizei postConvWidth = width, postConvHeight = height; 2983 GET_CURRENT_CONTEXT(ctx); 2984 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2985 2986 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2987 _mesa_update_state(ctx); 2988 2989 /* XXX should test internal format */ 2990 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 2991 2992 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, 2993 zoffset, postConvWidth, postConvHeight)) 2994 return; 2995 2996 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2997 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2998 2999 _mesa_lock_texture(ctx, texObj); 3000 { 3001 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3002 3003 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 3004 zoffset, postConvWidth, postConvHeight, 3005 texImage)) 3006 goto out; 3007 3008 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3009 xoffset += texImage->Border; 3010 yoffset += texImage->Border; 3011 zoffset += texImage->Border; 3012 3013 ASSERT(ctx->Driver.CopyTexSubImage3D); 3014 (*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, 3015 xoffset, yoffset, zoffset, 3016 x, y, width, height); 3017 ctx->NewState |= _NEW_TEXTURE; 3018 } 3019 out: 3020 _mesa_unlock_texture(ctx, texObj); 3021} 3022 3023 3024 3025 3026/**********************************************************************/ 3027/****** Compressed Textures ******/ 3028/**********************************************************************/ 3029 3030 3031/** 3032 * Error checking for glCompressedTexImage[123]D(). 3033 * \return error code or GL_NO_ERROR. 3034 */ 3035static GLenum 3036compressed_texture_error_check(GLcontext *ctx, GLint dimensions, 3037 GLenum target, GLint level, 3038 GLenum internalFormat, GLsizei width, 3039 GLsizei height, GLsizei depth, GLint border, 3040 GLsizei imageSize) 3041{ 3042 GLint expectedSize, maxLevels = 0, maxTextureSize; 3043 3044 if (dimensions == 1) { 3045 /* 1D compressed textures not allowed */ 3046 return GL_INVALID_ENUM; 3047 } 3048 else if (dimensions == 2) { 3049 if (target == GL_PROXY_TEXTURE_2D) { 3050 maxLevels = ctx->Const.MaxTextureLevels; 3051 } 3052 else if (target == GL_TEXTURE_2D) { 3053 maxLevels = ctx->Const.MaxTextureLevels; 3054 } 3055 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3056 if (!ctx->Extensions.ARB_texture_cube_map) 3057 return GL_INVALID_ENUM; /*target*/ 3058 maxLevels = ctx->Const.MaxCubeTextureLevels; 3059 } 3060 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3061 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3062 if (!ctx->Extensions.ARB_texture_cube_map) 3063 return GL_INVALID_ENUM; /*target*/ 3064 maxLevels = ctx->Const.MaxCubeTextureLevels; 3065 } 3066 else { 3067 return GL_INVALID_ENUM; /*target*/ 3068 } 3069 } 3070 else if (dimensions == 3) { 3071 /* 3D compressed textures not allowed */ 3072 return GL_INVALID_ENUM; 3073 } 3074 3075 maxTextureSize = 1 << (maxLevels - 1); 3076 3077 /* This will detect any invalid internalFormat value */ 3078 if (!is_compressed_format(ctx, internalFormat)) 3079 return GL_INVALID_ENUM; 3080 3081 /* This should really never fail */ 3082 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 3083 return GL_INVALID_ENUM; 3084 3085 if (border != 0) 3086 return GL_INVALID_VALUE; 3087 3088 /* 3089 * XXX We should probably use the proxy texture error check function here. 3090 */ 3091 if (width < 1 || width > maxTextureSize || 3092 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1)) 3093 return GL_INVALID_VALUE; 3094 3095 if ((height < 1 || height > maxTextureSize || 3096 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1)) 3097 && dimensions > 1) 3098 return GL_INVALID_VALUE; 3099 3100 if ((depth < 1 || depth > maxTextureSize || 3101 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1)) 3102 && dimensions > 2) 3103 return GL_INVALID_VALUE; 3104 3105 /* For cube map, width must equal height */ 3106 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3107 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 3108 return GL_INVALID_VALUE; 3109 3110 if (level < 0 || level >= maxLevels) 3111 return GL_INVALID_VALUE; 3112 3113 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3114 depth, internalFormat); 3115 if (expectedSize != imageSize) 3116 return GL_INVALID_VALUE; 3117 3118#if FEATURE_EXT_texture_sRGB 3119 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 3120 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 3121 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 3122 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 3123 && border != 0) { 3124 return GL_INVALID_OPERATION; 3125 } 3126#endif 3127 3128 return GL_NO_ERROR; 3129} 3130 3131 3132/** 3133 * Error checking for glCompressedTexSubImage[123]D(). 3134 * \warning There are some bad assumptions here about the size of compressed 3135 * texture tiles (multiple of 4) used to test the validity of the 3136 * offset and size parameters. 3137 * \return error code or GL_NO_ERROR. 3138 */ 3139static GLenum 3140compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 3141 GLenum target, GLint level, 3142 GLint xoffset, GLint yoffset, GLint zoffset, 3143 GLsizei width, GLsizei height, GLsizei depth, 3144 GLenum format, GLsizei imageSize) 3145{ 3146 GLint expectedSize, maxLevels = 0, maxTextureSize; 3147 (void) zoffset; 3148 3149 if (dimensions == 1) { 3150 /* 1D compressed textures not allowed */ 3151 return GL_INVALID_ENUM; 3152 } 3153 else if (dimensions == 2) { 3154 if (target == GL_PROXY_TEXTURE_2D) { 3155 maxLevels = ctx->Const.MaxTextureLevels; 3156 } 3157 else if (target == GL_TEXTURE_2D) { 3158 maxLevels = ctx->Const.MaxTextureLevels; 3159 } 3160 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3161 if (!ctx->Extensions.ARB_texture_cube_map) 3162 return GL_INVALID_ENUM; /*target*/ 3163 maxLevels = ctx->Const.MaxCubeTextureLevels; 3164 } 3165 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3166 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3167 if (!ctx->Extensions.ARB_texture_cube_map) 3168 return GL_INVALID_ENUM; /*target*/ 3169 maxLevels = ctx->Const.MaxCubeTextureLevels; 3170 } 3171 else { 3172 return GL_INVALID_ENUM; /*target*/ 3173 } 3174 } 3175 else if (dimensions == 3) { 3176 /* 3D compressed textures not allowed */ 3177 return GL_INVALID_ENUM; 3178 } 3179 3180 maxTextureSize = 1 << (maxLevels - 1); 3181 3182 /* this will catch any invalid compressed format token */ 3183 if (!is_compressed_format(ctx, format)) 3184 return GL_INVALID_ENUM; 3185 3186 if (width < 1 || width > maxTextureSize) 3187 return GL_INVALID_VALUE; 3188 3189 if ((height < 1 || height > maxTextureSize) 3190 && dimensions > 1) 3191 return GL_INVALID_VALUE; 3192 3193 if (level < 0 || level >= maxLevels) 3194 return GL_INVALID_VALUE; 3195 3196 /* XXX these tests are specific to the compressed format. 3197 * this code should be generalized in some way. 3198 */ 3199 if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 3200 return GL_INVALID_VALUE; 3201 3202 if ((width & 3) != 0 && width != 2 && width != 1) 3203 return GL_INVALID_VALUE; 3204 3205 if ((height & 3) != 0 && height != 2 && height != 1) 3206 return GL_INVALID_VALUE; 3207 3208 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3209 depth, format); 3210 if (expectedSize != imageSize) 3211 return GL_INVALID_VALUE; 3212 3213 return GL_NO_ERROR; 3214} 3215 3216 3217 3218void GLAPIENTRY 3219_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 3220 GLenum internalFormat, GLsizei width, 3221 GLint border, GLsizei imageSize, 3222 const GLvoid *data) 3223{ 3224 GET_CURRENT_CONTEXT(ctx); 3225 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3226 3227 if (target == GL_TEXTURE_1D) { 3228 /* non-proxy target */ 3229 struct gl_texture_unit *texUnit; 3230 struct gl_texture_object *texObj; 3231 struct gl_texture_image *texImage; 3232 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3233 internalFormat, width, 1, 1, border, imageSize); 3234 if (error) { 3235 _mesa_error(ctx, error, "glCompressedTexImage1D"); 3236 return; 3237 } 3238 3239 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3240 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3241 3242 _mesa_lock_texture(ctx, texObj); 3243 { 3244 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3245 if (!texImage) { 3246 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 3247 goto out; 3248 } 3249 3250 if (texImage->Data) { 3251 ctx->Driver.FreeTexImageData( ctx, texImage ); 3252 } 3253 ASSERT(texImage->Data == NULL); 3254 3255 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3256 border, internalFormat); 3257 3258 ASSERT(ctx->Driver.CompressedTexImage1D); 3259 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 3260 internalFormat, width, border, 3261 imageSize, data, 3262 texObj, texImage); 3263 3264 /* state update */ 3265 texObj->Complete = GL_FALSE; 3266 ctx->NewState |= _NEW_TEXTURE; 3267 } 3268 out: 3269 _mesa_unlock_texture(ctx, texObj); 3270 } 3271 else if (target == GL_PROXY_TEXTURE_1D) { 3272 /* Proxy texture: check for errors and update proxy state */ 3273 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3274 internalFormat, width, 1, 1, border, imageSize); 3275 if (!error) { 3276 ASSERT(ctx->Driver.TestProxyTexImage); 3277 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3278 internalFormat, GL_NONE, GL_NONE, 3279 width, 1, 1, border); 3280 } 3281 if (error) { 3282 /* if error, clear all proxy texture image parameters */ 3283 struct gl_texture_image *texImage; 3284 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3285 if (texImage) 3286 clear_teximage_fields(texImage); 3287 } 3288 else { 3289 /* store the teximage parameters */ 3290 struct gl_texture_unit *texUnit; 3291 struct gl_texture_object *texObj; 3292 struct gl_texture_image *texImage; 3293 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3294 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3295 3296 _mesa_lock_texture(ctx, texObj); 3297 { 3298 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3299 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3300 border, internalFormat); 3301 } 3302 _mesa_unlock_texture(ctx, texObj); 3303 } 3304 } 3305 else { 3306 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 3307 return; 3308 } 3309} 3310 3311 3312void GLAPIENTRY 3313_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3314 GLenum internalFormat, GLsizei width, 3315 GLsizei height, GLint border, GLsizei imageSize, 3316 const GLvoid *data) 3317{ 3318 GET_CURRENT_CONTEXT(ctx); 3319 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3320 3321 if (target == GL_TEXTURE_2D || 3322 (ctx->Extensions.ARB_texture_cube_map && 3323 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3324 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 3325 /* non-proxy target */ 3326 struct gl_texture_unit *texUnit; 3327 struct gl_texture_object *texObj; 3328 struct gl_texture_image *texImage; 3329 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3330 internalFormat, width, height, 1, border, imageSize); 3331 if (error) { 3332 _mesa_error(ctx, error, "glCompressedTexImage2D"); 3333 return; 3334 } 3335 3336 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3337 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3338 3339 _mesa_lock_texture(ctx, texObj); 3340 { 3341 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3342 if (!texImage) { 3343 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 3344 goto out; 3345 } 3346 3347 if (texImage->Data) { 3348 ctx->Driver.FreeTexImageData( ctx, texImage ); 3349 } 3350 ASSERT(texImage->Data == NULL); 3351 3352 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3353 border, internalFormat); 3354 3355 ASSERT(ctx->Driver.CompressedTexImage2D); 3356 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 3357 internalFormat, width, height, 3358 border, imageSize, data, 3359 texObj, texImage); 3360 3361 /* state update */ 3362 texObj->Complete = GL_FALSE; 3363 ctx->NewState |= _NEW_TEXTURE; 3364 } 3365 out: 3366 _mesa_unlock_texture(ctx, texObj); 3367 } 3368 else if (target == GL_PROXY_TEXTURE_2D || 3369 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 3370 ctx->Extensions.ARB_texture_cube_map)) { 3371 /* Proxy texture: check for errors and update proxy state */ 3372 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3373 internalFormat, width, height, 1, border, imageSize); 3374 if (!error) { 3375 ASSERT(ctx->Driver.TestProxyTexImage); 3376 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3377 internalFormat, GL_NONE, GL_NONE, 3378 width, height, 1, border); 3379 } 3380 if (error) { 3381 /* if error, clear all proxy texture image parameters */ 3382 struct gl_texture_image *texImage; 3383 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3384 if (texImage) 3385 clear_teximage_fields(texImage); 3386 } 3387 else { 3388 /* store the teximage parameters */ 3389 struct gl_texture_unit *texUnit; 3390 struct gl_texture_object *texObj; 3391 struct gl_texture_image *texImage; 3392 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3393 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3394 3395 _mesa_lock_texture(ctx, texObj); 3396 { 3397 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3398 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3399 border, internalFormat); 3400 } 3401 _mesa_unlock_texture(ctx, texObj); 3402 } 3403 } 3404 else { 3405 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 3406 return; 3407 } 3408} 3409 3410 3411void GLAPIENTRY 3412_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3413 GLenum internalFormat, GLsizei width, 3414 GLsizei height, GLsizei depth, GLint border, 3415 GLsizei imageSize, const GLvoid *data) 3416{ 3417 GET_CURRENT_CONTEXT(ctx); 3418 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3419 3420 if (target == GL_TEXTURE_3D) { 3421 /* non-proxy target */ 3422 struct gl_texture_unit *texUnit; 3423 struct gl_texture_object *texObj; 3424 struct gl_texture_image *texImage; 3425 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3426 internalFormat, width, height, depth, border, imageSize); 3427 if (error) { 3428 _mesa_error(ctx, error, "glCompressedTexImage3D"); 3429 return; 3430 } 3431 3432 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3433 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3434 _mesa_lock_texture(ctx, texObj); 3435 { 3436 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3437 if (!texImage) { 3438 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 3439 goto out; 3440 } 3441 3442 if (texImage->Data) { 3443 ctx->Driver.FreeTexImageData( ctx, texImage ); 3444 } 3445 ASSERT(texImage->Data == NULL); 3446 3447 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 3448 border, internalFormat); 3449 3450 ASSERT(ctx->Driver.CompressedTexImage3D); 3451 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 3452 internalFormat, 3453 width, height, depth, 3454 border, imageSize, data, 3455 texObj, texImage); 3456 3457 /* state update */ 3458 texObj->Complete = GL_FALSE; 3459 ctx->NewState |= _NEW_TEXTURE; 3460 } 3461 out: 3462 _mesa_unlock_texture(ctx, texObj); 3463 } 3464 else if (target == GL_PROXY_TEXTURE_3D) { 3465 /* Proxy texture: check for errors and update proxy state */ 3466 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3467 internalFormat, width, height, depth, border, imageSize); 3468 if (!error) { 3469 ASSERT(ctx->Driver.TestProxyTexImage); 3470 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3471 internalFormat, GL_NONE, GL_NONE, 3472 width, height, depth, border); 3473 } 3474 if (error) { 3475 /* if error, clear all proxy texture image parameters */ 3476 struct gl_texture_image *texImage; 3477 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3478 if (texImage) 3479 clear_teximage_fields(texImage); 3480 } 3481 else { 3482 /* store the teximage parameters */ 3483 struct gl_texture_unit *texUnit; 3484 struct gl_texture_object *texObj; 3485 struct gl_texture_image *texImage; 3486 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3487 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3488 _mesa_lock_texture(ctx, texObj); 3489 { 3490 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3491 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 3492 depth, border, internalFormat); 3493 } 3494 _mesa_unlock_texture(ctx, texObj); 3495 } 3496 } 3497 else { 3498 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 3499 return; 3500 } 3501} 3502 3503 3504void GLAPIENTRY 3505_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3506 GLsizei width, GLenum format, 3507 GLsizei imageSize, const GLvoid *data) 3508{ 3509 struct gl_texture_unit *texUnit; 3510 struct gl_texture_object *texObj; 3511 struct gl_texture_image *texImage; 3512 GLenum error; 3513 GET_CURRENT_CONTEXT(ctx); 3514 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3515 3516 error = compressed_subtexture_error_check(ctx, 1, target, level, 3517 xoffset, 0, 0, /* pos */ 3518 width, 1, 1, /* size */ 3519 format, imageSize); 3520 if (error) { 3521 _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 3522 return; 3523 } 3524 3525 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3526 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3527 _mesa_lock_texture(ctx, texObj); 3528 { 3529 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3530 assert(texImage); 3531 3532 if ((GLint) format != texImage->InternalFormat) { 3533 _mesa_error(ctx, GL_INVALID_OPERATION, 3534 "glCompressedTexSubImage1D(format)"); 3535 goto out; 3536 } 3537 3538 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 3539 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 3540 goto out; 3541 } 3542 3543 if (width == 0) 3544 goto out; /* no-op, not an error */ 3545 3546 if (ctx->Driver.CompressedTexSubImage1D) { 3547 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 3548 xoffset, width, 3549 format, imageSize, data, 3550 texObj, texImage); 3551 } 3552 ctx->NewState |= _NEW_TEXTURE; 3553 } 3554 out: 3555 _mesa_unlock_texture(ctx, texObj); 3556} 3557 3558 3559void GLAPIENTRY 3560_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3561 GLint yoffset, GLsizei width, GLsizei height, 3562 GLenum format, GLsizei imageSize, 3563 const GLvoid *data) 3564{ 3565 struct gl_texture_unit *texUnit; 3566 struct gl_texture_object *texObj; 3567 struct gl_texture_image *texImage; 3568 GLenum error; 3569 GET_CURRENT_CONTEXT(ctx); 3570 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3571 3572 error = compressed_subtexture_error_check(ctx, 2, target, level, 3573 xoffset, yoffset, 0, /* pos */ 3574 width, height, 1, /* size */ 3575 format, imageSize); 3576 if (error) { 3577 /* XXX proxy target? */ 3578 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 3579 return; 3580 } 3581 3582 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3583 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3584 _mesa_lock_texture(ctx, texObj); 3585 { 3586 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3587 assert(texImage); 3588 3589 if ((GLint) format != texImage->InternalFormat) { 3590 _mesa_error(ctx, GL_INVALID_OPERATION, 3591 "glCompressedTexSubImage2D(format)"); 3592 goto out; 3593 } 3594 3595 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3596 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 3597 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 3598 goto out; 3599 } 3600 3601 if (width == 0 || height == 0) 3602 goto out; /* no-op, not an error */ 3603 3604 if (ctx->Driver.CompressedTexSubImage2D) { 3605 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 3606 xoffset, yoffset, width, height, 3607 format, imageSize, data, 3608 texObj, texImage); 3609 } 3610 ctx->NewState |= _NEW_TEXTURE; 3611 } 3612 out: 3613 _mesa_unlock_texture(ctx, texObj); 3614} 3615 3616 3617void GLAPIENTRY 3618_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3619 GLint yoffset, GLint zoffset, GLsizei width, 3620 GLsizei height, GLsizei depth, GLenum format, 3621 GLsizei imageSize, const GLvoid *data) 3622{ 3623 struct gl_texture_unit *texUnit; 3624 struct gl_texture_object *texObj; 3625 struct gl_texture_image *texImage; 3626 GLenum error; 3627 GET_CURRENT_CONTEXT(ctx); 3628 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3629 3630 error = compressed_subtexture_error_check(ctx, 3, target, level, 3631 xoffset, yoffset, zoffset,/*pos*/ 3632 width, height, depth, /*size*/ 3633 format, imageSize); 3634 if (error) { 3635 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 3636 return; 3637 } 3638 3639 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3640 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3641 _mesa_lock_texture(ctx, texObj); 3642 { 3643 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3644 assert(texImage); 3645 3646 if ((GLint) format != texImage->InternalFormat) { 3647 _mesa_error(ctx, GL_INVALID_OPERATION, 3648 "glCompressedTexSubImage3D(format)"); 3649 goto out; 3650 } 3651 3652 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3653 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 3654 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 3655 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 3656 goto out; 3657 } 3658 3659 if (width == 0 || height == 0 || depth == 0) 3660 goto out; /* no-op, not an error */ 3661 3662 if (ctx->Driver.CompressedTexSubImage3D) { 3663 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 3664 xoffset, yoffset, zoffset, 3665 width, height, depth, 3666 format, imageSize, data, 3667 texObj, texImage); 3668 } 3669 ctx->NewState |= _NEW_TEXTURE; 3670 } 3671 out: 3672 _mesa_unlock_texture(ctx, texObj); 3673} 3674 3675 3676void GLAPIENTRY 3677_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 3678{ 3679 const struct gl_texture_unit *texUnit; 3680 struct gl_texture_object *texObj; 3681 struct gl_texture_image *texImage; 3682 GLint maxLevels; 3683 GET_CURRENT_CONTEXT(ctx); 3684 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3685 3686 3687 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3688 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3689 if (!texObj) { 3690 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 3691 return; 3692 } 3693 3694 maxLevels = _mesa_max_texture_levels(ctx, target); 3695 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 3696 3697 if (level < 0 || level >= maxLevels) { 3698 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 3699 return; 3700 } 3701 3702 if (_mesa_is_proxy_texture(target)) { 3703 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 3704 return; 3705 } 3706 3707 3708 _mesa_lock_texture(ctx, texObj); 3709 { 3710 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3711 if (!texImage) { 3712 /* probably invalid mipmap level */ 3713 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 3714 goto out; 3715 } 3716 3717 if (!texImage->IsCompressed) { 3718 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB"); 3719 goto out; 3720 } 3721 3722 /* this typically calls _mesa_get_compressed_teximage() */ 3723 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, texObj,texImage); 3724 } 3725 out: 3726 _mesa_unlock_texture(ctx, texObj); 3727} 3728