home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / texstore.cpp < prev    next >
C/C++ Source or Header  |  2002-12-08  |  85KB  |  2,119 lines

  1. /* $Id: texstore.c,v 1.49 2002/12/03 00:05:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  * Authors:
  29.  *   Brian Paul
  30.  */
  31.  
  32. /*
  33.  * The GL texture image functions in teximage.c basically just do
  34.  * error checking and data structure allocation.  They in turn call
  35.  * device driver functions which actually copy/convert/store the user's
  36.  * texture image data.
  37.  *
  38.  * However, most device drivers will be able to use the fallback functions
  39.  * in this file.  That is, most drivers will have the following bit of
  40.  * code:
  41.  *   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
  42.  *   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
  43.  *   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
  44.  *   etc...
  45.  *
  46.  * Texture image processing is actually kind of complicated.  We have to do:
  47.  *    Format/type conversions
  48.  *    pixel unpacking
  49.  *    pixel transfer (scale, bais, lookup, convolution!, etc)
  50.  *
  51.  * These functions can handle most everything, including processing full
  52.  * images and sub-images.
  53.  */
  54.  
  55.  
  56. #include "glheader.h"
  57. #include "colormac.h"
  58. #include "context.h"
  59. #include "convolve.h"
  60. #include "image.h"
  61. #include "macros.h"
  62. #include "imports.h"
  63. #include "texcompress.h"
  64. #include "texformat.h"
  65. #include "teximage.h"
  66. #include "texstore.h"
  67. #include "texutil.h"
  68.  
  69.  
  70. /*
  71.  * Given an internal texture format enum or 1, 2, 3, 4 return the
  72.  * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
  73.  * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
  74.  * number of components for the format.  Return -1 if invalid enum.
  75.  */
  76. static GLint
  77. components_in_intformat( GLint format )
  78. {
  79.    switch (format) {
  80.       case GL_ALPHA:
  81.       case GL_ALPHA4:
  82.       case GL_ALPHA8:
  83.       case GL_ALPHA12:
  84.       case GL_ALPHA16:
  85.          return 1;
  86.       case 1:
  87.       case GL_LUMINANCE:
  88.       case GL_LUMINANCE4:
  89.       case GL_LUMINANCE8:
  90.       case GL_LUMINANCE12:
  91.       case GL_LUMINANCE16:
  92.          return 1;
  93.       case 2:
  94.       case GL_LUMINANCE_ALPHA:
  95.       case GL_LUMINANCE4_ALPHA4:
  96.       case GL_LUMINANCE6_ALPHA2:
  97.       case GL_LUMINANCE8_ALPHA8:
  98.       case GL_LUMINANCE12_ALPHA4:
  99.       case GL_LUMINANCE12_ALPHA12:
  100.       case GL_LUMINANCE16_ALPHA16:
  101.          return 2;
  102.       case GL_INTENSITY:
  103.       case GL_INTENSITY4:
  104.       case GL_INTENSITY8:
  105.       case GL_INTENSITY12:
  106.       case GL_INTENSITY16:
  107.          return 1;
  108.       case 3:
  109.       case GL_RGB:
  110.       case GL_R3_G3_B2:
  111.       case GL_RGB4:
  112.       case GL_RGB5:
  113.       case GL_RGB8:
  114.       case GL_RGB10:
  115.       case GL_RGB12:
  116.       case GL_RGB16:
  117.          return 3;
  118.       case 4:
  119.       case GL_RGBA:
  120.       case GL_RGBA2:
  121.       case GL_RGBA4:
  122.       case GL_RGB5_A1:
  123.       case GL_RGBA8:
  124.       case GL_RGB10_A2:
  125.       case GL_RGBA12:
  126.       case GL_RGBA16:
  127.          return 4;
  128.       case GL_COLOR_INDEX:
  129.       case GL_COLOR_INDEX1_EXT:
  130.       case GL_COLOR_INDEX2_EXT:
  131.       case GL_COLOR_INDEX4_EXT:
  132.       case GL_COLOR_INDEX8_EXT:
  133.       case GL_COLOR_INDEX12_EXT:
  134.       case GL_COLOR_INDEX16_EXT:
  135.          return 1;
  136.       case GL_DEPTH_COMPONENT:
  137.       case GL_DEPTH_COMPONENT16_SGIX:
  138.       case GL_DEPTH_COMPONENT24_SGIX:
  139.       case GL_DEPTH_COMPONENT32_SGIX:
  140.          return 1;
  141.       case GL_YCBCR_MESA:
  142.          return 2; /* Y + (Cb or Cr) */
  143.       default:
  144.          return -1;  /* error */
  145.    }
  146. }
  147.  
  148.  
  149. /*
  150.  * This function is used to transfer the user's image data into a texture
  151.  * image buffer.  We handle both full texture images and subtexture images.
  152.  * We also take care of all image transfer operations here, including
  153.  * convolution, scale/bias, colortables, etc.
  154.  *
  155.  * The destination texel type is always GLchan.
  156.  * The destination texel format is one of the 6 basic types.
  157.  *
  158.  * A hardware driver may use this as a helper routine to unpack and
  159.  * apply pixel transfer ops into a temporary image buffer.  Then,
  160.  * convert the temporary image into the special hardware format.
  161.  *
  162.  * Input:
  163.  *   dimensions - 1, 2, or 3
  164.  *   texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
  165.  *                   GL_RGB or GL_RGBA (the destination format)
  166.  *   texDestAddr - destination image address
  167.  *   srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
  168.  *   dstXoffset, dstYoffset, dstZoffset - position to store the image within
  169.  *      the destination 3D texture
  170.  *   dstRowStride, dstImageStride - dest image strides in bytes
  171.  *   srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
  172.  *   srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
  173.  *   srcPacking - describes packing of incoming image.
  174.  *   transferOps - mask of pixel transfer operations
  175.  */
  176. static void
  177. transfer_teximage(GLcontext *ctx, GLuint dimensions,
  178.                   GLenum texDestFormat, GLvoid *texDestAddr,
  179.                   GLint srcWidth, GLint srcHeight, GLint srcDepth,
  180.                   GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
  181.                   GLint dstRowStride, GLint dstImageStride,
  182.                   GLenum srcFormat, GLenum srcType,
  183.                   const GLvoid *srcAddr,
  184.                   const struct gl_pixelstore_attrib *srcPacking,
  185.                   GLuint transferOps)
  186. {
  187.    GLint texComponents;
  188.  
  189.    ASSERT(ctx);
  190.    ASSERT(dimensions >= 1 && dimensions <= 3);
  191.    ASSERT(texDestFormat == GL_LUMINANCE ||
  192.           texDestFormat == GL_INTENSITY ||
  193.           texDestFormat == GL_LUMINANCE_ALPHA ||
  194.           texDestFormat == GL_ALPHA ||
  195.           texDestFormat == GL_RGB ||
  196.           texDestFormat == GL_RGBA ||
  197.           texDestFormat == GL_DEPTH_COMPONENT);
  198.    ASSERT(texDestAddr);
  199.    ASSERT(srcWidth >= 1);
  200.    ASSERT(srcHeight >= 1);
  201.    ASSERT(srcDepth >= 1);
  202.    ASSERT(dstXoffset >= 0);
  203.    ASSERT(dstYoffset >= 0);
  204.    ASSERT(dstZoffset >= 0);
  205.    ASSERT(dstRowStride >= 0);
  206.    ASSERT(dstImageStride >= 0);
  207.    ASSERT(srcAddr);
  208.    ASSERT(srcPacking);
  209.  
  210.    texComponents = components_in_intformat(texDestFormat);
  211.  
  212.    /* try common 2D texture cases first */
  213.    if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
  214.  
  215.       if (srcFormat == texDestFormat) {
  216.          /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
  217.           * GL_LUMINANCE_ALPHA, etc. texture formats.  Use memcpy().
  218.           */
  219.          const GLchan *src = (const GLchan *) _mesa_image_address(
  220.                                    srcPacking, srcAddr, srcWidth, srcHeight,
  221.                                    srcFormat, srcType, 0, 0, 0);
  222.          const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
  223.                                                srcWidth, srcFormat, srcType);
  224.          const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
  225.          GLchan *dst = (GLchan *) texDestAddr
  226.                      + dstYoffset * (dstRowStride / sizeof(GLchan))
  227.                      + dstXoffset * texComponents;
  228.          if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
  229.             MEMCPY(dst, src, srcHeight * widthInBytes);
  230.          }
  231.          else {
  232.             GLint i;
  233.             for (i = 0; i < srcHeight; i++) {
  234.                MEMCPY(dst, src, widthInBytes);
  235.                src += (srcRowStride / sizeof(GLchan));
  236.                dst += (dstRowStride / sizeof(GLchan));
  237.             }
  238.          }
  239.          return;  /* all done */
  240.       }
  241.       else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
  242.          /* commonly used by Quake */
  243.          const GLchan *src = (const GLchan *) _mesa_image_address(
  244.                                    srcPacking, srcAddr, srcWidth, srcHeight,
  245.                                    srcFormat, srcType, 0, 0, 0);
  246.          const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
  247.                                                srcWidth, srcFormat, srcType);
  248.          GLchan *dst = (GLchan *) texDestAddr
  249.                      + dstYoffset * (dstRowStride / sizeof(GLchan))
  250.                      + dstXoffset * texComponents;
  251.          GLint i, j;
  252.          for (i = 0; i < srcHeight; i++) {
  253.             const GLchan *s = src;
  254.             GLchan *d = dst;
  255.             for (j = 0; j < srcWidth; j++) {
  256.                *d++ = *s++;  /*red*/
  257.                *d++ = *s++;  /*green*/
  258.                *d++ = *s++;  /*blue*/
  259.                s++;          /*alpha*/
  260.             }
  261.             src += (srcRowStride / sizeof(GLchan));
  262.             dst += (dstRowStride / sizeof(GLchan));
  263.          }
  264.          return;  /* all done */
  265.       }
  266.    }
  267.  
  268.    /*
  269.     * General case solutions
  270.     */
  271.    if (texDestFormat == GL_COLOR_INDEX) {
  272.       /* color index texture */
  273.       const GLenum texType = CHAN_TYPE;
  274.       GLint img, row;
  275.       GLchan *dest = (GLchan *) texDestAddr
  276.                    + dstZoffset * (dstImageStride / sizeof(GLchan))
  277.                    + dstYoffset * (dstRowStride / sizeof(GLchan))
  278.                    + dstXoffset * texComponents;
  279.       for (img = 0; img < srcDepth; img++) {
  280.          GLchan *destRow = dest;
  281.          for (row = 0; row < srcHeight; row++) {
  282.             const GLvoid *src = _mesa_image_address(srcPacking,
  283.                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
  284.             _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
  285.                                     srcType, src, srcPacking, transferOps);
  286.             destRow += (dstRowStride / sizeof(GLchan));
  287.          }
  288.          dest += dstImageStride;
  289.       }
  290.    }
  291.    else if (texDestFormat == GL_YCBCR_MESA) {
  292.       /* YCbCr texture */
  293.       GLint img, row;
  294.       GLushort *dest = (GLushort *) texDestAddr
  295.                      + dstZoffset * (dstImageStride / sizeof(GLushort))
  296.                      + dstYoffset * (dstRowStride / sizeof(GLushort))
  297.                      + dstXoffset * texComponents;
  298.       ASSERT(ctx->Extensions.MESA_ycbcr_texture);
  299.       for (img = 0; img < srcDepth; img++) {
  300.          GLushort *destRow = dest;
  301.          for (row = 0; row < srcHeight; row++) {
  302.             const GLvoid *srcRow = _mesa_image_address(srcPacking,
  303.                                           srcAddr, srcWidth, srcHeight,
  304.                                           srcFormat, srcType, img, row, 0);
  305.             MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort));
  306.             destRow += (dstRowStride / sizeof(GLushort));
  307.          }
  308.          dest += dstImageStride / sizeof(GLushort);
  309.       }
  310.    }
  311.    else if (texDestFormat == GL_DEPTH_COMPONENT) {
  312.       /* Depth texture (shadow maps) */
  313.       GLint img, row;
  314.       GLubyte *dest = (GLubyte *) texDestAddr
  315.                     + dstZoffset * dstImageStride
  316.                     + dstYoffset * (dstRowStride / sizeof(GLchan))
  317.                     + dstXoffset * texComponents;
  318.       for (img = 0; img < srcDepth; img++) {
  319.          GLubyte *destRow = dest;
  320.          for (row = 0; row < srcHeight; row++) {
  321.             const GLvoid *src = _mesa_image_address(srcPacking,
  322.                 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
  323.             _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
  324.                                     srcType, src, srcPacking);
  325.             destRow += (dstRowStride / sizeof(GLchan));
  326.          }
  327.          dest += dstImageStride;
  328.       }
  329.    }
  330.    else {
  331.       /* regular, color texture */
  332.       if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
  333.           (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
  334.           (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
  335.          /*
  336.           * Fill texture image with convolution
  337.           */
  338.          GLint img, row;
  339.          GLint convWidth = srcWidth, convHeight = srcHeight;
  340.          GLfloat *tmpImage, *convImage;
  341.          tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
  342.          if (!tmpImage) {
  343.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
  344.             return;
  345.          }
  346.          convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
  347.          if (!convImage) {
  348.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
  349.             FREE(tmpImage);
  350.             return;
  351.          }
  352.  
  353.          for (img = 0; img < srcDepth; img++) {
  354.             const GLfloat *srcf;
  355.             GLfloat *dstf = tmpImage;
  356.             GLchan *dest;
  357.  
  358.             /* unpack and do transfer ops up to convolution */
  359.             for (row = 0; row < srcHeight; row++) {
  360.                const GLvoid *src = _mesa_image_address(srcPacking,
  361.                                               srcAddr, srcWidth, srcHeight,
  362.                                               srcFormat, srcType, img, row, 0);
  363.                _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
  364.                          srcFormat, srcType, src, srcPacking,
  365.                          transferOps & IMAGE_PRE_CONVOLUTION_BITS,
  366.                          GL_TRUE);
  367.                dstf += srcWidth * 4;
  368.             }
  369.  
  370.             /* convolve */
  371.             if (dimensions == 1) {
  372.                ASSERT(ctx->Pixel.Convolution1DEnabled);
  373.                _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
  374.             }
  375.             else {
  376.                if (ctx->Pixel.Convolution2DEnabled) {
  377.                   _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
  378.                                           tmpImage, convImage);
  379.                }
  380.                else {
  381.                   ASSERT(ctx->Pixel.Separable2DEnabled);
  382.                   _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
  383.                                            tmpImage, convImage);
  384.                }
  385.             }
  386.  
  387.             /* packing and transfer ops after convolution */
  388.             srcf = convImage;
  389.             dest = (GLchan *) texDestAddr
  390.                  + (dstZoffset + img) * (dstImageStride / sizeof(GLchan))
  391.                  + dstYoffset * (dstRowStride / sizeof(GLchan));
  392.             for (row = 0; row < convHeight; row++) {
  393.                _mesa_pack_float_rgba_span(ctx, convWidth,
  394.                                           (const GLfloat (*)[4]) srcf,
  395.                                           texDestFormat, CHAN_TYPE,
  396.                                           dest, &_mesa_native_packing,
  397.                                           transferOps
  398.                                           & IMAGE_POST_CONVOLUTION_BITS);
  399.                srcf += convWidth * 4;
  400.                dest += (dstRowStride / sizeof(GLchan));
  401.             }
  402.          }
  403.  
  404.          FREE(convImage);
  405.          FREE(tmpImage);
  406.       }
  407.       else {
  408.          /*
  409.           * no convolution
  410.           */
  411.          GLint img, row;
  412.          GLchan *dest = (GLchan *) texDestAddr
  413.                       + dstZoffset * (dstImageStride / sizeof(GLchan))
  414.                       + dstYoffset * (dstRowStride / sizeof(GLchan))
  415.                       + dstXoffset * texComponents;
  416.          for (img = 0; img < srcDepth; img++) {
  417.             GLchan *destRow = dest;
  418.             for (row = 0; row < srcHeight; row++) {
  419.                const GLvoid *srcRow = _mesa_image_address(srcPacking,
  420.                                               srcAddr, srcWidth, srcHeight,
  421.                                               srcFormat, srcType, img, row, 0);
  422.                _mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
  423.                                        destRow, srcFormat, srcType, srcRow,
  424.                                        srcPacking, transferOps);
  425.                destRow += (dstRowStride / sizeof(GLchan));
  426.             }
  427.             dest += dstImageStride / sizeof(GLchan);
  428.          }
  429.       }
  430.    }
  431. }
  432.  
  433.  
  434.  
  435. /*
  436.  * Transfer a texture image from user space to <destAddr> applying all
  437.  * needed image transfer operations and storing the result in the format
  438.  * specified by <dstFormat>.  <dstFormat> may be any format from texformat.h.
  439.  * Input:
  440.  *   dimensions - 1, 2 or 3
  441.  *   baseInternalFormat - base format of the internal texture format
  442.  *       specified by the user.  This is very important, see below.
  443.  *   dstFormat - destination image format
  444.  *   dstAddr - destination address
  445.  *   srcWidth, srcHeight, srcDepth - size of source iamge
  446.  *   dstX/Y/Zoffset - as specified by glTexSubImage
  447.  *   dstRowStride - stride between dest rows in bytes
  448.  *   dstImageStride - stride between dest images in bytes
  449.  *   srcFormat, srcType - incoming image format and datatype
  450.  *   srcAddr - source image address
  451.  *   srcPacking - packing params of source image
  452.  *
  453.  * XXX this function is a bit more complicated than it should be.  If
  454.  * _mesa_convert_texsubimage[123]d could handle any dest/source formats
  455.  * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
  456.  * could simplify things here.
  457.  */
  458. void
  459. _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
  460.                         GLenum baseInternalFormat,
  461.                         const struct gl_texture_format *dstFormat,
  462.                         GLvoid *dstAddr,
  463.                         GLint srcWidth, GLint srcHeight, GLint srcDepth,
  464.                         GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
  465.                         GLint dstRowStride, GLint dstImageStride,
  466.                         GLenum srcFormat, GLenum srcType,
  467.                         const GLvoid *srcAddr,
  468.                         const struct gl_pixelstore_attrib *srcPacking)
  469. {
  470.    const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
  471.    const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
  472.    GLboolean makeTemp;
  473.    GLuint transferOps = ctx->_ImageTransferState;
  474.    GLboolean freeSourceData = GL_FALSE;
  475.    GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
  476.  
  477.    assert(baseInternalFormat > 0);
  478.    ASSERT(baseInternalFormat == GL_LUMINANCE ||
  479.           baseInternalFormat == GL_INTENSITY ||
  480.           baseInternalFormat == GL_LUMINANCE_ALPHA ||
  481.           baseInternalFormat == GL_ALPHA ||
  482.           baseInternalFormat == GL_RGB ||
  483.           baseInternalFormat == GL_RGBA ||
  484.           baseInternalFormat == GL_DEPTH_COMPONENT);
  485.  
  486.    if (transferOps & IMAGE_CONVOLUTION_BIT) {
  487.       _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
  488.                                          &postConvHeight);
  489.    }
  490.  
  491.    /*
  492.     * Consider this scenario:  The user's source image is GL_RGB and the
  493.     * requested internal format is GL_LUMINANCE.  Now suppose the device
  494.     * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
  495.     * texture format.  In that case we still need to do an intermediate
  496.     * conversion to luminance format so that the incoming red channel gets
  497.     * replicated into the dest red, green and blue channels.  The following
  498.     * code takes care of that.
  499.     */
  500.    if (dstFormat->BaseFormat != baseInternalFormat) {
  501.       /* Allocate storage for temporary image in the baseInternalFormat */
  502.       const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
  503.          * sizeof(GLchan);
  504.       const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
  505.       const GLint tmpRowStride = texelSize * postConvWidth;
  506.       const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
  507.       GLvoid *tmpImage = MALLOC(bytes);
  508.       if (!tmpImage)
  509.          return;
  510.       transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
  511.                         srcWidth, srcHeight, srcDepth,
  512.                         0, 0, 0, /* x/y/zoffset */
  513.                         tmpRowStride, tmpImgStride,
  514.                         srcFormat, srcType, srcAddr, srcPacking, transferOps);
  515.  
  516.       /* this is our new source image */
  517.       srcWidth = postConvWidth;
  518.       srcHeight = postConvHeight;
  519.       srcFormat = baseInternalFormat;
  520.       srcType = CHAN_TYPE;
  521.       srcAddr = tmpImage;
  522.       srcPacking = &_mesa_native_packing;
  523.       freeSourceData = GL_TRUE;
  524.       transferOps = 0;  /* image transfer ops were completed */
  525.    }
  526.  
  527.    /* Let the optimized tex conversion functions take a crack at the
  528.     * image conversion if the dest format is a h/w format.
  529.     */
  530.    if (_mesa_is_hardware_tex_format(dstFormat)) {
  531.       if (transferOps) {
  532.          makeTemp = GL_TRUE;
  533.       }
  534.       else {
  535.          if (dimensions == 1) {
  536.             makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
  537.                                                     dstXoffset,
  538.                                                     srcWidth,
  539.                                                     srcFormat, srcType,
  540.                                                     srcPacking, srcAddr,
  541.                                                     dstAddr);
  542.          }
  543.          else if (dimensions == 2) {
  544.             makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
  545.                                                     dstXoffset, dstYoffset,
  546.                                                     srcWidth, srcHeight,
  547.                                                     dstRowStridePixels,
  548.                                                     srcFormat, srcType,
  549.                                                     srcPacking, srcAddr,
  550.                                                     dstAddr);
  551.          }
  552.          else {
  553.             assert(dimensions == 3);
  554.             makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
  555.                                       dstXoffset, dstYoffset, dstZoffset,
  556.                                       srcWidth, srcHeight, srcDepth,
  557.                                       dstRowStridePixels, dstImageStridePixels,
  558.                                       srcFormat, srcType,
  559.                                       srcPacking, srcAddr, dstAddr);
  560.          }
  561.          if (!makeTemp) {
  562.             /* all done! */
  563.             if (freeSourceData)
  564.                FREE((void *) srcAddr);
  565.             return;
  566.          }
  567.       }
  568.    }
  569.    else {
  570.       /* software texture format */
  571.       makeTemp = GL_FALSE;
  572.    }
  573.  
  574.    if (makeTemp) {
  575.       GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
  576.       GLenum tmpFormat;
  577.       GLuint tmpComps, tmpTexelSize;
  578.       GLint tmpRowStride, tmpImageStride;
  579.       GLubyte *tmpImage;
  580.  
  581.       if (transferOps & IMAGE_CONVOLUTION_BIT) {
  582.          _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
  583.                                             &postConvHeight);
  584.       }
  585.  
  586.       tmpFormat = dstFormat->BaseFormat;
  587.       tmpComps = _mesa_components_in_format(tmpFormat);
  588.       tmpTexelSize = tmpComps * sizeof(GLchan);
  589.       tmpRowStride = postConvWidth * tmpTexelSize;
  590.       tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
  591.       tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
  592.                                     srcDepth * tmpTexelSize);
  593.       if (!tmpImage) {
  594.          if (freeSourceData)
  595.             FREE((void *) srcAddr);
  596.          return;
  597.       }
  598.  
  599.       transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
  600.                         srcWidth, srcHeight, srcDepth,
  601.                         0, 0, 0, /* x/y/zoffset */
  602.                         tmpRowStride, tmpImageStride,
  603.                         srcFormat, srcType, srcAddr, srcPacking, transferOps);
  604.  
  605.       if (freeSourceData)
  606.          FREE((void *) srcAddr);
  607.  
  608.       /* the temp image is our new source image */
  609.       srcWidth = postConvWidth;
  610.       srcHeight = postConvHeight;
  611.       srcFormat = tmpFormat;
  612.       srcType = CHAN_TYPE;
  613.       srcAddr = tmpImage;
  614.       srcPacking = &_mesa_native_packing;
  615.       freeSourceData = GL_TRUE;
  616.    }
  617.  
  618.    if (_mesa_is_hardware_tex_format(dstFormat)) {
  619.       assert(makeTemp);
  620.       if (dimensions == 1) {
  621.          GLboolean b;
  622.          b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
  623.                                          dstXoffset,
  624.                                          srcWidth,
  625.                                          srcFormat, srcType,
  626.                                          srcPacking, srcAddr,
  627.                                          dstAddr);
  628.          assert(b);
  629.       }
  630.       else if (dimensions == 2) {
  631.          GLboolean b;
  632.          b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
  633.                                          dstXoffset, dstYoffset,
  634.                                          srcWidth, srcHeight,
  635.                                          dstRowStridePixels,
  636.                                          srcFormat, srcType,
  637.                                          srcPacking, srcAddr,
  638.                                          dstAddr);
  639.          assert(b);
  640.       }
  641.       else {
  642.          GLboolean b;
  643.          b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
  644.                                       dstXoffset, dstYoffset, dstZoffset,
  645.                                       srcWidth, srcHeight, srcDepth,
  646.                                       dstRowStridePixels, dstImageStridePixels,
  647.                                       srcFormat, srcType,
  648.                                       srcPacking, srcAddr, dstAddr);
  649.          assert(b);
  650.       }
  651.    }
  652.    else {
  653.       /* software format */
  654.       assert(!makeTemp);
  655.       transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
  656.                         srcWidth, srcHeight, srcDepth,
  657.                         dstXoffset, dstYoffset, dstZoffset,
  658.                         dstRowStride, dstImageStride,
  659.                         srcFormat, srcType, srcAddr, srcPacking, transferOps);
  660.    }
  661.  
  662.    if (freeSourceData)
  663.       FREE((void *) srcAddr);  /* the temp image */
  664. }
  665.  
  666.  
  667.  
  668. /**
  669.  * Given a user's uncompressed texture image, this function takes care of
  670.  * pixel unpacking, pixel transfer, format conversion and compression.
  671.  */
  672. static void
  673. transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions,
  674.                              GLsizei width, GLsizei height, GLsizei depth,
  675.                              GLenum srcFormat, GLenum srcType,
  676.                              const struct gl_pixelstore_attrib *unpacking,
  677.                              const GLvoid *source,
  678.                              const struct gl_texture_format *dstFormat,
  679.                              GLubyte *dest,
  680.                              GLint dstRowStride)
  681. {
  682.    GLchan *tempImage = NULL;
  683.    GLint srcRowStride;
  684.    GLenum baseFormat;
  685.  
  686.    ASSERT(dimensions == 2);
  687.    /* TexelBytes is zero if and only if it's a compressed format */
  688.    ASSERT(dstFormat->TexelBytes == 0);
  689.  
  690.    baseFormat = dstFormat->BaseFormat;
  691.  
  692.    if (srcFormat != baseFormat || srcType != CHAN_TYPE ||
  693.        ctx->_ImageTransferState != 0 || unpacking->SwapBytes) {
  694.       /* need to convert user's image to texImage->Format, GLchan */
  695.       GLint comps = components_in_intformat(baseFormat);
  696.       GLint postConvWidth = width, postConvHeight = height;
  697.  
  698.       /* XXX convolution untested */
  699.       if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
  700.          _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
  701.                                             &postConvHeight);
  702.       }
  703.  
  704.       tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan));
  705.       if (!tempImage) {
  706.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
  707.          return;
  708.       }
  709.       transfer_teximage(ctx, dimensions,
  710.                         baseFormat,             /* dest format */
  711.                         tempImage,              /* dst address */
  712.                         width, height, depth,   /* src size */
  713.                         0, 0, 0,                /* x/y/zoffset */
  714.                         comps * width,          /* dst row stride */
  715.                         comps * width * height, /* dst image stride */
  716.                         srcFormat, srcType,     /* src format, type */
  717.                         source, unpacking,      /* src and src packing */
  718.                         ctx->_ImageTransferState);
  719.       source = tempImage;
  720.       width = postConvWidth;
  721.       height = postConvHeight;
  722.       srcRowStride = width;
  723.    }
  724.    else {
  725.       if (unpacking->RowLength)
  726.          srcRowStride = unpacking->RowLength;
  727.       else
  728.          srcRowStride = width;
  729.    }
  730.  
  731.    _mesa_compress_teximage(ctx, width, height, baseFormat,
  732.                            (const GLchan *) source, srcRowStride,
  733.                            dstFormat, dest, dstRowStride);
  734.    if (tempImage) {
  735.       FREE(tempImage);
  736.    }
  737. }
  738.  
  739.  
  740.  
  741. /*
  742.  * This is the software fallback for Driver.TexImage1D()
  743.  * and Driver.CopyTexImage2D().
  744.  * The texture image type will be GLchan.
  745.  * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
  746.  * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
  747.  */
  748. void
  749. _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
  750.                        GLint internalFormat,
  751.                        GLint width, GLint border,
  752.                        GLenum format, GLenum type, const GLvoid *pixels,
  753.                        const struct gl_pixelstore_attrib *packing,
  754.                        struct gl_texture_object *texObj,
  755.                        struct gl_texture_image *texImage)
  756. {
  757.    GLint postConvWidth = width;
  758.    GLint texelBytes, sizeInBytes;
  759.  
  760.    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
  761.       _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
  762.    }
  763.  
  764.    /* choose the texture format */
  765.    assert(ctx->Driver.ChooseTextureFormat);
  766.    texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
  767.                                           internalFormat, format, type);
  768.    assert(texImage->TexFormat);
  769.    texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
  770.  
  771.    texelBytes = texImage->TexFormat->TexelBytes;
  772.  
  773.    /* allocate memory */
  774.    if (texImage->IsCompressed)
  775.       sizeInBytes = texImage->CompressedSize;
  776.    else
  777.       sizeInBytes = postConvWidth * texelBytes;
  778.    texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
  779.    if (!texImage->Data) {
  780.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
  781.       return;
  782.    }
  783.  
  784.    if (!pixels)
  785.       return;
  786.  
  787.    /* unpack image, apply transfer ops and store in texImage->Data */
  788.    if (texImage->IsCompressed) {
  789.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  790.                                                        width);
  791.       transfer_compressed_teximage(ctx, 1, width, 1, 1,
  792.                                    format, type, packing,
  793.                                    pixels, texImage->TexFormat,
  794.                                    (GLubyte *) texImage->Data, dstRowStride);
  795.    }
  796.    else {
  797.       _mesa_transfer_teximage(ctx, 1,
  798.                               texImage->Format, /* base format */
  799.                               texImage->TexFormat, texImage->Data,
  800.                               width, 1, 1,  /* src size */
  801.                               0, 0, 0,      /* dstX/Y/Zoffset */
  802.                               0, /* dstRowStride */
  803.                               0, /* dstImageStride */
  804.                               format, type, pixels, packing);
  805.    }
  806.  
  807.    /* GL_SGIS_generate_mipmap */
  808.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  809.       _mesa_generate_mipmap(ctx, target,
  810.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  811.                             texObj);
  812.    }
  813. }
  814.  
  815.  
  816. /*
  817.  * This is the software fallback for Driver.TexImage2D()
  818.  * and Driver.CopyTexImage2D().
  819.  * The texture image type will be GLchan.
  820.  * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
  821.  * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
  822.  */
  823. void
  824. _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
  825.                        GLint internalFormat,
  826.                        GLint width, GLint height, GLint border,
  827.                        GLenum format, GLenum type, const void *pixels,
  828.                        const struct gl_pixelstore_attrib *packing,
  829.                        struct gl_texture_object *texObj,
  830.                        struct gl_texture_image *texImage)
  831. {
  832.    GLint postConvWidth = width, postConvHeight = height;
  833.    GLint texelBytes, sizeInBytes;
  834.  
  835.    if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
  836.       _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
  837.                                          &postConvHeight);
  838.    }
  839.  
  840.    /* choose the texture format */
  841.    assert(ctx->Driver.ChooseTextureFormat);
  842.    texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
  843.                                           internalFormat, format, type);
  844.    assert(texImage->TexFormat);
  845.    texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
  846.  
  847.    texelBytes = texImage->TexFormat->TexelBytes;
  848.  
  849.    /* allocate memory */
  850.    if (texImage->IsCompressed)
  851.       sizeInBytes = texImage->CompressedSize;
  852.    else
  853.       sizeInBytes = postConvWidth * postConvHeight * texelBytes;
  854.    texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
  855.    if (!texImage->Data) {
  856.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
  857.       return;
  858.    }
  859.  
  860.    if (!pixels)
  861.       return;
  862.  
  863.    /* unpack image, apply transfer ops and store in texImage->Data */
  864.    if (texImage->IsCompressed) {
  865.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  866.                                                        width);
  867.       transfer_compressed_teximage(ctx, 2, width, height, 1,
  868.                                    format, type, packing,
  869.                                    pixels, texImage->TexFormat,
  870.                                    (GLubyte *) texImage->Data, dstRowStride);
  871.    }
  872.    else {
  873.       _mesa_transfer_teximage(ctx, 2,
  874.                               texImage->Format,
  875.                               texImage->TexFormat, texImage->Data,
  876.                               width, height, 1,  /* src size */
  877.                               0, 0, 0,           /* dstX/Y/Zoffset */
  878.                               texImage->Width * texelBytes, /* dstRowStride */
  879.                               0, /* dstImageStride */
  880.                               format, type, pixels, packing);
  881.    }
  882.  
  883.    /* GL_SGIS_generate_mipmap */
  884.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  885.       _mesa_generate_mipmap(ctx, target,
  886.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  887.                             texObj);
  888.    }
  889. }
  890.  
  891.  
  892.  
  893. /*
  894.  * This is the software fallback for Driver.TexImage3D()
  895.  * and Driver.CopyTexImage3D().
  896.  * The texture image type will be GLchan.
  897.  * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
  898.  * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
  899.  */
  900. void
  901. _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
  902.                        GLint internalFormat,
  903.                        GLint width, GLint height, GLint depth, GLint border,
  904.                        GLenum format, GLenum type, const void *pixels,
  905.                        const struct gl_pixelstore_attrib *packing,
  906.                        struct gl_texture_object *texObj,
  907.                        struct gl_texture_image *texImage)
  908. {
  909.    GLint texelBytes, sizeInBytes;
  910.  
  911.    /* choose the texture format */
  912.    assert(ctx->Driver.ChooseTextureFormat);
  913.    texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
  914.                                           internalFormat, format, type);
  915.    assert(texImage->TexFormat);
  916.    texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
  917.  
  918.    texelBytes = texImage->TexFormat->TexelBytes;
  919.  
  920.    /* allocate memory */
  921.    if (texImage->IsCompressed)
  922.       sizeInBytes = texImage->CompressedSize;
  923.    else
  924.       sizeInBytes = width * height * depth * texelBytes;
  925.    texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
  926.    if (!texImage->Data) {
  927.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
  928.       return;
  929.    }
  930.  
  931.    if (!pixels)
  932.       return;
  933.  
  934.    /* unpack image, apply transfer ops and store in texImage->Data */
  935.    if (texImage->IsCompressed) {
  936.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  937.                                                        width);
  938.       transfer_compressed_teximage(ctx, 3, width, height, depth,
  939.                                    format, type, packing,
  940.                                    pixels, texImage->TexFormat,
  941.                                    (GLubyte *) texImage->Data, dstRowStride);
  942.    }
  943.    else {
  944.       _mesa_transfer_teximage(ctx, 3,
  945.                               texImage->Format,
  946.                               texImage->TexFormat, texImage->Data,
  947.                               width, height, depth, /* src size */
  948.                               0, 0, 0,  /* dstX/Y/Zoffset */
  949.                               texImage->Width * texelBytes, /* dstRowStride */
  950.                               texImage->Width * texImage->Height * texelBytes,
  951.                               format, type, pixels, packing);
  952.    }
  953.  
  954.    /* GL_SGIS_generate_mipmap */
  955.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  956.       _mesa_generate_mipmap(ctx, target,
  957.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  958.                             texObj);
  959.    }
  960. }
  961.  
  962.  
  963.  
  964.  
  965. /*
  966.  * This is the software fallback for Driver.TexSubImage1D()
  967.  * and Driver.CopyTexSubImage1D().
  968.  */
  969. void
  970. _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
  971.                           GLint xoffset, GLint width,
  972.                           GLenum format, GLenum type, const void *pixels,
  973.                           const struct gl_pixelstore_attrib *packing,
  974.                           struct gl_texture_object *texObj,
  975.                           struct gl_texture_image *texImage)
  976. {
  977.    if (texImage->IsCompressed) {
  978.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  979.                                                        texImage->Width);
  980.       GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0,
  981.                                                      texImage->IntFormat,
  982.                                                      texImage->Width,
  983.                                                      (GLubyte*) texImage->Data);
  984.       transfer_compressed_teximage(ctx, 1,             /* dimensions */
  985.                                    width, 1, 1,        /* size to replace */
  986.                                    format, type,       /* source format/type */
  987.                                    packing,            /* source packing */
  988.                                    pixels,             /* source data */
  989.                                    texImage->TexFormat,/* dest format */
  990.                                    dest, dstRowStride);
  991.    }
  992.    else {
  993.       _mesa_transfer_teximage(ctx, 1,
  994.                               texImage->Format,
  995.                               texImage->TexFormat, texImage->Data,
  996.                               width, 1, 1, /* src size */
  997.                               xoffset, 0, 0, /* dest offsets */
  998.                               0, /* dstRowStride */
  999.                               0, /* dstImageStride */
  1000.                               format, type, pixels, packing);
  1001.    }
  1002.  
  1003.    /* GL_SGIS_generate_mipmap */
  1004.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  1005.       _mesa_generate_mipmap(ctx, target,
  1006.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  1007.                             texObj);
  1008.    }
  1009. }
  1010.  
  1011.  
  1012.  
  1013. /*
  1014.  * This is the software fallback for Driver.TexSubImage2D()
  1015.  * and Driver.CopyTexSubImage2D().
  1016.  */
  1017. void
  1018. _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
  1019.                           GLint xoffset, GLint yoffset,
  1020.                           GLint width, GLint height,
  1021.                           GLenum format, GLenum type, const void *pixels,
  1022.                           const struct gl_pixelstore_attrib *packing,
  1023.                           struct gl_texture_object *texObj,
  1024.                           struct gl_texture_image *texImage)
  1025. {
  1026.    if (texImage->IsCompressed) {
  1027.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  1028.                                                        texImage->Width);
  1029.       GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
  1030.                                                      texImage->IntFormat,
  1031.                                                      texImage->Width,
  1032.                                                      (GLubyte*) texImage->Data);
  1033.       transfer_compressed_teximage(ctx, 2,             /* dimensions */
  1034.                                    width, height, 1,   /* size to replace */
  1035.                                    format, type,       /* source format/type */
  1036.                                    packing,            /* source packing */
  1037.                                    pixels,             /* source data */
  1038.                                    texImage->TexFormat,/* dest format */
  1039.                                    dest, dstRowStride);
  1040.    }
  1041.    else {
  1042.       _mesa_transfer_teximage(ctx, 2,
  1043.                               texImage->Format,
  1044.                               texImage->TexFormat, texImage->Data,
  1045.                               width, height, 1, /* src size */
  1046.                               xoffset, yoffset, 0, /* dest offsets */
  1047.                               texImage->Width *texImage->TexFormat->TexelBytes,
  1048.                               0, /* dstImageStride */
  1049.                               format, type, pixels, packing);
  1050.    }
  1051.  
  1052.    /* GL_SGIS_generate_mipmap */
  1053.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  1054.       _mesa_generate_mipmap(ctx, target,
  1055.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  1056.                             texObj);
  1057.    }
  1058. }
  1059.  
  1060.  
  1061. /*
  1062.  * This is the software fallback for Driver.TexSubImage3D().
  1063.  * and Driver.CopyTexSubImage3D().
  1064.  */
  1065. void
  1066. _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
  1067.                           GLint xoffset, GLint yoffset, GLint zoffset,
  1068.                           GLint width, GLint height, GLint depth,
  1069.                           GLenum format, GLenum type, const void *pixels,
  1070.                           const struct gl_pixelstore_attrib *packing,
  1071.                           struct gl_texture_object *texObj,
  1072.                           struct gl_texture_image *texImage)
  1073. {
  1074.    if (texImage->IsCompressed) {
  1075.       GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  1076.                                                        texImage->Width);
  1077.       GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset,
  1078.                                                      texImage->IntFormat,
  1079.                                                      texImage->Width,
  1080.                                                      (GLubyte*) texImage->Data);
  1081.       transfer_compressed_teximage(ctx, 3,              /* dimensions */
  1082.                                    width, height, depth,/* size to replace */
  1083.                                    format, type,       /* source format/type */
  1084.                                    packing,            /* source packing */
  1085.                                    pixels,             /* source data */
  1086.                                    texImage->TexFormat,/* dest format */
  1087.                                    dest, dstRowStride);
  1088.    }
  1089.    else {
  1090.       const GLint texelBytes = texImage->TexFormat->TexelBytes;
  1091.       _mesa_transfer_teximage(ctx, 3,
  1092.                            texImage->Format,
  1093.                            texImage->TexFormat, texImage->Data,
  1094.                            width, height, depth, /* src size */
  1095.                            xoffset, yoffset, xoffset, /* dest offsets */
  1096.                            texImage->Width * texelBytes,  /* dst row stride */
  1097.                            texImage->Width * texImage->Height * texelBytes,
  1098.                            format, type, pixels, packing);
  1099.    }
  1100.  
  1101.    /* GL_SGIS_generate_mipmap */
  1102.    if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
  1103.       _mesa_generate_mipmap(ctx, target,
  1104.                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
  1105.                             texObj);
  1106.    }
  1107. }
  1108.  
  1109.  
  1110.  
  1111.  
  1112. /*
  1113.  * Fallback for Driver.CompressedTexImage1D()
  1114.  */
  1115. void
  1116. _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
  1117.                                   GLint internalFormat,
  1118.                                   GLint width, GLint border,
  1119.                                   GLsizei imageSize, const GLvoid *data,
  1120.                                   struct gl_texture_object *texObj,
  1121.                                   struct gl_texture_image *texImage)
  1122. {
  1123.    /* this space intentionally left blank */
  1124. }
  1125.  
  1126.  
  1127.  
  1128. /*
  1129.  * Fallback for Driver.CompressedTexImage2D()
  1130.  */
  1131. void
  1132. _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
  1133.                                   GLint internalFormat,
  1134.                                   GLint width, GLint height, GLint border,
  1135.                                   GLsizei imageSize, const GLvoid *data,
  1136.                                   struct gl_texture_object *texObj,
  1137.                                   struct gl_texture_image *texImage)
  1138. {
  1139.    /* This is pretty simple, basically just do a memcpy without worrying
  1140.     * about the usual image unpacking or image transfer operations.
  1141.     */
  1142.    ASSERT(texObj);
  1143.    ASSERT(texImage);
  1144.    ASSERT(texImage->Width > 0);
  1145.    ASSERT(texImage->Height > 0);
  1146.    ASSERT(texImage->Depth == 1);
  1147.    ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
  1148.  
  1149.    /* choose the texture format */
  1150.    assert(ctx->Driver.ChooseTextureFormat);
  1151.    texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
  1152.                                           internalFormat, 0, 0);
  1153.    assert(texImage->TexFormat);
  1154.    texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
  1155.  
  1156.    /* allocate storage */
  1157.    texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
  1158.    if (!texImage->Data) {
  1159.       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
  1160.       return;
  1161.    }
  1162.  
  1163.    /* copy the data */
  1164.    ASSERT(texImage->CompressedSize == imageSize);
  1165.    MEMCPY(texImage->Data, data, imageSize);
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /*
  1171.  * Fallback for Driver.CompressedTexImage3D()
  1172.  */
  1173. void
  1174. _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
  1175.                                   GLint internalFormat,
  1176.                                   GLint width, GLint height, GLint depth,
  1177.                                   GLint border,
  1178.                                   GLsizei imageSize, const GLvoid *data,
  1179.                                   struct gl_texture_object *texObj,
  1180.                                   struct gl_texture_image *texImage)
  1181. {
  1182.    /* this space intentionally left blank */
  1183. }
  1184.  
  1185.  
  1186.  
  1187. /**
  1188.  * Fallback for Driver.CompressedTexSubImage1D()
  1189.  */
  1190. void
  1191. _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
  1192.                                      GLint level,
  1193.                                      GLint xoffset, GLsizei width,
  1194.                                      GLenum format,
  1195.                                      GLsizei imageSize, const GLvoid *data,
  1196.                                      struct gl_texture_object *texObj,
  1197.                                      struct gl_texture_image *texImage)
  1198. {
  1199.    /* this space intentionally left blank */
  1200. }
  1201.  
  1202.  
  1203. /**
  1204.  * Fallback for Driver.CompressedTexSubImage2D()
  1205.  */
  1206. void
  1207. _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
  1208.                                      GLint level,
  1209.                                      GLint xoffset, GLint yoffset,
  1210.                                      GLsizei width, GLsizei height,
  1211.                                      GLenum format,
  1212.                                      GLsizei imageSize, const GLvoid *data,
  1213.                                      struct gl_texture_object *texObj,
  1214.                                      struct gl_texture_image *texImage)
  1215. {
  1216.    GLint bytesPerRow, destRowStride, srcRowStride;
  1217.    GLint i, rows;
  1218.    GLubyte *dest;
  1219.    const GLubyte *src;
  1220.  
  1221.    /* these should have been caught sooner */
  1222.    ASSERT((width & 3) == 0 || width == 2 || width == 1);
  1223.    ASSERT((height & 3) == 0 || height == 2 || height == 1);
  1224.    ASSERT((xoffset & 3) == 0);
  1225.    ASSERT((yoffset & 3) == 0);
  1226.  
  1227.    srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
  1228.    src = (const GLubyte *) data;
  1229.  
  1230.    destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
  1231.                                                texImage->Width);
  1232.    dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
  1233.                                          texImage->IntFormat,
  1234.                                          texImage->Width, (GLubyte*) texImage->Data);
  1235.  
  1236.    bytesPerRow = srcRowStride;
  1237.    rows = height / 4;
  1238.  
  1239.    for (i = 0; i < rows; i++) {
  1240.       MEMCPY(dest, src, bytesPerRow);
  1241.       dest += destRowStride;
  1242.       src += srcRowStride;
  1243.    }
  1244. }
  1245.  
  1246.  
  1247. /**
  1248.  * Fallback for Driver.CompressedTexSubImage3D()
  1249.  */
  1250. void
  1251. _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
  1252.                                 GLint level,
  1253.                                 GLint xoffset, GLint yoffset, GLint zoffset,
  1254.                                 GLsizei width, GLsizei height, GLsizei depth,
  1255.                                 GLenum format,
  1256.                                 GLsizei imageSize, const GLvoid *data,
  1257.                                 struct gl_texture_object *texObj,
  1258.                                 struct gl_texture_image *texImage)
  1259. {
  1260.    /* this space intentionally left blank */
  1261. }
  1262.  
  1263.  
  1264.  
  1265.  
  1266.  
  1267. /*
  1268.  * This is the fallback for Driver.TestProxyTexImage().
  1269.  */
  1270. GLboolean
  1271. _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
  1272.                           GLint internalFormat, GLenum format, GLenum type,
  1273.                           GLint width, GLint height, GLint depth, GLint border)
  1274. {
  1275.    struct gl_texture_unit *texUnit;
  1276.    struct gl_texture_object *texObj;
  1277.    struct gl_texture_image *texImage;
  1278.  
  1279.    (void) format;
  1280.    (void) type;
  1281.  
  1282.    texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
  1283.    texObj = _mesa_select_tex_object(ctx, texUnit, target);
  1284.    texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
  1285.  
  1286.    /* We always pass.
  1287.     * The core Mesa code will have already tested the image size, etc.
  1288.     * If a driver has more stringent texture limits to enforce it will
  1289.     * have to override this function.
  1290.     */
  1291.    /* choose the texture format */
  1292.    assert(ctx->Driver.ChooseTextureFormat);
  1293.    texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
  1294.                                           internalFormat, format, type);
  1295.    assert(texImage->TexFormat);
  1296.  
  1297.    return GL_TRUE;
  1298. }
  1299.  
  1300.  
  1301.  
  1302. /*
  1303.  * Average together two rows of a source image to produce a single new
  1304.  * row in the dest image.  It's legal for the two source rows to point
  1305.  * to the same data.  The source width must be equal to either the
  1306.  * dest width or two times the dest width.
  1307.  */
  1308. static void
  1309. do_row(const struct gl_texture_format *format, GLint srcWidth,
  1310.        const GLvoid *srcRowA, const GLvoid *srcRowB,
  1311.        GLint dstWidth, GLvoid *dstRow)
  1312. {
  1313.    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
  1314.    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
  1315.  
  1316.    assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
  1317.  
  1318.    switch (format->MesaFormat) {
  1319.    case MESA_FORMAT_RGBA:
  1320.       {
  1321.          GLuint i, j, k;
  1322.          const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
  1323.          const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
  1324.          GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
  1325.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1326.               i++, j += colStride, k += colStride) {
  1327.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1328.                          rowB[j][0] + rowB[k][0]) / 4;
  1329.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1330.                          rowB[j][1] + rowB[k][1]) / 4;
  1331.             dst[i][2] = (rowA[j][2] + rowA[k][2] +
  1332.                          rowB[j][2] + rowB[k][2]) / 4;
  1333.             dst[i][3] = (rowA[j][3] + rowA[k][3] +
  1334.                          rowB[j][3] + rowB[k][3]) / 4;
  1335.          }
  1336.       }
  1337.       return;
  1338.    case MESA_FORMAT_RGB:
  1339.       {
  1340.          GLuint i, j, k;
  1341.          const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
  1342.          const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
  1343.          GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
  1344.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1345.               i++, j += colStride, k += colStride) {
  1346.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1347.                          rowB[j][0] + rowB[k][0]) / 4;
  1348.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1349.                          rowB[j][1] + rowB[k][1]) / 4;
  1350.             dst[i][2] = (rowA[j][2] + rowA[k][2] +
  1351.                          rowB[j][2] + rowB[k][2]) / 4;
  1352.          }
  1353.       }
  1354.       return;
  1355.    case MESA_FORMAT_ALPHA:
  1356.    case MESA_FORMAT_LUMINANCE:
  1357.    case MESA_FORMAT_INTENSITY:
  1358.    case MESA_FORMAT_COLOR_INDEX:
  1359.       {
  1360.          GLuint i, j, k;
  1361.          const GLchan *rowA = (const GLchan *) srcRowA;
  1362.          const GLchan *rowB = (const GLchan *) srcRowB;
  1363.          GLchan *dst = (GLchan *) dstRow;
  1364.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1365.               i++, j += colStride, k += colStride) {
  1366.             dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
  1367.          }
  1368.       }
  1369.       return;
  1370.    case MESA_FORMAT_LUMINANCE_ALPHA:
  1371.       {
  1372.          GLuint i, j, k;
  1373.          const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
  1374.          const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
  1375.          GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
  1376.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1377.               i++, j += colStride, k += colStride) {
  1378.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1379.                          rowB[j][0] + rowB[k][0]) / 4;
  1380.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1381.                          rowB[j][1] + rowB[k][1]) / 4;
  1382.          }
  1383.       }
  1384.       return;
  1385.    case MESA_FORMAT_DEPTH_COMPONENT:
  1386.       {
  1387.          GLuint i, j, k;
  1388.          const GLfloat *rowA = (const GLfloat *) srcRowA;
  1389.          const GLfloat *rowB = (const GLfloat *) srcRowB;
  1390.          GLfloat *dst = (GLfloat *) dstRow;
  1391.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1392.               i++, j += colStride, k += colStride) {
  1393.             dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
  1394.          }
  1395.       }
  1396.       return;
  1397.    /* Begin hardware formats */
  1398.    case MESA_FORMAT_RGBA8888:
  1399.    case MESA_FORMAT_ARGB8888:
  1400.       {
  1401.          GLuint i, j, k;
  1402.          const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
  1403.          const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
  1404.          GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
  1405.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1406.               i++, j += colStride, k += colStride) {
  1407.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1408.                          rowB[j][0] + rowB[k][0]) / 4;
  1409.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1410.                          rowB[j][1] + rowB[k][1]) / 4;
  1411.             dst[i][2] = (rowA[j][2] + rowA[k][2] +
  1412.                          rowB[j][2] + rowB[k][2]) / 4;
  1413.             dst[i][3] = (rowA[j][3] + rowA[k][3] +
  1414.                          rowB[j][3] + rowB[k][3]) / 4;
  1415.          }
  1416.       }
  1417.       return;
  1418.    case MESA_FORMAT_RGB888:
  1419.       {
  1420.          GLuint i, j, k;
  1421.          const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
  1422.          const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
  1423.          GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
  1424.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1425.               i++, j += colStride, k += colStride) {
  1426.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1427.                          rowB[j][0] + rowB[k][0]) / 4;
  1428.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1429.                          rowB[j][1] + rowB[k][1]) / 4;
  1430.             dst[i][2] = (rowA[j][2] + rowA[k][2] +
  1431.                          rowB[j][2] + rowB[k][2]) / 4;
  1432.          }
  1433.       }
  1434.       return;
  1435.    case MESA_FORMAT_RGB565:
  1436.       {
  1437.          GLuint i, j, k;
  1438.          const GLushort *rowA = (const GLushort *) srcRowA;
  1439.          const GLushort *rowB = (const GLushort *) srcRowB;
  1440.          GLushort *dst = (GLushort *) dstRow;
  1441.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1442.               i++, j += colStride, k += colStride) {
  1443.             const GLint rowAr0 = rowA[j] & 0x1f;
  1444.             const GLint rowAr1 = rowA[k] & 0x1f;
  1445.             const GLint rowBr0 = rowB[j] & 0x1f;
  1446.             const GLint rowBr1 = rowB[k] & 0x1f;
  1447.             const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
  1448.             const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
  1449.             const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
  1450.             const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
  1451.             const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
  1452.             const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
  1453.             const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
  1454.             const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
  1455.             const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
  1456.             const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
  1457.             const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
  1458.             dst[i] = (blue << 11) | (green << 5) | red;
  1459.          }
  1460.       }
  1461.       return;
  1462.    case MESA_FORMAT_ARGB4444:
  1463.       {
  1464.          GLuint i, j, k;
  1465.          const GLushort *rowA = (const GLushort *) srcRowA;
  1466.          const GLushort *rowB = (const GLushort *) srcRowB;
  1467.          GLushort *dst = (GLushort *) dstRow;
  1468.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1469.               i++, j += colStride, k += colStride) {
  1470.             const GLint rowAr0 = rowA[j] & 0xf;
  1471.             const GLint rowAr1 = rowA[k] & 0xf;
  1472.             const GLint rowBr0 = rowB[j] & 0xf;
  1473.             const GLint rowBr1 = rowB[k] & 0xf;
  1474.             const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
  1475.             const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
  1476.             const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
  1477.             const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
  1478.             const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
  1479.             const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
  1480.             const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
  1481.             const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
  1482.             const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
  1483.             const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
  1484.             const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
  1485.             const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
  1486.             const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
  1487.             const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
  1488.             const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
  1489.             const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
  1490.             dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
  1491.          }
  1492.       }
  1493.       return;
  1494.    case MESA_FORMAT_ARGB1555:
  1495.       {
  1496.          GLuint i, j, k;
  1497.          const GLushort *rowA = (const GLushort *) srcRowA;
  1498.          const GLushort *rowB = (const GLushort *) srcRowB;
  1499.          GLushort *dst = (GLushort *) dstRow;
  1500.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1501.               i++, j += colStride, k += colStride) {
  1502.             const GLint rowAr0 = rowA[j] & 0x1f;
  1503.             const GLint rowAr1 = rowA[k] & 0x1f;
  1504.             const GLint rowBr0 = rowB[j] & 0x1f;
  1505.             const GLint rowBr1 = rowB[k] & 0xf;
  1506.             const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
  1507.             const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
  1508.             const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
  1509.             const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
  1510.             const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
  1511.             const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
  1512.             const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
  1513.             const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
  1514.             const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
  1515.             const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
  1516.             const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
  1517.             const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
  1518.             const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
  1519.             const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
  1520.             const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
  1521.             const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
  1522.             dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
  1523.          }
  1524.       }
  1525.       return;
  1526.    case MESA_FORMAT_AL88:
  1527.       {
  1528.          GLuint i, j, k;
  1529.          const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
  1530.          const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
  1531.          GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
  1532.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1533.               i++, j += colStride, k += colStride) {
  1534.             dst[i][0] = (rowA[j][0] + rowA[k][0] +
  1535.                          rowB[j][0] + rowB[k][0]) >> 2;
  1536.             dst[i][1] = (rowA[j][1] + rowA[k][1] +
  1537.                          rowB[j][1] + rowB[k][1]) >> 2;
  1538.          }
  1539.       }
  1540.       return;
  1541.    case MESA_FORMAT_RGB332:
  1542.       {
  1543.          GLuint i, j, k;
  1544.          const GLubyte *rowA = (const GLubyte *) srcRowA;
  1545.          const GLubyte *rowB = (const GLubyte *) srcRowB;
  1546.          GLubyte *dst = (GLubyte *) dstRow;
  1547.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1548.               i++, j += colStride, k += colStride) {
  1549.             const GLint rowAr0 = rowA[j] & 0x3;
  1550.             const GLint rowAr1 = rowA[k] & 0x3;
  1551.             const GLint rowBr0 = rowB[j] & 0x3;
  1552.             const GLint rowBr1 = rowB[k] & 0x3;
  1553.             const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
  1554.             const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
  1555.             const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
  1556.             const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
  1557.             const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
  1558.             const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
  1559.             const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
  1560.             const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
  1561.             const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
  1562.             const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
  1563.             const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
  1564.             dst[i] = (blue << 5) | (green << 2) | red;
  1565.          }
  1566.       }
  1567.       return;
  1568.    case MESA_FORMAT_A8:
  1569.    case MESA_FORMAT_L8:
  1570.    case MESA_FORMAT_I8:
  1571.    case MESA_FORMAT_CI8:
  1572.       {
  1573.          GLuint i, j, k;
  1574.          const GLubyte *rowA = (const GLubyte *) srcRowA;
  1575.          const GLubyte *rowB = (const GLubyte *) srcRowB;
  1576.          GLubyte *dst = (GLubyte *) dstRow;
  1577.          for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1578.               i++, j += colStride, k += colStride) {
  1579.             dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
  1580.          }
  1581.       }
  1582.       return;
  1583.    default:
  1584.       _mesa_problem(NULL, "bad format in do_row()");
  1585.    }
  1586. }
  1587.  
  1588.  
  1589. /*
  1590.  * These functions generate a 1/2-size mipmap image from a source image.
  1591.  * Texture borders are handled by copying or averaging the source image's
  1592.  * border texels, depending on the scale-down factor.
  1593.  */
  1594.  
  1595. static void
  1596. make_1d_mipmap(const struct gl_texture_format *format, GLint border,
  1597.                GLint srcWidth, const GLubyte *srcPtr,
  1598.                GLint dstWidth, GLubyte *dstPtr)
  1599. {
  1600.    const GLint bpt = format->TexelBytes;
  1601.    const GLubyte *src;
  1602.    GLubyte *dst;
  1603.  
  1604.    /* skip the border pixel, if any */
  1605.    src = srcPtr + border * bpt;
  1606.    dst = dstPtr + border * bpt;
  1607.  
  1608.    /* we just duplicate the input row, kind of hack, saves code */
  1609.    do_row(format, srcWidth - 2 * border, src, src,
  1610.           dstWidth - 2 * border, dst);
  1611.  
  1612.    if (border) {
  1613.       /* copy left-most pixel from source */
  1614.       MEMCPY(dstPtr, srcPtr, bpt);
  1615.       /* copy right-most pixel from source */
  1616.       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
  1617.              srcPtr + (srcWidth - 1) * bpt,
  1618.              bpt);
  1619.    }
  1620. }
  1621.  
  1622.  
  1623. static void
  1624. make_2d_mipmap(const struct gl_texture_format *format, GLint border,
  1625.                GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
  1626.                GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
  1627. {
  1628.    const GLint bpt = format->TexelBytes;
  1629.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1630.    const GLint dstWidthNB = dstWidth - 2 * border;
  1631.    const GLint dstHeightNB = dstHeight - 2 * border;
  1632.    const GLint srcRowStride = bpt * srcWidth;
  1633.    const GLint dstRowStride = bpt * dstWidth;
  1634.    const GLubyte *srcA, *srcB;
  1635.    GLubyte *dst;
  1636.    GLint row, colStride;
  1637.  
  1638.    colStride = (srcWidth == dstWidth) ? 1 : 2;
  1639.  
  1640.    /* Compute src and dst pointers, skipping any border */
  1641.    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
  1642.    if (srcHeight > 1)
  1643.       srcB = srcA + srcRowStride;
  1644.    else
  1645.       srcB = srcA;
  1646.    dst = dstPtr + border * ((dstWidth + 1) * bpt);
  1647.  
  1648.    for (row = 0; row < dstHeightNB; row++) {
  1649.       do_row(format, srcWidthNB, srcA, srcB,
  1650.              dstWidthNB, dst);
  1651.       srcA += 2 * srcRowStride;
  1652.       srcB += 2 * srcRowStride;
  1653.       dst += dstRowStride;
  1654.    }
  1655.  
  1656.    /* This is ugly but probably won't be used much */
  1657.    if (border > 0) {
  1658.       /* fill in dest border */
  1659.       /* lower-left border pixel */
  1660.       MEMCPY(dstPtr, srcPtr, bpt);
  1661.       /* lower-right border pixel */
  1662.       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
  1663.              srcPtr + (srcWidth - 1) * bpt, bpt);
  1664.       /* upper-left border pixel */
  1665.       MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
  1666.              srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
  1667.       /* upper-right border pixel */
  1668.       MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
  1669.              srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
  1670.       /* lower border */
  1671.       do_row(format, srcWidthNB,
  1672.              srcPtr + bpt,
  1673.              srcPtr + bpt,
  1674.              dstWidthNB, dstPtr + bpt);
  1675.       /* upper border */
  1676.       do_row(format, srcWidthNB,
  1677.              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1678.              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1679.              dstWidthNB,
  1680.              dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
  1681.       /* left and right borders */
  1682.       if (srcHeight == dstHeight) {
  1683.          /* copy border pixel from src to dst */
  1684.          for (row = 1; row < srcHeight; row++) {
  1685.             MEMCPY(dstPtr + dstWidth * row * bpt,
  1686.                    srcPtr + srcWidth * row * bpt, bpt);
  1687.             MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
  1688.                    srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
  1689.          }
  1690.       }
  1691.       else {
  1692.          /* average two src pixels each dest pixel */
  1693.          for (row = 0; row < dstHeightNB; row += 2) {
  1694.             do_row(format, 1,
  1695.                    srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
  1696.                    srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
  1697.                    1, dstPtr + (dstWidth * row + 1) * bpt);
  1698.             do_row(format, 1,
  1699.                    srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
  1700.                    srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
  1701.                    1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
  1702.          }
  1703.       }
  1704.    }
  1705. }
  1706.  
  1707.  
  1708. static void
  1709. make_3d_mipmap(const struct gl_texture_format *format, GLint border,
  1710.                GLint srcWidth, GLint srcHeight, GLint srcDepth,
  1711.                const GLubyte *srcPtr,
  1712.                GLint dstWidth, GLint dstHeight, GLint dstDepth,
  1713.                GLubyte *dstPtr)
  1714. {
  1715.    const GLint bpt = format->TexelBytes;
  1716.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1717.    const GLint srcDepthNB = srcDepth - 2 * border;
  1718.    const GLint dstWidthNB = dstWidth - 2 * border;
  1719.    const GLint dstHeightNB = dstHeight - 2 * border;
  1720.    const GLint dstDepthNB = dstDepth - 2 * border;
  1721.    GLvoid *tmpRowA, *tmpRowB;
  1722.    GLint img, row;
  1723.    GLint bytesPerSrcImage, bytesPerDstImage;
  1724.    GLint bytesPerSrcRow, bytesPerDstRow;
  1725.    GLint srcImageOffset, srcRowOffset;
  1726.  
  1727.    (void) srcDepthNB; /* silence warnings */
  1728.  
  1729.    /* Need two temporary row buffers */
  1730.    tmpRowA = MALLOC(srcWidth * bpt);
  1731.    if (!tmpRowA)
  1732.       return;
  1733.    tmpRowB = MALLOC(srcWidth * bpt);
  1734.    if (!tmpRowB) {
  1735.       FREE(tmpRowA);
  1736.       return;
  1737.    }
  1738.  
  1739.    bytesPerSrcImage = srcWidth * srcHeight * bpt;
  1740.    bytesPerDstImage = dstWidth * dstHeight * bpt;
  1741.  
  1742.    bytesPerSrcRow = srcWidth * bpt;
  1743.    bytesPerDstRow = dstWidth * bpt;
  1744.  
  1745.    /* Offset between adjacent src images to be averaged together */
  1746.    srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
  1747.  
  1748.    /* Offset between adjacent src rows to be averaged together */
  1749.    srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
  1750.  
  1751.    /*
  1752.     * Need to average together up to 8 src pixels for each dest pixel.
  1753.     * Break that down into 3 operations:
  1754.     *   1. take two rows from source image and average them together.
  1755.     *   2. take two rows from next source image and average them together.
  1756.     *   3. take the two averaged rows and average them for the final dst row.
  1757.     */
  1758.  
  1759.    /*
  1760.    _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
  1761.           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
  1762.    */
  1763.  
  1764.    for (img = 0; img < dstDepthNB; img++) {
  1765.       /* first source image pointer, skipping border */
  1766.       const GLubyte *imgSrcA = srcPtr
  1767.          + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
  1768.          + img * (bytesPerSrcImage + srcImageOffset);
  1769.       /* second source image pointer, skipping border */
  1770.       const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
  1771.       /* address of the dest image, skipping border */
  1772.       GLubyte *imgDst = dstPtr
  1773.          + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
  1774.          + img * bytesPerDstImage;
  1775.  
  1776.       /* setup the four source row pointers and the dest row pointer */
  1777.       const GLubyte *srcImgARowA = imgSrcA;
  1778.       const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
  1779.       const GLubyte *srcImgBRowA = imgSrcB;
  1780.       const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
  1781.       GLubyte *dstImgRow = imgDst;
  1782.  
  1783.       for (row = 0; row < dstHeightNB; row++) {
  1784.          /* Average together two rows from first src image */
  1785.          do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
  1786.                 srcWidthNB, tmpRowA);
  1787.          /* Average together two rows from second src image */
  1788.          do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
  1789.                 srcWidthNB, tmpRowB);
  1790.          /* Average together the temp rows to make the final row */
  1791.          do_row(format, srcWidthNB, tmpRowA, tmpRowB,
  1792.                 dstWidthNB, dstImgRow);
  1793.          /* advance to next rows */
  1794.          srcImgARowA += bytesPerSrcRow + srcRowOffset;
  1795.          srcImgARowB += bytesPerSrcRow + srcRowOffset;
  1796.          srcImgBRowA += bytesPerSrcRow + srcRowOffset;
  1797.          srcImgBRowB += bytesPerSrcRow + srcRowOffset;
  1798.          dstImgRow += bytesPerDstRow;
  1799.       }
  1800.    }
  1801.  
  1802.    FREE(tmpRowA);
  1803.    FREE(tmpRowB);
  1804.  
  1805.    /* Luckily we can leverage the make_2d_mipmap() function here! */
  1806.    if (border > 0) {
  1807.       /* do front border image */
  1808.       make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
  1809.                      dstWidth, dstHeight, dstPtr);
  1810.       /* do back border image */
  1811.       make_2d_mipmap(format, 1, srcWidth, srcHeight,
  1812.                      srcPtr + bytesPerSrcImage * (srcDepth - 1),
  1813.                      dstWidth, dstHeight,
  1814.                      dstPtr + bytesPerDstImage * (dstDepth - 1));
  1815.       /* do four remaining border edges that span the image slices */
  1816.       if (srcDepth == dstDepth) {
  1817.          /* just copy border pixels from src to dst */
  1818.          for (img = 0; img < dstDepthNB; img++) {
  1819.             const GLubyte *src;
  1820.             GLubyte *dst;
  1821.  
  1822.             /* do border along [img][row=0][col=0] */
  1823.             src = srcPtr + (img + 1) * bytesPerSrcImage;
  1824.             dst = dstPtr + (img + 1) * bytesPerDstImage;
  1825.             MEMCPY(dst, src, bpt);
  1826.  
  1827.             /* do border along [img][row=dstHeight-1][col=0] */
  1828.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1829.                          + (srcHeight - 1) * bytesPerSrcRow;
  1830.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1831.                          + (dstHeight - 1) * bytesPerDstRow;
  1832.             MEMCPY(dst, src, bpt);
  1833.  
  1834.             /* do border along [img][row=0][col=dstWidth-1] */
  1835.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1836.                          + (srcWidth - 1) * bpt;
  1837.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1838.                          + (dstWidth - 1) * bpt;
  1839.             MEMCPY(dst, src, bpt);
  1840.  
  1841.             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
  1842.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1843.                          + (bytesPerSrcImage - bpt);
  1844.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1845.                          + (bytesPerDstImage - bpt);
  1846.             MEMCPY(dst, src, bpt);
  1847.          }
  1848.       }
  1849.       else {
  1850.          /* average border pixels from adjacent src image pairs */
  1851.          ASSERT(srcDepthNB == 2 * dstDepthNB);
  1852.          for (img = 0; img < dstDepthNB; img++) {
  1853.             const GLubyte *src;
  1854.             GLubyte *dst;
  1855.  
  1856.             /* do border along [img][row=0][col=0] */
  1857.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
  1858.             dst = dstPtr + (img + 1) * bytesPerDstImage;
  1859.             do_row(format, 1, src, src + srcImageOffset, 1, dst);
  1860.  
  1861.             /* do border along [img][row=dstHeight-1][col=0] */
  1862.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1863.                          + (srcHeight - 1) * bytesPerSrcRow;
  1864.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1865.                          + (dstHeight - 1) * bytesPerDstRow;
  1866.             do_row(format, 1, src, src + srcImageOffset, 1, dst);
  1867.  
  1868.             /* do border along [img][row=0][col=dstWidth-1] */
  1869.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1870.                          + (srcWidth - 1) * bpt;
  1871.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1872.                          + (dstWidth - 1) * bpt;
  1873.             do_row(format, 1, src, src + srcImageOffset, 1, dst);
  1874.  
  1875.             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
  1876.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1877.                          + (bytesPerSrcImage - bpt);
  1878.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1879.                          + (bytesPerDstImage - bpt);
  1880.             do_row(format, 1, src, src + srcImageOffset, 1, dst);
  1881.          }
  1882.       }
  1883.    }
  1884. }
  1885.  
  1886.  
  1887. /*
  1888.  * For GL_SGIX_generate_mipmap:
  1889.  * Generate a complete set of mipmaps from texObj's base-level image.
  1890.  * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
  1891.  */
  1892. void
  1893. _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
  1894.                       const struct gl_texture_unit *texUnit,
  1895.                       struct gl_texture_object *texObj)
  1896. {
  1897.    const struct gl_texture_image *srcImage;
  1898.    const struct gl_texture_format *convertFormat;
  1899.    const GLubyte *srcData;
  1900.    GLubyte *dstData;
  1901.    GLint level, maxLevels;
  1902.  
  1903.    ASSERT(texObj);
  1904.    srcImage = texObj->Image[texObj->BaseLevel];
  1905.    ASSERT(srcImage);
  1906.  
  1907.    maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
  1908.    ASSERT(maxLevels > 0);  /* bad target */
  1909.  
  1910.    /* Find convertFormat - the format that do_row() will process */
  1911.    if (srcImage->IsCompressed) {
  1912.       /* setup for compressed textures */
  1913.       GLuint row;
  1914.       GLint  components, size;
  1915.       GLchan *dst;
  1916.  
  1917.       assert(texObj->Target == GL_TEXTURE_2D);
  1918.  
  1919.       if (srcImage->Format == GL_RGB) {
  1920.          convertFormat = &_mesa_texformat_rgb;
  1921.          components = 3;
  1922.       }
  1923.       else if (srcImage->Format == GL_RGBA) {
  1924.          convertFormat = &_mesa_texformat_rgba;
  1925.          components = 4;
  1926.       }
  1927.       else {
  1928.          _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps");
  1929.          return;
  1930.       }
  1931.  
  1932.       /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
  1933.       size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE)
  1934.          * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
  1935.       /* 20 extra bytes, just be safe when calling last FetchTexel */
  1936.       srcData = (GLubyte*) MALLOC(size);
  1937.       if (!srcData) {
  1938.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
  1939.          return;
  1940.       }
  1941.       dstData = (GLubyte*)MALLOC(size / 2);  /* 1/4 would probably be OK */
  1942.       if (!dstData) {
  1943.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
  1944.          FREE((void *) srcData);
  1945.          return;
  1946.       }
  1947.  
  1948.       /* decompress base image here */
  1949.       dst = (GLchan *) srcData;
  1950.       for (row = 0; row < srcImage->Height; row++) {
  1951.          GLuint col;
  1952.          for (col = 0; col < srcImage->Width; col++) {
  1953.             (*srcImage->FetchTexel)(srcImage, col, row, 0, (GLvoid *) dst);
  1954.             dst += components;
  1955.          }
  1956.       }
  1957.    }
  1958.    else {
  1959.       /* uncompressed */
  1960.       convertFormat = srcImage->TexFormat;
  1961.    }
  1962.  
  1963.    for (level = texObj->BaseLevel; level < texObj->MaxLevel
  1964.            && level < maxLevels - 1; level++) {
  1965.       /* generate image[level+1] from image[level] */
  1966.       const struct gl_texture_image *srcImage;
  1967.       struct gl_texture_image *dstImage;
  1968.       GLint srcWidth, srcHeight, srcDepth;
  1969.       GLint dstWidth, dstHeight, dstDepth;
  1970.       GLint border, bytesPerTexel;
  1971.  
  1972.       /* get src image parameters */
  1973.       srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
  1974.       ASSERT(srcImage);
  1975.       srcWidth = srcImage->Width;
  1976.       srcHeight = srcImage->Height;
  1977.       srcDepth = srcImage->Depth;
  1978.       border = srcImage->Border;
  1979.  
  1980.       /* compute next (level+1) image size */
  1981.       if (srcWidth - 2 * border > 1) {
  1982.          dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
  1983.       }
  1984.       else {
  1985.          dstWidth = srcWidth; /* can't go smaller */
  1986.       }
  1987.       if (srcHeight - 2 * border > 1) {
  1988.          dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
  1989.       }
  1990.       else {
  1991.          dstHeight = srcHeight; /* can't go smaller */
  1992.       }
  1993.       if (srcDepth - 2 * border > 1) {
  1994.          dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
  1995.       }
  1996.       else {
  1997.          dstDepth = srcDepth; /* can't go smaller */
  1998.       }
  1999.  
  2000.       if (dstWidth == srcWidth &&
  2001.           dstHeight == srcHeight &&
  2002.           dstDepth == srcDepth) {
  2003.          /* all done */
  2004.          if (srcImage->IsCompressed) {
  2005.             FREE((void *) srcData);
  2006.             FREE(dstData);
  2007.          }
  2008.          return;
  2009.       }
  2010.  
  2011.       /* get dest gl_texture_image */
  2012.       dstImage = _mesa_select_tex_image(ctx, texUnit, target, level+1);
  2013.       if (!dstImage) {
  2014.          dstImage = _mesa_alloc_texture_image();
  2015.          if (!dstImage) {
  2016.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  2017.             return;
  2018.          }
  2019.          _mesa_set_tex_image(texObj, target, level + 1, dstImage);
  2020.       }
  2021.  
  2022.       /* Free old image data */
  2023.       if (dstImage->Data)
  2024.          MESA_PBUFFER_FREE(dstImage->Data);
  2025.  
  2026.       /* initialize new image */
  2027.       _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
  2028.                                  dstDepth, border, srcImage->IntFormat);
  2029.       dstImage->DriverData = NULL;
  2030.       dstImage->TexFormat = srcImage->TexFormat;
  2031.       dstImage->FetchTexel = srcImage->FetchTexel;
  2032.       ASSERT(dstImage->TexFormat);
  2033.       ASSERT(dstImage->FetchTexel);
  2034.  
  2035.       /* Alloc new teximage data buffer.
  2036.        * Setup src and dest data pointers.
  2037.        */
  2038.       if (dstImage->IsCompressed) {
  2039.          ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
  2040.          dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize);
  2041.          if (!dstImage->Data) {
  2042.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  2043.             return;
  2044.          }
  2045.          /* srcData and dstData are already set */
  2046.          ASSERT(srcData);
  2047.          ASSERT(dstData);
  2048.       }
  2049.       else {
  2050.          bytesPerTexel = srcImage->TexFormat->TexelBytes;
  2051.          ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
  2052.          dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
  2053.                                              * bytesPerTexel);
  2054.          if (!dstImage->Data) {
  2055.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  2056.             return;
  2057.          }
  2058.          srcData = (const GLubyte *) srcImage->Data;
  2059.          dstData = (GLubyte *) dstImage->Data;
  2060.       }
  2061.  
  2062.       /*
  2063.        * We use simple 2x2 averaging to compute the next mipmap level.
  2064.        */
  2065.       switch (target) {
  2066.          case GL_TEXTURE_1D:
  2067.             make_1d_mipmap(convertFormat, border,
  2068.                            srcWidth, srcData,
  2069.                            dstWidth, dstData);
  2070.             break;
  2071.          case GL_TEXTURE_2D:
  2072.          case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
  2073.          case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
  2074.          case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
  2075.          case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
  2076.          case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
  2077.          case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
  2078.             make_2d_mipmap(convertFormat, border,
  2079.                            srcWidth, srcHeight, srcData,
  2080.                            dstWidth, dstHeight, dstData);
  2081.             break;
  2082.          case GL_TEXTURE_3D:
  2083.             make_3d_mipmap(convertFormat, border,
  2084.                            srcWidth, srcHeight, srcDepth, srcData,
  2085.                            dstWidth, dstHeight, dstDepth, dstData);
  2086.             break;
  2087.          case GL_TEXTURE_RECTANGLE_NV:
  2088.             /* no mipmaps, do nothing */
  2089.             break;
  2090.          default:
  2091.             _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
  2092.             return;
  2093.       }
  2094.  
  2095.       if (dstImage->IsCompressed) {
  2096.          GLubyte *temp;
  2097.          /* compress image from dstData into dstImage->Data */
  2098.          const GLenum srcFormat = convertFormat->BaseFormat;
  2099.          GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
  2100.                                                           dstWidth);
  2101.          ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
  2102.          _mesa_compress_teximage(ctx,
  2103.                                  dstWidth, dstHeight, /* size */
  2104.                                  srcFormat,           /* source format */
  2105.                                  dstData,             /* source buffer */
  2106.                                  dstWidth,            /* source row stride */
  2107.                                  dstImage->TexFormat, /* dest format */
  2108.                                  (GLubyte *)dstImage->Data,      /* dest buffer */
  2109.                                  dstRowStride );      /* dest row stride */
  2110.  
  2111.          /* swap src and dest pointers */
  2112.          temp = (GLubyte *) srcData;
  2113.          srcData = dstData;
  2114.          dstData = temp;
  2115.       }
  2116.  
  2117.    } /* loop over mipmap levels */
  2118. }
  2119.