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