texstore.c revision 2ce0654ebabc7fc6a2881f51e496e4e1f7533087
12ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul/* $Id: texstore.c,v 1.43 2002/10/18 17:41:45 brianp Exp $ */
28e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
38e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
48e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Mesa 3-D graphics library
542f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul * Version:  4.1
68e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
7aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
88e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
98e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * copy of this software and associated documentation files (the "Software"),
118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * to deal in the Software without restriction, including without limitation
128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense,
138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * and/or sell copies of the Software, and to permit persons to whom the
148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Software is furnished to do so, subject to the following conditions:
158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The above copyright notice and this permission notice shall be included
178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * in all copies or substantial portions of the Software.
188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Authors:
298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   Brian Paul
308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul/*
3389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * The GL texture image functions in teximage.c basically just do
3489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * error checking and data structure allocation.  They in turn call
3589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * device driver functions which actually copy/convert/store the user's
3689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * texture image data.
3789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *
3889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * However, most device drivers will be able to use the fallback functions
3989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * in this file.  That is, most drivers will have the following bit of
4089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * code:
4189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
4289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
4389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
4489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *   etc...
4589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *
4689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * Texture image processing is actually kind of complicated.  We have to do:
4789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *    Format/type conversions
4889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *    pixel unpacking
4989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *    pixel transfer (scale, bais, lookup, convolution!, etc)
5089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *
5189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * These functions can handle most everything, including processing full
5289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * images and sub-images.
5389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul */
5489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
5589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
5689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
57e75d2424e53d6023f4414e40694cd467e5392b96Brian Paul#include "colormac.h"
588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "context.h"
598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "convolve.h"
608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "image.h"
618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "macros.h"
628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "mem.h"
6389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul#include "texcompress.h"
64371ef9c058b0d59bfb62689b64af1b29a2214d9eGareth Hughes#include "texformat.h"
658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "teximage.h"
668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "texstore.h"
677d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul#include "texutil.h"
688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Given an internal texture format enum or 1, 2, 3, 4 return the
728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * number of components for the format.  Return -1 if invalid enum.
758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulstatic GLint
778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulcomponents_in_intformat( GLint format )
788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   switch (format) {
808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA:
818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA4:
828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA8:
838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA12:
848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA16:
858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 1:
878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE:
888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE4:
898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE8:
908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12:
918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE16:
928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 2:
948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE_ALPHA:
958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE4_ALPHA4:
968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE6_ALPHA2:
978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE8_ALPHA8:
988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12_ALPHA4:
998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12_ALPHA12:
1008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE16_ALPHA16:
1018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 2;
1028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY:
1038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY4:
1048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY8:
1058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY12:
1068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY16:
1078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
1088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 3:
1098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB:
1108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_R3_G3_B2:
1118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB4:
1128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB5:
1138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB8:
1148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB10:
1158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB12:
1168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB16:
1178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 3;
1188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 4:
1198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA:
1208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA2:
1218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA4:
1228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB5_A1:
1238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA8:
1248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB10_A2:
1258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA12:
1268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA16:
1278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 4;
1288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX:
1298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX1_EXT:
1308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX2_EXT:
1318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX4_EXT:
1328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX8_EXT:
1338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX12_EXT:
1348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX16_EXT:
1358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
136f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT:
137f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT16_SGIX:
138f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT24_SGIX:
139f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT32_SGIX:
140f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         return 1;
141c5b995066020191982b2315fc45d05e068eee761Brian Paul      case GL_YCBCR_MESA:
142c5b995066020191982b2315fc45d05e068eee761Brian Paul         return 2; /* Y + (Cb or Cr) */
1438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      default:
1448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return -1;  /* error */
1458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
1468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
1478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
1508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This function is used to transfer the user's image data into a texture
1518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * image buffer.  We handle both full texture images and subtexture images.
1528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * We also take care of all image transfer operations here, including
1538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * convolution, scale/bias, colortables, etc.
1548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
15589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * The destination texel type is always GLchan.
15689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * The destination texel format is one of the 6 basic types.
1578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
1588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * A hardware driver may use this as a helper routine to unpack and
1598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * apply pixel transfer ops into a temporary image buffer.  Then,
1608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * convert the temporary image into the special hardware format.
1618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
1628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Input:
1638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   dimensions - 1, 2, or 3
16489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *   texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
16589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul *                   GL_RGB or GL_RGBA (the destination format)
16656671022f97cfbc199a47b3338125431e42030eeBrian Paul *   texDestAddr - destination image address
1678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
1688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   dstXoffset, dstYoffset, dstZoffset - position to store the image within
1698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *      the destination 3D texture
17056671022f97cfbc199a47b3338125431e42030eeBrian Paul *   dstRowStride, dstImageStride - dest image strides in bytes
1718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
1728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
1738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcPacking - describes packing of incoming image.
1741c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   transferOps - mask of pixel transfer operations
1758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
1767d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paulstatic void
1777d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paultransfer_teximage(GLcontext *ctx, GLuint dimensions,
1787d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLenum texDestFormat, GLvoid *texDestAddr,
1797d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint srcWidth, GLint srcHeight, GLint srcDepth,
1807d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
1817d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint dstRowStride, GLint dstImageStride,
1827d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLenum srcFormat, GLenum srcType,
1837d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  const GLvoid *srcAddr,
1841c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                  const struct gl_pixelstore_attrib *srcPacking,
1851c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                  GLuint transferOps)
1868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
1878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint texComponents;
1888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(ctx);
1908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dimensions >= 1 && dimensions <= 3);
19189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texDestFormat == GL_LUMINANCE ||
19289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          texDestFormat == GL_INTENSITY ||
19389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          texDestFormat == GL_LUMINANCE_ALPHA ||
19489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          texDestFormat == GL_ALPHA ||
19589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          texDestFormat == GL_RGB ||
19689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          texDestFormat == GL_RGBA);
19756671022f97cfbc199a47b3338125431e42030eeBrian Paul   ASSERT(texDestAddr);
1988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcWidth >= 1);
1998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcHeight >= 1);
2008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcDepth >= 1);
2018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstXoffset >= 0);
2028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstYoffset >= 0);
2038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstZoffset >= 0);
2048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstRowStride >= 0);
2058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstImageStride >= 0);
2068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcAddr);
2078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcPacking);
2088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
2090299ad753224372c7a6147f598fdad33f576a714Brian Paul   texComponents = components_in_intformat(texDestFormat);
2108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
2118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* try common 2D texture cases first */
2121c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
2138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
2140299ad753224372c7a6147f598fdad33f576a714Brian Paul      if (srcFormat == texDestFormat) {
2158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
2168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * GL_LUMINANCE_ALPHA, etc. texture formats.  Use memcpy().
2178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
2188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLchan *src = (const GLchan *) _mesa_image_address(
2198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcPacking, srcAddr, srcWidth, srcHeight,
2208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcFormat, srcType, 0, 0, 0);
2218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
2228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                               srcWidth, srcFormat, srcType);
2238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
224a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul         GLchan *dst = (GLchan *) texDestAddr
225a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstYoffset * (dstRowStride / sizeof(GLchan))
226a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstXoffset * texComponents;
2278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
2288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            MEMCPY(dst, src, srcHeight * widthInBytes);
2298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         else {
2318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLint i;
2328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (i = 0; i < srcHeight; i++) {
2338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               MEMCPY(dst, src, widthInBytes);
234a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               src += (srcRowStride / sizeof(GLchan));
235a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               dst += (dstRowStride / sizeof(GLchan));
2368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
2378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2388e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return;  /* all done */
2398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2400299ad753224372c7a6147f598fdad33f576a714Brian Paul      else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
2418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /* commonly used by Quake */
2428e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLchan *src = (const GLchan *) _mesa_image_address(
2438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcPacking, srcAddr, srcWidth, srcHeight,
2448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcFormat, srcType, 0, 0, 0);
2458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
2468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                               srcWidth, srcFormat, srcType);
247a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul         GLchan *dst = (GLchan *) texDestAddr
248a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstYoffset * (dstRowStride / sizeof(GLchan))
249a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstXoffset * texComponents;
2508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint i, j;
2518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (i = 0; i < srcHeight; i++) {
2528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLchan *s = src;
2538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *d = dst;
2548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (j = 0; j < srcWidth; j++) {
2558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*red*/
2568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*green*/
2578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*blue*/
2588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               s++;          /*alpha*/
2598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
260a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            src += (srcRowStride / sizeof(GLchan));
261a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            dst += (dstRowStride / sizeof(GLchan));
2628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return;  /* all done */
2648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
2668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
2678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /*
2688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * General case solutions
2698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
2700299ad753224372c7a6147f598fdad33f576a714Brian Paul   if (texDestFormat == GL_COLOR_INDEX) {
2718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      /* color index texture */
2721ceda0f84fdfe07951071fdf4fa643d07f09a4d7Brian Paul      const GLenum texType = CHAN_TYPE;
2738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      GLint img, row;
27442f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul      GLchan *dest = (GLchan *) texDestAddr
27542f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                   + dstZoffset * (dstImageStride / sizeof(GLchan))
276a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                   + dstYoffset * (dstRowStride / sizeof(GLchan))
277a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                   + dstXoffset * texComponents;
2788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      for (img = 0; img < srcDepth; img++) {
2798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLchan *destRow = dest;
2808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (row = 0; row < srcHeight; row++) {
2818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLvoid *src = _mesa_image_address(srcPacking,
2828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
2841c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                    srcType, src, srcPacking, transferOps);
285a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            destRow += (dstRowStride / sizeof(GLchan));
2868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         dest += dstImageStride;
2888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
290c5b995066020191982b2315fc45d05e068eee761Brian Paul   else if (texDestFormat == GL_YCBCR_MESA) {
291c5b995066020191982b2315fc45d05e068eee761Brian Paul      /* YCbCr texture */
292c5b995066020191982b2315fc45d05e068eee761Brian Paul      GLint img, row;
293c5b995066020191982b2315fc45d05e068eee761Brian Paul      GLushort *dest = (GLushort *) texDestAddr
294c5b995066020191982b2315fc45d05e068eee761Brian Paul                     + dstZoffset * (dstImageStride / sizeof(GLushort))
295c5b995066020191982b2315fc45d05e068eee761Brian Paul                     + dstYoffset * (dstRowStride / sizeof(GLushort))
296c5b995066020191982b2315fc45d05e068eee761Brian Paul                     + dstXoffset * texComponents;
297c5b995066020191982b2315fc45d05e068eee761Brian Paul      ASSERT(ctx->Extensions.MESA_ycbcr_texture);
298c5b995066020191982b2315fc45d05e068eee761Brian Paul      printf("copy ycbcr\n");
299c5b995066020191982b2315fc45d05e068eee761Brian Paul      for (img = 0; img < srcDepth; img++) {
300c5b995066020191982b2315fc45d05e068eee761Brian Paul         GLushort *destRow = dest;
301c5b995066020191982b2315fc45d05e068eee761Brian Paul         for (row = 0; row < srcHeight; row++) {
302c5b995066020191982b2315fc45d05e068eee761Brian Paul            const GLvoid *srcRow = _mesa_image_address(srcPacking,
303c5b995066020191982b2315fc45d05e068eee761Brian Paul                                          srcAddr, srcWidth, srcHeight,
304c5b995066020191982b2315fc45d05e068eee761Brian Paul                                          srcFormat, srcType, img, row, 0);
305c5b995066020191982b2315fc45d05e068eee761Brian Paul            MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort));
306c5b995066020191982b2315fc45d05e068eee761Brian Paul            destRow += (dstRowStride / sizeof(GLushort));
307c5b995066020191982b2315fc45d05e068eee761Brian Paul         }
308c5b995066020191982b2315fc45d05e068eee761Brian Paul         dest += dstImageStride / sizeof(GLushort);
309c5b995066020191982b2315fc45d05e068eee761Brian Paul      }
310c5b995066020191982b2315fc45d05e068eee761Brian Paul   }
3110299ad753224372c7a6147f598fdad33f576a714Brian Paul   else if (texDestFormat == GL_DEPTH_COMPONENT) {
312f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      /* Depth texture (shadow maps) */
313f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      GLint img, row;
31456671022f97cfbc199a47b3338125431e42030eeBrian Paul      GLubyte *dest = (GLubyte *) texDestAddr
31556671022f97cfbc199a47b3338125431e42030eeBrian Paul                    + dstZoffset * dstImageStride
316a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                    + dstYoffset * (dstRowStride / sizeof(GLchan))
317f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul                    + dstXoffset * texComponents;
318f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      for (img = 0; img < srcDepth; img++) {
31956671022f97cfbc199a47b3338125431e42030eeBrian Paul         GLubyte *destRow = dest;
320f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         for (row = 0; row < srcHeight; row++) {
321f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul            const GLvoid *src = _mesa_image_address(srcPacking,
322f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
32356671022f97cfbc199a47b3338125431e42030eeBrian Paul            _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
324e75d2424e53d6023f4414e40694cd467e5392b96Brian Paul                                    srcType, src, srcPacking);
325a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            destRow += (dstRowStride / sizeof(GLchan));
326f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         }
327f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         dest += dstImageStride;
328f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      }
329f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul   }
3308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   else {
3318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      /* regular, color texture */
3328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
3338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
3348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
3358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /*
3368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * Fill texture image with convolution
3378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
3388e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint img, row;
3398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint convWidth = srcWidth, convHeight = srcHeight;
3408e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLfloat *tmpImage, *convImage;
3418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
3428e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (!tmpImage) {
34308836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
3448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            return;
3458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
3468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
3478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (!convImage) {
34808836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
3498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            FREE(tmpImage);
3508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            return;
3518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
3528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (img = 0; img < srcDepth; img++) {
3548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLfloat *srcf;
3558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLfloat *dstf = tmpImage;
3568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *dest;
3578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* unpack and do transfer ops up to convolution */
3598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < srcHeight; row++) {
3608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               const GLvoid *src = _mesa_image_address(srcPacking,
3618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcAddr, srcWidth, srcHeight,
3628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcFormat, srcType, img, row, 0);
3638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
3648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                         srcFormat, srcType, src, srcPacking,
3651c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                         transferOps & IMAGE_PRE_CONVOLUTION_BITS,
3668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                         GL_TRUE);
3678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               dstf += srcWidth * 4;
3688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* convolve */
3718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            if (dimensions == 1) {
3728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               ASSERT(ctx->Pixel.Convolution1DEnabled);
3738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
3748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            else {
3768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               if (ctx->Pixel.Convolution2DEnabled) {
3778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
3788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          tmpImage, convImage);
3798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               }
3808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               else {
3818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  ASSERT(ctx->Pixel.Separable2DEnabled);
3828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
3838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                           tmpImage, convImage);
3848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               }
3858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* packing and transfer ops after convolution */
3888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            srcf = convImage;
38942f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul            dest = (GLchan *) texDestAddr
39042f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                 + (dstZoffset + img) * (dstImageStride / sizeof(GLchan))
391a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                 + dstYoffset * (dstRowStride / sizeof(GLchan));
3928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < convHeight; row++) {
3938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_pack_float_rgba_span(ctx, convWidth,
3948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          (const GLfloat (*)[4]) srcf,
3950299ad753224372c7a6147f598fdad33f576a714Brian Paul                                          texDestFormat, CHAN_TYPE,
3968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          dest, &_mesa_native_packing,
3971c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                          transferOps
3988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          & IMAGE_POST_CONVOLUTION_BITS);
3998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               srcf += convWidth * 4;
400a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               dest += (dstRowStride / sizeof(GLchan));
4018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
4028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
4038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
4048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         FREE(convImage);
4058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         FREE(tmpImage);
4068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
4078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      else {
4088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /*
4098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * no convolution
4108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
4118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint img, row;
41242f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul         GLchan *dest = (GLchan *) texDestAddr
41342f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                      + dstZoffset * (dstImageStride / sizeof(GLchan))
414a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                      + dstYoffset * (dstRowStride / sizeof(GLchan))
415a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                      + dstXoffset * texComponents;
4168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (img = 0; img < srcDepth; img++) {
4178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *destRow = dest;
4188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < srcHeight; row++) {
4198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               const GLvoid *srcRow = _mesa_image_address(srcPacking,
4208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcAddr, srcWidth, srcHeight,
4218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcFormat, srcType, img, row, 0);
4220299ad753224372c7a6147f598fdad33f576a714Brian Paul               _mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
4230299ad753224372c7a6147f598fdad33f576a714Brian Paul                                       destRow, srcFormat, srcType, srcRow,
4241c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                       srcPacking, transferOps);
425a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               destRow += (dstRowStride / sizeof(GLchan));
4268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
42742f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul            dest += dstImageStride / sizeof(GLchan);
4288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
4298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
4308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
4318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
4328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
4338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
4348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
4358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
4367d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * Transfer a texture image from user space to <destAddr> applying all
4377d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * needed image transfer operations and storing the result in the format
4387d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * specified by <dstFormat>.  <dstFormat> may be any format from texformat.h.
4397d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * Input:
4401c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dimensions - 1, 2 or 3
4411c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   baseInternalFormat - base format of the internal texture format
4421c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *       specified by the user.  This is very important, see below.
4431c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstFormat - destination image format
4441c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstAddr - destination address
4451c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcWidth, srcHeight, srcDepth - size of source iamge
4461c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstX/Y/Zoffset - as specified by glTexSubImage
4477d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul *   dstRowStride - stride between dest rows in bytes
44842f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul *   dstImageStride - stride between dest images in bytes
4491c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcFormat, srcType - incoming image format and datatype
4501c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcAddr - source image address
4511c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcPacking - packing params of source image
4527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul *
4537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * XXX this function is a bit more complicated than it should be.  If
4547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * _mesa_convert_texsubimage[123]d could handle any dest/source formats
4557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
4567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * could simplify things here.
4577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul */
4587d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paulvoid
4597d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
4601c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        GLenum baseInternalFormat,
4617d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const struct gl_texture_format *dstFormat,
4627d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLvoid *dstAddr,
4637d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
4647d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
4657d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint dstRowStride, GLint dstImageStride,
4667d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLenum srcFormat, GLenum srcType,
4677d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const GLvoid *srcAddr,
4687d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const struct gl_pixelstore_attrib *srcPacking)
4697d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul{
4707d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
4717d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
4727d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   GLboolean makeTemp;
4731c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLuint transferOps = ctx->_ImageTransferState;
4741c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLboolean freeSourceData = GL_FALSE;
4751c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
4761c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
477e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   assert(baseInternalFormat > 0);
47889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(baseInternalFormat == GL_LUMINANCE ||
47989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          baseInternalFormat == GL_INTENSITY ||
48089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          baseInternalFormat == GL_LUMINANCE_ALPHA ||
48189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          baseInternalFormat == GL_ALPHA ||
48289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          baseInternalFormat == GL_RGB ||
48389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul          baseInternalFormat == GL_RGBA);
484e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
4851c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (transferOps & IMAGE_CONVOLUTION_BIT) {
4861c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
4871c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                         &postConvHeight);
4881c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   }
4891c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
4901c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   /*
4911c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * Consider this scenario:  The user's source image is GL_RGB and the
4921c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * requested internal format is GL_LUMINANCE.  Now suppose the device
4931c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
4941c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * texture format.  In that case we still need to do an intermediate
4951c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * conversion to luminance format so that the incoming red channel gets
4961c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * replicated into the dest red, green and blue channels.  The following
4971c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * code takes care of that.
4981c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    */
4991c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (dstFormat->BaseFormat != baseInternalFormat) {
5001c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      /* Allocate storage for temporary image in the baseInternalFormat */
5011c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
5021c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         * sizeof(GLchan);
5031c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
5041c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint tmpRowStride = texelSize * postConvWidth;
5051c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
5061c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      GLvoid *tmpImage = MALLOC(bytes);
5071c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (!tmpImage)
5081c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         return;
5091c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
5101c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcWidth, srcHeight, srcDepth,
5111c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        0, 0, 0, /* x/y/zoffset */
5121c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        tmpRowStride, tmpImgStride,
5131c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
5141c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
5151c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      /* this is our new source image */
5161c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcWidth = postConvWidth;
5171c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcHeight = postConvHeight;
5181c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcFormat = baseInternalFormat;
5191c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcType = CHAN_TYPE;
5201c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcAddr = tmpImage;
5211c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcPacking = &_mesa_native_packing;
5221c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      freeSourceData = GL_TRUE;
5231c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transferOps = 0;  /* image transfer ops were completed */
5241c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   }
5257d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5261c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   /* Let the optimized tex conversion functions take a crack at the
5271c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * image conversion if the dest format is a h/w format.
5281c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    */
5297d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (_mesa_is_hardware_tex_format(dstFormat)) {
5301c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (transferOps) {
5317d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         makeTemp = GL_TRUE;
5327d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5337d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else {
5347d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         if (dimensions == 1) {
5357d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
5367d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstXoffset,
5377d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcWidth,
5387d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcFormat, srcType,
5397d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcPacking, srcAddr,
5407d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstAddr);
5417d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5427d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         else if (dimensions == 2) {
5437d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
5447d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstXoffset, dstYoffset,
5457d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcWidth, srcHeight,
5467d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstRowStridePixels,
5477d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcFormat, srcType,
5487d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcPacking, srcAddr,
5497d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstAddr);
5507d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5517d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         else {
5527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            assert(dimensions == 3);
5537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
5547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstXoffset, dstYoffset, dstZoffset,
5557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcWidth, srcHeight, srcDepth,
5567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstRowStridePixels, dstImageStridePixels,
5577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcFormat, srcType,
5587d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcPacking, srcAddr, dstAddr);
5597d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5607d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         if (!makeTemp) {
5617d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            /* all done! */
5621c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul            if (freeSourceData)
5631c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul               FREE((void *) srcAddr);
5647d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            return;
5657d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5667d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5677d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5687d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   else {
5697d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* software texture format */
5707d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      makeTemp = GL_FALSE;
5717d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5727d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5737d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (makeTemp) {
5747d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
5757d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLenum tmpFormat;
5767d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLuint tmpComps, tmpTexelSize;
5777d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLint tmpRowStride, tmpImageStride;
5787d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLubyte *tmpImage;
5797d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5801c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (transferOps & IMAGE_CONVOLUTION_BIT) {
5817d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
5827d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                            &postConvHeight);
5837d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5847d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5851c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      tmpFormat = dstFormat->BaseFormat;
5867d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpComps = _mesa_components_in_format(tmpFormat);
58736f3712e85cafef1b038189678030f6ef4f8b7e9Brian Paul      tmpTexelSize = tmpComps * sizeof(GLchan);
5887d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpRowStride = postConvWidth * tmpTexelSize;
5897d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
5907d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
5917d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                    srcDepth * tmpTexelSize);
5921c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (!tmpImage) {
5931c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         if (freeSourceData)
5941c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul            FREE((void *) srcAddr);
5957d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         return;
5961c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      }
5977d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5987d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
5997d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        srcWidth, srcHeight, srcDepth,
6007d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        0, 0, 0, /* x/y/zoffset */
6017d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        tmpRowStride, tmpImageStride,
6021c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
6031c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
6041c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (freeSourceData)
6051c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         FREE((void *) srcAddr);
6067d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
6077d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* the temp image is our new source image */
6087d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcWidth = postConvWidth;
6097d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcHeight = postConvHeight;
6107d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcFormat = tmpFormat;
6117d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcType = CHAN_TYPE;
6127d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcAddr = tmpImage;
6137d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcPacking = &_mesa_native_packing;
6141c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      freeSourceData = GL_TRUE;
6157d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
6167d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
6177d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (_mesa_is_hardware_tex_format(dstFormat)) {
6187d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      assert(makeTemp);
6197d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      if (dimensions == 1) {
6207d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
6217d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
6227d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstXoffset,
6237d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcWidth,
6247d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcFormat, srcType,
6257d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcPacking, srcAddr,
6267d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstAddr);
6277d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
6287d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
6297d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else if (dimensions == 2) {
6307d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
6317d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
6327d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstXoffset, dstYoffset,
6337d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcWidth, srcHeight,
6347d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstRowStridePixels,
6357d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcFormat, srcType,
6367d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcPacking, srcAddr,
6377d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstAddr);
6387d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
6397d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
6407d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else {
6417d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
6427d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
6437d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstXoffset, dstYoffset, dstZoffset,
6447d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcWidth, srcHeight, srcDepth,
6457d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstRowStridePixels, dstImageStridePixels,
6467d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcFormat, srcType,
6477d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcPacking, srcAddr, dstAddr);
6487d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
6497d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
6507d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
6517d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   else {
6527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* software format */
6537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      assert(!makeTemp);
6541c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
6557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        srcWidth, srcHeight, srcDepth,
6567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        dstXoffset, dstYoffset, dstZoffset,
6577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        dstRowStride, dstImageStride,
6581c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
6597d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
6601c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
6611c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (freeSourceData)
6621c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      FREE((void *) srcAddr);  /* the temp image */
6637d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul}
6647d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
6657d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
66689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
66789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul/**
66889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * Given a user's uncompressed texture image, this function takes care of
66989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * pixel unpacking, pixel transfer, format conversion and compression.
67089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul */
67189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paulstatic void
67289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paultransfer_compressed_teximage(GLcontext *ctx, GLuint dimensions,
67389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                             GLsizei width, GLsizei height, GLsizei depth,
67489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                             GLenum srcFormat, GLenum srcType,
67589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                             const struct gl_pixelstore_attrib *unpacking,
67689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                             const GLvoid *source,
6772ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                             const struct gl_texture_format *dstFormat,
6782ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                             GLubyte *dest,
67989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                             GLint dstRowStride)
68089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul{
68189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLchan *tempImage = NULL;
68289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLint srcRowStride;
68389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLenum baseFormat;
68489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
68589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(dimensions == 2);
6862ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   /* TexelBytes is zero if and only if it's a compressed format */
6872ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   ASSERT(dstFormat->TexelBytes == 0);
68889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
6892ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   baseFormat = dstFormat->BaseFormat;
69089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
69189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (srcFormat != baseFormat || srcType != CHAN_TYPE ||
69289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul       ctx->_ImageTransferState != 0 || unpacking->SwapBytes) {
69389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      /* need to convert user's image to texImage->Format, GLchan */
69489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint comps = components_in_intformat(baseFormat);
69589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint postConvWidth = width, postConvHeight = height;
69689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
69789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      /* XXX convolution untested */
69889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
69989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
70089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                            &postConvHeight);
70189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      }
70289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
70389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan));
70489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      if (!tempImage) {
70589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
70689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         return;
70789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      }
70889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_teximage(ctx, dimensions,
70989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        baseFormat,             /* dest format */
71089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        tempImage,              /* dst address */
71189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        width, height, depth,   /* src size */
71289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        0, 0, 0,                /* x/y/zoffset */
71389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        comps * width,          /* dst row stride */
71489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        comps * width * height, /* dst image stride */
71589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        srcFormat, srcType,     /* src format, type */
71689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        source, unpacking,      /* src and src packing */
71789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                        ctx->_ImageTransferState);
71889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      source = tempImage;
71989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      width = postConvWidth;
72089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      height = postConvHeight;
72189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      srcRowStride = width;
72289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
72389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
72489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      if (unpacking->RowLength)
72589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         srcRowStride = unpacking->RowLength;
72689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      else
72789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         srcRowStride = width;
72889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
72989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
73089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   _mesa_compress_teximage(ctx, width, height, baseFormat,
73189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           (const GLchan *) source, srcRowStride,
73289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           dstFormat, dest, dstRowStride);
73389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (tempImage) {
73489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      FREE(tempImage);
73589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
73689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul}
73789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
73889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
73989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
7407d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul/*
74189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * This is the software fallback for Driver.TexImage1D()
74289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexImage2D().
7438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
7448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
7458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
7468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
7478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
7488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
7498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
7508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint border,
7518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const GLvoid *pixels,
7528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
7538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
7548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
7558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
7568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint postConvWidth = width;
757e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
7588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
7608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
7618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
7628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7637d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
7647d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
7657d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
7667d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
7677d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
7689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
7698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
77019d1e432612cf7db797da11793b13a6c1c6aac16Gareth Hughes   texelBytes = texImage->TexFormat->TexelBytes;
77119d1e432612cf7db797da11793b13a6c1c6aac16Gareth Hughes
7728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
77389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed)
77489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = texImage->CompressedSize;
77589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else
77689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = postConvWidth * texelBytes;
777aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
7787d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
7797d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
7807d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
7817d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
7828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
78389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (!pixels)
78489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      return;
78589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
78689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* unpack image, apply transfer ops and store in texImage->Data */
78789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
78889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
78989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       width);
79089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 1, width, 1, 1,
79189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type, packing,
7922ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   pixels, texImage->TexFormat,
79389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   (GLubyte *) texImage->Data, dstRowStride);
79489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
79589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
796f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 1,
79789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Format, /* base format */
798f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
79989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              width, 1, 1,  /* src size */
80089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, 0, 0,      /* dstX/Y/Zoffset */
801f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstRowStride */
802f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstImageStride */
803f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
80489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
805f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
80689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* GL_SGIS_generate_mipmap */
80789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
80889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_generate_mipmap(ctx, target,
80989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
81089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            texObj);
8113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
8128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
8138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
81689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * This is the software fallback for Driver.TexImage2D()
81789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexImage2D().
8188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
8198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
8208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
8218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
8228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
8238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
8248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
8258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint height, GLint border,
8268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const void *pixels,
8278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
8288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
8298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
8308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
8318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint postConvWidth = width, postConvHeight = height;
832e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
8338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
8358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
8368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                         &postConvHeight);
8378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
8388e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8397d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
8407d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
8417d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
8427d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
8437d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
8443893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
8452c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes
8462c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes   texelBytes = texImage->TexFormat->TexelBytes;
8478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
84989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed)
85089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = texImage->CompressedSize;
85189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else
85289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = postConvWidth * postConvHeight * texelBytes;
853aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
8547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
8557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
8567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
8577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
8588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
85989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (!pixels)
86089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      return;
86189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
86289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* unpack image, apply transfer ops and store in texImage->Data */
86389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
86489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
86589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       width);
86689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 2, width, height, 1,
86789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type, packing,
8682ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   pixels, texImage->TexFormat,
86989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   (GLubyte *) texImage->Data, dstRowStride);
87089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
87189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
872f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 2,
87389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Format,
874f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
87589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              width, height, 1,  /* src size */
87689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, 0, 0,           /* dstX/Y/Zoffset */
87789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Width * texelBytes, /* dstRowStride */
878f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstImageStride */
879f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
88089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
881f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
88289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* GL_SGIS_generate_mipmap */
88389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
88489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_generate_mipmap(ctx, target,
88589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
88689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            texObj);
8873893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
8888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
8898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
89389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * This is the software fallback for Driver.TexImage3D()
89489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexImage3D().
8958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
8968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
8978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
8988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
8998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
9008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
9018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
9028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint height, GLint depth, GLint border,
9038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const void *pixels,
9048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
9058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
9068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
9078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
908e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
9098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9107d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
9117d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
9127d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
9137d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
9147d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
9159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
9162c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes
917197c526d63e1d4ea96f29eece392cdc389770b38Brian Paul   texelBytes = texImage->TexFormat->TexelBytes;
9188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
92089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed)
92189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = texImage->CompressedSize;
92289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else
92389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      sizeInBytes = width * height * depth * texelBytes;
924aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
9257d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
9267d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
9277d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
9287d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
9298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
93089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (!pixels)
93189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      return;
93289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
93389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* unpack image, apply transfer ops and store in texImage->Data */
93489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
93589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
93689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       width);
93789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 3, width, height, depth,
93889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type, packing,
9392ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   pixels, texImage->TexFormat,
94089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   (GLubyte *) texImage->Data, dstRowStride);
94189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
94289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
943f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 3,
94489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Format,
945f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
94689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              width, height, depth, /* src size */
94789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, 0, 0,  /* dstX/Y/Zoffset */
94889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Width * texelBytes, /* dstRowStride */
949f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->Width * texImage->Height * texelBytes,
950f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
95189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
952f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
95389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* GL_SGIS_generate_mipmap */
95489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
95589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_generate_mipmap(ctx, target,
95689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
95789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                            texObj);
9583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
9598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
9608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
96589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * This is the software fallback for Driver.TexSubImage1D()
96689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexSubImage1D().
9678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
9688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
9698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
9708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint width,
9718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
9728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
9738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
9748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
9758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
97689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
97789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
97889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       texImage->Width);
97989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0,
98089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->IntFormat,
98189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Width,
98289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Data);
98389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 1,             /* dimensions */
98489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   width, 1, 1,        /* size to replace */
98589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type,       /* source format/type */
98689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   packing,            /* source packing */
98789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   pixels,             /* source data */
9882ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   texImage->TexFormat,/* dest format */
98989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   dest, dstRowStride);
99089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
99189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
99289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_transfer_teximage(ctx, 1,
99389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Format,
99489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->TexFormat, texImage->Data,
99589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              width, 1, 1, /* src size */
99689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              xoffset, 0, 0, /* dest offsets */
99789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, /* dstRowStride */
99889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, /* dstImageStride */
99989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              format, type, pixels, packing);
100089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
10013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
10023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
10033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1004d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
1005d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
10063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
10073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
10088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
10098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
10108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
101189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
10128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
101389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * This is the software fallback for Driver.TexSubImage2D()
101489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexSubImage2D().
10158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
10168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
10178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
10188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint yoffset,
10198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height,
10208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
10218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
10228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
10238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
10248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
102589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
102689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
102789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       texImage->Width);
102889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
102989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->IntFormat,
103089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Width,
103189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Data);
103289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 2,             /* dimensions */
103389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   width, height, 1,   /* size to replace */
103489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type,       /* source format/type */
103589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   packing,            /* source packing */
103689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   pixels,             /* source data */
10372ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   texImage->TexFormat,/* dest format */
103889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   dest, dstRowStride);
103989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
104089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
104189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_transfer_teximage(ctx, 2,
104289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Format,
104389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->TexFormat, texImage->Data,
104489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              width, height, 1, /* src size */
104589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              xoffset, yoffset, 0, /* dest offsets */
104689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              texImage->Width *texImage->TexFormat->TexelBytes,
104789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              0, /* dstImageStride */
104889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                              format, type, pixels, packing);
104989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
10503893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
10513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
10523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1053d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
1054d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
10553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
10563893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
10578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
10588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
10598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
10608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
10618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexSubImage3D().
106289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * and Driver.CopyTexSubImage3D().
10638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
10648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
10658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
10668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint yoffset, GLint zoffset,
10678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height, GLint depth,
10688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
10698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
10708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
10718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
10728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
107389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (texImage->IsCompressed) {
107489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
107589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                       texImage->Width);
107689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset,
107789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->IntFormat,
107889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Width,
107989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                                     texImage->Data);
108089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      transfer_compressed_teximage(ctx, 3,              /* dimensions */
108189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   width, height, depth,/* size to replace */
108289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   format, type,       /* source format/type */
108389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   packing,            /* source packing */
108489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   pixels,             /* source data */
10852ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                   texImage->TexFormat,/* dest format */
108689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                   dest, dstRowStride);
108789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
108889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   else {
108989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      const GLint texelBytes = texImage->TexFormat->TexelBytes;
109089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_transfer_teximage(ctx, 3,
109189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           texImage->Format,
10921c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           texImage->TexFormat, texImage->Data,
10938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           width, height, depth, /* src size */
10948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           xoffset, yoffset, xoffset, /* dest offsets */
109589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           texImage->Width * texelBytes,  /* dst row stride */
109638f28665bf9fb5b2464738ca5074848ec2777ae1Gareth Hughes                           texImage->Width * texImage->Height * texelBytes,
10978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           format, type, pixels, packing);
109889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
109989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
11003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
11013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1102d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
1103d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
11043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
11053893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
11068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
11078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11102aadbf41dfd4f63c6118d0ad2d8659d289cbe454Brian Paul
11112aadbf41dfd4f63c6118d0ad2d8659d289cbe454Brian Paul/*
11128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage1D()
11138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
11148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
11158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
11168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
11178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint border,
11188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
11198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
11208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
11218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
112289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* this space intentionally left blank */
11238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
11248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
11288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage2D()
11298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
11308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
11318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
11328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
11338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint height, GLint border,
11348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
11358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
11368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
11378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
113889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* This is pretty simple, basically just do a memcpy without worrying
113989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul    * about the usual image unpacking or image transfer operations.
11408e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
114189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texObj);
114289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage);
114389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage->Width > 0);
114489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage->Height > 0);
114589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage->Depth == 1);
114689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
114789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
114889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* choose the texture format */
114989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
115089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
115189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                          internalFormat, 0, 0);
115289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   assert(texImage->TexFormat);
115389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
115489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
115589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* allocate storage */
115689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
115789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   if (!texImage->Data) {
115889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
115989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      return;
116089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
116189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
116289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* copy the data */
116389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT(texImage->CompressedSize == imageSize);
116489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   MEMCPY(texImage->Data, data, imageSize);
11658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
11668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
11708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage3D()
11718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
11728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
11738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
11748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
11758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint height, GLint depth,
11768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint border,
11778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
11788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
11798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
11808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
118189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* this space intentionally left blank */
11828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
11838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
11858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
118689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul/**
118789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * Fallback for Driver.CompressedTexSubImage1D()
1188e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul */
1189e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paulvoid
119089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul_mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
119189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLint level,
119289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLint xoffset, GLsizei width,
119389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLenum format,
119489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLsizei imageSize, const GLvoid *data,
119589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     struct gl_texture_object *texObj,
119689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     struct gl_texture_image *texImage)
1197e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul{
119889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* this space intentionally left blank */
1199e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul}
1200e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
1201e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
120289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul/**
120389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * Fallback for Driver.CompressedTexSubImage2D()
120489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul */
120589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paulvoid
120689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul_mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
120789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLint level,
120889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLint xoffset, GLint yoffset,
120989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLsizei width, GLsizei height,
121089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLenum format,
121189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     GLsizei imageSize, const GLvoid *data,
121289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     struct gl_texture_object *texObj,
121389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                     struct gl_texture_image *texImage)
121489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul{
121589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLint bytesPerRow, destRowStride, srcRowStride;
121689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLint i, rows;
121789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLubyte *dest;
121889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   const GLubyte *src;
121989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
122089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* these should have been caught sooner */
122189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT((width & 3) == 0 || width == 2 || width == 1);
122289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT((height & 3) == 0 || height == 2 || height == 1);
122389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT((xoffset & 3) == 0);
122489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   ASSERT((yoffset & 3) == 0);
122589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
122689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
122789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   src = (const GLubyte *) data;
122889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
122989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
123089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                               texImage->Width);
123189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
123289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                         texImage->IntFormat,
123389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                         texImage->Width, texImage->Data);
123489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
123589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   bytesPerRow = srcRowStride;
123689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   rows = height / 4;
123789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
123889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   for (i = 0; i < rows; i++) {
123989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      MEMCPY(dest, src, bytesPerRow);
124089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      dest += destRowStride;
124189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      src += srcRowStride;
124289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
124389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul}
124489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
124589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
124689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul/**
124789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul * Fallback for Driver.CompressedTexSubImage3D()
124889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul */
124989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paulvoid
125089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul_mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
125189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                GLint level,
125289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                GLint xoffset, GLint yoffset, GLint zoffset,
125389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                GLsizei width, GLsizei height, GLsizei depth,
125489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                GLenum format,
125589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                GLsizei imageSize, const GLvoid *data,
125689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                struct gl_texture_object *texObj,
125789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                struct gl_texture_image *texImage)
125889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul{
125989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   /* this space intentionally left blank */
126089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul}
126189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
126289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
126389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
126489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
1265e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
1266e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul/*
12678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the fallback for Driver.TestProxyTexImage().
12688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
12698e39ad2cd67d49be40ff0822f3269affdf83d601Brian PaulGLboolean
12708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
12718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint internalFormat, GLenum format, GLenum type,
12728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height, GLint depth, GLint border)
12738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
12748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_unit *texUnit;
12758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_object *texObj;
12768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_image *texImage;
12778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
12788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   (void) format;
12798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   (void) type;
12808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
12818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
12828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texObj = _mesa_select_tex_object(ctx, texUnit, target);
12838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
12848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
12858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* We always pass.
12868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * The core Mesa code will have already tested the image size, etc.
12879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * If a driver has more stringent texture limits to enforce it will
12888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * have to override this function.
12898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
12907d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
12917d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
12927d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
12937d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
12947d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
12958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
12968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   return GL_TRUE;
12978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
12983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
12993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul/*
13023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Average together two rows of a source image to produce a single new
13033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * row in the dest image.  It's legal for the two source rows to point
13049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * to the same data.  The source width must be equal to either the
13059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * dest width or two times the dest width.
13063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul */
13073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
13089228e17bb5bf219269daeed5cbfdd912c118e926Brian Pauldo_row(const struct gl_texture_format *format, GLint srcWidth,
13099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul       const GLvoid *srcRowA, const GLvoid *srcRowB,
13109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul       GLint dstWidth, GLvoid *dstRow)
13113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
13129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
13139228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
13149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
13159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
13169228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
13173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   switch (format->MesaFormat) {
13183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_RGBA:
13193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
13209228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
13213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
13223893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
13233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
13247c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
13259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
13269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1327f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
13289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1329f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
13309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1331f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
13329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][3] = (rowA[j][3] + rowA[k][3] +
1333f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][3] + rowB[k][3]) / 4;
13343893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
13353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
13363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
13373893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_RGB:
13383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
13399228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
13403893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
13413893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
13423893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
13437c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
13449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
13459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1346f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
13479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1348f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
13499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1350f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
13513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
13523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
13533893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
13543893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_ALPHA:
13553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_LUMINANCE:
13563893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_INTENSITY:
13573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_COLOR_INDEX:
13583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
13599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
13603893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan *rowA = (const GLchan *) srcRowA;
13613893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan *rowB = (const GLchan *) srcRowB;
13623893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan *dst = (GLchan *) dstRow;
13637c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
13649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
1365f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
13663893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
13673893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
13683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
13693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_LUMINANCE_ALPHA:
13703893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
13719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
13723893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
13733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
13743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
13757c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
13769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
13779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1378f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
13799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1380f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
13813893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
13823893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
13833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
13843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_DEPTH_COMPONENT:
13858bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
13869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
13878bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLfloat *rowA = (const GLfloat *) srcRowA;
13888bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLfloat *rowB = (const GLfloat *) srcRowB;
13898bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLfloat *dst = (GLfloat *) dstRow;
13907c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
13919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
13929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
13938bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
13948bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
13958bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
13968bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   /* Begin hardware formats */
13978bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGBA8888:
13988bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB8888:
13998bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
14009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
14018bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
14028bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
14038bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
14047c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
14059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
14069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1407f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
14089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1409f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
14109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1411f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
14129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][3] = (rowA[j][3] + rowA[k][3] +
1413f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][3] + rowB[k][3]) / 4;
14148bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
14158bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
14168bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
14178bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB888:
14188bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
14199228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
14208bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
14218bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
14228bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
14237c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
14249228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
14259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1426f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
14279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1428f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
14299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1430f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
14318bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
14328bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
14338bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
14348bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB565:
14358bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
14369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
14378bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
14388bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
14398bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
14407c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
14419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
14429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x1f;
14439228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x1f;
14449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x1f;
14459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0x1f;
14469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
14479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
14489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
14499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
14509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
14519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
14529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
14539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
14548bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
14558bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
14568bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
14578bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (blue << 11) | (green << 5) | red;
14588bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
14598bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
14608bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
14618bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB4444:
14628bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
14639228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
14648bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
14658bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
14668bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
14677c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
14689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
14699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0xf;
14709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0xf;
14719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0xf;
14729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0xf;
14739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
14749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
14759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
14769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
14779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
14789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
14799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
14809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
14819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
14829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
14839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
14849228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
14858bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
14868bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
14878bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
14888bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
14898bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
14908bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
14918bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
14928bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
14938bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB1555:
14948bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
14959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
14968bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
14978bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
14988bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
14997c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
15009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
15019228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x1f;
15029228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x1f;
15039228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x1f;
15049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0xf;
15059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
15069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
15079228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
15089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
15099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
15109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
15119228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
15129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
15139228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
15149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
15159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
15169228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
15178bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
15188bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
15198bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
15208bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
15218bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
15228bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
15238bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
15248bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
15258bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_AL88:
15268bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
15279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
15288bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
15298bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
15308bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
15317c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
15329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
15339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
15349228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         rowB[j][0] + rowB[k][0]) >> 2;
15359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
15369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         rowB[j][1] + rowB[k][1]) >> 2;
15378bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
15388bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
15398bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
15408bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB332:
15418bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
15429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
15438bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowA = (const GLubyte *) srcRowA;
15448bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowB = (const GLubyte *) srcRowB;
15458bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte *dst = (GLubyte *) dstRow;
15467c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
15479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
15489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x3;
15499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x3;
15509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x3;
15519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0x3;
15529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
15539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
15549228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
15559228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
15569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
15579228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
15589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
15599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
15608bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
15618bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
15628bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
15638bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (blue << 5) | (green << 2) | red;
15648bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
15658bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
15668bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
15678bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_A8:
15688bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_L8:
15698bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_I8:
15708bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_CI8:
15718bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
15729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
15738bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowA = (const GLubyte *) srcRowA;
15748bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowB = (const GLubyte *) srcRowB;
15758bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte *dst = (GLubyte *) dstRow;
15767c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
15779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
15789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
15798bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
15808bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
15818bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
15823893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   default:
15833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      _mesa_problem(NULL, "bad format in do_row()");
15843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
15853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
15863893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
15873893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
15889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul/*
15899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * These functions generate a 1/2-size mipmap image from a source image.
15909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * Texture borders are handled by copying or averaging the source image's
15919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * border texels, depending on the scale-down factor.
15929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul */
15933893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
15943893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
15953893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_1d_mipmap(const struct gl_texture_format *format, GLint border,
15963893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, const GLubyte *srcPtr,
15973893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLubyte *dstPtr)
15983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
15993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint bpt = format->TexelBytes;
16003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLubyte *src;
16013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLubyte *dst;
16023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* skip the border pixel, if any */
16043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   src = srcPtr + border * bpt;
16053893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   dst = dstPtr + border * bpt;
16063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* we just duplicate the input row, kind of hack, saves code */
16089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   do_row(format, srcWidth - 2 * border, src, src,
16099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul          dstWidth - 2 * border, dst);
16103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (border) {
16123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* copy left-most pixel from source */
16133893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr, srcPtr, bpt);
16143893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* copy right-most pixel from source */
16153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
16163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth - 1) * bpt,
16173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             bpt);
16183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
16193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
16203893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16223893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
16233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_2d_mipmap(const struct gl_texture_format *format, GLint border,
16243893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
16253893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
16263893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
16273893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint bpt = format->TexelBytes;
16289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
16299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstWidthNB = dstWidth - 2 * border;
16309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstHeightNB = dstHeight - 2 * border;
16313893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint srcRowStride = bpt * srcWidth;
16323893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint dstRowStride = bpt * dstWidth;
16333893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLubyte *srcA, *srcB;
16343893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLubyte *dst;
16359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint row, colStride;
16369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
16379228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   colStride = (srcWidth == dstWidth) ? 1 : 2;
16383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* Compute src and dst pointers, skipping any border */
16403893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   srcA = srcPtr + border * ((srcWidth + 1) * bpt);
16413893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (srcHeight > 1)
16423893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB = srcA + srcRowStride;
16433893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   else
16443893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB = srcA;
16453893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   dst = dstPtr + border * ((dstWidth + 1) * bpt);
16463893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   for (row = 0; row < dstHeightNB; row++) {
16489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB, srcA, srcB,
16499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB, dst);
16503893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcA += 2 * srcRowStride;
16513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB += 2 * srcRowStride;
16523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      dst += dstRowStride;
16533893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
16543893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16558bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   /* This is ugly but probably won't be used much */
16563893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (border > 0) {
16573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* fill in dest border */
16583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower-left border pixel */
16593893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr, srcPtr, bpt);
16603893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower-right border pixel */
16613893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
16623893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth - 1) * bpt, bpt);
16633893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper-left border pixel */
16643893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
16653893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
16663893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper-right border pixel */
16673893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
16683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
16693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower border */
16709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB,
16719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             srcPtr + bpt,
16729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             srcPtr + bpt,
16739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB, dstPtr + bpt);
16743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper border */
16759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB,
16763893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
16773893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
16789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB,
16793893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
16803893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* left and right borders */
16819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      if (srcHeight == dstHeight) {
16829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* copy border pixel from src to dst */
16839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (row = 1; row < srcHeight; row++) {
16849228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dstPtr + dstWidth * row * bpt,
16859228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + srcWidth * row * bpt, bpt);
16869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
16879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
16889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
16899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
16909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      else {
16919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* average two src pixels each dest pixel */
16929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (row = 0; row < dstHeightNB; row += 2) {
16939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1,
16949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
16959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
16969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   1, dstPtr + (dstWidth * row + 1) * bpt);
16979228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1,
16989228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
16999228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
17009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
17019228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
17023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
17033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
17043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
17053893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
17083893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_3d_mipmap(const struct gl_texture_format *format, GLint border,
17093893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, GLint srcHeight, GLint srcDepth,
17103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               const GLubyte *srcPtr,
17113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLint dstHeight, GLint dstDepth,
17123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLubyte *dstPtr)
17133893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
17149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint bpt = format->TexelBytes;
17159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
17169228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcDepthNB = srcDepth - 2 * border;
17179228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstWidthNB = dstWidth - 2 * border;
17189228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstHeightNB = dstHeight - 2 * border;
17199228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstDepthNB = dstDepth - 2 * border;
17209228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLvoid *tmpRowA, *tmpRowB;
17213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLint img, row;
17229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint bytesPerSrcImage, bytesPerDstImage;
17239228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint bytesPerSrcRow, bytesPerDstRow;
17249228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint srcImageOffset, srcRowOffset;
17253893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17265c749d9e3c7824c0ba5b22e37d0ea5cbd54d6d2dBrian Paul   (void) srcDepthNB; /* silence warnings */
17275c749d9e3c7824c0ba5b22e37d0ea5cbd54d6d2dBrian Paul
17289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Need two temporary row buffers */
17299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   tmpRowA = MALLOC(srcWidth * bpt);
17309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (!tmpRowA)
17319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      return;
17329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   tmpRowB = MALLOC(srcWidth * bpt);
17339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (!tmpRowB) {
17349228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      FREE(tmpRowA);
17353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
17363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
17373893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17389228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerSrcImage = srcWidth * srcHeight * bpt;
17399228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerDstImage = dstWidth * dstHeight * bpt;
17409228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
17419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerSrcRow = srcWidth * bpt;
17429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerDstRow = dstWidth * bpt;
17433893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Offset between adjacent src images to be averaged together */
17459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
17463893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Offset between adjacent src rows to be averaged together */
17489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
17493893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /*
17519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * Need to average together up to 8 src pixels for each dest pixel.
17529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * Break that down into 3 operations:
17539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   1. take two rows from source image and average them together.
17549228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   2. take two rows from next source image and average them together.
17559228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   3. take the two averaged rows and average them for the final dst row.
17569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    */
17573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
17589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /*
17594e9676fb13f60ecdbc247b120031f18cd3febcb0Brian Paul   _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
17609228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul          srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
17619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   */
17629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
17639228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   for (img = 0; img < dstDepthNB; img++) {
17649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* first source image pointer, skipping border */
17659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *imgSrcA = srcPtr
17669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
17679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + img * (bytesPerSrcImage + srcImageOffset);
17689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* second source image pointer, skipping border */
17699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
17709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* address of the dest image, skipping border */
17719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      GLubyte *imgDst = dstPtr
17729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
17739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + img * bytesPerDstImage;
17749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
17759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* setup the four source row pointers and the dest row pointer */
17769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgARowA = imgSrcA;
17779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
17789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgBRowA = imgSrcB;
17799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
17809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      GLubyte *dstImgRow = imgDst;
17819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
17829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      for (row = 0; row < dstHeightNB; row++) {
17839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together two rows from first src image */
17849228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
17859228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                srcWidthNB, tmpRowA);
17869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together two rows from second src image */
17879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
17889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                srcWidthNB, tmpRowB);
17899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together the temp rows to make the final row */
17909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, tmpRowA, tmpRowB,
17919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                dstWidthNB, dstImgRow);
17929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* advance to next rows */
17939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgARowA += bytesPerSrcRow + srcRowOffset;
17949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgARowB += bytesPerSrcRow + srcRowOffset;
17959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
17969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
17979228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         dstImgRow += bytesPerDstRow;
17983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
17993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
18003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
18013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   FREE(tmpRowA);
18023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   FREE(tmpRowB);
18039228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Luckily we can leverage the make_2d_mipmap() function here! */
18059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (border > 0) {
18069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do front border image */
18079228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
18089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstWidth, dstHeight, dstPtr);
18099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do back border image */
18109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      make_2d_mipmap(format, 1, srcWidth, srcHeight,
18119228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     srcPtr + bytesPerSrcImage * (srcDepth - 1),
18129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstWidth, dstHeight,
18139228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstPtr + bytesPerDstImage * (dstDepth - 1));
18149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do four remaining border edges that span the image slices */
18159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      if (srcDepth == dstDepth) {
18169228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* just copy border pixels from src to dst */
18179228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (img = 0; img < dstDepthNB; img++) {
18189228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLubyte *src;
18199228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            GLubyte *dst;
18209228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18219228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=0] */
18229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img + 1) * bytesPerSrcImage;
18239228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage;
18249228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
18259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=0] */
18279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcHeight - 1) * bytesPerSrcRow;
18299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstHeight - 1) * bytesPerDstRow;
18319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
18329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=dstWidth-1] */
18349228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcWidth - 1) * bpt;
18369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18379228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstWidth - 1) * bpt;
18389228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
18399228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18409228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
18419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerSrcImage - bpt);
18439228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerDstImage - bpt);
18459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
18469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
18479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
18489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      else {
18499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* average border pixels from adjacent src image pairs */
18509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         ASSERT(srcDepthNB == 2 * dstDepthNB);
18519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (img = 0; img < dstDepthNB; img++) {
18529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLubyte *src;
18539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            GLubyte *dst;
18549228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18559228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=0] */
18569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
18579228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage;
18589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
18599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18609228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=0] */
18619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcHeight - 1) * bytesPerSrcRow;
18639228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstHeight - 1) * bytesPerDstRow;
18659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
18669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=dstWidth-1] */
18689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcWidth - 1) * bpt;
18709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstWidth - 1) * bpt;
18729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
18739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
18749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
18759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
18769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerSrcImage - bpt);
18779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
18789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerDstImage - bpt);
18799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
18809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
18819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
18829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   }
18833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
18843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
18853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
18863893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul/*
18873893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * For GL_SGIX_generate_mipmap:
18883893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Generate a complete set of mipmaps from texObj's base-level image.
18893893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
18903893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul */
18913893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulvoid
1892d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
18933893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                      const struct gl_texture_unit *texUnit,
18943893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                      struct gl_texture_object *texObj)
18953893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
18962ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   const struct gl_texture_image *srcImage;
18972ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   const struct gl_texture_format *convertFormat;
189889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   const GLubyte *srcData;
189989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   GLubyte *dstData;
19007c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz   GLint level;
1901cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul   GLint maxLevels = 0;
19023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
19033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   ASSERT(texObj);
19042ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   srcImage = texObj->Image[texObj->BaseLevel];
19052ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   ASSERT(srcImage);
19063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
19078afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   switch (texObj->Target) {
19088afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_1D:
1909cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxTextureLevels;
19103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
19118afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_2D:
1912cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxTextureLevels;
19133893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
19148afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_3D:
1915cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.Max3DTextureLevels;
19163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
19178afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_CUBE_MAP_ARB:
1918cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxCubeTextureLevels;
19193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
19208afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_RECTANGLE_NV:
19218afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul      maxLevels = 1;
19228afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul      break;
19233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   default:
19243893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      _mesa_problem(ctx,
19253893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                    "Bad texture object dimension in _mesa_generate_mipmaps");
19263893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
19273893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
19283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
19292ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   /* Find convertFormat - the format that do_row() will process */
19302ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   if (srcImage->IsCompressed) {
19312ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      /* setup for compressed textures */
19322ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      GLint row, components, size;
19332ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      GLchan *dst;
19342ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul
19352ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      assert(texObj->Target == GL_TEXTURE_2D);
19362ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul
19372ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      if (srcImage->Format == GL_RGB) {
19382ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         convertFormat = &_mesa_texformat_rgb;
19392ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         components = 3;
19402ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      }
19412ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      else if (srcImage->Format == GL_RGBA) {
19422ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         convertFormat = &_mesa_texformat_rgba;
19432ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         components = 4;
19442ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      }
19452ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      else {
19462ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps");
19472ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         return;
19482ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      }
19492ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul
19502ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
19512ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE)
19522ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
19532ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      /* 20 extra bytes, just be safe when calling last FetchTexel */
19542ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      srcData = MALLOC(size);
19552ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      if (!srcData) {
19562ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
19572ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         return;
19582ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      }
19592ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      dstData = MALLOC(size / 2);  /* 1/4 would probably be OK */
19602ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      if (!dstData) {
19612ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
19622ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         FREE((void *) srcData);
19632ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         return;
19642ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      }
19652ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul
19662ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      /* decompress base image here */
19672ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      dst = (GLchan *) srcData;
19682ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      for (row = 0; row < srcImage->Height; row++) {
19692ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         GLint col;
19702ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         for (col = 0; col < srcImage->Width; col++) {
19712ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul            (*srcImage->FetchTexel)(srcImage, col, row, 0, (GLvoid *) dst);
19722ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul            dst += components;
197389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         }
197489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      }
197589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul   }
19762ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   else {
19772ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      /* uncompressed */
19782ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul      convertFormat = srcImage->TexFormat;
19792ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul   }
198089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
19818bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   for (level = texObj->BaseLevel; level < texObj->MaxLevel
1982cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul           && level < maxLevels - 1; level++) {
19839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* generate image[level+1] from image[level] */
19843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      const struct gl_texture_image *srcImage;
19853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      struct gl_texture_image *dstImage;
19863893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint srcWidth, srcHeight, srcDepth;
19873893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint dstWidth, dstHeight, dstDepth;
19883893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint border, bytesPerTexel;
19893893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
199089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      /* get src image parameters */
19913893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcImage = texObj->Image[level];
19923893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      ASSERT(srcImage);
19933893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcWidth = srcImage->Width;
19943893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcHeight = srcImage->Height;
19953893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcDepth = srcImage->Depth;
19963893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      border = srcImage->Border;
19973893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
19983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* compute next (level+1) image size */
19993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcWidth - 2 * border > 1) {
20003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
20013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
20033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstWidth = srcWidth; /* can't go smaller */
20043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20053893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcHeight - 2 * border > 1) {
20063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
20073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20083893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
20093893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstHeight = srcHeight; /* can't go smaller */
20103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcDepth - 2 * border > 1) {
20123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
20133893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20143893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
20153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstDepth = srcDepth; /* can't go smaller */
20163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
20183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (dstWidth == srcWidth &&
20193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul          dstHeight == srcHeight &&
20203893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul          dstDepth == srcDepth) {
20213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         /* all done */
202289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         if (srcImage->IsCompressed) {
202389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            FREE((void *) srcData);
202489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            FREE(dstData);
202589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         }
20263893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         return;
20273893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
20283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
2029d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* get dest gl_texture_image */
2030d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage = _mesa_select_tex_image(ctx, texUnit, target, level+1);
2031d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      if (!dstImage) {
2032d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         dstImage = _mesa_alloc_texture_image();
20333893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         if (!dstImage) {
20343893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
20353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul            return;
20363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
2037d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_set_tex_image(texObj, target, level + 1, dstImage);
2038d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
20393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
2040d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* Free old image data */
2041d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      if (dstImage->Data)
2042d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         MESA_PBUFFER_FREE(dstImage->Data);
2043d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
2044d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* initialize new image */
2045e1cb2fb571ee47b59020db7627e554b7d227e454Brian Paul      _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
204689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                 dstDepth, border, srcImage->IntFormat);
2047d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->DriverData = NULL;
2048d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->TexFormat = srcImage->TexFormat;
2049d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->FetchTexel = srcImage->FetchTexel;
2050d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      ASSERT(dstImage->TexFormat);
2051d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      ASSERT(dstImage->FetchTexel);
2052d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
205389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      /* Alloc new teximage data buffer.
205489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul       * Setup src and dest data pointers.
205589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul       */
205689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      if (dstImage->IsCompressed) {
205789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
205889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize);
205989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         if (!dstImage->Data) {
206089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
206189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            return;
206289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         }
20632ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         /* srcData and dstData are already set */
206489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         ASSERT(srcData);
206589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         ASSERT(dstData);
206689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      }
206789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      else {
206889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         bytesPerTexel = srcImage->TexFormat->TexelBytes;
206989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
207089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
207189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                                             * bytesPerTexel);
207289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         if (!dstImage->Data) {
207389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
207489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            return;
207589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         }
207689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         srcData = (const GLubyte *) srcImage->Data;
207789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         dstData = (GLubyte *) dstImage->Data;
2078d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
2079d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
2080d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /*
2081d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul       * We use simple 2x2 averaging to compute the next mipmap level.
2082d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul       */
2083d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      switch (target) {
208489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_1D:
20852ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul            make_1d_mipmap(convertFormat, border,
208689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           srcWidth, srcData,
208789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           dstWidth, dstData);
208889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            break;
208989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_2D:
209089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
209189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
209289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
209389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
209489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
209589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
20962ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul            make_2d_mipmap(convertFormat, border,
209789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           srcWidth, srcHeight, srcData,
209889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           dstWidth, dstHeight, dstData);
209989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            break;
210089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_3D:
21012ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul            make_3d_mipmap(convertFormat, border,
210289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           srcWidth, srcHeight, srcDepth, srcData,
210389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul                           dstWidth, dstHeight, dstDepth, dstData);
210489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            break;
210589fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         case GL_TEXTURE_RECTANGLE_NV:
210689fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            /* no mipmaps, do nothing */
210789fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            break;
210889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         default:
210989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
211089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul            return;
2111d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
211289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
211389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      if (dstImage->IsCompressed) {
211489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         GLubyte *temp;
21152ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         /* compress image from dstData into dstImage->Data */
21162ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         const GLenum srcFormat = convertFormat->BaseFormat;
21172ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
21182ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                                          dstWidth);
21192ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
21202ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul         _mesa_compress_teximage(ctx,
21212ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstWidth, dstHeight, /* size */
21222ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 srcFormat,           /* source format */
21232ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstData,             /* source buffer */
21242ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstWidth,            /* source row stride */
21252ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstImage->TexFormat, /* dest format */
21262ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstImage->Data,      /* dest buffer */
21272ce0654ebabc7fc6a2881f51e496e4e1f7533087Brian Paul                                 dstRowStride );      /* dest row stride */
212889fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
212989fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         /* swap src and dest pointers */
213089fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         temp = (GLubyte *) srcData;
213189fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         srcData = dstData;
213289fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul         dstData = temp;
213389fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul      }
213489fb06fcc11cbe3f23521312155d6c55d869f526Brian Paul
2135d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul   } /* loop over mipmap levels */
21363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
2137