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