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