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