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