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