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