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