teximage.c revision 1a2bb37264b4448d33f2948fe1702c9dc936395d
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#include "convolve.h" 37#include "enums.h" 38#include "fbobject.h" 39#include "framebuffer.h" 40#include "hash.h" 41#include "image.h" 42#include "imports.h" 43#include "macros.h" 44#include "state.h" 45#include "texcompress.h" 46#include "texfetch.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 * Get the texture object that corresponds to the target of the given texture unit. 580 * 581 * \param ctx GL context. 582 * \param texUnit texture unit. 583 * \param target texture target. 584 * 585 * \return pointer to the texture object on success, or NULL on failure. 586 * 587 * \sa gl_texture_unit. 588 */ 589struct gl_texture_object * 590_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 591 GLenum target) 592{ 593 switch (target) { 594 case GL_TEXTURE_1D: 595 return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 596 case GL_PROXY_TEXTURE_1D: 597 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 598 case GL_TEXTURE_2D: 599 return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 600 case GL_PROXY_TEXTURE_2D: 601 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 602 case GL_TEXTURE_3D: 603 return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 604 case GL_PROXY_TEXTURE_3D: 605 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 606 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 607 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 608 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 609 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 610 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 611 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 612 case GL_TEXTURE_CUBE_MAP_ARB: 613 return ctx->Extensions.ARB_texture_cube_map 614 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 615 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 616 return ctx->Extensions.ARB_texture_cube_map 617 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 618 case GL_TEXTURE_RECTANGLE_NV: 619 return ctx->Extensions.NV_texture_rectangle 620 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 621 case GL_PROXY_TEXTURE_RECTANGLE_NV: 622 return ctx->Extensions.NV_texture_rectangle 623 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 624 case GL_TEXTURE_1D_ARRAY_EXT: 625 return ctx->Extensions.MESA_texture_array 626 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 627 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 628 return ctx->Extensions.MESA_texture_array 629 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 630 case GL_TEXTURE_2D_ARRAY_EXT: 631 return ctx->Extensions.MESA_texture_array 632 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 633 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 634 return ctx->Extensions.MESA_texture_array 635 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 636 default: 637 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 638 return NULL; 639 } 640} 641 642 643/** 644 * Get a texture image pointer from a texture object, given a texture 645 * target and mipmap level. The target and level parameters should 646 * have already been error-checked. 647 * 648 * \param ctx GL context. 649 * \param texObj texture unit. 650 * \param target texture target. 651 * \param level image level. 652 * 653 * \return pointer to the texture image structure, or NULL on failure. 654 */ 655struct gl_texture_image * 656_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 657 GLenum target, GLint level) 658{ 659 const GLuint face = _mesa_tex_target_to_face(target); 660 661 ASSERT(texObj); 662 ASSERT(level >= 0); 663 ASSERT(level < MAX_TEXTURE_LEVELS); 664 665 return texObj->Image[face][level]; 666} 667 668 669/** 670 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 671 * it and install it. Only return NULL if passed a bad parameter or run 672 * out of memory. 673 */ 674struct gl_texture_image * 675_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 676 GLenum target, GLint level) 677{ 678 struct gl_texture_image *texImage; 679 680 if (!texObj) 681 return NULL; 682 683 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 684 if (!texImage) { 685 texImage = ctx->Driver.NewTextureImage(ctx); 686 if (!texImage) { 687 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 688 return NULL; 689 } 690 691 _mesa_set_tex_image(texObj, target, level, texImage); 692 } 693 694 return texImage; 695} 696 697 698/** 699 * Return pointer to the specified proxy texture image. 700 * Note that proxy textures are per-context, not per-texture unit. 701 * \return pointer to texture image or NULL if invalid target, invalid 702 * level, or out of memory. 703 */ 704struct gl_texture_image * 705_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 706{ 707 struct gl_texture_image *texImage; 708 GLuint texIndex; 709 710 if (level < 0 ) 711 return NULL; 712 713 switch (target) { 714 case GL_PROXY_TEXTURE_1D: 715 if (level >= ctx->Const.MaxTextureLevels) 716 return NULL; 717 texIndex = TEXTURE_1D_INDEX; 718 break; 719 case GL_PROXY_TEXTURE_2D: 720 if (level >= ctx->Const.MaxTextureLevels) 721 return NULL; 722 texIndex = TEXTURE_2D_INDEX; 723 break; 724 case GL_PROXY_TEXTURE_3D: 725 if (level >= ctx->Const.Max3DTextureLevels) 726 return NULL; 727 texIndex = TEXTURE_3D_INDEX; 728 break; 729 case GL_PROXY_TEXTURE_CUBE_MAP: 730 if (level >= ctx->Const.MaxCubeTextureLevels) 731 return NULL; 732 texIndex = TEXTURE_CUBE_INDEX; 733 break; 734 case GL_PROXY_TEXTURE_RECTANGLE_NV: 735 if (level > 0) 736 return NULL; 737 texIndex = TEXTURE_RECT_INDEX; 738 break; 739 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 740 if (level >= ctx->Const.MaxTextureLevels) 741 return NULL; 742 texIndex = TEXTURE_1D_ARRAY_INDEX; 743 break; 744 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 745 if (level >= ctx->Const.MaxTextureLevels) 746 return NULL; 747 texIndex = TEXTURE_2D_ARRAY_INDEX; 748 break; 749 default: 750 return NULL; 751 } 752 753 texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 754 if (!texImage) { 755 texImage = ctx->Driver.NewTextureImage(ctx); 756 if (!texImage) { 757 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 758 return NULL; 759 } 760 ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 761 /* Set the 'back' pointer */ 762 texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 763 } 764 return texImage; 765} 766 767 768/** 769 * Get the maximum number of allowed mipmap levels. 770 * 771 * \param ctx GL context. 772 * \param target texture target. 773 * 774 * \return the maximum number of allowed mipmap levels for the given 775 * texture target, or zero if passed a bad target. 776 * 777 * \sa gl_constants. 778 */ 779GLint 780_mesa_max_texture_levels(GLcontext *ctx, GLenum target) 781{ 782 switch (target) { 783 case GL_TEXTURE_1D: 784 case GL_PROXY_TEXTURE_1D: 785 case GL_TEXTURE_2D: 786 case GL_PROXY_TEXTURE_2D: 787 return ctx->Const.MaxTextureLevels; 788 case GL_TEXTURE_3D: 789 case GL_PROXY_TEXTURE_3D: 790 return ctx->Const.Max3DTextureLevels; 791 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 792 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 793 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 794 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 795 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 796 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 797 case GL_TEXTURE_CUBE_MAP_ARB: 798 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 799 return ctx->Extensions.ARB_texture_cube_map 800 ? ctx->Const.MaxCubeTextureLevels : 0; 801 case GL_TEXTURE_RECTANGLE_NV: 802 case GL_PROXY_TEXTURE_RECTANGLE_NV: 803 return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 804 case GL_TEXTURE_1D_ARRAY_EXT: 805 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 806 case GL_TEXTURE_2D_ARRAY_EXT: 807 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 808 return ctx->Extensions.MESA_texture_array 809 ? ctx->Const.MaxTextureLevels : 0; 810 default: 811 return 0; /* bad target */ 812 } 813} 814 815 816 817#if 000 /* not used anymore */ 818/* 819 * glTexImage[123]D can accept a NULL image pointer. In this case we 820 * create a texture image with unspecified image contents per the OpenGL 821 * spec. 822 */ 823static GLubyte * 824make_null_texture(GLint width, GLint height, GLint depth, GLenum format) 825{ 826 const GLint components = _mesa_components_in_format(format); 827 const GLint numPixels = width * height * depth; 828 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 829 830#ifdef DEBUG 831 /* 832 * Let's see if anyone finds this. If glTexImage2D() is called with 833 * a NULL image pointer then load the texture image with something 834 * interesting instead of leaving it indeterminate. 835 */ 836 if (data) { 837 static const char message[8][32] = { 838 " X X XXXXX XXX X ", 839 " XX XX X X X X X ", 840 " X X X X X X X ", 841 " X X XXXX XXX XXXXX ", 842 " X X X X X X ", 843 " X X X X X X X ", 844 " X X XXXXX XXX X X ", 845 " " 846 }; 847 848 GLubyte *imgPtr = data; 849 GLint h, i, j, k; 850 for (h = 0; h < depth; h++) { 851 for (i = 0; i < height; i++) { 852 GLint srcRow = 7 - (i % 8); 853 for (j = 0; j < width; j++) { 854 GLint srcCol = j % 32; 855 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 856 for (k = 0; k < components; k++) { 857 *imgPtr++ = texel; 858 } 859 } 860 } 861 } 862 } 863#endif 864 865 return data; 866} 867#endif 868 869 870 871/** 872 * Reset the fields of a gl_texture_image struct to zero. 873 * 874 * \param img texture image structure. 875 * 876 * This is called when a proxy texture test fails, we set all the 877 * image members (except DriverData) to zero. 878 * It's also used in glTexImage[123]D as a safeguard to be sure all 879 * required fields get initialized properly by the Driver.TexImage[123]D 880 * functions. 881 */ 882static void 883clear_teximage_fields(struct gl_texture_image *img) 884{ 885 ASSERT(img); 886 img->_BaseFormat = 0; 887 img->InternalFormat = 0; 888 img->Border = 0; 889 img->Width = 0; 890 img->Height = 0; 891 img->Depth = 0; 892 img->RowStride = 0; 893 if (img->ImageOffsets) { 894 _mesa_free(img->ImageOffsets); 895 img->ImageOffsets = NULL; 896 } 897 img->Width2 = 0; 898 img->Height2 = 0; 899 img->Depth2 = 0; 900 img->WidthLog2 = 0; 901 img->HeightLog2 = 0; 902 img->DepthLog2 = 0; 903 img->Data = NULL; 904 img->TexFormat = MESA_FORMAT_NONE; 905 img->FetchTexelc = NULL; 906 img->FetchTexelf = NULL; 907} 908 909 910/** 911 * Initialize basic fields of the gl_texture_image struct. 912 * 913 * \param ctx GL context. 914 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 915 * \param img texture image structure to be initialized. 916 * \param width image width. 917 * \param height image height. 918 * \param depth image depth. 919 * \param border image border. 920 * \param internalFormat internal format. 921 * 922 * Fills in the fields of \p img with the given information. 923 * Note: width, height and depth include the border. 924 */ 925void 926_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 927 struct gl_texture_image *img, 928 GLsizei width, GLsizei height, GLsizei depth, 929 GLint border, GLenum internalFormat) 930{ 931 GLint i; 932 933 ASSERT(img); 934 ASSERT(width >= 0); 935 ASSERT(height >= 0); 936 ASSERT(depth >= 0); 937 938 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 939 ASSERT(img->_BaseFormat > 0); 940 img->InternalFormat = internalFormat; 941 img->Border = border; 942 img->Width = width; 943 img->Height = height; 944 img->Depth = depth; 945 946 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 947 img->WidthLog2 = logbase2(img->Width2); 948 949 if (height == 1) { /* 1-D texture */ 950 img->Height2 = 1; 951 img->HeightLog2 = 0; 952 } 953 else { 954 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 955 img->HeightLog2 = logbase2(img->Height2); 956 } 957 958 if (depth == 1) { /* 2-D texture */ 959 img->Depth2 = 1; 960 img->DepthLog2 = 0; 961 } 962 else { 963 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 964 img->DepthLog2 = logbase2(img->Depth2); 965 } 966 967 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 968 969 if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 970 (height == 1 || _mesa_is_pow_two(img->Height2)) && 971 (depth == 1 || _mesa_is_pow_two(img->Depth2))) 972 img->_IsPowerOfTwo = GL_TRUE; 973 else 974 img->_IsPowerOfTwo = GL_FALSE; 975 976 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 977 img->RowStride = width; 978 /* Allocate the ImageOffsets array and initialize to typical values. 979 * We allocate the array for 1D/2D textures too in order to avoid special- 980 * case code in the texstore routines. 981 */ 982 if (img->ImageOffsets) 983 _mesa_free(img->ImageOffsets); 984 img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 985 for (i = 0; i < depth; i++) { 986 img->ImageOffsets[i] = i * width * height; 987 } 988 989 /* Compute Width/Height/DepthScale for mipmap lod computation */ 990 if (target == GL_TEXTURE_RECTANGLE_NV) { 991 /* scale = 1.0 since texture coords directly map to texels */ 992 img->WidthScale = 1.0; 993 img->HeightScale = 1.0; 994 img->DepthScale = 1.0; 995 } 996 else { 997 img->WidthScale = (GLfloat) img->Width; 998 img->HeightScale = (GLfloat) img->Height; 999 img->DepthScale = (GLfloat) img->Depth; 1000 } 1001 1002 img->FetchTexelc = NULL; 1003 img->FetchTexelf = NULL; 1004} 1005 1006 1007/** 1008 * Free and clear fields of the gl_texture_image struct. 1009 * 1010 * \param ctx GL context. 1011 * \param texImage texture image structure to be cleared. 1012 * 1013 * After the call, \p texImage will have no data associated with it. Its 1014 * fields are cleared so that its parent object will test incomplete. 1015 */ 1016void 1017_mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage) 1018{ 1019 ctx->Driver.FreeTexImageData(ctx, texImage); 1020 clear_teximage_fields(texImage); 1021} 1022 1023 1024/** 1025 * This is the fallback for Driver.TestProxyTexImage(). Test the texture 1026 * level, width, height and depth against the ctx->Const limits for textures. 1027 * 1028 * A hardware driver might override this function if, for example, the 1029 * max 3D texture size is 512x512x64 (i.e. not a cube). 1030 * 1031 * Note that width, height, depth == 0 is not an error. However, a 1032 * texture with zero width/height/depth will be considered "incomplete" 1033 * and texturing will effectively be disabled. 1034 * 1035 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 1036 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 1037 * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 1038 * \param level as passed to glTexImage 1039 * \param internalFormat as passed to glTexImage 1040 * \param format as passed to glTexImage 1041 * \param type as passed to glTexImage 1042 * \param width as passed to glTexImage 1043 * \param height as passed to glTexImage 1044 * \param depth as passed to glTexImage 1045 * \param border as passed to glTexImage 1046 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1047 */ 1048GLboolean 1049_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 1050 GLint internalFormat, GLenum format, GLenum type, 1051 GLint width, GLint height, GLint depth, GLint border) 1052{ 1053 GLint maxSize; 1054 1055 (void) internalFormat; 1056 (void) format; 1057 (void) type; 1058 1059 switch (target) { 1060 case GL_PROXY_TEXTURE_1D: 1061 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1062 if (width < 2 * border || width > 2 + maxSize || 1063 (!ctx->Extensions.ARB_texture_non_power_of_two && 1064 width >0 && !_mesa_is_pow_two(width - 2 * border)) || 1065 level >= ctx->Const.MaxTextureLevels) { 1066 /* bad width or level */ 1067 return GL_FALSE; 1068 } 1069 return GL_TRUE; 1070 case GL_PROXY_TEXTURE_2D: 1071 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1072 if (width < 2 * border || width > 2 + maxSize || 1073 (!ctx->Extensions.ARB_texture_non_power_of_two && 1074 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1075 height < 2 * border || height > 2 + maxSize || 1076 (!ctx->Extensions.ARB_texture_non_power_of_two && 1077 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1078 level >= ctx->Const.MaxTextureLevels) { 1079 /* bad width or height or level */ 1080 return GL_FALSE; 1081 } 1082 return GL_TRUE; 1083 case GL_PROXY_TEXTURE_3D: 1084 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1085 if (width < 2 * border || width > 2 + maxSize || 1086 (!ctx->Extensions.ARB_texture_non_power_of_two && 1087 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1088 height < 2 * border || height > 2 + maxSize || 1089 (!ctx->Extensions.ARB_texture_non_power_of_two && 1090 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1091 depth < 2 * border || depth > 2 + maxSize || 1092 (!ctx->Extensions.ARB_texture_non_power_of_two && 1093 depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || 1094 level >= ctx->Const.Max3DTextureLevels) { 1095 /* bad width or height or depth or level */ 1096 return GL_FALSE; 1097 } 1098 return GL_TRUE; 1099 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1100 if (width < 0 || width > ctx->Const.MaxTextureRectSize || 1101 height < 0 || height > ctx->Const.MaxTextureRectSize || 1102 level != 0) { 1103 /* bad width or height or level */ 1104 return GL_FALSE; 1105 } 1106 return GL_TRUE; 1107 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 1108 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1109 if (width < 2 * border || width > 2 + maxSize || 1110 (!ctx->Extensions.ARB_texture_non_power_of_two && 1111 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1112 height < 2 * border || height > 2 + maxSize || 1113 (!ctx->Extensions.ARB_texture_non_power_of_two && 1114 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1115 level >= ctx->Const.MaxCubeTextureLevels) { 1116 /* bad width or height */ 1117 return GL_FALSE; 1118 } 1119 return GL_TRUE; 1120 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1121 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1122 if (width < 2 * border || width > 2 + maxSize || 1123 (!ctx->Extensions.ARB_texture_non_power_of_two && 1124 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1125 level >= ctx->Const.MaxTextureLevels) { 1126 /* bad width or level */ 1127 return GL_FALSE; 1128 } 1129 1130 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { 1131 return GL_FALSE; 1132 } 1133 return GL_TRUE; 1134 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1135 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1136 if (width < 2 * border || width > 2 + maxSize || 1137 (!ctx->Extensions.ARB_texture_non_power_of_two && 1138 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1139 height < 2 * border || height > 2 + maxSize || 1140 (!ctx->Extensions.ARB_texture_non_power_of_two && 1141 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1142 level >= ctx->Const.MaxTextureLevels) { 1143 /* bad width or height or level */ 1144 return GL_FALSE; 1145 } 1146 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { 1147 return GL_FALSE; 1148 } 1149 return GL_TRUE; 1150 default: 1151 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 1152 return GL_FALSE; 1153 } 1154} 1155 1156 1157/** 1158 * Helper function to determine whether a target supports compressed textures 1159 */ 1160static GLboolean 1161target_can_be_compressed(GLcontext *ctx, GLenum target) 1162{ 1163 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 1164 || ((ctx->Extensions.ARB_texture_cube_map && 1165 (target == GL_PROXY_TEXTURE_CUBE_MAP || 1166 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 1167 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))) 1168 || ((ctx->Extensions.MESA_texture_array && 1169 ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) || 1170 (target == GL_TEXTURE_2D_ARRAY_EXT))))); 1171} 1172 1173 1174/** 1175 * Test the glTexImage[123]D() parameters for errors. 1176 * 1177 * \param ctx GL context. 1178 * \param target texture target given by the user. 1179 * \param level image level given by the user. 1180 * \param internalFormat internal format given by the user. 1181 * \param format pixel data format given by the user. 1182 * \param type pixel data type given by the user. 1183 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1184 * \param width image width given by the user. 1185 * \param height image height given by the user. 1186 * \param depth image depth given by the user. 1187 * \param border image border given by the user. 1188 * 1189 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1190 * 1191 * Verifies each of the parameters against the constants specified in 1192 * __GLcontextRec::Const and the supported extensions, and according to the 1193 * OpenGL specification. 1194 */ 1195static GLboolean 1196texture_error_check( GLcontext *ctx, GLenum target, 1197 GLint level, GLint internalFormat, 1198 GLenum format, GLenum type, 1199 GLuint dimensions, 1200 GLint width, GLint height, 1201 GLint depth, GLint border ) 1202{ 1203 const GLboolean isProxy = _mesa_is_proxy_texture(target); 1204 GLboolean sizeOK = GL_TRUE; 1205 GLboolean colorFormat, indexFormat; 1206 GLenum proxy_target; 1207 1208 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1209 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1210 if (!isProxy) { 1211 _mesa_error(ctx, GL_INVALID_VALUE, 1212 "glTexImage%dD(level=%d)", dimensions, level); 1213 } 1214 return GL_TRUE; 1215 } 1216 1217 /* Check border */ 1218 if (border < 0 || border > 1 || 1219 ((target == GL_TEXTURE_RECTANGLE_NV || 1220 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1221 if (!isProxy) { 1222 _mesa_error(ctx, GL_INVALID_VALUE, 1223 "glTexImage%dD(border=%d)", dimensions, border); 1224 } 1225 return GL_TRUE; 1226 } 1227 1228 if (width < 0 || height < 0 || depth < 0) { 1229 if (!isProxy) { 1230 _mesa_error(ctx, GL_INVALID_VALUE, 1231 "glTexImage%dD(width, height or depth < 0)", dimensions); 1232 } 1233 return GL_TRUE; 1234 } 1235 1236 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1237 * level, width, height and depth. 1238 */ 1239 if (dimensions == 1) { 1240 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 1241 proxy_target = GL_PROXY_TEXTURE_1D; 1242 height = 1; 1243 depth = 1; 1244 } 1245 else { 1246 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1247 return GL_TRUE; 1248 } 1249 } 1250 else if (dimensions == 2) { 1251 depth = 1; 1252 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 1253 proxy_target = GL_PROXY_TEXTURE_2D; 1254 } 1255 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 1256 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1257 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1258 if (!ctx->Extensions.ARB_texture_cube_map) { 1259 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1260 return GL_TRUE; 1261 } 1262 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 1263 sizeOK = (width == height); 1264 } 1265 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 1266 target == GL_TEXTURE_RECTANGLE_NV) { 1267 if (!ctx->Extensions.NV_texture_rectangle) { 1268 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1269 return GL_TRUE; 1270 } 1271 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 1272 } 1273 else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 1274 target == GL_TEXTURE_1D_ARRAY_EXT) { 1275 proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; 1276 } 1277 else { 1278 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1279 return GL_TRUE; 1280 } 1281 } 1282 else if (dimensions == 3) { 1283 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 1284 proxy_target = GL_PROXY_TEXTURE_3D; 1285 } 1286 else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || 1287 target == GL_TEXTURE_2D_ARRAY_EXT) { 1288 proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; 1289 } 1290 else { 1291 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1292 return GL_TRUE; 1293 } 1294 } 1295 else { 1296 _mesa_problem( ctx, "bad dims in texture_error_check" ); 1297 return GL_TRUE; 1298 } 1299 1300 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 1301 internalFormat, format, 1302 type, width, height, 1303 depth, border); 1304 if (!sizeOK) { 1305 if (!isProxy) { 1306 _mesa_error(ctx, GL_INVALID_VALUE, 1307 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 1308 dimensions, level, width, height, depth); 1309 } 1310 return GL_TRUE; 1311 } 1312 1313 /* Check internalFormat */ 1314 if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1315 if (!isProxy) { 1316 _mesa_error(ctx, GL_INVALID_VALUE, 1317 "glTexImage%dD(internalFormat=0x%x)", 1318 dimensions, internalFormat); 1319 } 1320 return GL_TRUE; 1321 } 1322 1323 /* Check incoming image format and type */ 1324 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1325 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 1326 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 1327 */ 1328 if (!isProxy) { 1329 _mesa_error(ctx, GL_INVALID_OPERATION, 1330 "glTexImage%dD(incompatible format 0x%x, type 0x%x)", 1331 dimensions, format, type); 1332 } 1333 return GL_TRUE; 1334 } 1335 1336 /* make sure internal format and format basically agree */ 1337 colorFormat = _mesa_is_color_format(format); 1338 indexFormat = _mesa_is_index_format(format); 1339 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 1340 (_mesa_is_index_format(internalFormat) && !indexFormat) || 1341 (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || 1342 (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || 1343 (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || 1344 (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) { 1345 if (!isProxy) 1346 _mesa_error(ctx, GL_INVALID_OPERATION, 1347 "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", 1348 dimensions, internalFormat, format); 1349 return GL_TRUE; 1350 } 1351 1352 /* additional checks for ycbcr textures */ 1353 if (internalFormat == GL_YCBCR_MESA) { 1354 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 1355 if (type != GL_UNSIGNED_SHORT_8_8_MESA && 1356 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 1357 char message[100]; 1358 _mesa_sprintf(message, 1359 "glTexImage%d(format/type YCBCR mismatch", dimensions); 1360 _mesa_error(ctx, GL_INVALID_ENUM, message); 1361 return GL_TRUE; /* error */ 1362 } 1363 if (target != GL_TEXTURE_2D && 1364 target != GL_PROXY_TEXTURE_2D && 1365 target != GL_TEXTURE_RECTANGLE_NV && 1366 target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1367 if (!isProxy) 1368 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 1369 return GL_TRUE; 1370 } 1371 if (border != 0) { 1372 if (!isProxy) { 1373 char message[100]; 1374 _mesa_sprintf(message, 1375 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 1376 dimensions, border); 1377 _mesa_error(ctx, GL_INVALID_VALUE, message); 1378 } 1379 return GL_TRUE; 1380 } 1381 } 1382 1383 /* additional checks for depth textures */ 1384 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 1385 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 1386 if (target != GL_TEXTURE_1D && 1387 target != GL_PROXY_TEXTURE_1D && 1388 target != GL_TEXTURE_2D && 1389 target != GL_PROXY_TEXTURE_2D && 1390 target != GL_TEXTURE_RECTANGLE_ARB && 1391 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 1392 if (!isProxy) 1393 _mesa_error(ctx, GL_INVALID_ENUM, 1394 "glTexImage(target/internalFormat)"); 1395 return GL_TRUE; 1396 } 1397 } 1398 1399 /* additional checks for compressed textures */ 1400 if (is_compressed_format(ctx, internalFormat)) { 1401 if (!target_can_be_compressed(ctx, target) && !isProxy) { 1402 _mesa_error(ctx, GL_INVALID_ENUM, 1403 "glTexImage%d(target)", dimensions); 1404 return GL_TRUE; 1405 } 1406 if (border != 0) { 1407 if (!isProxy) { 1408 _mesa_error(ctx, GL_INVALID_OPERATION, 1409 "glTexImage%D(border!=0)", dimensions); 1410 } 1411 return GL_TRUE; 1412 } 1413 } 1414 1415 /* if we get here, the parameters are OK */ 1416 return GL_FALSE; 1417} 1418 1419 1420/** 1421 * Test glTexSubImage[123]D() parameters for errors. 1422 * 1423 * \param ctx GL context. 1424 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1425 * \param target texture target given by the user. 1426 * \param level image level given by the user. 1427 * \param xoffset sub-image x offset given by the user. 1428 * \param yoffset sub-image y offset given by the user. 1429 * \param zoffset sub-image z offset given by the user. 1430 * \param format pixel data format given by the user. 1431 * \param type pixel data type given by the user. 1432 * \param width image width given by the user. 1433 * \param height image height given by the user. 1434 * \param depth image depth given by the user. 1435 * 1436 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1437 * 1438 * Verifies each of the parameters against the constants specified in 1439 * __GLcontextRec::Const and the supported extensions, and according to the 1440 * OpenGL specification. 1441 */ 1442static GLboolean 1443subtexture_error_check( GLcontext *ctx, GLuint dimensions, 1444 GLenum target, GLint level, 1445 GLint xoffset, GLint yoffset, GLint zoffset, 1446 GLint width, GLint height, GLint depth, 1447 GLenum format, GLenum type ) 1448{ 1449 /* Check target */ 1450 if (dimensions == 1) { 1451 if (target != GL_TEXTURE_1D) { 1452 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 1453 return GL_TRUE; 1454 } 1455 } 1456 else if (dimensions == 2) { 1457 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1458 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1459 if (!ctx->Extensions.ARB_texture_cube_map) { 1460 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1461 return GL_TRUE; 1462 } 1463 } 1464 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1465 if (!ctx->Extensions.NV_texture_rectangle) { 1466 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1467 return GL_TRUE; 1468 } 1469 } 1470 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1471 if (!ctx->Extensions.MESA_texture_array) { 1472 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1473 return GL_TRUE; 1474 } 1475 } 1476 else if (target != GL_TEXTURE_2D) { 1477 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1478 return GL_TRUE; 1479 } 1480 } 1481 else if (dimensions == 3) { 1482 if (target == GL_TEXTURE_2D_ARRAY_EXT) { 1483 if (!ctx->Extensions.MESA_texture_array) { 1484 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1485 return GL_TRUE; 1486 } 1487 } 1488 else if (target != GL_TEXTURE_3D) { 1489 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1490 return GL_TRUE; 1491 } 1492 } 1493 else { 1494 _mesa_problem( ctx, "invalid dims in texture_error_check" ); 1495 return GL_TRUE; 1496 } 1497 1498 /* Basic level check */ 1499 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1500 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 1501 return GL_TRUE; 1502 } 1503 1504 if (width < 0) { 1505 _mesa_error(ctx, GL_INVALID_VALUE, 1506 "glTexSubImage%dD(width=%d)", dimensions, width); 1507 return GL_TRUE; 1508 } 1509 if (height < 0 && dimensions > 1) { 1510 _mesa_error(ctx, GL_INVALID_VALUE, 1511 "glTexSubImage%dD(height=%d)", dimensions, height); 1512 return GL_TRUE; 1513 } 1514 if (depth < 0 && dimensions > 2) { 1515 _mesa_error(ctx, GL_INVALID_VALUE, 1516 "glTexSubImage%dD(depth=%d)", dimensions, depth); 1517 return GL_TRUE; 1518 } 1519 1520 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1521 _mesa_error(ctx, GL_INVALID_ENUM, 1522 "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)", 1523 dimensions, format, type); 1524 return GL_TRUE; 1525 } 1526 1527 return GL_FALSE; 1528} 1529 1530static GLboolean 1531subtexture_error_check2( GLcontext *ctx, GLuint dimensions, 1532 GLenum target, GLint level, 1533 GLint xoffset, GLint yoffset, GLint zoffset, 1534 GLint width, GLint height, GLint depth, 1535 GLenum format, GLenum type, 1536 const struct gl_texture_image *destTex ) 1537{ 1538 if (!destTex) { 1539 /* undefined image level */ 1540 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 1541 return GL_TRUE; 1542 } 1543 1544 if (xoffset < -((GLint)destTex->Border)) { 1545 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 1546 dimensions); 1547 return GL_TRUE; 1548 } 1549 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1550 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 1551 dimensions); 1552 return GL_TRUE; 1553 } 1554 if (dimensions > 1) { 1555 if (yoffset < -((GLint)destTex->Border)) { 1556 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 1557 dimensions); 1558 return GL_TRUE; 1559 } 1560 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 1561 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 1562 dimensions); 1563 return GL_TRUE; 1564 } 1565 } 1566 if (dimensions > 2) { 1567 if (zoffset < -((GLint)destTex->Border)) { 1568 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 1569 return GL_TRUE; 1570 } 1571 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 1572 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 1573 return GL_TRUE; 1574 } 1575 } 1576 1577#if FEATURE_EXT_texture_sRGB 1578 if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 1579 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 1580 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 1581 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { 1582 if ((width & 0x3) || (height & 0x3) || 1583 (xoffset & 0x3) || (yoffset & 0x3)) 1584 _mesa_error(ctx, GL_INVALID_OPERATION, 1585 "glTexSubImage%dD(size or offset not multiple of 4)", 1586 dimensions); 1587 return GL_TRUE; 1588 } 1589#endif 1590 1591 if (_mesa_is_format_compressed(destTex->TexFormat)) { 1592 if (!target_can_be_compressed(ctx, target)) { 1593 _mesa_error(ctx, GL_INVALID_ENUM, 1594 "glTexSubImage%D(target)", dimensions); 1595 return GL_TRUE; 1596 } 1597 /* offset must be multiple of 4 */ 1598 if ((xoffset & 3) || (yoffset & 3)) { 1599 _mesa_error(ctx, GL_INVALID_OPERATION, 1600 "glTexSubImage%D(xoffset or yoffset)", dimensions); 1601 return GL_TRUE; 1602 } 1603 /* size must be multiple of 4 or equal to whole texture size */ 1604 if ((width & 3) && (GLuint) width != destTex->Width) { 1605 _mesa_error(ctx, GL_INVALID_OPERATION, 1606 "glTexSubImage%D(width)", dimensions); 1607 return GL_TRUE; 1608 } 1609 if ((height & 3) && (GLuint) height != destTex->Height) { 1610 _mesa_error(ctx, GL_INVALID_OPERATION, 1611 "glTexSubImage%D(width)", dimensions); 1612 return GL_TRUE; 1613 } 1614 } 1615 1616 return GL_FALSE; 1617} 1618 1619 1620/** 1621 * Test glCopyTexImage[12]D() parameters for errors. 1622 * 1623 * \param ctx GL context. 1624 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1625 * \param target texture target given by the user. 1626 * \param level image level given by the user. 1627 * \param internalFormat internal format given by the user. 1628 * \param width image width given by the user. 1629 * \param height image height given by the user. 1630 * \param border texture border. 1631 * 1632 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1633 * 1634 * Verifies each of the parameters against the constants specified in 1635 * __GLcontextRec::Const and the supported extensions, and according to the 1636 * OpenGL specification. 1637 */ 1638static GLboolean 1639copytexture_error_check( GLcontext *ctx, GLuint dimensions, 1640 GLenum target, GLint level, GLint internalFormat, 1641 GLint width, GLint height, GLint border ) 1642{ 1643 GLenum type; 1644 GLboolean sizeOK; 1645 GLint format; 1646 1647 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1648 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1649 _mesa_error(ctx, GL_INVALID_VALUE, 1650 "glCopyTexImage%dD(level=%d)", dimensions, level); 1651 return GL_TRUE; 1652 } 1653 1654 /* Check that the source buffer is complete */ 1655 if (ctx->ReadBuffer->Name) { 1656 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1657 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1658 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1659 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1660 return GL_TRUE; 1661 } 1662 } 1663 1664 /* Check border */ 1665 if (border < 0 || border > 1 || 1666 ((target == GL_TEXTURE_RECTANGLE_NV || 1667 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1668 return GL_TRUE; 1669 } 1670 1671 format = _mesa_base_tex_format(ctx, internalFormat); 1672 if (format < 0) { 1673 _mesa_error(ctx, GL_INVALID_VALUE, 1674 "glCopyTexImage%dD(internalFormat)", dimensions); 1675 return GL_TRUE; 1676 } 1677 1678 if (!_mesa_source_buffer_exists(ctx, format)) { 1679 _mesa_error(ctx, GL_INVALID_OPERATION, 1680 "glCopyTexImage%dD(missing readbuffer)", dimensions); 1681 return GL_TRUE; 1682 } 1683 1684 /* NOTE: the format and type aren't really significant for 1685 * TestProxyTexImage(). Only the internalformat really matters. 1686 */ 1687 type = GL_FLOAT; 1688 1689 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1690 * level, width, height and depth. 1691 */ 1692 if (dimensions == 1) { 1693 if (target == GL_TEXTURE_1D) { 1694 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 1695 level, internalFormat, 1696 format, type, 1697 width, 1, 1, border); 1698 } 1699 else { 1700 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 1701 return GL_TRUE; 1702 } 1703 } 1704 else if (dimensions == 2) { 1705 if (target == GL_TEXTURE_2D) { 1706 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 1707 level, internalFormat, 1708 format, type, 1709 width, height, 1, border); 1710 } 1711 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1712 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1713 if (!ctx->Extensions.ARB_texture_cube_map) { 1714 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1715 return GL_TRUE; 1716 } 1717 sizeOK = (width == height) && 1718 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 1719 level, internalFormat, format, type, 1720 width, height, 1, border); 1721 } 1722 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1723 if (!ctx->Extensions.NV_texture_rectangle) { 1724 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1725 return GL_TRUE; 1726 } 1727 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1728 GL_PROXY_TEXTURE_RECTANGLE_NV, 1729 level, internalFormat, 1730 format, type, 1731 width, height, 1, border); 1732 } 1733 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1734 if (!ctx->Extensions.MESA_texture_array) { 1735 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); 1736 return GL_TRUE; 1737 } 1738 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1739 GL_PROXY_TEXTURE_1D_ARRAY_EXT, 1740 level, internalFormat, 1741 format, type, 1742 width, height, 1, border); 1743 } 1744 else { 1745 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1746 return GL_TRUE; 1747 } 1748 } 1749 else { 1750 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 1751 return GL_TRUE; 1752 } 1753 1754 if (!sizeOK) { 1755 if (dimensions == 1) { 1756 _mesa_error(ctx, GL_INVALID_VALUE, 1757 "glCopyTexImage1D(width=%d)", width); 1758 } 1759 else { 1760 ASSERT(dimensions == 2); 1761 _mesa_error(ctx, GL_INVALID_VALUE, 1762 "glCopyTexImage2D(width=%d, height=%d)", width, height); 1763 } 1764 return GL_TRUE; 1765 } 1766 1767 if (is_compressed_format(ctx, internalFormat)) { 1768 if (!target_can_be_compressed(ctx, target)) { 1769 _mesa_error(ctx, GL_INVALID_ENUM, 1770 "glCopyTexImage%d(target)", dimensions); 1771 return GL_TRUE; 1772 } 1773 if (border != 0) { 1774 _mesa_error(ctx, GL_INVALID_OPERATION, 1775 "glCopyTexImage%D(border!=0)", dimensions); 1776 return GL_TRUE; 1777 } 1778 } 1779 else if (_mesa_is_depth_format(internalFormat)) { 1780 /* make sure we have depth/stencil buffers */ 1781 if (!ctx->ReadBuffer->_DepthBuffer) { 1782 _mesa_error(ctx, GL_INVALID_OPERATION, 1783 "glCopyTexImage%D(no depth)", dimensions); 1784 return GL_TRUE; 1785 } 1786 } 1787 else if (_mesa_is_depthstencil_format(internalFormat)) { 1788 /* make sure we have depth/stencil buffers */ 1789 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 1790 _mesa_error(ctx, GL_INVALID_OPERATION, 1791 "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 1792 return GL_TRUE; 1793 } 1794 } 1795 1796 /* if we get here, the parameters are OK */ 1797 return GL_FALSE; 1798} 1799 1800 1801/** 1802 * Test glCopyTexSubImage[12]D() parameters for errors. 1803 * Note that this is the first part of error checking. 1804 * See also copytexsubimage_error_check2() below for the second part. 1805 * 1806 * \param ctx GL context. 1807 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1808 * \param target texture target given by the user. 1809 * \param level image level given by the user. 1810 * 1811 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1812 */ 1813static GLboolean 1814copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions, 1815 GLenum target, GLint level) 1816{ 1817 /* Check that the source buffer is complete */ 1818 if (ctx->ReadBuffer->Name) { 1819 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1820 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1821 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1822 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1823 return GL_TRUE; 1824 } 1825 } 1826 1827 /* Check target */ 1828 if (dimensions == 1) { 1829 if (target != GL_TEXTURE_1D) { 1830 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 1831 return GL_TRUE; 1832 } 1833 } 1834 else if (dimensions == 2) { 1835 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1836 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1837 if (!ctx->Extensions.ARB_texture_cube_map) { 1838 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1839 return GL_TRUE; 1840 } 1841 } 1842 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1843 if (!ctx->Extensions.NV_texture_rectangle) { 1844 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1845 return GL_TRUE; 1846 } 1847 } 1848 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1849 if (!ctx->Extensions.MESA_texture_array) { 1850 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1851 return GL_TRUE; 1852 } 1853 } 1854 else if (target != GL_TEXTURE_2D) { 1855 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 1856 return GL_TRUE; 1857 } 1858 } 1859 else if (dimensions == 3) { 1860 if (((target != GL_TEXTURE_2D_ARRAY_EXT) || 1861 (!ctx->Extensions.MESA_texture_array)) 1862 && (target != GL_TEXTURE_3D)) { 1863 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 1864 return GL_TRUE; 1865 } 1866 } 1867 1868 /* Check level */ 1869 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1870 _mesa_error(ctx, GL_INVALID_VALUE, 1871 "glCopyTexSubImage%dD(level=%d)", dimensions, level); 1872 return GL_TRUE; 1873 } 1874 1875 return GL_FALSE; 1876} 1877 1878 1879/** 1880 * Second part of error checking for glCopyTexSubImage[12]D(). 1881 * \param xoffset sub-image x offset given by the user. 1882 * \param yoffset sub-image y offset given by the user. 1883 * \param zoffset sub-image z offset given by the user. 1884 * \param width image width given by the user. 1885 * \param height image height given by the user. 1886 */ 1887static GLboolean 1888copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 1889 GLenum target, GLint level, 1890 GLint xoffset, GLint yoffset, GLint zoffset, 1891 GLsizei width, GLsizei height, 1892 const struct gl_texture_image *teximage ) 1893{ 1894 /* check that dest tex image exists */ 1895 if (!teximage) { 1896 _mesa_error(ctx, GL_INVALID_OPERATION, 1897 "glCopyTexSubImage%dD(undefined texture level: %d)", 1898 dimensions, level); 1899 return GL_TRUE; 1900 } 1901 1902 /* Check size */ 1903 if (width < 0) { 1904 _mesa_error(ctx, GL_INVALID_VALUE, 1905 "glCopyTexSubImage%dD(width=%d)", dimensions, width); 1906 return GL_TRUE; 1907 } 1908 if (dimensions > 1 && height < 0) { 1909 _mesa_error(ctx, GL_INVALID_VALUE, 1910 "glCopyTexSubImage%dD(height=%d)", dimensions, height); 1911 return GL_TRUE; 1912 } 1913 1914 /* check x/y offsets */ 1915 if (xoffset < -((GLint)teximage->Border)) { 1916 _mesa_error(ctx, GL_INVALID_VALUE, 1917 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 1918 return GL_TRUE; 1919 } 1920 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 1921 _mesa_error(ctx, GL_INVALID_VALUE, 1922 "glCopyTexSubImage%dD(xoffset+width)", dimensions); 1923 return GL_TRUE; 1924 } 1925 if (dimensions > 1) { 1926 if (yoffset < -((GLint)teximage->Border)) { 1927 _mesa_error(ctx, GL_INVALID_VALUE, 1928 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 1929 return GL_TRUE; 1930 } 1931 /* NOTE: we're adding the border here, not subtracting! */ 1932 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 1933 _mesa_error(ctx, GL_INVALID_VALUE, 1934 "glCopyTexSubImage%dD(yoffset+height)", dimensions); 1935 return GL_TRUE; 1936 } 1937 } 1938 1939 /* check z offset */ 1940 if (dimensions > 2) { 1941 if (zoffset < -((GLint)teximage->Border)) { 1942 _mesa_error(ctx, GL_INVALID_VALUE, 1943 "glCopyTexSubImage%dD(zoffset)", dimensions); 1944 return GL_TRUE; 1945 } 1946 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 1947 _mesa_error(ctx, GL_INVALID_VALUE, 1948 "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 1949 return GL_TRUE; 1950 } 1951 } 1952 1953 if (_mesa_is_format_compressed(teximage->TexFormat)) { 1954 if (!target_can_be_compressed(ctx, target)) { 1955 _mesa_error(ctx, GL_INVALID_ENUM, 1956 "glCopyTexSubImage%d(target)", dimensions); 1957 return GL_TRUE; 1958 } 1959 /* offset must be multiple of 4 */ 1960 if ((xoffset & 3) || (yoffset & 3)) { 1961 _mesa_error(ctx, GL_INVALID_VALUE, 1962 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 1963 return GL_TRUE; 1964 } 1965 /* size must be multiple of 4 */ 1966 if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 1967 _mesa_error(ctx, GL_INVALID_VALUE, 1968 "glCopyTexSubImage%D(width)", dimensions); 1969 return GL_TRUE; 1970 } 1971 if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 1972 _mesa_error(ctx, GL_INVALID_VALUE, 1973 "glCopyTexSubImage%D(height)", dimensions); 1974 return GL_TRUE; 1975 } 1976 } 1977 1978 if (teximage->InternalFormat == GL_YCBCR_MESA) { 1979 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 1980 return GL_TRUE; 1981 } 1982 1983 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 1984 _mesa_error(ctx, GL_INVALID_OPERATION, 1985 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 1986 dimensions, teximage->_BaseFormat); 1987 return GL_TRUE; 1988 } 1989 1990 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 1991 if (!ctx->ReadBuffer->_DepthBuffer) { 1992 _mesa_error(ctx, GL_INVALID_OPERATION, 1993 "glCopyTexSubImage%D(no depth buffer)", 1994 dimensions); 1995 return GL_TRUE; 1996 } 1997 } 1998 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 1999 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 2000 _mesa_error(ctx, GL_INVALID_OPERATION, 2001 "glCopyTexSubImage%D(no depth/stencil buffer)", 2002 dimensions); 2003 return GL_TRUE; 2004 } 2005 } 2006 2007 /* if we get here, the parameters are OK */ 2008 return GL_FALSE; 2009} 2010 2011 2012/** Callback info for walking over FBO hash table */ 2013struct cb_info 2014{ 2015 GLcontext *ctx; 2016 struct gl_texture_object *texObj; 2017 GLuint level, face; 2018}; 2019 2020 2021/** 2022 * Check render to texture callback. Called from _mesa_HashWalk(). 2023 */ 2024static void 2025check_rtt_cb(GLuint key, void *data, void *userData) 2026{ 2027 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2028 const struct cb_info *info = (struct cb_info *) userData; 2029 GLcontext *ctx = info->ctx; 2030 const struct gl_texture_object *texObj = info->texObj; 2031 const GLuint level = info->level, face = info->face; 2032 2033 /* If this is a user-created FBO */ 2034 if (fb->Name) { 2035 GLuint i; 2036 /* check if any of the FBO's attachments point to 'texObj' */ 2037 for (i = 0; i < BUFFER_COUNT; i++) { 2038 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 2039 if (att->Type == GL_TEXTURE && 2040 att->Texture == texObj && 2041 att->TextureLevel == level && 2042 att->CubeMapFace == face) { 2043 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 2044 /* Tell driver about the new renderbuffer texture */ 2045 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 2046 /* Mark fb status as indeterminate to force re-validation */ 2047 fb->_Status = 0; 2048 } 2049 } 2050 } 2051} 2052 2053 2054/** 2055 * When a texture image is specified we have to check if it's bound to 2056 * any framebuffer objects (render to texture) in order to detect changes 2057 * in size or format since that effects FBO completeness. 2058 * Any FBOs rendering into the texture must be re-validated. 2059 */ 2060static void 2061update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 2062 GLuint face, GLuint level) 2063{ 2064 /* Only check this texture if it's been marked as RenderToTexture */ 2065 if (texObj->_RenderToTexture) { 2066 struct cb_info info; 2067 info.ctx = ctx; 2068 info.texObj = texObj; 2069 info.level = level; 2070 info.face = face; 2071 _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 2072 } 2073} 2074 2075 2076/** 2077 * If the texture object's GenerateMipmap flag is set and we've 2078 * changed the texture base level image, regenerate the rest of the 2079 * mipmap levels now. 2080 */ 2081static INLINE void 2082check_gen_mipmap(GLcontext *ctx, GLenum target, 2083 struct gl_texture_object *texObj, GLint level) 2084{ 2085 ASSERT(target != GL_TEXTURE_CUBE_MAP); 2086 if (texObj->GenerateMipmap && level == texObj->BaseLevel) { 2087 ASSERT(ctx->Driver.GenerateMipmap); 2088 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2089 } 2090} 2091 2092 2093/** Debug helper: override the user-requested internal format */ 2094static GLenum 2095override_internal_format(GLenum internalFormat, GLint width, GLint height) 2096{ 2097#if 0 2098 if (internalFormat == GL_RGBA16F_ARB || 2099 internalFormat == GL_RGBA32F_ARB) { 2100 printf("Convert rgba float tex to int %d x %d\n", width, height); 2101 return GL_RGBA; 2102 } 2103 else if (internalFormat == GL_RGB16F_ARB || 2104 internalFormat == GL_RGB32F_ARB) { 2105 printf("Convert rgb float tex to int %d x %d\n", width, height); 2106 return GL_RGB; 2107 } 2108 else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 2109 internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 2110 printf("Convert luminance float tex to int %d x %d\n", width, height); 2111 return GL_LUMINANCE_ALPHA; 2112 } 2113 else if (internalFormat == GL_LUMINANCE16F_ARB || 2114 internalFormat == GL_LUMINANCE32F_ARB) { 2115 printf("Convert luminance float tex to int %d x %d\n", width, height); 2116 return GL_LUMINANCE; 2117 } 2118 else if (internalFormat == GL_ALPHA16F_ARB || 2119 internalFormat == GL_ALPHA32F_ARB) { 2120 printf("Convert luminance float tex to int %d x %d\n", width, height); 2121 return GL_ALPHA; 2122 } 2123 /* 2124 else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 2125 internalFormat = GL_RGBA; 2126 } 2127 */ 2128 else { 2129 return internalFormat; 2130 } 2131#else 2132 return internalFormat; 2133#endif 2134} 2135 2136 2137/* 2138 * Called from the API. Note that width includes the border. 2139 */ 2140void GLAPIENTRY 2141_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 2142 GLsizei width, GLint border, GLenum format, 2143 GLenum type, const GLvoid *pixels ) 2144{ 2145 GLsizei postConvWidth = width; 2146 GET_CURRENT_CONTEXT(ctx); 2147 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2148 2149 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2150 _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n", 2151 _mesa_lookup_enum_by_nr(target), level, 2152 _mesa_lookup_enum_by_nr(internalFormat), width, border, 2153 _mesa_lookup_enum_by_nr(format), 2154 _mesa_lookup_enum_by_nr(type), pixels); 2155 2156 internalFormat = override_internal_format(internalFormat, width, 1); 2157 2158#if FEATURE_convolve 2159 if (_mesa_is_color_format(internalFormat)) { 2160 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2161 } 2162#endif 2163 2164 if (target == GL_TEXTURE_1D) { 2165 /* non-proxy target */ 2166 struct gl_texture_unit *texUnit; 2167 struct gl_texture_object *texObj; 2168 struct gl_texture_image *texImage; 2169 const GLuint face = _mesa_tex_target_to_face(target); 2170 2171 if (texture_error_check(ctx, target, level, internalFormat, 2172 format, type, 1, postConvWidth, 1, 1, border)) { 2173 return; /* error was recorded */ 2174 } 2175 2176 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2177 _mesa_update_state(ctx); 2178 2179 texUnit = _mesa_get_current_tex_unit(ctx); 2180 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2181 _mesa_lock_texture(ctx, texObj); 2182 { 2183 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2184 if (!texImage) { 2185 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2186 } 2187 else { 2188 if (texImage->Data) { 2189 ctx->Driver.FreeTexImageData( ctx, texImage ); 2190 } 2191 2192 ASSERT(texImage->Data == NULL); 2193 2194 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2195 _mesa_init_teximage_fields(ctx, target, texImage, 2196 postConvWidth, 1, 1, 2197 border, internalFormat); 2198 2199 /* Give the texture to the driver. <pixels> may be null. */ 2200 ASSERT(ctx->Driver.TexImage1D); 2201 ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 2202 width, border, format, type, pixels, 2203 &ctx->Unpack, texObj, texImage); 2204 2205 ASSERT(texImage->TexFormat); 2206 2207 _mesa_set_fetch_functions(texImage, 1); 2208 2209 check_gen_mipmap(ctx, target, texObj, level); 2210 2211 update_fbo_texture(ctx, texObj, face, level); 2212 2213 /* state update */ 2214 texObj->_Complete = GL_FALSE; 2215 ctx->NewState |= _NEW_TEXTURE; 2216 } 2217 } 2218 _mesa_unlock_texture(ctx, texObj); 2219 } 2220 else if (target == GL_PROXY_TEXTURE_1D) { 2221 /* Proxy texture: check for errors and update proxy state */ 2222 struct gl_texture_image *texImage; 2223 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2224 if (texture_error_check(ctx, target, level, internalFormat, 2225 format, type, 1, postConvWidth, 1, 1, border)) { 2226 /* when error, clear all proxy texture image parameters */ 2227 if (texImage) 2228 clear_teximage_fields(texImage); 2229 } 2230 else { 2231 /* no error, set the tex image parameters */ 2232 ASSERT(texImage); 2233 _mesa_init_teximage_fields(ctx, target, texImage, 2234 postConvWidth, 1, 1, 2235 border, internalFormat); 2236 texImage->TexFormat = 2237 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2238 } 2239 } 2240 else { 2241 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 2242 return; 2243 } 2244} 2245 2246 2247void GLAPIENTRY 2248_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 2249 GLsizei width, GLsizei height, GLint border, 2250 GLenum format, GLenum type, 2251 const GLvoid *pixels ) 2252{ 2253 GLsizei postConvWidth = width, postConvHeight = height; 2254 GET_CURRENT_CONTEXT(ctx); 2255 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2256 2257 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2258 _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n", 2259 _mesa_lookup_enum_by_nr(target), level, 2260 _mesa_lookup_enum_by_nr(internalFormat), width, height, 2261 border, _mesa_lookup_enum_by_nr(format), 2262 _mesa_lookup_enum_by_nr(type), pixels); 2263 2264 internalFormat = override_internal_format(internalFormat, width, height); 2265 2266#if FEATURE_convolve 2267 if (_mesa_is_color_format(internalFormat)) { 2268 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2269 &postConvHeight); 2270 } 2271#endif 2272 2273 if (target == GL_TEXTURE_2D || 2274 (ctx->Extensions.ARB_texture_cube_map && 2275 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2276 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 2277 (ctx->Extensions.NV_texture_rectangle && 2278 target == GL_TEXTURE_RECTANGLE_NV) || 2279 (ctx->Extensions.MESA_texture_array && 2280 target == GL_TEXTURE_1D_ARRAY_EXT)) { 2281 /* non-proxy target */ 2282 struct gl_texture_unit *texUnit; 2283 struct gl_texture_object *texObj; 2284 struct gl_texture_image *texImage; 2285 const GLuint face = _mesa_tex_target_to_face(target); 2286 2287 if (texture_error_check(ctx, target, level, internalFormat, 2288 format, type, 2, postConvWidth, postConvHeight, 2289 1, border)) { 2290 return; /* error was recorded */ 2291 } 2292 2293 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2294 _mesa_update_state(ctx); 2295 2296 texUnit = _mesa_get_current_tex_unit(ctx); 2297 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2298 _mesa_lock_texture(ctx, texObj); 2299 { 2300 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2301 if (!texImage) { 2302 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2303 } 2304 else { 2305 if (texImage->Data) { 2306 ctx->Driver.FreeTexImageData( ctx, texImage ); 2307 } 2308 2309 ASSERT(texImage->Data == NULL); 2310 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2311 _mesa_init_teximage_fields(ctx, target, texImage, 2312 postConvWidth, postConvHeight, 1, 2313 border, internalFormat); 2314 2315 /* Give the texture to the driver. <pixels> may be null. */ 2316 ASSERT(ctx->Driver.TexImage2D); 2317 ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 2318 width, height, border, format, type, 2319 pixels, &ctx->Unpack, texObj, texImage); 2320 2321 ASSERT(texImage->TexFormat); 2322 2323 _mesa_set_fetch_functions(texImage, 2); 2324 2325 check_gen_mipmap(ctx, target, texObj, level); 2326 2327 update_fbo_texture(ctx, texObj, face, level); 2328 2329 /* state update */ 2330 texObj->_Complete = GL_FALSE; 2331 ctx->NewState |= _NEW_TEXTURE; 2332 } 2333 } 2334 _mesa_unlock_texture(ctx, texObj); 2335 } 2336 else if (target == GL_PROXY_TEXTURE_2D || 2337 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 2338 ctx->Extensions.ARB_texture_cube_map) || 2339 (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2340 ctx->Extensions.NV_texture_rectangle) || 2341 (ctx->Extensions.MESA_texture_array && 2342 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 2343 /* Proxy texture: check for errors and update proxy state */ 2344 struct gl_texture_image *texImage; 2345 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2346 if (texture_error_check(ctx, target, level, internalFormat, 2347 format, type, 2, postConvWidth, postConvHeight, 2348 1, border)) { 2349 /* when error, clear all proxy texture image parameters */ 2350 if (texImage) 2351 clear_teximage_fields(texImage); 2352 } 2353 else { 2354 /* no error, set the tex image parameters */ 2355 _mesa_init_teximage_fields(ctx, target, texImage, 2356 postConvWidth, postConvHeight, 1, 2357 border, internalFormat); 2358 texImage->TexFormat = 2359 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2360 } 2361 } 2362 else { 2363 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 2364 return; 2365 } 2366} 2367 2368 2369/* 2370 * Called by the API or display list executor. 2371 * Note that width and height include the border. 2372 */ 2373void GLAPIENTRY 2374_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 2375 GLsizei width, GLsizei height, GLsizei depth, 2376 GLint border, GLenum format, GLenum type, 2377 const GLvoid *pixels ) 2378{ 2379 GET_CURRENT_CONTEXT(ctx); 2380 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2381 2382 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2383 _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n", 2384 _mesa_lookup_enum_by_nr(target), level, 2385 _mesa_lookup_enum_by_nr(internalFormat), width, height, 2386 depth, border, _mesa_lookup_enum_by_nr(format), 2387 _mesa_lookup_enum_by_nr(type), pixels); 2388 2389 internalFormat = override_internal_format(internalFormat, width, height); 2390 2391 if (target == GL_TEXTURE_3D || 2392 (ctx->Extensions.MESA_texture_array && 2393 target == GL_TEXTURE_2D_ARRAY_EXT)) { 2394 /* non-proxy target */ 2395 struct gl_texture_unit *texUnit; 2396 struct gl_texture_object *texObj; 2397 struct gl_texture_image *texImage; 2398 const GLuint face = _mesa_tex_target_to_face(target); 2399 2400 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 2401 format, type, 3, width, height, depth, border)) { 2402 return; /* error was recorded */ 2403 } 2404 2405 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2406 _mesa_update_state(ctx); 2407 2408 texUnit = _mesa_get_current_tex_unit(ctx); 2409 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2410 _mesa_lock_texture(ctx, texObj); 2411 { 2412 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2413 if (!texImage) { 2414 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2415 } 2416 else { 2417 if (texImage->Data) { 2418 ctx->Driver.FreeTexImageData( ctx, texImage ); 2419 } 2420 2421 ASSERT(texImage->Data == NULL); 2422 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2423 _mesa_init_teximage_fields(ctx, target, texImage, 2424 width, height, depth, 2425 border, internalFormat); 2426 2427 /* Give the texture to the driver. <pixels> may be null. */ 2428 ASSERT(ctx->Driver.TexImage3D); 2429 ctx->Driver.TexImage3D(ctx, target, level, internalFormat, 2430 width, height, depth, border, format, type, 2431 pixels, &ctx->Unpack, texObj, texImage); 2432 2433 ASSERT(texImage->TexFormat); 2434 2435 _mesa_set_fetch_functions(texImage, 3); 2436 2437 check_gen_mipmap(ctx, target, texObj, level); 2438 2439 update_fbo_texture(ctx, texObj, face, level); 2440 2441 /* state update */ 2442 texObj->_Complete = GL_FALSE; 2443 ctx->NewState |= _NEW_TEXTURE; 2444 } 2445 } 2446 _mesa_unlock_texture(ctx, texObj); 2447 } 2448 else if (target == GL_PROXY_TEXTURE_3D || 2449 (ctx->Extensions.MESA_texture_array && 2450 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 2451 /* Proxy texture: check for errors and update proxy state */ 2452 struct gl_texture_image *texImage; 2453 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2454 if (texture_error_check(ctx, target, level, internalFormat, 2455 format, type, 3, width, height, depth, border)) { 2456 /* when error, clear all proxy texture image parameters */ 2457 if (texImage) 2458 clear_teximage_fields(texImage); 2459 } 2460 else { 2461 /* no error, set the tex image parameters */ 2462 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 2463 depth, border, internalFormat); 2464 texImage->TexFormat = 2465 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2466 } 2467 } 2468 else { 2469 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 2470 return; 2471 } 2472} 2473 2474 2475void GLAPIENTRY 2476_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2477 GLsizei width, GLsizei height, GLsizei depth, 2478 GLint border, GLenum format, GLenum type, 2479 const GLvoid *pixels ) 2480{ 2481 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2482 depth, border, format, type, pixels); 2483} 2484 2485 2486 2487void GLAPIENTRY 2488_mesa_TexSubImage1D( GLenum target, GLint level, 2489 GLint xoffset, GLsizei width, 2490 GLenum format, GLenum type, 2491 const GLvoid *pixels ) 2492{ 2493 GLsizei postConvWidth = width; 2494 struct gl_texture_unit *texUnit; 2495 struct gl_texture_object *texObj; 2496 struct gl_texture_image *texImage = NULL; 2497 GET_CURRENT_CONTEXT(ctx); 2498 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2499 2500 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2501 _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n", 2502 _mesa_lookup_enum_by_nr(target), level, 2503 xoffset, width, _mesa_lookup_enum_by_nr(format), 2504 _mesa_lookup_enum_by_nr(type), pixels); 2505 2506 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2507 _mesa_update_state(ctx); 2508 2509#if FEATURE_convolve 2510 /* XXX should test internal format */ 2511 if (_mesa_is_color_format(format)) { 2512 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2513 } 2514#endif 2515 2516 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2517 postConvWidth, 1, 1, format, type)) { 2518 return; /* error was detected */ 2519 } 2520 2521 2522 texUnit = _mesa_get_current_tex_unit(ctx); 2523 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2524 assert(texObj); 2525 2526 _mesa_lock_texture(ctx, texObj); 2527 { 2528 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2529 2530 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 2531 postConvWidth, 1, 1, 2532 format, type, texImage)) { 2533 /* error was recorded */ 2534 } 2535 else if (width > 0) { 2536 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2537 xoffset += texImage->Border; 2538 2539 ASSERT(ctx->Driver.TexSubImage1D); 2540 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width, 2541 format, type, pixels, &ctx->Unpack, 2542 texObj, texImage); 2543 2544 check_gen_mipmap(ctx, target, texObj, level); 2545 2546 ctx->NewState |= _NEW_TEXTURE; 2547 } 2548 } 2549 _mesa_unlock_texture(ctx, texObj); 2550} 2551 2552 2553void GLAPIENTRY 2554_mesa_TexSubImage2D( GLenum target, GLint level, 2555 GLint xoffset, GLint yoffset, 2556 GLsizei width, GLsizei height, 2557 GLenum format, GLenum type, 2558 const GLvoid *pixels ) 2559{ 2560 GLsizei postConvWidth = width, postConvHeight = height; 2561 struct gl_texture_unit *texUnit; 2562 struct gl_texture_object *texObj; 2563 struct gl_texture_image *texImage; 2564 GET_CURRENT_CONTEXT(ctx); 2565 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2566 2567 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2568 _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n", 2569 _mesa_lookup_enum_by_nr(target), level, 2570 xoffset, yoffset, width, height, 2571 _mesa_lookup_enum_by_nr(format), 2572 _mesa_lookup_enum_by_nr(type), pixels); 2573 2574 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2575 _mesa_update_state(ctx); 2576 2577#if FEATURE_convolve 2578 /* XXX should test internal format */ 2579 if (_mesa_is_color_format(format)) { 2580 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2581 &postConvHeight); 2582 } 2583#endif 2584 2585 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2586 postConvWidth, postConvHeight, 1, format, type)) { 2587 return; /* error was detected */ 2588 } 2589 2590 texUnit = _mesa_get_current_tex_unit(ctx); 2591 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2592 2593 _mesa_lock_texture(ctx, texObj); 2594 { 2595 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2596 2597 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 2598 postConvWidth, postConvHeight, 1, 2599 format, type, texImage)) { 2600 /* error was recorded */ 2601 } 2602 else if (width > 0 && height >= 0) { 2603 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2604 xoffset += texImage->Border; 2605 yoffset += texImage->Border; 2606 2607 ASSERT(ctx->Driver.TexSubImage2D); 2608 ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset, 2609 width, height, format, type, pixels, 2610 &ctx->Unpack, texObj, texImage); 2611 2612 check_gen_mipmap(ctx, target, texObj, level); 2613 2614 ctx->NewState |= _NEW_TEXTURE; 2615 } 2616 } 2617 _mesa_unlock_texture(ctx, texObj); 2618} 2619 2620 2621 2622void GLAPIENTRY 2623_mesa_TexSubImage3D( GLenum target, GLint level, 2624 GLint xoffset, GLint yoffset, GLint zoffset, 2625 GLsizei width, GLsizei height, GLsizei depth, 2626 GLenum format, GLenum type, 2627 const GLvoid *pixels ) 2628{ 2629 struct gl_texture_unit *texUnit; 2630 struct gl_texture_object *texObj; 2631 struct gl_texture_image *texImage; 2632 GET_CURRENT_CONTEXT(ctx); 2633 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2634 2635 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2636 _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n", 2637 _mesa_lookup_enum_by_nr(target), level, 2638 xoffset, yoffset, zoffset, width, height, depth, 2639 _mesa_lookup_enum_by_nr(format), 2640 _mesa_lookup_enum_by_nr(type), pixels); 2641 2642 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2643 _mesa_update_state(ctx); 2644 2645 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2646 width, height, depth, format, type)) { 2647 return; /* error was detected */ 2648 } 2649 2650 texUnit = _mesa_get_current_tex_unit(ctx); 2651 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2652 2653 _mesa_lock_texture(ctx, texObj); 2654 { 2655 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2656 2657 if (subtexture_error_check2(ctx, 3, target, level, 2658 xoffset, yoffset, zoffset, 2659 width, height, depth, 2660 format, type, texImage)) { 2661 /* error was recorded */ 2662 } 2663 else if (width > 0 && height > 0 && height > 0) { 2664 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2665 xoffset += texImage->Border; 2666 yoffset += texImage->Border; 2667 zoffset += texImage->Border; 2668 2669 ASSERT(ctx->Driver.TexSubImage3D); 2670 ctx->Driver.TexSubImage3D(ctx, target, level, 2671 xoffset, yoffset, zoffset, 2672 width, height, depth, 2673 format, type, pixels, 2674 &ctx->Unpack, texObj, texImage ); 2675 2676 check_gen_mipmap(ctx, target, texObj, level); 2677 2678 ctx->NewState |= _NEW_TEXTURE; 2679 } 2680 } 2681 _mesa_unlock_texture(ctx, texObj); 2682} 2683 2684 2685 2686void GLAPIENTRY 2687_mesa_CopyTexImage1D( GLenum target, GLint level, 2688 GLenum internalFormat, 2689 GLint x, GLint y, 2690 GLsizei width, GLint border ) 2691{ 2692 struct gl_texture_unit *texUnit; 2693 struct gl_texture_object *texObj; 2694 struct gl_texture_image *texImage; 2695 GLsizei postConvWidth = width; 2696 const GLuint face = _mesa_tex_target_to_face(target); 2697 GET_CURRENT_CONTEXT(ctx); 2698 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2699 2700 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2701 _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n", 2702 _mesa_lookup_enum_by_nr(target), level, 2703 _mesa_lookup_enum_by_nr(internalFormat), 2704 x, y, width, border); 2705 2706 if (ctx->NewState & NEW_COPY_TEX_STATE) 2707 _mesa_update_state(ctx); 2708 2709#if FEATURE_convolve 2710 if (_mesa_is_color_format(internalFormat)) { 2711 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2712 } 2713#endif 2714 2715 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 2716 postConvWidth, 1, border)) 2717 return; 2718 2719 texUnit = _mesa_get_current_tex_unit(ctx); 2720 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2721 2722 _mesa_lock_texture(ctx, texObj); 2723 { 2724 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2725 if (!texImage) { 2726 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 2727 } 2728 else { 2729 if (texImage->Data) { 2730 ctx->Driver.FreeTexImageData( ctx, texImage ); 2731 } 2732 2733 ASSERT(texImage->Data == NULL); 2734 2735 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2736 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 2737 border, internalFormat); 2738 2739 ASSERT(ctx->Driver.CopyTexImage1D); 2740 ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, 2741 x, y, width, border); 2742 2743 ASSERT(texImage->TexFormat); 2744 2745 _mesa_set_fetch_functions(texImage, 1); 2746 2747 check_gen_mipmap(ctx, target, texObj, level); 2748 2749 update_fbo_texture(ctx, texObj, face, level); 2750 2751 /* state update */ 2752 texObj->_Complete = GL_FALSE; 2753 ctx->NewState |= _NEW_TEXTURE; 2754 } 2755 } 2756 _mesa_unlock_texture(ctx, texObj); 2757} 2758 2759 2760 2761void GLAPIENTRY 2762_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 2763 GLint x, GLint y, GLsizei width, GLsizei height, 2764 GLint border ) 2765{ 2766 struct gl_texture_unit *texUnit; 2767 struct gl_texture_object *texObj; 2768 struct gl_texture_image *texImage; 2769 GLsizei postConvWidth = width, postConvHeight = height; 2770 const GLuint face = _mesa_tex_target_to_face(target); 2771 GET_CURRENT_CONTEXT(ctx); 2772 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2773 2774 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2775 _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n", 2776 _mesa_lookup_enum_by_nr(target), level, 2777 _mesa_lookup_enum_by_nr(internalFormat), 2778 x, y, width, height, border); 2779 2780 if (ctx->NewState & NEW_COPY_TEX_STATE) 2781 _mesa_update_state(ctx); 2782 2783#if FEATURE_convolve 2784 if (_mesa_is_color_format(internalFormat)) { 2785 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2786 &postConvHeight); 2787 } 2788#endif 2789 2790 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 2791 postConvWidth, postConvHeight, border)) 2792 return; 2793 2794 texUnit = _mesa_get_current_tex_unit(ctx); 2795 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2796 2797 _mesa_lock_texture(ctx, texObj); 2798 { 2799 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2800 2801 if (!texImage) { 2802 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 2803 } 2804 else { 2805 if (texImage->Data) { 2806 ctx->Driver.FreeTexImageData( ctx, texImage ); 2807 } 2808 2809 ASSERT(texImage->Data == NULL); 2810 2811 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2812 _mesa_init_teximage_fields(ctx, target, texImage, 2813 postConvWidth, postConvHeight, 1, 2814 border, internalFormat); 2815 2816 ASSERT(ctx->Driver.CopyTexImage2D); 2817 ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, 2818 x, y, width, height, border); 2819 2820 ASSERT(texImage->TexFormat); 2821 2822 _mesa_set_fetch_functions(texImage, 2); 2823 2824 check_gen_mipmap(ctx, target, texObj, level); 2825 2826 update_fbo_texture(ctx, texObj, face, level); 2827 2828 /* state update */ 2829 texObj->_Complete = GL_FALSE; 2830 ctx->NewState |= _NEW_TEXTURE; 2831 } 2832 } 2833 _mesa_unlock_texture(ctx, texObj); 2834} 2835 2836 2837void GLAPIENTRY 2838_mesa_CopyTexSubImage1D( GLenum target, GLint level, 2839 GLint xoffset, GLint x, GLint y, GLsizei width ) 2840{ 2841 struct gl_texture_unit *texUnit; 2842 struct gl_texture_object *texObj; 2843 struct gl_texture_image *texImage; 2844 GLsizei postConvWidth = width; 2845 GLint yoffset = 0; 2846 GLsizei height = 1; 2847 2848 GET_CURRENT_CONTEXT(ctx); 2849 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2850 2851 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2852 _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n", 2853 _mesa_lookup_enum_by_nr(target), 2854 level, xoffset, x, y, width); 2855 2856 if (ctx->NewState & NEW_COPY_TEX_STATE) 2857 _mesa_update_state(ctx); 2858 2859 if (copytexsubimage_error_check1(ctx, 1, target, level)) 2860 return; 2861 2862 texUnit = _mesa_get_current_tex_unit(ctx); 2863 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2864 2865 _mesa_lock_texture(ctx, texObj); 2866 { 2867 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2868 2869#if FEATURE_convolve 2870 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2871 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2872 } 2873#endif 2874 2875 if (copytexsubimage_error_check2(ctx, 1, target, level, 2876 xoffset, 0, 0, postConvWidth, 1, 2877 texImage)) { 2878 /* error was recorded */ 2879 } 2880 else { 2881 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2882 xoffset += texImage->Border; 2883 2884 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 2885 &width, &height)) { 2886 ASSERT(ctx->Driver.CopyTexSubImage1D); 2887 ctx->Driver.CopyTexSubImage1D(ctx, target, level, 2888 xoffset, x, y, width); 2889 2890 check_gen_mipmap(ctx, target, texObj, level); 2891 2892 ctx->NewState |= _NEW_TEXTURE; 2893 } 2894 } 2895 } 2896 _mesa_unlock_texture(ctx, texObj); 2897} 2898 2899 2900 2901void GLAPIENTRY 2902_mesa_CopyTexSubImage2D( GLenum target, GLint level, 2903 GLint xoffset, GLint yoffset, 2904 GLint x, GLint y, GLsizei width, GLsizei height ) 2905{ 2906 struct gl_texture_unit *texUnit; 2907 struct gl_texture_object *texObj; 2908 struct gl_texture_image *texImage; 2909 GLsizei postConvWidth = width, postConvHeight = height; 2910 GET_CURRENT_CONTEXT(ctx); 2911 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2912 2913 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2914 _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n", 2915 _mesa_lookup_enum_by_nr(target), 2916 level, xoffset, yoffset, x, y, width, height); 2917 2918 if (ctx->NewState & NEW_COPY_TEX_STATE) 2919 _mesa_update_state(ctx); 2920 2921 if (copytexsubimage_error_check1(ctx, 2, target, level)) 2922 return; 2923 2924 texUnit = _mesa_get_current_tex_unit(ctx); 2925 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2926 2927 _mesa_lock_texture(ctx, texObj); 2928 { 2929 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2930 2931#if FEATURE_convolve 2932 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2933 _mesa_adjust_image_for_convolution(ctx, 2, 2934 &postConvWidth, &postConvHeight); 2935 } 2936#endif 2937 2938 if (copytexsubimage_error_check2(ctx, 2, target, level, 2939 xoffset, yoffset, 0, 2940 postConvWidth, postConvHeight, 2941 texImage)) { 2942 /* error was recorded */ 2943 } 2944 else { 2945 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2946 xoffset += texImage->Border; 2947 yoffset += texImage->Border; 2948 2949 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 2950 &width, &height)) { 2951 ASSERT(ctx->Driver.CopyTexSubImage2D); 2952 ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset, 2953 x, y, width, height); 2954 2955 check_gen_mipmap(ctx, target, texObj, level); 2956 2957 ctx->NewState |= _NEW_TEXTURE; 2958 } 2959 } 2960 } 2961 _mesa_unlock_texture(ctx, texObj); 2962} 2963 2964 2965 2966void GLAPIENTRY 2967_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2968 GLint xoffset, GLint yoffset, GLint zoffset, 2969 GLint x, GLint y, GLsizei width, GLsizei height ) 2970{ 2971 struct gl_texture_unit *texUnit; 2972 struct gl_texture_object *texObj; 2973 struct gl_texture_image *texImage; 2974 GLsizei postConvWidth = width, postConvHeight = height; 2975 GET_CURRENT_CONTEXT(ctx); 2976 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2977 2978 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2979 _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n", 2980 _mesa_lookup_enum_by_nr(target), 2981 level, xoffset, yoffset, zoffset, x, y, width, height); 2982 2983 if (ctx->NewState & NEW_COPY_TEX_STATE) 2984 _mesa_update_state(ctx); 2985 2986 if (copytexsubimage_error_check1(ctx, 3, target, level)) 2987 return; 2988 2989 texUnit = _mesa_get_current_tex_unit(ctx); 2990 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2991 2992 _mesa_lock_texture(ctx, texObj); 2993 { 2994 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2995 2996#if FEATURE_convolve 2997 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 2998 _mesa_adjust_image_for_convolution(ctx, 2, 2999 &postConvWidth, &postConvHeight); 3000 } 3001#endif 3002 3003 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 3004 zoffset, postConvWidth, postConvHeight, 3005 texImage)) { 3006 /* error was recored */ 3007 } 3008 else { 3009 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3010 xoffset += texImage->Border; 3011 yoffset += texImage->Border; 3012 zoffset += texImage->Border; 3013 3014 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3015 &width, &height)) { 3016 ASSERT(ctx->Driver.CopyTexSubImage3D); 3017 ctx->Driver.CopyTexSubImage3D(ctx, target, level, 3018 xoffset, yoffset, zoffset, 3019 x, y, width, height); 3020 3021 check_gen_mipmap(ctx, target, texObj, level); 3022 3023 ctx->NewState |= _NEW_TEXTURE; 3024 } 3025 } 3026 } 3027 _mesa_unlock_texture(ctx, texObj); 3028} 3029 3030 3031 3032 3033/**********************************************************************/ 3034/****** Compressed Textures ******/ 3035/**********************************************************************/ 3036 3037 3038/** 3039 * Error checking for glCompressedTexImage[123]D(). 3040 * \return error code or GL_NO_ERROR. 3041 */ 3042static GLenum 3043compressed_texture_error_check(GLcontext *ctx, GLint dimensions, 3044 GLenum target, GLint level, 3045 GLenum internalFormat, GLsizei width, 3046 GLsizei height, GLsizei depth, GLint border, 3047 GLsizei imageSize) 3048{ 3049 GLint expectedSize, maxLevels = 0, maxTextureSize; 3050 3051 if (dimensions == 1) { 3052 /* 1D compressed textures not allowed */ 3053 return GL_INVALID_ENUM; 3054 } 3055 else if (dimensions == 2) { 3056 if (target == GL_PROXY_TEXTURE_2D) { 3057 maxLevels = ctx->Const.MaxTextureLevels; 3058 } 3059 else if (target == GL_TEXTURE_2D) { 3060 maxLevels = ctx->Const.MaxTextureLevels; 3061 } 3062 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3063 if (!ctx->Extensions.ARB_texture_cube_map) 3064 return GL_INVALID_ENUM; /*target*/ 3065 maxLevels = ctx->Const.MaxCubeTextureLevels; 3066 } 3067 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3068 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3069 if (!ctx->Extensions.ARB_texture_cube_map) 3070 return GL_INVALID_ENUM; /*target*/ 3071 maxLevels = ctx->Const.MaxCubeTextureLevels; 3072 } 3073 else { 3074 return GL_INVALID_ENUM; /*target*/ 3075 } 3076 } 3077 else if (dimensions == 3) { 3078 /* 3D compressed textures not allowed */ 3079 return GL_INVALID_ENUM; 3080 } 3081 3082 maxTextureSize = 1 << (maxLevels - 1); 3083 3084 /* This will detect any invalid internalFormat value */ 3085 if (!is_compressed_format(ctx, internalFormat)) 3086 return GL_INVALID_ENUM; 3087 3088 /* This should really never fail */ 3089 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 3090 return GL_INVALID_ENUM; 3091 3092 if (border != 0) 3093 return GL_INVALID_VALUE; 3094 3095 /* 3096 * XXX We should probably use the proxy texture error check function here. 3097 */ 3098 if (width < 1 || width > maxTextureSize || 3099 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 3100 return GL_INVALID_VALUE; 3101 3102 if ((height < 1 || height > maxTextureSize || 3103 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 3104 && dimensions > 1) 3105 return GL_INVALID_VALUE; 3106 3107 if ((depth < 1 || depth > maxTextureSize || 3108 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 3109 && dimensions > 2) 3110 return GL_INVALID_VALUE; 3111 3112 /* For cube map, width must equal height */ 3113 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3114 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 3115 return GL_INVALID_VALUE; 3116 3117 if (level < 0 || level >= maxLevels) 3118 return GL_INVALID_VALUE; 3119 3120 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3121 depth, internalFormat); 3122 if (expectedSize != imageSize) 3123 return GL_INVALID_VALUE; 3124 3125#if FEATURE_EXT_texture_sRGB 3126 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 3127 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 3128 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 3129 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 3130 && border != 0) { 3131 return GL_INVALID_OPERATION; 3132 } 3133#endif 3134 3135 return GL_NO_ERROR; 3136} 3137 3138 3139/** 3140 * Error checking for glCompressedTexSubImage[123]D(). 3141 * \warning There are some bad assumptions here about the size of compressed 3142 * texture tiles (multiple of 4) used to test the validity of the 3143 * offset and size parameters. 3144 * \return error code or GL_NO_ERROR. 3145 */ 3146static GLenum 3147compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 3148 GLenum target, GLint level, 3149 GLint xoffset, GLint yoffset, GLint zoffset, 3150 GLsizei width, GLsizei height, GLsizei depth, 3151 GLenum format, GLsizei imageSize) 3152{ 3153 GLint expectedSize, maxLevels = 0, maxTextureSize; 3154 (void) zoffset; 3155 3156 if (dimensions == 1) { 3157 /* 1D compressed textures not allowed */ 3158 return GL_INVALID_ENUM; 3159 } 3160 else if (dimensions == 2) { 3161 if (target == GL_PROXY_TEXTURE_2D) { 3162 maxLevels = ctx->Const.MaxTextureLevels; 3163 } 3164 else if (target == GL_TEXTURE_2D) { 3165 maxLevels = ctx->Const.MaxTextureLevels; 3166 } 3167 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3168 if (!ctx->Extensions.ARB_texture_cube_map) 3169 return GL_INVALID_ENUM; /*target*/ 3170 maxLevels = ctx->Const.MaxCubeTextureLevels; 3171 } 3172 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3173 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3174 if (!ctx->Extensions.ARB_texture_cube_map) 3175 return GL_INVALID_ENUM; /*target*/ 3176 maxLevels = ctx->Const.MaxCubeTextureLevels; 3177 } 3178 else { 3179 return GL_INVALID_ENUM; /*target*/ 3180 } 3181 } 3182 else if (dimensions == 3) { 3183 /* 3D compressed textures not allowed */ 3184 return GL_INVALID_ENUM; 3185 } 3186 3187 maxTextureSize = 1 << (maxLevels - 1); 3188 3189 /* this will catch any invalid compressed format token */ 3190 if (!is_compressed_format(ctx, format)) 3191 return GL_INVALID_ENUM; 3192 3193 if (width < 1 || width > maxTextureSize) 3194 return GL_INVALID_VALUE; 3195 3196 if ((height < 1 || height > maxTextureSize) 3197 && dimensions > 1) 3198 return GL_INVALID_VALUE; 3199 3200 if (level < 0 || level >= maxLevels) 3201 return GL_INVALID_VALUE; 3202 3203 /* XXX these tests are specific to the compressed format. 3204 * this code should be generalized in some way. 3205 */ 3206 if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 3207 return GL_INVALID_VALUE; 3208 3209 if ((width & 3) != 0 && width != 2 && width != 1) 3210 return GL_INVALID_VALUE; 3211 3212 if ((height & 3) != 0 && height != 2 && height != 1) 3213 return GL_INVALID_VALUE; 3214 3215 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3216 depth, format); 3217 if (expectedSize != imageSize) 3218 return GL_INVALID_VALUE; 3219 3220 return GL_NO_ERROR; 3221} 3222 3223 3224 3225void GLAPIENTRY 3226_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 3227 GLenum internalFormat, GLsizei width, 3228 GLint border, GLsizei imageSize, 3229 const GLvoid *data) 3230{ 3231 GET_CURRENT_CONTEXT(ctx); 3232 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3233 3234 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 3235 _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n", 3236 _mesa_lookup_enum_by_nr(target), level, 3237 _mesa_lookup_enum_by_nr(internalFormat), 3238 width, border, imageSize, data); 3239 3240 if (target == GL_TEXTURE_1D) { 3241 /* non-proxy target */ 3242 struct gl_texture_unit *texUnit; 3243 struct gl_texture_object *texObj; 3244 struct gl_texture_image *texImage; 3245 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3246 internalFormat, width, 1, 1, border, imageSize); 3247 if (error) { 3248 _mesa_error(ctx, error, "glCompressedTexImage1D"); 3249 return; 3250 } 3251 3252 texUnit = _mesa_get_current_tex_unit(ctx); 3253 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3254 3255 _mesa_lock_texture(ctx, texObj); 3256 { 3257 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3258 if (!texImage) { 3259 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 3260 } 3261 else { 3262 if (texImage->Data) { 3263 ctx->Driver.FreeTexImageData( ctx, texImage ); 3264 } 3265 ASSERT(texImage->Data == NULL); 3266 3267 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3268 border, internalFormat); 3269 3270 ASSERT(ctx->Driver.CompressedTexImage1D); 3271 ctx->Driver.CompressedTexImage1D(ctx, target, level, 3272 internalFormat, width, border, 3273 imageSize, data, 3274 texObj, texImage); 3275 3276 _mesa_set_fetch_functions(texImage, 1); 3277 3278 check_gen_mipmap(ctx, target, texObj, level); 3279 3280 /* state update */ 3281 texObj->_Complete = GL_FALSE; 3282 ctx->NewState |= _NEW_TEXTURE; 3283 } 3284 } 3285 _mesa_unlock_texture(ctx, texObj); 3286 } 3287 else if (target == GL_PROXY_TEXTURE_1D) { 3288 /* Proxy texture: check for errors and update proxy state */ 3289 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3290 internalFormat, width, 1, 1, border, imageSize); 3291 if (!error) { 3292 ASSERT(ctx->Driver.TestProxyTexImage); 3293 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3294 internalFormat, GL_NONE, GL_NONE, 3295 width, 1, 1, border); 3296 } 3297 if (error) { 3298 /* if error, clear all proxy texture image parameters */ 3299 struct gl_texture_image *texImage; 3300 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3301 if (texImage) 3302 clear_teximage_fields(texImage); 3303 } 3304 else { 3305 /* store the teximage parameters */ 3306 struct gl_texture_unit *texUnit; 3307 struct gl_texture_object *texObj; 3308 struct gl_texture_image *texImage; 3309 texUnit = _mesa_get_current_tex_unit(ctx); 3310 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3311 3312 _mesa_lock_texture(ctx, texObj); 3313 { 3314 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3315 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3316 border, internalFormat); 3317 } 3318 _mesa_unlock_texture(ctx, texObj); 3319 } 3320 } 3321 else { 3322 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 3323 return; 3324 } 3325} 3326 3327 3328void GLAPIENTRY 3329_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3330 GLenum internalFormat, GLsizei width, 3331 GLsizei height, GLint border, GLsizei imageSize, 3332 const GLvoid *data) 3333{ 3334 GET_CURRENT_CONTEXT(ctx); 3335 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3336 3337 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 3338 _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n", 3339 _mesa_lookup_enum_by_nr(target), level, 3340 _mesa_lookup_enum_by_nr(internalFormat), 3341 width, height, border, imageSize, data); 3342 3343 if (target == GL_TEXTURE_2D || 3344 (ctx->Extensions.ARB_texture_cube_map && 3345 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3346 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 3347 /* non-proxy target */ 3348 struct gl_texture_unit *texUnit; 3349 struct gl_texture_object *texObj; 3350 struct gl_texture_image *texImage; 3351 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3352 internalFormat, width, height, 1, border, imageSize); 3353 if (error) { 3354 _mesa_error(ctx, error, "glCompressedTexImage2D"); 3355 return; 3356 } 3357 3358 texUnit = _mesa_get_current_tex_unit(ctx); 3359 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3360 3361 _mesa_lock_texture(ctx, texObj); 3362 { 3363 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3364 if (!texImage) { 3365 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 3366 } 3367 else { 3368 if (texImage->Data) { 3369 ctx->Driver.FreeTexImageData( ctx, texImage ); 3370 } 3371 ASSERT(texImage->Data == NULL); 3372 3373 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3374 border, internalFormat); 3375 3376 ASSERT(ctx->Driver.CompressedTexImage2D); 3377 ctx->Driver.CompressedTexImage2D(ctx, target, level, 3378 internalFormat, width, height, 3379 border, imageSize, data, 3380 texObj, texImage); 3381 3382 _mesa_set_fetch_functions(texImage, 2); 3383 3384 check_gen_mipmap(ctx, target, texObj, level); 3385 3386 /* state update */ 3387 texObj->_Complete = GL_FALSE; 3388 ctx->NewState |= _NEW_TEXTURE; 3389 } 3390 } 3391 _mesa_unlock_texture(ctx, texObj); 3392 } 3393 else if (target == GL_PROXY_TEXTURE_2D || 3394 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 3395 ctx->Extensions.ARB_texture_cube_map)) { 3396 /* Proxy texture: check for errors and update proxy state */ 3397 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3398 internalFormat, width, height, 1, border, imageSize); 3399 if (!error) { 3400 ASSERT(ctx->Driver.TestProxyTexImage); 3401 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3402 internalFormat, GL_NONE, GL_NONE, 3403 width, height, 1, border); 3404 } 3405 if (error) { 3406 /* if error, clear all proxy texture image parameters */ 3407 struct gl_texture_image *texImage; 3408 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3409 if (texImage) 3410 clear_teximage_fields(texImage); 3411 } 3412 else { 3413 /* store the teximage parameters */ 3414 struct gl_texture_unit *texUnit; 3415 struct gl_texture_object *texObj; 3416 struct gl_texture_image *texImage; 3417 texUnit = _mesa_get_current_tex_unit(ctx); 3418 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3419 3420 _mesa_lock_texture(ctx, texObj); 3421 { 3422 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3423 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3424 border, internalFormat); 3425 } 3426 _mesa_unlock_texture(ctx, texObj); 3427 } 3428 } 3429 else { 3430 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 3431 return; 3432 } 3433} 3434 3435 3436void GLAPIENTRY 3437_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3438 GLenum internalFormat, GLsizei width, 3439 GLsizei height, GLsizei depth, GLint border, 3440 GLsizei imageSize, const GLvoid *data) 3441{ 3442 GET_CURRENT_CONTEXT(ctx); 3443 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3444 3445 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 3446 _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n", 3447 _mesa_lookup_enum_by_nr(target), level, 3448 _mesa_lookup_enum_by_nr(internalFormat), 3449 width, height, depth, border, imageSize, data); 3450 3451 if (target == GL_TEXTURE_3D) { 3452 /* non-proxy target */ 3453 struct gl_texture_unit *texUnit; 3454 struct gl_texture_object *texObj; 3455 struct gl_texture_image *texImage; 3456 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3457 internalFormat, width, height, depth, border, imageSize); 3458 if (error) { 3459 _mesa_error(ctx, error, "glCompressedTexImage3D"); 3460 return; 3461 } 3462 3463 texUnit = _mesa_get_current_tex_unit(ctx); 3464 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3465 _mesa_lock_texture(ctx, texObj); 3466 { 3467 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3468 if (!texImage) { 3469 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 3470 } 3471 else { 3472 if (texImage->Data) { 3473 ctx->Driver.FreeTexImageData( ctx, texImage ); 3474 } 3475 ASSERT(texImage->Data == NULL); 3476 3477 _mesa_init_teximage_fields(ctx, target, texImage, 3478 width, height, depth, 3479 border, internalFormat); 3480 3481 ASSERT(ctx->Driver.CompressedTexImage3D); 3482 ctx->Driver.CompressedTexImage3D(ctx, target, level, 3483 internalFormat, 3484 width, height, depth, 3485 border, imageSize, data, 3486 texObj, texImage); 3487 3488 _mesa_set_fetch_functions(texImage, 3); 3489 3490 check_gen_mipmap(ctx, target, texObj, level); 3491 3492 /* state update */ 3493 texObj->_Complete = GL_FALSE; 3494 ctx->NewState |= _NEW_TEXTURE; 3495 } 3496 } 3497 _mesa_unlock_texture(ctx, texObj); 3498 } 3499 else if (target == GL_PROXY_TEXTURE_3D) { 3500 /* Proxy texture: check for errors and update proxy state */ 3501 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3502 internalFormat, width, height, depth, border, imageSize); 3503 if (!error) { 3504 ASSERT(ctx->Driver.TestProxyTexImage); 3505 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3506 internalFormat, GL_NONE, GL_NONE, 3507 width, height, depth, border); 3508 } 3509 if (error) { 3510 /* if error, clear all proxy texture image parameters */ 3511 struct gl_texture_image *texImage; 3512 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3513 if (texImage) 3514 clear_teximage_fields(texImage); 3515 } 3516 else { 3517 /* store the teximage parameters */ 3518 struct gl_texture_unit *texUnit; 3519 struct gl_texture_object *texObj; 3520 struct gl_texture_image *texImage; 3521 texUnit = _mesa_get_current_tex_unit(ctx); 3522 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3523 _mesa_lock_texture(ctx, texObj); 3524 { 3525 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3526 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 3527 depth, border, internalFormat); 3528 } 3529 _mesa_unlock_texture(ctx, texObj); 3530 } 3531 } 3532 else { 3533 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 3534 return; 3535 } 3536} 3537 3538 3539void GLAPIENTRY 3540_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3541 GLsizei width, GLenum format, 3542 GLsizei imageSize, const GLvoid *data) 3543{ 3544 struct gl_texture_unit *texUnit; 3545 struct gl_texture_object *texObj; 3546 struct gl_texture_image *texImage; 3547 GLenum error; 3548 GET_CURRENT_CONTEXT(ctx); 3549 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3550 3551 error = compressed_subtexture_error_check(ctx, 1, target, level, 3552 xoffset, 0, 0, /* pos */ 3553 width, 1, 1, /* size */ 3554 format, imageSize); 3555 if (error) { 3556 _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 3557 return; 3558 } 3559 3560 texUnit = _mesa_get_current_tex_unit(ctx); 3561 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3562 3563 _mesa_lock_texture(ctx, texObj); 3564 { 3565 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3566 assert(texImage); 3567 3568 if ((GLint) format != texImage->InternalFormat) { 3569 _mesa_error(ctx, GL_INVALID_OPERATION, 3570 "glCompressedTexSubImage1D(format)"); 3571 } 3572 else if ((width == 1 || width == 2) && 3573 (GLuint) width != texImage->Width) { 3574 _mesa_error(ctx, GL_INVALID_VALUE, 3575 "glCompressedTexSubImage1D(width)"); 3576 } 3577 else if (width > 0) { 3578 if (ctx->Driver.CompressedTexSubImage1D) { 3579 ctx->Driver.CompressedTexSubImage1D(ctx, target, level, 3580 xoffset, width, 3581 format, imageSize, data, 3582 texObj, texImage); 3583 } 3584 3585 check_gen_mipmap(ctx, target, texObj, level); 3586 3587 ctx->NewState |= _NEW_TEXTURE; 3588 } 3589 } 3590 _mesa_unlock_texture(ctx, texObj); 3591} 3592 3593 3594void GLAPIENTRY 3595_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3596 GLint yoffset, GLsizei width, GLsizei height, 3597 GLenum format, GLsizei imageSize, 3598 const GLvoid *data) 3599{ 3600 struct gl_texture_unit *texUnit; 3601 struct gl_texture_object *texObj; 3602 struct gl_texture_image *texImage; 3603 GLenum error; 3604 GET_CURRENT_CONTEXT(ctx); 3605 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3606 3607 error = compressed_subtexture_error_check(ctx, 2, target, level, 3608 xoffset, yoffset, 0, /* pos */ 3609 width, height, 1, /* size */ 3610 format, imageSize); 3611 if (error) { 3612 /* XXX proxy target? */ 3613 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 3614 return; 3615 } 3616 3617 texUnit = _mesa_get_current_tex_unit(ctx); 3618 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3619 3620 _mesa_lock_texture(ctx, texObj); 3621 { 3622 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3623 assert(texImage); 3624 3625 if ((GLint) format != texImage->InternalFormat) { 3626 _mesa_error(ctx, GL_INVALID_OPERATION, 3627 "glCompressedTexSubImage2D(format)"); 3628 } 3629 else if (((width == 1 || width == 2) 3630 && (GLuint) width != texImage->Width) || 3631 ((height == 1 || height == 2) 3632 && (GLuint) height != texImage->Height)) { 3633 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 3634 } 3635 else if (width > 0 && height > 0) { 3636 if (ctx->Driver.CompressedTexSubImage2D) { 3637 ctx->Driver.CompressedTexSubImage2D(ctx, target, level, 3638 xoffset, yoffset, width, height, 3639 format, imageSize, data, 3640 texObj, texImage); 3641 } 3642 3643 check_gen_mipmap(ctx, target, texObj, level); 3644 3645 ctx->NewState |= _NEW_TEXTURE; 3646 } 3647 } 3648 _mesa_unlock_texture(ctx, texObj); 3649} 3650 3651 3652void GLAPIENTRY 3653_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3654 GLint yoffset, GLint zoffset, GLsizei width, 3655 GLsizei height, GLsizei depth, GLenum format, 3656 GLsizei imageSize, const GLvoid *data) 3657{ 3658 struct gl_texture_unit *texUnit; 3659 struct gl_texture_object *texObj; 3660 struct gl_texture_image *texImage; 3661 GLenum error; 3662 GET_CURRENT_CONTEXT(ctx); 3663 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3664 3665 error = compressed_subtexture_error_check(ctx, 3, target, level, 3666 xoffset, yoffset, zoffset,/*pos*/ 3667 width, height, depth, /*size*/ 3668 format, imageSize); 3669 if (error) { 3670 _mesa_error(ctx, error, "glCompressedTexSubImage3D"); 3671 return; 3672 } 3673 3674 texUnit = _mesa_get_current_tex_unit(ctx); 3675 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3676 3677 _mesa_lock_texture(ctx, texObj); 3678 { 3679 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3680 assert(texImage); 3681 3682 if ((GLint) format != texImage->InternalFormat) { 3683 _mesa_error(ctx, GL_INVALID_OPERATION, 3684 "glCompressedTexSubImage3D(format)"); 3685 } 3686 else if (((width == 1 || width == 2) 3687 && (GLuint) width != texImage->Width) || 3688 ((height == 1 || height == 2) 3689 && (GLuint) height != texImage->Height) || 3690 ((depth == 1 || depth == 2) 3691 && (GLuint) depth != texImage->Depth)) { 3692 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 3693 } 3694 else if (width > 0 && height > 0 && depth > 0) { 3695 if (ctx->Driver.CompressedTexSubImage3D) { 3696 ctx->Driver.CompressedTexSubImage3D(ctx, target, level, 3697 xoffset, yoffset, zoffset, 3698 width, height, depth, 3699 format, imageSize, data, 3700 texObj, texImage); 3701 } 3702 3703 check_gen_mipmap(ctx, target, texObj, level); 3704 3705 ctx->NewState |= _NEW_TEXTURE; 3706 } 3707 } 3708 _mesa_unlock_texture(ctx, texObj); 3709} 3710 3711 3712