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