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