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