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