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