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