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