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