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