texstore.c revision 2e2a9813355993ba79eeb8070391e45aabb84f94
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.1 4 * 5 * Copyright (C) 1999-2006 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 textureBaseFormat"); 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 GLuint 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, 615 const GLuint *dstImageOffsets, 616 617 GLint srcWidth, GLint srcHeight, GLint srcDepth, 618 const GLvoid *srcAddr, 619 const struct gl_pixelstore_attrib *srcPacking ) 620{ 621 GLint srcComponents = _mesa_components_in_format(srcFormat); 622 GLubyte srcmap[6], map[4]; 623 GLint i; 624 625 const GLint srcRowStride = 626 _mesa_image_row_stride(srcPacking, srcWidth, 627 srcFormat, GL_UNSIGNED_BYTE); 628 const GLint srcImageStride 629 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat, 630 GL_UNSIGNED_BYTE); 631 const GLubyte *srcImage 632 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr, 633 srcWidth, srcHeight, srcFormat, 634 GL_UNSIGNED_BYTE, 0, 0, 0); 635 636 (void) ctx; 637 638 compute_component_mapping(srcFormat, GL_RGBA, srcmap); 639 640 for (i = 0; i < 4; i++) 641 map[i] = srcmap[dstmap[i]]; 642 643 if (srcRowStride == srcWidth * srcComponents && 644 dimensions < 3) { 645 /* 1 and 2D images only */ 646 GLubyte *dstImage = (GLubyte *) dstAddr 647 + dstYoffset * dstRowStride 648 + dstXoffset * dstComponents; 649 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map, 650 srcWidth * srcHeight); 651 } 652 else { 653 GLint img, row; 654 for (img = 0; img < srcDepth; img++) { 655 const GLubyte *srcRow = srcImage; 656 GLubyte *dstRow = (GLubyte *) dstAddr 657 + dstImageOffsets[dstZoffset + img] * dstComponents 658 + dstYoffset * dstRowStride 659 + dstXoffset * dstComponents; 660 for (row = 0; row < srcHeight; row++) { 661 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth); 662 dstRow += dstRowStride; 663 srcRow += srcRowStride; 664 } 665 srcImage += srcImageStride; 666 } 667 } 668} 669 670 671/** 672 * Teximage storage routine for when a simple memcpy will do. 673 * No pixel transfer operations or special texel encodings allowed. 674 * 1D, 2D and 3D images supported. 675 */ 676static void 677memcpy_texture(GLcontext *ctx, 678 GLuint dimensions, 679 const struct gl_texture_format *dstFormat, 680 GLvoid *dstAddr, 681 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset, 682 GLint dstRowStride, 683 const GLuint *dstImageOffsets, 684 GLint srcWidth, GLint srcHeight, GLint srcDepth, 685 GLenum srcFormat, GLenum srcType, 686 const GLvoid *srcAddr, 687 const struct gl_pixelstore_attrib *srcPacking) 688{ 689 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, 690 srcFormat, srcType); 691 const GLint srcImageStride = _mesa_image_image_stride(srcPacking, 692 srcWidth, srcHeight, srcFormat, srcType); 693 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions, 694 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0); 695 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes; 696 697#if 0 698 /* XXX update/re-enable for dstImageOffsets array */ 699 const GLint bytesPerImage = srcHeight * bytesPerRow; 700 const GLint bytesPerTexture = srcDepth * bytesPerImage; 701 GLubyte *dstImage = (GLubyte *) dstAddr 702 + dstZoffset * dstImageStride 703 + dstYoffset * dstRowStride 704 + dstXoffset * dstFormat->TexelBytes; 705 706 if (dstRowStride == srcRowStride && 707 dstRowStride == bytesPerRow && 708 ((dstImageStride == srcImageStride && 709 dstImageStride == bytesPerImage) || 710 (srcDepth == 1))) { 711 /* one big memcpy */ 712 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture); 713 } 714 else 715 { 716 GLint img, row; 717 for (img = 0; img < srcDepth; img++) { 718 const GLubyte *srcRow = srcImage; 719 GLubyte *dstRow = dstImage; 720 for (row = 0; row < srcHeight; row++) { 721 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow); 722 dstRow += dstRowStride; 723 srcRow += srcRowStride; 724 } 725 srcImage += srcImageStride; 726 dstImage += dstImageStride; 727 } 728 } 729#endif 730 731 GLint img, row; 732 for (img = 0; img < srcDepth; img++) { 733 const GLubyte *srcRow = srcImage; 734 GLubyte *dstRow = (GLubyte *) dstAddr 735 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 736 + dstYoffset * dstRowStride 737 + dstXoffset * dstFormat->TexelBytes; 738 for (row = 0; row < srcHeight; row++) { 739 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow); 740 dstRow += dstRowStride; 741 srcRow += srcRowStride; 742 } 743 srcImage += srcImageStride; 744 } 745} 746 747 748 749/** 750 * Store an image in any of the formats: 751 * _mesa_texformat_rgba 752 * _mesa_texformat_rgb 753 * _mesa_texformat_alpha 754 * _mesa_texformat_luminance 755 * _mesa_texformat_luminance_alpha 756 * _mesa_texformat_intensity 757 * 758 */ 759GLboolean 760_mesa_texstore_rgba(TEXSTORE_PARAMS) 761{ 762 const GLint components = _mesa_components_in_format(baseInternalFormat); 763 764 ASSERT(dstFormat == &_mesa_texformat_rgba || 765 dstFormat == &_mesa_texformat_rgb || 766 dstFormat == &_mesa_texformat_alpha || 767 dstFormat == &_mesa_texformat_luminance || 768 dstFormat == &_mesa_texformat_luminance_alpha || 769 dstFormat == &_mesa_texformat_intensity); 770 ASSERT(baseInternalFormat == GL_RGBA || 771 baseInternalFormat == GL_RGB || 772 baseInternalFormat == GL_ALPHA || 773 baseInternalFormat == GL_LUMINANCE || 774 baseInternalFormat == GL_LUMINANCE_ALPHA || 775 baseInternalFormat == GL_INTENSITY); 776 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan)); 777 778 if (!ctx->_ImageTransferState && 779 !srcPacking->SwapBytes && 780 baseInternalFormat == srcFormat && 781 srcType == CHAN_TYPE) { 782 /* simple memcpy path */ 783 memcpy_texture(ctx, dims, 784 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 785 dstRowStride, 786 dstImageOffsets, 787 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 788 srcAddr, srcPacking); 789 } 790 else if (!ctx->_ImageTransferState && 791 !srcPacking->SwapBytes && 792 dstFormat == &_mesa_texformat_rgb && 793 srcFormat == GL_RGBA && 794 srcType == CHAN_TYPE) { 795 /* extract RGB from RGBA */ 796 GLint img, row, col; 797 for (img = 0; img < srcDepth; img++) { 798 GLchan *dstImage = (GLchan *) 799 ((GLubyte *) dstAddr 800 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 801 + dstYoffset * dstRowStride 802 + dstXoffset * dstFormat->TexelBytes); 803 804 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 805 srcWidth, srcFormat, srcType); 806 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking, 807 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 808 GLchan *dstRow = dstImage; 809 for (row = 0; row < srcHeight; row++) { 810 for (col = 0; col < srcWidth; col++) { 811 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP]; 812 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP]; 813 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP]; 814 } 815 dstRow += dstRowStride / sizeof(GLchan); 816 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride); 817 } 818 } 819 } 820 else { 821 /* general path */ 822 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 823 baseInternalFormat, 824 dstFormat->BaseFormat, 825 srcWidth, srcHeight, srcDepth, 826 srcFormat, srcType, srcAddr, 827 srcPacking); 828 const GLchan *src = tempImage; 829 GLint bytesPerRow; 830 GLint img, row; 831 if (!tempImage) 832 return GL_FALSE; 833 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 834 bytesPerRow = srcWidth * components * sizeof(GLchan); 835 for (img = 0; img < srcDepth; img++) { 836 GLubyte *dstRow = (GLubyte *) dstAddr 837 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 838 + dstYoffset * dstRowStride 839 + dstXoffset * dstFormat->TexelBytes; 840 for (row = 0; row < srcHeight; row++) { 841 _mesa_memcpy(dstRow, src, bytesPerRow); 842 dstRow += dstRowStride; 843 src += srcWidth * components; 844 } 845 } 846 847 _mesa_free((void *) tempImage); 848 } 849 return GL_TRUE; 850} 851 852 853/** 854 * Store a 32-bit integer depth component texture image. 855 */ 856GLboolean 857_mesa_texstore_z32(TEXSTORE_PARAMS) 858{ 859 const GLfloat depthScale = (GLfloat) 0xffffffff; 860 (void) dims; 861 ASSERT(dstFormat == &_mesa_texformat_z32); 862 ASSERT(dstFormat->TexelBytes == sizeof(GLuint)); 863 864 if (!ctx->_ImageTransferState && 865 !srcPacking->SwapBytes && 866 baseInternalFormat == GL_DEPTH_COMPONENT && 867 srcFormat == GL_DEPTH_COMPONENT && 868 srcType == GL_UNSIGNED_INT) { 869 /* simple memcpy path */ 870 memcpy_texture(ctx, dims, 871 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 872 dstRowStride, 873 dstImageOffsets, 874 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 875 srcAddr, srcPacking); 876 } 877 else { 878 /* general path */ 879 GLint img, row; 880 for (img = 0; img < srcDepth; img++) { 881 GLubyte *dstRow = (GLubyte *) dstAddr 882 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 883 + dstYoffset * dstRowStride 884 + dstXoffset * dstFormat->TexelBytes; 885 for (row = 0; row < srcHeight; row++) { 886 const GLvoid *src = _mesa_image_address(dims, srcPacking, 887 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 888 _mesa_unpack_depth_span(ctx, srcWidth, 889 GL_UNSIGNED_INT, (GLuint *) dstRow, 890 depthScale, srcType, src, srcPacking); 891 dstRow += dstRowStride; 892 } 893 } 894 } 895 return GL_TRUE; 896} 897 898#define STRIDE_3D 0 899 900/** 901 * Store a 16-bit integer depth component texture image. 902 */ 903GLboolean 904_mesa_texstore_z16(TEXSTORE_PARAMS) 905{ 906 const GLfloat depthScale = 65535.0f; 907 (void) dims; 908 ASSERT(dstFormat == &_mesa_texformat_z16); 909 ASSERT(dstFormat->TexelBytes == sizeof(GLushort)); 910 911 if (!ctx->_ImageTransferState && 912 !srcPacking->SwapBytes && 913 baseInternalFormat == GL_DEPTH_COMPONENT && 914 srcFormat == GL_DEPTH_COMPONENT && 915 srcType == GL_UNSIGNED_SHORT) { 916 /* simple memcpy path */ 917 memcpy_texture(ctx, dims, 918 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 919 dstRowStride, 920 dstImageOffsets, 921 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 922 srcAddr, srcPacking); 923 } 924 else { 925 /* general path */ 926 GLint img, row; 927 for (img = 0; img < srcDepth; img++) { 928 GLubyte *dstRow = (GLubyte *) dstAddr 929 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 930 + dstYoffset * dstRowStride 931 + dstXoffset * dstFormat->TexelBytes; 932 for (row = 0; row < srcHeight; row++) { 933 const GLvoid *src = _mesa_image_address(dims, srcPacking, 934 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 935 GLushort *dst16 = (GLushort *) dstRow; 936 _mesa_unpack_depth_span(ctx, srcWidth, 937 GL_UNSIGNED_SHORT, dst16, depthScale, 938 srcType, src, srcPacking); 939 dstRow += dstRowStride; 940 } 941 } 942 } 943 return GL_TRUE; 944} 945 946 947/** 948 * Store an rgb565 or rgb565_rev texture image. 949 */ 950GLboolean 951_mesa_texstore_rgb565(TEXSTORE_PARAMS) 952{ 953 ASSERT(dstFormat == &_mesa_texformat_rgb565 || 954 dstFormat == &_mesa_texformat_rgb565_rev); 955 ASSERT(dstFormat->TexelBytes == 2); 956 957 if (!ctx->_ImageTransferState && 958 !srcPacking->SwapBytes && 959 dstFormat == &_mesa_texformat_rgb565 && 960 baseInternalFormat == GL_RGB && 961 srcFormat == GL_RGB && 962 srcType == GL_UNSIGNED_SHORT_5_6_5) { 963 /* simple memcpy path */ 964 memcpy_texture(ctx, dims, 965 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 966 dstRowStride, 967 dstImageOffsets, 968 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 969 srcAddr, srcPacking); 970 } 971 else if (!ctx->_ImageTransferState && 972 !srcPacking->SwapBytes && 973 baseInternalFormat == GL_RGB && 974 srcFormat == GL_RGB && 975 srcType == GL_UNSIGNED_BYTE && 976 dims == 2) { 977 /* do optimized tex store */ 978 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth, 979 srcFormat, srcType); 980 const GLubyte *src = (const GLubyte *) 981 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight, 982 srcFormat, srcType, 0, 0, 0); 983 GLubyte *dst = (GLubyte *) dstAddr 984 + dstYoffset * dstRowStride 985 + dstXoffset * dstFormat->TexelBytes; 986 GLint row, col; 987 for (row = 0; row < srcHeight; row++) { 988 const GLubyte *srcUB = (const GLubyte *) src; 989 GLushort *dstUS = (GLushort *) dst; 990 /* check for byteswapped format */ 991 if (dstFormat == &_mesa_texformat_rgb565) { 992 for (col = 0; col < srcWidth; col++) { 993 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] ); 994 srcUB += 3; 995 } 996 } 997 else { 998 for (col = 0; col < srcWidth; col++) { 999 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] ); 1000 srcUB += 3; 1001 } 1002 } 1003 dst += dstRowStride; 1004 src += srcRowStride; 1005 } 1006 } 1007 else { 1008 /* general path */ 1009 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1010 baseInternalFormat, 1011 dstFormat->BaseFormat, 1012 srcWidth, srcHeight, srcDepth, 1013 srcFormat, srcType, srcAddr, 1014 srcPacking); 1015 const GLchan *src = tempImage; 1016 GLint img, row, col; 1017 if (!tempImage) 1018 return GL_FALSE; 1019 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1020 for (img = 0; img < srcDepth; img++) { 1021 GLubyte *dstRow = (GLubyte *) dstAddr 1022 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1023 + dstYoffset * dstRowStride 1024 + dstXoffset * dstFormat->TexelBytes; 1025 for (row = 0; row < srcHeight; row++) { 1026 GLushort *dstUS = (GLushort *) dstRow; 1027 /* check for byteswapped format */ 1028 if (dstFormat == &_mesa_texformat_rgb565) { 1029 for (col = 0; col < srcWidth; col++) { 1030 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]), 1031 CHAN_TO_UBYTE(src[GCOMP]), 1032 CHAN_TO_UBYTE(src[BCOMP]) ); 1033 src += 3; 1034 } 1035 } 1036 else { 1037 for (col = 0; col < srcWidth; col++) { 1038 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]), 1039 CHAN_TO_UBYTE(src[GCOMP]), 1040 CHAN_TO_UBYTE(src[BCOMP]) ); 1041 src += 3; 1042 } 1043 } 1044 dstRow += dstRowStride; 1045 } 1046 } 1047 _mesa_free((void *) tempImage); 1048 } 1049 return GL_TRUE; 1050} 1051 1052 1053GLboolean 1054_mesa_texstore_rgba8888(TEXSTORE_PARAMS) 1055{ 1056 const GLuint ui = 1; 1057 const GLubyte littleEndian = *((const GLubyte *) &ui); 1058 1059 (void)littleEndian; 1060 ASSERT(dstFormat == &_mesa_texformat_rgba8888 || 1061 dstFormat == &_mesa_texformat_rgba8888_rev); 1062 ASSERT(dstFormat->TexelBytes == 4); 1063 1064 if (!ctx->_ImageTransferState && 1065 !srcPacking->SwapBytes && 1066 dstFormat == &_mesa_texformat_rgba8888 && 1067 baseInternalFormat == GL_RGBA && 1068 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) || 1069 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && !littleEndian) || 1070 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || 1071 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && littleEndian))) { 1072 /* simple memcpy path */ 1073 memcpy_texture(ctx, dims, 1074 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1075 dstRowStride, 1076 dstImageOffsets, 1077 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1078 srcAddr, srcPacking); 1079 } 1080 else if (!ctx->_ImageTransferState && 1081 !srcPacking->SwapBytes && 1082 dstFormat == &_mesa_texformat_rgba8888_rev && 1083 baseInternalFormat == GL_RGBA && 1084 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV) || 1085 (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE && littleEndian) || 1086 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8) || 1087 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_BYTE && !littleEndian))) { 1088 /* simple memcpy path */ 1089 memcpy_texture(ctx, dims, 1090 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1091 dstRowStride, 1092 dstImageOffsets, 1093 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1094 srcAddr, srcPacking); 1095 } 1096#if 0 1097 /* broken? */ 1098 else if (!ctx->_ImageTransferState && 1099 !srcPacking->SwapBytes && 1100 srcType == GL_UNSIGNED_BYTE && 1101 dstFormat == &_mesa_texformat_rgba8888 && 1102 littleEndian && 1103 /* Three texture formats involved: srcFormat, 1104 * baseInternalFormat and destFormat (GL_RGBA). Only two 1105 * may differ. _mesa_swizzle_ubyte_image can't handle two 1106 * propagations at once correctly. */ 1107 (srcFormat == baseInternalFormat || 1108 baseInternalFormat == GL_RGBA) && 1109 can_swizzle(srcFormat)) { 1110 GLubyte dstmap[4]; 1111 1112 /* dstmap - how to swizzle from GL_RGBA to dst format: 1113 * 1114 * FIXME - add !litteEndian and _rev varients: 1115 */ 1116 dstmap[3] = 0; 1117 dstmap[2] = 1; 1118 dstmap[1] = 2; 1119 dstmap[0] = 3; 1120 1121 _mesa_swizzle_ubyte_image(ctx, dims, 1122 srcFormat, 1123 dstmap, 4, 1124 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1125 dstRowStride, dstImageStride, 1126 srcWidth, srcHeight, srcDepth, srcAddr, 1127 srcPacking); 1128 } 1129#endif 1130 else { 1131 /* general path */ 1132 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1133 baseInternalFormat, 1134 dstFormat->BaseFormat, 1135 srcWidth, srcHeight, srcDepth, 1136 srcFormat, srcType, srcAddr, 1137 srcPacking); 1138 const GLchan *src = tempImage; 1139 GLint img, row, col; 1140 if (!tempImage) 1141 return GL_FALSE; 1142 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1143 for (img = 0; img < srcDepth; img++) { 1144 GLubyte *dstRow = (GLubyte *) dstAddr 1145 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1146 + dstYoffset * dstRowStride 1147 + dstXoffset * dstFormat->TexelBytes; 1148 for (row = 0; row < srcHeight; row++) { 1149 GLuint *dstUI = (GLuint *) dstRow; 1150 if (dstFormat == &_mesa_texformat_rgba8888) { 1151 for (col = 0; col < srcWidth; col++) { 1152 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]), 1153 CHAN_TO_UBYTE(src[GCOMP]), 1154 CHAN_TO_UBYTE(src[BCOMP]), 1155 CHAN_TO_UBYTE(src[ACOMP]) ); 1156 src += 4; 1157 } 1158 } 1159 else { 1160 for (col = 0; col < srcWidth; col++) { 1161 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]), 1162 CHAN_TO_UBYTE(src[GCOMP]), 1163 CHAN_TO_UBYTE(src[BCOMP]), 1164 CHAN_TO_UBYTE(src[ACOMP]) ); 1165 src += 4; 1166 } 1167 } 1168 dstRow += dstRowStride; 1169 } 1170 } 1171 _mesa_free((void *) tempImage); 1172 } 1173 return GL_TRUE; 1174} 1175 1176 1177GLboolean 1178_mesa_texstore_argb8888(TEXSTORE_PARAMS) 1179{ 1180 const GLuint ui = 1; 1181 const GLubyte littleEndian = *((const GLubyte *) &ui); 1182 1183 ASSERT(dstFormat == &_mesa_texformat_argb8888 || 1184 dstFormat == &_mesa_texformat_argb8888_rev); 1185 ASSERT(dstFormat->TexelBytes == 4); 1186 1187 if (!ctx->_ImageTransferState && 1188 !srcPacking->SwapBytes && 1189 dstFormat == &_mesa_texformat_argb8888 && 1190 baseInternalFormat == GL_RGBA && 1191 srcFormat == GL_BGRA && 1192 ((srcType == GL_UNSIGNED_BYTE && littleEndian) || 1193 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) { 1194 /* simple memcpy path (little endian) */ 1195 memcpy_texture(ctx, dims, 1196 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1197 dstRowStride, 1198 dstImageOffsets, 1199 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1200 srcAddr, srcPacking); 1201 } 1202 else if (!ctx->_ImageTransferState && 1203 !srcPacking->SwapBytes && 1204 dstFormat == &_mesa_texformat_argb8888_rev && 1205 baseInternalFormat == GL_RGBA && 1206 srcFormat == GL_BGRA && 1207 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) || 1208 srcType == GL_UNSIGNED_INT_8_8_8_8)) { 1209 /* simple memcpy path (big endian) */ 1210 memcpy_texture(ctx, dims, 1211 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1212 dstRowStride, 1213 dstImageOffsets, 1214 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1215 srcAddr, srcPacking); 1216 } 1217 else if (!ctx->_ImageTransferState && 1218 !srcPacking->SwapBytes && 1219 dstFormat == &_mesa_texformat_argb8888 && 1220 srcFormat == GL_RGB && 1221 srcType == GL_UNSIGNED_BYTE) { 1222 1223 int img, row, col; 1224 for (img = 0; img < srcDepth; img++) { 1225 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1226 srcWidth, srcFormat, srcType); 1227 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1228 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1229 GLubyte *dstRow = (GLubyte *) dstAddr 1230 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1231 + dstYoffset * dstRowStride 1232 + dstXoffset * dstFormat->TexelBytes; 1233 for (row = 0; row < srcHeight; row++) { 1234 for (col = 0; col < srcWidth; col++) { 1235 dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP]; 1236 dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP]; 1237 dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP]; 1238 dstRow[col * 4 + 3] = 0xff; 1239 } 1240 dstRow += dstRowStride; 1241 srcRow += srcRowStride; 1242 } 1243 } 1244 } 1245 else if (!ctx->_ImageTransferState && 1246 !srcPacking->SwapBytes && 1247 dstFormat == &_mesa_texformat_argb8888 && 1248 srcFormat == GL_RGBA && 1249 (srcType == GL_UNSIGNED_BYTE && littleEndian)) { 1250 GLint img, row, col; 1251 /* For some reason, streaming copies to write-combined regions 1252 * are extremely sensitive to the characteristics of how the 1253 * source data is retrieved. By reordering the source reads to 1254 * be in-order, the speed of this operation increases by half. 1255 * Strangely the same isn't required for the RGB path, above. 1256 */ 1257 for (img = 0; img < srcDepth; img++) { 1258 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1259 srcWidth, srcFormat, srcType); 1260 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1261 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1262 GLubyte *dstRow = (GLubyte *) dstAddr 1263 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1264 + dstYoffset * dstRowStride 1265 + dstXoffset * dstFormat->TexelBytes; 1266 1267 for (row = 0; row < srcHeight; row++) { 1268 for (col = 0; col < srcWidth; col++) { 1269 *(GLuint *)(dstRow + col * 4) = (srcRow[col * 4 + RCOMP] << 16 | 1270 srcRow[col * 4 + GCOMP] << 8 | 1271 srcRow[col * 4 + BCOMP] << 0 | 1272 srcRow[col * 4 + ACOMP] << 24); 1273 } 1274 dstRow += dstRowStride; 1275 srcRow += srcRowStride; 1276 } 1277 } 1278 } 1279 else if (!ctx->_ImageTransferState && 1280 !srcPacking->SwapBytes && 1281 dstFormat == &_mesa_texformat_argb8888 && 1282 srcFormat == GL_RGBA && 1283 srcType == GL_UNSIGNED_BYTE) { 1284 1285 GLint img, row, col; 1286 for (img = 0; img < srcDepth; img++) { 1287 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1288 srcWidth, srcFormat, srcType); 1289 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1290 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1291 GLubyte *dstRow = (GLubyte *) dstAddr 1292 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1293 + dstYoffset * dstRowStride 1294 + dstXoffset * dstFormat->TexelBytes; 1295 for (row = 0; row < srcHeight; row++) { 1296 for (col = 0; col < srcWidth; col++) { 1297 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP]; 1298 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP]; 1299 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP]; 1300 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP]; 1301 } 1302 dstRow += dstRowStride; 1303 srcRow += srcRowStride; 1304 } 1305 } 1306 } 1307 else if (!ctx->_ImageTransferState && 1308 !srcPacking->SwapBytes && 1309 dstFormat == &_mesa_texformat_argb8888 && 1310 srcType == GL_UNSIGNED_BYTE && 1311 littleEndian && 1312 /* Three texture formats involved: srcFormat, 1313 * baseInternalFormat and destFormat (GL_RGBA). Only two 1314 * may differ. _mesa_swizzle_ubyte_image can't handle two 1315 * propagations at once correctly. */ 1316 (srcFormat == baseInternalFormat || 1317 baseInternalFormat == GL_RGBA) && 1318 can_swizzle(srcFormat)) { 1319 1320 GLubyte dstmap[4]; 1321 1322 /* dstmap - how to swizzle from GL_RGBA to dst format: 1323 */ 1324 dstmap[3] = 3; /* alpha */ 1325 dstmap[2] = 0; /* red */ 1326 dstmap[1] = 1; /* green */ 1327 dstmap[0] = 2; /* blue */ 1328 1329 _mesa_swizzle_ubyte_image(ctx, dims, 1330 srcFormat, 1331 dstmap, 4, 1332 dstAddr, dstXoffset, dstYoffset, dstZoffset, 1333 dstRowStride, 1334 dstImageOffsets, 1335 srcWidth, srcHeight, srcDepth, srcAddr, 1336 srcPacking); 1337 } 1338 else { 1339 /* general path */ 1340 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1341 baseInternalFormat, 1342 dstFormat->BaseFormat, 1343 srcWidth, srcHeight, srcDepth, 1344 srcFormat, srcType, srcAddr, 1345 srcPacking); 1346 const GLchan *src = tempImage; 1347 GLint img, row, col; 1348 if (!tempImage) 1349 return GL_FALSE; 1350 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1351 for (img = 0; img < srcDepth; img++) { 1352 GLubyte *dstRow = (GLubyte *) dstAddr 1353 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1354 + dstYoffset * dstRowStride 1355 + dstXoffset * dstFormat->TexelBytes; 1356 for (row = 0; row < srcHeight; row++) { 1357 GLuint *dstUI = (GLuint *) dstRow; 1358 if (dstFormat == &_mesa_texformat_argb8888) { 1359 for (col = 0; col < srcWidth; col++) { 1360 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]), 1361 CHAN_TO_UBYTE(src[RCOMP]), 1362 CHAN_TO_UBYTE(src[GCOMP]), 1363 CHAN_TO_UBYTE(src[BCOMP]) ); 1364 src += 4; 1365 } 1366 } 1367 else { 1368 for (col = 0; col < srcWidth; col++) { 1369 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]), 1370 CHAN_TO_UBYTE(src[RCOMP]), 1371 CHAN_TO_UBYTE(src[GCOMP]), 1372 CHAN_TO_UBYTE(src[BCOMP]) ); 1373 src += 4; 1374 } 1375 } 1376 dstRow += dstRowStride; 1377 } 1378 } 1379 _mesa_free((void *) tempImage); 1380 } 1381 return GL_TRUE; 1382} 1383 1384 1385GLboolean 1386_mesa_texstore_rgb888(TEXSTORE_PARAMS) 1387{ 1388 const GLuint ui = 1; 1389 const GLubyte littleEndian = *((const GLubyte *) &ui); 1390 1391 ASSERT(dstFormat == &_mesa_texformat_rgb888); 1392 ASSERT(dstFormat->TexelBytes == 3); 1393 1394 if (!ctx->_ImageTransferState && 1395 !srcPacking->SwapBytes && 1396 baseInternalFormat == GL_RGB && 1397 srcFormat == GL_BGR && 1398 srcType == GL_UNSIGNED_BYTE && 1399 littleEndian) { 1400 /* simple memcpy path */ 1401 memcpy_texture(ctx, dims, 1402 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1403 dstRowStride, 1404 dstImageOffsets, 1405 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1406 srcAddr, srcPacking); 1407 } 1408 else if (!ctx->_ImageTransferState && 1409 !srcPacking->SwapBytes && 1410 srcFormat == GL_RGBA && 1411 srcType == GL_UNSIGNED_BYTE) { 1412 /* extract RGB from RGBA */ 1413 GLint img, row, col; 1414 for (img = 0; img < srcDepth; img++) { 1415 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1416 srcWidth, srcFormat, srcType); 1417 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1418 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1419 GLubyte *dstRow = (GLubyte *) dstAddr 1420 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1421 + dstYoffset * dstRowStride 1422 + dstXoffset * dstFormat->TexelBytes; 1423 for (row = 0; row < srcHeight; row++) { 1424 for (col = 0; col < srcWidth; col++) { 1425 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP]; 1426 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; 1427 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP]; 1428 } 1429 dstRow += dstRowStride; 1430 srcRow += srcRowStride; 1431 } 1432 } 1433 } 1434 else { 1435 /* general path */ 1436 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1437 baseInternalFormat, 1438 dstFormat->BaseFormat, 1439 srcWidth, srcHeight, srcDepth, 1440 srcFormat, srcType, srcAddr, 1441 srcPacking); 1442 const GLchan *src = (const GLchan *) tempImage; 1443 GLint img, row, col; 1444 if (!tempImage) 1445 return GL_FALSE; 1446 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1447 for (img = 0; img < srcDepth; img++) { 1448 GLubyte *dstRow = (GLubyte *) dstAddr 1449 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1450 + dstYoffset * dstRowStride 1451 + dstXoffset * dstFormat->TexelBytes; 1452 for (row = 0; row < srcHeight; row++) { 1453#if 0 1454 if (littleEndian) { 1455 for (col = 0; col < srcWidth; col++) { 1456 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); 1457 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1458 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); 1459 srcUB += 3; 1460 } 1461 } 1462 else { 1463 for (col = 0; col < srcWidth; col++) { 1464 dstRow[col * 3 + 0] = srcUB[BCOMP]; 1465 dstRow[col * 3 + 1] = srcUB[GCOMP]; 1466 dstRow[col * 3 + 2] = srcUB[RCOMP]; 1467 srcUB += 3; 1468 } 1469 } 1470#else 1471 for (col = 0; col < srcWidth; col++) { 1472 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]); 1473 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1474 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]); 1475 src += 3; 1476 } 1477#endif 1478 dstRow += dstRowStride; 1479 } 1480 } 1481 _mesa_free((void *) tempImage); 1482 } 1483 return GL_TRUE; 1484} 1485 1486 1487GLboolean 1488_mesa_texstore_bgr888(TEXSTORE_PARAMS) 1489{ 1490 const GLuint ui = 1; 1491 const GLubyte littleEndian = *((const GLubyte *) &ui); 1492 1493 ASSERT(dstFormat == &_mesa_texformat_bgr888); 1494 ASSERT(dstFormat->TexelBytes == 3); 1495 1496 if (!ctx->_ImageTransferState && 1497 !srcPacking->SwapBytes && 1498 baseInternalFormat == GL_RGB && 1499 srcFormat == GL_RGB && 1500 srcType == GL_UNSIGNED_BYTE && 1501 littleEndian) { 1502 /* simple memcpy path */ 1503 memcpy_texture(ctx, dims, 1504 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1505 dstRowStride, 1506 dstImageOffsets, 1507 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1508 srcAddr, srcPacking); 1509 } 1510 else if (!ctx->_ImageTransferState && 1511 !srcPacking->SwapBytes && 1512 srcFormat == GL_RGBA && 1513 srcType == GL_UNSIGNED_BYTE) { 1514 /* extract BGR from RGBA */ 1515 int img, row, col; 1516 for (img = 0; img < srcDepth; img++) { 1517 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, 1518 srcWidth, srcFormat, srcType); 1519 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking, 1520 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0); 1521 GLubyte *dstRow = (GLubyte *) dstAddr 1522 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1523 + dstYoffset * dstRowStride 1524 + dstXoffset * dstFormat->TexelBytes; 1525 for (row = 0; row < srcHeight; row++) { 1526 for (col = 0; col < srcWidth; col++) { 1527 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP]; 1528 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP]; 1529 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP]; 1530 } 1531 dstRow += dstRowStride; 1532 srcRow += srcRowStride; 1533 } 1534 } 1535 } 1536 else { 1537 /* general path */ 1538 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1539 baseInternalFormat, 1540 dstFormat->BaseFormat, 1541 srcWidth, srcHeight, srcDepth, 1542 srcFormat, srcType, srcAddr, 1543 srcPacking); 1544 const GLchan *src = (const GLchan *) tempImage; 1545 GLint img, row, col; 1546 if (!tempImage) 1547 return GL_FALSE; 1548 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1549 for (img = 0; img < srcDepth; img++) { 1550 GLubyte *dstRow = (GLubyte *) dstAddr 1551 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1552 + dstYoffset * dstRowStride 1553 + dstXoffset * dstFormat->TexelBytes; 1554 for (row = 0; row < srcHeight; row++) { 1555 for (col = 0; col < srcWidth; col++) { 1556 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]); 1557 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]); 1558 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]); 1559 src += 3; 1560 } 1561 dstRow += dstRowStride; 1562 } 1563 } 1564 _mesa_free((void *) tempImage); 1565 } 1566 return GL_TRUE; 1567} 1568 1569 1570GLboolean 1571_mesa_texstore_argb4444(TEXSTORE_PARAMS) 1572{ 1573 ASSERT(dstFormat == &_mesa_texformat_argb4444 || 1574 dstFormat == &_mesa_texformat_argb4444_rev); 1575 ASSERT(dstFormat->TexelBytes == 2); 1576 1577 if (!ctx->_ImageTransferState && 1578 !srcPacking->SwapBytes && 1579 dstFormat == &_mesa_texformat_argb4444 && 1580 baseInternalFormat == GL_RGBA && 1581 srcFormat == GL_BGRA && 1582 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) { 1583 /* simple memcpy path */ 1584 memcpy_texture(ctx, dims, 1585 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1586 dstRowStride, 1587 dstImageOffsets, 1588 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1589 srcAddr, srcPacking); 1590 } 1591 else { 1592 /* general path */ 1593 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1594 baseInternalFormat, 1595 dstFormat->BaseFormat, 1596 srcWidth, srcHeight, srcDepth, 1597 srcFormat, srcType, srcAddr, 1598 srcPacking); 1599 const GLchan *src = tempImage; 1600 GLint img, row, col; 1601 if (!tempImage) 1602 return GL_FALSE; 1603 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1604 for (img = 0; img < srcDepth; img++) { 1605 GLubyte *dstRow = (GLubyte *) dstAddr 1606 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1607 + dstYoffset * dstRowStride 1608 + dstXoffset * dstFormat->TexelBytes; 1609 for (row = 0; row < srcHeight; row++) { 1610 GLushort *dstUS = (GLushort *) dstRow; 1611 if (dstFormat == &_mesa_texformat_argb4444) { 1612 for (col = 0; col < srcWidth; col++) { 1613 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]), 1614 CHAN_TO_UBYTE(src[RCOMP]), 1615 CHAN_TO_UBYTE(src[GCOMP]), 1616 CHAN_TO_UBYTE(src[BCOMP]) ); 1617 src += 4; 1618 } 1619 } 1620 else { 1621 for (col = 0; col < srcWidth; col++) { 1622 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]), 1623 CHAN_TO_UBYTE(src[RCOMP]), 1624 CHAN_TO_UBYTE(src[GCOMP]), 1625 CHAN_TO_UBYTE(src[BCOMP]) ); 1626 src += 4; 1627 } 1628 } 1629 dstRow += dstRowStride; 1630 } 1631 } 1632 _mesa_free((void *) tempImage); 1633 } 1634 return GL_TRUE; 1635} 1636 1637 1638 1639GLboolean 1640_mesa_texstore_argb1555(TEXSTORE_PARAMS) 1641{ 1642 ASSERT(dstFormat == &_mesa_texformat_argb1555 || 1643 dstFormat == &_mesa_texformat_argb1555_rev); 1644 ASSERT(dstFormat->TexelBytes == 2); 1645 1646 if (!ctx->_ImageTransferState && 1647 !srcPacking->SwapBytes && 1648 dstFormat == &_mesa_texformat_argb1555 && 1649 baseInternalFormat == GL_RGBA && 1650 srcFormat == GL_BGRA && 1651 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) { 1652 /* simple memcpy path */ 1653 memcpy_texture(ctx, dims, 1654 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1655 dstRowStride, 1656 dstImageOffsets, 1657 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1658 srcAddr, srcPacking); 1659 } 1660 else { 1661 /* general path */ 1662 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1663 baseInternalFormat, 1664 dstFormat->BaseFormat, 1665 srcWidth, srcHeight, srcDepth, 1666 srcFormat, srcType, srcAddr, 1667 srcPacking); 1668 const GLchan *src =tempImage; 1669 GLint img, row, col; 1670 if (!tempImage) 1671 return GL_FALSE; 1672 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1673 for (img = 0; img < srcDepth; img++) { 1674 GLubyte *dstRow = (GLubyte *) dstAddr 1675 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1676 + dstYoffset * dstRowStride 1677 + dstXoffset * dstFormat->TexelBytes; 1678 for (row = 0; row < srcHeight; row++) { 1679 GLushort *dstUS = (GLushort *) dstRow; 1680 if (dstFormat == &_mesa_texformat_argb1555) { 1681 for (col = 0; col < srcWidth; col++) { 1682 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]), 1683 CHAN_TO_UBYTE(src[RCOMP]), 1684 CHAN_TO_UBYTE(src[GCOMP]), 1685 CHAN_TO_UBYTE(src[BCOMP]) ); 1686 src += 4; 1687 } 1688 } 1689 else { 1690 for (col = 0; col < srcWidth; col++) { 1691 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]), 1692 CHAN_TO_UBYTE(src[RCOMP]), 1693 CHAN_TO_UBYTE(src[GCOMP]), 1694 CHAN_TO_UBYTE(src[BCOMP]) ); 1695 src += 4; 1696 } 1697 } 1698 dstRow += dstRowStride; 1699 } 1700 } 1701 _mesa_free((void *) tempImage); 1702 } 1703 return GL_TRUE; 1704} 1705 1706 1707GLboolean 1708_mesa_texstore_al88(TEXSTORE_PARAMS) 1709{ 1710 const GLuint ui = 1; 1711 const GLubyte littleEndian = *((const GLubyte *) &ui); 1712 1713 ASSERT(dstFormat == &_mesa_texformat_al88 || 1714 dstFormat == &_mesa_texformat_al88_rev); 1715 ASSERT(dstFormat->TexelBytes == 2); 1716 1717 if (!ctx->_ImageTransferState && 1718 !srcPacking->SwapBytes && 1719 dstFormat == &_mesa_texformat_al88 && 1720 baseInternalFormat == GL_LUMINANCE_ALPHA && 1721 srcFormat == GL_LUMINANCE_ALPHA && 1722 srcType == GL_UNSIGNED_BYTE && 1723 littleEndian) { 1724 /* simple memcpy path */ 1725 memcpy_texture(ctx, dims, 1726 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1727 dstRowStride, 1728 dstImageOffsets, 1729 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1730 srcAddr, srcPacking); 1731 } 1732 else { 1733 /* general path */ 1734 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1735 baseInternalFormat, 1736 dstFormat->BaseFormat, 1737 srcWidth, srcHeight, srcDepth, 1738 srcFormat, srcType, srcAddr, 1739 srcPacking); 1740 const GLchan *src = tempImage; 1741 GLint img, row, col; 1742 if (!tempImage) 1743 return GL_FALSE; 1744 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1745 for (img = 0; img < srcDepth; img++) { 1746 GLubyte *dstRow = (GLubyte *) dstAddr 1747 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1748 + dstYoffset * dstRowStride 1749 + dstXoffset * dstFormat->TexelBytes; 1750 for (row = 0; row < srcHeight; row++) { 1751 GLushort *dstUS = (GLushort *) dstRow; 1752 if (dstFormat == &_mesa_texformat_al88) { 1753 for (col = 0; col < srcWidth; col++) { 1754 /* src[0] is luminance, src[1] is alpha */ 1755 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]), 1756 CHAN_TO_UBYTE(src[0]) ); 1757 src += 2; 1758 } 1759 } 1760 else { 1761 for (col = 0; col < srcWidth; col++) { 1762 /* src[0] is luminance, src[1] is alpha */ 1763 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]), 1764 CHAN_TO_UBYTE(src[0]) ); 1765 src += 2; 1766 } 1767 } 1768 dstRow += dstRowStride; 1769 } 1770 } 1771 _mesa_free((void *) tempImage); 1772 } 1773 return GL_TRUE; 1774} 1775 1776 1777GLboolean 1778_mesa_texstore_rgb332(TEXSTORE_PARAMS) 1779{ 1780 ASSERT(dstFormat == &_mesa_texformat_rgb332); 1781 ASSERT(dstFormat->TexelBytes == 1); 1782 1783 if (!ctx->_ImageTransferState && 1784 !srcPacking->SwapBytes && 1785 baseInternalFormat == GL_RGB && 1786 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) { 1787 /* simple memcpy path */ 1788 memcpy_texture(ctx, dims, 1789 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1790 dstRowStride, 1791 dstImageOffsets, 1792 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1793 srcAddr, srcPacking); 1794 } 1795 else { 1796 /* general path */ 1797 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1798 baseInternalFormat, 1799 dstFormat->BaseFormat, 1800 srcWidth, srcHeight, srcDepth, 1801 srcFormat, srcType, srcAddr, 1802 srcPacking); 1803 const GLchan *src = tempImage; 1804 GLint img, row, col; 1805 if (!tempImage) 1806 return GL_FALSE; 1807 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1808 for (img = 0; img < srcDepth; img++) { 1809 GLubyte *dstRow = (GLubyte *) dstAddr 1810 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1811 + dstYoffset * dstRowStride 1812 + dstXoffset * dstFormat->TexelBytes; 1813 for (row = 0; row < srcHeight; row++) { 1814 for (col = 0; col < srcWidth; col++) { 1815 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]), 1816 CHAN_TO_UBYTE(src[GCOMP]), 1817 CHAN_TO_UBYTE(src[BCOMP]) ); 1818 src += 3; 1819 } 1820 dstRow += dstRowStride; 1821 } 1822 } 1823 _mesa_free((void *) tempImage); 1824 } 1825 return GL_TRUE; 1826} 1827 1828 1829/** 1830 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8. 1831 */ 1832GLboolean 1833_mesa_texstore_a8(TEXSTORE_PARAMS) 1834{ 1835 ASSERT(dstFormat == &_mesa_texformat_a8 || 1836 dstFormat == &_mesa_texformat_l8 || 1837 dstFormat == &_mesa_texformat_i8); 1838 ASSERT(dstFormat->TexelBytes == 1); 1839 1840 if (!ctx->_ImageTransferState && 1841 !srcPacking->SwapBytes && 1842 baseInternalFormat == srcFormat && 1843 srcType == GL_UNSIGNED_BYTE) { 1844 /* simple memcpy path */ 1845 memcpy_texture(ctx, dims, 1846 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1847 dstRowStride, 1848 dstImageOffsets, 1849 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1850 srcAddr, srcPacking); 1851 } 1852 else { 1853 /* general path */ 1854 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims, 1855 baseInternalFormat, 1856 dstFormat->BaseFormat, 1857 srcWidth, srcHeight, srcDepth, 1858 srcFormat, srcType, srcAddr, 1859 srcPacking); 1860 const GLchan *src = tempImage; 1861 GLint img, row, col; 1862 if (!tempImage) 1863 return GL_FALSE; 1864 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 1865 for (img = 0; img < srcDepth; img++) { 1866 GLubyte *dstRow = (GLubyte *) dstAddr 1867 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1868 + dstYoffset * dstRowStride 1869 + dstXoffset * dstFormat->TexelBytes; 1870 for (row = 0; row < srcHeight; row++) { 1871 for (col = 0; col < srcWidth; col++) { 1872 dstRow[col] = CHAN_TO_UBYTE(src[col]); 1873 } 1874 dstRow += dstRowStride; 1875 src += srcWidth; 1876 } 1877 } 1878 _mesa_free((void *) tempImage); 1879 } 1880 return GL_TRUE; 1881} 1882 1883 1884 1885GLboolean 1886_mesa_texstore_ci8(TEXSTORE_PARAMS) 1887{ 1888 (void) dims; (void) baseInternalFormat; 1889 ASSERT(dstFormat == &_mesa_texformat_ci8); 1890 ASSERT(dstFormat->TexelBytes == 1); 1891 ASSERT(baseInternalFormat == GL_COLOR_INDEX); 1892 1893 if (!ctx->_ImageTransferState && 1894 !srcPacking->SwapBytes && 1895 srcFormat == GL_COLOR_INDEX && 1896 srcType == GL_UNSIGNED_BYTE) { 1897 /* simple memcpy path */ 1898 memcpy_texture(ctx, dims, 1899 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1900 dstRowStride, 1901 dstImageOffsets, 1902 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1903 srcAddr, srcPacking); 1904 } 1905 else { 1906 /* general path */ 1907 GLint img, row; 1908 for (img = 0; img < srcDepth; img++) { 1909 GLubyte *dstRow = (GLubyte *) dstAddr 1910 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1911 + dstYoffset * dstRowStride 1912 + dstXoffset * dstFormat->TexelBytes; 1913 for (row = 0; row < srcHeight; row++) { 1914 const GLvoid *src = _mesa_image_address(dims, srcPacking, 1915 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0); 1916 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow, 1917 srcType, src, srcPacking, 1918 ctx->_ImageTransferState); 1919 dstRow += dstRowStride; 1920 } 1921 } 1922 } 1923 return GL_TRUE; 1924} 1925 1926 1927/** 1928 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev. 1929 */ 1930GLboolean 1931_mesa_texstore_ycbcr(TEXSTORE_PARAMS) 1932{ 1933 const GLuint ui = 1; 1934 const GLubyte littleEndian = *((const GLubyte *) &ui); 1935 (void) ctx; (void) dims; (void) baseInternalFormat; 1936 1937 ASSERT((dstFormat == &_mesa_texformat_ycbcr) || 1938 (dstFormat == &_mesa_texformat_ycbcr_rev)); 1939 ASSERT(dstFormat->TexelBytes == 2); 1940 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 1941 ASSERT(srcFormat == GL_YCBCR_MESA); 1942 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) || 1943 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA)); 1944 ASSERT(baseInternalFormat == GL_YCBCR_MESA); 1945 1946 /* always just memcpy since no pixel transfer ops apply */ 1947 memcpy_texture(ctx, dims, 1948 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1949 dstRowStride, 1950 dstImageOffsets, 1951 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1952 srcAddr, srcPacking); 1953 1954 /* Check if we need byte swapping */ 1955 /* XXX the logic here _might_ be wrong */ 1956 if (srcPacking->SwapBytes ^ 1957 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^ 1958 (dstFormat == &_mesa_texformat_ycbcr_rev) ^ 1959 !littleEndian) { 1960 GLint img, row; 1961 for (img = 0; img < srcDepth; img++) { 1962 GLubyte *dstRow = (GLubyte *) dstAddr 1963 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 1964 + dstYoffset * dstRowStride 1965 + dstXoffset * dstFormat->TexelBytes; 1966 for (row = 0; row < srcHeight; row++) { 1967 _mesa_swap2((GLushort *) dstRow, srcWidth); 1968 dstRow += dstRowStride; 1969 } 1970 } 1971 } 1972 return GL_TRUE; 1973} 1974 1975 1976 1977/** 1978 * Store a combined depth/stencil texture image. 1979 */ 1980GLboolean 1981_mesa_texstore_z24_s8(TEXSTORE_PARAMS) 1982{ 1983 ASSERT(dstFormat == &_mesa_texformat_z24_s8); 1984 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT); 1985 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT); 1986 1987 if (!ctx->_ImageTransferState && 1988 !srcPacking->SwapBytes) { 1989 /* simple path */ 1990 memcpy_texture(ctx, dims, 1991 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 1992 dstRowStride, 1993 dstImageOffsets, 1994 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 1995 srcAddr, srcPacking); 1996 } 1997 else { 1998 /* general path */ 1999 const GLint srcRowStride 2000 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType) 2001 / sizeof(GLuint); 2002 GLint img, row; 2003 2004 for (img = 0; img < srcDepth; img++) { 2005 GLuint *dstRow = (GLuint *) dstAddr 2006 + dstImageOffsets[dstZoffset + img] 2007 + dstYoffset * dstRowStride / sizeof(GLuint) 2008 + dstXoffset; 2009 const GLuint *src 2010 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr, 2011 srcWidth, srcHeight, 2012 srcFormat, srcType, 2013 img, 0, 0); 2014 for (row = 0; row < srcHeight; row++) { 2015 GLubyte stencil[MAX_WIDTH]; 2016 GLint i; 2017 /* the 24 depth bits will be in the high position: */ 2018 _mesa_unpack_depth_span(ctx, srcWidth, 2019 GL_UNSIGNED_INT, /* dst type */ 2020 dstRow, /* dst addr */ 2021 (GLfloat) 0xffffff, /* depthScale */ 2022 srcType, src, srcPacking); 2023 /* get the 8-bit stencil values */ 2024 _mesa_unpack_stencil_span(ctx, srcWidth, 2025 GL_UNSIGNED_BYTE, /* dst type */ 2026 stencil, /* dst addr */ 2027 srcType, src, srcPacking, 2028 ctx->_ImageTransferState); 2029 /* merge stencil values into depth values */ 2030 for (i = 0; i < srcWidth; i++) 2031 dstRow[i] |= stencil[i]; 2032 2033 src += srcRowStride; 2034 dstRow += dstRowStride / sizeof(GLuint); 2035 } 2036 } 2037 } 2038 return GL_TRUE; 2039} 2040 2041 2042 2043/** 2044 * Store an image in any of the formats: 2045 * _mesa_texformat_rgba_float32 2046 * _mesa_texformat_rgb_float32 2047 * _mesa_texformat_alpha_float32 2048 * _mesa_texformat_luminance_float32 2049 * _mesa_texformat_luminance_alpha_float32 2050 * _mesa_texformat_intensity_float32 2051 */ 2052GLboolean 2053_mesa_texstore_rgba_float32(TEXSTORE_PARAMS) 2054{ 2055 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat); 2056 2057 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 || 2058 dstFormat == &_mesa_texformat_rgb_float32 || 2059 dstFormat == &_mesa_texformat_alpha_float32 || 2060 dstFormat == &_mesa_texformat_luminance_float32 || 2061 dstFormat == &_mesa_texformat_luminance_alpha_float32 || 2062 dstFormat == &_mesa_texformat_intensity_float32); 2063 ASSERT(baseInternalFormat == GL_RGBA || 2064 baseInternalFormat == GL_RGB || 2065 baseInternalFormat == GL_ALPHA || 2066 baseInternalFormat == GL_LUMINANCE || 2067 baseInternalFormat == GL_LUMINANCE_ALPHA || 2068 baseInternalFormat == GL_INTENSITY); 2069 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat)); 2070 2071 if (!ctx->_ImageTransferState && 2072 !srcPacking->SwapBytes && 2073 baseInternalFormat == srcFormat && 2074 srcType == GL_FLOAT) { 2075 /* simple memcpy path */ 2076 memcpy_texture(ctx, dims, 2077 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2078 dstRowStride, 2079 dstImageOffsets, 2080 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2081 srcAddr, srcPacking); 2082 } 2083 else { 2084 /* general path */ 2085 const GLfloat *tempImage = make_temp_float_image(ctx, dims, 2086 baseInternalFormat, 2087 dstFormat->BaseFormat, 2088 srcWidth, srcHeight, srcDepth, 2089 srcFormat, srcType, srcAddr, 2090 srcPacking); 2091 const GLfloat *srcRow = tempImage; 2092 GLint bytesPerRow; 2093 GLint img, row; 2094 if (!tempImage) 2095 return GL_FALSE; 2096 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2097 bytesPerRow = srcWidth * components * sizeof(GLfloat); 2098 for (img = 0; img < srcDepth; img++) { 2099 GLubyte *dstRow = (GLubyte *) dstAddr 2100 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2101 + dstYoffset * dstRowStride 2102 + dstXoffset * dstFormat->TexelBytes; 2103 for (row = 0; row < srcHeight; row++) { 2104 _mesa_memcpy(dstRow, srcRow, bytesPerRow); 2105 dstRow += dstRowStride; 2106 srcRow += srcWidth * components; 2107 } 2108 } 2109 2110 _mesa_free((void *) tempImage); 2111 } 2112 return GL_TRUE; 2113} 2114 2115 2116/** 2117 * As above, but store 16-bit floats. 2118 */ 2119GLboolean 2120_mesa_texstore_rgba_float16(TEXSTORE_PARAMS) 2121{ 2122 const GLint components = _mesa_components_in_format(dstFormat->BaseFormat); 2123 2124 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 || 2125 dstFormat == &_mesa_texformat_rgb_float16 || 2126 dstFormat == &_mesa_texformat_alpha_float16 || 2127 dstFormat == &_mesa_texformat_luminance_float16 || 2128 dstFormat == &_mesa_texformat_luminance_alpha_float16 || 2129 dstFormat == &_mesa_texformat_intensity_float16); 2130 ASSERT(baseInternalFormat == GL_RGBA || 2131 baseInternalFormat == GL_RGB || 2132 baseInternalFormat == GL_ALPHA || 2133 baseInternalFormat == GL_LUMINANCE || 2134 baseInternalFormat == GL_LUMINANCE_ALPHA || 2135 baseInternalFormat == GL_INTENSITY); 2136 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB)); 2137 2138 if (!ctx->_ImageTransferState && 2139 !srcPacking->SwapBytes && 2140 baseInternalFormat == srcFormat && 2141 srcType == GL_HALF_FLOAT_ARB) { 2142 /* simple memcpy path */ 2143 memcpy_texture(ctx, dims, 2144 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset, 2145 dstRowStride, 2146 dstImageOffsets, 2147 srcWidth, srcHeight, srcDepth, srcFormat, srcType, 2148 srcAddr, srcPacking); 2149 } 2150 else { 2151 /* general path */ 2152 const GLfloat *tempImage = make_temp_float_image(ctx, dims, 2153 baseInternalFormat, 2154 dstFormat->BaseFormat, 2155 srcWidth, srcHeight, srcDepth, 2156 srcFormat, srcType, srcAddr, 2157 srcPacking); 2158 const GLfloat *src = tempImage; 2159 GLint img, row; 2160 if (!tempImage) 2161 return GL_FALSE; 2162 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight); 2163 for (img = 0; img < srcDepth; img++) { 2164 GLubyte *dstRow = (GLubyte *) dstAddr 2165 + dstImageOffsets[dstZoffset + img] * dstFormat->TexelBytes 2166 + dstYoffset * dstRowStride 2167 + dstXoffset * dstFormat->TexelBytes; 2168 for (row = 0; row < srcHeight; row++) { 2169 GLhalfARB *dstTexel = (GLhalfARB *) dstRow; 2170 GLint i; 2171 for (i = 0; i < srcWidth * components; i++) { 2172 dstTexel[i] = _mesa_float_to_half(src[i]); 2173 } 2174 dstRow += dstRowStride; 2175 src += srcWidth * components; 2176 } 2177 } 2178 2179 _mesa_free((void *) tempImage); 2180 } 2181 return GL_TRUE; 2182} 2183 2184 2185#if FEATURE_EXT_texture_sRGB 2186GLboolean 2187_mesa_texstore_srgb8(TEXSTORE_PARAMS) 2188{ 2189 const GLuint ui = 1; 2190 const GLubyte littleEndian = *((const GLubyte *) &ui); 2191 const struct gl_texture_format *newDstFormat; 2192 StoreTexImageFunc store; 2193 GLboolean k; 2194 2195 ASSERT(dstFormat == &_mesa_texformat_srgb8); 2196 2197 /* reuse normal rgb texstore code */ 2198 if (littleEndian) { 2199 newDstFormat = &_mesa_texformat_bgr888; 2200 store = _mesa_texstore_bgr888; 2201 } 2202 else { 2203 newDstFormat = &_mesa_texformat_rgb888; 2204 store = _mesa_texstore_rgb888; 2205 } 2206 2207 k = store(ctx, dims, baseInternalFormat, 2208 newDstFormat, dstAddr, 2209 dstXoffset, dstYoffset, dstZoffset, 2210 dstRowStride, dstImageOffsets, 2211 srcWidth, srcHeight, srcDepth, 2212 srcFormat, srcType, 2213 srcAddr, srcPacking); 2214 return k; 2215} 2216 2217 2218GLboolean 2219_mesa_texstore_srgba8(TEXSTORE_PARAMS) 2220{ 2221 const GLuint ui = 1; 2222 const GLubyte littleEndian = *((const GLubyte *) &ui); 2223 const struct gl_texture_format *newDstFormat; 2224 GLboolean k; 2225 2226 ASSERT(dstFormat == &_mesa_texformat_srgba8); 2227 2228 /* reuse normal rgba texstore code */ 2229 if (littleEndian) 2230 newDstFormat = &_mesa_texformat_rgba8888_rev; 2231 else 2232 newDstFormat = &_mesa_texformat_rgba8888; 2233 2234 k = _mesa_texstore_rgba8888(ctx, dims, baseInternalFormat, 2235 newDstFormat, dstAddr, 2236 dstXoffset, dstYoffset, dstZoffset, 2237 dstRowStride, dstImageOffsets, 2238 srcWidth, srcHeight, srcDepth, 2239 srcFormat, srcType, 2240 srcAddr, srcPacking); 2241 return k; 2242} 2243 2244 2245GLboolean 2246_mesa_texstore_sl8(TEXSTORE_PARAMS) 2247{ 2248 const struct gl_texture_format *newDstFormat; 2249 GLboolean k; 2250 2251 ASSERT(dstFormat == &_mesa_texformat_sl8); 2252 2253 newDstFormat = &_mesa_texformat_l8; 2254 2255 /* _mesa_textore_a8 handles luminance8 too */ 2256 k = _mesa_texstore_a8(ctx, dims, baseInternalFormat, 2257 newDstFormat, dstAddr, 2258 dstXoffset, dstYoffset, dstZoffset, 2259 dstRowStride, dstImageOffsets, 2260 srcWidth, srcHeight, srcDepth, 2261 srcFormat, srcType, 2262 srcAddr, srcPacking); 2263 return k; 2264} 2265 2266 2267GLboolean 2268_mesa_texstore_sla8(TEXSTORE_PARAMS) 2269{ 2270 const GLuint ui = 1; 2271 const GLubyte littleEndian = *((const GLubyte *) &ui); 2272 const struct gl_texture_format *newDstFormat; 2273 GLboolean k; 2274 2275 ASSERT(dstFormat == &_mesa_texformat_sla8); 2276 2277 /* reuse normal luminance/alpha texstore code */ 2278 if (littleEndian) 2279 newDstFormat = &_mesa_texformat_al88; 2280 else 2281 newDstFormat = &_mesa_texformat_al88_rev; 2282 2283 k = _mesa_texstore_al88(ctx, dims, baseInternalFormat, 2284 newDstFormat, dstAddr, 2285 dstXoffset, dstYoffset, dstZoffset, 2286 dstRowStride, dstImageOffsets, 2287 srcWidth, srcHeight, srcDepth, 2288 srcFormat, srcType, 2289 srcAddr, srcPacking); 2290 return k; 2291} 2292 2293#endif /* FEATURE_EXT_texture_sRGB */ 2294 2295 2296/** 2297 * Check if an unpack PBO is active prior to fetching a texture image. 2298 * If so, do bounds checking and map the buffer into main memory. 2299 * Any errors detected will be recorded. 2300 * The caller _must_ call _mesa_unmap_teximage_pbo() too! 2301 */ 2302const GLvoid * 2303_mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions, 2304 GLsizei width, GLsizei height, GLsizei depth, 2305 GLenum format, GLenum type, const GLvoid *pixels, 2306 const struct gl_pixelstore_attrib *unpack, 2307 const char *funcName) 2308{ 2309 GLubyte *buf; 2310 2311 if (unpack->BufferObj->Name == 0) { 2312 /* no PBO */ 2313 return pixels; 2314 } 2315 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 2316 format, type, pixels)) { 2317 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); 2318 return NULL; 2319 } 2320 2321 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2322 GL_READ_ONLY_ARB, unpack->BufferObj); 2323 if (!buf) { 2324 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); 2325 return NULL; 2326 } 2327 2328 return ADD_POINTERS(buf, pixels); 2329} 2330 2331 2332/** 2333 * Check if an unpack PBO is active prior to fetching a compressed texture 2334 * image. 2335 * If so, do bounds checking and map the buffer into main memory. 2336 * Any errors detected will be recorded. 2337 * The caller _must_ call _mesa_unmap_teximage_pbo() too! 2338 */ 2339const GLvoid * 2340_mesa_validate_pbo_compressed_teximage(GLcontext *ctx, 2341 GLsizei imageSize, const GLvoid *pixels, 2342 const struct gl_pixelstore_attrib *packing, 2343 const char *funcName) 2344{ 2345 GLubyte *buf; 2346 2347 if (packing->BufferObj->Name == 0) { 2348 /* not using a PBO - return pointer unchanged */ 2349 return pixels; 2350 } 2351 if ((const GLubyte *) pixels + imageSize > 2352 ((const GLubyte *) 0) + packing->BufferObj->Size) { 2353 /* out of bounds read! */ 2354 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access"); 2355 return NULL; 2356 } 2357 2358 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2359 GL_READ_ONLY_ARB, packing->BufferObj); 2360 if (!buf) { 2361 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); 2362 return NULL; 2363 } 2364 2365 return ADD_POINTERS(buf, pixels); 2366} 2367 2368 2369/** 2370 * This function must be called after either of the validate_pbo_*_teximage() 2371 * functions. It unmaps the PBO buffer if it was mapped earlier. 2372 */ 2373void 2374_mesa_unmap_teximage_pbo(GLcontext *ctx, 2375 const struct gl_pixelstore_attrib *unpack) 2376{ 2377 if (unpack->BufferObj->Name) { 2378 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 2379 unpack->BufferObj); 2380 } 2381} 2382 2383 2384 2385/** 2386 * Adaptor for fetching a GLchan texel from a float-valued texture. 2387 */ 2388static void 2389FetchTexelFloatToChan( const struct gl_texture_image *texImage, 2390 GLint i, GLint j, GLint k, GLchan *texelOut ) 2391{ 2392 GLfloat temp[4]; 2393 ASSERT(texImage->FetchTexelf); 2394 texImage->FetchTexelf(texImage, i, j, k, temp); 2395 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT || 2396 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { 2397 /* just one channel */ 2398 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); 2399 } 2400 else { 2401 /* four channels */ 2402 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]); 2403 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]); 2404 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]); 2405 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]); 2406 } 2407} 2408 2409 2410/** 2411 * Adaptor for fetching a float texel from a GLchan-valued texture. 2412 */ 2413static void 2414FetchTexelChanToFloat( const struct gl_texture_image *texImage, 2415 GLint i, GLint j, GLint k, GLfloat *texelOut ) 2416{ 2417 GLchan temp[4]; 2418 ASSERT(texImage->FetchTexelc); 2419 texImage->FetchTexelc(texImage, i, j, k, temp); 2420 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT || 2421 texImage->TexFormat->BaseFormat == GL_DEPTH_STENCIL_EXT) { 2422 /* just one channel */ 2423 texelOut[0] = CHAN_TO_FLOAT(temp[0]); 2424 } 2425 else { 2426 /* four channels */ 2427 texelOut[0] = CHAN_TO_FLOAT(temp[0]); 2428 texelOut[1] = CHAN_TO_FLOAT(temp[1]); 2429 texelOut[2] = CHAN_TO_FLOAT(temp[2]); 2430 texelOut[3] = CHAN_TO_FLOAT(temp[3]); 2431 } 2432} 2433 2434 2435/** 2436 * Initialize the texture image's FetchTexelc and FetchTexelf methods. 2437 */ 2438static void 2439set_fetch_functions(struct gl_texture_image *texImage, GLuint dims) 2440{ 2441 ASSERT(dims == 1 || dims == 2 || dims == 3); 2442 ASSERT(texImage->TexFormat); 2443 2444 switch (dims) { 2445 case 1: 2446 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; 2447 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; 2448 break; 2449 case 2: 2450 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; 2451 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; 2452 break; 2453 case 3: 2454 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D; 2455 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df; 2456 break; 2457 default: 2458 ; 2459 } 2460 2461 /* now check if we need to use a float/chan adaptor */ 2462 if (!texImage->FetchTexelc) { 2463 texImage->FetchTexelc = FetchTexelFloatToChan; 2464 } 2465 else if (!texImage->FetchTexelf) { 2466 texImage->FetchTexelf = FetchTexelChanToFloat; 2467 } 2468 2469 2470 ASSERT(texImage->FetchTexelc); 2471 ASSERT(texImage->FetchTexelf); 2472} 2473 2474 2475/** 2476 * Choose the actual storage format for a new texture image. 2477 * Mainly, this is a wrapper for the driver's ChooseTextureFormat() function. 2478 * Also set some other texImage fields related to texture compression, etc. 2479 * \param ctx rendering context 2480 * \param texImage the gl_texture_image 2481 * \param dims texture dimensions (1, 2 or 3) 2482 * \param format the user-specified format parameter 2483 * \param type the user-specified type parameter 2484 * \param internalFormat the user-specified internal format hint 2485 */ 2486static void 2487choose_texture_format(GLcontext *ctx, struct gl_texture_image *texImage, 2488 GLuint dims, 2489 GLenum format, GLenum type, GLint internalFormat) 2490{ 2491 ASSERT(dims == 1 || dims == 2 || dims == 3); 2492 ASSERT(ctx->Driver.ChooseTextureFormat); 2493 2494 texImage->TexFormat 2495 = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2496 2497 ASSERT(texImage->TexFormat); 2498 2499 set_fetch_functions(texImage, dims); 2500 2501 if (texImage->TexFormat->TexelBytes == 0) { 2502 /* must be a compressed format */ 2503 texImage->IsCompressed = GL_TRUE; 2504 texImage->CompressedSize = 2505 ctx->Driver.CompressedTextureSize(ctx, texImage->Width, 2506 texImage->Height, texImage->Depth, 2507 texImage->TexFormat->MesaFormat); 2508 } 2509 else { 2510 /* non-compressed format */ 2511 texImage->IsCompressed = GL_FALSE; 2512 texImage->CompressedSize = 0; 2513 } 2514} 2515 2516 2517 2518/* 2519 * This is the software fallback for Driver.TexImage1D() 2520 * and Driver.CopyTexImage1D(). 2521 * \sa _mesa_store_teximage2d() 2522 */ 2523void 2524_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level, 2525 GLint internalFormat, 2526 GLint width, GLint border, 2527 GLenum format, GLenum type, const GLvoid *pixels, 2528 const struct gl_pixelstore_attrib *packing, 2529 struct gl_texture_object *texObj, 2530 struct gl_texture_image *texImage) 2531{ 2532 GLint postConvWidth = width; 2533 GLint sizeInBytes; 2534 (void) border; 2535 2536 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { 2537 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2538 } 2539 2540 choose_texture_format(ctx, texImage, 1, format, type, internalFormat); 2541 2542 /* allocate memory */ 2543 if (texImage->IsCompressed) 2544 sizeInBytes = texImage->CompressedSize; 2545 else 2546 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes; 2547 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 2548 if (!texImage->Data) { 2549 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2550 return; 2551 } 2552 2553 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, 2554 pixels, packing, "glTexImage1D"); 2555 if (!pixels) { 2556 /* Note: we check for a NULL image pointer here, _after_ we allocated 2557 * memory for the texture. That's what the GL spec calls for. 2558 */ 2559 return; 2560 } 2561 else { 2562 const GLint dstRowStride = 0; 2563 GLboolean success; 2564 ASSERT(texImage->TexFormat->StoreImage); 2565 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat, 2566 texImage->TexFormat, 2567 texImage->Data, 2568 0, 0, 0, /* dstX/Y/Zoffset */ 2569 dstRowStride, 2570 texImage->ImageOffsets, 2571 width, 1, 1, 2572 format, type, pixels, packing); 2573 if (!success) { 2574 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2575 } 2576 } 2577 2578 /* GL_SGIS_generate_mipmap */ 2579 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2580 _mesa_generate_mipmap(ctx, target, 2581 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2582 texObj); 2583 } 2584 2585 _mesa_unmap_teximage_pbo(ctx, packing); 2586} 2587 2588 2589/** 2590 * This is the software fallback for Driver.TexImage2D() 2591 * and Driver.CopyTexImage2D(). 2592 * 2593 * This function is oriented toward storing images in main memory, rather 2594 * than VRAM. Device driver's can easily plug in their own replacement. 2595 * 2596 * Note: width and height may be pre-convolved dimensions, but 2597 * texImage->Width and texImage->Height will be post-convolved dimensions. 2598 */ 2599void 2600_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level, 2601 GLint internalFormat, 2602 GLint width, GLint height, GLint border, 2603 GLenum format, GLenum type, const void *pixels, 2604 const struct gl_pixelstore_attrib *packing, 2605 struct gl_texture_object *texObj, 2606 struct gl_texture_image *texImage) 2607{ 2608 GLint postConvWidth = width, postConvHeight = height; 2609 GLint texelBytes, sizeInBytes; 2610 (void) border; 2611 2612 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { 2613 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2614 &postConvHeight); 2615 } 2616 2617 choose_texture_format(ctx, texImage, 2, format, type, internalFormat); 2618 2619 texelBytes = texImage->TexFormat->TexelBytes; 2620 2621 /* allocate memory */ 2622 if (texImage->IsCompressed) 2623 sizeInBytes = texImage->CompressedSize; 2624 else 2625 sizeInBytes = postConvWidth * postConvHeight * texelBytes; 2626 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 2627 if (!texImage->Data) { 2628 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2629 return; 2630 } 2631 2632 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, 2633 pixels, packing, "glTexImage2D"); 2634 if (!pixels) { 2635 /* Note: we check for a NULL image pointer here, _after_ we allocated 2636 * memory for the texture. That's what the GL spec calls for. 2637 */ 2638 return; 2639 } 2640 else { 2641 GLint dstRowStride; 2642 GLboolean success; 2643 if (texImage->IsCompressed) { 2644 dstRowStride 2645 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); 2646 } 2647 else { 2648 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 2649 } 2650 ASSERT(texImage->TexFormat->StoreImage); 2651 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, 2652 texImage->TexFormat, 2653 texImage->Data, 2654 0, 0, 0, /* dstX/Y/Zoffset */ 2655 dstRowStride, 2656 texImage->ImageOffsets, 2657 width, height, 1, 2658 format, type, pixels, packing); 2659 if (!success) { 2660 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2661 } 2662 } 2663 2664 /* GL_SGIS_generate_mipmap */ 2665 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2666 _mesa_generate_mipmap(ctx, target, 2667 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2668 texObj); 2669 } 2670 2671 _mesa_unmap_teximage_pbo(ctx, packing); 2672} 2673 2674 2675 2676/** 2677 * This is the software fallback for Driver.TexImage3D() 2678 * and Driver.CopyTexImage3D(). 2679 * \sa _mesa_store_teximage2d() 2680 */ 2681void 2682_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level, 2683 GLint internalFormat, 2684 GLint width, GLint height, GLint depth, GLint border, 2685 GLenum format, GLenum type, const void *pixels, 2686 const struct gl_pixelstore_attrib *packing, 2687 struct gl_texture_object *texObj, 2688 struct gl_texture_image *texImage) 2689{ 2690 GLint texelBytes, sizeInBytes; 2691 (void) border; 2692 2693 choose_texture_format(ctx, texImage, 3, format, type, internalFormat); 2694 2695 texelBytes = texImage->TexFormat->TexelBytes; 2696 2697 /* allocate memory */ 2698 if (texImage->IsCompressed) 2699 sizeInBytes = texImage->CompressedSize; 2700 else 2701 sizeInBytes = width * height * depth * texelBytes; 2702 texImage->Data = _mesa_alloc_texmemory(sizeInBytes); 2703 if (!texImage->Data) { 2704 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2705 return; 2706 } 2707 2708 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, 2709 type, pixels, packing, "glTexImage3D"); 2710 if (!pixels) { 2711 /* Note: we check for a NULL image pointer here, _after_ we allocated 2712 * memory for the texture. That's what the GL spec calls for. 2713 */ 2714 return; 2715 } 2716 else { 2717 GLint dstRowStride; 2718 GLboolean success; 2719 if (texImage->IsCompressed) { 2720 dstRowStride 2721 = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); 2722 } 2723 else { 2724 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 2725 } 2726 ASSERT(texImage->TexFormat->StoreImage); 2727 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat, 2728 texImage->TexFormat, 2729 texImage->Data, 2730 0, 0, 0, /* dstX/Y/Zoffset */ 2731 dstRowStride, 2732 texImage->ImageOffsets, 2733 width, height, depth, 2734 format, type, pixels, packing); 2735 if (!success) { 2736 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2737 } 2738 } 2739 2740 /* GL_SGIS_generate_mipmap */ 2741 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2742 _mesa_generate_mipmap(ctx, target, 2743 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2744 texObj); 2745 } 2746 2747 _mesa_unmap_teximage_pbo(ctx, packing); 2748} 2749 2750 2751 2752 2753/* 2754 * This is the software fallback for Driver.TexSubImage1D() 2755 * and Driver.CopyTexSubImage1D(). 2756 */ 2757void 2758_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level, 2759 GLint xoffset, GLint width, 2760 GLenum format, GLenum type, const void *pixels, 2761 const struct gl_pixelstore_attrib *packing, 2762 struct gl_texture_object *texObj, 2763 struct gl_texture_image *texImage) 2764{ 2765 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 2766 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type, 2767 pixels, packing, "glTexSubImage1D"); 2768 if (!pixels) 2769 return; 2770 2771 { 2772 const GLint dstRowStride = 0; 2773 GLboolean success; 2774 ASSERT(texImage->TexFormat->StoreImage); 2775 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat, 2776 texImage->TexFormat, 2777 texImage->Data, 2778 xoffset, 0, 0, /* offsets */ 2779 dstRowStride, 2780 texImage->ImageOffsets, 2781 width, 1, 1, 2782 format, type, pixels, packing); 2783 if (!success) { 2784 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); 2785 } 2786 } 2787 2788 /* GL_SGIS_generate_mipmap */ 2789 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2790 _mesa_generate_mipmap(ctx, target, 2791 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2792 texObj); 2793 } 2794 2795 _mesa_unmap_teximage_pbo(ctx, packing); 2796} 2797 2798 2799 2800/** 2801 * This is the software fallback for Driver.TexSubImage2D() 2802 * and Driver.CopyTexSubImage2D(). 2803 */ 2804void 2805_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level, 2806 GLint xoffset, GLint yoffset, 2807 GLint width, GLint height, 2808 GLenum format, GLenum type, const void *pixels, 2809 const struct gl_pixelstore_attrib *packing, 2810 struct gl_texture_object *texObj, 2811 struct gl_texture_image *texImage) 2812{ 2813 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 2814 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type, 2815 pixels, packing, "glTexSubImage2D"); 2816 if (!pixels) 2817 return; 2818 2819 { 2820 GLint dstRowStride = 0; 2821 GLboolean success; 2822 if (texImage->IsCompressed) { 2823 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, 2824 texImage->Width); 2825 } 2826 else { 2827 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 2828 } 2829 ASSERT(texImage->TexFormat->StoreImage); 2830 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat, 2831 texImage->TexFormat, 2832 texImage->Data, 2833 xoffset, yoffset, 0, 2834 dstRowStride, 2835 texImage->ImageOffsets, 2836 width, height, 1, 2837 format, type, pixels, packing); 2838 if (!success) { 2839 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); 2840 } 2841 } 2842 2843 /* GL_SGIS_generate_mipmap */ 2844 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2845 _mesa_generate_mipmap(ctx, target, 2846 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2847 texObj); 2848 } 2849 2850 _mesa_unmap_teximage_pbo(ctx, packing); 2851} 2852 2853 2854/* 2855 * This is the software fallback for Driver.TexSubImage3D(). 2856 * and Driver.CopyTexSubImage3D(). 2857 */ 2858void 2859_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level, 2860 GLint xoffset, GLint yoffset, GLint zoffset, 2861 GLint width, GLint height, GLint depth, 2862 GLenum format, GLenum type, const void *pixels, 2863 const struct gl_pixelstore_attrib *packing, 2864 struct gl_texture_object *texObj, 2865 struct gl_texture_image *texImage) 2866{ 2867 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 2868 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format, 2869 type, pixels, packing, 2870 "glTexSubImage3D"); 2871 if (!pixels) 2872 return; 2873 2874 { 2875 GLint dstRowStride; 2876 GLboolean success; 2877 if (texImage->IsCompressed) { 2878 dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, 2879 texImage->Width); 2880 } 2881 else { 2882 dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes; 2883 } 2884 ASSERT(texImage->TexFormat->StoreImage); 2885 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat, 2886 texImage->TexFormat, 2887 texImage->Data, 2888 xoffset, yoffset, zoffset, 2889 dstRowStride, 2890 texImage->ImageOffsets, 2891 width, height, depth, 2892 format, type, pixels, packing); 2893 if (!success) { 2894 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D"); 2895 } 2896 } 2897 2898 /* GL_SGIS_generate_mipmap */ 2899 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2900 _mesa_generate_mipmap(ctx, target, 2901 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2902 texObj); 2903 } 2904 2905 _mesa_unmap_teximage_pbo(ctx, packing); 2906} 2907 2908 2909/* 2910 * Fallback for Driver.CompressedTexImage1D() 2911 */ 2912void 2913_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level, 2914 GLint internalFormat, 2915 GLint width, GLint border, 2916 GLsizei imageSize, const GLvoid *data, 2917 struct gl_texture_object *texObj, 2918 struct gl_texture_image *texImage) 2919{ 2920 /* this space intentionally left blank */ 2921 (void) ctx; 2922 (void) target; (void) level; 2923 (void) internalFormat; 2924 (void) width; (void) border; 2925 (void) imageSize; (void) data; 2926 (void) texObj; 2927 (void) texImage; 2928} 2929 2930 2931 2932/** 2933 * Fallback for Driver.CompressedTexImage2D() 2934 */ 2935void 2936_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level, 2937 GLint internalFormat, 2938 GLint width, GLint height, GLint border, 2939 GLsizei imageSize, const GLvoid *data, 2940 struct gl_texture_object *texObj, 2941 struct gl_texture_image *texImage) 2942{ 2943 (void) width; (void) height; (void) border; 2944 2945 /* This is pretty simple, basically just do a memcpy without worrying 2946 * about the usual image unpacking or image transfer operations. 2947 */ 2948 ASSERT(texObj); 2949 ASSERT(texImage); 2950 ASSERT(texImage->Width > 0); 2951 ASSERT(texImage->Height > 0); 2952 ASSERT(texImage->Depth == 1); 2953 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */ 2954 2955 choose_texture_format(ctx, texImage, 2, 0, 0, internalFormat); 2956 2957 /* allocate storage */ 2958 texImage->Data = _mesa_alloc_texmemory(imageSize); 2959 if (!texImage->Data) { 2960 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB"); 2961 return; 2962 } 2963 2964 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, 2965 &ctx->Unpack, 2966 "glCompressedTexImage2D"); 2967 if (!data) 2968 return; 2969 2970 /* copy the data */ 2971 ASSERT(texImage->CompressedSize == (GLuint) imageSize); 2972 MEMCPY(texImage->Data, data, imageSize); 2973 2974 /* GL_SGIS_generate_mipmap */ 2975 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 2976 _mesa_generate_mipmap(ctx, target, 2977 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 2978 texObj); 2979 } 2980 2981 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); 2982} 2983 2984 2985 2986/* 2987 * Fallback for Driver.CompressedTexImage3D() 2988 */ 2989void 2990_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level, 2991 GLint internalFormat, 2992 GLint width, GLint height, GLint depth, 2993 GLint border, 2994 GLsizei imageSize, const GLvoid *data, 2995 struct gl_texture_object *texObj, 2996 struct gl_texture_image *texImage) 2997{ 2998 /* this space intentionally left blank */ 2999 (void) ctx; 3000 (void) target; (void) level; 3001 (void) internalFormat; 3002 (void) width; (void) height; (void) depth; 3003 (void) border; 3004 (void) imageSize; (void) data; 3005 (void) texObj; 3006 (void) texImage; 3007} 3008 3009 3010 3011/** 3012 * Fallback for Driver.CompressedTexSubImage1D() 3013 */ 3014void 3015_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target, 3016 GLint level, 3017 GLint xoffset, GLsizei width, 3018 GLenum format, 3019 GLsizei imageSize, const GLvoid *data, 3020 struct gl_texture_object *texObj, 3021 struct gl_texture_image *texImage) 3022{ 3023 /* there are no compressed 1D texture formats yet */ 3024 (void) ctx; 3025 (void) target; (void) level; 3026 (void) xoffset; (void) width; 3027 (void) format; 3028 (void) imageSize; (void) data; 3029 (void) texObj; 3030 (void) texImage; 3031} 3032 3033 3034/** 3035 * Fallback for Driver.CompressedTexSubImage2D() 3036 */ 3037void 3038_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target, 3039 GLint level, 3040 GLint xoffset, GLint yoffset, 3041 GLsizei width, GLsizei height, 3042 GLenum format, 3043 GLsizei imageSize, const GLvoid *data, 3044 struct gl_texture_object *texObj, 3045 struct gl_texture_image *texImage) 3046{ 3047 GLint bytesPerRow, destRowStride, srcRowStride; 3048 GLint i, rows; 3049 GLubyte *dest; 3050 const GLubyte *src; 3051 const GLuint mesaFormat = texImage->TexFormat->MesaFormat; 3052 3053 (void) format; 3054 3055 /* these should have been caught sooner */ 3056 ASSERT((width & 3) == 0 || width == 2 || width == 1); 3057 ASSERT((height & 3) == 0 || height == 2 || height == 1); 3058 ASSERT((xoffset & 3) == 0); 3059 ASSERT((yoffset & 3) == 0); 3060 3061 /* get pointer to src pixels (may be in a pbo which we'll map here) */ 3062 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data, 3063 &ctx->Unpack, 3064 "glCompressedTexSubImage2D"); 3065 if (!data) 3066 return; 3067 3068 srcRowStride = _mesa_compressed_row_stride(mesaFormat, width); 3069 src = (const GLubyte *) data; 3070 3071 destRowStride = _mesa_compressed_row_stride(mesaFormat, texImage->Width); 3072 dest = _mesa_compressed_image_address(xoffset, yoffset, 0, 3073 texImage->TexFormat->MesaFormat, 3074 texImage->Width, 3075 (GLubyte *) texImage->Data); 3076 3077 bytesPerRow = srcRowStride; 3078 rows = height / 4; 3079 3080 for (i = 0; i < rows; i++) { 3081 MEMCPY(dest, src, bytesPerRow); 3082 dest += destRowStride; 3083 src += srcRowStride; 3084 } 3085 3086 /* GL_SGIS_generate_mipmap */ 3087 if (level == texObj->BaseLevel && texObj->GenerateMipmap) { 3088 _mesa_generate_mipmap(ctx, target, 3089 &ctx->Texture.Unit[ctx->Texture.CurrentUnit], 3090 texObj); 3091 } 3092 3093 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack); 3094} 3095 3096 3097/** 3098 * Fallback for Driver.CompressedTexSubImage3D() 3099 */ 3100void 3101_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target, 3102 GLint level, 3103 GLint xoffset, GLint yoffset, GLint zoffset, 3104 GLsizei width, GLsizei height, GLsizei depth, 3105 GLenum format, 3106 GLsizei imageSize, const GLvoid *data, 3107 struct gl_texture_object *texObj, 3108 struct gl_texture_image *texImage) 3109{ 3110 /* there are no compressed 3D texture formats yet */ 3111 (void) ctx; 3112 (void) target; (void) level; 3113 (void) xoffset; (void) yoffset; (void) zoffset; 3114 (void) width; (void) height; (void) depth; 3115 (void) format; 3116 (void) imageSize; (void) data; 3117 (void) texObj; 3118 (void) texImage; 3119} 3120 3121 3122/* 3123 * Average together two rows of a source image to produce a single new 3124 * row in the dest image. It's legal for the two source rows to point 3125 * to the same data. The source width must be equal to either the 3126 * dest width or two times the dest width. 3127 */ 3128static void 3129do_row(const struct gl_texture_format *format, GLint srcWidth, 3130 const GLvoid *srcRowA, const GLvoid *srcRowB, 3131 GLint dstWidth, GLvoid *dstRow) 3132{ 3133 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1; 3134 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2; 3135 3136 /* This assertion is no longer valid with non-power-of-2 textures 3137 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth); 3138 */ 3139 3140 switch (format->MesaFormat) { 3141 case MESA_FORMAT_RGBA: 3142 { 3143 GLuint i, j, k; 3144 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA; 3145 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB; 3146 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow; 3147 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3148 i++, j += colStride, k += colStride) { 3149 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3150 rowB[j][0] + rowB[k][0]) / 4; 3151 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3152 rowB[j][1] + rowB[k][1]) / 4; 3153 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3154 rowB[j][2] + rowB[k][2]) / 4; 3155 dst[i][3] = (rowA[j][3] + rowA[k][3] + 3156 rowB[j][3] + rowB[k][3]) / 4; 3157 } 3158 } 3159 return; 3160 case MESA_FORMAT_RGB: 3161 { 3162 GLuint i, j, k; 3163 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA; 3164 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB; 3165 GLchan (*dst)[3] = (GLchan (*)[3]) 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]) / 4; 3170 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3171 rowB[j][1] + rowB[k][1]) / 4; 3172 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3173 rowB[j][2] + rowB[k][2]) / 4; 3174 } 3175 } 3176 return; 3177 case MESA_FORMAT_ALPHA: 3178 case MESA_FORMAT_LUMINANCE: 3179 case MESA_FORMAT_INTENSITY: 3180 { 3181 GLuint i, j, k; 3182 const GLchan *rowA = (const GLchan *) srcRowA; 3183 const GLchan *rowB = (const GLchan *) srcRowB; 3184 GLchan *dst = (GLchan *) dstRow; 3185 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3186 i++, j += colStride, k += colStride) { 3187 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 3188 } 3189 } 3190 return; 3191 case MESA_FORMAT_LUMINANCE_ALPHA: 3192 { 3193 GLuint i, j, k; 3194 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA; 3195 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB; 3196 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow; 3197 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3198 i++, j += colStride, k += colStride) { 3199 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3200 rowB[j][0] + rowB[k][0]) / 4; 3201 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3202 rowB[j][1] + rowB[k][1]) / 4; 3203 } 3204 } 3205 return; 3206 case MESA_FORMAT_Z32: 3207 { 3208 GLuint i, j, k; 3209 const GLuint *rowA = (const GLuint *) srcRowA; 3210 const GLuint *rowB = (const GLuint *) srcRowB; 3211 GLfloat *dst = (GLfloat *) dstRow; 3212 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3213 i++, j += colStride, k += colStride) { 3214 dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4; 3215 } 3216 } 3217 return; 3218 case MESA_FORMAT_Z16: 3219 { 3220 GLuint i, j, k; 3221 const GLushort *rowA = (const GLushort *) srcRowA; 3222 const GLushort *rowB = (const GLushort *) srcRowB; 3223 GLushort *dst = (GLushort *) dstRow; 3224 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3225 i++, j += colStride, k += colStride) { 3226 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 3227 } 3228 } 3229 return; 3230 /* Begin hardware formats */ 3231 case MESA_FORMAT_RGBA8888: 3232 case MESA_FORMAT_RGBA8888_REV: 3233 case MESA_FORMAT_ARGB8888: 3234 case MESA_FORMAT_ARGB8888_REV: 3235#if FEATURE_EXT_texture_sRGB 3236 case MESA_FORMAT_SRGBA8: 3237#endif 3238 { 3239 GLuint i, j, k; 3240 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA; 3241 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB; 3242 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow; 3243 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3244 i++, j += colStride, k += colStride) { 3245 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3246 rowB[j][0] + rowB[k][0]) / 4; 3247 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3248 rowB[j][1] + rowB[k][1]) / 4; 3249 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3250 rowB[j][2] + rowB[k][2]) / 4; 3251 dst[i][3] = (rowA[j][3] + rowA[k][3] + 3252 rowB[j][3] + rowB[k][3]) / 4; 3253 } 3254 } 3255 return; 3256 case MESA_FORMAT_RGB888: 3257 case MESA_FORMAT_BGR888: 3258#if FEATURE_EXT_texture_sRGB 3259 case MESA_FORMAT_SRGB8: 3260#endif 3261 { 3262 GLuint i, j, k; 3263 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA; 3264 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB; 3265 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow; 3266 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3267 i++, j += colStride, k += colStride) { 3268 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3269 rowB[j][0] + rowB[k][0]) / 4; 3270 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3271 rowB[j][1] + rowB[k][1]) / 4; 3272 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3273 rowB[j][2] + rowB[k][2]) / 4; 3274 } 3275 } 3276 return; 3277 case MESA_FORMAT_RGB565: 3278 case MESA_FORMAT_RGB565_REV: 3279 { 3280 GLuint i, j, k; 3281 const GLushort *rowA = (const GLushort *) srcRowA; 3282 const GLushort *rowB = (const GLushort *) srcRowB; 3283 GLushort *dst = (GLushort *) dstRow; 3284 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3285 i++, j += colStride, k += colStride) { 3286 const GLint rowAr0 = rowA[j] & 0x1f; 3287 const GLint rowAr1 = rowA[k] & 0x1f; 3288 const GLint rowBr0 = rowB[j] & 0x1f; 3289 const GLint rowBr1 = rowB[k] & 0x1f; 3290 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f; 3291 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f; 3292 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f; 3293 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f; 3294 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f; 3295 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f; 3296 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f; 3297 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f; 3298 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 3299 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 3300 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 3301 dst[i] = (blue << 11) | (green << 5) | red; 3302 } 3303 } 3304 return; 3305 case MESA_FORMAT_ARGB4444: 3306 case MESA_FORMAT_ARGB4444_REV: 3307 { 3308 GLuint i, j, k; 3309 const GLushort *rowA = (const GLushort *) srcRowA; 3310 const GLushort *rowB = (const GLushort *) srcRowB; 3311 GLushort *dst = (GLushort *) dstRow; 3312 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3313 i++, j += colStride, k += colStride) { 3314 const GLint rowAr0 = rowA[j] & 0xf; 3315 const GLint rowAr1 = rowA[k] & 0xf; 3316 const GLint rowBr0 = rowB[j] & 0xf; 3317 const GLint rowBr1 = rowB[k] & 0xf; 3318 const GLint rowAg0 = (rowA[j] >> 4) & 0xf; 3319 const GLint rowAg1 = (rowA[k] >> 4) & 0xf; 3320 const GLint rowBg0 = (rowB[j] >> 4) & 0xf; 3321 const GLint rowBg1 = (rowB[k] >> 4) & 0xf; 3322 const GLint rowAb0 = (rowA[j] >> 8) & 0xf; 3323 const GLint rowAb1 = (rowA[k] >> 8) & 0xf; 3324 const GLint rowBb0 = (rowB[j] >> 8) & 0xf; 3325 const GLint rowBb1 = (rowB[k] >> 8) & 0xf; 3326 const GLint rowAa0 = (rowA[j] >> 12) & 0xf; 3327 const GLint rowAa1 = (rowA[k] >> 12) & 0xf; 3328 const GLint rowBa0 = (rowB[j] >> 12) & 0xf; 3329 const GLint rowBa1 = (rowB[k] >> 12) & 0xf; 3330 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 3331 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 3332 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 3333 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 3334 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red; 3335 } 3336 } 3337 return; 3338 case MESA_FORMAT_ARGB1555: 3339 case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */ 3340 { 3341 GLuint i, j, k; 3342 const GLushort *rowA = (const GLushort *) srcRowA; 3343 const GLushort *rowB = (const GLushort *) srcRowB; 3344 GLushort *dst = (GLushort *) dstRow; 3345 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3346 i++, j += colStride, k += colStride) { 3347 const GLint rowAr0 = rowA[j] & 0x1f; 3348 const GLint rowAr1 = rowA[k] & 0x1f; 3349 const GLint rowBr0 = rowB[j] & 0x1f; 3350 const GLint rowBr1 = rowB[k] & 0xf; 3351 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f; 3352 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f; 3353 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f; 3354 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f; 3355 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f; 3356 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f; 3357 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f; 3358 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f; 3359 const GLint rowAa0 = (rowA[j] >> 15) & 0x1; 3360 const GLint rowAa1 = (rowA[k] >> 15) & 0x1; 3361 const GLint rowBa0 = (rowB[j] >> 15) & 0x1; 3362 const GLint rowBa1 = (rowB[k] >> 15) & 0x1; 3363 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 3364 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 3365 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 3366 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2; 3367 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red; 3368 } 3369 } 3370 return; 3371 case MESA_FORMAT_AL88: 3372 case MESA_FORMAT_AL88_REV: 3373#if FEATURE_EXT_texture_sRGB 3374 case MESA_FORMAT_SLA8: 3375#endif 3376 { 3377 GLuint i, j, k; 3378 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA; 3379 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB; 3380 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow; 3381 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3382 i++, j += colStride, k += colStride) { 3383 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3384 rowB[j][0] + rowB[k][0]) >> 2; 3385 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3386 rowB[j][1] + rowB[k][1]) >> 2; 3387 } 3388 } 3389 return; 3390 case MESA_FORMAT_RGB332: 3391 { 3392 GLuint i, j, k; 3393 const GLubyte *rowA = (const GLubyte *) srcRowA; 3394 const GLubyte *rowB = (const GLubyte *) srcRowB; 3395 GLubyte *dst = (GLubyte *) dstRow; 3396 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3397 i++, j += colStride, k += colStride) { 3398 const GLint rowAr0 = rowA[j] & 0x3; 3399 const GLint rowAr1 = rowA[k] & 0x3; 3400 const GLint rowBr0 = rowB[j] & 0x3; 3401 const GLint rowBr1 = rowB[k] & 0x3; 3402 const GLint rowAg0 = (rowA[j] >> 2) & 0x7; 3403 const GLint rowAg1 = (rowA[k] >> 2) & 0x7; 3404 const GLint rowBg0 = (rowB[j] >> 2) & 0x7; 3405 const GLint rowBg1 = (rowB[k] >> 2) & 0x7; 3406 const GLint rowAb0 = (rowA[j] >> 5) & 0x7; 3407 const GLint rowAb1 = (rowA[k] >> 5) & 0x7; 3408 const GLint rowBb0 = (rowB[j] >> 5) & 0x7; 3409 const GLint rowBb1 = (rowB[k] >> 5) & 0x7; 3410 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2; 3411 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2; 3412 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2; 3413 dst[i] = (blue << 5) | (green << 2) | red; 3414 } 3415 } 3416 return; 3417 case MESA_FORMAT_A8: 3418 case MESA_FORMAT_L8: 3419 case MESA_FORMAT_I8: 3420 case MESA_FORMAT_CI8: 3421#if FEATURE_EXT_texture_sRGB 3422 case MESA_FORMAT_SL8: 3423#endif 3424 { 3425 GLuint i, j, k; 3426 const GLubyte *rowA = (const GLubyte *) srcRowA; 3427 const GLubyte *rowB = (const GLubyte *) srcRowB; 3428 GLubyte *dst = (GLubyte *) dstRow; 3429 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3430 i++, j += colStride, k += colStride) { 3431 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2; 3432 } 3433 } 3434 return; 3435 case MESA_FORMAT_RGBA_FLOAT32: 3436 { 3437 GLuint i, j, k; 3438 const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA; 3439 const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB; 3440 GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow; 3441 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3442 i++, j += colStride, k += colStride) { 3443 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3444 rowB[j][0] + rowB[k][0]) * 0.25F; 3445 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3446 rowB[j][1] + rowB[k][1]) * 0.25F; 3447 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3448 rowB[j][2] + rowB[k][2]) * 0.25F; 3449 dst[i][3] = (rowA[j][3] + rowA[k][3] + 3450 rowB[j][3] + rowB[k][3]) * 0.25F; 3451 } 3452 } 3453 return; 3454 case MESA_FORMAT_RGBA_FLOAT16: 3455 { 3456 GLuint i, j, k, comp; 3457 const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA; 3458 const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB; 3459 GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow; 3460 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3461 i++, j += colStride, k += colStride) { 3462 for (comp = 0; comp < 4; comp++) { 3463 GLfloat aj, ak, bj, bk; 3464 aj = _mesa_half_to_float(rowA[j][comp]); 3465 ak = _mesa_half_to_float(rowA[k][comp]); 3466 bj = _mesa_half_to_float(rowB[j][comp]); 3467 bk = _mesa_half_to_float(rowB[k][comp]); 3468 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 3469 } 3470 } 3471 } 3472 return; 3473 case MESA_FORMAT_RGB_FLOAT32: 3474 { 3475 GLuint i, j, k; 3476 const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA; 3477 const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB; 3478 GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow; 3479 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3480 i++, j += colStride, k += colStride) { 3481 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3482 rowB[j][0] + rowB[k][0]) * 0.25F; 3483 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3484 rowB[j][1] + rowB[k][1]) * 0.25F; 3485 dst[i][2] = (rowA[j][2] + rowA[k][2] + 3486 rowB[j][2] + rowB[k][2]) * 0.25F; 3487 } 3488 } 3489 return; 3490 case MESA_FORMAT_RGB_FLOAT16: 3491 { 3492 GLuint i, j, k, comp; 3493 const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA; 3494 const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB; 3495 GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow; 3496 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3497 i++, j += colStride, k += colStride) { 3498 for (comp = 0; comp < 3; comp++) { 3499 GLfloat aj, ak, bj, bk; 3500 aj = _mesa_half_to_float(rowA[j][comp]); 3501 ak = _mesa_half_to_float(rowA[k][comp]); 3502 bj = _mesa_half_to_float(rowB[j][comp]); 3503 bk = _mesa_half_to_float(rowB[k][comp]); 3504 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 3505 } 3506 } 3507 } 3508 return; 3509 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32: 3510 { 3511 GLuint i, j, k; 3512 const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA; 3513 const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB; 3514 GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow; 3515 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3516 i++, j += colStride, k += colStride) { 3517 dst[i][0] = (rowA[j][0] + rowA[k][0] + 3518 rowB[j][0] + rowB[k][0]) * 0.25F; 3519 dst[i][1] = (rowA[j][1] + rowA[k][1] + 3520 rowB[j][1] + rowB[k][1]) * 0.25F; 3521 } 3522 } 3523 return; 3524 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16: 3525 { 3526 GLuint i, j, k, comp; 3527 const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA; 3528 const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB; 3529 GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow; 3530 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3531 i++, j += colStride, k += colStride) { 3532 for (comp = 0; comp < 2; comp++) { 3533 GLfloat aj, ak, bj, bk; 3534 aj = _mesa_half_to_float(rowA[j][comp]); 3535 ak = _mesa_half_to_float(rowA[k][comp]); 3536 bj = _mesa_half_to_float(rowB[j][comp]); 3537 bk = _mesa_half_to_float(rowB[k][comp]); 3538 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 3539 } 3540 } 3541 } 3542 return; 3543 case MESA_FORMAT_ALPHA_FLOAT32: 3544 case MESA_FORMAT_LUMINANCE_FLOAT32: 3545 case MESA_FORMAT_INTENSITY_FLOAT32: 3546 { 3547 GLuint i, j, k; 3548 const GLfloat *rowA = (const GLfloat *) srcRowA; 3549 const GLfloat *rowB = (const GLfloat *) srcRowB; 3550 GLfloat *dst = (GLfloat *) dstRow; 3551 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3552 i++, j += colStride, k += colStride) { 3553 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F; 3554 } 3555 } 3556 return; 3557 case MESA_FORMAT_ALPHA_FLOAT16: 3558 case MESA_FORMAT_LUMINANCE_FLOAT16: 3559 case MESA_FORMAT_INTENSITY_FLOAT16: 3560 { 3561 GLuint i, j, k; 3562 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA; 3563 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB; 3564 GLhalfARB *dst = (GLhalfARB *) dstRow; 3565 for (i = j = 0, k = k0; i < (GLuint) dstWidth; 3566 i++, j += colStride, k += colStride) { 3567 GLfloat aj, ak, bj, bk; 3568 aj = _mesa_half_to_float(rowA[j]); 3569 ak = _mesa_half_to_float(rowA[k]); 3570 bj = _mesa_half_to_float(rowB[j]); 3571 bk = _mesa_half_to_float(rowB[k]); 3572 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F); 3573 } 3574 } 3575 return; 3576 3577 default: 3578 _mesa_problem(NULL, "bad format in do_row()"); 3579 } 3580} 3581 3582 3583/* 3584 * These functions generate a 1/2-size mipmap image from a source image. 3585 * Texture borders are handled by copying or averaging the source image's 3586 * border texels, depending on the scale-down factor. 3587 */ 3588 3589static void 3590make_1d_mipmap(const struct gl_texture_format *format, GLint border, 3591 GLint srcWidth, const GLubyte *srcPtr, 3592 GLint dstWidth, GLubyte *dstPtr) 3593{ 3594 const GLint bpt = format->TexelBytes; 3595 const GLubyte *src; 3596 GLubyte *dst; 3597 3598 /* skip the border pixel, if any */ 3599 src = srcPtr + border * bpt; 3600 dst = dstPtr + border * bpt; 3601 3602 /* we just duplicate the input row, kind of hack, saves code */ 3603 do_row(format, srcWidth - 2 * border, src, src, 3604 dstWidth - 2 * border, dst); 3605 3606 if (border) { 3607 /* copy left-most pixel from source */ 3608 MEMCPY(dstPtr, srcPtr, bpt); 3609 /* copy right-most pixel from source */ 3610 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 3611 srcPtr + (srcWidth - 1) * bpt, 3612 bpt); 3613 } 3614} 3615 3616 3617/** 3618 * XXX need to use the tex image's row stride! 3619 */ 3620static void 3621make_2d_mipmap(const struct gl_texture_format *format, GLint border, 3622 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr, 3623 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr) 3624{ 3625 const GLint bpt = format->TexelBytes; 3626 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 3627 const GLint dstWidthNB = dstWidth - 2 * border; 3628 const GLint dstHeightNB = dstHeight - 2 * border; 3629 const GLint srcRowStride = bpt * srcWidth; 3630 const GLint dstRowStride = bpt * dstWidth; 3631 const GLubyte *srcA, *srcB; 3632 GLubyte *dst; 3633 GLint row; 3634 3635 /* Compute src and dst pointers, skipping any border */ 3636 srcA = srcPtr + border * ((srcWidth + 1) * bpt); 3637 if (srcHeight > 1) 3638 srcB = srcA + srcRowStride; 3639 else 3640 srcB = srcA; 3641 dst = dstPtr + border * ((dstWidth + 1) * bpt); 3642 3643 for (row = 0; row < dstHeightNB; row++) { 3644 do_row(format, srcWidthNB, srcA, srcB, 3645 dstWidthNB, dst); 3646 srcA += 2 * srcRowStride; 3647 srcB += 2 * srcRowStride; 3648 dst += dstRowStride; 3649 } 3650 3651 /* This is ugly but probably won't be used much */ 3652 if (border > 0) { 3653 /* fill in dest border */ 3654 /* lower-left border pixel */ 3655 MEMCPY(dstPtr, srcPtr, bpt); 3656 /* lower-right border pixel */ 3657 MEMCPY(dstPtr + (dstWidth - 1) * bpt, 3658 srcPtr + (srcWidth - 1) * bpt, bpt); 3659 /* upper-left border pixel */ 3660 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt, 3661 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt); 3662 /* upper-right border pixel */ 3663 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt, 3664 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt); 3665 /* lower border */ 3666 do_row(format, srcWidthNB, 3667 srcPtr + bpt, 3668 srcPtr + bpt, 3669 dstWidthNB, dstPtr + bpt); 3670 /* upper border */ 3671 do_row(format, srcWidthNB, 3672 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 3673 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt, 3674 dstWidthNB, 3675 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt); 3676 /* left and right borders */ 3677 if (srcHeight == dstHeight) { 3678 /* copy border pixel from src to dst */ 3679 for (row = 1; row < srcHeight; row++) { 3680 MEMCPY(dstPtr + dstWidth * row * bpt, 3681 srcPtr + srcWidth * row * bpt, bpt); 3682 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt, 3683 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt); 3684 } 3685 } 3686 else { 3687 /* average two src pixels each dest pixel */ 3688 for (row = 0; row < dstHeightNB; row += 2) { 3689 do_row(format, 1, 3690 srcPtr + (srcWidth * (row * 2 + 1)) * bpt, 3691 srcPtr + (srcWidth * (row * 2 + 2)) * bpt, 3692 1, dstPtr + (dstWidth * row + 1) * bpt); 3693 do_row(format, 1, 3694 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt, 3695 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt, 3696 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt); 3697 } 3698 } 3699 } 3700} 3701 3702 3703static void 3704make_3d_mipmap(const struct gl_texture_format *format, GLint border, 3705 GLint srcWidth, GLint srcHeight, GLint srcDepth, 3706 const GLubyte *srcPtr, 3707 GLint dstWidth, GLint dstHeight, GLint dstDepth, 3708 GLubyte *dstPtr) 3709{ 3710 const GLint bpt = format->TexelBytes; 3711 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */ 3712 const GLint srcDepthNB = srcDepth - 2 * border; 3713 const GLint dstWidthNB = dstWidth - 2 * border; 3714 const GLint dstHeightNB = dstHeight - 2 * border; 3715 const GLint dstDepthNB = dstDepth - 2 * border; 3716 GLvoid *tmpRowA, *tmpRowB; 3717 GLint img, row; 3718 GLint bytesPerSrcImage, bytesPerDstImage; 3719 GLint bytesPerSrcRow, bytesPerDstRow; 3720 GLint srcImageOffset, srcRowOffset; 3721 3722 (void) srcDepthNB; /* silence warnings */ 3723 3724 /* Need two temporary row buffers */ 3725 tmpRowA = _mesa_malloc(srcWidth * bpt); 3726 if (!tmpRowA) 3727 return; 3728 tmpRowB = _mesa_malloc(srcWidth * bpt); 3729 if (!tmpRowB) { 3730 _mesa_free(tmpRowA); 3731 return; 3732 } 3733 3734 bytesPerSrcImage = srcWidth * srcHeight * bpt; 3735 bytesPerDstImage = dstWidth * dstHeight * bpt; 3736 3737 bytesPerSrcRow = srcWidth * bpt; 3738 bytesPerDstRow = dstWidth * bpt; 3739 3740 /* Offset between adjacent src images to be averaged together */ 3741 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage; 3742 3743 /* Offset between adjacent src rows to be averaged together */ 3744 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt; 3745 3746 /* 3747 * Need to average together up to 8 src pixels for each dest pixel. 3748 * Break that down into 3 operations: 3749 * 1. take two rows from source image and average them together. 3750 * 2. take two rows from next source image and average them together. 3751 * 3. take the two averaged rows and average them for the final dst row. 3752 */ 3753 3754 /* 3755 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n", 3756 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth); 3757 */ 3758 3759 for (img = 0; img < dstDepthNB; img++) { 3760 /* first source image pointer, skipping border */ 3761 const GLubyte *imgSrcA = srcPtr 3762 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border 3763 + img * (bytesPerSrcImage + srcImageOffset); 3764 /* second source image pointer, skipping border */ 3765 const GLubyte *imgSrcB = imgSrcA + srcImageOffset; 3766 /* address of the dest image, skipping border */ 3767 GLubyte *imgDst = dstPtr 3768 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border 3769 + img * bytesPerDstImage; 3770 3771 /* setup the four source row pointers and the dest row pointer */ 3772 const GLubyte *srcImgARowA = imgSrcA; 3773 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset; 3774 const GLubyte *srcImgBRowA = imgSrcB; 3775 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset; 3776 GLubyte *dstImgRow = imgDst; 3777 3778 for (row = 0; row < dstHeightNB; row++) { 3779 /* Average together two rows from first src image */ 3780 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB, 3781 srcWidthNB, tmpRowA); 3782 /* Average together two rows from second src image */ 3783 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB, 3784 srcWidthNB, tmpRowB); 3785 /* Average together the temp rows to make the final row */ 3786 do_row(format, srcWidthNB, tmpRowA, tmpRowB, 3787 dstWidthNB, dstImgRow); 3788 /* advance to next rows */ 3789 srcImgARowA += bytesPerSrcRow + srcRowOffset; 3790 srcImgARowB += bytesPerSrcRow + srcRowOffset; 3791 srcImgBRowA += bytesPerSrcRow + srcRowOffset; 3792 srcImgBRowB += bytesPerSrcRow + srcRowOffset; 3793 dstImgRow += bytesPerDstRow; 3794 } 3795 } 3796 3797 _mesa_free(tmpRowA); 3798 _mesa_free(tmpRowB); 3799 3800 /* Luckily we can leverage the make_2d_mipmap() function here! */ 3801 if (border > 0) { 3802 /* do front border image */ 3803 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr, 3804 dstWidth, dstHeight, dstPtr); 3805 /* do back border image */ 3806 make_2d_mipmap(format, 1, srcWidth, srcHeight, 3807 srcPtr + bytesPerSrcImage * (srcDepth - 1), 3808 dstWidth, dstHeight, 3809 dstPtr + bytesPerDstImage * (dstDepth - 1)); 3810 /* do four remaining border edges that span the image slices */ 3811 if (srcDepth == dstDepth) { 3812 /* just copy border pixels from src to dst */ 3813 for (img = 0; img < dstDepthNB; img++) { 3814 const GLubyte *src; 3815 GLubyte *dst; 3816 3817 /* do border along [img][row=0][col=0] */ 3818 src = srcPtr + (img + 1) * bytesPerSrcImage; 3819 dst = dstPtr + (img + 1) * bytesPerDstImage; 3820 MEMCPY(dst, src, bpt); 3821 3822 /* do border along [img][row=dstHeight-1][col=0] */ 3823 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3824 + (srcHeight - 1) * bytesPerSrcRow; 3825 dst = dstPtr + (img + 1) * bytesPerDstImage 3826 + (dstHeight - 1) * bytesPerDstRow; 3827 MEMCPY(dst, src, bpt); 3828 3829 /* do border along [img][row=0][col=dstWidth-1] */ 3830 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3831 + (srcWidth - 1) * bpt; 3832 dst = dstPtr + (img + 1) * bytesPerDstImage 3833 + (dstWidth - 1) * bpt; 3834 MEMCPY(dst, src, bpt); 3835 3836 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 3837 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3838 + (bytesPerSrcImage - bpt); 3839 dst = dstPtr + (img + 1) * bytesPerDstImage 3840 + (bytesPerDstImage - bpt); 3841 MEMCPY(dst, src, bpt); 3842 } 3843 } 3844 else { 3845 /* average border pixels from adjacent src image pairs */ 3846 ASSERT(srcDepthNB == 2 * dstDepthNB); 3847 for (img = 0; img < dstDepthNB; img++) { 3848 const GLubyte *src; 3849 GLubyte *dst; 3850 3851 /* do border along [img][row=0][col=0] */ 3852 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage; 3853 dst = dstPtr + (img + 1) * bytesPerDstImage; 3854 do_row(format, 1, src, src + srcImageOffset, 1, dst); 3855 3856 /* do border along [img][row=dstHeight-1][col=0] */ 3857 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3858 + (srcHeight - 1) * bytesPerSrcRow; 3859 dst = dstPtr + (img + 1) * bytesPerDstImage 3860 + (dstHeight - 1) * bytesPerDstRow; 3861 do_row(format, 1, src, src + srcImageOffset, 1, dst); 3862 3863 /* do border along [img][row=0][col=dstWidth-1] */ 3864 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3865 + (srcWidth - 1) * bpt; 3866 dst = dstPtr + (img + 1) * bytesPerDstImage 3867 + (dstWidth - 1) * bpt; 3868 do_row(format, 1, src, src + srcImageOffset, 1, dst); 3869 3870 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */ 3871 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage 3872 + (bytesPerSrcImage - bpt); 3873 dst = dstPtr + (img + 1) * bytesPerDstImage 3874 + (bytesPerDstImage - bpt); 3875 do_row(format, 1, src, src + srcImageOffset, 1, dst); 3876 } 3877 } 3878 } 3879} 3880 3881 3882/** 3883 * For GL_SGIX_generate_mipmap: 3884 * Generate a complete set of mipmaps from texObj's base-level image. 3885 * Stop at texObj's MaxLevel or when we get to the 1x1 texture. 3886 */ 3887void 3888_mesa_generate_mipmap(GLcontext *ctx, GLenum target, 3889 const struct gl_texture_unit *texUnit, 3890 struct gl_texture_object *texObj) 3891{ 3892 const struct gl_texture_image *srcImage; 3893 const struct gl_texture_format *convertFormat; 3894 const GLubyte *srcData = NULL; 3895 GLubyte *dstData = NULL; 3896 GLint level, maxLevels; 3897 3898 ASSERT(texObj); 3899 /* XXX choose cube map face here??? */ 3900 srcImage = texObj->Image[0][texObj->BaseLevel]; 3901 ASSERT(srcImage); 3902 3903 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target); 3904 ASSERT(maxLevels > 0); /* bad target */ 3905 3906 /* Find convertFormat - the format that do_row() will process */ 3907 if (srcImage->IsCompressed) { 3908 /* setup for compressed textures */ 3909 GLuint row; 3910 GLint components, size; 3911 GLchan *dst; 3912 3913 assert(texObj->Target == GL_TEXTURE_2D); 3914 3915 if (srcImage->_BaseFormat == GL_RGB) { 3916 convertFormat = &_mesa_texformat_rgb; 3917 components = 3; 3918 } 3919 else if (srcImage->_BaseFormat == GL_RGBA) { 3920 convertFormat = &_mesa_texformat_rgba; 3921 components = 4; 3922 } 3923 else { 3924 _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); 3925 return; 3926 } 3927 3928 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */ 3929 size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE) 3930 * srcImage->Width * srcImage->Height * srcImage->Depth + 20; 3931 /* 20 extra bytes, just be safe when calling last FetchTexel */ 3932 srcData = (GLubyte *) _mesa_malloc(size); 3933 if (!srcData) { 3934 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 3935 return; 3936 } 3937 dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */ 3938 if (!dstData) { 3939 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps"); 3940 _mesa_free((void *) srcData); 3941 return; 3942 } 3943 3944 /* decompress base image here */ 3945 dst = (GLchan *) srcData; 3946 for (row = 0; row < srcImage->Height; row++) { 3947 GLuint col; 3948 for (col = 0; col < srcImage->Width; col++) { 3949 srcImage->FetchTexelc(srcImage, col, row, 0, dst); 3950 dst += components; 3951 } 3952 } 3953 } 3954 else { 3955 /* uncompressed */ 3956 convertFormat = srcImage->TexFormat; 3957 } 3958 3959 for (level = texObj->BaseLevel; level < texObj->MaxLevel 3960 && level < maxLevels - 1; level++) { 3961 /* generate image[level+1] from image[level] */ 3962 const struct gl_texture_image *srcImage; 3963 struct gl_texture_image *dstImage; 3964 GLint srcWidth, srcHeight, srcDepth; 3965 GLint dstWidth, dstHeight, dstDepth; 3966 GLint border, bytesPerTexel; 3967 3968 /* get src image parameters */ 3969 srcImage = _mesa_select_tex_image(ctx, texUnit, target, level); 3970 ASSERT(srcImage); 3971 srcWidth = srcImage->Width; 3972 srcHeight = srcImage->Height; 3973 srcDepth = srcImage->Depth; 3974 border = srcImage->Border; 3975 3976 /* compute next (level+1) image size */ 3977 if (srcWidth - 2 * border > 1) { 3978 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border; 3979 } 3980 else { 3981 dstWidth = srcWidth; /* can't go smaller */ 3982 } 3983 if (srcHeight - 2 * border > 1) { 3984 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border; 3985 } 3986 else { 3987 dstHeight = srcHeight; /* can't go smaller */ 3988 } 3989 if (srcDepth - 2 * border > 1) { 3990 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border; 3991 } 3992 else { 3993 dstDepth = srcDepth; /* can't go smaller */ 3994 } 3995 3996 if (dstWidth == srcWidth && 3997 dstHeight == srcHeight && 3998 dstDepth == srcDepth) { 3999 /* all done */ 4000 if (srcImage->IsCompressed) { 4001 _mesa_free((void *) srcData); 4002 _mesa_free(dstData); 4003 } 4004 return; 4005 } 4006 4007 /* get dest gl_texture_image */ 4008 dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1); 4009 if (!dstImage) { 4010 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 4011 return; 4012 } 4013 4014 /* Free old image data */ 4015 if (dstImage->Data) 4016 ctx->Driver.FreeTexImageData(ctx, dstImage); 4017 4018 /* initialize new image */ 4019 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight, 4020 dstDepth, border, srcImage->InternalFormat); 4021 dstImage->DriverData = NULL; 4022 dstImage->TexFormat = srcImage->TexFormat; 4023 dstImage->FetchTexelc = srcImage->FetchTexelc; 4024 dstImage->FetchTexelf = srcImage->FetchTexelf; 4025 dstImage->IsCompressed = srcImage->IsCompressed; 4026 if (dstImage->IsCompressed) { 4027 dstImage->CompressedSize 4028 = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width, 4029 dstImage->Height, 4030 dstImage->Depth, 4031 dstImage->TexFormat->MesaFormat); 4032 ASSERT(dstImage->CompressedSize > 0); 4033 } 4034 4035 ASSERT(dstImage->TexFormat); 4036 ASSERT(dstImage->FetchTexelc); 4037 ASSERT(dstImage->FetchTexelf); 4038 4039 /* Alloc new teximage data buffer. 4040 * Setup src and dest data pointers. 4041 */ 4042 if (dstImage->IsCompressed) { 4043 dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize); 4044 if (!dstImage->Data) { 4045 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 4046 return; 4047 } 4048 /* srcData and dstData are already set */ 4049 ASSERT(srcData); 4050 ASSERT(dstData); 4051 } 4052 else { 4053 bytesPerTexel = dstImage->TexFormat->TexelBytes; 4054 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0); 4055 dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight 4056 * dstDepth * bytesPerTexel); 4057 if (!dstImage->Data) { 4058 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps"); 4059 return; 4060 } 4061 srcData = (const GLubyte *) srcImage->Data; 4062 dstData = (GLubyte *) dstImage->Data; 4063 } 4064 4065 /* 4066 * We use simple 2x2 averaging to compute the next mipmap level. 4067 */ 4068 switch (target) { 4069 case GL_TEXTURE_1D: 4070 make_1d_mipmap(convertFormat, border, 4071 srcWidth, srcData, 4072 dstWidth, dstData); 4073 break; 4074 case GL_TEXTURE_2D: 4075 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 4076 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 4077 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 4078 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 4079 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 4080 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 4081 make_2d_mipmap(convertFormat, border, 4082 srcWidth, srcHeight, srcData, 4083 dstWidth, dstHeight, dstData); 4084 break; 4085 case GL_TEXTURE_3D: 4086 make_3d_mipmap(convertFormat, border, 4087 srcWidth, srcHeight, srcDepth, srcData, 4088 dstWidth, dstHeight, dstDepth, dstData); 4089 break; 4090 case GL_TEXTURE_RECTANGLE_NV: 4091 /* no mipmaps, do nothing */ 4092 break; 4093 default: 4094 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps"); 4095 return; 4096 } 4097 4098 if (dstImage->IsCompressed) { 4099 GLubyte *temp; 4100 /* compress image from dstData into dstImage->Data */ 4101 const GLenum srcFormat = convertFormat->BaseFormat; 4102 GLint dstRowStride 4103 = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth); 4104 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA); 4105 dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat, 4106 dstImage->TexFormat, 4107 dstImage->Data, 4108 0, 0, 0, /* dstX/Y/Zoffset */ 4109 dstRowStride, 0, /* strides */ 4110 dstWidth, dstHeight, 1, /* size */ 4111 srcFormat, CHAN_TYPE, 4112 dstData, /* src data, actually */ 4113 &ctx->DefaultPacking); 4114 /* swap src and dest pointers */ 4115 temp = (GLubyte *) srcData; 4116 srcData = dstData; 4117 dstData = temp; 4118 } 4119 4120 } /* loop over mipmap levels */ 4121} 4122 4123 4124/** 4125 * Helper function for drivers which need to rescale texture images to 4126 * certain aspect ratios. 4127 * Nearest filtering only (for broken hardware that can't support 4128 * all aspect ratios). This can be made a lot faster, but I don't 4129 * really care enough... 4130 */ 4131void 4132_mesa_rescale_teximage2d (GLuint bytesPerPixel, 4133 GLuint srcStrideInPixels, 4134 GLuint dstRowStride, 4135 GLint srcWidth, GLint srcHeight, 4136 GLint dstWidth, GLint dstHeight, 4137 const GLvoid *srcImage, GLvoid *dstImage) 4138{ 4139 GLint row, col; 4140 4141#define INNER_LOOP( TYPE, HOP, WOP ) \ 4142 for ( row = 0 ; row < dstHeight ; row++ ) { \ 4143 GLint srcRow = row HOP hScale; \ 4144 for ( col = 0 ; col < dstWidth ; col++ ) { \ 4145 GLint srcCol = col WOP wScale; \ 4146 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \ 4147 } \ 4148 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \ 4149 } \ 4150 4151#define RESCALE_IMAGE( TYPE ) \ 4152do { \ 4153 const TYPE *src = (const TYPE *)srcImage; \ 4154 TYPE *dst = (TYPE *)dstImage; \ 4155 \ 4156 if ( srcHeight < dstHeight ) { \ 4157 const GLint hScale = dstHeight / srcHeight; \ 4158 if ( srcWidth < dstWidth ) { \ 4159 const GLint wScale = dstWidth / srcWidth; \ 4160 INNER_LOOP( TYPE, /, / ); \ 4161 } \ 4162 else { \ 4163 const GLint wScale = srcWidth / dstWidth; \ 4164 INNER_LOOP( TYPE, /, * ); \ 4165 } \ 4166 } \ 4167 else { \ 4168 const GLint hScale = srcHeight / dstHeight; \ 4169 if ( srcWidth < dstWidth ) { \ 4170 const GLint wScale = dstWidth / srcWidth; \ 4171 INNER_LOOP( TYPE, *, / ); \ 4172 } \ 4173 else { \ 4174 const GLint wScale = srcWidth / dstWidth; \ 4175 INNER_LOOP( TYPE, *, * ); \ 4176 } \ 4177 } \ 4178} while (0) 4179 4180 switch ( bytesPerPixel ) { 4181 case 4: 4182 RESCALE_IMAGE( GLuint ); 4183 break; 4184 4185 case 2: 4186 RESCALE_IMAGE( GLushort ); 4187 break; 4188 4189 case 1: 4190 RESCALE_IMAGE( GLubyte ); 4191 break; 4192 default: 4193 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d"); 4194 } 4195} 4196 4197 4198/** 4199 * Upscale an image by replication, not (typical) stretching. 4200 * We use this when the image width or height is less than a 4201 * certain size (4, 8) and we need to upscale an image. 4202 */ 4203void 4204_mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight, 4205 GLsizei outWidth, GLsizei outHeight, 4206 GLint comps, const GLchan *src, GLint srcRowStride, 4207 GLchan *dest ) 4208{ 4209 GLint i, j, k; 4210 4211 ASSERT(outWidth >= inWidth); 4212 ASSERT(outHeight >= inHeight); 4213#if 0 4214 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2); 4215 ASSERT((outWidth & 3) == 0); 4216 ASSERT((outHeight & 3) == 0); 4217#endif 4218 4219 for (i = 0; i < outHeight; i++) { 4220 const GLint ii = i % inHeight; 4221 for (j = 0; j < outWidth; j++) { 4222 const GLint jj = j % inWidth; 4223 for (k = 0; k < comps; k++) { 4224 dest[(i * outWidth + j) * comps + k] 4225 = src[ii * srcRowStride + jj * comps + k]; 4226 } 4227 } 4228 } 4229} 4230 4231 4232#if FEATURE_EXT_texture_sRGB 4233 4234/** 4235 * Test if given texture image is an sRGB format. 4236 */ 4237static GLboolean 4238is_srgb_teximage(const struct gl_texture_image *texImage) 4239{ 4240 switch (texImage->TexFormat->MesaFormat) { 4241 case MESA_FORMAT_SRGB8: 4242 case MESA_FORMAT_SRGBA8: 4243 case MESA_FORMAT_SL8: 4244 case MESA_FORMAT_SLA8: 4245 return GL_TRUE; 4246 default: 4247 return GL_FALSE; 4248 } 4249} 4250 4251#endif /* FEATURE_EXT_texture_sRGB */ 4252 4253 4254/** 4255 * This is the software fallback for Driver.GetTexImage(). 4256 * All error checking will have been done before this routine is called. 4257 */ 4258void 4259_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, 4260 GLenum format, GLenum type, GLvoid *pixels, 4261 struct gl_texture_object *texObj, 4262 struct gl_texture_image *texImage) 4263{ 4264 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 4265 4266 if (ctx->Pack.BufferObj->Name) { 4267 /* Packing texture image into a PBO. 4268 * Map the (potentially) VRAM-based buffer into our process space so 4269 * we can write into it with the code below. 4270 * A hardware driver might use a sophisticated blit to move the 4271 * texture data to the PBO if the PBO is in VRAM along with the texture. 4272 */ 4273 GLubyte *buf = (GLubyte *) 4274 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 4275 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 4276 if (!buf) { 4277 /* buffer is already mapped - that's an error */ 4278 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)"); 4279 return; 4280 } 4281 /* <pixels> was an offset into the PBO. 4282 * Now make it a real, client-side pointer inside the mapped region. 4283 */ 4284 pixels = ADD_POINTERS(buf, pixels); 4285 } 4286 else if (!pixels) { 4287 /* not an error */ 4288 return; 4289 } 4290 4291 { 4292 const GLint width = texImage->Width; 4293 const GLint height = texImage->Height; 4294 const GLint depth = texImage->Depth; 4295 GLint img, row; 4296 for (img = 0; img < depth; img++) { 4297 for (row = 0; row < height; row++) { 4298 /* compute destination address in client memory */ 4299 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels, 4300 width, height, format, type, 4301 img, row, 0); 4302 assert(dest); 4303 4304 if (format == GL_COLOR_INDEX) { 4305 GLuint indexRow[MAX_WIDTH]; 4306 GLint col; 4307 /* Can't use FetchTexel here because that returns RGBA */ 4308 if (texImage->TexFormat->IndexBits == 8) { 4309 const GLubyte *src = (const GLubyte *) texImage->Data; 4310 src += width * (img * texImage->Height + row); 4311 for (col = 0; col < width; col++) { 4312 indexRow[col] = src[col]; 4313 } 4314 } 4315 else if (texImage->TexFormat->IndexBits == 16) { 4316 const GLushort *src = (const GLushort *) texImage->Data; 4317 src += width * (img * texImage->Height + row); 4318 for (col = 0; col < width; col++) { 4319 indexRow[col] = src[col]; 4320 } 4321 } 4322 else { 4323 _mesa_problem(ctx, 4324 "Color index problem in _mesa_GetTexImage"); 4325 } 4326 _mesa_pack_index_span(ctx, width, type, dest, 4327 indexRow, &ctx->Pack, 4328 0 /* no image transfer */); 4329 } 4330 else if (format == GL_DEPTH_COMPONENT) { 4331 GLfloat depthRow[MAX_WIDTH]; 4332 GLint col; 4333 for (col = 0; col < width; col++) { 4334 (*texImage->FetchTexelf)(texImage, col, row, img, 4335 depthRow + col); 4336 } 4337 _mesa_pack_depth_span(ctx, width, dest, type, 4338 depthRow, &ctx->Pack); 4339 } 4340 else if (format == GL_DEPTH_STENCIL_EXT) { 4341 /* XXX Note: we're bypassing texImage->FetchTexel()! */ 4342 const GLuint *src = (const GLuint *) texImage->Data; 4343 src += width * row + width * height * img; 4344 _mesa_memcpy(dest, src, width * sizeof(GLuint)); 4345 if (ctx->Pack.SwapBytes) { 4346 _mesa_swap4((GLuint *) dest, width); 4347 } 4348 } 4349 else if (format == GL_YCBCR_MESA) { 4350 /* No pixel transfer */ 4351 const GLint rowstride = texImage->RowStride; 4352 MEMCPY(dest, 4353 (const GLushort *) texImage->Data + row * rowstride, 4354 width * sizeof(GLushort)); 4355 /* check for byte swapping */ 4356 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR 4357 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 4358 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV 4359 && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 4360 if (!ctx->Pack.SwapBytes) 4361 _mesa_swap2((GLushort *) dest, width); 4362 } 4363 else if (ctx->Pack.SwapBytes) { 4364 _mesa_swap2((GLushort *) dest, width); 4365 } 4366 } 4367#if FEATURE_EXT_texture_sRGB 4368 else if (is_srgb_teximage(texImage)) { 4369 /* no pixel transfer and no non-linear to linear conversion */ 4370 const GLint comps = texImage->TexFormat->TexelBytes; 4371 const GLint rowstride = comps * texImage->RowStride; 4372 MEMCPY(dest, 4373 (const GLubyte *) texImage->Data + row * rowstride, 4374 comps * width * sizeof(GLubyte)); 4375 } 4376#endif /* FEATURE_EXT_texture_sRGB */ 4377 else { 4378 /* general case: convert row to RGBA format */ 4379 GLfloat rgba[MAX_WIDTH][4]; 4380 GLint col; 4381 for (col = 0; col < width; col++) { 4382 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); 4383 } 4384 _mesa_pack_rgba_span_float(ctx, width, 4385 (const GLfloat (*)[4]) rgba, 4386 format, type, dest, &ctx->Pack, 4387 0 /* no image transfer */); 4388 } /* format */ 4389 } /* row */ 4390 } /* img */ 4391 } 4392 4393 if (ctx->Pack.BufferObj->Name) { 4394 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 4395 ctx->Pack.BufferObj); 4396 } 4397} 4398 4399 4400 4401/** 4402 * This is the software fallback for Driver.GetCompressedTexImage(). 4403 * All error checking will have been done before this routine is called. 4404 */ 4405void 4406_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, 4407 GLvoid *img, 4408 const struct gl_texture_object *texObj, 4409 const struct gl_texture_image *texImage) 4410{ 4411 GLuint size; 4412 4413 if (ctx->Pack.BufferObj->Name) { 4414 /* pack texture image into a PBO */ 4415 GLubyte *buf; 4416 if ((const GLubyte *) img + texImage->CompressedSize > 4417 (const GLubyte *) ctx->Pack.BufferObj->Size) { 4418 _mesa_error(ctx, GL_INVALID_OPERATION, 4419 "glGetCompressedTexImage(invalid PBO access)"); 4420 return; 4421 } 4422 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 4423 GL_WRITE_ONLY_ARB, 4424 ctx->Pack.BufferObj); 4425 if (!buf) { 4426 /* buffer is already mapped - that's an error */ 4427 _mesa_error(ctx, GL_INVALID_OPERATION, 4428 "glGetCompressedTexImage(PBO is mapped)"); 4429 return; 4430 } 4431 img = ADD_POINTERS(buf, img); 4432 } 4433 else if (!img) { 4434 /* not an error */ 4435 return; 4436 } 4437 4438 /* don't use texImage->CompressedSize since that may be padded out */ 4439 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height, 4440 texImage->Depth, 4441 texImage->TexFormat->MesaFormat); 4442 4443 /* just memcpy, no pixelstore or pixel transfer */ 4444 _mesa_memcpy(img, texImage->Data, size); 4445 4446 if (ctx->Pack.BufferObj->Name) { 4447 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 4448 ctx->Pack.BufferObj); 4449 } 4450} 4451