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