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