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