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