texstore.c revision b623fa9e2d6f97f9febc978c158d790b26e175a7
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/* 26 * Authors: 27 * Brian Paul 28 */ 29 30/** 31 * The GL texture image functions in teximage.c basically just do 32 * error checking and data structure allocation. They in turn call 33 * device driver functions which actually copy/convert/store the user's 34 * texture image data. 35 * 36 * However, most device drivers will be able to use the fallback functions 37 * in this file. That is, most drivers will have the following bit of 38 * code: 39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d; 40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d; 41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d; 42 * etc... 43 * 44 * Texture image processing is actually kind of complicated. We have to do: 45 * Format/type conversions 46 * pixel unpacking 47 * pixel transfer (scale, bais, lookup, convolution!, etc) 48 * 49 * These functions can handle most everything, including processing full 50 * images and sub-images. 51 */ 52 53 54#include "glheader.h" 55#include "bufferobj.h" 56#include "colormac.h" 57#include "context.h" 58#if FEATURE_convolve 59#include "convolve.h" 60#endif 61#include "image.h" 62#include "macros.h" 63#include "mipmap.h" 64#include "imports.h" 65#include "texcompress.h" 66#include "texformat.h" 67#include "teximage.h" 68#include "texstore.h" 69#include "enums.h" 70 71 72enum { 73 ZERO = 4, 74 ONE = 5 75}; 76 77 78/** 79 * Return GL_TRUE if the given image format is one that be converted 80 * to another format by swizzling. 81 */ 82static GLboolean 83can_swizzle(GLenum logicalBaseFormat) 84{ 85 switch (logicalBaseFormat) { 86 case GL_RGBA: 87 case GL_RGB: 88 case GL_LUMINANCE_ALPHA: 89 case GL_INTENSITY: 90 case GL_ALPHA: 91 case GL_LUMINANCE: 92 case GL_RED: 93 case GL_GREEN: 94 case GL_BLUE: 95 case GL_BGR: 96 case GL_BGRA: 97 case GL_ABGR_EXT: 98 return GL_TRUE; 99 default: 100 return GL_FALSE; 101 } 102} 103 104 105 106enum { 107 IDX_LUMINANCE = 0, 108 IDX_ALPHA, 109 IDX_INTENSITY, 110 IDX_LUMINANCE_ALPHA, 111 IDX_RGB, 112 IDX_RGBA, 113 IDX_RED, 114 IDX_GREEN, 115 IDX_BLUE, 116 IDX_BGR, 117 IDX_BGRA, 118 IDX_ABGR, 119 MAX_IDX 120}; 121 122#define MAP1(x) MAP4(x, ZERO, ZERO, ZERO) 123#define MAP2(x,y) MAP4(x, y, ZERO, ZERO) 124#define MAP3(x,y,z) MAP4(x, y, z, ZERO) 125#define MAP4(x,y,z,w) { x, y, z, w, ZERO, ONE } 126 127 128static const struct { 129 GLubyte format_idx; 130 GLubyte to_rgba[6]; 131 GLubyte from_rgba[6]; 132} mappings[MAX_IDX] = 133{ 134 { 135 IDX_LUMINANCE, 136 MAP4(0,0,0,ONE), 137 MAP1(0) 138 }, 139 140 { 141 IDX_ALPHA, 142 MAP4(ZERO, ZERO, ZERO, 0), 143 MAP1(3) 144 }, 145 146 { 147 IDX_INTENSITY, 148 MAP4(0, 0, 0, 0), 149 MAP1(0), 150 }, 151 152 { 153 IDX_LUMINANCE_ALPHA, 154 MAP4(0,0,0,1), 155 MAP2(0,3) 156 }, 157 158 { 159 IDX_RGB, 160 MAP4(0,1,2,ONE), 161 MAP3(0,1,2) 162 }, 163 164 { 165 IDX_RGBA, 166 MAP4(0,1,2,3), 167 MAP4(0,1,2,3), 168 }, 169 170 171 { 172 IDX_RED, 173 MAP4(0, ZERO, ZERO, ONE), 174 MAP1(0), 175 }, 176 177 { 178 IDX_GREEN, 179 MAP4(ZERO, 0, ZERO, ONE), 180 MAP1(1), 181 }, 182 183 { 184 IDX_BLUE, 185 MAP4(ZERO, ZERO, 0, ONE), 186 MAP1(2), 187 }, 188 189 { 190 IDX_BGR, 191 MAP4(2,1,0,ONE), 192 MAP3(2,1,0) 193 }, 194 195 { 196 IDX_BGRA, 197 MAP4(2,1,0,3), 198 MAP4(2,1,0,3) 199 }, 200 201 { 202 IDX_ABGR, 203 MAP4(3,2,1,0), 204 MAP4(3,2,1,0) 205 }, 206}; 207 208 209 210/** 211 * Convert a GL image format enum to an IDX_* value (see above). 212 */ 213static int 214get_map_idx(GLenum value) 215{ 216 switch (value) { 217 case GL_LUMINANCE: return IDX_LUMINANCE; 218 case GL_ALPHA: return IDX_ALPHA; 219 case GL_INTENSITY: return IDX_INTENSITY; 220 case GL_LUMINANCE_ALPHA: return IDX_LUMINANCE_ALPHA; 221 case GL_RGB: return IDX_RGB; 222 case GL_RGBA: return IDX_RGBA; 223 case GL_RED: return IDX_RED; 224 case GL_GREEN: return IDX_GREEN; 225 case GL_BLUE: return IDX_BLUE; 226 case GL_BGR: return IDX_BGR; 227 case GL_BGRA: return IDX_BGRA; 228 case GL_ABGR_EXT: return IDX_ABGR; 229 default: 230 _mesa_problem(NULL, "Unexpected inFormat"); 231 return 0; 232 } 233} 234 235 236/** 237 * When promoting texture formats (see below) we need to compute the 238 * mapping of dest components back to source components. 239 * This function does that. 240 * \param inFormat the incoming format of the texture 241 * \param outFormat the final texture format 242 * \return map[6] a full 6-component map 243 */ 244static void 245compute_component_mapping(GLenum inFormat, GLenum outFormat, 246 GLubyte *map) 247{ 248 const int inFmt = get_map_idx(inFormat); 249 const int outFmt = get_map_idx(outFormat); 250 const GLubyte *in2rgba = mappings[inFmt].to_rgba; 251 const GLubyte *rgba2out = mappings[outFmt].from_rgba; 252 int i; 253 254 for (i = 0; i < 4; i++) 255 map[i] = in2rgba[rgba2out[i]]; 256 257 map[ZERO] = ZERO; 258 map[ONE] = ONE; 259 260/* 261 _mesa_printf("from %x/%s to %x/%s map %d %d %d %d %d %d\n", 262 inFormat, _mesa_lookup_enum_by_nr(inFormat), 263 outFormat, _mesa_lookup_enum_by_nr(outFormat), 264 map[0], 265 map[1], 266 map[2], 267 map[3], 268 map[4], 269 map[5]); 270*/ 271} 272 273 274#if !FEATURE_convolve 275static void 276_mesa_adjust_image_for_convolution(GLcontext *ctx, GLuint dims, 277 GLsizei *srcWidth, GLsizei *srcHeight) 278{ 279 /* no-op */ 280} 281#endif 282 283 284/** 285 * Make a temporary (color) texture image with GLfloat components. 286 * Apply all needed pixel unpacking and pixel transfer operations. 287 * Note that there are both logicalBaseFormat and textureBaseFormat parameters. 288 * Suppose the user specifies GL_LUMINANCE as the internal texture format 289 * but the graphics hardware doesn't support luminance textures. So, might 290 * use an RGB hardware format instead. 291 * If logicalBaseFormat != textureBaseFormat we have some extra work to do. 292 * 293 * \param ctx the rendering context 294 * \param dims image dimensions: 1, 2 or 3 295 * \param logicalBaseFormat basic texture derived from the user's 296 * internal texture format value 297 * \param textureBaseFormat the actual basic format of the texture 298 * \param srcWidth source image width 299 * \param srcHeight source image height 300 * \param srcDepth source image depth 301 * \param srcFormat source image format 302 * \param srcType source image type 303 * \param srcAddr source image address 304 * \param srcPacking source image pixel packing 305 * \return resulting image with format = textureBaseFormat and type = GLfloat. 306 */ 307static GLfloat * 308make_temp_float_image(GLcontext *ctx, GLuint dims, 309 GLenum logicalBaseFormat, 310 GLenum textureBaseFormat, 311 GLint srcWidth, GLint srcHeight, GLint srcDepth, 312 GLenum srcFormat, GLenum srcType, 313 const GLvoid *srcAddr, 314 const struct gl_pixelstore_attrib *srcPacking) 315{ 316 GLuint transferOps = ctx->_ImageTransferState; 317 GLfloat *tempImage; 318 319 ASSERT(dims >= 1 && dims <= 3); 320 321 ASSERT(logicalBaseFormat == GL_RGBA || 322 logicalBaseFormat == GL_RGB || 323 logicalBaseFormat == GL_LUMINANCE_ALPHA || 324 logicalBaseFormat == GL_LUMINANCE || 325 logicalBaseFormat == GL_ALPHA || 326 logicalBaseFormat == GL_INTENSITY || 327 logicalBaseFormat == GL_COLOR_INDEX || 328 logicalBaseFormat == GL_DEPTH_COMPONENT); 329 330 ASSERT(textureBaseFormat == GL_RGBA || 331 textureBaseFormat == GL_RGB || 332 textureBaseFormat == GL_LUMINANCE_ALPHA || 333 textureBaseFormat == GL_LUMINANCE || 334 textureBaseFormat == GL_ALPHA || 335 textureBaseFormat == GL_INTENSITY || 336 textureBaseFormat == GL_COLOR_INDEX || 337 textureBaseFormat == GL_DEPTH_COMPONENT); 338 339 /* conventional color image */ 340 341 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || 342 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || 343 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { 344 /* need image convolution */ 345 const GLuint preConvTransferOps 346 = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; 347 const GLuint postConvTransferOps 348 = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT; 349 GLint img, row; 350 GLint convWidth, convHeight; 351 GLfloat *convImage; 352 353 /* pre-convolution image buffer (3D) */ 354 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth 355 * 4 * sizeof(GLfloat)); 356 if (!tempImage) 357 return NULL; 358 359 /* post-convolution image buffer (2D) */ 360 convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight 361 * 4 * sizeof(GLfloat)); 362 if (!convImage) { 363 _mesa_free(tempImage); 364 return NULL; 365 } 366 367 /* loop over 3D image slices */ 368 for (img = 0; img < srcDepth; img++) { 369 GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4); 370 371 /* unpack and do transfer ops up to convolution */ 372 for (row = 0; row < srcHeight; row++) { 373 const GLvoid *src = _mesa_image_address(dims, srcPacking, 374 srcAddr, srcWidth, srcHeight, 375 srcFormat, srcType, img, row, 0); 376 _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst, 377 srcFormat, srcType, src, 378 srcPacking, 379 preConvTransferOps); 380 dst += srcWidth * 4; 381 } 382 383#if FEATURE_convolve 384 /* do convolution */ 385 { 386 GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4); 387 convWidth = srcWidth; 388 convHeight = srcHeight; 389 if (dims == 1) { 390 ASSERT(ctx->Pixel.Convolution1DEnabled); 391 _mesa_convolve_1d_image(ctx, &convWidth, src, convImage); 392 } 393 else { 394 if (ctx->Pixel.Convolution2DEnabled) { 395 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight, 396 src, convImage); 397 } 398 else { 399 ASSERT(ctx->Pixel.Separable2DEnabled); 400 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight, 401 src, convImage); 402 } 403 } 404 } 405#endif 406 /* do post-convolution transfer and pack into tempImage */ 407 { 408 const GLint logComponents 409 = _mesa_components_in_format(logicalBaseFormat); 410 const GLfloat *src = convImage; 411 GLfloat *dst = tempImage + img * (convWidth * convHeight * 4); 412 for (row = 0; row < convHeight; row++) { 413 _mesa_pack_rgba_span_float(ctx, convWidth, 414 (GLfloat (*)[4]) src, 415 logicalBaseFormat, GL_FLOAT, 416 dst, &ctx->DefaultPacking, 417 postConvTransferOps); 418 src += convWidth * 4; 419 dst += convWidth * logComponents; 420 } 421 } 422 } /* loop over 3D image slices */ 423 424 _mesa_free(convImage); 425 426 /* might need these below */ 427 srcWidth = convWidth; 428 srcHeight = convHeight; 429 } 430 else { 431 /* no convolution */ 432 const GLint components = _mesa_components_in_format(logicalBaseFormat); 433 const GLint srcStride = _mesa_image_row_stride(srcPacking, 434 srcWidth, srcFormat, srcType); 435 GLfloat *dst; 436 GLint img, row; 437 438 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth 439 * components * sizeof(GLfloat)); 440 if (!tempImage) 441 return NULL; 442 443 dst = tempImage; 444 for (img = 0; img < srcDepth; img++) { 445 const GLubyte *src 446 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, 447 srcWidth, srcHeight, 448 srcFormat, srcType, 449 img, 0, 0); 450 for (row = 0; row < srcHeight; row++) { 451 _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat, 452 dst, srcFormat, srcType, src, 453 srcPacking, transferOps); 454 dst += srcWidth * components; 455 src += srcStride; 456 } 457 } 458 } 459 460 if (logicalBaseFormat != textureBaseFormat) { 461 /* more work */ 462 GLint texComponents = _mesa_components_in_format(textureBaseFormat); 463 GLint logComponents = _mesa_components_in_format(logicalBaseFormat); 464 GLfloat *newImage; 465 GLint i, n; 466 GLubyte map[6]; 467 468 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ 469 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || 470 textureBaseFormat == GL_LUMINANCE_ALPHA); 471 472 /* The actual texture format should have at least as many components 473 * as the logical texture format. 474 */ 475 ASSERT(texComponents >= logComponents); 476 477 newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth 478 * texComponents * sizeof(GLfloat)); 479 if (!newImage) { 480 _mesa_free(tempImage); 481 return NULL; 482 } 483 484 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); 485 486 n = srcWidth * srcHeight * srcDepth; 487 for (i = 0; i < n; i++) { 488 GLint k; 489 for (k = 0; k < texComponents; k++) { 490 GLint j = map[k]; 491 if (j == ZERO) 492 newImage[i * texComponents + k] = 0.0F; 493 else if (j == ONE) 494 newImage[i * texComponents + k] = 1.0F; 495 else 496 newImage[i * texComponents + k] = tempImage[i * logComponents + j]; 497 } 498 } 499 500 _mesa_free(tempImage); 501 tempImage = newImage; 502 } 503 504 return tempImage; 505} 506 507 508/** 509 * Make a temporary (color) texture image with GLchan components. 510 * Apply all needed pixel unpacking and pixel transfer operations. 511 * Note that there are both logicalBaseFormat and textureBaseFormat parameters. 512 * Suppose the user specifies GL_LUMINANCE as the internal texture format 513 * but the graphics hardware doesn't support luminance textures. So, might 514 * use an RGB hardware format instead. 515 * If logicalBaseFormat != textureBaseFormat we have some extra work to do. 516 * 517 * \param ctx the rendering context 518 * \param dims image dimensions: 1, 2 or 3 519 * \param logicalBaseFormat basic texture derived from the user's 520 * internal texture format value 521 * \param textureBaseFormat the actual basic format of the texture 522 * \param srcWidth source image width 523 * \param srcHeight source image height 524 * \param srcDepth source image depth 525 * \param srcFormat source image format 526 * \param srcType source image type 527 * \param srcAddr source image address 528 * \param srcPacking source image pixel packing 529 * \return resulting image with format = textureBaseFormat and type = GLchan. 530 */ 531GLchan * 532_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, 533 GLenum logicalBaseFormat, 534 GLenum textureBaseFormat, 535 GLint srcWidth, GLint srcHeight, GLint srcDepth, 536 GLenum srcFormat, GLenum srcType, 537 const GLvoid *srcAddr, 538 const struct gl_pixelstore_attrib *srcPacking) 539{ 540 GLuint transferOps = ctx->_ImageTransferState; 541 const GLint components = _mesa_components_in_format(logicalBaseFormat); 542 GLboolean freeSrcImage = GL_FALSE; 543 GLint img, row; 544 GLchan *tempImage, *dst; 545 546 ASSERT(dims >= 1 && dims <= 3); 547 548 ASSERT(logicalBaseFormat == GL_RGBA || 549 logicalBaseFormat == GL_RGB || 550 logicalBaseFormat == GL_LUMINANCE_ALPHA || 551 logicalBaseFormat == GL_LUMINANCE || 552 logicalBaseFormat == GL_ALPHA || 553 logicalBaseFormat == GL_INTENSITY); 554 555 ASSERT(textureBaseFormat == GL_RGBA || 556 textureBaseFormat == GL_RGB || 557 textureBaseFormat == GL_LUMINANCE_ALPHA || 558 textureBaseFormat == GL_LUMINANCE || 559 textureBaseFormat == GL_ALPHA || 560 textureBaseFormat == GL_INTENSITY); 561 562#if FEATURE_convolve 563 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) || 564 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) || 565 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) { 566 /* get convolved image */ 567 GLfloat *convImage = make_temp_float_image(ctx, dims, 568 logicalBaseFormat, 569 logicalBaseFormat, 570 srcWidth, srcHeight, srcDepth, 571 srcFormat, srcType, 572 srcAddr, srcPacking); 573 if (!convImage) 574 return NULL; 575 /* the convolved image is our new source image */ 576 srcAddr = convImage; 577 srcFormat = logicalBaseFormat; 578 srcType = GL_FLOAT; 579 srcPacking = &ctx->DefaultPacking; 580 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 581 transferOps = 0; 582 freeSrcImage = GL_TRUE; 583 } 584#endif 585 586 /* unpack and transfer the source image */ 587 tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth 588 * components * sizeof(GLchan)); 589 if (!tempImage) 590 return NULL; 591 592 dst = tempImage; 593 for (img = 0; img < srcDepth; img++) { 594 const GLint srcStride = _mesa_image_row_stride(srcPacking, 595 srcWidth, srcFormat, 596 srcType); 597 const GLubyte *src 598 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr, 599 srcWidth, srcHeight, 600 srcFormat, srcType, 601 img, 0, 0); 602 for (row = 0; row < srcHeight; row++) { 603 _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst, 604 srcFormat, srcType, src, srcPacking, 605 transferOps); 606 dst += srcWidth * components; 607 src += srcStride; 608 } 609 } 610 611 /* If we made a temporary image for convolution, free it here */ 612 if (freeSrcImage) { 613 _mesa_free((void *) srcAddr); 614 } 615 616 if (logicalBaseFormat != textureBaseFormat) { 617 /* one more conversion step */ 618 GLint texComponents = _mesa_components_in_format(textureBaseFormat); 619 GLint logComponents = _mesa_components_in_format(logicalBaseFormat); 620 GLchan *newImage; 621 GLint i, n; 622 GLubyte map[6]; 623 624 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */ 625 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA || 626 textureBaseFormat == GL_LUMINANCE_ALPHA); 627 628 /* The actual texture format should have at least as many components 629 * as the logical texture format. 630 */ 631 ASSERT(texComponents >= logComponents); 632 633 newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth 634 * texComponents * sizeof(GLchan)); 635 if (!newImage) { 636 _mesa_free(tempImage); 637 return NULL; 638 } 639 640 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map); 641 642 n = srcWidth * srcHeight * srcDepth; 643 for (i = 0; i < n; i++) { 644 GLint k; 645 for (k = 0; k < texComponents; k++) { 646 GLint j = map[k]; 647 if (j == ZERO) 648 newImage[i * texComponents + k] = 0; 649 else if (j == ONE) 650 newImage[i * texComponents + k] = CHAN_MAX; 651 else 652 newImage[i * texComponents + k] = tempImage[i * logComponents + j]; 653 } 654 } 655 656 _mesa_free(tempImage); 657 tempImage = newImage; 658 } 659 660 return tempImage; 661} 662 663 664/** 665 * Copy GLubyte pixels from <src> to <dst> with swizzling. 666 * \param dst destination pixels 667 * \param dstComponents number of color components in destination pixels 668 * \param src source pixels 669 * \param srcComponents number of color components in source pixels 670 * \param map the swizzle mapping. map[X] says where to find the X component 671 * in the source image's pixels. For example, if the source image 672 * is GL_BGRA and X = red, map[0] yields 2. 673 * \param count number of pixels to copy/swizzle. 674 */ 675static void 676swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src, 677 GLuint srcComponents, const GLubyte *map, GLuint count) 678{ 679 GLubyte tmp[6]; 680 GLuint i; 681 682 tmp[ZERO] = 0x0; 683 tmp[ONE] = 0xff; 684 685 switch (dstComponents) { 686 case 4: 687 for (i = 0; i < count; i++) { 688 COPY_4UBV(tmp, src); 689 src += srcComponents; 690 dst[0] = tmp[map[0]]; 691 dst[1] = tmp[map[1]]; 692 dst[2] = tmp[map[2]]; 693 dst[3] = tmp[map[3]]; 694 dst += 4; 695 } 696 break; 697 case 3: 698 for (i = 0; i < count; i++) { 699 COPY_4UBV(tmp, src); 700 src += srcComponents; 701 dst[0] = tmp[map[0]]; 702 dst[1] = tmp[map[1]]; 703 dst[2] = tmp[map[2]]; 704 dst += 3; 705 } 706 break; 707 case 2: 708 for (i = 0; i < count; i++) { 709 COPY_4UBV(tmp, src); 710 src += srcComponents; 711 dst[0] = tmp[map[0]]; 712 dst[1] = tmp[map[1]]; 713 dst += 2; 714 } 715 break; 716 case 1: 717 /* XXX investigate valgrind invalid read when running demos/texenv.c */ 718 for (i = 0; i < count; i++) { 719 COPY_4UBV(tmp, src); 720 src += srcComponents; 721 dst[0] = tmp[map[0]]; 722 dst += 1; 723 } 724 break; 725 } 726} 727 728 729static const GLubyte map_identity[6] = { 0, 1, 2, 3, ZERO, ONE }; 730static const GLubyte map_3210[6] = { 3, 2, 1, 0, ZERO, ONE }; 731 732/* Deal with the _REV input types: 733 */ 734static const GLubyte * 735type_mapping( GLenum srcType ) 736{ 737 switch (srcType) { 738 case GL_UNSIGNED_BYTE: 739 return map_identity; 740 case GL_UNSIGNED_INT_8_8_8_8: 741 return _mesa_little_endian() ? map_3210 : map_identity; 742 case GL_UNSIGNED_INT_8_8_8_8_REV: 743 return _mesa_little_endian() ? map_identity : map_3210; 744 default: 745 return NULL; 746 } 747} 748 749/* Mapping required if input type is 750 */ 751static const GLubyte * 752byteswap_mapping( GLboolean swapBytes, 753 GLenum srcType ) 754{ 755 if (!swapBytes) 756 return map_identity; 757 758 switch (srcType) { 759 case GL_UNSIGNED_BYTE: 760 return map_identity; 761 case GL_UNSIGNED_INT_8_8_8_8: 762 case GL_UNSIGNED_INT_8_8_8_8_REV: 763 return map_3210; 764 default: 765 return NULL; 766 } 767} 768 769 770 771/** 772 * Transfer a GLubyte texture image with component swizzling. 773 */ 774static void 775_mesa_swizzle_ubyte_image(GLcontext *ctx, 776 GLuint dimensions, 777 GLenum srcFormat, 778 GLenum srcType, 779 780 GLenum baseInternalFormat, 781 782 const GLubyte *rgba2dst, 783 GLuint dstComponents, 784 785 GLvoid *dstAddr, 786 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, 787 GLint dstRowStride, 788 const GLuint *dstImageOffsets, 789 790 GLint srcWidth, GLint srcHeight, GLint srcDepth, 791 const GLvoid *srcAddr, 792 const struct gl_pixelstore_attrib *srcPacking ) 793{ 794 GLint srcComponents = _mesa_components_in_format(srcFormat); 795 const GLubyte *srctype2ubyte, *swap; 796 GLubyte map[4], src2base[6], base2rgba[6]; 797 GLint i; 798 const GLint srcRowStride = 799 _mesa_image_row_stride(srcPacking, srcWidth, 800 srcFormat, GL_UNSIGNED_BYTE); 801 const GLint srcImageStride 802 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat, 803 GL_UNSIGNED_BYTE); 804 const GLubyte *srcImage 805 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr, 806 srcWidth, srcHeight, srcFormat, 807 GL_UNSIGNED_BYTE, 0, 0, 0); 808 809 (void) ctx; 810 811 /* Translate from src->baseInternal->GL_RGBA->dst. This will 812 * correctly deal with RGBA->RGB->RGBA conversions where the final 813 * A value must be 0xff regardless of the incoming alpha values. 814 */ 815 compute_component_mapping(srcFormat, baseInternalFormat, src2base); 816 compute_component_mapping(baseInternalFormat, GL_RGBA, base2rgba); 817 swap = byteswap_mapping(srcPacking->SwapBytes, srcType); 818 srctype2ubyte = type_mapping(srcType); 819 820 821 for (i = 0; i < 4; i++) 822 map[i] = srctype2ubyte[swap[src2base[base2rgba[rgba2dst[i]]]]]; 823 824/* _mesa_printf("map %d %d %d %d\n", map[0], map[1], map[2], map[3]); */ 825 826 if (srcComponents == dstComponents && 827 srcRowStride == dstRowStride && 828 srcRowStride == srcWidth * srcComponents && 829 dimensions < 3) { 830 /* 1 and 2D images only */ 831 GLubyte *dstImage = (GLubyte *) dstAddr 832 + dstYoffset * dstRowStride 833 + dstXoffset * dstComponents; 834 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, 835 srcWidth * srcHeight); 836 } 837 else { 838 GLint img, row; 839 for (img = 0; img < srcDepth; img++) { 840 const GLubyte *srcRow = srcImage; 841 GLubyte *dstRow = (GLubyte *) dstAddr 842 + dstImageOffsets[dstZoffset + img] * dstComponents 843 + dstYoffset * dstRowStride 844 + dstXoffset * dstComponents; 845 for (row = 0; row < srcHeight; row++) { 846 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); 847 dstRow += dstRowStride; 848 srcRow += srcRowStride; 849 } 850 srcImage += srcImageStride; 851 } 852 } 853} 854 855 856/** 857 * Teximage storage routine for when a simple memcpy will do. 858 * No pixel transfer operations or special texel encodings allowed. 859 * 1D, 2D and 3D images supported. 860 */ 861static void 862memcpy_texture(GLcontext *ctx, 863 GLuint dimensions, 864 const struct gl_texture_format *dstFormat, 865 GLvoid *dstAddr, 866 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, 867 GLint dstRowStride, 868 const GLuint *dstImageOffsets, 869 GLint srcWidth, GLint srcHeight, GLint srcDepth, 870 GLenum srcFormat, GLenum srcType, 871 const GLvoid *srcAddr, 872 const struct gl_pixelstore_attrib *srcPacking) 873{ 874 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, 875 srcFormat, srcType); 876 const GLint srcImageStride = _mesa_image_image_stride(srcPacking, 877 srcWidth, srcHeight, srcFormat, srcType); 878 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, 879 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); 880 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes; 881 882#if 0 883 /* XXX update/re-enable for dstImageOffsets array */ 884 const GLint bytesPerImage = srcHeight * bytesPerRow; 885 const GLint bytesPerTexture = srcDepth * bytesPerImage; 886 GLubyte *dstImage = (GLubyte *) dstAddr 887 + dstZoffset * dstImageStride 888 + dstYoffset * dstRowStride 889 + dstXoffset * dstFormat->TexelBytes; 890 891 if (dstRowStride == srcRowStride && 892 dstRowStride == bytesPerRow && 893 ((dstImageStride == srcImageStride && 894 dstImageStride == bytesPerImage) || 895 (srcDepth == 1))) { 896 /* one big memcpy */ 897 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture); 898 } 899 else 900 { 901 GLint img, row; 902 for (img = 0; img < srcDepth; img++) { 903 const GLubyte *srcRow = srcImage; 904 GLubyte *dstRow = dstImage; 905 for (row = 0; row < srcHeight; row++) { 906 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow); 907 dstRow += dstRowStride; 908 srcRow += srcRowStride; 909 } 910 srcImage += srcImageStride; 911 dstImage += dstImageStride; 912 } 913 } 914#endif 915 916 GLint img, row; 917 for (img = 0; img < srcDepth; img++) { 918 const GLubyte *srcRow = srcImage; 919 GLubyte *dstRow = (GLubyte *) dstAddr 920 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 921 + dstYoffset * dstRowStride 922 + dstXoffset * dstFormat->TexelBytes; 923 for (row = 0; row < srcHeight; row++) { 924 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow); 925 dstRow += dstRowStride; 926 srcRow += srcRowStride; 927 } 928 srcImage += srcImageStride; 929 } 930} 931 932 933 934/** 935 * Store an image in any of the formats: 936 * _mesa_texformat_rgba 937 * _mesa_texformat_rgb 938 * _mesa_texformat_alpha 939 * _mesa_texformat_luminance 940 * _mesa_texformat_luminance_alpha 941 * _mesa_texformat_intensity 942 * 943 */ 944GLboolean 945_mesa_texstore_rgba(TEXSTORE_PARAMS) 946{ 947 const GLint components = _mesa_components_in_format(baseInternalFormat); 948 949 ASSERT(dstFormat == &_mesa_texformat_rgba || 950 dstFormat == &_mesa_texformat_rgb || 951 dstFormat == &_mesa_texformat_alpha || 952 dstFormat == &_mesa_texformat_luminance || 953 dstFormat == &_mesa_texformat_luminance_alpha || 954 dstFormat == &_mesa_texformat_intensity); 955 ASSERT(baseInternalFormat == GL_RGBA || 956 baseInternalFormat == GL_RGB || 957 baseInternalFormat == GL_ALPHA || 958 baseInternalFormat == GL_LUMINANCE || 959 baseInternalFormat == GL_LUMINANCE_ALPHA || 960 baseInternalFormat == GL_INTENSITY); 961 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan)); 962 963 if (!ctx->_ImageTransferState && 964 !srcPacking->SwapBytes && 965 baseInternalFormat == srcFormat && 966 srcType == CHAN_TYPE) { 967 /* simple memcpy path */ 968 memcpy_texture(ctx, dims, 969 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 970 dstRowStride, 971 dstImageOffsets, 972 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 973 srcAddr, srcPacking); 974 } 975 else if (!ctx->_ImageTransferState && 976 !srcPacking->SwapBytes && 977 dstFormat == &_mesa_texformat_rgb && 978 srcFormat == GL_RGBA && 979 srcType == CHAN_TYPE) { 980 /* extract RGB from RGBA */ 981 GLint img, row, col; 982 for (img = 0; img < srcDepth; img++) { 983 GLchan *dstImage = (GLchan *) 984 ((GLubyte *) dstAddr 985 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 986 + dstYoffset * dstRowStride 987 + dstXoffset * dstFormat->TexelBytes); 988 989 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 990 srcWidth, srcFormat, srcType); 991 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking, 992 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 993 GLchan *dstRow = dstImage; 994 for (row = 0; row < srcHeight; row++) { 995 for (col = 0; col < srcWidth; col++) { 996 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP]; 997 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP]; 998 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP]; 999 } 1000 dstRow += dstRowStride / sizeof(GLchan); 1001 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride); 1002 } 1003 } 1004 } 1005 else if (!ctx->_ImageTransferState && 1006 CHAN_TYPE == GL_UNSIGNED_BYTE && 1007 (srcType == GL_UNSIGNED_BYTE || 1008 srcType == GL_UNSIGNED_INT_8_8_8_8 || 1009 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && 1010 can_swizzle(baseInternalFormat) && 1011 can_swizzle(srcFormat)) { 1012 1013 const GLubyte *dstmap; 1014 GLuint components; 1015 1016 /* dstmap - how to swizzle from RGBA to dst format: 1017 */ 1018 if (dstFormat == &_mesa_texformat_rgba) { 1019 dstmap = mappings[IDX_RGBA].from_rgba; 1020 components = 4; 1021 } 1022 else if (dstFormat == &_mesa_texformat_rgb) { 1023 dstmap = mappings[IDX_RGB].from_rgba; 1024 components = 3; 1025 } 1026 else if (dstFormat == &_mesa_texformat_alpha) { 1027 dstmap = mappings[IDX_ALPHA].from_rgba; 1028 components = 1; 1029 } 1030 else if (dstFormat == &_mesa_texformat_luminance) { 1031 dstmap = mappings[IDX_LUMINANCE].from_rgba; 1032 components = 1; 1033 } 1034 else if (dstFormat == &_mesa_texformat_luminance_alpha) { 1035 dstmap = mappings[IDX_LUMINANCE_ALPHA].from_rgba; 1036 components = 2; 1037 } 1038 else if (dstFormat == &_mesa_texformat_intensity) { 1039 dstmap = mappings[IDX_INTENSITY].from_rgba; 1040 components = 1; 1041 } 1042 else { 1043 _mesa_problem(ctx, "Unexpected dstFormat in _mesa_texstore_rgba"); 1044 return GL_FALSE; 1045 } 1046 1047 _mesa_swizzle_ubyte_image(ctx, dims, 1048 srcFormat, 1049 srcType, 1050 baseInternalFormat, 1051 dstmap, components, 1052 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1053 dstRowStride, dstImageOffsets, 1054 srcWidth, srcHeight, srcDepth, srcAddr, 1055 srcPacking); 1056 } 1057 else { 1058 /* general path */ 1059 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1060 baseInternalFormat, 1061 dstFormat->BaseFormat, 1062 srcWidth, srcHeight, srcDepth, 1063 srcFormat, srcType, srcAddr, 1064 srcPacking); 1065 const GLchan *src = tempImage; 1066 GLint bytesPerRow; 1067 GLint img, row; 1068 if (!tempImage) 1069 return GL_FALSE; 1070 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1071 bytesPerRow = srcWidth * components * sizeof(GLchan); 1072 for (img = 0; img < srcDepth; img++) { 1073 GLubyte *dstRow = (GLubyte *) dstAddr 1074 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1075 + dstYoffset * dstRowStride 1076 + dstXoffset * dstFormat->TexelBytes; 1077 for (row = 0; row < srcHeight; row++) { 1078 _mesa_memcpy(dstRow, src, bytesPerRow); 1079 dstRow += dstRowStride; 1080 src += srcWidth * components; 1081 } 1082 } 1083 1084 _mesa_free((void *) tempImage); 1085 } 1086 return GL_TRUE; 1087} 1088 1089 1090/** 1091 * Store a 32-bit integer depth component texture image. 1092 */ 1093GLboolean 1094_mesa_texstore_z32(TEXSTORE_PARAMS) 1095{ 1096 const GLuint depthScale = 0xffffffff; 1097 (void) dims; 1098 ASSERT(dstFormat == &_mesa_texformat_z32); 1099 ASSERT(dstFormat->TexelBytes == sizeof(GLuint)); 1100 1101 if (!ctx->_ImageTransferState && 1102 !srcPacking->SwapBytes && 1103 baseInternalFormat == GL_DEPTH_COMPONENT && 1104 srcFormat == GL_DEPTH_COMPONENT && 1105 srcType == GL_UNSIGNED_INT) { 1106 /* simple memcpy path */ 1107 memcpy_texture(ctx, dims, 1108 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1109 dstRowStride, 1110 dstImageOffsets, 1111 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1112 srcAddr, srcPacking); 1113 } 1114 else { 1115 /* general path */ 1116 GLint img, row; 1117 for (img = 0; img < srcDepth; img++) { 1118 GLubyte *dstRow = (GLubyte *) dstAddr 1119 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1120 + dstYoffset * dstRowStride 1121 + dstXoffset * dstFormat->TexelBytes; 1122 for (row = 0; row < srcHeight; row++) { 1123 const GLvoid *src = _mesa_image_address(dims, srcPacking, 1124 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 1125 _mesa_unpack_depth_span(ctx, srcWidth, 1126 GL_UNSIGNED_INT, (GLuint *) dstRow, 1127 depthScale, srcType, src, srcPacking); 1128 dstRow += dstRowStride; 1129 } 1130 } 1131 } 1132 return GL_TRUE; 1133} 1134 1135#define STRIDE_3D 0 1136 1137/** 1138 * Store a 16-bit integer depth component texture image. 1139 */ 1140GLboolean 1141_mesa_texstore_z16(TEXSTORE_PARAMS) 1142{ 1143 const GLuint depthScale = 0xffff; 1144 (void) dims; 1145 ASSERT(dstFormat == &_mesa_texformat_z16); 1146 ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); 1147 1148 if (!ctx->_ImageTransferState && 1149 !srcPacking->SwapBytes && 1150 baseInternalFormat == GL_DEPTH_COMPONENT && 1151 srcFormat == GL_DEPTH_COMPONENT && 1152 srcType == GL_UNSIGNED_SHORT) { 1153 /* simple memcpy path */ 1154 memcpy_texture(ctx, dims, 1155 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1156 dstRowStride, 1157 dstImageOffsets, 1158 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1159 srcAddr, srcPacking); 1160 } 1161 else { 1162 /* general path */ 1163 GLint img, row; 1164 for (img = 0; img < srcDepth; img++) { 1165 GLubyte *dstRow = (GLubyte *) dstAddr 1166 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1167 + dstYoffset * dstRowStride 1168 + dstXoffset * dstFormat->TexelBytes; 1169 for (row = 0; row < srcHeight; row++) { 1170 const GLvoid *src = _mesa_image_address(dims, srcPacking, 1171 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 1172 GLushort *dst16 = (GLushort *) dstRow; 1173 _mesa_unpack_depth_span(ctx, srcWidth, 1174 GL_UNSIGNED_SHORT, dst16, depthScale, 1175 srcType, src, srcPacking); 1176 dstRow += dstRowStride; 1177 } 1178 } 1179 } 1180 return GL_TRUE; 1181} 1182 1183 1184/** 1185 * Store an rgb565 or rgb565_rev texture image. 1186 */ 1187GLboolean 1188_mesa_texstore_rgb565(TEXSTORE_PARAMS) 1189{ 1190 ASSERT(dstFormat == &_mesa_texformat_rgb565 || 1191 dstFormat == &_mesa_texformat_rgb565_rev); 1192 ASSERT(dstFormat->TexelBytes == 2); 1193 1194 if (!ctx->_ImageTransferState && 1195 !srcPacking->SwapBytes && 1196 dstFormat == &_mesa_texformat_rgb565 && 1197 baseInternalFormat == GL_RGB && 1198 srcFormat == GL_RGB && 1199 srcType == GL_UNSIGNED_SHORT_5_6_5) { 1200 /* simple memcpy path */ 1201 memcpy_texture(ctx, dims, 1202 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1203 dstRowStride, 1204 dstImageOffsets, 1205 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1206 srcAddr, srcPacking); 1207 } 1208 else if (!ctx->_ImageTransferState && 1209 !srcPacking->SwapBytes && 1210 baseInternalFormat == GL_RGB && 1211 srcFormat == GL_RGB && 1212 srcType == GL_UNSIGNED_BYTE && 1213 dims == 2) { 1214 /* do optimized tex store */ 1215 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, 1216 srcFormat, srcType); 1217 const GLubyte *src = (const GLubyte *) 1218 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, 1219 srcFormat, srcType, 0, 0, 0); 1220 GLubyte *dst = (GLubyte *) dstAddr 1221 + dstYoffset * dstRowStride 1222 + dstXoffset * dstFormat->TexelBytes; 1223 GLint row, col; 1224 for (row = 0; row < srcHeight; row++) { 1225 const GLubyte *srcUB = (const GLubyte *) src; 1226 GLushort *dstUS = (GLushort *) dst; 1227 /* check for byteswapped format */ 1228 if (dstFormat == &_mesa_texformat_rgb565) { 1229 for (col = 0; col < srcWidth; col++) { 1230 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] ); 1231 srcUB += 3; 1232 } 1233 } 1234 else { 1235 for (col = 0; col < srcWidth; col++) { 1236 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] ); 1237 srcUB += 3; 1238 } 1239 } 1240 dst += dstRowStride; 1241 src += srcRowStride; 1242 } 1243 } 1244 else { 1245 /* general path */ 1246 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1247 baseInternalFormat, 1248 dstFormat->BaseFormat, 1249 srcWidth, srcHeight, srcDepth, 1250 srcFormat, srcType, srcAddr, 1251 srcPacking); 1252 const GLchan *src = tempImage; 1253 GLint img, row, col; 1254 if (!tempImage) 1255 return GL_FALSE; 1256 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1257 for (img = 0; img < srcDepth; img++) { 1258 GLubyte *dstRow = (GLubyte *) dstAddr 1259 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1260 + dstYoffset * dstRowStride 1261 + dstXoffset * dstFormat->TexelBytes; 1262 for (row = 0; row < srcHeight; row++) { 1263 GLushort *dstUS = (GLushort *) dstRow; 1264 /* check for byteswapped format */ 1265 if (dstFormat == &_mesa_texformat_rgb565) { 1266 for (col = 0; col < srcWidth; col++) { 1267 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]), 1268 CHAN_TO_UBYTE(src[GCOMP]), 1269 CHAN_TO_UBYTE(src[BCOMP]) ); 1270 src += 3; 1271 } 1272 } 1273 else { 1274 for (col = 0; col < srcWidth; col++) { 1275 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]), 1276 CHAN_TO_UBYTE(src[GCOMP]), 1277 CHAN_TO_UBYTE(src[BCOMP]) ); 1278 src += 3; 1279 } 1280 } 1281 dstRow += dstRowStride; 1282 } 1283 } 1284 _mesa_free((void *) tempImage); 1285 } 1286 return GL_TRUE; 1287} 1288 1289 1290/** 1291 * Store a texture in MESA_FORMAT_RGBA8888 or MESA_FORMAT_RGBA8888_REV. 1292 */ 1293GLboolean 1294_mesa_texstore_rgba8888(TEXSTORE_PARAMS) 1295{ 1296 const GLboolean littleEndian = _mesa_little_endian(); 1297 1298 ASSERT(dstFormat == &_mesa_texformat_rgba8888 || 1299 dstFormat == &_mesa_texformat_rgba8888_rev); 1300 ASSERT(dstFormat->TexelBytes == 4); 1301 1302 if (!ctx->_ImageTransferState && 1303 !srcPacking->SwapBytes && 1304 dstFormat == &_mesa_texformat_rgba8888 && 1305 baseInternalFormat == GL_RGBA && 1306 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || 1307 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || 1308 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || 1309 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) { 1310 /* simple memcpy path */ 1311 memcpy_texture(ctx, dims, 1312 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1313 dstRowStride, 1314 dstImageOffsets, 1315 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1316 srcAddr, srcPacking); 1317 } 1318 else if (!ctx->_ImageTransferState && 1319 !srcPacking->SwapBytes && 1320 dstFormat == &_mesa_texformat_rgba8888_rev && 1321 baseInternalFormat == GL_RGBA && 1322 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || 1323 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || 1324 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || 1325 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) { 1326 /* simple memcpy path */ 1327 memcpy_texture(ctx, dims, 1328 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1329 dstRowStride, 1330 dstImageOffsets, 1331 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1332 srcAddr, srcPacking); 1333 } 1334 else if (!ctx->_ImageTransferState && 1335 (srcType == GL_UNSIGNED_BYTE || 1336 srcType == GL_UNSIGNED_INT_8_8_8_8 || 1337 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && 1338 can_swizzle(baseInternalFormat) && 1339 can_swizzle(srcFormat)) { 1340 1341 GLubyte dstmap[4]; 1342 1343 /* dstmap - how to swizzle from RGBA to dst format: 1344 */ 1345 if ((littleEndian && dstFormat == &_mesa_texformat_rgba8888) || 1346 (!littleEndian && dstFormat == &_mesa_texformat_rgba8888_rev)) { 1347 dstmap[3] = 0; 1348 dstmap[2] = 1; 1349 dstmap[1] = 2; 1350 dstmap[0] = 3; 1351 } 1352 else { 1353 dstmap[3] = 3; 1354 dstmap[2] = 2; 1355 dstmap[1] = 1; 1356 dstmap[0] = 0; 1357 } 1358 1359 _mesa_swizzle_ubyte_image(ctx, dims, 1360 srcFormat, 1361 srcType, 1362 baseInternalFormat, 1363 dstmap, 4, 1364 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1365 dstRowStride, dstImageOffsets, 1366 srcWidth, srcHeight, srcDepth, srcAddr, 1367 srcPacking); 1368 } 1369 else { 1370 /* general path */ 1371 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1372 baseInternalFormat, 1373 dstFormat->BaseFormat, 1374 srcWidth, srcHeight, srcDepth, 1375 srcFormat, srcType, srcAddr, 1376 srcPacking); 1377 const GLchan *src = tempImage; 1378 GLint img, row, col; 1379 if (!tempImage) 1380 return GL_FALSE; 1381 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1382 for (img = 0; img < srcDepth; img++) { 1383 GLubyte *dstRow = (GLubyte *) dstAddr 1384 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1385 + dstYoffset * dstRowStride 1386 + dstXoffset * dstFormat->TexelBytes; 1387 for (row = 0; row < srcHeight; row++) { 1388 GLuint *dstUI = (GLuint *) dstRow; 1389 if (dstFormat == &_mesa_texformat_rgba8888) { 1390 for (col = 0; col < srcWidth; col++) { 1391 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]), 1392 CHAN_TO_UBYTE(src[GCOMP]), 1393 CHAN_TO_UBYTE(src[BCOMP]), 1394 CHAN_TO_UBYTE(src[ACOMP]) ); 1395 src += 4; 1396 } 1397 } 1398 else { 1399 for (col = 0; col < srcWidth; col++) { 1400 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]), 1401 CHAN_TO_UBYTE(src[GCOMP]), 1402 CHAN_TO_UBYTE(src[BCOMP]), 1403 CHAN_TO_UBYTE(src[ACOMP]) ); 1404 src += 4; 1405 } 1406 } 1407 dstRow += dstRowStride; 1408 } 1409 } 1410 _mesa_free((void *) tempImage); 1411 } 1412 return GL_TRUE; 1413} 1414 1415 1416GLboolean 1417_mesa_texstore_argb8888(TEXSTORE_PARAMS) 1418{ 1419 const GLboolean littleEndian = _mesa_little_endian(); 1420 1421 ASSERT(dstFormat == &_mesa_texformat_argb8888 || 1422 dstFormat == &_mesa_texformat_argb8888_rev); 1423 ASSERT(dstFormat->TexelBytes == 4); 1424 1425 if (!ctx->_ImageTransferState && 1426 !srcPacking->SwapBytes && 1427 dstFormat == &_mesa_texformat_argb8888 && 1428 baseInternalFormat == GL_RGBA && 1429 srcFormat == GL_BGRA && 1430 ((srcType == GL_UNSIGNED_BYTE && littleEndian) || 1431 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { 1432 /* simple memcpy path (little endian) */ 1433 memcpy_texture(ctx, dims, 1434 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1435 dstRowStride, 1436 dstImageOffsets, 1437 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1438 srcAddr, srcPacking); 1439 } 1440 else if (!ctx->_ImageTransferState && 1441 !srcPacking->SwapBytes && 1442 dstFormat == &_mesa_texformat_argb8888_rev && 1443 baseInternalFormat == GL_RGBA && 1444 srcFormat == GL_BGRA && 1445 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || 1446 srcType == GL_UNSIGNED_INT_8_8_8_8)) { 1447 /* simple memcpy path (big endian) */ 1448 memcpy_texture(ctx, dims, 1449 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1450 dstRowStride, 1451 dstImageOffsets, 1452 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1453 srcAddr, srcPacking); 1454 } 1455 else if (!ctx->_ImageTransferState && 1456 !srcPacking->SwapBytes && 1457 dstFormat == &_mesa_texformat_argb8888 && 1458 srcFormat == GL_RGB && 1459 (baseInternalFormat == GL_RGBA || 1460 baseInternalFormat == GL_RGB) && 1461 srcType == GL_UNSIGNED_BYTE) { 1462 int img, row, col; 1463 for (img = 0; img < srcDepth; img++) { 1464 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1465 srcWidth, srcFormat, srcType); 1466 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1467 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1468 GLubyte *dstRow = (GLubyte *) dstAddr 1469 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1470 + dstYoffset * dstRowStride 1471 + dstXoffset * dstFormat->TexelBytes; 1472 for (row = 0; row < srcHeight; row++) { 1473 GLuint *d4 = (GLuint *) dstRow; 1474 for (col = 0; col < srcWidth; col++) { 1475 d4[col] = ((0xff << 24) | 1476 (srcRow[col * 3 + RCOMP] << 16) | 1477 (srcRow[col * 3 + GCOMP] << 8) | 1478 (srcRow[col * 3 + BCOMP] << 0)); 1479 } 1480 dstRow += dstRowStride; 1481 srcRow += srcRowStride; 1482 } 1483 } 1484 } 1485 else if (!ctx->_ImageTransferState && 1486 !srcPacking->SwapBytes && 1487 dstFormat == &_mesa_texformat_argb8888 && 1488 srcFormat == GL_RGBA && 1489 baseInternalFormat == GL_RGBA && 1490 srcType == GL_UNSIGNED_BYTE && 1491 littleEndian) { 1492 /* same as above case, but src data has alpha too */ 1493 GLint img, row, col; 1494 /* For some reason, streaming copies to write-combined regions 1495 * are extremely sensitive to the characteristics of how the 1496 * source data is retrieved. By reordering the source reads to 1497 * be in-order, the speed of this operation increases by half. 1498 * Strangely the same isn't required for the RGB path, above. 1499 */ 1500 for (img = 0; img < srcDepth; img++) { 1501 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1502 srcWidth, srcFormat, srcType); 1503 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1504 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1505 GLubyte *dstRow = (GLubyte *) dstAddr 1506 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1507 + dstYoffset * dstRowStride 1508 + dstXoffset * dstFormat->TexelBytes; 1509 for (row = 0; row < srcHeight; row++) { 1510 GLuint *d4 = (GLuint *) dstRow; 1511 for (col = 0; col < srcWidth; col++) { 1512 d4[col] = ((srcRow[col * 4 + ACOMP] << 24) | 1513 (srcRow[col * 4 + RCOMP] << 16) | 1514 (srcRow[col * 4 + GCOMP] << 8) | 1515 (srcRow[col * 4 + BCOMP] << 0)); 1516 } 1517 dstRow += dstRowStride; 1518 srcRow += srcRowStride; 1519 } 1520 } 1521 } 1522 else if (!ctx->_ImageTransferState && 1523 !srcPacking->SwapBytes && 1524 dstFormat == &_mesa_texformat_argb8888 && 1525 srcFormat == GL_RGBA && 1526 baseInternalFormat == GL_RGBA && 1527 srcType == GL_UNSIGNED_BYTE) { 1528 1529 GLint img, row, col; 1530 for (img = 0; img < srcDepth; img++) { 1531 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1532 srcWidth, srcFormat, srcType); 1533 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1534 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1535 GLubyte *dstRow = (GLubyte *) dstAddr 1536 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1537 + dstYoffset * dstRowStride 1538 + dstXoffset * dstFormat->TexelBytes; 1539 for (row = 0; row < srcHeight; row++) { 1540 for (col = 0; col < srcWidth; col++) { 1541 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP]; 1542 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP]; 1543 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP]; 1544 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP]; 1545 } 1546 dstRow += dstRowStride; 1547 srcRow += srcRowStride; 1548 } 1549 } 1550 } 1551 else if (!ctx->_ImageTransferState && 1552 (srcType == GL_UNSIGNED_BYTE || 1553 srcType == GL_UNSIGNED_INT_8_8_8_8 || 1554 srcType == GL_UNSIGNED_INT_8_8_8_8_REV) && 1555 can_swizzle(baseInternalFormat) && 1556 can_swizzle(srcFormat)) { 1557 1558 GLubyte dstmap[4]; 1559 1560 /* dstmap - how to swizzle from RGBA to dst format: 1561 */ 1562 if ((littleEndian && dstFormat == &_mesa_texformat_argb8888) || 1563 (!littleEndian && dstFormat == &_mesa_texformat_argb8888_rev)) { 1564 dstmap[3] = 3; /* alpha */ 1565 dstmap[2] = 0; /* red */ 1566 dstmap[1] = 1; /* green */ 1567 dstmap[0] = 2; /* blue */ 1568 } 1569 else { 1570 assert((littleEndian && dstFormat == &_mesa_texformat_argb8888_rev) || 1571 (!littleEndian && dstFormat == &_mesa_texformat_argb8888)); 1572 dstmap[3] = 2; 1573 dstmap[2] = 1; 1574 dstmap[1] = 0; 1575 dstmap[0] = 3; 1576 } 1577 1578 _mesa_swizzle_ubyte_image(ctx, dims, 1579 srcFormat, 1580 srcType, 1581 1582 baseInternalFormat, 1583 dstmap, 4, 1584 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1585 dstRowStride, 1586 dstImageOffsets, 1587 srcWidth, srcHeight, srcDepth, srcAddr, 1588 srcPacking); 1589 } 1590 else { 1591 /* general path */ 1592 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1593 baseInternalFormat, 1594 dstFormat->BaseFormat, 1595 srcWidth, srcHeight, srcDepth, 1596 srcFormat, srcType, srcAddr, 1597 srcPacking); 1598 const GLchan *src = tempImage; 1599 GLint img, row, col; 1600 if (!tempImage) 1601 return GL_FALSE; 1602 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1603 for (img = 0; img < srcDepth; img++) { 1604 GLubyte *dstRow = (GLubyte *) dstAddr 1605 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1606 + dstYoffset * dstRowStride 1607 + dstXoffset * dstFormat->TexelBytes; 1608 for (row = 0; row < srcHeight; row++) { 1609 GLuint *dstUI = (GLuint *) dstRow; 1610 if (dstFormat == &_mesa_texformat_argb8888) { 1611 for (col = 0; col < srcWidth; col++) { 1612 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]), 1613 CHAN_TO_UBYTE(src[RCOMP]), 1614 CHAN_TO_UBYTE(src[GCOMP]), 1615 CHAN_TO_UBYTE(src[BCOMP]) ); 1616 src += 4; 1617 } 1618 } 1619 else { 1620 for (col = 0; col < srcWidth; col++) { 1621 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]), 1622 CHAN_TO_UBYTE(src[RCOMP]), 1623 CHAN_TO_UBYTE(src[GCOMP]), 1624 CHAN_TO_UBYTE(src[BCOMP]) ); 1625 src += 4; 1626 } 1627 } 1628 dstRow += dstRowStride; 1629 } 1630 } 1631 _mesa_free((void *) tempImage); 1632 } 1633 return GL_TRUE; 1634} 1635 1636 1637GLboolean 1638_mesa_texstore_rgb888(TEXSTORE_PARAMS) 1639{ 1640 const GLboolean littleEndian = _mesa_little_endian(); 1641 1642 ASSERT(dstFormat == &_mesa_texformat_rgb888); 1643 ASSERT(dstFormat->TexelBytes == 3); 1644 1645 if (!ctx->_ImageTransferState && 1646 !srcPacking->SwapBytes && 1647 baseInternalFormat == GL_RGB && 1648 srcFormat == GL_BGR && 1649 srcType == GL_UNSIGNED_BYTE && 1650 littleEndian) { 1651 /* simple memcpy path */ 1652 memcpy_texture(ctx, dims, 1653 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1654 dstRowStride, 1655 dstImageOffsets, 1656 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1657 srcAddr, srcPacking); 1658 } 1659 else if (!ctx->_ImageTransferState && 1660 !srcPacking->SwapBytes && 1661 srcFormat == GL_RGBA && 1662 srcType == GL_UNSIGNED_BYTE) { 1663 /* extract RGB from RGBA */ 1664 GLint img, row, col; 1665 for (img = 0; img < srcDepth; img++) { 1666 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1667 srcWidth, srcFormat, srcType); 1668 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1669 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1670 GLubyte *dstRow = (GLubyte *) dstAddr 1671 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1672 + dstYoffset * dstRowStride 1673 + dstXoffset * dstFormat->TexelBytes; 1674 for (row = 0; row < srcHeight; row++) { 1675 for (col = 0; col < srcWidth; col++) { 1676 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP]; 1677 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; 1678 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP]; 1679 } 1680 dstRow += dstRowStride; 1681 srcRow += srcRowStride; 1682 } 1683 } 1684 } 1685 else if (!ctx->_ImageTransferState && 1686 srcType == GL_UNSIGNED_BYTE && 1687 can_swizzle(baseInternalFormat) && 1688 can_swizzle(srcFormat)) { 1689 1690 GLubyte dstmap[4]; 1691 1692 /* dstmap - how to swizzle from RGBA to dst format: 1693 */ 1694 dstmap[0] = 2; 1695 dstmap[1] = 1; 1696 dstmap[2] = 0; 1697 dstmap[3] = ONE; /* ? */ 1698 1699 _mesa_swizzle_ubyte_image(ctx, dims, 1700 srcFormat, 1701 srcType, 1702 baseInternalFormat, 1703 dstmap, 3, 1704 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1705 dstRowStride, dstImageOffsets, 1706 srcWidth, srcHeight, srcDepth, srcAddr, 1707 srcPacking); 1708 } 1709 else { 1710 /* general path */ 1711 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1712 baseInternalFormat, 1713 dstFormat->BaseFormat, 1714 srcWidth, srcHeight, srcDepth, 1715 srcFormat, srcType, srcAddr, 1716 srcPacking); 1717 const GLchan *src = (const GLchan *) tempImage; 1718 GLint img, row, col; 1719 if (!tempImage) 1720 return GL_FALSE; 1721 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1722 for (img = 0; img < srcDepth; img++) { 1723 GLubyte *dstRow = (GLubyte *) dstAddr 1724 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1725 + dstYoffset * dstRowStride 1726 + dstXoffset * dstFormat->TexelBytes; 1727 for (row = 0; row < srcHeight; row++) { 1728#if 0 1729 if (littleEndian) { 1730 for (col = 0; col < srcWidth; col++) { 1731 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); 1732 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1733 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); 1734 srcUB += 3; 1735 } 1736 } 1737 else { 1738 for (col = 0; col < srcWidth; col++) { 1739 dstRow[col * 3 + 0] = srcUB[BCOMP]; 1740 dstRow[col * 3 + 1] = srcUB[GCOMP]; 1741 dstRow[col * 3 + 2] = srcUB[RCOMP]; 1742 srcUB += 3; 1743 } 1744 } 1745#else 1746 for (col = 0; col < srcWidth; col++) { 1747 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]); 1748 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1749 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]); 1750 src += 3; 1751 } 1752#endif 1753 dstRow += dstRowStride; 1754 } 1755 } 1756 _mesa_free((void *) tempImage); 1757 } 1758 return GL_TRUE; 1759} 1760 1761 1762GLboolean 1763_mesa_texstore_bgr888(TEXSTORE_PARAMS) 1764{ 1765 const GLboolean littleEndian = _mesa_little_endian(); 1766 1767 ASSERT(dstFormat == &_mesa_texformat_bgr888); 1768 ASSERT(dstFormat->TexelBytes == 3); 1769 1770 if (!ctx->_ImageTransferState && 1771 !srcPacking->SwapBytes && 1772 baseInternalFormat == GL_RGB && 1773 srcFormat == GL_RGB && 1774 srcType == GL_UNSIGNED_BYTE && 1775 littleEndian) { 1776 /* simple memcpy path */ 1777 memcpy_texture(ctx, dims, 1778 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1779 dstRowStride, 1780 dstImageOffsets, 1781 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1782 srcAddr, srcPacking); 1783 } 1784 else if (!ctx->_ImageTransferState && 1785 !srcPacking->SwapBytes && 1786 srcFormat == GL_RGBA && 1787 srcType == GL_UNSIGNED_BYTE) { 1788 /* extract BGR from RGBA */ 1789 int img, row, col; 1790 for (img = 0; img < srcDepth; img++) { 1791 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1792 srcWidth, srcFormat, srcType); 1793 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1794 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1795 GLubyte *dstRow = (GLubyte *) dstAddr 1796 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1797 + dstYoffset * dstRowStride 1798 + dstXoffset * dstFormat->TexelBytes; 1799 for (row = 0; row < srcHeight; row++) { 1800 for (col = 0; col < srcWidth; col++) { 1801 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP]; 1802 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; 1803 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP]; 1804 } 1805 dstRow += dstRowStride; 1806 srcRow += srcRowStride; 1807 } 1808 } 1809 } 1810 else if (!ctx->_ImageTransferState && 1811 srcType == GL_UNSIGNED_BYTE && 1812 can_swizzle(baseInternalFormat) && 1813 can_swizzle(srcFormat)) { 1814 1815 GLubyte dstmap[4]; 1816 1817 /* dstmap - how to swizzle from RGBA to dst format: 1818 */ 1819 dstmap[0] = 0; 1820 dstmap[1] = 1; 1821 dstmap[2] = 2; 1822 dstmap[3] = ONE; /* ? */ 1823 1824 _mesa_swizzle_ubyte_image(ctx, dims, 1825 srcFormat, 1826 srcType, 1827 baseInternalFormat, 1828 dstmap, 3, 1829 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1830 dstRowStride, dstImageOffsets, 1831 srcWidth, srcHeight, srcDepth, srcAddr, 1832 srcPacking); 1833 } 1834 else { 1835 /* general path */ 1836 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1837 baseInternalFormat, 1838 dstFormat->BaseFormat, 1839 srcWidth, srcHeight, srcDepth, 1840 srcFormat, srcType, srcAddr, 1841 srcPacking); 1842 const GLchan *src = (const GLchan *) tempImage; 1843 GLint img, row, col; 1844 if (!tempImage) 1845 return GL_FALSE; 1846 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1847 for (img = 0; img < srcDepth; img++) { 1848 GLubyte *dstRow = (GLubyte *) dstAddr 1849 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1850 + dstYoffset * dstRowStride 1851 + dstXoffset * dstFormat->TexelBytes; 1852 for (row = 0; row < srcHeight; row++) { 1853 for (col = 0; col < srcWidth; col++) { 1854 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); 1855 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1856 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); 1857 src += 3; 1858 } 1859 dstRow += dstRowStride; 1860 } 1861 } 1862 _mesa_free((void *) tempImage); 1863 } 1864 return GL_TRUE; 1865} 1866 1867 1868GLboolean 1869_mesa_texstore_argb4444(TEXSTORE_PARAMS) 1870{ 1871 ASSERT(dstFormat == &_mesa_texformat_argb4444 || 1872 dstFormat == &_mesa_texformat_argb4444_rev); 1873 ASSERT(dstFormat->TexelBytes == 2); 1874 1875 if (!ctx->_ImageTransferState && 1876 !srcPacking->SwapBytes && 1877 dstFormat == &_mesa_texformat_argb4444 && 1878 baseInternalFormat == GL_RGBA && 1879 srcFormat == GL_BGRA && 1880 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) { 1881 /* simple memcpy path */ 1882 memcpy_texture(ctx, dims, 1883 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1884 dstRowStride, 1885 dstImageOffsets, 1886 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1887 srcAddr, srcPacking); 1888 } 1889 else { 1890 /* general path */ 1891 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1892 baseInternalFormat, 1893 dstFormat->BaseFormat, 1894 srcWidth, srcHeight, srcDepth, 1895 srcFormat, srcType, srcAddr, 1896 srcPacking); 1897 const GLchan *src = tempImage; 1898 GLint img, row, col; 1899 if (!tempImage) 1900 return GL_FALSE; 1901 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1902 for (img = 0; img < srcDepth; img++) { 1903 GLubyte *dstRow = (GLubyte *) dstAddr 1904 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1905 + dstYoffset * dstRowStride 1906 + dstXoffset * dstFormat->TexelBytes; 1907 for (row = 0; row < srcHeight; row++) { 1908 GLushort *dstUS = (GLushort *) dstRow; 1909 if (dstFormat == &_mesa_texformat_argb4444) { 1910 for (col = 0; col < srcWidth; col++) { 1911 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]), 1912 CHAN_TO_UBYTE(src[RCOMP]), 1913 CHAN_TO_UBYTE(src[GCOMP]), 1914 CHAN_TO_UBYTE(src[BCOMP]) ); 1915 src += 4; 1916 } 1917 } 1918 else { 1919 for (col = 0; col < srcWidth; col++) { 1920 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]), 1921 CHAN_TO_UBYTE(src[RCOMP]), 1922 CHAN_TO_UBYTE(src[GCOMP]), 1923 CHAN_TO_UBYTE(src[BCOMP]) ); 1924 src += 4; 1925 } 1926 } 1927 dstRow += dstRowStride; 1928 } 1929 } 1930 _mesa_free((void *) tempImage); 1931 } 1932 return GL_TRUE; 1933} 1934 1935 1936 1937GLboolean 1938_mesa_texstore_argb1555(TEXSTORE_PARAMS) 1939{ 1940 ASSERT(dstFormat == &_mesa_texformat_argb1555 || 1941 dstFormat == &_mesa_texformat_argb1555_rev); 1942 ASSERT(dstFormat->TexelBytes == 2); 1943 1944 if (!ctx->_ImageTransferState && 1945 !srcPacking->SwapBytes && 1946 dstFormat == &_mesa_texformat_argb1555 && 1947 baseInternalFormat == GL_RGBA && 1948 srcFormat == GL_BGRA && 1949 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) { 1950 /* simple memcpy path */ 1951 memcpy_texture(ctx, dims, 1952 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1953 dstRowStride, 1954 dstImageOffsets, 1955 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1956 srcAddr, srcPacking); 1957 } 1958 else { 1959 /* general path */ 1960 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1961 baseInternalFormat, 1962 dstFormat->BaseFormat, 1963 srcWidth, srcHeight, srcDepth, 1964 srcFormat, srcType, srcAddr, 1965 srcPacking); 1966 const GLchan *src =tempImage; 1967 GLint img, row, col; 1968 if (!tempImage) 1969 return GL_FALSE; 1970 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1971 for (img = 0; img < srcDepth; img++) { 1972 GLubyte *dstRow = (GLubyte *) dstAddr 1973 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1974 + dstYoffset * dstRowStride 1975 + dstXoffset * dstFormat->TexelBytes; 1976 for (row = 0; row < srcHeight; row++) { 1977 GLushort *dstUS = (GLushort *) dstRow; 1978 if (dstFormat == &_mesa_texformat_argb1555) { 1979 for (col = 0; col < srcWidth; col++) { 1980 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]), 1981 CHAN_TO_UBYTE(src[RCOMP]), 1982 CHAN_TO_UBYTE(src[GCOMP]), 1983 CHAN_TO_UBYTE(src[BCOMP]) ); 1984 src += 4; 1985 } 1986 } 1987 else { 1988 for (col = 0; col < srcWidth; col++) { 1989 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]), 1990 CHAN_TO_UBYTE(src[RCOMP]), 1991 CHAN_TO_UBYTE(src[GCOMP]), 1992 CHAN_TO_UBYTE(src[BCOMP]) ); 1993 src += 4; 1994 } 1995 } 1996 dstRow += dstRowStride; 1997 } 1998 } 1999 _mesa_free((void *) tempImage); 2000 } 2001 return GL_TRUE; 2002} 2003 2004 2005GLboolean 2006_mesa_texstore_al88(TEXSTORE_PARAMS) 2007{ 2008 const GLboolean littleEndian = _mesa_little_endian(); 2009 2010 ASSERT(dstFormat == &_mesa_texformat_al88 || 2011 dstFormat == &_mesa_texformat_al88_rev); 2012 ASSERT(dstFormat->TexelBytes == 2); 2013 2014 if (!ctx->_ImageTransferState && 2015 !srcPacking->SwapBytes && 2016 dstFormat == &_mesa_texformat_al88 && 2017 baseInternalFormat == GL_LUMINANCE_ALPHA && 2018 srcFormat == GL_LUMINANCE_ALPHA && 2019 srcType == GL_UNSIGNED_BYTE && 2020 littleEndian) { 2021 /* simple memcpy path */ 2022 memcpy_texture(ctx, dims, 2023 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2024 dstRowStride, 2025 dstImageOffsets, 2026 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2027 srcAddr, srcPacking); 2028 } 2029 else if (!ctx->_ImageTransferState && 2030 littleEndian && 2031 srcType == GL_UNSIGNED_BYTE && 2032 can_swizzle(baseInternalFormat) && 2033 can_swizzle(srcFormat)) { 2034 2035 GLubyte dstmap[4]; 2036 2037 /* dstmap - how to swizzle from RGBA to dst format: 2038 */ 2039 if ((littleEndian && dstFormat == &_mesa_texformat_al88) || 2040 (!littleEndian && dstFormat == &_mesa_texformat_al88_rev)) { 2041 dstmap[0] = 0; 2042 dstmap[1] = 3; 2043 } 2044 else { 2045 dstmap[0] = 3; 2046 dstmap[1] = 0; 2047 } 2048 dstmap[2] = ZERO; /* ? */ 2049 dstmap[3] = ONE; /* ? */ 2050 2051 _mesa_swizzle_ubyte_image(ctx, dims, 2052 srcFormat, 2053 srcType, 2054 baseInternalFormat, 2055 dstmap, 2, 2056 dstAddr, dstXoffset, dstYoffset, dstZoffset, 2057 dstRowStride, dstImageOffsets, 2058 srcWidth, srcHeight, srcDepth, srcAddr, 2059 srcPacking); 2060 } 2061 else { 2062 /* general path */ 2063 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 2064 baseInternalFormat, 2065 dstFormat->BaseFormat, 2066 srcWidth, srcHeight, srcDepth, 2067 srcFormat, srcType, srcAddr, 2068 srcPacking); 2069 const GLchan *src = tempImage; 2070 GLint img, row, col; 2071 if (!tempImage) 2072 return GL_FALSE; 2073 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2074 for (img = 0; img < srcDepth; img++) { 2075 GLubyte *dstRow = (GLubyte *) dstAddr 2076 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2077 + dstYoffset * dstRowStride 2078 + dstXoffset * dstFormat->TexelBytes; 2079 for (row = 0; row < srcHeight; row++) { 2080 GLushort *dstUS = (GLushort *) dstRow; 2081 if (dstFormat == &_mesa_texformat_al88) { 2082 for (col = 0; col < srcWidth; col++) { 2083 /* src[0] is luminance, src[1] is alpha */ 2084 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]), 2085 CHAN_TO_UBYTE(src[0]) ); 2086 src += 2; 2087 } 2088 } 2089 else { 2090 for (col = 0; col < srcWidth; col++) { 2091 /* src[0] is luminance, src[1] is alpha */ 2092 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]), 2093 CHAN_TO_UBYTE(src[0]) ); 2094 src += 2; 2095 } 2096 } 2097 dstRow += dstRowStride; 2098 } 2099 } 2100 _mesa_free((void *) tempImage); 2101 } 2102 return GL_TRUE; 2103} 2104 2105 2106GLboolean 2107_mesa_texstore_rgb332(TEXSTORE_PARAMS) 2108{ 2109 ASSERT(dstFormat == &_mesa_texformat_rgb332); 2110 ASSERT(dstFormat->TexelBytes == 1); 2111 2112 if (!ctx->_ImageTransferState && 2113 !srcPacking->SwapBytes && 2114 baseInternalFormat == GL_RGB && 2115 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) { 2116 /* simple memcpy path */ 2117 memcpy_texture(ctx, dims, 2118 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2119 dstRowStride, 2120 dstImageOffsets, 2121 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2122 srcAddr, srcPacking); 2123 } 2124 else { 2125 /* general path */ 2126 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 2127 baseInternalFormat, 2128 dstFormat->BaseFormat, 2129 srcWidth, srcHeight, srcDepth, 2130 srcFormat, srcType, srcAddr, 2131 srcPacking); 2132 const GLchan *src = tempImage; 2133 GLint img, row, col; 2134 if (!tempImage) 2135 return GL_FALSE; 2136 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2137 for (img = 0; img < srcDepth; img++) { 2138 GLubyte *dstRow = (GLubyte *) dstAddr 2139 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2140 + dstYoffset * dstRowStride 2141 + dstXoffset * dstFormat->TexelBytes; 2142 for (row = 0; row < srcHeight; row++) { 2143 for (col = 0; col < srcWidth; col++) { 2144 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]), 2145 CHAN_TO_UBYTE(src[GCOMP]), 2146 CHAN_TO_UBYTE(src[BCOMP]) ); 2147 src += 3; 2148 } 2149 dstRow += dstRowStride; 2150 } 2151 } 2152 _mesa_free((void *) tempImage); 2153 } 2154 return GL_TRUE; 2155} 2156 2157 2158/** 2159 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. 2160 */ 2161GLboolean 2162_mesa_texstore_a8(TEXSTORE_PARAMS) 2163{ 2164 ASSERT(dstFormat == &_mesa_texformat_a8 || 2165 dstFormat == &_mesa_texformat_l8 || 2166 dstFormat == &_mesa_texformat_i8); 2167 ASSERT(dstFormat->TexelBytes == 1); 2168 2169 if (!ctx->_ImageTransferState && 2170 !srcPacking->SwapBytes && 2171 baseInternalFormat == srcFormat && 2172 srcType == GL_UNSIGNED_BYTE) { 2173 /* simple memcpy path */ 2174 memcpy_texture(ctx, dims, 2175 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2176 dstRowStride, 2177 dstImageOffsets, 2178 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2179 srcAddr, srcPacking); 2180 } 2181 else if (!ctx->_ImageTransferState && 2182 srcType == GL_UNSIGNED_BYTE && 2183 can_swizzle(baseInternalFormat) && 2184 can_swizzle(srcFormat)) { 2185 2186 GLubyte dstmap[4]; 2187 2188 /* dstmap - how to swizzle from RGBA to dst format: 2189 */ 2190 if (dstFormat == &_mesa_texformat_a8) { 2191 dstmap[0] = 3; 2192 } 2193 else { 2194 dstmap[0] = 0; 2195 } 2196 dstmap[1] = ZERO; /* ? */ 2197 dstmap[2] = ZERO; /* ? */ 2198 dstmap[3] = ONE; /* ? */ 2199 2200 _mesa_swizzle_ubyte_image(ctx, dims, 2201 srcFormat, 2202 srcType, 2203 baseInternalFormat, 2204 dstmap, 1, 2205 dstAddr, dstXoffset, dstYoffset, dstZoffset, 2206 dstRowStride, dstImageOffsets, 2207 srcWidth, srcHeight, srcDepth, srcAddr, 2208 srcPacking); 2209 } 2210 else { 2211 /* general path */ 2212 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 2213 baseInternalFormat, 2214 dstFormat->BaseFormat, 2215 srcWidth, srcHeight, srcDepth, 2216 srcFormat, srcType, srcAddr, 2217 srcPacking); 2218 const GLchan *src = tempImage; 2219 GLint img, row, col; 2220 if (!tempImage) 2221 return GL_FALSE; 2222 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2223 for (img = 0; img < srcDepth; img++) { 2224 GLubyte *dstRow = (GLubyte *) dstAddr 2225 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2226 + dstYoffset * dstRowStride 2227 + dstXoffset * dstFormat->TexelBytes; 2228 for (row = 0; row < srcHeight; row++) { 2229 for (col = 0; col < srcWidth; col++) { 2230 dstRow[col] = CHAN_TO_UBYTE(src[col]); 2231 } 2232 dstRow += dstRowStride; 2233 src += srcWidth; 2234 } 2235 } 2236 _mesa_free((void *) tempImage); 2237 } 2238 return GL_TRUE; 2239} 2240 2241 2242 2243GLboolean 2244_mesa_texstore_ci8(TEXSTORE_PARAMS) 2245{ 2246 (void) dims; (void) baseInternalFormat; 2247 ASSERT(dstFormat == &_mesa_texformat_ci8); 2248 ASSERT(dstFormat->TexelBytes == 1); 2249 ASSERT(baseInternalFormat == GL_COLOR_INDEX); 2250 2251 if (!ctx->_ImageTransferState && 2252 !srcPacking->SwapBytes && 2253 srcFormat == GL_COLOR_INDEX && 2254 srcType == GL_UNSIGNED_BYTE) { 2255 /* simple memcpy path */ 2256 memcpy_texture(ctx, dims, 2257 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2258 dstRowStride, 2259 dstImageOffsets, 2260 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2261 srcAddr, srcPacking); 2262 } 2263 else { 2264 /* general path */ 2265 GLint img, row; 2266 for (img = 0; img < srcDepth; img++) { 2267 GLubyte *dstRow = (GLubyte *) dstAddr 2268 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2269 + dstYoffset * dstRowStride 2270 + dstXoffset * dstFormat->TexelBytes; 2271 for (row = 0; row < srcHeight; row++) { 2272 const GLvoid *src = _mesa_image_address(dims, srcPacking, 2273 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 2274 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow, 2275 srcType, src, srcPacking, 2276 ctx->_ImageTransferState); 2277 dstRow += dstRowStride; 2278 } 2279 } 2280 } 2281 return GL_TRUE; 2282} 2283 2284 2285/** 2286 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev. 2287 */ 2288GLboolean 2289_mesa_texstore_ycbcr(TEXSTORE_PARAMS) 2290{ 2291 const GLboolean littleEndian = _mesa_little_endian(); 2292 (void) ctx; (void) dims; (void) baseInternalFormat; 2293 2294 ASSERT((dstFormat == &_mesa_texformat_ycbcr) || 2295 (dstFormat == &_mesa_texformat_ycbcr_rev)); 2296 ASSERT(dstFormat->TexelBytes == 2); 2297 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 2298 ASSERT(srcFormat == GL_YCBCR_MESA); 2299 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) || 2300 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA)); 2301 ASSERT(baseInternalFormat == GL_YCBCR_MESA); 2302 2303 /* always just memcpy since no pixel transfer ops apply */ 2304 memcpy_texture(ctx, dims, 2305 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2306 dstRowStride, 2307 dstImageOffsets, 2308 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2309 srcAddr, srcPacking); 2310 2311 /* Check if we need byte swapping */ 2312 /* XXX the logic here _might_ be wrong */ 2313 if (srcPacking->SwapBytes ^ 2314 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^ 2315 (dstFormat == &_mesa_texformat_ycbcr_rev) ^ 2316 !littleEndian) { 2317 GLint img, row; 2318 for (img = 0; img < srcDepth; img++) { 2319 GLubyte *dstRow = (GLubyte *) dstAddr 2320 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2321 + dstYoffset * dstRowStride 2322 + dstXoffset * dstFormat->TexelBytes; 2323 for (row = 0; row < srcHeight; row++) { 2324 _mesa_swap2((GLushort *) dstRow, srcWidth); 2325 dstRow += dstRowStride; 2326 } 2327 } 2328 } 2329 return GL_TRUE; 2330} 2331 2332 2333 2334/** 2335 * Store a combined depth/stencil texture image. 2336 */ 2337GLboolean 2338_mesa_texstore_z24_s8(TEXSTORE_PARAMS) 2339{ 2340 const GLfloat depthScale = (GLfloat) 0xffffff; 2341 2342 ASSERT(dstFormat == &_mesa_texformat_z24_s8); 2343 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT); 2344 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT); 2345 2346 if (!ctx->_ImageTransferState && 2347 !srcPacking->SwapBytes) { 2348 /* simple path */ 2349 memcpy_texture(ctx, dims, 2350 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2351 dstRowStride, 2352 dstImageOffsets, 2353 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2354 srcAddr, srcPacking); 2355 } 2356 else { 2357 /* general path */ 2358 const GLint srcRowStride 2359 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) 2360 / sizeof(GLuint); 2361 GLint img, row; 2362 2363 for (img = 0; img < srcDepth; img++) { 2364 GLuint *dstRow = (GLuint *) dstAddr 2365 + dstImageOffsets[dstZoffset + img] 2366 + dstYoffset * dstRowStride / sizeof(GLuint) 2367 + dstXoffset; 2368 const GLuint *src 2369 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr, 2370 srcWidth, srcHeight, 2371 srcFormat, srcType, 2372 img, 0, 0); 2373 for (row = 0; row < srcHeight; row++) { 2374 GLubyte stencil[MAX_WIDTH]; 2375 GLint i; 2376 /* the 24 depth bits will be in the high position: */ 2377 _mesa_unpack_depth_span(ctx, srcWidth, 2378 GL_UNSIGNED_INT_24_8_EXT, /* dst type */ 2379 dstRow, /* dst addr */ 2380 depthScale, 2381 srcType, src, srcPacking); 2382 /* get the 8-bit stencil values */ 2383 _mesa_unpack_stencil_span(ctx, srcWidth, 2384 GL_UNSIGNED_BYTE, /* dst type */ 2385 stencil, /* dst addr */ 2386 srcType, src, srcPacking, 2387 ctx->_ImageTransferState); 2388 /* merge stencil values into depth values */ 2389 for (i = 0; i < srcWidth; i++) 2390 dstRow[i] |= stencil[i]; 2391 2392 src += srcRowStride; 2393 dstRow += dstRowStride / sizeof(GLuint); 2394 } 2395 } 2396 } 2397 return GL_TRUE; 2398} 2399 2400 2401/** 2402 * Store a combined depth/stencil texture image. 2403 */ 2404GLboolean 2405_mesa_texstore_s8_z24(TEXSTORE_PARAMS) 2406{ 2407 const GLuint depthScale = 0xffffff; 2408 2409 ASSERT(dstFormat == &_mesa_texformat_s8_z24); 2410 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT || srcFormat == GL_DEPTH_COMPONENT); 2411 ASSERT(srcFormat != GL_DEPTH_STENCIL_EXT || srcType == GL_UNSIGNED_INT_24_8_EXT); 2412 2413 const GLint srcRowStride 2414 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) 2415 / sizeof(GLuint); 2416 GLint img, row; 2417 2418 /* Incase we only upload depth we need to preserve the stencil */ 2419 if (srcFormat == GL_DEPTH_COMPONENT) { 2420 for (img = 0; img < srcDepth; img++) { 2421 GLuint *dstRow = (GLuint *) dstAddr 2422 + dstImageOffsets[dstZoffset + img] 2423 + dstYoffset * dstRowStride / sizeof(GLuint) 2424 + dstXoffset; 2425 const GLuint *src 2426 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr, 2427 srcWidth, srcHeight, 2428 srcFormat, srcType, 2429 img, 0, 0); 2430 for (row = 0; row < srcHeight; row++) { 2431 GLuint depth[MAX_WIDTH]; 2432 GLint i; 2433 _mesa_unpack_depth_span(ctx, srcWidth, 2434 GL_UNSIGNED_INT, /* dst type */ 2435 depth, /* dst addr */ 2436 depthScale, 2437 srcType, src, srcPacking); 2438 2439 for (i = 0; i < srcWidth; i++) 2440 dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000); 2441 2442 src += srcRowStride; 2443 dstRow += dstRowStride / sizeof(GLuint); 2444 } 2445 } 2446 } else { 2447 for (img = 0; img < srcDepth; img++) { 2448 GLuint *dstRow = (GLuint *) dstAddr 2449 + dstImageOffsets[dstZoffset + img] 2450 + dstYoffset * dstRowStride / sizeof(GLuint) 2451 + dstXoffset; 2452 const GLuint *src 2453 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr, 2454 srcWidth, srcHeight, 2455 srcFormat, srcType, 2456 img, 0, 0); 2457 for (row = 0; row < srcHeight; row++) { 2458 GLubyte stencil[MAX_WIDTH]; 2459 GLint i; 2460 /* the 24 depth bits will be in the high position: */ 2461 _mesa_unpack_depth_span(ctx, srcWidth, 2462 GL_UNSIGNED_INT, /* dst type */ 2463 dstRow, /* dst addr */ 2464 depthScale, 2465 srcType, src, srcPacking); 2466 /* get the 8-bit stencil values */ 2467 _mesa_unpack_stencil_span(ctx, srcWidth, 2468 GL_UNSIGNED_BYTE, /* dst type */ 2469 stencil, /* dst addr */ 2470 srcType, src, srcPacking, 2471 ctx->_ImageTransferState); 2472 /* merge stencil values into depth values */ 2473 for (i = 0; i < srcWidth; i++) 2474 dstRow[i] = stencil[i] << 24; 2475 2476 src += srcRowStride; 2477 dstRow += dstRowStride / sizeof(GLuint); 2478 } 2479 } 2480 } 2481 return GL_TRUE; 2482} 2483 2484/** 2485 * Store an image in any of the formats: 2486 * _mesa_texformat_rgba_float32 2487 * _mesa_texformat_rgb_float32 2488 * _mesa_texformat_alpha_float32 2489 * _mesa_texformat_luminance_float32 2490 * _mesa_texformat_luminance_alpha_float32 2491 * _mesa_texformat_intensity_float32 2492 */ 2493GLboolean 2494_mesa_texstore_rgba_float32(TEXSTORE_PARAMS) 2495{ 2496 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat); 2497 2498 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 || 2499 dstFormat == &_mesa_texformat_rgb_float32 || 2500 dstFormat == &_mesa_texformat_alpha_float32 || 2501 dstFormat == &_mesa_texformat_luminance_float32 || 2502 dstFormat == &_mesa_texformat_luminance_alpha_float32 || 2503 dstFormat == &_mesa_texformat_intensity_float32); 2504 ASSERT(baseInternalFormat == GL_RGBA || 2505 baseInternalFormat == GL_RGB || 2506 baseInternalFormat == GL_ALPHA || 2507 baseInternalFormat == GL_LUMINANCE || 2508 baseInternalFormat == GL_LUMINANCE_ALPHA || 2509 baseInternalFormat == GL_INTENSITY); 2510 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat)); 2511 2512 if (!ctx->_ImageTransferState && 2513 !srcPacking->SwapBytes && 2514 baseInternalFormat == srcFormat && 2515 srcType == GL_FLOAT) { 2516 /* simple memcpy path */ 2517 memcpy_texture(ctx, dims, 2518 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2519 dstRowStride, 2520 dstImageOffsets, 2521 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2522 srcAddr, srcPacking); 2523 } 2524 else { 2525 /* general path */ 2526 const GLfloat *tempImage = make_temp_float_image(ctx, dims, 2527 baseInternalFormat, 2528 dstFormat->BaseFormat, 2529 srcWidth, srcHeight, srcDepth, 2530 srcFormat, srcType, srcAddr, 2531 srcPacking); 2532 const GLfloat *srcRow = tempImage; 2533 GLint bytesPerRow; 2534 GLint img, row; 2535 if (!tempImage) 2536 return GL_FALSE; 2537 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2538 bytesPerRow = srcWidth * components * sizeof(GLfloat); 2539 for (img = 0; img < srcDepth; img++) { 2540 GLubyte *dstRow = (GLubyte *) dstAddr 2541 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2542 + dstYoffset * dstRowStride 2543 + dstXoffset * dstFormat->TexelBytes; 2544 for (row = 0; row < srcHeight; row++) { 2545 _mesa_memcpy(dstRow, srcRow, bytesPerRow); 2546 dstRow += dstRowStride; 2547 srcRow += srcWidth * components; 2548 } 2549 } 2550 2551 _mesa_free((void *) tempImage); 2552 } 2553 return GL_TRUE; 2554} 2555 2556 2557/** 2558 * As above, but store 16-bit floats. 2559 */ 2560GLboolean 2561_mesa_texstore_rgba_float16(TEXSTORE_PARAMS) 2562{ 2563 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat); 2564 2565 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 || 2566 dstFormat == &_mesa_texformat_rgb_float16 || 2567 dstFormat == &_mesa_texformat_alpha_float16 || 2568 dstFormat == &_mesa_texformat_luminance_float16 || 2569 dstFormat == &_mesa_texformat_luminance_alpha_float16 || 2570 dstFormat == &_mesa_texformat_intensity_float16); 2571 ASSERT(baseInternalFormat == GL_RGBA || 2572 baseInternalFormat == GL_RGB || 2573 baseInternalFormat == GL_ALPHA || 2574 baseInternalFormat == GL_LUMINANCE || 2575 baseInternalFormat == GL_LUMINANCE_ALPHA || 2576 baseInternalFormat == GL_INTENSITY); 2577 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB)); 2578 2579 if (!ctx->_ImageTransferState && 2580 !srcPacking->SwapBytes && 2581 baseInternalFormat == srcFormat && 2582 srcType == GL_HALF_FLOAT_ARB) { 2583 /* simple memcpy path */ 2584 memcpy_texture(ctx, dims, 2585 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2586 dstRowStride, 2587 dstImageOffsets, 2588 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2589 srcAddr, srcPacking); 2590 } 2591 else { 2592 /* general path */ 2593 const GLfloat *tempImage = make_temp_float_image(ctx, dims, 2594 baseInternalFormat, 2595 dstFormat->BaseFormat, 2596 srcWidth, srcHeight, srcDepth, 2597 srcFormat, srcType, srcAddr, 2598 srcPacking); 2599 const GLfloat *src = tempImage; 2600 GLint img, row; 2601 if (!tempImage) 2602 return GL_FALSE; 2603 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2604 for (img = 0; img < srcDepth; img++) { 2605 GLubyte *dstRow = (GLubyte *) dstAddr 2606 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2607 + dstYoffset * dstRowStride 2608 + dstXoffset * dstFormat->TexelBytes; 2609 for (row = 0; row < srcHeight; row++) { 2610 GLhalfARB *dstTexel = (GLhalfARB *) dstRow; 2611 GLint i; 2612 for (i = 0; i < srcWidth * components; i++) { 2613 dstTexel[i] = _mesa_float_to_half(src[i]); 2614 } 2615 dstRow += dstRowStride; 2616 src += srcWidth * components; 2617 } 2618 } 2619 2620 _mesa_free((void *) tempImage); 2621 } 2622 return GL_TRUE; 2623} 2624 2625 2626#if FEATURE_EXT_texture_sRGB 2627GLboolean 2628_mesa_texstore_srgb8(TEXSTORE_PARAMS) 2629{ 2630 const GLboolean littleEndian = _mesa_little_endian(); 2631 const struct gl_texture_format *newDstFormat; 2632 StoreTexImageFunc store; 2633 GLboolean k; 2634 2635 ASSERT(dstFormat == &_mesa_texformat_srgb8); 2636 2637 /* reuse normal rgb texstore code */ 2638 if (littleEndian) { 2639 newDstFormat = &_mesa_texformat_bgr888; 2640 store = _mesa_texstore_bgr888; 2641 } 2642 else { 2643 newDstFormat = &_mesa_texformat_rgb888; 2644 store = _mesa_texstore_rgb888; 2645 } 2646 2647 k = store(ctx, dims, baseInternalFormat, 2648 newDstFormat, dstAddr, 2649 dstXoffset, dstYoffset, dstZoffset, 2650 dstRowStride, dstImageOffsets, 2651 srcWidth, srcHeight, srcDepth, 2652 srcFormat, srcType, 2653 srcAddr, srcPacking); 2654 return k; 2655} 2656 2657 2658GLboolean 2659_mesa_texstore_srgba8(TEXSTORE_PARAMS) 2660{ 2661 const GLboolean littleEndian = _mesa_little_endian(); 2662 const struct gl_texture_format *newDstFormat; 2663 GLboolean k; 2664 2665 ASSERT(dstFormat == &_mesa_texformat_srgba8); 2666 2667 /* reuse normal rgba texstore code */ 2668 if (littleEndian) 2669 newDstFormat = &_mesa_texformat_rgba8888_rev; 2670 else 2671 newDstFormat = &_mesa_texformat_rgba8888; 2672 2673 k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat, 2674 newDstFormat, dstAddr, 2675 dstXoffset, dstYoffset, dstZoffset, 2676 dstRowStride, dstImageOffsets, 2677 srcWidth, srcHeight, srcDepth, 2678 srcFormat, srcType, 2679 srcAddr, srcPacking); 2680 return k; 2681} 2682 2683 2684GLboolean 2685_mesa_texstore_sl8(TEXSTORE_PARAMS) 2686{ 2687 const struct gl_texture_format *newDstFormat; 2688 GLboolean k; 2689 2690 ASSERT(dstFormat == &_mesa_texformat_sl8); 2691 2692 newDstFormat = &_mesa_texformat_l8; 2693 2694 /* _mesa_textore_a8 handles luminance8 too */ 2695 k = _mesa_texstore_a8(ctx, dims, baseInternalFormat, 2696 newDstFormat, dstAddr, 2697 dstXoffset, dstYoffset, dstZoffset, 2698 dstRowStride, dstImageOffsets, 2699 srcWidth, srcHeight, srcDepth, 2700 srcFormat, srcType, 2701 srcAddr, srcPacking); 2702 return k; 2703} 2704 2705 2706GLboolean 2707_mesa_texstore_sla8(TEXSTORE_PARAMS) 2708{ 2709 const GLboolean littleEndian = _mesa_little_endian(); 2710 const struct gl_texture_format *newDstFormat; 2711 GLboolean k; 2712 2713 ASSERT(dstFormat == &_mesa_texformat_sla8); 2714 2715 /* reuse normal luminance/alpha texstore code */ 2716 if (littleEndian) 2717 newDstFormat = &_mesa_texformat_al88; 2718 else 2719 newDstFormat = &_mesa_texformat_al88_rev; 2720 2721 k = _mesa_texstore_al88(ctx, dims, baseInternalFormat, 2722 newDstFormat, dstAddr, 2723 dstXoffset, dstYoffset, dstZoffset, 2724 dstRowStride, dstImageOffsets, 2725 srcWidth, srcHeight, srcDepth, 2726 srcFormat, srcType, 2727 srcAddr, srcPacking); 2728 return k; 2729} 2730 2731#endif /* FEATURE_EXT_texture_sRGB */ 2732 2733 2734/** 2735 * Check if an unpack PBO is active prior to fetching a texture image. 2736 * If so, do bounds checking and map the buffer into main memory. 2737 * Any errors detected will be recorded. 2738 * The caller _must_ call _mesa_unmap_teximage_pbo() too! 2739 */ 2740const GLvoid * 2741_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, 2742 GLsizei width, GLsizei height, GLsizei depth, 2743 GLenum format, GLenum type, const GLvoid *pixels, 2744 const struct gl_pixelstore_attrib *unpack, 2745 const char *funcName) 2746{ 2747 GLubyte *buf; 2748 2749 if (unpack->BufferObj->Name == 0) { 2750 /* no PBO */ 2751 return pixels; 2752 } 2753 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 2754 format, type, pixels)) { 2755 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); 2756 return NULL; 2757 } 2758 2759 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2760 GL_READ_ONLY_ARB, unpack->BufferObj); 2761 if (!buf) { 2762 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); 2763 return NULL; 2764 } 2765 2766 return ADD_POINTERS(buf, pixels); 2767} 2768 2769 2770/** 2771 * Check if an unpack PBO is active prior to fetching a compressed texture 2772 * image. 2773 * If so, do bounds checking and map the buffer into main memory. 2774 * Any errors detected will be recorded. 2775 * The caller _must_ call _mesa_unmap_teximage_pbo() too! 2776 */ 2777const GLvoid * 2778_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, 2779 GLsizei imageSize, const GLvoid *pixels, 2780 const struct gl_pixelstore_attrib *packing, 2781 const char *funcName) 2782{ 2783 GLubyte *buf; 2784 2785 if (packing->BufferObj->Name == 0) { 2786 /* not using a PBO - return pointer unchanged */ 2787 return pixels; 2788 } 2789 if ((const GLubyte *) pixels + imageSize > 2790 ((const GLubyte *) 0) + packing->BufferObj->Size) { 2791 /* out of bounds read! */ 2792 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); 2793 return NULL; 2794 } 2795 2796 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2797 GL_READ_ONLY_ARB, packing->BufferObj); 2798 if (!buf) { 2799 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); 2800 return NULL; 2801 } 2802 2803 return ADD_POINTERS(buf, pixels); 2804} 2805 2806 2807/** 2808 * This function must be called after either of the validate_pbo_*_teximage() 2809 * functions. It unmaps the PBO buffer if it was mapped earlier. 2810 */ 2811void 2812_mesa_unmap_teximage_pbo(GLcontext *ctx, 2813 const struct gl_pixelstore_attrib *unpack) 2814{ 2815 if (unpack->BufferObj->Name) { 2816 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2817 unpack->BufferObj); 2818 } 2819} 2820 2821 2822 2823/** 2824 * Adaptor for fetching a GLchan texel from a float-valued texture. 2825 */ 2826static void 2827fetch_texel_float_to_chan(const struct gl_texture_image *texImage, 2828 GLint i, GLint j, GLint k, GLchan *texelOut) 2829{ 2830 GLfloat temp[4]; 2831 ASSERT(texImage->FetchTexelf); 2832 texImage->FetchTexelf(texImage, i, j, k, temp); 2833 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT || 2834 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { 2835 /* just one channel */ 2836 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); 2837 } 2838 else { 2839 /* four channels */ 2840 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); 2841 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]); 2842 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]); 2843 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]); 2844 } 2845} 2846 2847 2848/** 2849 * Adaptor for fetching a float texel from a GLchan-valued texture. 2850 */ 2851static void 2852fetch_texel_chan_to_float(const struct gl_texture_image *texImage, 2853 GLint i, GLint j, GLint k, GLfloat *texelOut) 2854{ 2855 GLchan temp[4]; 2856 ASSERT(texImage->FetchTexelc); 2857 texImage->FetchTexelc(texImage, i, j, k, temp); 2858 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT || 2859 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { 2860 /* just one channel */ 2861 texelOut[0] = CHAN_TO_FLOAT(temp[0]); 2862 } 2863 else { 2864 /* four channels */ 2865 texelOut[0] = CHAN_TO_FLOAT(temp[0]); 2866 texelOut[1] = CHAN_TO_FLOAT(temp[1]); 2867 texelOut[2] = CHAN_TO_FLOAT(temp[2]); 2868 texelOut[3] = CHAN_TO_FLOAT(temp[3]); 2869 } 2870} 2871 2872 2873/** 2874 * Initialize the texture image's FetchTexelc and FetchTexelf methods. 2875 */ 2876void 2877_mesa_set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) 2878{ 2879 ASSERT(dims == 1 || dims == 2 || dims == 3); 2880 ASSERT(texImage->TexFormat); 2881 2882 switch (dims) { 2883 case 1: 2884 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; 2885 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; 2886 break; 2887 case 2: 2888 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; 2889 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; 2890 break; 2891 case 3: 2892 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; 2893 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; 2894 break; 2895 default: 2896 ; 2897 } 2898 2899 /* now check if we need to use a float/chan adaptor */ 2900 if (!texImage->FetchTexelc) { 2901 texImage->FetchTexelc = fetch_texel_float_to_chan; 2902 } 2903 else if (!texImage->FetchTexelf) { 2904 texImage->FetchTexelf = fetch_texel_chan_to_float; 2905 } 2906 2907 2908 ASSERT(texImage->FetchTexelc); 2909 ASSERT(texImage->FetchTexelf); 2910} 2911 2912 2913/** 2914 * Choose the actual storage format for a new texture image. 2915 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function. 2916 * Also set some other texImage fields related to texture compression, etc. 2917 * \param ctx rendering context 2918 * \param texImage the gl_texture_image 2919 * \param dims texture dimensions (1, 2 or 3) 2920 * \param format the user-specified format parameter 2921 * \param type the user-specified type parameter 2922 * \param internalFormat the user-specified internal format hint 2923 */ 2924static void 2925choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage, 2926 GLuint dims, 2927 GLenum format, GLenum type, GLint internalFormat) 2928{ 2929 ASSERT(dims == 1 || dims == 2 || dims == 3); 2930 ASSERT(ctx->Driver.ChooseTextureFormat); 2931 2932 texImage->TexFormat 2933 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2934 2935 ASSERT(texImage->TexFormat); 2936 2937 _mesa_set_fetch_functions(texImage, dims); 2938 2939 if (texImage->TexFormat->TexelBytes == 0) { 2940 /* must be a compressed format */ 2941 texImage->IsCompressed = GL_TRUE; 2942 texImage->CompressedSize = 2943 ctx->Driver.CompressedTextureSize(ctx, texImage->Width, 2944 texImage->Height, texImage->Depth, 2945 texImage->TexFormat->MesaFormat); 2946 } 2947 else { 2948 /* non-compressed format */ 2949 texImage->IsCompressed = GL_FALSE; 2950 texImage->CompressedSize = 0; 2951 } 2952} 2953 2954 2955 2956/* 2957 * This is the software fallback for Driver.TexImage1D() 2958 * and Driver.CopyTexImage1D(). 2959 * \sa _mesa_store_teximage2d() 2960 */ 2961void 2962_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, 2963 GLint internalFormat, 2964 GLint width, GLint border, 2965 GLenum format, GLenum type, const GLvoid *pixels, 2966 const struct gl_pixelstore_attrib *packing, 2967 struct gl_texture_object *texObj, 2968 struct gl_texture_image *texImage) 2969{ 2970 GLint postConvWidth = width; 2971 GLint sizeInBytes; 2972 (void) border; 2973 2974 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { 2975 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2976 } 2977 2978 choose_texture_format(ctx, texImage, 1, format, type, internalFormat); 2979 2980 /* allocate memory */ 2981 if (texImage->IsCompressed) 2982 sizeInBytes = texImage->CompressedSize; 2983 else 2984 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes; 2985 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 2986 if (!texImage->Data) { 2987 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2988 return; 2989 } 2990 2991 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, 2992 pixels, packing, "glTexImage1D"); 2993 if (!pixels) { 2994 /* Note: we check for a NULL image pointer here, _after_ we allocated 2995 * memory for the texture. That's what the GL spec calls for. 2996 */ 2997 return; 2998 } 2999 else { 3000 const GLint dstRowStride = 0; 3001 GLboolean success; 3002 ASSERT(texImage->TexFormat->StoreImage); 3003 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat, 3004 texImage->TexFormat, 3005 texImage->Data, 3006 0, 0, 0, /* dstX/Y/Zoffset */ 3007 dstRowStride, 3008 texImage->ImageOffsets, 3009 width, 1, 1, 3010 format, type, pixels, packing); 3011 if (!success) { 3012 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 3013 } 3014 } 3015 3016 /* GL_SGIS_generate_mipmap */ 3017 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3018 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3019 } 3020 3021 _mesa_unmap_teximage_pbo(ctx, packing); 3022} 3023 3024 3025/** 3026 * This is the software fallback for Driver.TexImage2D() 3027 * and Driver.CopyTexImage2D(). 3028 * 3029 * This function is oriented toward storing images in main memory, rather 3030 * than VRAM. Device driver's can easily plug in their own replacement. 3031 * 3032 * Note: width and height may be pre-convolved dimensions, but 3033 * texImage->Width and texImage->Height will be post-convolved dimensions. 3034 */ 3035void 3036_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, 3037 GLint internalFormat, 3038 GLint width, GLint height, GLint border, 3039 GLenum format, GLenum type, const void *pixels, 3040 const struct gl_pixelstore_attrib *packing, 3041 struct gl_texture_object *texObj, 3042 struct gl_texture_image *texImage) 3043{ 3044 GLint postConvWidth = width, postConvHeight = height; 3045 GLint texelBytes, sizeInBytes; 3046 (void) border; 3047 3048 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { 3049 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 3050 &postConvHeight); 3051 } 3052 3053 choose_texture_format(ctx, texImage, 2, format, type, internalFormat); 3054 3055 texelBytes = texImage->TexFormat->TexelBytes; 3056 3057 /* allocate memory */ 3058 if (texImage->IsCompressed) 3059 sizeInBytes = texImage->CompressedSize; 3060 else 3061 sizeInBytes = postConvWidth * postConvHeight * texelBytes; 3062 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 3063 if (!texImage->Data) { 3064 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 3065 return; 3066 } 3067 3068 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, 3069 pixels, packing, "glTexImage2D"); 3070 if (!pixels) { 3071 /* Note: we check for a NULL image pointer here, _after_ we allocated 3072 * memory for the texture. That's what the GL spec calls for. 3073 */ 3074 return; 3075 } 3076 else { 3077 GLint dstRowStride; 3078 GLboolean success; 3079 if (texImage->IsCompressed) { 3080 dstRowStride 3081 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); 3082 } 3083 else { 3084 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 3085 } 3086 ASSERT(texImage->TexFormat->StoreImage); 3087 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, 3088 texImage->TexFormat, 3089 texImage->Data, 3090 0, 0, 0, /* dstX/Y/Zoffset */ 3091 dstRowStride, 3092 texImage->ImageOffsets, 3093 width, height, 1, 3094 format, type, pixels, packing); 3095 if (!success) { 3096 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 3097 } 3098 } 3099 3100 /* GL_SGIS_generate_mipmap */ 3101 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3102 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3103 } 3104 3105 _mesa_unmap_teximage_pbo(ctx, packing); 3106} 3107 3108 3109 3110/** 3111 * This is the software fallback for Driver.TexImage3D() 3112 * and Driver.CopyTexImage3D(). 3113 * \sa _mesa_store_teximage2d() 3114 */ 3115void 3116_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, 3117 GLint internalFormat, 3118 GLint width, GLint height, GLint depth, GLint border, 3119 GLenum format, GLenum type, const void *pixels, 3120 const struct gl_pixelstore_attrib *packing, 3121 struct gl_texture_object *texObj, 3122 struct gl_texture_image *texImage) 3123{ 3124 GLint texelBytes, sizeInBytes; 3125 (void) border; 3126 3127 choose_texture_format(ctx, texImage, 3, format, type, internalFormat); 3128 3129 texelBytes = texImage->TexFormat->TexelBytes; 3130 3131 /* allocate memory */ 3132 if (texImage->IsCompressed) 3133 sizeInBytes = texImage->CompressedSize; 3134 else 3135 sizeInBytes = width * height * depth * texelBytes; 3136 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 3137 if (!texImage->Data) { 3138 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 3139 return; 3140 } 3141 3142 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, 3143 type, pixels, packing, "glTexImage3D"); 3144 if (!pixels) { 3145 /* Note: we check for a NULL image pointer here, _after_ we allocated 3146 * memory for the texture. That's what the GL spec calls for. 3147 */ 3148 return; 3149 } 3150 else { 3151 GLint dstRowStride; 3152 GLboolean success; 3153 if (texImage->IsCompressed) { 3154 dstRowStride 3155 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); 3156 } 3157 else { 3158 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 3159 } 3160 ASSERT(texImage->TexFormat->StoreImage); 3161 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat, 3162 texImage->TexFormat, 3163 texImage->Data, 3164 0, 0, 0, /* dstX/Y/Zoffset */ 3165 dstRowStride, 3166 texImage->ImageOffsets, 3167 width, height, depth, 3168 format, type, pixels, packing); 3169 if (!success) { 3170 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 3171 } 3172 } 3173 3174 /* GL_SGIS_generate_mipmap */ 3175 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3176 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3177 } 3178 3179 _mesa_unmap_teximage_pbo(ctx, packing); 3180} 3181 3182 3183 3184 3185/* 3186 * This is the software fallback for Driver.TexSubImage1D() 3187 * and Driver.CopyTexSubImage1D(). 3188 */ 3189void 3190_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, 3191 GLint xoffset, GLint width, 3192 GLenum format, GLenum type, const void *pixels, 3193 const struct gl_pixelstore_attrib *packing, 3194 struct gl_texture_object *texObj, 3195 struct gl_texture_image *texImage) 3196{ 3197 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 3198 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, 3199 pixels, packing, "glTexSubImage1D"); 3200 if (!pixels) 3201 return; 3202 3203 { 3204 const GLint dstRowStride = 0; 3205 GLboolean success; 3206 ASSERT(texImage->TexFormat->StoreImage); 3207 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat, 3208 texImage->TexFormat, 3209 texImage->Data, 3210 xoffset, 0, 0, /* offsets */ 3211 dstRowStride, 3212 texImage->ImageOffsets, 3213 width, 1, 1, 3214 format, type, pixels, packing); 3215 if (!success) { 3216 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); 3217 } 3218 } 3219 3220 /* GL_SGIS_generate_mipmap */ 3221 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3222 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3223 } 3224 3225 _mesa_unmap_teximage_pbo(ctx, packing); 3226} 3227 3228 3229 3230/** 3231 * This is the software fallback for Driver.TexSubImage2D() 3232 * and Driver.CopyTexSubImage2D(). 3233 */ 3234void 3235_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, 3236 GLint xoffset, GLint yoffset, 3237 GLint width, GLint height, 3238 GLenum format, GLenum type, const void *pixels, 3239 const struct gl_pixelstore_attrib *packing, 3240 struct gl_texture_object *texObj, 3241 struct gl_texture_image *texImage) 3242{ 3243 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 3244 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, 3245 pixels, packing, "glTexSubImage2D"); 3246 if (!pixels) 3247 return; 3248 3249 { 3250 GLint dstRowStride = 0; 3251 GLboolean success; 3252 if (texImage->IsCompressed) { 3253 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, 3254 texImage->Width); 3255 } 3256 else { 3257 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 3258 } 3259 ASSERT(texImage->TexFormat->StoreImage); 3260 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, 3261 texImage->TexFormat, 3262 texImage->Data, 3263 xoffset, yoffset, 0, 3264 dstRowStride, 3265 texImage->ImageOffsets, 3266 width, height, 1, 3267 format, type, pixels, packing); 3268 if (!success) { 3269 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); 3270 } 3271 } 3272 3273 /* GL_SGIS_generate_mipmap */ 3274 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3275 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3276 } 3277 3278 _mesa_unmap_teximage_pbo(ctx, packing); 3279} 3280 3281 3282/* 3283 * This is the software fallback for Driver.TexSubImage3D(). 3284 * and Driver.CopyTexSubImage3D(). 3285 */ 3286void 3287_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, 3288 GLint xoffset, GLint yoffset, GLint zoffset, 3289 GLint width, GLint height, GLint depth, 3290 GLenum format, GLenum type, const void *pixels, 3291 const struct gl_pixelstore_attrib *packing, 3292 struct gl_texture_object *texObj, 3293 struct gl_texture_image *texImage) 3294{ 3295 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 3296 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, 3297 type, pixels, packing, 3298 "glTexSubImage3D"); 3299 if (!pixels) 3300 return; 3301 3302 { 3303 GLint dstRowStride; 3304 GLboolean success; 3305 if (texImage->IsCompressed) { 3306 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, 3307 texImage->Width); 3308 } 3309 else { 3310 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 3311 } 3312 ASSERT(texImage->TexFormat->StoreImage); 3313 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat, 3314 texImage->TexFormat, 3315 texImage->Data, 3316 xoffset, yoffset, zoffset, 3317 dstRowStride, 3318 texImage->ImageOffsets, 3319 width, height, depth, 3320 format, type, pixels, packing); 3321 if (!success) { 3322 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); 3323 } 3324 } 3325 3326 /* GL_SGIS_generate_mipmap */ 3327 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3328 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3329 } 3330 3331 _mesa_unmap_teximage_pbo(ctx, packing); 3332} 3333 3334 3335/* 3336 * Fallback for Driver.CompressedTexImage1D() 3337 */ 3338void 3339_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, 3340 GLint internalFormat, 3341 GLint width, GLint border, 3342 GLsizei imageSize, const GLvoid *data, 3343 struct gl_texture_object *texObj, 3344 struct gl_texture_image *texImage) 3345{ 3346 /* this space intentionally left blank */ 3347 (void) ctx; 3348 (void) target; (void) level; 3349 (void) internalFormat; 3350 (void) width; (void) border; 3351 (void) imageSize; (void) data; 3352 (void) texObj; 3353 (void) texImage; 3354} 3355 3356 3357 3358/** 3359 * Fallback for Driver.CompressedTexImage2D() 3360 */ 3361void 3362_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, 3363 GLint internalFormat, 3364 GLint width, GLint height, GLint border, 3365 GLsizei imageSize, const GLvoid *data, 3366 struct gl_texture_object *texObj, 3367 struct gl_texture_image *texImage) 3368{ 3369 (void) width; (void) height; (void) border; 3370 3371 /* This is pretty simple, basically just do a memcpy without worrying 3372 * about the usual image unpacking or image transfer operations. 3373 */ 3374 ASSERT(texObj); 3375 ASSERT(texImage); 3376 ASSERT(texImage->Width > 0); 3377 ASSERT(texImage->Height > 0); 3378 ASSERT(texImage->Depth == 1); 3379 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */ 3380 3381 choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat); 3382 3383 /* allocate storage */ 3384 texImage->Data = _mesa_alloc_texmemory(imageSize); 3385 if (!texImage->Data) { 3386 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); 3387 return; 3388 } 3389 3390 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, 3391 &ctx->Unpack, 3392 "glCompressedTexImage2D"); 3393 if (!data) 3394 return; 3395 3396 /* copy the data */ 3397 ASSERT(texImage->CompressedSize == (GLuint) imageSize); 3398 MEMCPY(texImage->Data, data, imageSize); 3399 3400 /* GL_SGIS_generate_mipmap */ 3401 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3402 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3403 } 3404 3405 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); 3406} 3407 3408 3409 3410/* 3411 * Fallback for Driver.CompressedTexImage3D() 3412 */ 3413void 3414_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, 3415 GLint internalFormat, 3416 GLint width, GLint height, GLint depth, 3417 GLint border, 3418 GLsizei imageSize, const GLvoid *data, 3419 struct gl_texture_object *texObj, 3420 struct gl_texture_image *texImage) 3421{ 3422 /* this space intentionally left blank */ 3423 (void) ctx; 3424 (void) target; (void) level; 3425 (void) internalFormat; 3426 (void) width; (void) height; (void) depth; 3427 (void) border; 3428 (void) imageSize; (void) data; 3429 (void) texObj; 3430 (void) texImage; 3431} 3432 3433 3434 3435/** 3436 * Fallback for Driver.CompressedTexSubImage1D() 3437 */ 3438void 3439_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, 3440 GLint level, 3441 GLint xoffset, GLsizei width, 3442 GLenum format, 3443 GLsizei imageSize, const GLvoid *data, 3444 struct gl_texture_object *texObj, 3445 struct gl_texture_image *texImage) 3446{ 3447 /* there are no compressed 1D texture formats yet */ 3448 (void) ctx; 3449 (void) target; (void) level; 3450 (void) xoffset; (void) width; 3451 (void) format; 3452 (void) imageSize; (void) data; 3453 (void) texObj; 3454 (void) texImage; 3455} 3456 3457 3458/** 3459 * Fallback for Driver.CompressedTexSubImage2D() 3460 */ 3461void 3462_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, 3463 GLint level, 3464 GLint xoffset, GLint yoffset, 3465 GLsizei width, GLsizei height, 3466 GLenum format, 3467 GLsizei imageSize, const GLvoid *data, 3468 struct gl_texture_object *texObj, 3469 struct gl_texture_image *texImage) 3470{ 3471 GLint bytesPerRow, destRowStride, srcRowStride; 3472 GLint i, rows; 3473 GLubyte *dest; 3474 const GLubyte *src; 3475 const GLuint mesaFormat = texImage->TexFormat->MesaFormat; 3476 3477 (void) format; 3478 3479 /* these should have been caught sooner */ 3480 ASSERT((width & 3) == 0 || width == 2 || width == 1); 3481 ASSERT((height & 3) == 0 || height == 2 || height == 1); 3482 ASSERT((xoffset & 3) == 0); 3483 ASSERT((yoffset & 3) == 0); 3484 3485 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 3486 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, 3487 &ctx->Unpack, 3488 "glCompressedTexSubImage2D"); 3489 if (!data) 3490 return; 3491 3492 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width); 3493 src = (const GLubyte *) data; 3494 3495 destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width); 3496 dest = _mesa_compressed_image_address(xoffset, yoffset, 0, 3497 texImage->TexFormat->MesaFormat, 3498 texImage->Width, 3499 (GLubyte *) texImage->Data); 3500 3501 bytesPerRow = srcRowStride; 3502 rows = height / 4; 3503 3504 for (i = 0; i < rows; i++) { 3505 MEMCPY(dest, src, bytesPerRow); 3506 dest += destRowStride; 3507 src += srcRowStride; 3508 } 3509 3510 /* GL_SGIS_generate_mipmap */ 3511 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3512 ctx->Driver.GenerateMipmap(ctx, target, texObj); 3513 } 3514 3515 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); 3516} 3517 3518 3519/** 3520 * Fallback for Driver.CompressedTexSubImage3D() 3521 */ 3522void 3523_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, 3524 GLint level, 3525 GLint xoffset, GLint yoffset, GLint zoffset, 3526 GLsizei width, GLsizei height, GLsizei depth, 3527 GLenum format, 3528 GLsizei imageSize, const GLvoid *data, 3529 struct gl_texture_object *texObj, 3530 struct gl_texture_image *texImage) 3531{ 3532 /* there are no compressed 3D texture formats yet */ 3533 (void) ctx; 3534 (void) target; (void) level; 3535 (void) xoffset; (void) yoffset; (void) zoffset; 3536 (void) width; (void) height; (void) depth; 3537 (void) format; 3538 (void) imageSize; (void) data; 3539 (void) texObj; 3540 (void) texImage; 3541} 3542 3543 3544 3545 3546#if FEATURE_EXT_texture_sRGB 3547 3548/** 3549 * Test if given texture image is an sRGB format. 3550 */ 3551static GLboolean 3552is_srgb_teximage(const struct gl_texture_image *texImage) 3553{ 3554 switch (texImage->TexFormat->MesaFormat) { 3555 case MESA_FORMAT_SRGB8: 3556 case MESA_FORMAT_SRGBA8: 3557 case MESA_FORMAT_SL8: 3558 case MESA_FORMAT_SLA8: 3559 return GL_TRUE; 3560 default: 3561 return GL_FALSE; 3562 } 3563} 3564 3565#endif /* FEATURE_EXT_texture_sRGB */ 3566 3567 3568/** 3569 * This is the software fallback for Driver.GetTexImage(). 3570 * All error checking will have been done before this routine is called. 3571 */ 3572void 3573_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, 3574 GLenum format, GLenum type, GLvoid *pixels, 3575 struct gl_texture_object *texObj, 3576 struct gl_texture_image *texImage) 3577{ 3578 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 3579 3580 if (ctx->Pack.BufferObj->Name) { 3581 /* Packing texture image into a PBO. 3582 * Map the (potentially) VRAM-based buffer into our process space so 3583 * we can write into it with the code below. 3584 * A hardware driver might use a sophisticated blit to move the 3585 * texture data to the PBO if the PBO is in VRAM along with the texture. 3586 */ 3587 GLubyte *buf = (GLubyte *) 3588 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 3589 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 3590 if (!buf) { 3591 /* buffer is already mapped - that's an error */ 3592 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)"); 3593 return; 3594 } 3595 /* <pixels> was an offset into the PBO. 3596 * Now make it a real, client-side pointer inside the mapped region. 3597 */ 3598 pixels = ADD_POINTERS(buf, pixels); 3599 } 3600 else if (!pixels) { 3601 /* not an error */ 3602 return; 3603 } 3604 3605 { 3606 const GLint width = texImage->Width; 3607 const GLint height = texImage->Height; 3608 const GLint depth = texImage->Depth; 3609 GLint img, row; 3610 for (img = 0; img < depth; img++) { 3611 for (row = 0; row < height; row++) { 3612 /* compute destination address in client memory */ 3613 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels, 3614 width, height, format, type, 3615 img, row, 0); 3616 assert(dest); 3617 3618 if (format == GL_COLOR_INDEX) { 3619 GLuint indexRow[MAX_WIDTH]; 3620 GLint col; 3621 /* Can't use FetchTexel here because that returns RGBA */ 3622 if (texImage->TexFormat->IndexBits == 8) { 3623 const GLubyte *src = (const GLubyte *) texImage->Data; 3624 src += width * (img * texImage->Height + row); 3625 for (col = 0; col < width; col++) { 3626 indexRow[col] = src[col]; 3627 } 3628 } 3629 else if (texImage->TexFormat->IndexBits == 16) { 3630 const GLushort *src = (const GLushort *) texImage->Data; 3631 src += width * (img * texImage->Height + row); 3632 for (col = 0; col < width; col++) { 3633 indexRow[col] = src[col]; 3634 } 3635 } 3636 else { 3637 _mesa_problem(ctx, 3638 "Color index problem in _mesa_GetTexImage"); 3639 } 3640 _mesa_pack_index_span(ctx, width, type, dest, 3641 indexRow, &ctx->Pack, 3642 0 /* no image transfer */); 3643 } 3644 else if (format == GL_DEPTH_COMPONENT) { 3645 GLfloat depthRow[MAX_WIDTH]; 3646 GLint col; 3647 for (col = 0; col < width; col++) { 3648 (*texImage->FetchTexelf)(texImage, col, row, img, 3649 depthRow + col); 3650 } 3651 _mesa_pack_depth_span(ctx, width, dest, type, 3652 depthRow, &ctx->Pack); 3653 } 3654 else if (format == GL_DEPTH_STENCIL_EXT) { 3655 /* XXX Note: we're bypassing texImage->FetchTexel()! */ 3656 const GLuint *src = (const GLuint *) texImage->Data; 3657 src += width * row + width * height * img; 3658 _mesa_memcpy(dest, src, width * sizeof(GLuint)); 3659 if (ctx->Pack.SwapBytes) { 3660 _mesa_swap4((GLuint *) dest, width); 3661 } 3662 } 3663 else if (format == GL_YCBCR_MESA) { 3664 /* No pixel transfer */ 3665 const GLint rowstride = texImage->RowStride; 3666 MEMCPY(dest, 3667 (const GLushort *) texImage->Data + row * rowstride, 3668 width * sizeof(GLushort)); 3669 /* check for byte swapping */ 3670 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR 3671 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 3672 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV 3673 && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 3674 if (!ctx->Pack.SwapBytes) 3675 _mesa_swap2((GLushort *) dest, width); 3676 } 3677 else if (ctx->Pack.SwapBytes) { 3678 _mesa_swap2((GLushort *) dest, width); 3679 } 3680 } 3681#if FEATURE_EXT_texture_sRGB 3682 else if (is_srgb_teximage(texImage)) { 3683 /* no pixel transfer and no non-linear to linear conversion */ 3684 const GLint comps = texImage->TexFormat->TexelBytes; 3685 const GLint rowstride = comps * texImage->RowStride; 3686 MEMCPY(dest, 3687 (const GLubyte *) texImage->Data + row * rowstride, 3688 comps * width * sizeof(GLubyte)); 3689 } 3690#endif /* FEATURE_EXT_texture_sRGB */ 3691 else { 3692 /* general case: convert row to RGBA format */ 3693 GLfloat rgba[MAX_WIDTH][4]; 3694 GLint col; 3695 for (col = 0; col < width; col++) { 3696 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); 3697 if (texImage->TexFormat->BaseFormat == GL_ALPHA) { 3698 rgba[col][RCOMP] = 0.0; 3699 rgba[col][GCOMP] = 0.0; 3700 rgba[col][BCOMP] = 0.0; 3701 } 3702 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE) { 3703 rgba[col][GCOMP] = 0.0; 3704 rgba[col][BCOMP] = 0.0; 3705 rgba[col][ACOMP] = 1.0; 3706 } 3707 else if (texImage->TexFormat->BaseFormat == GL_LUMINANCE_ALPHA) { 3708 rgba[col][GCOMP] = 0.0; 3709 rgba[col][BCOMP] = 0.0; 3710 } 3711 else if (texImage->TexFormat->BaseFormat == GL_INTENSITY) { 3712 rgba[col][GCOMP] = 0.0; 3713 rgba[col][BCOMP] = 0.0; 3714 rgba[col][ACOMP] = 1.0; 3715 } 3716 } 3717 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 3718 format, type, dest, 3719 &ctx->Pack, 0x0 /*image xfer ops*/); 3720 } /* format */ 3721 } /* row */ 3722 } /* img */ 3723 } 3724 3725 if (ctx->Pack.BufferObj->Name) { 3726 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 3727 ctx->Pack.BufferObj); 3728 } 3729} 3730 3731 3732 3733/** 3734 * This is the software fallback for Driver.GetCompressedTexImage(). 3735 * All error checking will have been done before this routine is called. 3736 */ 3737void 3738_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, 3739 GLvoid *img, 3740 const struct gl_texture_object *texObj, 3741 const struct gl_texture_image *texImage) 3742{ 3743 GLuint size; 3744 3745 if (ctx->Pack.BufferObj->Name) { 3746 /* pack texture image into a PBO */ 3747 GLubyte *buf; 3748 if ((const GLubyte *) img + texImage->CompressedSize > 3749 (const GLubyte *) ctx->Pack.BufferObj->Size) { 3750 _mesa_error(ctx, GL_INVALID_OPERATION, 3751 "glGetCompressedTexImage(invalid PBO access)"); 3752 return; 3753 } 3754 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 3755 GL_WRITE_ONLY_ARB, 3756 ctx->Pack.BufferObj); 3757 if (!buf) { 3758 /* buffer is already mapped - that's an error */ 3759 _mesa_error(ctx, GL_INVALID_OPERATION, 3760 "glGetCompressedTexImage(PBO is mapped)"); 3761 return; 3762 } 3763 img = ADD_POINTERS(buf, img); 3764 } 3765 else if (!img) { 3766 /* not an error */ 3767 return; 3768 } 3769 3770 /* don't use texImage->CompressedSize since that may be padded out */ 3771 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height, 3772 texImage->Depth, 3773 texImage->TexFormat->MesaFormat); 3774 3775 /* just memcpy, no pixelstore or pixel transfer */ 3776 _mesa_memcpy(img, texImage->Data, size); 3777 3778 if (ctx->Pack.BufferObj->Name) { 3779 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 3780 ctx->Pack.BufferObj); 3781 } 3782} 3783