teximage.c revision afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c
1/* $Id: teximage.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.1 6 * 7 * Copyright (C) 1999 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 <assert.h> 32#include <stdio.h> 33#include <stdlib.h> 34#include <string.h> 35#include "context.h" 36#include "image.h" 37#include "macros.h" 38#include "mmath.h" 39#include "span.h" 40#include "teximage.h" 41#include "texstate.h" 42#include "types.h" 43#ifdef XFree86Server 44#include "GL/xf86glx.h" 45#endif 46#endif 47 48 49/* 50 * NOTES: 51 * 52 * The internal texture storage convension is an array of N GLubytes 53 * where N = width * height * components. There is no padding. 54 */ 55 56 57 58 59/* 60 * Compute log base 2 of n. 61 * If n isn't an exact power of two return -1. 62 * If n<0 return -1. 63 */ 64static int logbase2( int n ) 65{ 66 GLint i = 1; 67 GLint log2 = 0; 68 69 if (n<0) { 70 return -1; 71 } 72 73 while ( n > i ) { 74 i *= 2; 75 log2++; 76 } 77 if (i != n) { 78 return -1; 79 } 80 else { 81 return log2; 82 } 83} 84 85 86 87/* 88 * Given an internal texture format enum or 1, 2, 3, 4 return the 89 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 90 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return -1 if 91 * invalid enum. 92 */ 93static GLint decode_internal_format( GLint format ) 94{ 95 switch (format) { 96 case GL_ALPHA: 97 case GL_ALPHA4: 98 case GL_ALPHA8: 99 case GL_ALPHA12: 100 case GL_ALPHA16: 101 return GL_ALPHA; 102 case 1: 103 case GL_LUMINANCE: 104 case GL_LUMINANCE4: 105 case GL_LUMINANCE8: 106 case GL_LUMINANCE12: 107 case GL_LUMINANCE16: 108 return GL_LUMINANCE; 109 case 2: 110 case GL_LUMINANCE_ALPHA: 111 case GL_LUMINANCE4_ALPHA4: 112 case GL_LUMINANCE6_ALPHA2: 113 case GL_LUMINANCE8_ALPHA8: 114 case GL_LUMINANCE12_ALPHA4: 115 case GL_LUMINANCE12_ALPHA12: 116 case GL_LUMINANCE16_ALPHA16: 117 return GL_LUMINANCE_ALPHA; 118 case GL_INTENSITY: 119 case GL_INTENSITY4: 120 case GL_INTENSITY8: 121 case GL_INTENSITY12: 122 case GL_INTENSITY16: 123 return GL_INTENSITY; 124 case 3: 125 case GL_RGB: 126 case GL_R3_G3_B2: 127 case GL_RGB4: 128 case GL_RGB5: 129 case GL_RGB8: 130 case GL_RGB10: 131 case GL_RGB12: 132 case GL_RGB16: 133 return GL_RGB; 134 case 4: 135 case GL_RGBA: 136 case GL_RGBA2: 137 case GL_RGBA4: 138 case GL_RGB5_A1: 139 case GL_RGBA8: 140 case GL_RGB10_A2: 141 case GL_RGBA12: 142 case GL_RGBA16: 143 return GL_RGBA; 144 case GL_COLOR_INDEX: 145 case GL_COLOR_INDEX1_EXT: 146 case GL_COLOR_INDEX2_EXT: 147 case GL_COLOR_INDEX4_EXT: 148 case GL_COLOR_INDEX8_EXT: 149 case GL_COLOR_INDEX12_EXT: 150 case GL_COLOR_INDEX16_EXT: 151 return GL_COLOR_INDEX; 152 default: 153 return -1; /* error */ 154 } 155} 156 157 158 159/* 160 * Given an internal texture format enum or 1, 2, 3, 4 return the 161 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE, 162 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the 163 * number of components for the format. Return -1 if invalid enum. 164 */ 165static GLint components_in_intformat( GLint format ) 166{ 167 switch (format) { 168 case GL_ALPHA: 169 case GL_ALPHA4: 170 case GL_ALPHA8: 171 case GL_ALPHA12: 172 case GL_ALPHA16: 173 return 1; 174 case 1: 175 case GL_LUMINANCE: 176 case GL_LUMINANCE4: 177 case GL_LUMINANCE8: 178 case GL_LUMINANCE12: 179 case GL_LUMINANCE16: 180 return 1; 181 case 2: 182 case GL_LUMINANCE_ALPHA: 183 case GL_LUMINANCE4_ALPHA4: 184 case GL_LUMINANCE6_ALPHA2: 185 case GL_LUMINANCE8_ALPHA8: 186 case GL_LUMINANCE12_ALPHA4: 187 case GL_LUMINANCE12_ALPHA12: 188 case GL_LUMINANCE16_ALPHA16: 189 return 2; 190 case GL_INTENSITY: 191 case GL_INTENSITY4: 192 case GL_INTENSITY8: 193 case GL_INTENSITY12: 194 case GL_INTENSITY16: 195 return 1; 196 case 3: 197 case GL_RGB: 198 case GL_R3_G3_B2: 199 case GL_RGB4: 200 case GL_RGB5: 201 case GL_RGB8: 202 case GL_RGB10: 203 case GL_RGB12: 204 case GL_RGB16: 205 return 3; 206 case 4: 207 case GL_RGBA: 208 case GL_RGBA2: 209 case GL_RGBA4: 210 case GL_RGB5_A1: 211 case GL_RGBA8: 212 case GL_RGB10_A2: 213 case GL_RGBA12: 214 case GL_RGBA16: 215 return 4; 216 case GL_COLOR_INDEX: 217 case GL_COLOR_INDEX1_EXT: 218 case GL_COLOR_INDEX2_EXT: 219 case GL_COLOR_INDEX4_EXT: 220 case GL_COLOR_INDEX8_EXT: 221 case GL_COLOR_INDEX12_EXT: 222 case GL_COLOR_INDEX16_EXT: 223 return 1; 224 default: 225 return -1; /* error */ 226 } 227} 228 229 230 231struct gl_texture_image *gl_alloc_texture_image( void ) 232{ 233 return (struct gl_texture_image *) calloc( 1, sizeof(struct gl_texture_image) ); 234} 235 236 237 238void gl_free_texture_image( struct gl_texture_image *teximage ) 239{ 240 if (teximage->Data) { 241 free( teximage->Data ); 242 } 243 free( teximage ); 244} 245 246 247 248/* 249 * Examine the texImage->Format field and set the Red, Green, Blue, etc 250 * texel component sizes to default values. 251 * These fields are set only here by core Mesa but device drivers may 252 * overwritting these fields to indicate true texel resolution. 253 */ 254static void set_teximage_component_sizes( struct gl_texture_image *texImage ) 255{ 256 switch (texImage->Format) { 257 case GL_ALPHA: 258 texImage->RedBits = 0; 259 texImage->GreenBits = 0; 260 texImage->BlueBits = 0; 261 texImage->AlphaBits = 8; 262 texImage->IntensityBits = 0; 263 texImage->LuminanceBits = 0; 264 texImage->IndexBits = 0; 265 break; 266 case GL_LUMINANCE: 267 texImage->RedBits = 0; 268 texImage->GreenBits = 0; 269 texImage->BlueBits = 0; 270 texImage->AlphaBits = 0; 271 texImage->IntensityBits = 0; 272 texImage->LuminanceBits = 8; 273 texImage->IndexBits = 0; 274 break; 275 case GL_LUMINANCE_ALPHA: 276 texImage->RedBits = 0; 277 texImage->GreenBits = 0; 278 texImage->BlueBits = 0; 279 texImage->AlphaBits = 8; 280 texImage->IntensityBits = 0; 281 texImage->LuminanceBits = 8; 282 texImage->IndexBits = 0; 283 break; 284 case GL_INTENSITY: 285 texImage->RedBits = 0; 286 texImage->GreenBits = 0; 287 texImage->BlueBits = 0; 288 texImage->AlphaBits = 0; 289 texImage->IntensityBits = 8; 290 texImage->LuminanceBits = 0; 291 texImage->IndexBits = 0; 292 break; 293 case GL_RGB: 294 texImage->RedBits = 8; 295 texImage->GreenBits = 8; 296 texImage->BlueBits = 8; 297 texImage->AlphaBits = 0; 298 texImage->IntensityBits = 0; 299 texImage->LuminanceBits = 0; 300 texImage->IndexBits = 0; 301 break; 302 case GL_RGBA: 303 texImage->RedBits = 8; 304 texImage->GreenBits = 8; 305 texImage->BlueBits = 8; 306 texImage->AlphaBits = 8; 307 texImage->IntensityBits = 0; 308 texImage->LuminanceBits = 0; 309 texImage->IndexBits = 0; 310 break; 311 case GL_COLOR_INDEX: 312 texImage->RedBits = 0; 313 texImage->GreenBits = 0; 314 texImage->BlueBits = 0; 315 texImage->AlphaBits = 0; 316 texImage->IntensityBits = 0; 317 texImage->LuminanceBits = 0; 318 texImage->IndexBits = 8; 319 break; 320 default: 321 gl_problem(NULL, "unexpected format in set_teximage_component_sizes"); 322 } 323} 324 325 326/* Need this to prevent an out-of-bounds memory access when using 327 * X86 optimized code. 328 */ 329#ifdef USE_X86_ASM 330# define EXTRA_BYTE 1 331#else 332# define EXTRA_BYTE 0 333#endif 334 335 336/* 337 * Given a gl_image, apply the pixel transfer scale, bias, and mapping 338 * to produce a gl_texture_image. Convert image data to GLubytes. 339 * Input: image - the incoming gl_image 340 * internalFormat - desired format of resultant texture 341 * border - texture border width (0 or 1) 342 * Return: pointer to a gl_texture_image or NULL if an error occurs. 343 */ 344static struct gl_texture_image * 345image_to_texture( GLcontext *ctx, const struct gl_image *image, 346 GLint internalFormat, GLint border ) 347{ 348 GLint components; 349 struct gl_texture_image *texImage; 350 GLint numPixels, pixel; 351 GLboolean scaleOrBias; 352 353 assert(image); 354 assert(image->Width>0); 355 assert(image->Height>0); 356 assert(image->Depth>0); 357 358 /* internalFormat = decode_internal_format(internalFormat);*/ 359 components = components_in_intformat(internalFormat); 360 numPixels = image->Width * image->Height * image->Depth; 361 362 texImage = gl_alloc_texture_image(); 363 if (!texImage) 364 return NULL; 365 366 texImage->Format = (GLenum) decode_internal_format(internalFormat); 367 set_teximage_component_sizes( texImage ); 368 texImage->IntFormat = (GLenum) internalFormat; 369 texImage->Border = border; 370 texImage->Width = image->Width; 371 texImage->Height = image->Height; 372 texImage->Depth = image->Depth; 373 texImage->WidthLog2 = logbase2(image->Width - 2*border); 374 if (image->Height==1) /* 1-D texture */ 375 texImage->HeightLog2 = 0; 376 else 377 texImage->HeightLog2 = logbase2(image->Height - 2*border); 378 if (image->Depth==1) /* 2-D texture */ 379 texImage->DepthLog2 = 0; 380 else 381 texImage->DepthLog2 = logbase2(image->Depth - 2*border); 382 texImage->Width2 = 1 << texImage->WidthLog2; 383 texImage->Height2 = 1 << texImage->HeightLog2; 384 texImage->Depth2 = 1 << texImage->DepthLog2; 385 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 ); 386 texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE ); 387 388 if (!texImage->Data) { 389 /* out of memory */ 390 gl_free_texture_image( texImage ); 391 return NULL; 392 } 393 394 /* Determine if scaling and/or biasing is needed */ 395 if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F || 396 ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F || 397 ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F || 398 ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) { 399 scaleOrBias = GL_TRUE; 400 } 401 else { 402 scaleOrBias = GL_FALSE; 403 } 404 405 switch (image->Type) { 406 case GL_BITMAP: 407 { 408 GLint shift = ctx->Pixel.IndexShift; 409 GLint offset = ctx->Pixel.IndexOffset; 410 /* MapIto[RGBA]Size must be powers of two */ 411 GLint rMask = ctx->Pixel.MapItoRsize-1; 412 GLint gMask = ctx->Pixel.MapItoGsize-1; 413 GLint bMask = ctx->Pixel.MapItoBsize-1; 414 GLint aMask = ctx->Pixel.MapItoAsize-1; 415 GLint i, j; 416 GLubyte *srcPtr = (GLubyte *) image->Data; 417 418 assert( image->Format==GL_COLOR_INDEX ); 419 420 for (j=0; j<image->Height; j++) { 421 GLubyte bitMask = 128; 422 for (i=0; i<image->Width; i++) { 423 GLint index; 424 GLubyte red, green, blue, alpha; 425 426 /* Fetch image color index */ 427 index = (*srcPtr & bitMask) ? 1 : 0; 428 bitMask = bitMask >> 1; 429 if (bitMask==0) { 430 bitMask = 128; 431 srcPtr++; 432 } 433 /* apply index shift and offset */ 434 if (shift>=0) { 435 index = (index << shift) + offset; 436 } 437 else { 438 index = (index >> -shift) + offset; 439 } 440 /* convert index to RGBA */ 441 red = (GLint) (ctx->Pixel.MapItoR[index & rMask] * 255.0F); 442 green = (GLint) (ctx->Pixel.MapItoG[index & gMask] * 255.0F); 443 blue = (GLint) (ctx->Pixel.MapItoB[index & bMask] * 255.0F); 444 alpha = (GLint) (ctx->Pixel.MapItoA[index & aMask] * 255.0F); 445 446 /* store texel (components are GLubytes in [0,255]) */ 447 pixel = j * image->Width + i; 448 switch (texImage->Format) { 449 case GL_ALPHA: 450 texImage->Data[pixel] = alpha; 451 break; 452 case GL_LUMINANCE: 453 texImage->Data[pixel] = red; 454 break; 455 case GL_LUMINANCE_ALPHA: 456 texImage->Data[pixel*2+0] = red; 457 texImage->Data[pixel*2+1] = alpha; 458 break; 459 case GL_INTENSITY: 460 texImage->Data[pixel] = red; 461 break; 462 case GL_RGB: 463 texImage->Data[pixel*3+0] = red; 464 texImage->Data[pixel*3+1] = green; 465 texImage->Data[pixel*3+2] = blue; 466 break; 467 case GL_RGBA: 468 texImage->Data[pixel*4+0] = red; 469 texImage->Data[pixel*4+1] = green; 470 texImage->Data[pixel*4+2] = blue; 471 texImage->Data[pixel*4+3] = alpha; 472 break; 473 default: 474 gl_problem(ctx,"Bad format in image_to_texture"); 475 return NULL; 476 } 477 } 478 if (bitMask!=128) { 479 srcPtr++; 480 } 481 } 482 } 483 break; 484 485 case GL_UNSIGNED_BYTE: 486 if (image->Format == texImage->Format && !scaleOrBias && !ctx->Pixel.MapColorFlag) { 487 switch (image->Format) { 488 case GL_COLOR_INDEX: 489 if (decode_internal_format(internalFormat)!=GL_COLOR_INDEX) { 490 /* convert color index to RGBA */ 491 for (pixel=0; pixel<numPixels; pixel++) { 492 GLint index = ((GLubyte*)image->Data)[pixel]; 493 index = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); 494 texImage->Data[pixel] = index; 495 } 496 numPixels = 0; 497 break; 498 } 499 case GL_ALPHA: 500 case GL_LUMINANCE: 501 case GL_INTENSITY: 502 MEMCPY(texImage->Data, image->Data, numPixels * 1); 503 numPixels = 0; 504 break; 505 case GL_LUMINANCE_ALPHA: 506 MEMCPY(texImage->Data, image->Data, numPixels * 2); 507 numPixels = 0; 508 break; 509 case GL_RGB: 510 MEMCPY(texImage->Data, image->Data, numPixels * 3); 511 numPixels = 0; 512 break; 513 case GL_RGBA: 514 MEMCPY(texImage->Data, image->Data, numPixels * 4); 515 numPixels = 0; 516 break; 517 default: 518 break; 519 } 520 } 521 for (pixel=0; pixel<numPixels; pixel++) { 522 GLubyte red, green, blue, alpha; 523 switch (image->Format) { 524 case GL_COLOR_INDEX: 525 if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { 526 /* a paletted texture */ 527 GLint index = ((GLubyte*)image->Data)[pixel]; 528 red = index; 529 } 530 else { 531 /* convert color index to RGBA */ 532 GLint index = ((GLubyte*)image->Data)[pixel]; 533 red = (GLint) (255.0F * ctx->Pixel.MapItoR[index]); 534 green = (GLint) (255.0F * ctx->Pixel.MapItoG[index]); 535 blue = (GLint) (255.0F * ctx->Pixel.MapItoB[index]); 536 alpha = (GLint) (255.0F * ctx->Pixel.MapItoA[index]); 537 } 538 break; 539 case GL_RGB: 540 /* Fetch image RGBA values */ 541 red = ((GLubyte*) image->Data)[pixel*3+0]; 542 green = ((GLubyte*) image->Data)[pixel*3+1]; 543 blue = ((GLubyte*) image->Data)[pixel*3+2]; 544 alpha = 255; 545 break; 546 case GL_RGBA: 547 red = ((GLubyte*) image->Data)[pixel*4+0]; 548 green = ((GLubyte*) image->Data)[pixel*4+1]; 549 blue = ((GLubyte*) image->Data)[pixel*4+2]; 550 alpha = ((GLubyte*) image->Data)[pixel*4+3]; 551 break; 552 case GL_RED: 553 red = ((GLubyte*) image->Data)[pixel]; 554 green = 0; 555 blue = 0; 556 alpha = 255; 557 break; 558 case GL_GREEN: 559 red = 0; 560 green = ((GLubyte*) image->Data)[pixel]; 561 blue = 0; 562 alpha = 255; 563 break; 564 case GL_BLUE: 565 red = 0; 566 green = 0; 567 blue = ((GLubyte*) image->Data)[pixel]; 568 alpha = 255; 569 break; 570 case GL_ALPHA: 571 red = 0; 572 green = 0; 573 blue = 0; 574 alpha = ((GLubyte*) image->Data)[pixel]; 575 break; 576 case GL_LUMINANCE: 577 red = ((GLubyte*) image->Data)[pixel]; 578 green = red; 579 blue = red; 580 alpha = 255; 581 break; 582 case GL_LUMINANCE_ALPHA: 583 red = ((GLubyte*) image->Data)[pixel*2+0]; 584 green = red; 585 blue = red; 586 alpha = ((GLubyte*) image->Data)[pixel*2+1]; 587 break; 588 default: 589 gl_problem(ctx,"Bad format (2) in image_to_texture"); 590 return NULL; 591 } 592 593 if (scaleOrBias || ctx->Pixel.MapColorFlag) { 594 /* Apply RGBA scale and bias */ 595 GLfloat r = UBYTE_COLOR_TO_FLOAT_COLOR(red); 596 GLfloat g = UBYTE_COLOR_TO_FLOAT_COLOR(green); 597 GLfloat b = UBYTE_COLOR_TO_FLOAT_COLOR(blue); 598 GLfloat a = UBYTE_COLOR_TO_FLOAT_COLOR(alpha); 599 if (scaleOrBias) { 600 /* r,g,b,a now in [0,1] */ 601 r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias; 602 g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; 603 b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; 604 a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; 605 r = CLAMP( r, 0.0F, 1.0F ); 606 g = CLAMP( g, 0.0F, 1.0F ); 607 b = CLAMP( b, 0.0F, 1.0F ); 608 a = CLAMP( a, 0.0F, 1.0F ); 609 } 610 /* Apply pixel maps */ 611 if (ctx->Pixel.MapColorFlag) { 612 GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize); 613 GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize); 614 GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize); 615 GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize); 616 r = ctx->Pixel.MapRtoR[ir]; 617 g = ctx->Pixel.MapGtoG[ig]; 618 b = ctx->Pixel.MapBtoB[ib]; 619 a = ctx->Pixel.MapAtoA[ia]; 620 } 621 red = (GLint) (r * 255.0F); 622 green = (GLint) (g * 255.0F); 623 blue = (GLint) (b * 255.0F); 624 alpha = (GLint) (a * 255.0F); 625 } 626 627 /* store texel (components are GLubytes in [0,255]) */ 628 switch (texImage->Format) { 629 case GL_COLOR_INDEX: 630 texImage->Data[pixel] = red; /* really an index */ 631 break; 632 case GL_ALPHA: 633 texImage->Data[pixel] = alpha; 634 break; 635 case GL_LUMINANCE: 636 texImage->Data[pixel] = red; 637 break; 638 case GL_LUMINANCE_ALPHA: 639 texImage->Data[pixel*2+0] = red; 640 texImage->Data[pixel*2+1] = alpha; 641 break; 642 case GL_INTENSITY: 643 texImage->Data[pixel] = red; 644 break; 645 case GL_RGB: 646 texImage->Data[pixel*3+0] = red; 647 texImage->Data[pixel*3+1] = green; 648 texImage->Data[pixel*3+2] = blue; 649 break; 650 case GL_RGBA: 651 texImage->Data[pixel*4+0] = red; 652 texImage->Data[pixel*4+1] = green; 653 texImage->Data[pixel*4+2] = blue; 654 texImage->Data[pixel*4+3] = alpha; 655 break; 656 default: 657 gl_problem(ctx,"Bad format (3) in image_to_texture"); 658 return NULL; 659 } 660 } 661 break; 662 663 case GL_FLOAT: 664 for (pixel=0; pixel<numPixels; pixel++) { 665 GLfloat red, green, blue, alpha; 666 switch (image->Format) { 667 case GL_COLOR_INDEX: 668 if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) { 669 /* a paletted texture */ 670 GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; 671 red = index; 672 } 673 else { 674 GLint shift = ctx->Pixel.IndexShift; 675 GLint offset = ctx->Pixel.IndexOffset; 676 /* MapIto[RGBA]Size must be powers of two */ 677 GLint rMask = ctx->Pixel.MapItoRsize-1; 678 GLint gMask = ctx->Pixel.MapItoGsize-1; 679 GLint bMask = ctx->Pixel.MapItoBsize-1; 680 GLint aMask = ctx->Pixel.MapItoAsize-1; 681 /* Fetch image color index */ 682 GLint index = (GLint) ((GLfloat*) image->Data)[pixel]; 683 /* apply index shift and offset */ 684 if (shift>=0) { 685 index = (index << shift) + offset; 686 } 687 else { 688 index = (index >> -shift) + offset; 689 } 690 /* convert index to RGBA */ 691 red = ctx->Pixel.MapItoR[index & rMask]; 692 green = ctx->Pixel.MapItoG[index & gMask]; 693 blue = ctx->Pixel.MapItoB[index & bMask]; 694 alpha = ctx->Pixel.MapItoA[index & aMask]; 695 } 696 break; 697 case GL_RGB: 698 /* Fetch image RGBA values */ 699 red = ((GLfloat*) image->Data)[pixel*3+0]; 700 green = ((GLfloat*) image->Data)[pixel*3+1]; 701 blue = ((GLfloat*) image->Data)[pixel*3+2]; 702 alpha = 1.0; 703 break; 704 case GL_RGBA: 705 red = ((GLfloat*) image->Data)[pixel*4+0]; 706 green = ((GLfloat*) image->Data)[pixel*4+1]; 707 blue = ((GLfloat*) image->Data)[pixel*4+2]; 708 alpha = ((GLfloat*) image->Data)[pixel*4+3]; 709 break; 710 case GL_RED: 711 red = ((GLfloat*) image->Data)[pixel]; 712 green = 0.0; 713 blue = 0.0; 714 alpha = 1.0; 715 break; 716 case GL_GREEN: 717 red = 0.0; 718 green = ((GLfloat*) image->Data)[pixel]; 719 blue = 0.0; 720 alpha = 1.0; 721 break; 722 case GL_BLUE: 723 red = 0.0; 724 green = 0.0; 725 blue = ((GLfloat*) image->Data)[pixel]; 726 alpha = 1.0; 727 break; 728 case GL_ALPHA: 729 red = 0.0; 730 green = 0.0; 731 blue = 0.0; 732 alpha = ((GLfloat*) image->Data)[pixel]; 733 break; 734 case GL_LUMINANCE: 735 red = ((GLfloat*) image->Data)[pixel]; 736 green = red; 737 blue = red; 738 alpha = 1.0; 739 break; 740 case GL_LUMINANCE_ALPHA: 741 red = ((GLfloat*) image->Data)[pixel*2+0]; 742 green = red; 743 blue = red; 744 alpha = ((GLfloat*) image->Data)[pixel*2+1]; 745 break; 746 default: 747 gl_problem(ctx,"Bad format (4) in image_to_texture"); 748 return NULL; 749 } 750 751 if (image->Format!=GL_COLOR_INDEX) { 752 /* Apply RGBA scale and bias */ 753 if (scaleOrBias) { 754 red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias; 755 green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias; 756 blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias; 757 alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias; 758 red = CLAMP( red, 0.0F, 1.0F ); 759 green = CLAMP( green, 0.0F, 1.0F ); 760 blue = CLAMP( blue, 0.0F, 1.0F ); 761 alpha = CLAMP( alpha, 0.0F, 1.0F ); 762 } 763 /* Apply pixel maps */ 764 if (ctx->Pixel.MapColorFlag) { 765 GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize); 766 GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize); 767 GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize); 768 GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize); 769 red = ctx->Pixel.MapRtoR[ir]; 770 green = ctx->Pixel.MapGtoG[ig]; 771 blue = ctx->Pixel.MapBtoB[ib]; 772 alpha = ctx->Pixel.MapAtoA[ia]; 773 } 774 } 775 776 /* store texel (components are GLubytes in [0,255]) */ 777 switch (texImage->Format) { 778 case GL_COLOR_INDEX: 779 /* a paletted texture */ 780 texImage->Data[pixel] = (GLint) (red * 255.0F); 781 break; 782 case GL_ALPHA: 783 texImage->Data[pixel] = (GLint) (alpha * 255.0F); 784 break; 785 case GL_LUMINANCE: 786 texImage->Data[pixel] = (GLint) (red * 255.0F); 787 break; 788 case GL_LUMINANCE_ALPHA: 789 texImage->Data[pixel*2+0] = (GLint) (red * 255.0F); 790 texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F); 791 break; 792 case GL_INTENSITY: 793 texImage->Data[pixel] = (GLint) (red * 255.0F); 794 break; 795 case GL_RGB: 796 texImage->Data[pixel*3+0] = (GLint) (red * 255.0F); 797 texImage->Data[pixel*3+1] = (GLint) (green * 255.0F); 798 texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F); 799 break; 800 case GL_RGBA: 801 texImage->Data[pixel*4+0] = (GLint) (red * 255.0F); 802 texImage->Data[pixel*4+1] = (GLint) (green * 255.0F); 803 texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F); 804 texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F); 805 break; 806 default: 807 gl_problem(ctx,"Bad format (5) in image_to_texture"); 808 return NULL; 809 } 810 } 811 break; 812 813 default: 814 gl_problem(ctx, "Bad image type in image_to_texture"); 815 return NULL; 816 } 817 818 return texImage; 819} 820 821 822 823/* 824 * glTexImage[123]D can accept a NULL image pointer. In this case we 825 * create a texture image with unspecified image contents per the OpenGL 826 * spec. 827 */ 828static struct gl_texture_image * 829make_null_texture( GLcontext *ctx, GLenum internalFormat, 830 GLsizei width, GLsizei height, GLsizei depth, GLint border ) 831{ 832 GLint components; 833 struct gl_texture_image *texImage; 834 GLint numPixels; 835 (void) ctx; 836 837 /*internalFormat = decode_internal_format(internalFormat);*/ 838 components = components_in_intformat(internalFormat); 839 numPixels = width * height * depth; 840 841 texImage = gl_alloc_texture_image(); 842 if (!texImage) 843 return NULL; 844 845 texImage->Format = (GLenum) decode_internal_format(internalFormat); 846 set_teximage_component_sizes( texImage ); 847 texImage->IntFormat = internalFormat; 848 texImage->Border = border; 849 texImage->Width = width; 850 texImage->Height = height; 851 texImage->Depth = depth; 852 texImage->WidthLog2 = logbase2(width - 2*border); 853 if (height==1) /* 1-D texture */ 854 texImage->HeightLog2 = 0; 855 else 856 texImage->HeightLog2 = logbase2(height - 2*border); 857 if (depth==1) /* 2-D texture */ 858 texImage->DepthLog2 = 0; 859 else 860 texImage->DepthLog2 = logbase2(depth - 2*border); 861 texImage->Width2 = 1 << texImage->WidthLog2; 862 texImage->Height2 = 1 << texImage->HeightLog2; 863 texImage->Depth2 = 1 << texImage->DepthLog2; 864 texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 ); 865 866 /* XXX should we really allocate memory for the image or let it be NULL? */ 867 /*texImage->Data = NULL;*/ 868 869 texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE ); 870 871 /* 872 * Let's see if anyone finds this. If glTexImage2D() is called with 873 * a NULL image pointer then load the texture image with something 874 * interesting instead of leaving it indeterminate. 875 */ 876 if (texImage->Data) { 877 char message[8][32] = { 878 " X X XXXXX XXX X ", 879 " XX XX X X X X X ", 880 " X X X X X X X ", 881 " X X XXXX XXX XXXXX ", 882 " X X X X X X ", 883 " X X X X X X X ", 884 " X X XXXXX XXX X X ", 885 " " 886 }; 887 888 GLubyte *imgPtr = texImage->Data; 889 GLint i, j, k; 890 for (i=0;i<height;i++) { 891 GLint srcRow = 7 - i % 8; 892 for (j=0;j<width;j++) { 893 GLint srcCol = j % 32; 894 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 895 for (k=0;k<components;k++) { 896 *imgPtr++ = texel; 897 } 898 } 899 } 900 } 901 902 return texImage; 903} 904 905 906 907/* 908 * Test glTexImage() parameters for errors. 909 * Input: 910 * dimensions - must be 1 or 2 or 3 911 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors 912 */ 913static GLboolean texture_error_check( GLcontext *ctx, GLenum target, 914 GLint level, GLint internalFormat, 915 GLenum format, GLenum type, 916 GLint dimensions, 917 GLint width, GLint height, 918 GLint depth, GLint border ) 919{ 920 GLboolean isProxy; 921 GLint iformat; 922 923 if (dimensions == 1) { 924 isProxy = (target == GL_PROXY_TEXTURE_1D); 925 if (target != GL_TEXTURE_1D && !isProxy) { 926 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 927 return GL_TRUE; 928 } 929 } 930 else if (dimensions == 2) { 931 isProxy = (target == GL_PROXY_TEXTURE_2D); 932 if (target != GL_TEXTURE_2D && !isProxy) { 933 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 934 return GL_TRUE; 935 } 936 } 937 else if (dimensions == 3) { 938 isProxy = (target == GL_PROXY_TEXTURE_3D); 939 if (target != GL_TEXTURE_3D && !isProxy) { 940 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 941 return GL_TRUE; 942 } 943 } 944 else { 945 gl_problem( ctx, "bad dims in texture_error_check" ); 946 return GL_TRUE; 947 } 948 949 /* Border */ 950 if (border!=0 && border!=1) { 951 if (!isProxy) { 952 if (dimensions == 1) 953 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" ); 954 else if (dimensions == 2) 955 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" ); 956 else if (dimensions == 3) 957 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(border)" ); 958 } 959 return GL_TRUE; 960 } 961 962 /* Width */ 963 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize 964 || logbase2( width - 2 * border ) < 0) { 965 if (!isProxy) { 966 if (dimensions == 1) 967 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" ); 968 else if (dimensions == 2) 969 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" ); 970 else if (dimensions == 3) 971 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(width)" ); 972 } 973 return GL_TRUE; 974 } 975 976 /* Height */ 977 if (dimensions >= 2) { 978 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize 979 || logbase2( height - 2 * border ) < 0) { 980 if (!isProxy) { 981 if (dimensions == 2) 982 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" ); 983 else if (dimensions == 3) 984 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(height)" ); 985 return GL_TRUE; 986 } 987 } 988 } 989 990 /* Depth */ 991 if (dimensions >= 3) { 992 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize 993 || logbase2( depth - 2 * border ) < 0) { 994 if (!isProxy) { 995 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" ); 996 } 997 return GL_TRUE; 998 } 999 } 1000 1001 /* Level */ 1002 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1003 if (dimensions == 1) 1004 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" ); 1005 else if (dimensions == 2) 1006 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" ); 1007 else if (dimensions == 3) 1008 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(level)" ); 1009 return GL_TRUE; 1010 } 1011 1012 iformat = decode_internal_format( internalFormat ); 1013 if (iformat < 0) { 1014 if (dimensions == 1) 1015 gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" ); 1016 else if (dimensions == 2) 1017 gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" ); 1018 else if (dimensions == 3) 1019 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(internalFormat)" ); 1020 return GL_TRUE; 1021 } 1022 1023 if (!gl_is_legal_format_and_type( format, type )) { 1024 if (dimensions == 1) 1025 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(format or type)"); 1026 else if (dimensions == 2) 1027 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(format or type)"); 1028 else if (dimensions == 3) 1029 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(format or type)"); 1030 return GL_TRUE; 1031 } 1032 1033 /* if we get here, the parameters are OK */ 1034 return GL_FALSE; 1035} 1036 1037 1038 1039/* 1040 * Called from the API. Note that width includes the border. 1041 */ 1042void gl_TexImage1D( GLcontext *ctx, 1043 GLenum target, GLint level, GLint internalformat, 1044 GLsizei width, GLint border, GLenum format, 1045 GLenum type, struct gl_image *image ) 1046{ 1047 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1048 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D"); 1049 1050 if (target==GL_TEXTURE_1D) { 1051 struct gl_texture_image *teximage; 1052 if (texture_error_check( ctx, target, level, internalformat, 1053 format, type, 1, width, 1, 1, border )) { 1054 /* error in texture image was detected */ 1055 return; 1056 } 1057 1058 /* free current texture image, if any */ 1059 if (texUnit->CurrentD[1]->Image[level]) { 1060 gl_free_texture_image( texUnit->CurrentD[1]->Image[level] ); 1061 } 1062 1063 /* make new texture from source image */ 1064 if (image) { 1065 teximage = image_to_texture(ctx, image, internalformat, border); 1066 } 1067 else { 1068 teximage = make_null_texture(ctx, (GLenum) internalformat, 1069 width, 1, 1, border); 1070 } 1071 1072 /* install new texture image */ 1073 1074 texUnit->CurrentD[1]->Image[level] = teximage; 1075 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); 1076 ctx->NewState |= NEW_TEXTURING; 1077 1078 /* free the source image */ 1079 if (image && image->RefCount==0) { 1080 /* if RefCount>0 then image must be in a display list */ 1081 gl_free_image(image); 1082 } 1083 1084 /* tell driver about change */ 1085 if (ctx->Driver.TexImage) { 1086 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, 1087 texUnit->CurrentD[1], 1088 level, internalformat, teximage ); 1089 } 1090 } 1091 else if (target==GL_PROXY_TEXTURE_1D) { 1092 /* Proxy texture: check for errors and update proxy state */ 1093 if (texture_error_check( ctx, target, level, internalformat, 1094 format, type, 1, width, 1, 1, border )) { 1095 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1096 MEMSET( ctx->Texture.Proxy1D->Image[level], 0, 1097 sizeof(struct gl_texture_image) ); 1098 } 1099 } 1100 else { 1101 ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format; 1102 set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] ); 1103 ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat; 1104 ctx->Texture.Proxy1D->Image[level]->Border = border; 1105 ctx->Texture.Proxy1D->Image[level]->Width = width; 1106 ctx->Texture.Proxy1D->Image[level]->Height = 1; 1107 ctx->Texture.Proxy1D->Image[level]->Depth = 1; 1108 } 1109 if (image && image->RefCount==0) { 1110 /* if RefCount>0 then image must be in a display list */ 1111 gl_free_image(image); 1112 } 1113 } 1114 else { 1115 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1116 return; 1117 } 1118} 1119 1120 1121 1122 1123/* 1124 * Called by the API or display list executor. 1125 * Note that width and height include the border. 1126 */ 1127void gl_TexImage2D( GLcontext *ctx, 1128 GLenum target, GLint level, GLint internalformat, 1129 GLsizei width, GLsizei height, GLint border, 1130 GLenum format, GLenum type, 1131 struct gl_image *image ) 1132{ 1133 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1134 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D"); 1135 1136 if (target==GL_TEXTURE_2D) { 1137 struct gl_texture_image *teximage; 1138 if (texture_error_check( ctx, target, level, internalformat, 1139 format, type, 2, width, height, 1, border )) { 1140 /* error in texture image was detected */ 1141 return; 1142 } 1143 1144 /* free current texture image, if any */ 1145 if (texUnit->CurrentD[2]->Image[level]) { 1146 gl_free_texture_image( texUnit->CurrentD[2]->Image[level] ); 1147 } 1148 1149 /* make new texture from source image */ 1150 if (image) { 1151 teximage = image_to_texture(ctx, image, internalformat, border); 1152 } 1153 else { 1154 teximage = make_null_texture(ctx, (GLenum) internalformat, 1155 width, height, 1, border); 1156 } 1157 1158 /* install new texture image */ 1159 texUnit->CurrentD[2]->Image[level] = teximage; 1160 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); 1161 ctx->NewState |= NEW_TEXTURING; 1162 1163 /* free the source image */ 1164 if (image && image->RefCount==0) { 1165 /* if RefCount>0 then image must be in a display list */ 1166 gl_free_image(image); 1167 } 1168 1169 /* tell driver about change */ 1170 if (ctx->Driver.TexImage) { 1171 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, 1172 texUnit->CurrentD[2], 1173 level, internalformat, teximage ); 1174 } 1175 } 1176 else if (target==GL_PROXY_TEXTURE_2D) { 1177 /* Proxy texture: check for errors and update proxy state */ 1178 if (texture_error_check( ctx, target, level, internalformat, 1179 format, type, 2, width, height, 1, border )) { 1180 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1181 MEMSET( ctx->Texture.Proxy2D->Image[level], 0, 1182 sizeof(struct gl_texture_image) ); 1183 } 1184 } 1185 else { 1186 ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format; 1187 set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] ); 1188 ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalformat; 1189 ctx->Texture.Proxy2D->Image[level]->Border = border; 1190 ctx->Texture.Proxy2D->Image[level]->Width = width; 1191 ctx->Texture.Proxy2D->Image[level]->Height = height; 1192 ctx->Texture.Proxy2D->Image[level]->Depth = 1; 1193 } 1194 if (image && image->RefCount==0) { 1195 /* if RefCount>0 then image must be in a display list */ 1196 gl_free_image(image); 1197 } 1198 } 1199 else { 1200 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 1201 return; 1202 } 1203} 1204 1205 1206 1207/* 1208 * Called by the API or display list executor. 1209 * Note that width and height include the border. 1210 */ 1211void gl_TexImage3DEXT( GLcontext *ctx, 1212 GLenum target, GLint level, GLint internalformat, 1213 GLsizei width, GLsizei height, GLsizei depth, 1214 GLint border, GLenum format, GLenum type, 1215 struct gl_image *image ) 1216{ 1217 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1218 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT"); 1219 1220 if (target==GL_TEXTURE_3D_EXT) { 1221 struct gl_texture_image *teximage; 1222 if (texture_error_check( ctx, target, level, internalformat, 1223 format, type, 3, width, height, depth, 1224 border )) { 1225 /* error in texture image was detected */ 1226 return; 1227 } 1228 1229 /* free current texture image, if any */ 1230 if (texUnit->CurrentD[3]->Image[level]) { 1231 gl_free_texture_image( texUnit->CurrentD[3]->Image[level] ); 1232 } 1233 1234 /* make new texture from source image */ 1235 if (image) { 1236 teximage = image_to_texture(ctx, image, internalformat, border); 1237 } 1238 else { 1239 teximage = make_null_texture(ctx, (GLenum) internalformat, 1240 width, height, depth, border); 1241 } 1242 1243 /* install new texture image */ 1244 texUnit->CurrentD[3]->Image[level] = teximage; 1245 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); 1246 ctx->NewState |= NEW_TEXTURING; 1247 1248 /* free the source image */ 1249 if (image && image->RefCount==0) { 1250 /* if RefCount>0 then image must be in a display list */ 1251 gl_free_image(image); 1252 } 1253 1254 /* tell driver about change */ 1255 if (ctx->Driver.TexImage) { 1256 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, 1257 texUnit->CurrentD[3], 1258 level, internalformat, teximage ); 1259 } 1260 } 1261 else if (target==GL_PROXY_TEXTURE_3D_EXT) { 1262 /* Proxy texture: check for errors and update proxy state */ 1263 if (texture_error_check( ctx, target, level, internalformat, 1264 format, type, 3, width, height, depth, 1265 border )) { 1266 if (level>=0 && level<ctx->Const.MaxTextureLevels) { 1267 MEMSET( ctx->Texture.Proxy3D->Image[level], 0, 1268 sizeof(struct gl_texture_image) ); 1269 } 1270 } 1271 else { 1272 ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format; 1273 set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] ); 1274 ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalformat; 1275 ctx->Texture.Proxy3D->Image[level]->Border = border; 1276 ctx->Texture.Proxy3D->Image[level]->Width = width; 1277 ctx->Texture.Proxy3D->Image[level]->Height = height; 1278 ctx->Texture.Proxy3D->Image[level]->Depth = depth; 1279 } 1280 if (image && image->RefCount==0) { 1281 /* if RefCount>0 then image must be in a display list */ 1282 gl_free_image(image); 1283 } 1284 } 1285 else { 1286 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3DEXT(target)" ); 1287 return; 1288 } 1289} 1290 1291 1292 1293void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format, 1294 GLenum type, GLvoid *pixels ) 1295{ 1296 const struct gl_texture_object *texObj; 1297 1298 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage"); 1299 1300 if (level < 0 || level >= ctx->Const.MaxTextureLevels) { 1301 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 1302 return; 1303 } 1304 1305 if (gl_sizeof_type(type) <= 0) { 1306 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 1307 return; 1308 } 1309 1310 if (gl_components_in_format(format) <= 0) { 1311 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 1312 return; 1313 } 1314 1315 if (!pixels) 1316 return; /* XXX generate an error??? */ 1317 1318 switch (target) { 1319 case GL_TEXTURE_1D: 1320 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1]; 1321 break; 1322 case GL_TEXTURE_2D: 1323 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2]; 1324 break; 1325 case GL_TEXTURE_3D: 1326 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3]; 1327 break; 1328 default: 1329 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" ); 1330 return; 1331 } 1332 1333 if (texObj->Image[level] && texObj->Image[level]->Data) { 1334 const struct gl_texture_image *texImage = texObj->Image[level]; 1335 GLint width = texImage->Width; 1336 GLint height = texImage->Height; 1337 GLint row; 1338 1339 for (row = 0; row < height; row++) { 1340 /* compute destination address in client memory */ 1341 GLvoid *dest = gl_pixel_addr_in_image( &ctx->Unpack, pixels, 1342 width, height, 1343 format, type, 0, row, 0); 1344 1345 assert(dest); 1346 if (texImage->Format == GL_RGBA) { 1347 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte); 1348 gl_pack_rgba_span( ctx, width, (void *) src, format, type, dest, 1349 &ctx->Pack, GL_TRUE ); 1350 } 1351 else { 1352 /* fetch RGBA row from texture image then pack it in client mem */ 1353 GLubyte rgba[MAX_WIDTH][4]; 1354 GLint i; 1355 const GLubyte *src; 1356 switch (texImage->Format) { 1357 case GL_ALPHA: 1358 src = texImage->Data + row * width * sizeof(GLubyte); 1359 for (i = 0; i < width; i++) { 1360 rgba[i][RCOMP] = 255; 1361 rgba[i][GCOMP] = 255; 1362 rgba[i][BCOMP] = 255; 1363 rgba[i][ACOMP] = src[i]; 1364 } 1365 break; 1366 case GL_LUMINANCE: 1367 src = texImage->Data + row * width * sizeof(GLubyte); 1368 for (i = 0; i < width; i++) { 1369 rgba[i][RCOMP] = src[i]; 1370 rgba[i][GCOMP] = src[i]; 1371 rgba[i][BCOMP] = src[i]; 1372 rgba[i][ACOMP] = 255; 1373 } 1374 break; 1375 case GL_LUMINANCE_ALPHA: 1376 src = texImage->Data + row * 2 * width * sizeof(GLubyte); 1377 for (i = 0; i < width; i++) { 1378 rgba[i][RCOMP] = src[i*2+0]; 1379 rgba[i][GCOMP] = src[i*2+0]; 1380 rgba[i][BCOMP] = src[i*2+0]; 1381 rgba[i][ACOMP] = src[i*2+1]; 1382 } 1383 break; 1384 case GL_INTENSITY: 1385 src = texImage->Data + row * width * sizeof(GLubyte); 1386 for (i = 0; i < width; i++) { 1387 rgba[i][RCOMP] = src[i]; 1388 rgba[i][GCOMP] = src[i]; 1389 rgba[i][BCOMP] = src[i]; 1390 rgba[i][ACOMP] = 255; 1391 } 1392 break; 1393 case GL_RGB: 1394 src = texImage->Data + row * 3 * width * sizeof(GLubyte); 1395 for (i = 0; i < width; i++) { 1396 rgba[i][RCOMP] = src[i*3+0]; 1397 rgba[i][GCOMP] = src[i*3+1]; 1398 rgba[i][BCOMP] = src[i*3+2]; 1399 rgba[i][ACOMP] = 255; 1400 } 1401 break; 1402 case GL_RGBA: 1403 /* this special case should have been handled above! */ 1404 gl_problem( ctx, "error 1 in gl_GetTexImage" ); 1405 break; 1406 case GL_COLOR_INDEX: 1407 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" ); 1408 break; 1409 default: 1410 gl_problem( ctx, "bad format in gl_GetTexImage" ); 1411 } 1412 gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba, 1413 format, type, dest, &ctx->Pack, GL_TRUE ); 1414 } 1415 } 1416 } 1417} 1418 1419 1420 1421/* 1422 * Unpack the image data given to glTexSubImage[12]D. 1423 * This function is just a wrapper for gl_unpack_image() but it does 1424 * some extra error checking. 1425 */ 1426struct gl_image * 1427gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height, 1428 GLenum format, GLenum type, const GLvoid *pixels ) 1429{ 1430 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { 1431 return NULL; 1432 } 1433 1434 if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ 1435 return NULL; 1436 } 1437 1438 if (gl_sizeof_type(type)<=0) { 1439 return NULL; 1440 } 1441 1442 return gl_unpack_image3D( ctx, width, height, 1, format, type, pixels, &ctx->Unpack ); 1443} 1444 1445 1446/* 1447 * Unpack the image data given to glTexSubImage3D. 1448 * This function is just a wrapper for gl_unpack_image() but it does 1449 * some extra error checking. 1450 */ 1451struct gl_image * 1452gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height, 1453 GLint depth, GLenum format, GLenum type, 1454 const GLvoid *pixels ) 1455{ 1456 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { 1457 return NULL; 1458 } 1459 1460 if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){ 1461 return NULL; 1462 } 1463 1464 if (gl_sizeof_type(type)<=0) { 1465 return NULL; 1466 } 1467 1468 return gl_unpack_image3D( ctx, width, height, depth, format, type, pixels, 1469 &ctx->Unpack ); 1470} 1471 1472 1473 1474void gl_TexSubImage1D( GLcontext *ctx, 1475 GLenum target, GLint level, GLint xoffset, 1476 GLsizei width, GLenum format, GLenum type, 1477 struct gl_image *image ) 1478{ 1479 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1480 struct gl_texture_image *destTex; 1481 1482 if (target!=GL_TEXTURE_1D) { 1483 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 1484 return; 1485 } 1486 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1487 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" ); 1488 return; 1489 } 1490 1491 destTex = texUnit->CurrentD[1]->Image[level]; 1492 if (!destTex) { 1493 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" ); 1494 return; 1495 } 1496 1497 if (xoffset < -((GLint)destTex->Border)) { 1498 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" ); 1499 return; 1500 } 1501 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1502 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" ); 1503 return; 1504 } 1505 1506 if (image) { 1507 /* unpacking must have been error-free */ 1508 GLint texcomponents = components_in_intformat(destTex->Format); 1509 1510 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { 1511 /* Simple case, just byte copy image data into texture image */ 1512 /* row by row. */ 1513 GLubyte *dst = destTex->Data + texcomponents * xoffset; 1514 GLubyte *src = (GLubyte *) image->Data; 1515 MEMCPY( dst, src, width * texcomponents ); 1516 } 1517 else { 1518 /* General case, convert image pixels into texels, scale, bias, etc */ 1519 struct gl_texture_image *subTexImg = image_to_texture(ctx, image, 1520 destTex->IntFormat, destTex->Border); 1521 GLubyte *dst = destTex->Data + texcomponents * xoffset; 1522 GLubyte *src = subTexImg->Data; 1523 MEMCPY( dst, src, width * texcomponents ); 1524 gl_free_texture_image(subTexImg); 1525 } 1526 1527 /* if the image's reference count is zero, delete it now */ 1528 if (image->RefCount==0) { 1529 gl_free_image(image); 1530 } 1531 1532 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] ); 1533 1534 /* tell driver about change */ 1535 if (ctx->Driver.TexSubImage) { 1536 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, 1537 texUnit->CurrentD[1], level, 1538 xoffset,0,width,1, 1539 texUnit->CurrentD[1]->Image[level]->IntFormat, 1540 destTex ); 1541 } 1542 else { 1543 if (ctx->Driver.TexImage) { 1544 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, 1545 texUnit->CurrentD[1]->Image[level]->IntFormat, 1546 destTex ); 1547 } 1548 } 1549 } 1550 else { 1551 /* if no image, an error must have occured, do more testing now */ 1552 GLint components, size; 1553 1554 if (width<0) { 1555 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" ); 1556 return; 1557 } 1558 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { 1559 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); 1560 return; 1561 } 1562 components = components_in_intformat( format ); 1563 if (components<0 || format==GL_STENCIL_INDEX 1564 || format==GL_DEPTH_COMPONENT){ 1565 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); 1566 return; 1567 } 1568 size = gl_sizeof_type( type ); 1569 if (size<=0) { 1570 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" ); 1571 return; 1572 } 1573 /* if we get here, probably ran out of memory during unpacking */ 1574 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" ); 1575 } 1576} 1577 1578 1579 1580void gl_TexSubImage2D( GLcontext *ctx, 1581 GLenum target, GLint level, 1582 GLint xoffset, GLint yoffset, 1583 GLsizei width, GLsizei height, 1584 GLenum format, GLenum type, 1585 struct gl_image *image ) 1586{ 1587 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1588 struct gl_texture_image *destTex; 1589 1590 if (target!=GL_TEXTURE_2D) { 1591 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1592 return; 1593 } 1594 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1595 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" ); 1596 return; 1597 } 1598 1599 destTex = texUnit->CurrentD[2]->Image[level]; 1600 if (!destTex) { 1601 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" ); 1602 return; 1603 } 1604 1605 if (xoffset < -((GLint)destTex->Border)) { 1606 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" ); 1607 return; 1608 } 1609 if (yoffset < -((GLint)destTex->Border)) { 1610 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" ); 1611 return; 1612 } 1613 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1614 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" ); 1615 return; 1616 } 1617 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 1618 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" ); 1619 return; 1620 } 1621 1622 if (image) { 1623 /* unpacking must have been error-free */ 1624 GLint texcomponents = components_in_intformat(destTex->Format); 1625 1626 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { 1627 /* Simple case, just byte copy image data into texture image */ 1628 /* row by row. */ 1629 GLubyte *dst = destTex->Data 1630 + (yoffset * destTex->Width + xoffset) * texcomponents; 1631 GLubyte *src = (GLubyte *) image->Data; 1632 GLint j; 1633 for (j=0;j<height;j++) { 1634 MEMCPY( dst, src, width * texcomponents ); 1635 dst += destTex->Width * texcomponents * sizeof(GLubyte); 1636 src += width * texcomponents * sizeof(GLubyte); 1637 } 1638 } 1639 else { 1640 /* General case, convert image pixels into texels, scale, bias, etc */ 1641 struct gl_texture_image *subTexImg = image_to_texture(ctx, image, 1642 destTex->IntFormat, destTex->Border); 1643 GLubyte *dst = destTex->Data 1644 + (yoffset * destTex->Width + xoffset) * texcomponents; 1645 GLubyte *src = subTexImg->Data; 1646 GLint j; 1647 for (j=0;j<height;j++) { 1648 MEMCPY( dst, src, width * texcomponents ); 1649 dst += destTex->Width * texcomponents * sizeof(GLubyte); 1650 src += width * texcomponents * sizeof(GLubyte); 1651 } 1652 gl_free_texture_image(subTexImg); 1653 } 1654 1655 /* if the image's reference count is zero, delete it now */ 1656 if (image->RefCount==0) { 1657 gl_free_image(image); 1658 } 1659 1660 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] ); 1661 1662 /* tell driver about change */ 1663 if (ctx->Driver.TexSubImage) { 1664 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, 1665 xoffset, yoffset, width, height, 1666 texUnit->CurrentD[2]->Image[level]->IntFormat, 1667 destTex ); 1668 } 1669 else { 1670 if (ctx->Driver.TexImage) { 1671 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, 1672 texUnit->CurrentD[2]->Image[level]->IntFormat, 1673 destTex ); 1674 } 1675 } 1676 } 1677 else { 1678 /* if no image, an error must have occured, do more testing now */ 1679 GLint components, size; 1680 1681 if (width<0) { 1682 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" ); 1683 return; 1684 } 1685 if (height<0) { 1686 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" ); 1687 return; 1688 } 1689 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { 1690 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" ); 1691 return; 1692 } 1693 components = gl_components_in_format( format ); 1694 if (components<0 || format==GL_STENCIL_INDEX 1695 || format==GL_DEPTH_COMPONENT){ 1696 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" ); 1697 return; 1698 } 1699 size = gl_sizeof_packed_type( type ); 1700 if (size<=0) { 1701 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" ); 1702 return; 1703 } 1704 /* if we get here, probably ran out of memory during unpacking */ 1705 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" ); 1706 } 1707} 1708 1709 1710 1711void gl_TexSubImage3DEXT( GLcontext *ctx, 1712 GLenum target, GLint level, 1713 GLint xoffset, GLint yoffset, GLint zoffset, 1714 GLsizei width, GLsizei height, GLsizei depth, 1715 GLenum format, GLenum type, 1716 struct gl_image *image ) 1717{ 1718 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 1719 struct gl_texture_image *destTex; 1720 1721 if (target!=GL_TEXTURE_3D_EXT) { 1722 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" ); 1723 return; 1724 } 1725 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1726 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" ); 1727 return; 1728 } 1729 1730 destTex = texUnit->CurrentD[3]->Image[level]; 1731 if (!destTex) { 1732 gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" ); 1733 return; 1734 } 1735 1736 if (xoffset < -((GLint)destTex->Border)) { 1737 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" ); 1738 return; 1739 } 1740 if (yoffset < -((GLint)destTex->Border)) { 1741 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" ); 1742 return; 1743 } 1744 if (zoffset < -((GLint)destTex->Border)) { 1745 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" ); 1746 return; 1747 } 1748 if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) { 1749 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" ); 1750 return; 1751 } 1752 if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) { 1753 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" ); 1754 return; 1755 } 1756 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) { 1757 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" ); 1758 return; 1759 } 1760 1761 if (image) { 1762 /* unpacking must have been error-free */ 1763 GLint texcomponents = components_in_intformat(destTex->Format); 1764 GLint dstRectArea = destTex->Width * destTex->Height; 1765 GLint srcRectArea = width * height; 1766 1767 if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) { 1768 /* Simple case, just byte copy image data into texture image */ 1769 /* row by row. */ 1770 GLubyte *dst = destTex->Data 1771 + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset) 1772 * texcomponents; 1773 GLubyte *src = (GLubyte *) image->Data; 1774 GLint j, k; 1775 for(k=0;k<depth; k++) { 1776 for (j=0;j<height;j++) { 1777 MEMCPY( dst, src, width * texcomponents ); 1778 dst += destTex->Width * texcomponents; 1779 src += width * texcomponents; 1780 } 1781 dst += dstRectArea * texcomponents * sizeof(GLubyte); 1782 src += srcRectArea * texcomponents * sizeof(GLubyte); 1783 } 1784 } 1785 else { 1786 /* General case, convert image pixels into texels, scale, bias, etc */ 1787 struct gl_texture_image *subTexImg = image_to_texture(ctx, image, 1788 destTex->IntFormat, destTex->Border); 1789 GLubyte *dst = destTex->Data 1790 + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset) 1791 * texcomponents; 1792 GLubyte *src = subTexImg->Data; 1793 GLint j, k; 1794 for(k=0;k<depth; k++) { 1795 for (j=0;j<height;j++) { 1796 MEMCPY( dst, src, width * texcomponents ); 1797 dst += destTex->Width * texcomponents; 1798 src += width * texcomponents; 1799 } 1800 dst += dstRectArea * texcomponents * sizeof(GLubyte); 1801 src += srcRectArea * texcomponents * sizeof(GLubyte); 1802 } 1803 gl_free_texture_image(subTexImg); 1804 } 1805 /* if the image's reference count is zero, delete it now */ 1806 if (image->RefCount==0) { 1807 gl_free_image(image); 1808 } 1809 1810 gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] ); 1811 1812 /* tell driver about change */ 1813 if (ctx->Driver.TexImage) { 1814 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], 1815 level, texUnit->CurrentD[3]->Image[level]->IntFormat, 1816 destTex ); 1817 } 1818 } 1819 else { 1820 /* if no image, an error must have occured, do more testing now */ 1821 GLint components, size; 1822 1823 if (width<0) { 1824 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" ); 1825 return; 1826 } 1827 if (height<0) { 1828 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" ); 1829 return; 1830 } 1831 if (depth<0) { 1832 gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" ); 1833 return; 1834 } 1835 if (type==GL_BITMAP && format!=GL_COLOR_INDEX) { 1836 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); 1837 return; 1838 } 1839 components = components_in_intformat( format ); 1840 if (components<0 || format==GL_STENCIL_INDEX 1841 || format==GL_DEPTH_COMPONENT){ 1842 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" ); 1843 return; 1844 } 1845 size = gl_sizeof_type( type ); 1846 if (size<=0) { 1847 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" ); 1848 return; 1849 } 1850 /* if we get here, probably ran out of memory during unpacking */ 1851 gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" ); 1852 } 1853} 1854 1855 1856 1857/* 1858 * Read an RGBA image from the frame buffer. 1859 * Input: ctx - the context 1860 * x, y - lower left corner 1861 * width, height - size of region to read 1862 * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc. 1863 * Return: gl_image pointer or NULL if out of memory 1864 */ 1865static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y, 1866 GLsizei width, GLsizei height, 1867 GLenum format ) 1868{ 1869 struct gl_image *image; 1870 GLubyte *imgptr; 1871 GLint components; 1872 GLint i, j; 1873 1874 components = components_in_intformat( format ); 1875 1876 /* 1877 * Allocate image struct and image data buffer 1878 */ 1879 image = (struct gl_image *) malloc( sizeof(struct gl_image) ); 1880 if (image) { 1881 image->Width = width; 1882 image->Height = height; 1883 image->Depth = 1; 1884 image->Components = components; 1885 image->Format = format; 1886 image->Type = GL_UNSIGNED_BYTE; 1887 image->RefCount = 0; 1888 image->Data = (GLubyte *) malloc( width * height * components ); 1889 if (!image->Data) { 1890 free(image); 1891 return NULL; 1892 } 1893 } 1894 else { 1895 return NULL; 1896 } 1897 1898 imgptr = (GLubyte *) image->Data; 1899 1900 /* Select buffer to read from */ 1901 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); 1902 1903 for (j=0;j<height;j++) { 1904 GLubyte rgba[MAX_WIDTH][4]; 1905 gl_read_rgba_span( ctx, width, x, y+j, rgba ); 1906 1907 switch (format) { 1908 case GL_ALPHA: 1909 for (i=0;i<width;i++) { 1910 *imgptr++ = rgba[i][ACOMP]; 1911 } 1912 break; 1913 case GL_LUMINANCE: 1914 for (i=0;i<width;i++) { 1915 *imgptr++ = rgba[i][RCOMP]; 1916 } 1917 break; 1918 case GL_LUMINANCE_ALPHA: 1919 for (i=0;i<width;i++) { 1920 *imgptr++ = rgba[i][RCOMP]; 1921 *imgptr++ = rgba[i][ACOMP]; 1922 } 1923 break; 1924 case GL_INTENSITY: 1925 for (i=0;i<width;i++) { 1926 *imgptr++ = rgba[i][RCOMP]; 1927 } 1928 break; 1929 case GL_RGB: 1930 for (i=0;i<width;i++) { 1931 *imgptr++ = rgba[i][RCOMP]; 1932 *imgptr++ = rgba[i][GCOMP]; 1933 *imgptr++ = rgba[i][BCOMP]; 1934 } 1935 break; 1936 case GL_RGBA: 1937 for (i=0;i<width;i++) { 1938 *imgptr++ = rgba[i][RCOMP]; 1939 *imgptr++ = rgba[i][GCOMP]; 1940 *imgptr++ = rgba[i][BCOMP]; 1941 *imgptr++ = rgba[i][ACOMP]; 1942 } 1943 break; 1944 default: 1945 gl_problem(ctx, "Bad format in read_color_image"); 1946 break; 1947 } /*switch*/ 1948 1949 } /*for*/ 1950 1951 /* Restore drawing buffer */ 1952 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); 1953 1954 return image; 1955} 1956 1957 1958 1959 1960void gl_CopyTexImage1D( GLcontext *ctx, 1961 GLenum target, GLint level, 1962 GLenum internalformat, 1963 GLint x, GLint y, 1964 GLsizei width, GLint border ) 1965{ 1966 GLint format; 1967 struct gl_image *teximage; 1968 1969 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D"); 1970 if (target!=GL_TEXTURE_1D) { 1971 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 1972 return; 1973 } 1974 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 1975 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" ); 1976 return; 1977 } 1978 if (border!=0 && border!=1) { 1979 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" ); 1980 return; 1981 } 1982 if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) { 1983 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" ); 1984 return; 1985 } 1986 format = decode_internal_format( internalformat ); 1987 if (format<0 || (internalformat>=1 && internalformat<=4)) { 1988 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" ); 1989 return; 1990 } 1991 1992 teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format ); 1993 if (!teximage) { 1994 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" ); 1995 return; 1996 } 1997 1998 gl_TexImage1D( ctx, target, level, internalformat, width, 1999 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); 2000 2001 /* teximage was freed in gl_TexImage1D */ 2002} 2003 2004 2005 2006void gl_CopyTexImage2D( GLcontext *ctx, 2007 GLenum target, GLint level, GLenum internalformat, 2008 GLint x, GLint y, GLsizei width, GLsizei height, 2009 GLint border ) 2010{ 2011 GLint format; 2012 struct gl_image *teximage; 2013 2014 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D"); 2015 if (target!=GL_TEXTURE_2D) { 2016 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 2017 return; 2018 } 2019 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 2020 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" ); 2021 return; 2022 } 2023 if (border!=0 && border!=1) { 2024 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" ); 2025 return; 2026 } 2027 if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) { 2028 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" ); 2029 return; 2030 } 2031 if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) { 2032 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" ); 2033 return; 2034 } 2035 format = decode_internal_format( internalformat ); 2036 if (format<0 || (internalformat>=1 && internalformat<=4)) { 2037 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" ); 2038 return; 2039 } 2040 2041 teximage = read_color_image( ctx, x, y, width, height, (GLenum) format ); 2042 if (!teximage) { 2043 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" ); 2044 return; 2045 } 2046 2047 gl_TexImage2D( ctx, target, level, internalformat, width, height, 2048 border, GL_RGBA, GL_UNSIGNED_BYTE, teximage ); 2049 2050 /* teximage was freed in gl_TexImage2D */ 2051} 2052 2053 2054 2055 2056/* 2057 * Do the work of glCopyTexSubImage[123]D. 2058 * TODO: apply pixel bias scale and mapping. 2059 */ 2060static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest, 2061 GLint width, GLint height, 2062 GLint srcx, GLint srcy, 2063 GLint dstx, GLint dsty, GLint zoffset ) 2064{ 2065 GLint i, j; 2066 GLint format, components, rectarea; 2067 GLint texwidth, texheight; 2068 2069 texwidth = dest->Width; 2070 texheight = dest->Height; 2071 rectarea = texwidth * texheight; 2072 zoffset *= rectarea; 2073 format = dest->Format; 2074 components = components_in_intformat( format ); 2075 2076 /* Select buffer to read from */ 2077 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer ); 2078 2079 for (j=0;j<height;j++) { 2080 GLubyte rgba[MAX_WIDTH][4]; 2081 GLubyte *texptr; 2082 2083 gl_read_rgba_span( ctx, width, srcx, srcy+j, rgba ); 2084 2085 texptr = dest->Data + ( zoffset + (dsty+j) * texwidth + dstx) * components; 2086 2087 switch (format) { 2088 case GL_ALPHA: 2089 for (i=0;i<width;i++) { 2090 *texptr++ = rgba[i][ACOMP]; 2091 } 2092 break; 2093 case GL_LUMINANCE: 2094 for (i=0;i<width;i++) { 2095 *texptr++ = rgba[i][RCOMP]; 2096 } 2097 break; 2098 case GL_LUMINANCE_ALPHA: 2099 for (i=0;i<width;i++) { 2100 *texptr++ = rgba[i][RCOMP]; 2101 *texptr++ = rgba[i][ACOMP]; 2102 } 2103 break; 2104 case GL_INTENSITY: 2105 for (i=0;i<width;i++) { 2106 *texptr++ = rgba[i][RCOMP]; 2107 } 2108 break; 2109 case GL_RGB: 2110 for (i=0;i<width;i++) { 2111 *texptr++ = rgba[i][RCOMP]; 2112 *texptr++ = rgba[i][GCOMP]; 2113 *texptr++ = rgba[i][BCOMP]; 2114 } 2115 break; 2116 case GL_RGBA: 2117 for (i=0;i<width;i++) { 2118 *texptr++ = rgba[i][RCOMP]; 2119 *texptr++ = rgba[i][GCOMP]; 2120 *texptr++ = rgba[i][BCOMP]; 2121 *texptr++ = rgba[i][ACOMP]; 2122 } 2123 break; 2124 } /*switch*/ 2125 } /*for*/ 2126 2127 2128 /* Restore drawing buffer */ 2129 (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer ); 2130} 2131 2132 2133 2134 2135void gl_CopyTexSubImage1D( GLcontext *ctx, 2136 GLenum target, GLint level, 2137 GLint xoffset, GLint x, GLint y, GLsizei width ) 2138{ 2139 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2140 struct gl_texture_image *teximage; 2141 2142 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D"); 2143 if (target!=GL_TEXTURE_1D) { 2144 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 2145 return; 2146 } 2147 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 2148 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" ); 2149 return; 2150 } 2151 if (width<0) { 2152 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" ); 2153 return; 2154 } 2155 2156 teximage = texUnit->CurrentD[1]->Image[level]; 2157 2158 if (teximage) { 2159 if (xoffset < -((GLint)teximage->Border)) { 2160 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" ); 2161 return; 2162 } 2163 /* NOTE: we're adding the border here, not subtracting! */ 2164 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { 2165 gl_error( ctx, GL_INVALID_VALUE, 2166 "glCopyTexSubImage1D(xoffset+width)" ); 2167 return; 2168 } 2169 if (teximage->Data) { 2170 copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 ); 2171 2172 /* tell driver about change */ 2173 if (ctx->Driver.TexSubImage) { 2174 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D, 2175 texUnit->CurrentD[1], level, 2176 xoffset,0,width,1, 2177 teximage->IntFormat, 2178 teximage ); 2179 } 2180 else { 2181 if (ctx->Driver.TexImage) { 2182 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level, 2183 teximage->IntFormat, 2184 teximage ); 2185 } 2186 } 2187 } 2188 } 2189 else { 2190 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" ); 2191 } 2192} 2193 2194 2195 2196void gl_CopyTexSubImage2D( GLcontext *ctx, 2197 GLenum target, GLint level, 2198 GLint xoffset, GLint yoffset, 2199 GLint x, GLint y, GLsizei width, GLsizei height ) 2200{ 2201 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2202 struct gl_texture_image *teximage; 2203 2204 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D"); 2205 if (target!=GL_TEXTURE_2D) { 2206 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2207 return; 2208 } 2209 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 2210 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" ); 2211 return; 2212 } 2213 if (width<0) { 2214 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" ); 2215 return; 2216 } 2217 if (height<0) { 2218 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" ); 2219 return; 2220 } 2221 2222 teximage = texUnit->CurrentD[2]->Image[level]; 2223 2224 if (teximage) { 2225 if (xoffset < -((GLint)teximage->Border)) { 2226 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" ); 2227 return; 2228 } 2229 if (yoffset < -((GLint)teximage->Border)) { 2230 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" ); 2231 return; 2232 } 2233 /* NOTE: we're adding the border here, not subtracting! */ 2234 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { 2235 gl_error( ctx, GL_INVALID_VALUE, 2236 "glCopyTexSubImage2D(xoffset+width)" ); 2237 return; 2238 } 2239 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { 2240 gl_error( ctx, GL_INVALID_VALUE, 2241 "glCopyTexSubImage2D(yoffset+height)" ); 2242 return; 2243 } 2244 2245 if (teximage->Data) { 2246 copy_tex_sub_image( ctx, teximage, width, height, 2247 x, y, xoffset, yoffset, 0 ); 2248 /* tell driver about change */ 2249 if (ctx->Driver.TexSubImage) { 2250 (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, 2251 xoffset, yoffset, width, height, 2252 teximage->IntFormat, 2253 teximage ); 2254 } 2255 else { 2256 if (ctx->Driver.TexImage) { 2257 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level, 2258 teximage->IntFormat, 2259 teximage ); 2260 } 2261 } 2262 } 2263 } 2264 else { 2265 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" ); 2266 } 2267} 2268 2269 2270 2271void gl_CopyTexSubImage3DEXT( GLcontext *ctx, 2272 GLenum target, GLint level, 2273 GLint xoffset, GLint yoffset, GLint zoffset, 2274 GLint x, GLint y, GLsizei width, GLsizei height ) 2275{ 2276 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 2277 struct gl_texture_image *teximage; 2278 2279 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT"); 2280 if (target!=GL_TEXTURE_2D) { 2281 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" ); 2282 return; 2283 } 2284 if (level<0 || level>=ctx->Const.MaxTextureLevels) { 2285 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" ); 2286 return; 2287 } 2288 if (width<0) { 2289 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" ); 2290 return; 2291 } 2292 if (height<0) { 2293 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" ); 2294 return; 2295 } 2296 2297 teximage = texUnit->CurrentD[3]->Image[level]; 2298 if (teximage) { 2299 if (xoffset < -((GLint)teximage->Border)) { 2300 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" ); 2301 return; 2302 } 2303 if (yoffset < -((GLint)teximage->Border)) { 2304 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" ); 2305 return; 2306 } 2307 if (zoffset < -((GLint)teximage->Border)) { 2308 gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" ); 2309 return; 2310 } 2311 /* NOTE: we're adding the border here, not subtracting! */ 2312 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) { 2313 gl_error( ctx, GL_INVALID_VALUE, 2314 "glCopyTexSubImage3DEXT(xoffset+width)" ); 2315 return; 2316 } 2317 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) { 2318 gl_error( ctx, GL_INVALID_VALUE, 2319 "glCopyTexSubImage3DEXT(yoffset+height)" ); 2320 return; 2321 } 2322 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) { 2323 gl_error( ctx, GL_INVALID_VALUE, 2324 "glCopyTexSubImage3DEXT(zoffset+depth)" ); 2325 return; 2326 } 2327 2328 if (teximage->Data) { 2329 copy_tex_sub_image( ctx, teximage, width, height, 2330 x, y, xoffset, yoffset, zoffset); 2331 2332 /* tell driver about change */ 2333 if (ctx->Driver.TexImage) { 2334 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3], 2335 level, teximage->IntFormat, 2336 teximage ); 2337 } 2338 } 2339 } 2340 else { 2341 gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" ); 2342 } 2343} 2344 2345