teximage.c revision 9fd2b0a698163b397b0a17493e52b27273e51b63
1 2/* 3 * Mesa 3-D graphics library 4 * Version: 3.3 5 * 6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27#ifdef PC_HEADER 28#include "all.h" 29#else 30#include "glheader.h" 31#include "context.h" 32#include "image.h" 33#include "mem.h" 34#include "mmath.h" 35#include "span.h" 36#include "teximage.h" 37#include "texstate.h" 38#include "types.h" 39#endif 40 41 42/* 43 * NOTES: 44 * 45 * Mesa's native texture datatype is GLubyte. Native formats are 46 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA, 47 * and GL_COLOR_INDEX. 48 * Device drivers are free to implement any internal format they want. 49 */ 50 51 52/* 53 * Compute log base 2 of n. 54 * If n isn't an exact power of two return -1. 55 * If n<0 return -1. 56 */ 57static int 58logbase2( int n ) 59{ 60 GLint i = 1; 61 GLint log2 = 0; 62 63 if (n<0) { 64 return -1; 65 } 66 67 while ( n > i ) { 68 i *= 2; 69 log2++; 70 } 71 if (i != n) { 72 return -1; 73 } 74 else { 75 return log2; 76 } 77} 78 79 80 81/* 82 * Given an internal texture format enum or 1, 2, 3, 4 return the 83 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 84 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. 85 * Return -1 if invalid enum. 86 */ 87GLint 88_mesa_base_tex_format( GLint format ) 89{ 90 switch (format) { 91 case GL_ALPHA: 92 case GL_ALPHA4: 93 case GL_ALPHA8: 94 case GL_ALPHA12: 95 case GL_ALPHA16: 96 return GL_ALPHA; 97 case 1: 98 case GL_LUMINANCE: 99 case GL_LUMINANCE4: 100 case GL_LUMINANCE8: 101 case GL_LUMINANCE12: 102 case GL_LUMINANCE16: 103 return GL_LUMINANCE; 104 case 2: 105 case GL_LUMINANCE_ALPHA: 106 case GL_LUMINANCE4_ALPHA4: 107 case GL_LUMINANCE6_ALPHA2: 108 case GL_LUMINANCE8_ALPHA8: 109 case GL_LUMINANCE12_ALPHA4: 110 case GL_LUMINANCE12_ALPHA12: 111 case GL_LUMINANCE16_ALPHA16: 112 return GL_LUMINANCE_ALPHA; 113 case GL_INTENSITY: 114 case GL_INTENSITY4: 115 case GL_INTENSITY8: 116 case GL_INTENSITY12: 117 case GL_INTENSITY16: 118 return GL_INTENSITY; 119 case 3: 120 case GL_RGB: 121 case GL_R3_G3_B2: 122 case GL_RGB4: 123 case GL_RGB5: 124 case GL_RGB8: 125 case GL_RGB10: 126 case GL_RGB12: 127 case GL_RGB16: 128 return GL_RGB; 129 case 4: 130 case GL_RGBA: 131 case GL_RGBA2: 132 case GL_RGBA4: 133 case GL_RGB5_A1: 134 case GL_RGBA8: 135 case GL_RGB10_A2: 136 case GL_RGBA12: 137 case GL_RGBA16: 138 return GL_RGBA; 139 case GL_COLOR_INDEX: 140 case GL_COLOR_INDEX1_EXT: 141 case GL_COLOR_INDEX2_EXT: 142 case GL_COLOR_INDEX4_EXT: 143 case GL_COLOR_INDEX8_EXT: 144 case GL_COLOR_INDEX12_EXT: 145 case GL_COLOR_INDEX16_EXT: 146 return GL_COLOR_INDEX; 147 default: 148 return -1; /* error */ 149 } 150} 151 152 153 154/* 155 * Given an internal texture format enum or 1, 2, 3, 4 return the 156 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 157 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the 158 * number of components for the format. Return -1 if invalid enum. 159 */ 160static GLint 161components_in_intformat( GLint format ) 162{ 163 switch (format) { 164 case GL_ALPHA: 165 case GL_ALPHA4: 166 case GL_ALPHA8: 167 case GL_ALPHA12: 168 case GL_ALPHA16: 169 return 1; 170 case 1: 171 case GL_LUMINANCE: 172 case GL_LUMINANCE4: 173 case GL_LUMINANCE8: 174 case GL_LUMINANCE12: 175 case GL_LUMINANCE16: 176 return 1; 177 case 2: 178 case GL_LUMINANCE_ALPHA: 179 case GL_LUMINANCE4_ALPHA4: 180 case GL_LUMINANCE6_ALPHA2: 181 case GL_LUMINANCE8_ALPHA8: 182 case GL_LUMINANCE12_ALPHA4: 183 case GL_LUMINANCE12_ALPHA12: 184 case GL_LUMINANCE16_ALPHA16: 185 return 2; 186 case GL_INTENSITY: 187 case GL_INTENSITY4: 188 case GL_INTENSITY8: 189 case GL_INTENSITY12: 190 case GL_INTENSITY16: 191 return 1; 192 case 3: 193 case GL_RGB: 194 case GL_R3_G3_B2: 195 case GL_RGB4: 196 case GL_RGB5: 197 case GL_RGB8: 198 case GL_RGB10: 199 case GL_RGB12: 200 case GL_RGB16: 201 return 3; 202 case 4: 203 case GL_RGBA: 204 case GL_RGBA2: 205 case GL_RGBA4: 206 case GL_RGB5_A1: 207 case GL_RGBA8: 208 case GL_RGB10_A2: 209 case GL_RGBA12: 210 case GL_RGBA16: 211 return 4; 212 case GL_COLOR_INDEX: 213 case GL_COLOR_INDEX1_EXT: 214 case GL_COLOR_INDEX2_EXT: 215 case GL_COLOR_INDEX4_EXT: 216 case GL_COLOR_INDEX8_EXT: 217 case GL_COLOR_INDEX12_EXT: 218 case GL_COLOR_INDEX16_EXT: 219 return 1; 220 default: 221 return -1; /* error */ 222 } 223} 224 225 226 227/* 228 * Examine the texImage->Format field and set the Red, Green, Blue, etc 229 * texel component sizes to default values. 230 * These fields are set only here by core Mesa but device drivers may 231 * overwritting these fields to indicate true texel resolution. 232 */ 233static void 234set_teximage_component_sizes( struct gl_texture_image *texImage ) 235{ 236 switch (texImage->Format) { 237 case GL_ALPHA: 238 texImage->RedBits = 0; 239 texImage->GreenBits = 0; 240 texImage->BlueBits = 0; 241 texImage->AlphaBits = 8; 242 texImage->IntensityBits = 0; 243 texImage->LuminanceBits = 0; 244 texImage->IndexBits = 0; 245 break; 246 case GL_LUMINANCE: 247 texImage->RedBits = 0; 248 texImage->GreenBits = 0; 249 texImage->BlueBits = 0; 250 texImage->AlphaBits = 0; 251 texImage->IntensityBits = 0; 252 texImage->LuminanceBits = 8; 253 texImage->IndexBits = 0; 254 break; 255 case GL_LUMINANCE_ALPHA: 256 texImage->RedBits = 0; 257 texImage->GreenBits = 0; 258 texImage->BlueBits = 0; 259 texImage->AlphaBits = 8; 260 texImage->IntensityBits = 0; 261 texImage->LuminanceBits = 8; 262 texImage->IndexBits = 0; 263 break; 264 case GL_INTENSITY: 265 texImage->RedBits = 0; 266 texImage->GreenBits = 0; 267 texImage->BlueBits = 0; 268 texImage->AlphaBits = 0; 269 texImage->IntensityBits = 8; 270 texImage->LuminanceBits = 0; 271 texImage->IndexBits = 0; 272 break; 273 case GL_RED: 274 texImage->RedBits = 8; 275 texImage->GreenBits = 0; 276 texImage->BlueBits = 0; 277 texImage->AlphaBits = 0; 278 texImage->IntensityBits = 0; 279 texImage->LuminanceBits = 0; 280 texImage->IndexBits = 0; 281 break; 282 case GL_GREEN: 283 texImage->RedBits = 0; 284 texImage->GreenBits = 8; 285 texImage->BlueBits = 0; 286 texImage->AlphaBits = 0; 287 texImage->IntensityBits = 0; 288 texImage->LuminanceBits = 0; 289 texImage->IndexBits = 0; 290 break; 291 case GL_BLUE: 292 texImage->RedBits = 0; 293 texImage->GreenBits = 0; 294 texImage->BlueBits = 8; 295 texImage->AlphaBits = 0; 296 texImage->IntensityBits = 0; 297 texImage->LuminanceBits = 0; 298 texImage->IndexBits = 0; 299 break; 300 case GL_RGB: 301 case GL_BGR: 302 texImage->RedBits = 8; 303 texImage->GreenBits = 8; 304 texImage->BlueBits = 8; 305 texImage->AlphaBits = 0; 306 texImage->IntensityBits = 0; 307 texImage->LuminanceBits = 0; 308 texImage->IndexBits = 0; 309 break; 310 case GL_RGBA: 311 case GL_BGRA: 312 case GL_ABGR_EXT: 313 texImage->RedBits = 8; 314 texImage->GreenBits = 8; 315 texImage->BlueBits = 8; 316 texImage->AlphaBits = 8; 317 texImage->IntensityBits = 0; 318 texImage->LuminanceBits = 0; 319 texImage->IndexBits = 0; 320 break; 321 case GL_COLOR_INDEX: 322 texImage->RedBits = 0; 323 texImage->GreenBits = 0; 324 texImage->BlueBits = 0; 325 texImage->AlphaBits = 0; 326 texImage->IntensityBits = 0; 327 texImage->LuminanceBits = 0; 328 texImage->IndexBits = 8; 329 break; 330 default: 331 gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); 332 } 333} 334 335 336 337/* 338 * Return new gl_texture_image struct with all fields initialized to zero. 339 */ 340struct gl_texture_image * 341gl_alloc_texture_image( void ) 342{ 343 return CALLOC_STRUCT(gl_texture_image); 344} 345 346 347 348/* 349 * Initialize most fields of a gl_texture_image struct. 350 */ 351static void 352init_texture_image( struct gl_texture_image *img, 353 GLsizei width, GLsizei height, GLsizei depth, 354 GLint border, GLenum internalFormat ) 355{ 356 ASSERT(img); 357 ASSERT(!img->Data); 358 img->Format = (GLenum) _mesa_base_tex_format(internalFormat); 359 set_teximage_component_sizes( img ); 360 img->IntFormat = (GLenum) internalFormat; 361 img->Border = border; 362 img->Width = width; 363 img->Height = height; 364 img->Depth = depth; 365 img->WidthLog2 = logbase2(width - 2 * border); 366 if (height == 1) /* 1-D texture */ 367 img->HeightLog2 = 0; 368 else 369 img->HeightLog2 = logbase2(height - 2 * border); 370 if (depth == 1) /* 2-D texture */ 371 img->DepthLog2 = 0; 372 else 373 img->DepthLog2 = logbase2(depth - 2 * border); 374 img->Width2 = 1 << img->WidthLog2; 375 img->Height2 = 1 << img->HeightLog2; 376 img->Depth2 = 1 << img->DepthLog2; 377 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 378} 379 380 381 382void 383gl_free_texture_image( struct gl_texture_image *teximage ) 384{ 385 if (teximage->Data) { 386 FREE( teximage->Data ); 387 teximage->Data = NULL; 388 } 389 FREE( teximage ); 390} 391 392 393 394/* Need this to prevent an out-of-bounds memory access when using 395 * X86 optimized code. 396 */ 397#ifdef USE_X86_ASM 398# define EXTRA_BYTE 1 399#else 400# define EXTRA_BYTE 0 401#endif 402 403 404 405/* 406 * Called by glTexImage[123]D. Fill in a texture image with data given 407 * by the client. All pixel transfer and unpack modes are handled here. 408 * NOTE: All texture image parameters should have already been error checked. 409 */ 410static void 411make_texture_image( GLcontext *ctx, 412 struct gl_texture_image *texImage, 413 GLenum srcFormat, GLenum srcType, const GLvoid *pixels, 414 const struct gl_pixelstore_attrib *unpacking) 415{ 416 GLint components, numPixels; 417 GLint internalFormat, width, height, depth, border; 418 419 ASSERT(ctx); 420 ASSERT(texImage); 421 ASSERT(!texImage->Data); 422 ASSERT(pixels); 423 ASSERT(unpacking); 424 425 internalFormat = texImage->IntFormat; 426 width = texImage->Width; 427 height = texImage->Height; 428 depth = texImage->Depth; 429 border = texImage->Border; 430 components = components_in_intformat(internalFormat); 431 432 ASSERT(width > 0); 433 ASSERT(height > 0); 434 ASSERT(depth > 0); 435 ASSERT(border == 0 || border == 1); 436 ASSERT(pixels); 437 ASSERT(unpacking); 438 ASSERT(components); 439 440 numPixels = width * height * depth; 441 442 texImage->Data = (GLubyte *) MALLOC(numPixels * components + EXTRA_BYTE); 443 if (!texImage->Data) 444 return; /* out of memory */ 445 446 /* 447 * OK, the texture image struct has been initialized and the texture 448 * image memory has been allocated. 449 * Now fill in the texture image from the source data. 450 * This includes applying the pixel transfer operations. 451 */ 452 453 /* try common 2D texture cases first */ 454 if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag 455 && !ctx->Pixel.IndexOffset && !ctx->Pixel.IndexShift 456 && srcType == GL_UNSIGNED_BYTE && depth == 1) { 457 458 if (srcFormat == internalFormat || 459 (srcFormat == GL_LUMINANCE && internalFormat == 1) || 460 (srcFormat == GL_LUMINANCE_ALPHA && internalFormat == 2) || 461 (srcFormat == GL_RGB && internalFormat == 3) || 462 (srcFormat == GL_RGBA && internalFormat == 4)) { 463 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA, 464 * GL_LUMINANCE_ALPHA, etc. texture formats. 465 */ 466 const GLubyte *src = (const GLubyte *) _mesa_image_address( 467 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0); 468 const GLint srcStride = _mesa_image_row_stride(unpacking, width, 469 srcFormat, srcType); 470 GLubyte *dst = texImage->Data; 471 GLint dstBytesPerRow = width * components * sizeof(GLubyte); 472 if (srcStride == dstBytesPerRow) { 473 MEMCPY(dst, src, height * dstBytesPerRow); 474 } 475 else { 476 GLint i; 477 for (i = 0; i < height; i++) { 478 MEMCPY(dst, src, dstBytesPerRow); 479 src += srcStride; 480 dst += dstBytesPerRow; 481 } 482 } 483 return; /* all done */ 484 } 485 else if (srcFormat == GL_RGBA && internalFormat == GL_RGB) { 486 /* commonly used by Quake */ 487 const GLubyte *src = (const GLubyte *) _mesa_image_address( 488 unpacking, pixels, width, height, srcFormat, srcType, 0, 0, 0); 489 const GLint srcStride = _mesa_image_row_stride(unpacking, width, 490 srcFormat, srcType); 491 GLubyte *dst = texImage->Data; 492 GLint i, j; 493 for (i = 0; i < height; i++) { 494 const GLubyte *s = src; 495 for (j = 0; j < width; j++) { 496 *dst++ = *s++; /*red*/ 497 *dst++ = *s++; /*green*/ 498 *dst++ = *s++; /*blue*/ 499 s++; /*alpha*/ 500 } 501 src += srcStride; 502 } 503 return; /* all done */ 504 } 505 } 506 507 508 /* 509 * General case solutions 510 */ 511 if (texImage->Format == GL_COLOR_INDEX) { 512 /* color index texture */ 513 const GLint destBytesPerRow = width * components * sizeof(GLubyte); 514 const GLenum dstType = GL_UNSIGNED_BYTE; 515 GLubyte *dest = texImage->Data; 516 GLint img, row; 517 for (img = 0; img < depth; img++) { 518 for (row = 0; row < height; row++) { 519 const GLvoid *source = _mesa_image_address(unpacking, 520 pixels, width, height, srcFormat, srcType, img, row, 0); 521 _mesa_unpack_index_span(ctx, width, dstType, dest, 522 srcType, source, unpacking, GL_TRUE); 523 dest += destBytesPerRow; 524 } 525 } 526 } 527 else { 528 /* regular, color texture */ 529 const GLint destBytesPerRow = width * components * sizeof(GLubyte); 530 const GLenum dstFormat = texImage->Format; 531 GLubyte *dest = texImage->Data; 532 GLint img, row; 533 for (img = 0; img < depth; img++) { 534 for (row = 0; row < height; row++) { 535 const GLvoid *source = _mesa_image_address(unpacking, 536 pixels, width, height, srcFormat, srcType, img, row, 0); 537 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, dest, 538 srcFormat, srcType, source, unpacking, GL_TRUE); 539 dest += destBytesPerRow; 540 } 541 } 542 } 543} 544 545 546 547/* 548 * glTexImage[123]D can accept a NULL image pointer. In this case we 549 * create a texture image with unspecified image contents per the OpenGL 550 * spec. This function creates an empty image for the given texture image. 551 */ 552static void 553make_null_texture( struct gl_texture_image *texImage ) 554{ 555 GLint components; 556 GLint numPixels; 557 558 ASSERT(texImage); 559 ASSERT(!texImage->Data); 560 561 components = components_in_intformat(texImage->IntFormat); 562 numPixels = texImage->Width * texImage->Height * texImage->Depth; 563 564 texImage->Data = (GLubyte *) MALLOC( numPixels * components + EXTRA_BYTE ); 565 566 /* 567 * Let's see if anyone finds this. If glTexImage2D() is called with 568 * a NULL image pointer then load the texture image with something 569 * interesting instead of leaving it indeterminate. 570 */ 571 if (texImage->Data) { 572 static const char message[8][32] = { 573 " X X XXXXX XXX X ", 574 " XX XX X X X X X ", 575 " X X X X X X X ", 576 " X X XXXX XXX XXXXX ", 577 " X X X X X X ", 578 " X X X X X X X ", 579 " X X XXXXX XXX X X ", 580 " " 581 }; 582 583 GLubyte *imgPtr = texImage->Data; 584 GLint i, j, k; 585 for (i = 0; i < texImage->Height; i++) { 586 GLint srcRow = 7 - i % 8; 587 for (j = 0; j < texImage->Width; j++) { 588 GLint srcCol = j % 32; 589 GLint texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 590 for (k=0;k<components;k++) { 591 *imgPtr++ = (GLubyte) texel; 592 } 593 } 594 } 595 } 596} 597 598 599 600/* 601 * Test glTexImage[123]D() parameters for errors. 602 * Input: 603 * dimensions - must be 1 or 2 or 3 604 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 605 */ 606static GLboolean 607texture_error_check( GLcontext *ctx, GLenum target, 608 GLint level, GLint internalFormat, 609 GLenum format, GLenum type, 610 GLuint dimensions, 611 GLint width, GLint height, 612 GLint depth, GLint border ) 613{ 614 GLboolean isProxy; 615 GLint iformat; 616 617 if (dimensions == 1) { 618 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D); 619 if (target != GL_TEXTURE_1D && !isProxy) { 620 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 621 return GL_TRUE; 622 } 623 } 624 else if (dimensions == 2) { 625 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D); 626 if (target != GL_TEXTURE_2D && !isProxy) { 627 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 628 return GL_TRUE; 629 } 630 } 631 else if (dimensions == 3) { 632 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D); 633 if (target != GL_TEXTURE_3D && !isProxy) { 634 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 635 return GL_TRUE; 636 } 637 } 638 else { 639 gl_problem( ctx, "bad dims in texture_error_check" ); 640 return GL_TRUE; 641 } 642 643 /* Border */ 644 if (border != 0 && border != 1) { 645 if (!isProxy) { 646 char message[100]; 647 sprintf(message, "glTexImage%dD(border)", dimensions); 648 gl_error(ctx, GL_INVALID_VALUE, message); 649 } 650 return GL_TRUE; 651 } 652 653 /* Width */ 654 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize 655 || logbase2( width - 2 * border ) < 0) { 656 if (!isProxy) { 657 char message[100]; 658 sprintf(message, "glTexImage%dD(width)", dimensions); 659 gl_error(ctx, GL_INVALID_VALUE, message); 660 } 661 return GL_TRUE; 662 } 663 664 /* Height */ 665 if (dimensions >= 2) { 666 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize 667 || logbase2( height - 2 * border ) < 0) { 668 if (!isProxy) { 669 char message[100]; 670 sprintf(message, "glTexImage%dD(height)", dimensions); 671 gl_error(ctx, GL_INVALID_VALUE, message); 672 } 673 return GL_TRUE; 674 } 675 } 676 677 /* Depth */ 678 if (dimensions >= 3) { 679 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize 680 || logbase2( depth - 2 * border ) < 0) { 681 if (!isProxy) { 682 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" ); 683 } 684 return GL_TRUE; 685 } 686 } 687 688 /* Level */ 689 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 690 if (!isProxy) { 691 char message[100]; 692 sprintf(message, "glTexImage%dD(level)", dimensions); 693 gl_error(ctx, GL_INVALID_VALUE, message); 694 } 695 return GL_TRUE; 696 } 697 698 iformat = _mesa_base_tex_format( internalFormat ); 699 if (iformat < 0) { 700 if (!isProxy) { 701 char message[100]; 702 sprintf(message, "glTexImage%dD(internalFormat)", dimensions); 703 gl_error(ctx, GL_INVALID_VALUE, message); 704 } 705 return GL_TRUE; 706 } 707 708 if (!_mesa_is_legal_format_and_type( format, type )) { 709 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 710 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 711 */ 712 if (!isProxy) { 713 char message[100]; 714 sprintf(message, "glTexImage%dD(format or type)", dimensions); 715 gl_error(ctx, GL_INVALID_OPERATION, message); 716 } 717 return GL_TRUE; 718 } 719 720 /* if we get here, the parameters are OK */ 721 return GL_FALSE; 722} 723 724 725 726/* 727 * Test glTexSubImage[123]D() parameters for errors. 728 * Input: 729 * dimensions - must be 1 or 2 or 3 730 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 731 */ 732static GLboolean 733subtexture_error_check( GLcontext *ctx, GLuint dimensions, 734 GLenum target, GLint level, 735 GLint xoffset, GLint yoffset, GLint zoffset, 736 GLint width, GLint height, GLint depth, 737 GLenum format, GLenum type ) 738{ 739 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 740 struct gl_texture_image *destTex; 741 742 if (dimensions == 1) { 743 if (target != GL_TEXTURE_1D) { 744 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 745 return GL_TRUE; 746 } 747 } 748 else if (dimensions == 2) { 749 if (target != GL_TEXTURE_2D) { 750 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 751 return GL_TRUE; 752 } 753 } 754 else if (dimensions == 3) { 755 if (target != GL_TEXTURE_3D) { 756 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 757 return GL_TRUE; 758 } 759 } 760 else { 761 gl_problem( ctx, "bad dims in texture_error_check" ); 762 return GL_TRUE; 763 } 764 765 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 766 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)"); 767 return GL_TRUE; 768 } 769 770 if (width < 0) { 771 char message[100]; 772 sprintf(message, "glTexSubImage%dD(width)", dimensions); 773 gl_error(ctx, GL_INVALID_VALUE, message); 774 return GL_TRUE; 775 } 776 if (height < 0 && dimensions > 1) { 777 char message[100]; 778 sprintf(message, "glTexSubImage%dD(height)", dimensions); 779 gl_error(ctx, GL_INVALID_VALUE, message); 780 return GL_TRUE; 781 } 782 if (depth < 0 && dimensions > 2) { 783 char message[100]; 784 sprintf(message, "glTexSubImage%dD(depth)", dimensions); 785 gl_error(ctx, GL_INVALID_VALUE, message); 786 return GL_TRUE; 787 } 788 789 destTex = texUnit->CurrentD[2]->Image[level]; 790 if (!destTex) { 791 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D"); 792 return GL_TRUE; 793 } 794 795 if (xoffset < -((GLint)destTex->Border)) { 796 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)"); 797 return GL_TRUE; 798 } 799 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 800 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)"); 801 return GL_TRUE; 802 } 803 if (dimensions > 1) { 804 if (yoffset < -((GLint)destTex->Border)) { 805 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)"); 806 return GL_TRUE; 807 } 808 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 809 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)"); 810 return GL_TRUE; 811 } 812 } 813 if (dimensions > 2) { 814 if (zoffset < -((GLint)destTex->Border)) { 815 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 816 return GL_TRUE; 817 } 818 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { 819 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 820 return GL_TRUE; 821 } 822 } 823 824 if (!_mesa_is_legal_format_and_type(format, type)) { 825 char message[100]; 826 sprintf(message, "glTexSubImage%dD(format or type)", dimensions); 827 gl_error(ctx, GL_INVALID_ENUM, message); 828 return GL_TRUE; 829 } 830 831 return GL_FALSE; 832} 833 834 835/* 836 * Test glCopyTexImage[12]D() parameters for errors. 837 * Input: dimensions - must be 1 or 2 or 3 838 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 839 */ 840static GLboolean 841copytexture_error_check( GLcontext *ctx, GLuint dimensions, 842 GLenum target, GLint level, GLint internalFormat, 843 GLint width, GLint height, GLint border ) 844{ 845 GLint iformat; 846 847 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D) { 848 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1/2D(target)" ); 849 return GL_TRUE; 850 } 851 852 if (dimensions == 1 && target != GL_TEXTURE_1D) { 853 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 854 return GL_TRUE; 855 } 856 else if (dimensions == 2 && target != GL_TEXTURE_2D) { 857 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 858 return GL_TRUE; 859 } 860 861 /* Border */ 862 if (border!=0 && border!=1) { 863 char message[100]; 864 sprintf(message, "glCopyTexImage%dD(border)", dimensions); 865 gl_error(ctx, GL_INVALID_VALUE, message); 866 return GL_TRUE; 867 } 868 869 /* Width */ 870 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize 871 || logbase2( width - 2 * border ) < 0) { 872 char message[100]; 873 sprintf(message, "glCopyTexImage%dD(width)", dimensions); 874 gl_error(ctx, GL_INVALID_VALUE, message); 875 return GL_TRUE; 876 } 877 878 /* Height */ 879 if (dimensions >= 2) { 880 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize 881 || logbase2( height - 2 * border ) < 0) { 882 char message[100]; 883 sprintf(message, "glCopyTexImage%dD(height)", dimensions); 884 gl_error(ctx, GL_INVALID_VALUE, message); 885 return GL_TRUE; 886 } 887 } 888 889 /* Level */ 890 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 891 char message[100]; 892 sprintf(message, "glCopyTexImage%dD(level)", dimensions); 893 gl_error(ctx, GL_INVALID_VALUE, message); 894 return GL_TRUE; 895 } 896 897 iformat = _mesa_base_tex_format( internalFormat ); 898 if (iformat < 0) { 899 char message[100]; 900 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions); 901 gl_error(ctx, GL_INVALID_VALUE, message); 902 return GL_TRUE; 903 } 904 905 /* if we get here, the parameters are OK */ 906 return GL_FALSE; 907} 908 909 910static GLboolean 911copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions, 912 GLenum target, GLint level, 913 GLint xoffset, GLint yoffset, GLint zoffset, 914 GLsizei width, GLsizei height ) 915{ 916 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 917 struct gl_texture_image *teximage; 918 919 if (dimensions == 1 && target != GL_TEXTURE_1D) { 920 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 921 return GL_TRUE; 922 } 923 else if (dimensions == 2 && target != GL_TEXTURE_2D) { 924 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 925 return GL_TRUE; 926 } 927 else if (dimensions == 3 && target != GL_TEXTURE_3D) { 928 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 929 return GL_TRUE; 930 } 931 932 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 933 char message[100]; 934 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions); 935 gl_error(ctx, GL_INVALID_VALUE, message); 936 return GL_TRUE; 937 } 938 939 if (width < 0) { 940 char message[100]; 941 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions ); 942 gl_error(ctx, GL_INVALID_VALUE, message); 943 return GL_TRUE; 944 } 945 if (dimensions > 1 && height < 0) { 946 char message[100]; 947 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions ); 948 gl_error(ctx, GL_INVALID_VALUE, message); 949 return GL_TRUE; 950 } 951 952 teximage = texUnit->CurrentD[dimensions]->Image[level]; 953 if (!teximage) { 954 char message[100]; 955 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions); 956 gl_error(ctx, GL_INVALID_OPERATION, message); 957 return GL_TRUE; 958 } 959 960 if (xoffset < -((GLint)teximage->Border)) { 961 char message[100]; 962 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions); 963 gl_error(ctx, GL_INVALID_VALUE, message); 964 return GL_TRUE; 965 } 966 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { 967 char message[100]; 968 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions); 969 gl_error(ctx, GL_INVALID_VALUE, message); 970 return GL_TRUE; 971 } 972 if (dimensions > 1) { 973 if (yoffset < -((GLint)teximage->Border)) { 974 char message[100]; 975 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions); 976 gl_error(ctx, GL_INVALID_VALUE, message); 977 return GL_TRUE; 978 } 979 /* NOTE: we're adding the border here, not subtracting! */ 980 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { 981 char message[100]; 982 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions); 983 gl_error(ctx, GL_INVALID_VALUE, message); 984 return GL_TRUE; 985 } 986 } 987 988 if (dimensions > 2) { 989 if (zoffset < -((GLint)teximage->Border)) { 990 char message[100]; 991 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions); 992 gl_error(ctx, GL_INVALID_VALUE, message); 993 return GL_TRUE; 994 } 995 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { 996 char message[100]; 997 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 998 gl_error(ctx, GL_INVALID_VALUE, message); 999 return GL_TRUE; 1000 } 1001 } 1002 1003 /* if we get here, the parameters are OK */ 1004 return GL_FALSE; 1005} 1006 1007 1008 1009 1010/* 1011 * Called from the API. Note that width includes the border. 1012 */ 1013void 1014_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 1015 GLsizei width, GLint border, GLenum format, 1016 GLenum type, const GLvoid *pixels ) 1017{ 1018 GET_CURRENT_CONTEXT(ctx); 1019 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); 1020 1021 if (target==GL_TEXTURE_1D) { 1022 struct gl_texture_unit *texUnit; 1023 struct gl_texture_object *texObj; 1024 struct gl_texture_image *texImage; 1025 1026 if (texture_error_check( ctx, target, level, internalFormat, 1027 format, type, 1, width, 1, 1, border )) { 1028 return; /* error in texture image was detected */ 1029 } 1030 1031 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1032 texObj = texUnit->CurrentD[1]; 1033 texImage = texObj->Image[level]; 1034 1035 if (!texImage) { 1036 texImage = gl_alloc_texture_image(); 1037 texObj->Image[level] = texImage; 1038 if (!texImage) { 1039 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 1040 return; 1041 } 1042 } 1043 else if (texImage->Data) { 1044 FREE(texImage->Data); 1045 texImage->Data = NULL; 1046 } 1047 1048 /* setup the teximage struct's fields */ 1049 init_texture_image(texImage, width, 1, 1, border, internalFormat); 1050 1051 /* process the texture image */ 1052 if (pixels) { 1053 GLboolean retain = GL_TRUE; 1054 GLboolean success = GL_FALSE; 1055 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1056 && ctx->Driver.TexImage1D) { 1057 /* let device driver try to use raw image */ 1058 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format, 1059 type, pixels, &ctx->Unpack, 1060 texObj, texImage, &retain); 1061 } 1062 if (retain || !success) { 1063 /* make internal copy of the texture image */ 1064 make_texture_image(ctx, texImage, format, type, 1065 pixels, &ctx->Unpack); 1066 if (!success && ctx->Driver.TexImage1D) { 1067 /* let device driver try to use unpacked image */ 1068 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 1069 GL_UNSIGNED_BYTE, texImage->Data, 1070 &_mesa_native_packing, 1071 texObj, texImage, &retain); 1072 } 1073 } 1074 if (!retain && texImage->Data) { 1075 FREE(texImage->Data); 1076 texImage->Data = NULL; 1077 } 1078 } 1079 else { 1080 make_null_texture(texImage); 1081 if (ctx->Driver.TexImage1D) { 1082 GLboolean retain; 1083 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 1084 GL_UNSIGNED_BYTE, texImage->Data, 1085 &_mesa_native_packing, 1086 texObj, texImage, &retain); 1087 } 1088 } 1089 1090 /* state update */ 1091 gl_put_texobj_on_dirty_list( ctx, texObj ); 1092 ctx->NewState |= NEW_TEXTURING; 1093 } 1094 else if (target==GL_PROXY_TEXTURE_1D) { 1095 /* Proxy texture: check for errors and update proxy state */ 1096 if (texture_error_check( ctx, target, level, internalFormat, 1097 format, type, 1, width, 1, 1, border )) { 1098 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1099 MEMSET( ctx->Texture.Proxy1D->Image[level], 0, 1100 sizeof(struct gl_texture_image) ); 1101 } 1102 } 1103 else { 1104 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; 1105 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); 1106 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalFormat; 1107 ctx->Texture.Proxy1D->Image[level]->Border = border; 1108 ctx->Texture.Proxy1D->Image[level]->Width = width; 1109 ctx->Texture.Proxy1D->Image[level]->Height = 1; 1110 ctx->Texture.Proxy1D->Image[level]->Depth = 1; 1111 } 1112 } 1113 else { 1114 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1115 return; 1116 } 1117} 1118 1119 1120void 1121_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 1122 GLsizei width, GLsizei height, GLint border, 1123 GLenum format, GLenum type, 1124 const GLvoid *pixels ) 1125{ 1126 GET_CURRENT_CONTEXT(ctx); 1127 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); 1128 1129 if (target==GL_TEXTURE_2D) { 1130 struct gl_texture_unit *texUnit; 1131 struct gl_texture_object *texObj; 1132 struct gl_texture_image *texImage; 1133 1134 if (texture_error_check( ctx, target, level, internalFormat, 1135 format, type, 2, width, height, 1, border )) { 1136 return; /* error in texture image was detected */ 1137 } 1138 1139 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1140 texObj = texUnit->CurrentD[2]; 1141 texImage = texObj->Image[level]; 1142 1143 if (!texImage) { 1144 texImage = gl_alloc_texture_image(); 1145 texObj->Image[level] = texImage; 1146 if (!texImage) { 1147 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 1148 return; 1149 } 1150 } 1151 else if (texImage->Data) { 1152 FREE(texImage->Data); 1153 texImage->Data = NULL; 1154 } 1155 1156 /* setup the teximage struct's fields */ 1157 init_texture_image(texImage, width, height, 1, border, internalFormat); 1158 1159 /* process the texture image */ 1160 if (pixels) { 1161 GLboolean retain = GL_TRUE; 1162 GLboolean success = GL_FALSE; 1163 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1164 && ctx->Driver.TexImage2D) { 1165 /* let device driver try to use raw image */ 1166 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format, 1167 type, pixels, &ctx->Unpack, 1168 texObj, texImage, &retain); 1169 } 1170 if (retain || !success) { 1171 /* make internal copy of the texture image */ 1172 make_texture_image(ctx, texImage, format, type, 1173 pixels, &ctx->Unpack); 1174 if (!success && ctx->Driver.TexImage2D) { 1175 /* let device driver try to use unpacked image */ 1176 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, 1177 GL_UNSIGNED_BYTE, texImage->Data, 1178 &_mesa_native_packing, 1179 texObj, texImage, &retain); 1180 } 1181 } 1182 if (!retain && texImage->Data) { 1183 FREE(texImage->Data); 1184 texImage->Data = NULL; 1185 } 1186 } 1187 else { 1188 make_null_texture(texImage); 1189 if (ctx->Driver.TexImage2D) { 1190 GLboolean retain; 1191 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format, 1192 GL_UNSIGNED_BYTE, texImage->Data, 1193 &_mesa_native_packing, 1194 texObj, texImage, &retain); 1195 } 1196 } 1197 1198#define OLD_DD_TEXTURE 1199#ifdef OLD_DD_TEXTURE 1200 /* XXX this will be removed in the future */ 1201 if (ctx->Driver.TexImage) { 1202 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat, 1203 texImage ); 1204 } 1205#endif 1206 1207 /* state update */ 1208 gl_put_texobj_on_dirty_list( ctx, texObj ); 1209 ctx->NewState |= NEW_TEXTURING; 1210 } 1211 else if (target==GL_PROXY_TEXTURE_2D) { 1212 /* Proxy texture: check for errors and update proxy state */ 1213 if (texture_error_check( ctx, target, level, internalFormat, 1214 format, type, 2, width, height, 1, border )) { 1215 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1216 MEMSET( ctx->Texture.Proxy2D->Image[level], 0, 1217 sizeof(struct gl_texture_image) ); 1218 } 1219 } 1220 else { 1221 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format; 1222 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] ); 1223 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalFormat; 1224 ctx->Texture.Proxy2D->Image[level]->Border = border; 1225 ctx->Texture.Proxy2D->Image[level]->Width = width; 1226 ctx->Texture.Proxy2D->Image[level]->Height = height; 1227 ctx->Texture.Proxy2D->Image[level]->Depth = 1; 1228 } 1229 } 1230 else { 1231 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 1232 return; 1233 } 1234} 1235 1236 1237 1238/* 1239 * Called by the API or display list executor. 1240 * Note that width and height include the border. 1241 */ 1242void 1243_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 1244 GLsizei width, GLsizei height, GLsizei depth, 1245 GLint border, GLenum format, GLenum type, 1246 const GLvoid *pixels ) 1247{ 1248 GET_CURRENT_CONTEXT(ctx); 1249 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D"); 1250 1251 if (target==GL_TEXTURE_3D_EXT) { 1252 struct gl_texture_unit *texUnit; 1253 struct gl_texture_object *texObj; 1254 struct gl_texture_image *texImage; 1255 if (texture_error_check( ctx, target, level, internalFormat, 1256 format, type, 3, width, height, depth, 1257 border )) { 1258 return; /* error in texture image was detected */ 1259 } 1260 1261 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1262 texObj = texUnit->CurrentD[3]; 1263 texImage = texObj->Image[level]; 1264 1265 if (!texImage) { 1266 texImage = gl_alloc_texture_image(); 1267 texObj->Image[level] = texImage; 1268 if (!texImage) { 1269 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 1270 return; 1271 } 1272 } 1273 else if (texImage->Data) { 1274 FREE(texImage->Data); 1275 texImage->Data = NULL; 1276 } 1277 1278 /* setup the teximage struct's fields */ 1279 init_texture_image(texImage, width, height, depth, 1280 border, internalFormat); 1281 1282 /* process the texture image */ 1283 if (pixels) { 1284 GLboolean retain = GL_TRUE; 1285 GLboolean success = GL_FALSE; 1286 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1287 && ctx->Driver.TexImage3D) { 1288 /* let device driver try to use raw image */ 1289 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format, 1290 type, pixels, &ctx->Unpack, 1291 texObj, texImage, &retain); 1292 } 1293 if (retain || !success) { 1294 /* make internal copy of the texture image */ 1295 make_texture_image(ctx, texImage, format, type, 1296 pixels, &ctx->Unpack); 1297 if (!success && ctx->Driver.TexImage3D) { 1298 /* let device driver try to use unpacked image */ 1299 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, 1300 GL_UNSIGNED_BYTE, texImage->Data, 1301 &_mesa_native_packing, 1302 texObj, texImage, &retain); 1303 } 1304 } 1305 if (!retain && texImage->Data) { 1306 FREE(texImage->Data); 1307 texImage->Data = NULL; 1308 } 1309 } 1310 else { 1311 make_null_texture(texImage); 1312 if (ctx->Driver.TexImage3D) { 1313 GLboolean retain; 1314 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format, 1315 GL_UNSIGNED_BYTE, texImage->Data, 1316 &_mesa_native_packing, 1317 texObj, texImage, &retain); 1318 } 1319 } 1320 1321 /* state update */ 1322 gl_put_texobj_on_dirty_list( ctx, texObj ); 1323 ctx->NewState |= NEW_TEXTURING; 1324 } 1325 else if (target==GL_PROXY_TEXTURE_3D_EXT) { 1326 /* Proxy texture: check for errors and update proxy state */ 1327 if (texture_error_check( ctx, target, level, internalFormat, 1328 format, type, 3, width, height, depth, 1329 border )) { 1330 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1331 MEMSET( ctx->Texture.Proxy3D->Image[level], 0, 1332 sizeof(struct gl_texture_image) ); 1333 } 1334 } 1335 else { 1336 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format; 1337 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] ); 1338 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalFormat; 1339 ctx->Texture.Proxy3D->Image[level]->Border = border; 1340 ctx->Texture.Proxy3D->Image[level]->Width = width; 1341 ctx->Texture.Proxy3D->Image[level]->Height = height; 1342 ctx->Texture.Proxy3D->Image[level]->Depth = depth; 1343 } 1344 } 1345 else { 1346 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1347 return; 1348 } 1349} 1350 1351 1352void 1353_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 1354 GLsizei width, GLsizei height, GLsizei depth, 1355 GLint border, GLenum format, GLenum type, 1356 const GLvoid *pixels ) 1357{ 1358 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 1359 depth, border, format, type, pixels); 1360} 1361 1362 1363/* 1364 * Fetch a texture image from the device driver. 1365 * Store the results in the given texture object at the given mipmap level. 1366 */ 1367static void 1368get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level, 1369 const struct gl_texture_object *texObj ) 1370{ 1371 GLvoid *image; 1372 GLenum imgFormat, imgType; 1373 GLboolean freeImage; 1374 struct gl_texture_image *texImage; 1375 GLint destComponents, numPixels, srcBytesPerTexel; 1376 1377 if (!ctx->Driver.GetTexImage) 1378 return; 1379 1380 image = (*ctx->Driver.GetTexImage)( ctx, target, level, 1381 &imgFormat, &imgType, &freeImage); 1382 if (!image) 1383 return; 1384 1385 texImage = texObj->Image[level]; 1386 ASSERT(texImage); 1387 if (!texImage) 1388 return; 1389 1390 destComponents = components_in_intformat(texImage->Format); 1391 assert(destComponents > 0); 1392 numPixels = texImage->Width * texImage->Height * texImage->Depth; 1393 assert(numPixels > 0); 1394 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType); 1395 assert(srcBytesPerTexel > 0); 1396 1397 if (!texImage->Data) { 1398 /* Allocate memory for the texture image data */ 1399 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE); 1400 } 1401 1402 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) { 1403 /* We got lucky! The driver's format and type match Mesa's format. */ 1404 if (texImage->Data) { 1405 MEMCPY(texImage->Data, image, numPixels * destComponents); 1406 } 1407 } 1408 else { 1409 /* Convert the texture image from the driver's format to Mesa's 1410 * internal format. 1411 */ 1412 const GLint width = texImage->Width; 1413 const GLint height = texImage->Height; 1414 const GLint depth = texImage->Depth; 1415 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan); 1416 const GLint srcBytesPerRow = width * srcBytesPerTexel; 1417 const GLenum dstType = GL_UNSIGNED_BYTE; 1418 const GLenum dstFormat = texImage->Format; 1419 const GLubyte *srcPtr = (const GLubyte *) image; 1420 GLubyte *destPtr = texImage->Data; 1421 1422 if (texImage->Format == GL_COLOR_INDEX) { 1423 /* color index texture */ 1424 GLint img, row; 1425 assert(imgFormat == GL_COLOR_INDEX); 1426 for (img = 0; img < depth; img++) { 1427 for (row = 0; row < height; row++) { 1428 _mesa_unpack_index_span(ctx, width, dstType, destPtr, 1429 imgType, srcPtr, &_mesa_native_packing, GL_FALSE); 1430 destPtr += destBytesPerRow; 1431 srcPtr += srcBytesPerRow; 1432 } 1433 } 1434 } 1435 else { 1436 /* color texture */ 1437 GLint img, row; 1438 for (img = 0; img < depth; img++) { 1439 for (row = 0; row < height; row++) { 1440 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr, 1441 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE); 1442 destPtr += destBytesPerRow; 1443 srcPtr += srcBytesPerRow; 1444 } 1445 } 1446 } 1447 } 1448 1449 if (freeImage) 1450 FREE(image); 1451} 1452 1453 1454void 1455_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 1456 GLenum type, GLvoid *pixels ) 1457{ 1458 GET_CURRENT_CONTEXT(ctx); 1459 const struct gl_texture_object *texObj; 1460 struct gl_texture_image *texImage; 1461 GLboolean discardImage; 1462 1463 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage"); 1464 1465 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 1466 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 1467 return; 1468 } 1469 1470 if (_mesa_sizeof_type(type) <= 0) { 1471 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 1472 return; 1473 } 1474 1475 if (_mesa_components_in_format(format) <= 0) { 1476 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 1477 return; 1478 } 1479 1480 if (!pixels) 1481 return; 1482 1483 switch (target) { 1484 case GL_TEXTURE_1D: 1485 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; 1486 break; 1487 case GL_TEXTURE_2D: 1488 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; 1489 break; 1490 case GL_TEXTURE_3D: 1491 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; 1492 break; 1493 default: 1494 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" ); 1495 return; 1496 } 1497 1498 texImage = texObj->Image[level]; 1499 if (!texImage) { 1500 /* invalid mipmap level */ 1501 return; 1502 } 1503 1504 if (!texImage->Data) { 1505 /* try to get the texture image from the device driver */ 1506 get_teximage_from_driver(ctx, target, level, texObj); 1507 discardImage = GL_TRUE; 1508 } 1509 else { 1510 discardImage = GL_FALSE; 1511 } 1512 1513 if (texImage->Data) { 1514 GLint width = texImage->Width; 1515 GLint height = texImage->Height; 1516 GLint row; 1517 1518 for (row = 0; row < height; row++) { 1519 /* compute destination address in client memory */ 1520 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels, 1521 width, height, 1522 format, type, 0, row, 0); 1523 1524 assert(dest); 1525 if (texImage->Format == GL_RGBA) { 1526 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte); 1527 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src, 1528 format, type, dest, &ctx->Pack, GL_TRUE ); 1529 } 1530 else { 1531 /* fetch RGBA row from texture image then pack it in client mem */ 1532 GLubyte rgba[MAX_WIDTH][4]; 1533 GLint i; 1534 const GLubyte *src; 1535 switch (texImage->Format) { 1536 case GL_ALPHA: 1537 src = texImage->Data + row * width * sizeof(GLubyte); 1538 for (i = 0; i < width; i++) { 1539 rgba[i][RCOMP] = 255; 1540 rgba[i][GCOMP] = 255; 1541 rgba[i][BCOMP] = 255; 1542 rgba[i][ACOMP] = src[i]; 1543 } 1544 break; 1545 case GL_LUMINANCE: 1546 src = texImage->Data + row * width * sizeof(GLubyte); 1547 for (i = 0; i < width; i++) { 1548 rgba[i][RCOMP] = src[i]; 1549 rgba[i][GCOMP] = src[i]; 1550 rgba[i][BCOMP] = src[i]; 1551 rgba[i][ACOMP] = 255; 1552 } 1553 break; 1554 case GL_LUMINANCE_ALPHA: 1555 src = texImage->Data + row * 2 * width * sizeof(GLubyte); 1556 for (i = 0; i < width; i++) { 1557 rgba[i][RCOMP] = src[i*2+0]; 1558 rgba[i][GCOMP] = src[i*2+0]; 1559 rgba[i][BCOMP] = src[i*2+0]; 1560 rgba[i][ACOMP] = src[i*2+1]; 1561 } 1562 break; 1563 case GL_INTENSITY: 1564 src = texImage->Data + row * width * sizeof(GLubyte); 1565 for (i = 0; i < width; i++) { 1566 rgba[i][RCOMP] = src[i]; 1567 rgba[i][GCOMP] = src[i]; 1568 rgba[i][BCOMP] = src[i]; 1569 rgba[i][ACOMP] = 255; 1570 } 1571 break; 1572 case GL_RGB: 1573 src = texImage->Data + row * 3 * width * sizeof(GLubyte); 1574 for (i = 0; i < width; i++) { 1575 rgba[i][RCOMP] = src[i*3+0]; 1576 rgba[i][GCOMP] = src[i*3+1]; 1577 rgba[i][BCOMP] = src[i*3+2]; 1578 rgba[i][ACOMP] = 255; 1579 } 1580 break; 1581 case GL_RGBA: 1582 /* this special case should have been handled above! */ 1583 gl_problem( ctx, "error 1 in gl_GetTexImage" ); 1584 break; 1585 case GL_COLOR_INDEX: 1586 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" ); 1587 break; 1588 default: 1589 gl_problem( ctx, "bad format in gl_GetTexImage" ); 1590 } 1591 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba, 1592 format, type, dest, &ctx->Pack, GL_TRUE ); 1593 } 1594 } 1595 1596 /* if we got the teximage from the device driver we'll discard it now */ 1597 if (discardImage) { 1598 FREE(texImage->Data); 1599 texImage->Data = NULL; 1600 } 1601 } 1602} 1603 1604 1605 1606void 1607_mesa_TexSubImage1D( GLenum target, GLint level, 1608 GLint xoffset, GLsizei width, 1609 GLenum format, GLenum type, 1610 const GLvoid *pixels ) 1611{ 1612 GET_CURRENT_CONTEXT(ctx); 1613 struct gl_texture_unit *texUnit; 1614 struct gl_texture_object *texObj; 1615 struct gl_texture_image *texImage; 1616 GLboolean success = GL_FALSE; 1617 1618 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 1619 width, 1, 1, format, type)) { 1620 return; /* error was detected */ 1621 } 1622 1623 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1624 texObj = texUnit->CurrentD[1]; 1625 texImage = texObj->Image[level]; 1626 assert(texImage); 1627 1628 if (width == 0 || !pixels) 1629 return; /* no-op, not an error */ 1630 1631 1632 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1633 && ctx->Driver.TexSubImage1D) { 1634 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset, 1635 width, format, type, pixels, 1636 &ctx->Unpack, texObj, texImage ); 1637 } 1638 if (!success) { 1639 /* XXX if Driver.TexSubImage1D, unpack image and try again? */ 1640 1641 const GLint texComponents = components_in_intformat(texImage->Format); 1642 const GLenum texFormat = texImage->Format; 1643 const GLint xoffsetb = xoffset + texImage->Border; 1644 GLboolean retain = GL_TRUE; 1645 if (!texImage->Data) { 1646 get_teximage_from_driver( ctx, target, level, texObj ); 1647 if (!texImage->Data) { 1648 make_null_texture(texImage); 1649 } 1650 if (!texImage->Data) 1651 return; /* we're really out of luck! */ 1652 } 1653 1654 if (texFormat == GL_COLOR_INDEX) { 1655 /* color index texture */ 1656 GLubyte *dst = texImage->Data + xoffsetb * texComponents; 1657 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, 1658 1, format, type, 0, 0, 0); 1659 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, 1660 type, src, &ctx->Unpack, GL_TRUE); 1661 } 1662 else { 1663 /* color texture */ 1664 GLubyte *dst = texImage->Data + xoffsetb * texComponents; 1665 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width, 1666 1, format, type, 0, 0, 0); 1667 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, 1668 type, src, &ctx->Unpack, GL_TRUE); 1669 } 1670 1671 if (ctx->Driver.TexImage1D) { 1672 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format, 1673 GL_UNSIGNED_BYTE, texImage->Data, 1674 &_mesa_native_packing, texObj, texImage, 1675 &retain ); 1676 } 1677 1678 if (!retain && texImage->Data) { 1679 FREE(texImage->Data); 1680 texImage->Data = NULL; 1681 } 1682 } 1683 1684 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/ 1685} 1686 1687 1688void 1689_mesa_TexSubImage2D( GLenum target, GLint level, 1690 GLint xoffset, GLint yoffset, 1691 GLsizei width, GLsizei height, 1692 GLenum format, GLenum type, 1693 const GLvoid *pixels ) 1694{ 1695 GET_CURRENT_CONTEXT(ctx); 1696 struct gl_texture_unit *texUnit; 1697 struct gl_texture_object *texObj; 1698 struct gl_texture_image *texImage; 1699 GLboolean success = GL_FALSE; 1700 1701 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 1702 width, height, 1, format, type)) { 1703 return; /* error was detected */ 1704 } 1705 1706 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1707 texObj = texUnit->CurrentD[2]; 1708 texImage = texObj->Image[level]; 1709 assert(texImage); 1710 1711 if (width == 0 || height == 0 || !pixels) 1712 return; /* no-op, not an error */ 1713 1714 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1715 && ctx->Driver.TexSubImage2D) { 1716 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset, 1717 yoffset, width, height, format, type, 1718 pixels, &ctx->Unpack, texObj, texImage ); 1719 } 1720 if (!success) { 1721 /* XXX if Driver.TexSubImage2D, unpack image and try again? */ 1722 1723 const GLint texComponents = components_in_intformat(texImage->Format); 1724 const GLenum texFormat = texImage->Format; 1725 const GLint xoffsetb = xoffset + texImage->Border; 1726 const GLint yoffsetb = yoffset + texImage->Border; 1727 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width, 1728 format, type); 1729 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte); 1730 GLboolean retain = GL_TRUE; 1731 1732 if (!texImage->Data) { 1733 get_teximage_from_driver( ctx, target, level, texObj ); 1734 if (!texImage->Data) { 1735 make_null_texture(texImage); 1736 } 1737 if (!texImage->Data) 1738 return; /* we're really out of luck! */ 1739 } 1740 1741 if (texFormat == GL_COLOR_INDEX) { 1742 /* color index texture */ 1743 GLubyte *dst = texImage->Data 1744 + (yoffsetb * texImage->Width + xoffsetb) * texComponents; 1745 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, 1746 width, height, format, type, 0, 0, 0); 1747 GLint row; 1748 for (row = 0; row < height; row++) { 1749 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type, 1750 (const GLvoid *) src, &ctx->Unpack, GL_TRUE); 1751 src += srcStride; 1752 dst += dstStride; 1753 } 1754 } 1755 else { 1756 /* color texture */ 1757 GLubyte *dst = texImage->Data 1758 + (yoffsetb * texImage->Width + xoffsetb) * texComponents; 1759 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, 1760 width, height, format, type, 0, 0, 0); 1761 GLint row; 1762 for (row = 0; row < height; row++) { 1763 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format, 1764 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); 1765 src += srcStride; 1766 dst += dstStride; 1767 } 1768 } 1769 1770 if (ctx->Driver.TexImage2D) { 1771 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format, 1772 GL_UNSIGNED_BYTE, texImage->Data, 1773 &_mesa_native_packing, texObj, texImage, 1774 &retain); 1775 } 1776 1777 if (!retain && texImage->Data) { 1778 FREE(texImage->Data); 1779 texImage->Data = NULL; 1780 } 1781 1782#ifdef OLD_DD_TEXTURE 1783 /* XXX this will be removed in the future */ 1784 if (ctx->Driver.TexSubImage) { 1785 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level, 1786 xoffset, yoffset, width, height, 1787 texImage->IntFormat, texImage); 1788 } 1789 else if (ctx->Driver.TexImage) { 1790 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj, 1791 level, texImage->IntFormat, texImage ); 1792 } 1793#endif 1794 } 1795} 1796 1797 1798 1799void 1800_mesa_TexSubImage3D( GLenum target, GLint level, 1801 GLint xoffset, GLint yoffset, GLint zoffset, 1802 GLsizei width, GLsizei height, GLsizei depth, 1803 GLenum format, GLenum type, 1804 const GLvoid *pixels ) 1805{ 1806 GET_CURRENT_CONTEXT(ctx); 1807 struct gl_texture_unit *texUnit; 1808 struct gl_texture_object *texObj; 1809 struct gl_texture_image *texImage; 1810 GLboolean success = GL_FALSE; 1811 1812 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 1813 width, height, depth, format, type)) { 1814 return; /* error was detected */ 1815 } 1816 1817 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1818 texObj = texUnit->CurrentD[3]; 1819 texImage = texObj->Image[level]; 1820 assert(texImage); 1821 1822 if (width == 0 || height == 0 || height == 0 || !pixels) 1823 return; /* no-op, not an error */ 1824 1825 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA 1826 && ctx->Driver.TexSubImage3D) { 1827 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset, 1828 yoffset, zoffset, width, height, depth, format, 1829 type, pixels, &ctx->Unpack, texObj, texImage ); 1830 } 1831 if (!success) { 1832 /* XXX if Driver.TexSubImage3D, unpack image and try again? */ 1833 1834 const GLint texComponents = components_in_intformat(texImage->Format); 1835 const GLenum texFormat = texImage->Format; 1836 const GLint xoffsetb = xoffset + texImage->Border; 1837 const GLint yoffsetb = yoffset + texImage->Border; 1838 const GLint zoffsetb = zoffset + texImage->Border; 1839 const GLint texWidth = texImage->Width; 1840 const GLint dstRectArea = texWidth * texImage->Height; 1841 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, 1842 width, format, type); 1843 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte); 1844 GLboolean retain = GL_TRUE; 1845 1846 if (texFormat == GL_COLOR_INDEX) { 1847 /* color index texture */ 1848 GLint img, row; 1849 for (img = 0; img < depth; img++) { 1850 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, 1851 width, height, format, type, img, 0, 0); 1852 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea 1853 + yoffsetb * texWidth + xoffsetb) * texComponents; 1854 for (row = 0; row < height; row++) { 1855 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, 1856 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); 1857 src += srcStride; 1858 dst += dstStride; 1859 } 1860 } 1861 } 1862 else { 1863 /* color texture */ 1864 GLint img, row; 1865 for (img = 0; img < depth; img++) { 1866 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels, 1867 width, height, format, type, img, 0, 0); 1868 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea 1869 + yoffsetb * texWidth + xoffsetb) * texComponents; 1870 for (row = 0; row < height; row++) { 1871 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, 1872 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE); 1873 src += srcStride; 1874 dst += dstStride; 1875 } 1876 } 1877 } 1878 1879 if (ctx->Driver.TexImage3D) { 1880 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format, 1881 GL_UNSIGNED_BYTE, texImage->Data, 1882 &_mesa_native_packing, texObj, texImage, 1883 &retain); 1884 } 1885 1886 if (!retain && texImage->Data) { 1887 FREE(texImage->Data); 1888 texImage->Data = NULL; 1889 } 1890 } 1891} 1892 1893 1894 1895/* 1896 * Read an RGBA image from the frame buffer. 1897 * This is used by glCopyTexSubImage[12]D(). 1898 * Input: ctx - the context 1899 * x, y - lower left corner 1900 * width, height - size of region to read 1901 * Return: pointer to block of GL_RGBA, GLubyte data. 1902 */ 1903static GLubyte * 1904read_color_image( GLcontext *ctx, GLint x, GLint y, 1905 GLsizei width, GLsizei height ) 1906{ 1907 GLint stride, i; 1908 GLubyte *image, *dst; 1909 1910 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte)); 1911 if (!image) 1912 return NULL; 1913 1914 /* Select buffer to read from */ 1915 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, 1916 ctx->Pixel.DriverReadBuffer ); 1917 1918 dst = image; 1919 stride = width * 4 * sizeof(GLubyte); 1920 for (i = 0; i < height; i++) { 1921 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i, 1922 (GLubyte (*)[4]) dst ); 1923 dst += stride; 1924 } 1925 1926 /* Read from draw buffer (the default) */ 1927 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, 1928 ctx->Color.DriverDrawBuffer ); 1929 1930 return image; 1931} 1932 1933 1934 1935void 1936_mesa_CopyTexImage1D( GLenum target, GLint level, 1937 GLenum internalFormat, 1938 GLint x, GLint y, 1939 GLsizei width, GLint border ) 1940{ 1941 GET_CURRENT_CONTEXT(ctx); 1942 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); 1943 1944 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 1945 width, 1, border)) 1946 return; 1947 1948 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA 1949 || !ctx->Driver.CopyTexImage1D 1950 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level, 1951 internalFormat, x, y, width, border)) 1952 { 1953 GLubyte *image = read_color_image( ctx, x, y, width, 1 ); 1954 if (!image) { 1955 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); 1956 return; 1957 } 1958 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width, 1959 border, GL_RGBA, GL_UNSIGNED_BYTE, image ); 1960 FREE(image); 1961 } 1962} 1963 1964 1965 1966void 1967_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 1968 GLint x, GLint y, GLsizei width, GLsizei height, 1969 GLint border ) 1970{ 1971 GET_CURRENT_CONTEXT(ctx); 1972 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); 1973 1974 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 1975 width, height, border)) 1976 return; 1977 1978 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA 1979 || !ctx->Driver.CopyTexImage2D 1980 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level, 1981 internalFormat, x, y, width, height, border)) 1982 { 1983 GLubyte *image = read_color_image( ctx, x, y, width, height ); 1984 if (!image) { 1985 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); 1986 return; 1987 } 1988 (ctx->Exec->TexImage2D)( target, level, internalFormat, width, 1989 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image ); 1990 FREE(image); 1991 } 1992} 1993 1994 1995 1996/* 1997 * Do the work of glCopyTexSubImage[123]D. 1998 */ 1999static void 2000copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, 2001 GLint width, GLint height, 2002 GLint srcx, GLint srcy, 2003 GLint dstx, GLint dsty, GLint dstz ) 2004{ 2005 GLint i; 2006 GLint format, components, rectarea; 2007 GLint texwidth, texheight, zoffset; 2008 2009 /* dst[xyz] may be negative if we have a texture border! */ 2010 dstx += dest->Border; 2011 dsty += dest->Border; 2012 dstz += dest->Border; 2013 texwidth = dest->Width; 2014 texheight = dest->Height; 2015 rectarea = texwidth * texheight; 2016 zoffset = dstz * rectarea; 2017 format = dest->Format; 2018 components = components_in_intformat( format ); 2019 2020 /* Select buffer to read from */ 2021 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer, 2022 ctx->Pixel.DriverReadBuffer ); 2023 2024 for (i = 0;i < height; i++) { 2025 GLubyte rgba[MAX_WIDTH][4]; 2026 GLubyte *dst; 2027 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba ); 2028 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components; 2029 _mesa_unpack_ubyte_color_span(ctx, width, format, dst, 2030 GL_RGBA, GL_UNSIGNED_BYTE, rgba, 2031 &_mesa_native_packing, GL_TRUE); 2032 } 2033 2034 /* Read from draw buffer (the default) */ 2035 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer, 2036 ctx->Color.DriverDrawBuffer ); 2037} 2038 2039 2040 2041 2042void 2043_mesa_CopyTexSubImage1D( GLenum target, GLint level, 2044 GLint xoffset, GLint x, GLint y, GLsizei width ) 2045{ 2046 GET_CURRENT_CONTEXT(ctx); 2047 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); 2048 2049 if (copytexsubimage_error_check(ctx, 1, target, level, 2050 xoffset, 0, 0, width, 1)) 2051 return; 2052 2053 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA 2054 || !ctx->Driver.CopyTexSubImage1D 2055 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level, 2056 xoffset, x, y, width)) { 2057 struct gl_texture_unit *texUnit; 2058 struct gl_texture_image *teximage; 2059 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2060 teximage = texUnit->CurrentD[1]->Image[level]; 2061 assert(teximage); 2062 if (teximage->Data) { 2063 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0); 2064 /* tell driver about the change */ 2065 /* XXX this is obsolete */ 2066 if (ctx->Driver.TexImage) { 2067 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, 2068 texUnit->CurrentD[1], 2069 level, teximage->IntFormat, teximage ); 2070 } 2071 } 2072 } 2073} 2074 2075 2076 2077void 2078_mesa_CopyTexSubImage2D( GLenum target, GLint level, 2079 GLint xoffset, GLint yoffset, 2080 GLint x, GLint y, GLsizei width, GLsizei height ) 2081{ 2082 GET_CURRENT_CONTEXT(ctx); 2083 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); 2084 2085 if (copytexsubimage_error_check(ctx, 2, target, level, 2086 xoffset, yoffset, 0, width, height)) 2087 return; 2088 2089 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA 2090 || !ctx->Driver.CopyTexSubImage2D 2091 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level, 2092 xoffset, yoffset, x, y, width, height )) { 2093 struct gl_texture_unit *texUnit; 2094 struct gl_texture_image *teximage; 2095 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2096 teximage = texUnit->CurrentD[2]->Image[level]; 2097 assert(teximage); 2098 if (teximage->Data) { 2099 copy_tex_sub_image(ctx, teximage, width, height, 2100 x, y, xoffset, yoffset, 0); 2101 /* tell driver about the change */ 2102 /* XXX this is obsolete */ 2103 if (ctx->Driver.TexImage) { 2104 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, 2105 texUnit->CurrentD[2], 2106 level, teximage->IntFormat, teximage ); 2107 } 2108 } 2109 } 2110} 2111 2112 2113 2114void 2115_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2116 GLint xoffset, GLint yoffset, GLint zoffset, 2117 GLint x, GLint y, GLsizei width, GLsizei height ) 2118{ 2119 GET_CURRENT_CONTEXT(ctx); 2120 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D"); 2121 2122 if (copytexsubimage_error_check(ctx, 3, target, level, 2123 xoffset, yoffset, zoffset, width, height)) 2124 return; 2125 2126 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA 2127 || !ctx->Driver.CopyTexSubImage3D 2128 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level, 2129 xoffset, yoffset, zoffset, x, y, width, height )) { 2130 struct gl_texture_unit *texUnit; 2131 struct gl_texture_image *teximage; 2132 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2133 teximage = texUnit->CurrentD[3]->Image[level]; 2134 assert(teximage); 2135 if (teximage->Data) { 2136 copy_tex_sub_image(ctx, teximage, width, height, 2137 x, y, xoffset, yoffset, zoffset); 2138 /* tell driver about the change */ 2139 /* XXX this is obsolete */ 2140 if (ctx->Driver.TexImage) { 2141 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D, 2142 texUnit->CurrentD[3], 2143 level, teximage->IntFormat, teximage ); 2144 } 2145 } 2146 } 2147} 2148