teximage.c revision c80a380ebb58c15db87309d466ef57fb006b40ae
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 _mesa_lock_texture(ctx, texObj); 2327 { 2328 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2329 if (!texImage) { 2330 /* invalid mipmap level, not an error */ 2331 goto out; 2332 } 2333 2334 2335 /* Make sure the requested image format is compatible with the 2336 * texture's format. Note that a color index texture can be converted 2337 * to RGBA so that combo is allowed. 2338 */ 2339 if (is_color_format(format) 2340 && !is_color_format(texImage->TexFormat->BaseFormat) 2341 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2342 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2343 goto out; 2344 } 2345 else if (is_index_format(format) 2346 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2347 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2348 goto out; 2349 } 2350 else if (is_depth_format(format) 2351 && !is_depth_format(texImage->TexFormat->BaseFormat) 2352 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2353 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2354 goto out; 2355 } 2356 else if (is_ycbcr_format(format) 2357 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 2358 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2359 goto out; 2360 } 2361 else if (is_depthstencil_format(format) 2362 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2363 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2364 goto out; 2365 } 2366 2367 if (ctx->Pack.BufferObj->Name) { 2368 /* packing texture image into a PBO */ 2369 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 2370 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 2371 texImage->Height, texImage->Depth, 2372 format, type, pixels)) { 2373 _mesa_error(ctx, GL_INVALID_OPERATION, 2374 "glGetTexImage(invalid PBO access)"); 2375 goto out; 2376 } 2377 } 2378 2379 /* typically, this will call _mesa_get_teximage() */ 2380 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 2381 texObj, texImage); 2382 2383 } 2384 out: 2385 _mesa_unlock_texture(ctx, texObj); 2386} 2387 2388 2389 2390/** 2391 * Check if the given texture image is bound to any framebuffer objects 2392 * and update/invalidate them. 2393 * XXX We're only checking the currently bound framebuffer object for now. 2394 * In the future, perhaps struct gl_texture_image should have a pointer (or 2395 * list of pointers (yikes)) to the gl_framebuffer(s) which it's bound to. 2396 */ 2397static void 2398update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 2399 GLuint face, GLuint level) 2400{ 2401 if (ctx->DrawBuffer->Name) { 2402 GLuint i; 2403 for (i = 0; i < BUFFER_COUNT; i++) { 2404 struct gl_renderbuffer_attachment *att = 2405 ctx->DrawBuffer->Attachment + i; 2406 if (att->Type == GL_TEXTURE && 2407 att->Texture == texObj && 2408 att->TextureLevel == level && 2409 att->CubeMapFace == face) { 2410 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 2411 /* Tell driver about the new renderbuffer texture */ 2412 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 2413 } 2414 } 2415 } 2416} 2417 2418 2419 2420/* 2421 * Called from the API. Note that width includes the border. 2422 */ 2423void GLAPIENTRY 2424_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 2425 GLsizei width, GLint border, GLenum format, 2426 GLenum type, const GLvoid *pixels ) 2427{ 2428 GLsizei postConvWidth = width; 2429 GET_CURRENT_CONTEXT(ctx); 2430 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2431 2432 if (is_color_format(internalFormat)) { 2433 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2434 } 2435 2436 if (target == GL_TEXTURE_1D) { 2437 /* non-proxy target */ 2438 struct gl_texture_unit *texUnit; 2439 struct gl_texture_object *texObj; 2440 struct gl_texture_image *texImage; 2441 const GLuint face = _mesa_tex_target_to_face(target); 2442 2443 if (texture_error_check(ctx, target, level, internalFormat, 2444 format, type, 1, postConvWidth, 1, 1, border)) { 2445 return; /* error was recorded */ 2446 } 2447 2448 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2449 _mesa_update_state(ctx); 2450 2451 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2452 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2453 _mesa_lock_texture(ctx, texObj); 2454 { 2455 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2456 if (!texImage) { 2457 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2458 goto out; 2459 } 2460 2461 if (texImage->Data) { 2462 ctx->Driver.FreeTexImageData( ctx, texImage ); 2463 } 2464 2465 ASSERT(texImage->Data == NULL); 2466 2467 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2468 _mesa_init_teximage_fields(ctx, target, texImage, 2469 postConvWidth, 1, 1, 2470 border, internalFormat); 2471 2472 ASSERT(ctx->Driver.TexImage1D); 2473 2474 /* Give the texture to the driver! <pixels> may be null! */ 2475 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 2476 width, border, format, type, pixels, 2477 &ctx->Unpack, texObj, texImage); 2478 2479 ASSERT(texImage->TexFormat); 2480 2481 update_fbo_texture(ctx, texObj, face, level); 2482 2483 /* state update */ 2484 texObj->_Complete = GL_FALSE; 2485 ctx->NewState |= _NEW_TEXTURE; 2486 } 2487 out: 2488 _mesa_unlock_texture(ctx, texObj); 2489 } 2490 else if (target == GL_PROXY_TEXTURE_1D) { 2491 /* Proxy texture: check for errors and update proxy state */ 2492 struct gl_texture_image *texImage; 2493 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2494 if (texture_error_check(ctx, target, level, internalFormat, 2495 format, type, 1, postConvWidth, 1, 1, border)) { 2496 /* when error, clear all proxy texture image parameters */ 2497 if (texImage) 2498 clear_teximage_fields(texImage); 2499 } 2500 else { 2501 /* no error, set the tex image parameters */ 2502 ASSERT(texImage); 2503 _mesa_init_teximage_fields(ctx, target, texImage, 2504 postConvWidth, 1, 1, 2505 border, internalFormat); 2506 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2507 internalFormat, format, type); 2508 } 2509 } 2510 else { 2511 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 2512 return; 2513 } 2514} 2515 2516 2517void GLAPIENTRY 2518_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 2519 GLsizei width, GLsizei height, GLint border, 2520 GLenum format, GLenum type, 2521 const GLvoid *pixels ) 2522{ 2523 GLsizei postConvWidth = width, postConvHeight = height; 2524 GET_CURRENT_CONTEXT(ctx); 2525 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2526 2527 if (is_color_format(internalFormat)) { 2528 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2529 &postConvHeight); 2530 } 2531 2532 if (target == GL_TEXTURE_2D || 2533 (ctx->Extensions.ARB_texture_cube_map && 2534 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2535 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 2536 (ctx->Extensions.NV_texture_rectangle && 2537 target == GL_TEXTURE_RECTANGLE_NV) || 2538 (ctx->Extensions.MESA_texture_array && 2539 target == GL_TEXTURE_1D_ARRAY_EXT)) { 2540 /* non-proxy target */ 2541 struct gl_texture_unit *texUnit; 2542 struct gl_texture_object *texObj; 2543 struct gl_texture_image *texImage; 2544 const GLuint face = _mesa_tex_target_to_face(target); 2545 2546 if (texture_error_check(ctx, target, level, internalFormat, 2547 format, type, 2, postConvWidth, postConvHeight, 2548 1, border)) { 2549 return; /* error was recorded */ 2550 } 2551 2552 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2553 _mesa_update_state(ctx); 2554 2555 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2556 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2557 _mesa_lock_texture(ctx, texObj); 2558 { 2559 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2560 if (!texImage) { 2561 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2562 goto out; 2563 } 2564 2565 if (texImage->Data) { 2566 ctx->Driver.FreeTexImageData( ctx, texImage ); 2567 } 2568 2569 ASSERT(texImage->Data == NULL); 2570 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2571 _mesa_init_teximage_fields(ctx, target, texImage, 2572 postConvWidth, postConvHeight, 1, 2573 border, internalFormat); 2574 2575 ASSERT(ctx->Driver.TexImage2D); 2576 2577 /* Give the texture to the driver! <pixels> may be null! */ 2578 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 2579 width, height, border, format, type, pixels, 2580 &ctx->Unpack, texObj, texImage); 2581 2582 ASSERT(texImage->TexFormat); 2583 2584 update_fbo_texture(ctx, texObj, face, level); 2585 2586 /* state update */ 2587 texObj->_Complete = GL_FALSE; 2588 ctx->NewState |= _NEW_TEXTURE; 2589 } 2590 out: 2591 _mesa_unlock_texture(ctx, texObj); 2592 } 2593 else if (target == GL_PROXY_TEXTURE_2D || 2594 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 2595 ctx->Extensions.ARB_texture_cube_map) || 2596 (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2597 ctx->Extensions.NV_texture_rectangle) || 2598 (ctx->Extensions.MESA_texture_array && 2599 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 2600 /* Proxy texture: check for errors and update proxy state */ 2601 struct gl_texture_image *texImage; 2602 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2603 if (texture_error_check(ctx, target, level, internalFormat, 2604 format, type, 2, postConvWidth, postConvHeight, 2605 1, border)) { 2606 /* when error, clear all proxy texture image parameters */ 2607 if (texImage) 2608 clear_teximage_fields(ctx->Texture.Proxy2D->Image[0][level]); 2609 } 2610 else { 2611 /* no error, set the tex image parameters */ 2612 _mesa_init_teximage_fields(ctx, target, texImage, 2613 postConvWidth, postConvHeight, 1, 2614 border, internalFormat); 2615 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2616 internalFormat, format, type); 2617 } 2618 } 2619 else { 2620 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 2621 return; 2622 } 2623} 2624 2625 2626/* 2627 * Called by the API or display list executor. 2628 * Note that width and height include the border. 2629 */ 2630void GLAPIENTRY 2631_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 2632 GLsizei width, GLsizei height, GLsizei depth, 2633 GLint border, GLenum format, GLenum type, 2634 const GLvoid *pixels ) 2635{ 2636 GET_CURRENT_CONTEXT(ctx); 2637 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2638 2639 if (target == GL_TEXTURE_3D || 2640 (ctx->Extensions.MESA_texture_array && 2641 target == GL_TEXTURE_2D_ARRAY_EXT)) { 2642 /* non-proxy target */ 2643 struct gl_texture_unit *texUnit; 2644 struct gl_texture_object *texObj; 2645 struct gl_texture_image *texImage; 2646 const GLuint face = _mesa_tex_target_to_face(target); 2647 2648 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 2649 format, type, 3, width, height, depth, border)) { 2650 return; /* error was recorded */ 2651 } 2652 2653 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2654 _mesa_update_state(ctx); 2655 2656 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2657 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2658 _mesa_lock_texture(ctx, texObj); 2659 { 2660 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2661 if (!texImage) { 2662 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2663 goto out; 2664 } 2665 2666 if (texImage->Data) { 2667 ctx->Driver.FreeTexImageData( ctx, texImage ); 2668 } 2669 2670 ASSERT(texImage->Data == NULL); 2671 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2672 _mesa_init_teximage_fields(ctx, target, texImage, 2673 width, height, depth, 2674 border, internalFormat); 2675 2676 ASSERT(ctx->Driver.TexImage3D); 2677 2678 /* Give the texture to the driver! <pixels> may be null! */ 2679 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 2680 width, height, depth, border, format, type, 2681 pixels, &ctx->Unpack, texObj, texImage); 2682 2683 ASSERT(texImage->TexFormat); 2684 2685 update_fbo_texture(ctx, texObj, face, level); 2686 2687 /* state update */ 2688 texObj->_Complete = GL_FALSE; 2689 ctx->NewState |= _NEW_TEXTURE; 2690 } 2691 out: 2692 _mesa_unlock_texture(ctx, texObj); 2693 } 2694 else if (target == GL_PROXY_TEXTURE_3D || 2695 (ctx->Extensions.MESA_texture_array && 2696 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 2697 /* Proxy texture: check for errors and update proxy state */ 2698 struct gl_texture_image *texImage; 2699 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2700 if (texture_error_check(ctx, target, level, internalFormat, 2701 format, type, 3, width, height, depth, border)) { 2702 /* when error, clear all proxy texture image parameters */ 2703 if (texImage) 2704 clear_teximage_fields(texImage); 2705 } 2706 else { 2707 /* no error, set the tex image parameters */ 2708 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 2709 border, internalFormat); 2710 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2711 internalFormat, format, type); 2712 } 2713 } 2714 else { 2715 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 2716 return; 2717 } 2718} 2719 2720 2721void GLAPIENTRY 2722_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2723 GLsizei width, GLsizei height, GLsizei depth, 2724 GLint border, GLenum format, GLenum type, 2725 const GLvoid *pixels ) 2726{ 2727 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2728 depth, border, format, type, pixels); 2729} 2730 2731 2732 2733void GLAPIENTRY 2734_mesa_TexSubImage1D( GLenum target, GLint level, 2735 GLint xoffset, GLsizei width, 2736 GLenum format, GLenum type, 2737 const GLvoid *pixels ) 2738{ 2739 GLsizei postConvWidth = width; 2740 struct gl_texture_unit *texUnit; 2741 struct gl_texture_object *texObj; 2742 struct gl_texture_image *texImage = NULL; 2743 GET_CURRENT_CONTEXT(ctx); 2744 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2745 2746 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2747 _mesa_update_state(ctx); 2748 2749 /* XXX should test internal format */ 2750 if (is_color_format(format)) { 2751 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2752 } 2753 2754 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2755 postConvWidth, 1, 1, format, type)) { 2756 return; /* error was detected */ 2757 } 2758 2759 2760 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2761 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2762 assert(texObj); 2763 2764 _mesa_lock_texture(ctx, texObj); 2765 { 2766 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2767 2768 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 2769 postConvWidth, 1, 1, format, type, texImage)) { 2770 goto out; /* error was detected */ 2771 } 2772 2773 if (width == 0) 2774 goto out; /* no-op, not an error */ 2775 2776 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2777 xoffset += texImage->Border; 2778 2779 ASSERT(ctx->Driver.TexSubImage1D); 2780 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 2781 format, type, pixels, &ctx->Unpack, 2782 texObj, texImage); 2783 ctx->NewState |= _NEW_TEXTURE; 2784 } 2785 out: 2786 _mesa_unlock_texture(ctx, texObj); 2787} 2788 2789 2790void GLAPIENTRY 2791_mesa_TexSubImage2D( GLenum target, GLint level, 2792 GLint xoffset, GLint yoffset, 2793 GLsizei width, GLsizei height, 2794 GLenum format, GLenum type, 2795 const GLvoid *pixels ) 2796{ 2797 GLsizei postConvWidth = width, postConvHeight = height; 2798 struct gl_texture_unit *texUnit; 2799 struct gl_texture_object *texObj; 2800 struct gl_texture_image *texImage; 2801 GET_CURRENT_CONTEXT(ctx); 2802 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2803 2804 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2805 _mesa_update_state(ctx); 2806 2807 /* XXX should test internal format */ 2808 if (is_color_format(format)) { 2809 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2810 &postConvHeight); 2811 } 2812 2813 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2814 postConvWidth, postConvHeight, 1, format, type)) { 2815 return; /* error was detected */ 2816 } 2817 2818 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2819 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2820 _mesa_lock_texture(ctx, texObj); 2821 { 2822 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2823 2824 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 2825 postConvWidth, postConvHeight, 1, format, type, 2826 texImage)) { 2827 goto out; /* error was detected */ 2828 } 2829 2830 if (width == 0 || height == 0) 2831 goto out; /* no-op, not an error */ 2832 2833 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2834 xoffset += texImage->Border; 2835 yoffset += texImage->Border; 2836 2837 ASSERT(ctx->Driver.TexSubImage2D); 2838 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 2839 width, height, format, type, pixels, 2840 &ctx->Unpack, texObj, texImage); 2841 ctx->NewState |= _NEW_TEXTURE; 2842 } 2843 out: 2844 _mesa_unlock_texture(ctx, texObj); 2845} 2846 2847 2848 2849void GLAPIENTRY 2850_mesa_TexSubImage3D( GLenum target, GLint level, 2851 GLint xoffset, GLint yoffset, GLint zoffset, 2852 GLsizei width, GLsizei height, GLsizei depth, 2853 GLenum format, GLenum type, 2854 const GLvoid *pixels ) 2855{ 2856 struct gl_texture_unit *texUnit; 2857 struct gl_texture_object *texObj; 2858 struct gl_texture_image *texImage; 2859 GET_CURRENT_CONTEXT(ctx); 2860 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2861 2862 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2863 _mesa_update_state(ctx); 2864 2865 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2866 width, height, depth, format, type)) { 2867 return; /* error was detected */ 2868 } 2869 2870 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2871 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2872 2873 _mesa_lock_texture(ctx, texObj); 2874 { 2875 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2876 2877 if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 2878 width, height, depth, format, type, texImage)) { 2879 goto out; /* error was detected */ 2880 } 2881 2882 if (width == 0 || height == 0 || height == 0) 2883 goto out; /* no-op, not an error */ 2884 2885 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2886 xoffset += texImage->Border; 2887 yoffset += texImage->Border; 2888 zoffset += texImage->Border; 2889 2890 ASSERT(ctx->Driver.TexSubImage3D); 2891 (*ctx->Driver.TexSubImage3D)(ctx, target, level, 2892 xoffset, yoffset, zoffset, 2893 width, height, depth, 2894 format, type, pixels, 2895 &ctx->Unpack, texObj, texImage ); 2896 ctx->NewState |= _NEW_TEXTURE; 2897 } 2898 out: 2899 _mesa_unlock_texture(ctx, texObj); 2900} 2901 2902 2903 2904void GLAPIENTRY 2905_mesa_CopyTexImage1D( GLenum target, GLint level, 2906 GLenum internalFormat, 2907 GLint x, GLint y, 2908 GLsizei width, GLint border ) 2909{ 2910 struct gl_texture_unit *texUnit; 2911 struct gl_texture_object *texObj; 2912 struct gl_texture_image *texImage; 2913 GLsizei postConvWidth = width; 2914 const GLuint face = _mesa_tex_target_to_face(target); 2915 GET_CURRENT_CONTEXT(ctx); 2916 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2917 2918 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2919 _mesa_update_state(ctx); 2920 2921 if (is_color_format(internalFormat)) { 2922 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2923 } 2924 2925 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 2926 postConvWidth, 1, border)) 2927 return; 2928 2929 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2930 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2931 _mesa_lock_texture(ctx, texObj); 2932 { 2933 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2934 if (!texImage) { 2935 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 2936 goto out; 2937 } 2938 2939 if (texImage->Data) { 2940 ctx->Driver.FreeTexImageData( ctx, texImage ); 2941 } 2942 2943 ASSERT(texImage->Data == NULL); 2944 2945 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2946 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 2947 border, internalFormat); 2948 2949 2950 ASSERT(ctx->Driver.CopyTexImage1D); 2951 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 2952 x, y, width, border); 2953 2954 ASSERT(texImage->TexFormat); 2955 2956 update_fbo_texture(ctx, texObj, face, level); 2957 2958 /* state update */ 2959 texObj->_Complete = GL_FALSE; 2960 ctx->NewState |= _NEW_TEXTURE; 2961 } 2962 out: 2963 _mesa_unlock_texture(ctx, texObj); 2964} 2965 2966 2967 2968void GLAPIENTRY 2969_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 2970 GLint x, GLint y, GLsizei width, GLsizei height, 2971 GLint border ) 2972{ 2973 struct gl_texture_unit *texUnit; 2974 struct gl_texture_object *texObj; 2975 struct gl_texture_image *texImage; 2976 GLsizei postConvWidth = width, postConvHeight = height; 2977 const GLuint face = _mesa_tex_target_to_face(target); 2978 GET_CURRENT_CONTEXT(ctx); 2979 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2980 2981 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 2982 _mesa_update_state(ctx); 2983 2984 if (is_color_format(internalFormat)) { 2985 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2986 &postConvHeight); 2987 } 2988 2989 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 2990 postConvWidth, postConvHeight, border)) 2991 return; 2992 2993 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2994 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2995 2996 _mesa_lock_texture(ctx, texObj); 2997 { 2998 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2999 3000 if (!texImage) { 3001 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 3002 goto out; 3003 } 3004 3005 if (texImage->Data) { 3006 ctx->Driver.FreeTexImageData( ctx, texImage ); 3007 } 3008 3009 ASSERT(texImage->Data == NULL); 3010 3011 clear_teximage_fields(texImage); /* not really needed, but helpful */ 3012 _mesa_init_teximage_fields(ctx, target, texImage, 3013 postConvWidth, postConvHeight, 1, 3014 border, internalFormat); 3015 3016 ASSERT(ctx->Driver.CopyTexImage2D); 3017 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 3018 x, y, width, height, border); 3019 3020 ASSERT(texImage->TexFormat); 3021 3022 update_fbo_texture(ctx, texObj, face, level); 3023 3024 /* state update */ 3025 texObj->_Complete = GL_FALSE; 3026 ctx->NewState |= _NEW_TEXTURE; 3027 } 3028 out: 3029 _mesa_unlock_texture(ctx, texObj); 3030} 3031 3032 3033void GLAPIENTRY 3034_mesa_CopyTexSubImage1D( GLenum target, GLint level, 3035 GLint xoffset, GLint x, GLint y, GLsizei width ) 3036{ 3037 struct gl_texture_unit *texUnit; 3038 struct gl_texture_object *texObj; 3039 struct gl_texture_image *texImage; 3040 GLsizei postConvWidth = width; 3041 GLint yoffset = 0; 3042 GLsizei height = 1; 3043 3044 GET_CURRENT_CONTEXT(ctx); 3045 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3046 3047 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 3048 _mesa_update_state(ctx); 3049 3050 /* XXX should test internal format */ 3051 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 3052 3053 if (copytexsubimage_error_check(ctx, 1, target, level, 3054 xoffset, 0, 0, postConvWidth, 1)) 3055 return; 3056 3057 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3058 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3059 3060 _mesa_lock_texture(ctx, texObj); 3061 { 3062 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3063 3064 if (copytexsubimage_error_check2(ctx, 1, target, level, 3065 xoffset, 0, 0, postConvWidth, 1, 3066 texImage)) 3067 goto out; 3068 3069 3070 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3071 xoffset += texImage->Border; 3072 3073 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3074 &width, &height)) { 3075 ASSERT(ctx->Driver.CopyTexSubImage1D); 3076 ctx->Driver.CopyTexSubImage1D(ctx, target, level, 3077 xoffset, x, y, width); 3078 } 3079 3080 ctx->NewState |= _NEW_TEXTURE; 3081 } 3082 out: 3083 _mesa_unlock_texture(ctx, texObj); 3084} 3085 3086 3087 3088void GLAPIENTRY 3089_mesa_CopyTexSubImage2D( GLenum target, GLint level, 3090 GLint xoffset, GLint yoffset, 3091 GLint x, GLint y, GLsizei width, GLsizei height ) 3092{ 3093 struct gl_texture_unit *texUnit; 3094 struct gl_texture_object *texObj; 3095 struct gl_texture_image *texImage; 3096 GLsizei postConvWidth = width, postConvHeight = height; 3097 GET_CURRENT_CONTEXT(ctx); 3098 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3099 3100 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 3101 _mesa_update_state(ctx); 3102 3103 /* XXX should test internal format */ 3104 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 3105 3106 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 3107 postConvWidth, postConvHeight)) 3108 return; 3109 3110 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3111 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3112 3113 _mesa_lock_texture(ctx, texObj); 3114 { 3115 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3116 3117 if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 3118 postConvWidth, postConvHeight, texImage)) 3119 goto out; 3120 3121 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3122 xoffset += texImage->Border; 3123 yoffset += texImage->Border; 3124 3125 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3126 &width, &height)) { 3127 ASSERT(ctx->Driver.CopyTexSubImage2D); 3128 ctx->Driver.CopyTexSubImage2D(ctx, target, level, 3129 xoffset, yoffset, x, y, width, height); 3130 } 3131 3132 ctx->NewState |= _NEW_TEXTURE; 3133 } 3134 out: 3135 _mesa_unlock_texture(ctx, texObj); 3136} 3137 3138 3139 3140void GLAPIENTRY 3141_mesa_CopyTexSubImage3D( GLenum target, GLint level, 3142 GLint xoffset, GLint yoffset, GLint zoffset, 3143 GLint x, GLint y, GLsizei width, GLsizei height ) 3144{ 3145 struct gl_texture_unit *texUnit; 3146 struct gl_texture_object *texObj; 3147 struct gl_texture_image *texImage; 3148 GLsizei postConvWidth = width, postConvHeight = height; 3149 GET_CURRENT_CONTEXT(ctx); 3150 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3151 3152 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 3153 _mesa_update_state(ctx); 3154 3155 /* XXX should test internal format */ 3156 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, &postConvHeight); 3157 3158 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset, 3159 zoffset, postConvWidth, postConvHeight)) 3160 return; 3161 3162 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3163 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3164 3165 _mesa_lock_texture(ctx, texObj); 3166 { 3167 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3168 3169 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 3170 zoffset, postConvWidth, postConvHeight, 3171 texImage)) 3172 goto out; 3173 3174 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3175 xoffset += texImage->Border; 3176 yoffset += texImage->Border; 3177 zoffset += texImage->Border; 3178 3179 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3180 &width, &height)) { 3181 ASSERT(ctx->Driver.CopyTexSubImage3D); 3182 ctx->Driver.CopyTexSubImage3D(ctx, target, level, 3183 xoffset, yoffset, zoffset, 3184 x, y, width, height); 3185 } 3186 3187 ctx->NewState |= _NEW_TEXTURE; 3188 } 3189 out: 3190 _mesa_unlock_texture(ctx, texObj); 3191} 3192 3193 3194 3195 3196/**********************************************************************/ 3197/****** Compressed Textures ******/ 3198/**********************************************************************/ 3199 3200 3201/** 3202 * Error checking for glCompressedTexImage[123]D(). 3203 * \return error code or GL_NO_ERROR. 3204 */ 3205static GLenum 3206compressed_texture_error_check(GLcontext *ctx, GLint dimensions, 3207 GLenum target, GLint level, 3208 GLenum internalFormat, GLsizei width, 3209 GLsizei height, GLsizei depth, GLint border, 3210 GLsizei imageSize) 3211{ 3212 GLint expectedSize, maxLevels = 0, maxTextureSize; 3213 3214 if (dimensions == 1) { 3215 /* 1D compressed textures not allowed */ 3216 return GL_INVALID_ENUM; 3217 } 3218 else if (dimensions == 2) { 3219 if (target == GL_PROXY_TEXTURE_2D) { 3220 maxLevels = ctx->Const.MaxTextureLevels; 3221 } 3222 else if (target == GL_TEXTURE_2D) { 3223 maxLevels = ctx->Const.MaxTextureLevels; 3224 } 3225 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3226 if (!ctx->Extensions.ARB_texture_cube_map) 3227 return GL_INVALID_ENUM; /*target*/ 3228 maxLevels = ctx->Const.MaxCubeTextureLevels; 3229 } 3230 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3231 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3232 if (!ctx->Extensions.ARB_texture_cube_map) 3233 return GL_INVALID_ENUM; /*target*/ 3234 maxLevels = ctx->Const.MaxCubeTextureLevels; 3235 } 3236 else { 3237 return GL_INVALID_ENUM; /*target*/ 3238 } 3239 } 3240 else if (dimensions == 3) { 3241 /* 3D compressed textures not allowed */ 3242 return GL_INVALID_ENUM; 3243 } 3244 3245 maxTextureSize = 1 << (maxLevels - 1); 3246 3247 /* This will detect any invalid internalFormat value */ 3248 if (!is_compressed_format(ctx, internalFormat)) 3249 return GL_INVALID_ENUM; 3250 3251 /* This should really never fail */ 3252 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 3253 return GL_INVALID_ENUM; 3254 3255 if (border != 0) 3256 return GL_INVALID_VALUE; 3257 3258 /* 3259 * XXX We should probably use the proxy texture error check function here. 3260 */ 3261 if (width < 1 || width > maxTextureSize || 3262 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(width) != 1)) 3263 return GL_INVALID_VALUE; 3264 3265 if ((height < 1 || height > maxTextureSize || 3266 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(height) != 1)) 3267 && dimensions > 1) 3268 return GL_INVALID_VALUE; 3269 3270 if ((depth < 1 || depth > maxTextureSize || 3271 (!ctx->Extensions.ARB_texture_non_power_of_two && _mesa_bitcount(depth) != 1)) 3272 && dimensions > 2) 3273 return GL_INVALID_VALUE; 3274 3275 /* For cube map, width must equal height */ 3276 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3277 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 3278 return GL_INVALID_VALUE; 3279 3280 if (level < 0 || level >= maxLevels) 3281 return GL_INVALID_VALUE; 3282 3283 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3284 depth, internalFormat); 3285 if (expectedSize != imageSize) 3286 return GL_INVALID_VALUE; 3287 3288#if FEATURE_EXT_texture_sRGB 3289 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 3290 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 3291 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 3292 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 3293 && border != 0) { 3294 return GL_INVALID_OPERATION; 3295 } 3296#endif 3297 3298 return GL_NO_ERROR; 3299} 3300 3301 3302/** 3303 * Error checking for glCompressedTexSubImage[123]D(). 3304 * \warning There are some bad assumptions here about the size of compressed 3305 * texture tiles (multiple of 4) used to test the validity of the 3306 * offset and size parameters. 3307 * \return error code or GL_NO_ERROR. 3308 */ 3309static GLenum 3310compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 3311 GLenum target, GLint level, 3312 GLint xoffset, GLint yoffset, GLint zoffset, 3313 GLsizei width, GLsizei height, GLsizei depth, 3314 GLenum format, GLsizei imageSize) 3315{ 3316 GLint expectedSize, maxLevels = 0, maxTextureSize; 3317 (void) zoffset; 3318 3319 if (dimensions == 1) { 3320 /* 1D compressed textures not allowed */ 3321 return GL_INVALID_ENUM; 3322 } 3323 else if (dimensions == 2) { 3324 if (target == GL_PROXY_TEXTURE_2D) { 3325 maxLevels = ctx->Const.MaxTextureLevels; 3326 } 3327 else if (target == GL_TEXTURE_2D) { 3328 maxLevels = ctx->Const.MaxTextureLevels; 3329 } 3330 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3331 if (!ctx->Extensions.ARB_texture_cube_map) 3332 return GL_INVALID_ENUM; /*target*/ 3333 maxLevels = ctx->Const.MaxCubeTextureLevels; 3334 } 3335 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3336 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3337 if (!ctx->Extensions.ARB_texture_cube_map) 3338 return GL_INVALID_ENUM; /*target*/ 3339 maxLevels = ctx->Const.MaxCubeTextureLevels; 3340 } 3341 else { 3342 return GL_INVALID_ENUM; /*target*/ 3343 } 3344 } 3345 else if (dimensions == 3) { 3346 /* 3D compressed textures not allowed */ 3347 return GL_INVALID_ENUM; 3348 } 3349 3350 maxTextureSize = 1 << (maxLevels - 1); 3351 3352 /* this will catch any invalid compressed format token */ 3353 if (!is_compressed_format(ctx, format)) 3354 return GL_INVALID_ENUM; 3355 3356 if (width < 1 || width > maxTextureSize) 3357 return GL_INVALID_VALUE; 3358 3359 if ((height < 1 || height > maxTextureSize) 3360 && dimensions > 1) 3361 return GL_INVALID_VALUE; 3362 3363 if (level < 0 || level >= maxLevels) 3364 return GL_INVALID_VALUE; 3365 3366 /* XXX these tests are specific to the compressed format. 3367 * this code should be generalized in some way. 3368 */ 3369 if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 3370 return GL_INVALID_VALUE; 3371 3372 if ((width & 3) != 0 && width != 2 && width != 1) 3373 return GL_INVALID_VALUE; 3374 3375 if ((height & 3) != 0 && height != 2 && height != 1) 3376 return GL_INVALID_VALUE; 3377 3378 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3379 depth, format); 3380 if (expectedSize != imageSize) 3381 return GL_INVALID_VALUE; 3382 3383 return GL_NO_ERROR; 3384} 3385 3386 3387 3388void GLAPIENTRY 3389_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 3390 GLenum internalFormat, GLsizei width, 3391 GLint border, GLsizei imageSize, 3392 const GLvoid *data) 3393{ 3394 GET_CURRENT_CONTEXT(ctx); 3395 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3396 3397 if (target == GL_TEXTURE_1D) { 3398 /* non-proxy target */ 3399 struct gl_texture_unit *texUnit; 3400 struct gl_texture_object *texObj; 3401 struct gl_texture_image *texImage; 3402 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3403 internalFormat, width, 1, 1, border, imageSize); 3404 if (error) { 3405 _mesa_error(ctx, error, "glCompressedTexImage1D"); 3406 return; 3407 } 3408 3409 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3410 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3411 3412 _mesa_lock_texture(ctx, texObj); 3413 { 3414 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3415 if (!texImage) { 3416 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 3417 goto out; 3418 } 3419 3420 if (texImage->Data) { 3421 ctx->Driver.FreeTexImageData( ctx, texImage ); 3422 } 3423 ASSERT(texImage->Data == NULL); 3424 3425 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3426 border, internalFormat); 3427 3428 ASSERT(ctx->Driver.CompressedTexImage1D); 3429 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 3430 internalFormat, width, border, 3431 imageSize, data, 3432 texObj, texImage); 3433 3434 /* state update */ 3435 texObj->_Complete = GL_FALSE; 3436 ctx->NewState |= _NEW_TEXTURE; 3437 } 3438 out: 3439 _mesa_unlock_texture(ctx, texObj); 3440 } 3441 else if (target == GL_PROXY_TEXTURE_1D) { 3442 /* Proxy texture: check for errors and update proxy state */ 3443 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3444 internalFormat, width, 1, 1, border, imageSize); 3445 if (!error) { 3446 ASSERT(ctx->Driver.TestProxyTexImage); 3447 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3448 internalFormat, GL_NONE, GL_NONE, 3449 width, 1, 1, border); 3450 } 3451 if (error) { 3452 /* if error, clear all proxy texture image parameters */ 3453 struct gl_texture_image *texImage; 3454 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3455 if (texImage) 3456 clear_teximage_fields(texImage); 3457 } 3458 else { 3459 /* store the teximage parameters */ 3460 struct gl_texture_unit *texUnit; 3461 struct gl_texture_object *texObj; 3462 struct gl_texture_image *texImage; 3463 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3464 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3465 3466 _mesa_lock_texture(ctx, texObj); 3467 { 3468 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3469 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3470 border, internalFormat); 3471 } 3472 _mesa_unlock_texture(ctx, texObj); 3473 } 3474 } 3475 else { 3476 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 3477 return; 3478 } 3479} 3480 3481 3482void GLAPIENTRY 3483_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3484 GLenum internalFormat, GLsizei width, 3485 GLsizei height, GLint border, GLsizei imageSize, 3486 const GLvoid *data) 3487{ 3488 GET_CURRENT_CONTEXT(ctx); 3489 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3490 3491 if (target == GL_TEXTURE_2D || 3492 (ctx->Extensions.ARB_texture_cube_map && 3493 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3494 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 3495 /* non-proxy target */ 3496 struct gl_texture_unit *texUnit; 3497 struct gl_texture_object *texObj; 3498 struct gl_texture_image *texImage; 3499 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3500 internalFormat, width, height, 1, border, imageSize); 3501 if (error) { 3502 _mesa_error(ctx, error, "glCompressedTexImage2D"); 3503 return; 3504 } 3505 3506 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3507 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3508 3509 _mesa_lock_texture(ctx, texObj); 3510 { 3511 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3512 if (!texImage) { 3513 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 3514 goto out; 3515 } 3516 3517 if (texImage->Data) { 3518 ctx->Driver.FreeTexImageData( ctx, texImage ); 3519 } 3520 ASSERT(texImage->Data == NULL); 3521 3522 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3523 border, internalFormat); 3524 3525 ASSERT(ctx->Driver.CompressedTexImage2D); 3526 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 3527 internalFormat, width, height, 3528 border, imageSize, data, 3529 texObj, texImage); 3530 3531 /* state update */ 3532 texObj->_Complete = GL_FALSE; 3533 ctx->NewState |= _NEW_TEXTURE; 3534 } 3535 out: 3536 _mesa_unlock_texture(ctx, texObj); 3537 } 3538 else if (target == GL_PROXY_TEXTURE_2D || 3539 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 3540 ctx->Extensions.ARB_texture_cube_map)) { 3541 /* Proxy texture: check for errors and update proxy state */ 3542 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3543 internalFormat, width, height, 1, border, imageSize); 3544 if (!error) { 3545 ASSERT(ctx->Driver.TestProxyTexImage); 3546 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3547 internalFormat, GL_NONE, GL_NONE, 3548 width, height, 1, border); 3549 } 3550 if (error) { 3551 /* if error, clear all proxy texture image parameters */ 3552 struct gl_texture_image *texImage; 3553 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3554 if (texImage) 3555 clear_teximage_fields(texImage); 3556 } 3557 else { 3558 /* store the teximage parameters */ 3559 struct gl_texture_unit *texUnit; 3560 struct gl_texture_object *texObj; 3561 struct gl_texture_image *texImage; 3562 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3563 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3564 3565 _mesa_lock_texture(ctx, texObj); 3566 { 3567 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3568 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3569 border, internalFormat); 3570 } 3571 _mesa_unlock_texture(ctx, texObj); 3572 } 3573 } 3574 else { 3575 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 3576 return; 3577 } 3578} 3579 3580 3581void GLAPIENTRY 3582_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3583 GLenum internalFormat, GLsizei width, 3584 GLsizei height, GLsizei depth, GLint border, 3585 GLsizei imageSize, const GLvoid *data) 3586{ 3587 GET_CURRENT_CONTEXT(ctx); 3588 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3589 3590 if (target == GL_TEXTURE_3D) { 3591 /* non-proxy target */ 3592 struct gl_texture_unit *texUnit; 3593 struct gl_texture_object *texObj; 3594 struct gl_texture_image *texImage; 3595 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3596 internalFormat, width, height, depth, border, imageSize); 3597 if (error) { 3598 _mesa_error(ctx, error, "glCompressedTexImage3D"); 3599 return; 3600 } 3601 3602 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3603 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3604 _mesa_lock_texture(ctx, texObj); 3605 { 3606 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3607 if (!texImage) { 3608 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 3609 goto out; 3610 } 3611 3612 if (texImage->Data) { 3613 ctx->Driver.FreeTexImageData( ctx, texImage ); 3614 } 3615 ASSERT(texImage->Data == NULL); 3616 3617 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 3618 border, internalFormat); 3619 3620 ASSERT(ctx->Driver.CompressedTexImage3D); 3621 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 3622 internalFormat, 3623 width, height, depth, 3624 border, imageSize, data, 3625 texObj, texImage); 3626 3627 /* state update */ 3628 texObj->_Complete = GL_FALSE; 3629 ctx->NewState |= _NEW_TEXTURE; 3630 } 3631 out: 3632 _mesa_unlock_texture(ctx, texObj); 3633 } 3634 else if (target == GL_PROXY_TEXTURE_3D) { 3635 /* Proxy texture: check for errors and update proxy state */ 3636 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3637 internalFormat, width, height, depth, border, imageSize); 3638 if (!error) { 3639 ASSERT(ctx->Driver.TestProxyTexImage); 3640 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3641 internalFormat, GL_NONE, GL_NONE, 3642 width, height, depth, border); 3643 } 3644 if (error) { 3645 /* if error, clear all proxy texture image parameters */ 3646 struct gl_texture_image *texImage; 3647 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3648 if (texImage) 3649 clear_teximage_fields(texImage); 3650 } 3651 else { 3652 /* store the teximage parameters */ 3653 struct gl_texture_unit *texUnit; 3654 struct gl_texture_object *texObj; 3655 struct gl_texture_image *texImage; 3656 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3657 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3658 _mesa_lock_texture(ctx, texObj); 3659 { 3660 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3661 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 3662 depth, border, internalFormat); 3663 } 3664 _mesa_unlock_texture(ctx, texObj); 3665 } 3666 } 3667 else { 3668 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 3669 return; 3670 } 3671} 3672 3673 3674void GLAPIENTRY 3675_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3676 GLsizei width, GLenum format, 3677 GLsizei imageSize, const GLvoid *data) 3678{ 3679 struct gl_texture_unit *texUnit; 3680 struct gl_texture_object *texObj; 3681 struct gl_texture_image *texImage; 3682 GLenum error; 3683 GET_CURRENT_CONTEXT(ctx); 3684 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3685 3686 error = compressed_subtexture_error_check(ctx, 1, target, level, 3687 xoffset, 0, 0, /* pos */ 3688 width, 1, 1, /* size */ 3689 format, imageSize); 3690 if (error) { 3691 _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 3692 return; 3693 } 3694 3695 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3696 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3697 _mesa_lock_texture(ctx, texObj); 3698 { 3699 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3700 assert(texImage); 3701 3702 if ((GLint) format != texImage->InternalFormat) { 3703 _mesa_error(ctx, GL_INVALID_OPERATION, 3704 "glCompressedTexSubImage1D(format)"); 3705 goto out; 3706 } 3707 3708 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 3709 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 3710 goto out; 3711 } 3712 3713 if (width == 0) 3714 goto out; /* no-op, not an error */ 3715 3716 if (ctx->Driver.CompressedTexSubImage1D) { 3717 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 3718 xoffset, width, 3719 format, imageSize, data, 3720 texObj, texImage); 3721 } 3722 ctx->NewState |= _NEW_TEXTURE; 3723 } 3724 out: 3725 _mesa_unlock_texture(ctx, texObj); 3726} 3727 3728 3729void GLAPIENTRY 3730_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3731 GLint yoffset, GLsizei width, GLsizei height, 3732 GLenum format, GLsizei imageSize, 3733 const GLvoid *data) 3734{ 3735 struct gl_texture_unit *texUnit; 3736 struct gl_texture_object *texObj; 3737 struct gl_texture_image *texImage; 3738 GLenum error; 3739 GET_CURRENT_CONTEXT(ctx); 3740 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3741 3742 error = compressed_subtexture_error_check(ctx, 2, target, level, 3743 xoffset, yoffset, 0, /* pos */ 3744 width, height, 1, /* size */ 3745 format, imageSize); 3746 if (error) { 3747 /* XXX proxy target? */ 3748 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 3749 return; 3750 } 3751 3752 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3753 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3754 _mesa_lock_texture(ctx, texObj); 3755 { 3756 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3757 assert(texImage); 3758 3759 if ((GLint) format != texImage->InternalFormat) { 3760 _mesa_error(ctx, GL_INVALID_OPERATION, 3761 "glCompressedTexSubImage2D(format)"); 3762 goto out; 3763 } 3764 3765 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3766 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 3767 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 3768 goto out; 3769 } 3770 3771 if (width == 0 || height == 0) 3772 goto out; /* no-op, not an error */ 3773 3774 if (ctx->Driver.CompressedTexSubImage2D) { 3775 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 3776 xoffset, yoffset, width, height, 3777 format, imageSize, data, 3778 texObj, texImage); 3779 } 3780 ctx->NewState |= _NEW_TEXTURE; 3781 } 3782 out: 3783 _mesa_unlock_texture(ctx, texObj); 3784} 3785 3786 3787void GLAPIENTRY 3788_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3789 GLint yoffset, GLint zoffset, GLsizei width, 3790 GLsizei height, GLsizei depth, GLenum format, 3791 GLsizei imageSize, const GLvoid *data) 3792{ 3793 struct gl_texture_unit *texUnit; 3794 struct gl_texture_object *texObj; 3795 struct gl_texture_image *texImage; 3796 GLenum error; 3797 GET_CURRENT_CONTEXT(ctx); 3798 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3799 3800 error = compressed_subtexture_error_check(ctx, 3, target, level, 3801 xoffset, yoffset, zoffset,/*pos*/ 3802 width, height, depth, /*size*/ 3803 format, imageSize); 3804 if (error) { 3805 _mesa_error(ctx, error, "glCompressedTexSubImage3D"); 3806 return; 3807 } 3808 3809 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3810 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3811 _mesa_lock_texture(ctx, texObj); 3812 { 3813 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3814 assert(texImage); 3815 3816 if ((GLint) format != texImage->InternalFormat) { 3817 _mesa_error(ctx, GL_INVALID_OPERATION, 3818 "glCompressedTexSubImage3D(format)"); 3819 goto out; 3820 } 3821 3822 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3823 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 3824 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 3825 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 3826 goto out; 3827 } 3828 3829 if (width == 0 || height == 0 || depth == 0) 3830 goto out; /* no-op, not an error */ 3831 3832 if (ctx->Driver.CompressedTexSubImage3D) { 3833 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 3834 xoffset, yoffset, zoffset, 3835 width, height, depth, 3836 format, imageSize, data, 3837 texObj, texImage); 3838 } 3839 ctx->NewState |= _NEW_TEXTURE; 3840 } 3841 out: 3842 _mesa_unlock_texture(ctx, texObj); 3843} 3844 3845 3846void GLAPIENTRY 3847_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 3848{ 3849 const struct gl_texture_unit *texUnit; 3850 struct gl_texture_object *texObj; 3851 struct gl_texture_image *texImage; 3852 GLint maxLevels; 3853 GET_CURRENT_CONTEXT(ctx); 3854 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3855 3856 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 3857 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3858 if (!texObj) { 3859 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 3860 return; 3861 } 3862 3863 maxLevels = _mesa_max_texture_levels(ctx, target); 3864 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 3865 3866 if (level < 0 || level >= maxLevels) { 3867 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 3868 return; 3869 } 3870 3871 if (_mesa_is_proxy_texture(target)) { 3872 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 3873 return; 3874 } 3875 3876 _mesa_lock_texture(ctx, texObj); 3877 { 3878 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3879 if (texImage) { 3880 if (texImage->IsCompressed) { 3881 /* this typically calls _mesa_get_compressed_teximage() */ 3882 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 3883 texObj, texImage); 3884 } 3885 else { 3886 _mesa_error(ctx, GL_INVALID_OPERATION, 3887 "glGetCompressedTexImageARB"); 3888 } 3889 } 3890 else { 3891 /* probably invalid mipmap level */ 3892 _mesa_error(ctx, GL_INVALID_VALUE, 3893 "glGetCompressedTexImageARB(level)"); 3894 } 3895 } 3896 _mesa_unlock_texture(ctx, texObj); 3897} 3898