texstore.c revision d5bbbd41c431ad93c0867d5b0b234426d8570499
1d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul/* $Id: texstore.c,v 1.39 2002/09/16 17:57:14 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
32e75d2424e53d6023f4414e40694cd467e5392b96Brian Paul#include "colormac.h"
338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "context.h"
348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "convolve.h"
358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "image.h"
368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "macros.h"
378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "mem.h"
38371ef9c058b0d59bfb62689b64af1b29a2214d9eGareth Hughes#include "texformat.h"
398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "teximage.h"
408e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul#include "texstore.h"
417d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul#include "texutil.h"
428e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Given an internal texture format enum or 1, 2, 3, 4 return the
468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * corresponding _base_ internal format:  GL_ALPHA, GL_LUMINANCE,
478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.  Return the
488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * number of components for the format.  Return -1 if invalid enum.
496b406bf09dc18f4d84ccb636d043c990a30da4e1Gareth Hughes *
506b406bf09dc18f4d84ccb636d043c990a30da4e1Gareth Hughes * GH: Do we really need this?  We have the number of bytes per texel
516b406bf09dc18f4d84ccb636d043c990a30da4e1Gareth Hughes * in the texture format structures, so why don't we just use that?
528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulstatic GLint
548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulcomponents_in_intformat( GLint format )
558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   switch (format) {
578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA:
588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA4:
598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA8:
608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA12:
618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_ALPHA16:
628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 1:
648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE:
658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE4:
668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE8:
678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12:
688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE16:
698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 2:
718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE_ALPHA:
728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE4_ALPHA4:
738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE6_ALPHA2:
748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE8_ALPHA8:
758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12_ALPHA4:
768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE12_ALPHA12:
778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_LUMINANCE16_ALPHA16:
788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 2;
798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY:
808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY4:
818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY8:
828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY12:
838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_INTENSITY16:
848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 3:
868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB:
878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_R3_G3_B2:
888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB4:
898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB5:
908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB8:
918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB10:
928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB12:
938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB16:
948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 3;
958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case 4:
968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA:
978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA2:
988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA4:
998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB5_A1:
1008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA8:
1018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGB10_A2:
1028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA12:
1038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_RGBA16:
1048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 4;
1058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX:
1068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX1_EXT:
1078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX2_EXT:
1088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX4_EXT:
1098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX8_EXT:
1108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX12_EXT:
1118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      case GL_COLOR_INDEX16_EXT:
1128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return 1;
113f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT:
114f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT16_SGIX:
115f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT24_SGIX:
116f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      case GL_DEPTH_COMPONENT32_SGIX:
117f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         return 1;
1188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      default:
1198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return -1;  /* error */
1208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
1218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
1228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
1258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This function is used to transfer the user's image data into a texture
1268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * image buffer.  We handle both full texture images and subtexture images.
1278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * We also take care of all image transfer operations here, including
1288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * convolution, scale/bias, colortables, etc.
1298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
1308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The destination texel channel type is always GLchan.
1318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
1328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * A hardware driver may use this as a helper routine to unpack and
1338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * apply pixel transfer ops into a temporary image buffer.  Then,
1348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * convert the temporary image into the special hardware format.
1358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
1368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Input:
1378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   dimensions - 1, 2, or 3
1388e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
1398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *               GL_RGB or GL_RGBA
14056671022f97cfbc199a47b3338125431e42030eeBrian Paul *   texDestAddr - destination image address
1418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
1428e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   dstXoffset, dstYoffset, dstZoffset - position to store the image within
1438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *      the destination 3D texture
14456671022f97cfbc199a47b3338125431e42030eeBrian Paul *   dstRowStride, dstImageStride - dest image strides in bytes
1458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
1468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
1478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *   srcPacking - describes packing of incoming image.
1481c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   transferOps - mask of pixel transfer operations
1498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
1507d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paulstatic void
1517d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paultransfer_teximage(GLcontext *ctx, GLuint dimensions,
1527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLenum texDestFormat, GLvoid *texDestAddr,
1537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint srcWidth, GLint srcHeight, GLint srcDepth,
1547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
1557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLint dstRowStride, GLint dstImageStride,
1567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  GLenum srcFormat, GLenum srcType,
1577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                  const GLvoid *srcAddr,
1581c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                  const struct gl_pixelstore_attrib *srcPacking,
1591c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                  GLuint transferOps)
1608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
1618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint texComponents;
1628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(ctx);
1648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dimensions >= 1 && dimensions <= 3);
16556671022f97cfbc199a47b3338125431e42030eeBrian Paul   ASSERT(texDestAddr);
1668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcWidth >= 1);
1678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcHeight >= 1);
1688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcDepth >= 1);
1698e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstXoffset >= 0);
1708e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstYoffset >= 0);
1718e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstZoffset >= 0);
1728e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstRowStride >= 0);
1738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(dstImageStride >= 0);
1748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcAddr);
1758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   ASSERT(srcPacking);
1768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1770299ad753224372c7a6147f598fdad33f576a714Brian Paul   texComponents = components_in_intformat(texDestFormat);
1788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* try common 2D texture cases first */
1801c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
1818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
1820299ad753224372c7a6147f598fdad33f576a714Brian Paul      if (srcFormat == texDestFormat) {
1838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
1848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * GL_LUMINANCE_ALPHA, etc. texture formats.  Use memcpy().
1858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
1868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLchan *src = (const GLchan *) _mesa_image_address(
1878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcPacking, srcAddr, srcWidth, srcHeight,
1888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcFormat, srcType, 0, 0, 0);
1898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                               srcWidth, srcFormat, srcType);
1918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
192a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul         GLchan *dst = (GLchan *) texDestAddr
193a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstYoffset * (dstRowStride / sizeof(GLchan))
194a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstXoffset * texComponents;
1958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
1968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            MEMCPY(dst, src, srcHeight * widthInBytes);
1978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
1988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         else {
1998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLint i;
2008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (i = 0; i < srcHeight; i++) {
2018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               MEMCPY(dst, src, widthInBytes);
202a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               src += (srcRowStride / sizeof(GLchan));
203a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               dst += (dstRowStride / sizeof(GLchan));
2048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
2058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return;  /* all done */
2078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2080299ad753224372c7a6147f598fdad33f576a714Brian Paul      else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
2098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /* commonly used by Quake */
2108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLchan *src = (const GLchan *) _mesa_image_address(
2118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcPacking, srcAddr, srcWidth, srcHeight,
2128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                   srcFormat, srcType, 0, 0, 0);
2138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
2148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                               srcWidth, srcFormat, srcType);
215a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul         GLchan *dst = (GLchan *) texDestAddr
216a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstYoffset * (dstRowStride / sizeof(GLchan))
217a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                     + dstXoffset * texComponents;
2188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint i, j;
2198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (i = 0; i < srcHeight; i++) {
2208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLchan *s = src;
2218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *d = dst;
2228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (j = 0; j < srcWidth; j++) {
2238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*red*/
2248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*green*/
2258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               *d++ = *s++;  /*blue*/
2268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               s++;          /*alpha*/
2278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
228a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            src += (srcRowStride / sizeof(GLchan));
229a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            dst += (dstRowStride / sizeof(GLchan));
2308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         return;  /* all done */
2328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
2348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
2358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /*
2368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * General case solutions
2378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
2380299ad753224372c7a6147f598fdad33f576a714Brian Paul   if (texDestFormat == GL_COLOR_INDEX) {
2398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      /* color index texture */
2401ceda0f84fdfe07951071fdf4fa643d07f09a4d7Brian Paul      const GLenum texType = CHAN_TYPE;
2418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      GLint img, row;
24242f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul      GLchan *dest = (GLchan *) texDestAddr
24342f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                   + dstZoffset * (dstImageStride / sizeof(GLchan))
244a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                   + dstYoffset * (dstRowStride / sizeof(GLchan))
245a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                   + dstXoffset * texComponents;
2468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      for (img = 0; img < srcDepth; img++) {
2478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLchan *destRow = dest;
2488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (row = 0; row < srcHeight; row++) {
2498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLvoid *src = _mesa_image_address(srcPacking,
2508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
2518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
2521c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                    srcType, src, srcPacking, transferOps);
253a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            destRow += (dstRowStride / sizeof(GLchan));
2548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         dest += dstImageStride;
2568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
2578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
2580299ad753224372c7a6147f598fdad33f576a714Brian Paul   else if (texDestFormat == GL_DEPTH_COMPONENT) {
259f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      /* Depth texture (shadow maps) */
260f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      GLint img, row;
26156671022f97cfbc199a47b3338125431e42030eeBrian Paul      GLubyte *dest = (GLubyte *) texDestAddr
26256671022f97cfbc199a47b3338125431e42030eeBrian Paul                    + dstZoffset * dstImageStride
263a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                    + dstYoffset * (dstRowStride / sizeof(GLchan))
264f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul                    + dstXoffset * texComponents;
265f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      for (img = 0; img < srcDepth; img++) {
26656671022f97cfbc199a47b3338125431e42030eeBrian Paul         GLubyte *destRow = dest;
267f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         for (row = 0; row < srcHeight; row++) {
268f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul            const GLvoid *src = _mesa_image_address(srcPacking,
269f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul                srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
27056671022f97cfbc199a47b3338125431e42030eeBrian Paul            _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
271e75d2424e53d6023f4414e40694cd467e5392b96Brian Paul                                    srcType, src, srcPacking);
272a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul            destRow += (dstRowStride / sizeof(GLchan));
273f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         }
274f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul         dest += dstImageStride;
275f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul      }
276f7e1dfeaefda8865252513bc4d880ea8640efe4dBrian Paul   }
2778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   else {
2788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      /* regular, color texture */
2798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
2808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
2818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
2828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /*
2838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * Fill texture image with convolution
2848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
2858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint img, row;
2868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint convWidth = srcWidth, convHeight = srcHeight;
2878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLfloat *tmpImage, *convImage;
2888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
2898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (!tmpImage) {
29008836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
2918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            return;
2928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
2948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         if (!convImage) {
29508836341788a9f9d638d9dc8328510ccd18ddeb5Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
2968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            FREE(tmpImage);
2978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            return;
2988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
2998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (img = 0; img < srcDepth; img++) {
3018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            const GLfloat *srcf;
3028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLfloat *dstf = tmpImage;
3038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *dest;
3048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* unpack and do transfer ops up to convolution */
3068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < srcHeight; row++) {
3078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               const GLvoid *src = _mesa_image_address(srcPacking,
3088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcAddr, srcWidth, srcHeight,
3098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcFormat, srcType, img, row, 0);
3108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
3118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                         srcFormat, srcType, src, srcPacking,
3121c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                         transferOps & IMAGE_PRE_CONVOLUTION_BITS,
3138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                         GL_TRUE);
3148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               dstf += srcWidth * 4;
3158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* convolve */
3188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            if (dimensions == 1) {
3198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               ASSERT(ctx->Pixel.Convolution1DEnabled);
3208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
3218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            else {
3238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               if (ctx->Pixel.Convolution2DEnabled) {
3248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
3258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          tmpImage, convImage);
3268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               }
3278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               else {
3288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  ASSERT(ctx->Pixel.Separable2DEnabled);
3298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                  _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
3308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                           tmpImage, convImage);
3318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               }
3328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            /* packing and transfer ops after convolution */
3358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            srcf = convImage;
33642f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul            dest = (GLchan *) texDestAddr
33742f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                 + (dstZoffset + img) * (dstImageStride / sizeof(GLchan))
338a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                 + dstYoffset * (dstRowStride / sizeof(GLchan));
3398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < convHeight; row++) {
3408e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               _mesa_pack_float_rgba_span(ctx, convWidth,
3418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          (const GLfloat (*)[4]) srcf,
3420299ad753224372c7a6147f598fdad33f576a714Brian Paul                                          texDestFormat, CHAN_TYPE,
3438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          dest, &_mesa_native_packing,
3441c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                          transferOps
3458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                          & IMAGE_POST_CONVOLUTION_BITS);
3468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               srcf += convWidth * 4;
347a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               dest += (dstRowStride / sizeof(GLchan));
3488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
3498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
3508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         FREE(convImage);
3528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         FREE(tmpImage);
3538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
3548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      else {
3558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         /*
3568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          * no convolution
3578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul          */
3588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         GLint img, row;
35942f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul         GLchan *dest = (GLchan *) texDestAddr
36042f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul                      + dstZoffset * (dstImageStride / sizeof(GLchan))
361a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                      + dstYoffset * (dstRowStride / sizeof(GLchan))
362a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul                      + dstXoffset * texComponents;
3638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         for (img = 0; img < srcDepth; img++) {
3648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            GLchan *destRow = dest;
3658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            for (row = 0; row < srcHeight; row++) {
3668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul               const GLvoid *srcRow = _mesa_image_address(srcPacking,
3678e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcAddr, srcWidth, srcHeight,
3688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                              srcFormat, srcType, img, row, 0);
3690299ad753224372c7a6147f598fdad33f576a714Brian Paul               _mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
3700299ad753224372c7a6147f598fdad33f576a714Brian Paul                                       destRow, srcFormat, srcType, srcRow,
3711c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                       srcPacking, transferOps);
372a1503b00f863a48a517939a42d512f9cfe77f79cBrian Paul               destRow += (dstRowStride / sizeof(GLchan));
3738e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul            }
37442f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul            dest += dstImageStride / sizeof(GLchan);
3758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul         }
3768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      }
3778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
3788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
3798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
3828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
3837d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * Transfer a texture image from user space to <destAddr> applying all
3847d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * needed image transfer operations and storing the result in the format
3857d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * specified by <dstFormat>.  <dstFormat> may be any format from texformat.h.
3867d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * Input:
3871c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dimensions - 1, 2 or 3
3881c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   baseInternalFormat - base format of the internal texture format
3891c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *       specified by the user.  This is very important, see below.
3901c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstFormat - destination image format
3911c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstAddr - destination address
3921c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcWidth, srcHeight, srcDepth - size of source iamge
3931c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   dstX/Y/Zoffset - as specified by glTexSubImage
3947d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul *   dstRowStride - stride between dest rows in bytes
39542f916de5cb3f4362e4682cdaa5eea00fe2de857Brian Paul *   dstImageStride - stride between dest images in bytes
3961c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcFormat, srcType - incoming image format and datatype
3971c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcAddr - source image address
3981c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul *   srcPacking - packing params of source image
3997d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul *
4007d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * XXX this function is a bit more complicated than it should be.  If
4017d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * _mesa_convert_texsubimage[123]d could handle any dest/source formats
4027d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
4037d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul * could simplify things here.
4047d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul */
4057d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paulvoid
4067d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul_mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
4071c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        GLenum baseInternalFormat,
4087d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const struct gl_texture_format *dstFormat,
4097d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLvoid *dstAddr,
4107d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
4117d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
4127d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLint dstRowStride, GLint dstImageStride,
4137d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        GLenum srcFormat, GLenum srcType,
4147d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const GLvoid *srcAddr,
4157d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        const struct gl_pixelstore_attrib *srcPacking)
4167d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul{
4177d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
4187d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
4197d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   GLboolean makeTemp;
4201c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLuint transferOps = ctx->_ImageTransferState;
4211c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLboolean freeSourceData = GL_FALSE;
4221c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
4231c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
424e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   assert(baseInternalFormat > 0);
425e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
4261c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (transferOps & IMAGE_CONVOLUTION_BIT) {
4271c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
4281c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                                         &postConvHeight);
4291c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   }
4301c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
4311c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   /*
4321c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * Consider this scenario:  The user's source image is GL_RGB and the
4331c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * requested internal format is GL_LUMINANCE.  Now suppose the device
4341c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
4351c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * texture format.  In that case we still need to do an intermediate
4361c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * conversion to luminance format so that the incoming red channel gets
4371c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * replicated into the dest red, green and blue channels.  The following
4381c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * code takes care of that.
4391c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    */
4401c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (dstFormat->BaseFormat != baseInternalFormat) {
4411c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      /* Allocate storage for temporary image in the baseInternalFormat */
4421c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
4431c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         * sizeof(GLchan);
4441c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
4451c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint tmpRowStride = texelSize * postConvWidth;
4461c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
4471c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      GLvoid *tmpImage = MALLOC(bytes);
4481c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (!tmpImage)
4491c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         return;
4501c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
4511c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcWidth, srcHeight, srcDepth,
4521c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        0, 0, 0, /* x/y/zoffset */
4531c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        tmpRowStride, tmpImgStride,
4541c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
4551c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
4561c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      /* this is our new source image */
4571c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcWidth = postConvWidth;
4581c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcHeight = postConvHeight;
4591c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcFormat = baseInternalFormat;
4601c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcType = CHAN_TYPE;
4611c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcAddr = tmpImage;
4621c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      srcPacking = &_mesa_native_packing;
4631c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      freeSourceData = GL_TRUE;
4641c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transferOps = 0;  /* image transfer ops were completed */
4651c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   }
4667d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
4671c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   /* Let the optimized tex conversion functions take a crack at the
4681c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    * image conversion if the dest format is a h/w format.
4691c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul    */
4707d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (_mesa_is_hardware_tex_format(dstFormat)) {
4711c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (transferOps) {
4727d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         makeTemp = GL_TRUE;
4737d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
4747d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else {
4757d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         if (dimensions == 1) {
4767d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
4777d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstXoffset,
4787d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcWidth,
4797d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcFormat, srcType,
4807d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcPacking, srcAddr,
4817d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstAddr);
4827d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
4837d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         else if (dimensions == 2) {
4847d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
4857d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstXoffset, dstYoffset,
4867d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcWidth, srcHeight,
4877d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstRowStridePixels,
4887d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcFormat, srcType,
4897d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    srcPacking, srcAddr,
4907d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                                    dstAddr);
4917d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
4927d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         else {
4937d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            assert(dimensions == 3);
4947d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
4957d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstXoffset, dstYoffset, dstZoffset,
4967d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcWidth, srcHeight, srcDepth,
4977d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstRowStridePixels, dstImageStridePixels,
4987d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcFormat, srcType,
4997d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcPacking, srcAddr, dstAddr);
5007d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5017d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         if (!makeTemp) {
5027d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            /* all done! */
5031c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul            if (freeSourceData)
5041c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul               FREE((void *) srcAddr);
5057d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul            return;
5067d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         }
5077d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5087d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5097d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   else {
5107d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* software texture format */
5117d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      makeTemp = GL_FALSE;
5127d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5137d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5147d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (makeTemp) {
5157d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
5167d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLenum tmpFormat;
5177d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLuint tmpComps, tmpTexelSize;
5187d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLint tmpRowStride, tmpImageStride;
5197d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      GLubyte *tmpImage;
5207d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5211c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (transferOps & IMAGE_CONVOLUTION_BIT) {
5227d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
5237d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                            &postConvHeight);
5247d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5257d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5261c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      tmpFormat = dstFormat->BaseFormat;
5277d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpComps = _mesa_components_in_format(tmpFormat);
52836f3712e85cafef1b038189678030f6ef4f8b7e9Brian Paul      tmpTexelSize = tmpComps * sizeof(GLchan);
5297d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpRowStride = postConvWidth * tmpTexelSize;
5307d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
5317d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
5327d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                    srcDepth * tmpTexelSize);
5331c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (!tmpImage) {
5341c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         if (freeSourceData)
5351c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul            FREE((void *) srcAddr);
5367d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         return;
5371c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      }
5387d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5397d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
5407d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        srcWidth, srcHeight, srcDepth,
5417d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        0, 0, 0, /* x/y/zoffset */
5427d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        tmpRowStride, tmpImageStride,
5431c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
5441c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
5451c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      if (freeSourceData)
5461c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul         FREE((void *) srcAddr);
5477d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5487d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* the temp image is our new source image */
5497d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcWidth = postConvWidth;
5507d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcHeight = postConvHeight;
5517d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcFormat = tmpFormat;
5527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcType = CHAN_TYPE;
5537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcAddr = tmpImage;
5547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      srcPacking = &_mesa_native_packing;
5551c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      freeSourceData = GL_TRUE;
5567d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5577d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
5587d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (_mesa_is_hardware_tex_format(dstFormat)) {
5597d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      assert(makeTemp);
5607d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      if (dimensions == 1) {
5617d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
5627d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
5637d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstXoffset,
5647d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcWidth,
5657d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcFormat, srcType,
5667d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcPacking, srcAddr,
5677d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstAddr);
5687d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
5697d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5707d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else if (dimensions == 2) {
5717d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
5727d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
5737d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstXoffset, dstYoffset,
5747d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcWidth, srcHeight,
5757d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstRowStridePixels,
5767d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcFormat, srcType,
5777d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         srcPacking, srcAddr,
5787d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                         dstAddr);
5797d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
5807d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5817d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      else {
5827d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         GLboolean b;
5837d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
5847d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstXoffset, dstYoffset, dstZoffset,
5857d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcWidth, srcHeight, srcDepth,
5867d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      dstRowStridePixels, dstImageStridePixels,
5877d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcFormat, srcType,
5887d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                      srcPacking, srcAddr, dstAddr);
5897d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul         assert(b);
5907d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      }
5917d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
5927d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   else {
5937d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      /* software format */
5947d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      assert(!makeTemp);
5951c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
5967d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        srcWidth, srcHeight, srcDepth,
5977d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        dstXoffset, dstYoffset, dstZoffset,
5987d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                        dstRowStride, dstImageStride,
5991c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                        srcFormat, srcType, srcAddr, srcPacking, transferOps);
6007d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
6011c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul
6021c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   if (freeSourceData)
6031c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul      FREE((void *) srcAddr);  /* the temp image */
6047d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul}
6057d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
6067d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul
6077d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul/*
6088e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexImage1D().
6098e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
6108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
6118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
6128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
6138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
6148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
6158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
6168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
6178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint border,
6188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const GLvoid *pixels,
6198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
6208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
6218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
6228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
6238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint postConvWidth = width;
624e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
6258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
6268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
6278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
6288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
6298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
6307d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
6317d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
6327d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
6337d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
6347d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
6359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
6368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
63719d1e432612cf7db797da11793b13a6c1c6aac16Gareth Hughes   texelBytes = texImage->TexFormat->TexelBytes;
63819d1e432612cf7db797da11793b13a6c1c6aac16Gareth Hughes
639e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   /* Compute image size, in bytes */
640e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   if (texImage->IsCompressed) {
641e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(ctx->Driver.CompressedTextureSize);
642e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
643e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(sizeInBytes > 0);
644e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      texImage->CompressedSize = sizeInBytes;
645e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
646e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   else {
647e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = postConvWidth * texelBytes;
648e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
649e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
6508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
651aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
6527d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
6537d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
6547d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
6557d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
6568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
657f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul   if (pixels) {
658f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* unpack image, apply transfer ops and store in texImage->Data */
659f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 1,
660f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              _mesa_base_tex_format(ctx, internalFormat),
661f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
662f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              width, 1, 1, 0, 0, 0,
663f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstRowStride */
664f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstImageStride */
665f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
666f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
667f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* GL_SGIS_generate_mipmap */
668f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
669d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_generate_mipmap(ctx, target,
670f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
671f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               texObj);
672f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      }
6733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
6748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
6758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
6768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
6778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
6788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexImage2D().
6798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
6808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
6818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
6828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
683e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * NOTE: if real texture compression is supported, this whole function
684e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * will need to be overridden.
6858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
6868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
6878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
6888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
6898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint height, GLint border,
6908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const void *pixels,
6918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
6928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
6938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
6948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
6958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   GLint postConvWidth = width, postConvHeight = height;
696e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
6978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
6988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
6998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul      _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
7008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                         &postConvHeight);
7018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   }
7028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7037d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
7047d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
7057d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
7067d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
7077d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
7083893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
7092c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes
7102c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes   texelBytes = texImage->TexFormat->TexelBytes;
7118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
712e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   /* Compute image size, in bytes */
713e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   if (texImage->IsCompressed) {
714e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(ctx->Driver.CompressedTextureSize);
715e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
716e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(sizeInBytes > 0);
717e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      texImage->CompressedSize = sizeInBytes;
718e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
719e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   else {
720e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = postConvWidth * postConvHeight * texelBytes;
721e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
722e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
7238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
724aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
7257d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
7267d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
7277d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
7287d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
7298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
730f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul   if (pixels) {
731f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* unpack image, apply transfer ops and store in texImage->Data */
732f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 2,
733f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              _mesa_base_tex_format(ctx, internalFormat),
734f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
735f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              width, height, 1, 0, 0, 0,
736f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->Width * texelBytes,
737f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              0, /* dstImageStride */
738f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
739f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
740f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* GL_SGIS_generate_mipmap */
741f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
742d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_generate_mipmap(ctx, target,
743f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
744f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               texObj);
745f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      }
7463893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
7478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
7488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
7528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexImage3D().
7538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image type will be GLchan.
7548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
7558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
7568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul *
7578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
7588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
7598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
7608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint internalFormat,
7618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLint width, GLint height, GLint depth, GLint border,
7628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       GLenum format, GLenum type, const void *pixels,
7638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       const struct gl_pixelstore_attrib *packing,
7648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_object *texObj,
7658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                       struct gl_texture_image *texImage)
7668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
767e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   GLint texelBytes, sizeInBytes;
7688e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
7697d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
7707d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
7717d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
7727d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
7737d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
7749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
7752c3d34c905fa6b831a066afae83b938de05eb241Gareth Hughes
776197c526d63e1d4ea96f29eece392cdc389770b38Brian Paul   texelBytes = texImage->TexFormat->TexelBytes;
7778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
778e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   /* Compute image size, in bytes */
779e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   if (texImage->IsCompressed) {
780e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(ctx->Driver.CompressedTextureSize);
781e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
782e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      assert(sizeInBytes > 0);
783e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      texImage->CompressedSize = sizeInBytes;
784e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
785e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   else {
786e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul      sizeInBytes = width * height * depth * texelBytes;
787e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   }
788e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
7898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* allocate memory */
790aeb4434563c4014a662ea334878b60d3031bb3c1Brian Paul   texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
7917d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   if (!texImage->Data) {
7927d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
7937d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul      return;
7947d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   }
7958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
796f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul   if (pixels) {
797f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* unpack image, apply transfer ops and store in texImage->Data */
798f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      _mesa_transfer_teximage(ctx, 3,
799f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              _mesa_base_tex_format(ctx, internalFormat),
800f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->TexFormat, texImage->Data,
801f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              width, height, depth, 0, 0, 0,
802f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->Width * texelBytes,
803f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              texImage->Width * texImage->Height * texelBytes,
804f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                              format, type, pixels, packing);
805f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul
806f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      /* GL_SGIS_generate_mipmap */
807f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
808d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_generate_mipmap(ctx, target,
809f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
810f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul                               texObj);
811f3b85c983f469875ac76081a61539a6c7b26777cBrian Paul      }
8123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
8138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
8148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
8198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexSubImage1D().
8208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
8218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
8228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
8238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint width,
8248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
8258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
8268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
8278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
8288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
8291c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   _mesa_transfer_teximage(ctx, 1,
8301c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           _mesa_base_tex_format(ctx, texImage->IntFormat),
8311c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           texImage->TexFormat, texImage->Data,
8328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           width, 1, 1, /* src size */
8338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           xoffset, 0, 0, /* dest offsets */
8348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           0, /* dstRowStride */
8358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           0, /* dstImageStride */
8368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           format, type, pixels, packing);
8373893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
8383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
8393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
840d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
841d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
8423893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
8433893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
8448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
8458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
8488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexSubImage2D().
8498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
8508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
8518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
8528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint yoffset,
8538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height,
8548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
8558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
8568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
8578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
8588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
8591c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   _mesa_transfer_teximage(ctx, 2,
8601c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           _mesa_base_tex_format(ctx, texImage->IntFormat),
8611c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           texImage->TexFormat, texImage->Data,
8628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           width, height, 1, /* src size */
8638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           xoffset, yoffset, 0, /* dest offsets */
86438f28665bf9fb5b2464738ca5074848ec2777ae1Gareth Hughes                           texImage->Width * texImage->TexFormat->TexelBytes,
8658e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           0, /* dstImageStride */
8668e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           format, type, pixels, packing);
8673893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
8683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
8693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
870d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
871d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
8723893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
8733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
8748e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
8758e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8768e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
8778e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
8788e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the software fallback for Driver.TexSubImage3D().
8798e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
8808e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
8818e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
8828e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint xoffset, GLint yoffset, GLint zoffset,
8838e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height, GLint depth,
8848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLenum format, GLenum type, const void *pixels,
8858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          const struct gl_pixelstore_attrib *packing,
8868e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_object *texObj,
8878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          struct gl_texture_image *texImage)
8888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
88938f28665bf9fb5b2464738ca5074848ec2777ae1Gareth Hughes   const GLint texelBytes = texImage->TexFormat->TexelBytes;
8901c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul   _mesa_transfer_teximage(ctx, 3,
8911c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           _mesa_base_tex_format(ctx, texImage->IntFormat),
8921c85aa33321821b44bea83d3dee702ab4e05f406Brian Paul                           texImage->TexFormat, texImage->Data,
8938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           width, height, depth, /* src size */
8948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           xoffset, yoffset, xoffset, /* dest offsets */
89538f28665bf9fb5b2464738ca5074848ec2777ae1Gareth Hughes                           texImage->Width * texelBytes,
89638f28665bf9fb5b2464738ca5074848ec2777ae1Gareth Hughes                           texImage->Width * texImage->Height * texelBytes,
8978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                           format, type, pixels, packing);
8983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* GL_SGIS_generate_mipmap */
8993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
900d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_generate_mipmap(ctx, target,
901d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                            &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
9023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                            texObj);
9033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
9048e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
9058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9078e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9082aadbf41dfd4f63c6118d0ad2d8659d289cbe454Brian Paul
9092aadbf41dfd4f63c6118d0ad2d8659d289cbe454Brian Paul/*
9108e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage1D()
9118e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
9128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
9138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
9148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
9158e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint border,
9168e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
9178e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
9188e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
9198e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
9208e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* Nothing here.
9218e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * The device driver has to do it all.
9228e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
9238e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
9248e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9258e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9268e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9278e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
9288e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage2D()
9298e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
9308e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
9318e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
9328e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
9338e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint height, GLint border,
9348e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
9358e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
9368e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
9378e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
9388e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* Nothing here.
9398e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * The device driver has to do it all.
9408e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
9418e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
9428e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9438e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9448e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9458e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
9468e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * Fallback for Driver.CompressedTexImage3D()
9478e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
9488e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paulvoid
9498e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
9508e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint internalFormat,
9518e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint width, GLint height, GLint depth,
9528e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLint border,
9538e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  GLsizei imageSize, const GLvoid *data,
9548e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_object *texObj,
9558e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                                  struct gl_texture_image *texImage)
9568e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
9578e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* Nothing here.
9588e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * The device driver has to do it all.
9598e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
9608e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
9618e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9628e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9638e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9648e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul/*
965e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * Fallback for Driver.GetCompressedTexImage3D()
966e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * This will probably work find for hardware drivers.  That is, hardware
967e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * drivers won't have to override this function, unless the compressed
968e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul * texture must first be fetched from the TRAM.
969e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul */
970e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paulvoid
971e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target,
972e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul                              GLint level, void *image,
973e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul                              const struct gl_texture_object *texObj,
974e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul                              struct gl_texture_image *texImage)
975e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul{
976e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   assert(texImage->IsCompressed);
977e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   assert(texImage->CompressedSize > 0);
978e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul   MEMCPY(image, texImage->Data, texImage->CompressedSize);
979e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul}
980e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
981e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
982e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul
983e4276667dafc8de0c6e64af8300fc7598437de6eBrian Paul/*
9848e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul * This is the fallback for Driver.TestProxyTexImage().
9858e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul */
9868e39ad2cd67d49be40ff0822f3269affdf83d601Brian PaulGLboolean
9878e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
9888e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint internalFormat, GLenum format, GLenum type,
9898e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul                          GLint width, GLint height, GLint depth, GLint border)
9908e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul{
9918e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_unit *texUnit;
9928e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_object *texObj;
9938e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   struct gl_texture_image *texImage;
9948e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9958e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   (void) format;
9968e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   (void) type;
9978e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
9988e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
9998e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texObj = _mesa_select_tex_object(ctx, texUnit, target);
10008e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
10018e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
10028e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   /* We always pass.
10038e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * The core Mesa code will have already tested the image size, etc.
10049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * If a driver has more stringent texture limits to enforce it will
10058e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    * have to override this function.
10068e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul    */
10077d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   /* choose the texture format */
10087d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(ctx->Driver.ChooseTextureFormat);
10097d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
10107d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul                                          internalFormat, format, type);
10117d58f44f73be59bd3583e6dfeedf56c43f7fbd55Brian Paul   assert(texImage->TexFormat);
10128e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul
10138e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul   return GL_TRUE;
10148e39ad2cd67d49be40ff0822f3269affdf83d601Brian Paul}
10153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
10163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
10173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
10183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul/*
10193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Average together two rows of a source image to produce a single new
10203893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * row in the dest image.  It's legal for the two source rows to point
10219228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * to the same data.  The source width must be equal to either the
10229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * dest width or two times the dest width.
10233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul */
10243893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
10259228e17bb5bf219269daeed5cbfdd912c118e926Brian Pauldo_row(const struct gl_texture_format *format, GLint srcWidth,
10269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul       const GLvoid *srcRowA, const GLvoid *srcRowB,
10279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul       GLint dstWidth, GLvoid *dstRow)
10283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
10299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
10309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
10319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
10329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
10339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
10343893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   switch (format->MesaFormat) {
10353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_RGBA:
10363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
10379228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
10383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
10393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
10403893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
10417c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
10429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
10439228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1044f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
10459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1046f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
10479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1048f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
10499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][3] = (rowA[j][3] + rowA[k][3] +
1050f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][3] + rowB[k][3]) / 4;
10513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
10523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
10533893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
10543893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_RGB:
10553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
10569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
10573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
10583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
10593893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
10607c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
10619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
10629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1063f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
10649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1065f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
10669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1067f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
10683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
10693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
10703893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
10713893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_ALPHA:
10723893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_LUMINANCE:
10733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_INTENSITY:
10743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_COLOR_INDEX:
10753893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
10769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
10773893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan *rowA = (const GLchan *) srcRowA;
10783893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan *rowB = (const GLchan *) srcRowB;
10793893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan *dst = (GLchan *) dstRow;
10807c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
10819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
1082f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
10833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
10843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
10853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
10863893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_LUMINANCE_ALPHA:
10873893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      {
10889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
10893893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
10903893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
10913893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
10927c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
10939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
10949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1095f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
10969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1097f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
10983893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
10993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
11003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
11013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   case MESA_FORMAT_DEPTH_COMPONENT:
11028bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
11039228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
11048bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLfloat *rowA = (const GLfloat *) srcRowA;
11058bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLfloat *rowB = (const GLfloat *) srcRowB;
11068bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLfloat *dst = (GLfloat *) dstRow;
11077c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
11089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
11099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
11108bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
11118bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
11128bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
11138bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   /* Begin hardware formats */
11148bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGBA8888:
11158bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB8888:
11168bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
11179228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
11188bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
11198bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
11208bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
11217c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
11229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
11239228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1124f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
11259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1126f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
11279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1128f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
11299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][3] = (rowA[j][3] + rowA[k][3] +
1130f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][3] + rowB[k][3]) / 4;
11318bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
11328bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
11338bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
11348bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB888:
11358bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
11369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
11378bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
11388bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
11398bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
11407c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
11419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
11429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
1143f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][0] + rowB[k][0]) / 4;
11449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
1145f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][1] + rowB[k][1]) / 4;
11469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][2] = (rowA[j][2] + rowA[k][2] +
1147f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul                         rowB[j][2] + rowB[k][2]) / 4;
11488bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
11498bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
11508bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
11518bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB565:
11528bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
11539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
11548bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
11558bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
11568bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
11577c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
11589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
11599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x1f;
11609228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x1f;
11619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x1f;
11629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0x1f;
11639228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
11649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
11659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
11669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
11679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
11689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
11699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
11709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
11718bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
11728bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
11738bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
11748bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (blue << 11) | (green << 5) | red;
11758bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
11768bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
11778bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
11788bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB4444:
11798bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
11809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
11818bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
11828bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
11838bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
11847c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
11859228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
11869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0xf;
11879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0xf;
11889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0xf;
11899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0xf;
11909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
11919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
11929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
11939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
11949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
11959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
11969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
11979228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
11989228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
11999228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
12009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
12019228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
12028bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
12038bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
12048bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
12058bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
12068bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
12078bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
12088bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
12098bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
12108bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_ARGB1555:
12118bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
12129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
12138bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowA = (const GLushort *) srcRowA;
12148bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLushort *rowB = (const GLushort *) srcRowB;
12158bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLushort *dst = (GLushort *) dstRow;
12167c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
12179228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
12189228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x1f;
12199228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x1f;
12209228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x1f;
12219228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0xf;
12229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
12239228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
12249228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
12259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
12269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
12279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
12289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
12299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
12309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
12319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
12329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
12339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
12348bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
12358bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
12368bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
12378bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
12388bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
12398bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
12408bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
12418bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
12428bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_AL88:
12438bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
12449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
12458bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
12468bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
12478bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
12487c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
12499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
12509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][0] = (rowA[j][0] + rowA[k][0] +
12519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         rowB[j][0] + rowB[k][0]) >> 2;
12529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i][1] = (rowA[j][1] + rowA[k][1] +
12539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         rowB[j][1] + rowB[k][1]) >> 2;
12548bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
12558bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
12568bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
12578bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_RGB332:
12588bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
12599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
12608bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowA = (const GLubyte *) srcRowA;
12618bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowB = (const GLubyte *) srcRowB;
12628bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte *dst = (GLubyte *) dstRow;
12637c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
12649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
12659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr0 = rowA[j] & 0x3;
12669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAr1 = rowA[k] & 0x3;
12679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr0 = rowB[j] & 0x3;
12689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBr1 = rowB[k] & 0x3;
12699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
12709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
12719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
12729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
12739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
12749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
12759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
12769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
12778bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint red   = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
12788bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
12798bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            const GLint blue  = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
12808bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul            dst[i] = (blue << 5) | (green << 2) | red;
12818bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
12828bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
12838bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
12848bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_A8:
12858bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_L8:
12868bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_I8:
12878bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   case MESA_FORMAT_CI8:
12888bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      {
12899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         GLuint i, j, k;
12908bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowA = (const GLubyte *) srcRowA;
12918bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         const GLubyte *rowB = (const GLubyte *) srcRowB;
12928bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         GLubyte *dst = (GLubyte *) dstRow;
12937c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz         for (i = j = 0, k = k0; i < (GLuint) dstWidth;
12949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul              i++, j += colStride, k += colStride) {
12959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
12968bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul         }
12978bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      }
12988bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul      return;
12993893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   default:
13003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      _mesa_problem(NULL, "bad format in do_row()");
13013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
13023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
13033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul/*
13069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * These functions generate a 1/2-size mipmap image from a source image.
13079228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * Texture borders are handled by copying or averaging the source image's
13089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul * border texels, depending on the scale-down factor.
13099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul */
13103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
13123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_1d_mipmap(const struct gl_texture_format *format, GLint border,
13133893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, const GLubyte *srcPtr,
13143893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLubyte *dstPtr)
13153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
13163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint bpt = format->TexelBytes;
13173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLubyte *src;
13183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLubyte *dst;
13193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13203893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* skip the border pixel, if any */
13213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   src = srcPtr + border * bpt;
13223893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   dst = dstPtr + border * bpt;
13233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13243893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* we just duplicate the input row, kind of hack, saves code */
13259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   do_row(format, srcWidth - 2 * border, src, src,
13269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul          dstWidth - 2 * border, dst);
13273893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (border) {
13293893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* copy left-most pixel from source */
13303893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr, srcPtr, bpt);
13313893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* copy right-most pixel from source */
13323893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
13333893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth - 1) * bpt,
13343893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             bpt);
13353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
13363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
13373893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
13403893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_2d_mipmap(const struct gl_texture_format *format, GLint border,
13413893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
13423893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
13433893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
13443893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint bpt = format->TexelBytes;
13459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
13469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstWidthNB = dstWidth - 2 * border;
13479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstHeightNB = dstHeight - 2 * border;
13483893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint srcRowStride = bpt * srcWidth;
13493893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLint dstRowStride = bpt * dstWidth;
13503893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   const GLubyte *srcA, *srcB;
13513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLubyte *dst;
13529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint row, colStride;
13539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
13549228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   colStride = (srcWidth == dstWidth) ? 1 : 2;
13553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13563893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   /* Compute src and dst pointers, skipping any border */
13573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   srcA = srcPtr + border * ((srcWidth + 1) * bpt);
13583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (srcHeight > 1)
13593893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB = srcA + srcRowStride;
13603893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   else
13613893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB = srcA;
13623893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   dst = dstPtr + border * ((dstWidth + 1) * bpt);
13633893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   for (row = 0; row < dstHeightNB; row++) {
13659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB, srcA, srcB,
13669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB, dst);
13673893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcA += 2 * srcRowStride;
13683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcB += 2 * srcRowStride;
13693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      dst += dstRowStride;
13703893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
13713893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
13728bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   /* This is ugly but probably won't be used much */
13733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   if (border > 0) {
13743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* fill in dest border */
13753893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower-left border pixel */
13763893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr, srcPtr, bpt);
13773893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower-right border pixel */
13783893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth - 1) * bpt,
13793893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth - 1) * bpt, bpt);
13803893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper-left border pixel */
13813893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
13823893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
13833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper-right border pixel */
13843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
13853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
13863893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* lower border */
13879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB,
13889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             srcPtr + bpt,
13899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             srcPtr + bpt,
13909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB, dstPtr + bpt);
13913893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* upper border */
13929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      do_row(format, srcWidthNB,
13933893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
13943893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
13959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul             dstWidthNB,
13963893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul             dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
13973893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* left and right borders */
13989228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      if (srcHeight == dstHeight) {
13999228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* copy border pixel from src to dst */
14009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (row = 1; row < srcHeight; row++) {
14019228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dstPtr + dstWidth * row * bpt,
14029228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + srcWidth * row * bpt, bpt);
14039228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
14049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
14059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
14069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
14079228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      else {
14089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* average two src pixels each dest pixel */
14099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (row = 0; row < dstHeightNB; row += 2) {
14109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1,
14119228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
14129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
14139228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   1, dstPtr + (dstWidth * row + 1) * bpt);
14149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1,
14159228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
14169228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
14179228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                   1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
14189228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
14193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
14203893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
14213893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
14223893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14233893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14243893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulstatic void
14253893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulmake_3d_mipmap(const struct gl_texture_format *format, GLint border,
14263893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint srcWidth, GLint srcHeight, GLint srcDepth,
14273893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               const GLubyte *srcPtr,
14283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLint dstWidth, GLint dstHeight, GLint dstDepth,
14293893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul               GLubyte *dstPtr)
14303893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
14319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint bpt = format->TexelBytes;
14329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
14339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint srcDepthNB = srcDepth - 2 * border;
14349228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstWidthNB = dstWidth - 2 * border;
14359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstHeightNB = dstHeight - 2 * border;
14369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   const GLint dstDepthNB = dstDepth - 2 * border;
14379228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLvoid *tmpRowA, *tmpRowB;
14383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   GLint img, row;
14399228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint bytesPerSrcImage, bytesPerDstImage;
14409228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint bytesPerSrcRow, bytesPerDstRow;
14419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   GLint srcImageOffset, srcRowOffset;
14423893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14435c749d9e3c7824c0ba5b22e37d0ea5cbd54d6d2dBrian Paul   (void) srcDepthNB; /* silence warnings */
14445c749d9e3c7824c0ba5b22e37d0ea5cbd54d6d2dBrian Paul
14459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Need two temporary row buffers */
14469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   tmpRowA = MALLOC(srcWidth * bpt);
14479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (!tmpRowA)
14489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      return;
14499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   tmpRowB = MALLOC(srcWidth * bpt);
14509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (!tmpRowB) {
14519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      FREE(tmpRowA);
14523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
14533893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
14543893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14559228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerSrcImage = srcWidth * srcHeight * bpt;
14569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerDstImage = dstWidth * dstHeight * bpt;
14579228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
14589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerSrcRow = srcWidth * bpt;
14599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   bytesPerDstRow = dstWidth * bpt;
14603893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Offset between adjacent src images to be averaged together */
14629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
14633893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Offset between adjacent src rows to be averaged together */
14659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
14663893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /*
14689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * Need to average together up to 8 src pixels for each dest pixel.
14699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    * Break that down into 3 operations:
14709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   1. take two rows from source image and average them together.
14719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   2. take two rows from next source image and average them together.
14729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    *   3. take the two averaged rows and average them for the final dst row.
14739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul    */
14743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
14759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /*
14764e9676fb13f60ecdbc247b120031f18cd3febcb0Brian Paul   _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
14779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul          srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
14789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   */
14799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
14809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   for (img = 0; img < dstDepthNB; img++) {
14819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* first source image pointer, skipping border */
14829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *imgSrcA = srcPtr
14839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
14849228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + img * (bytesPerSrcImage + srcImageOffset);
14859228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* second source image pointer, skipping border */
14869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
14879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* address of the dest image, skipping border */
14889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      GLubyte *imgDst = dstPtr
14899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
14909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         + img * bytesPerDstImage;
14919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
14929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* setup the four source row pointers and the dest row pointer */
14939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgARowA = imgSrcA;
14949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
14959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgBRowA = imgSrcB;
14969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
14979228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      GLubyte *dstImgRow = imgDst;
14989228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
14999228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      for (row = 0; row < dstHeightNB; row++) {
15009228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together two rows from first src image */
15019228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
15029228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                srcWidthNB, tmpRowA);
15039228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together two rows from second src image */
15049228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
15059228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                srcWidthNB, tmpRowB);
15069228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* Average together the temp rows to make the final row */
15079228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         do_row(format, srcWidthNB, tmpRowA, tmpRowB,
15089228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                dstWidthNB, dstImgRow);
15099228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* advance to next rows */
15109228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgARowA += bytesPerSrcRow + srcRowOffset;
15119228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgARowB += bytesPerSrcRow + srcRowOffset;
15129228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
15139228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
15149228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         dstImgRow += bytesPerDstRow;
15153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
15163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
15173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
15183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   FREE(tmpRowA);
15193893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   FREE(tmpRowB);
15209228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15219228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   /* Luckily we can leverage the make_2d_mipmap() function here! */
15229228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   if (border > 0) {
15239228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do front border image */
15249228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
15259228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstWidth, dstHeight, dstPtr);
15269228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do back border image */
15279228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      make_2d_mipmap(format, 1, srcWidth, srcHeight,
15289228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     srcPtr + bytesPerSrcImage * (srcDepth - 1),
15299228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstWidth, dstHeight,
15309228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                     dstPtr + bytesPerDstImage * (dstDepth - 1));
15319228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* do four remaining border edges that span the image slices */
15329228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      if (srcDepth == dstDepth) {
15339228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* just copy border pixels from src to dst */
15349228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (img = 0; img < dstDepthNB; img++) {
15359228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLubyte *src;
15369228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            GLubyte *dst;
15379228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15389228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=0] */
15399228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img + 1) * bytesPerSrcImage;
15409228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage;
15419228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
15429228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15439228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=0] */
15449228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15459228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcHeight - 1) * bytesPerSrcRow;
15469228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15479228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstHeight - 1) * bytesPerDstRow;
15489228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
15499228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15509228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=dstWidth-1] */
15519228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15529228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcWidth - 1) * bpt;
15539228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15549228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstWidth - 1) * bpt;
15559228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
15569228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15579228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
15589228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15599228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerSrcImage - bpt);
15609228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15619228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerDstImage - bpt);
15629228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            MEMCPY(dst, src, bpt);
15639228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
15649228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
15659228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      else {
15669228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         /* average border pixels from adjacent src image pairs */
15679228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         ASSERT(srcDepthNB == 2 * dstDepthNB);
15689228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         for (img = 0; img < dstDepthNB; img++) {
15699228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            const GLubyte *src;
15709228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            GLubyte *dst;
15719228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15729228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=0] */
15739228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
15749228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage;
15759228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
15769228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15779228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=0] */
15789228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15799228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcHeight - 1) * bytesPerSrcRow;
15809228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15819228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstHeight - 1) * bytesPerDstRow;
15829228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
15839228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15849228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=0][col=dstWidth-1] */
15859228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15869228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (srcWidth - 1) * bpt;
15879228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15889228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (dstWidth - 1) * bpt;
15899228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
15909228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul
15919228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
15929228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
15939228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerSrcImage - bpt);
15949228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            dst = dstPtr + (img + 1) * bytesPerDstImage
15959228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul                         + (bytesPerDstImage - bpt);
15969228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul            do_row(format, 1, src, src + srcImageOffset, 1, dst);
15979228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul         }
15989228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      }
15999228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul   }
16003893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
16013893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16023893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16033893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul/*
16043893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * For GL_SGIX_generate_mipmap:
16053893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Generate a complete set of mipmaps from texObj's base-level image.
16063893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
16073893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul */
16083893e638e6521b9c070e01c0b31d22754ff97a88Brian Paulvoid
1609d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
16103893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                      const struct gl_texture_unit *texUnit,
16113893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                      struct gl_texture_object *texObj)
16123893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul{
16137c4268176eaaeb45003db4d5042a518b84c9f6dcKarl Schultz   GLint level;
1614cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul   GLint maxLevels = 0;
16153893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16163893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   ASSERT(texObj);
16173893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   ASSERT(texObj->Image[texObj->BaseLevel]);
16183893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16198afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   switch (texObj->Target) {
16208afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_1D:
1621cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxTextureLevels;
16223893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
16238afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_2D:
1624cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxTextureLevels;
16253893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
16268afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_3D:
1627cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.Max3DTextureLevels;
16283893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
16298afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_CUBE_MAP_ARB:
1630cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul      maxLevels = ctx->Const.MaxCubeTextureLevels;
16313893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      break;
16328afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul   case GL_TEXTURE_RECTANGLE_NV:
16338afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul      maxLevels = 1;
16348afe7de8deaf3c9613fd68b344de8c52b02b1879Brian Paul      break;
16353893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   default:
16363893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      _mesa_problem(ctx,
16373893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul                    "Bad texture object dimension in _mesa_generate_mipmaps");
16383893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      return;
16393893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul   }
16403893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16418bd06931018d5662b92f1cfeee2abaf352d0044cBrian Paul   for (level = texObj->BaseLevel; level < texObj->MaxLevel
1642cd1cefae9146fc14b35ee93a04bdb1b1590fba7bBrian Paul           && level < maxLevels - 1; level++) {
16439228e17bb5bf219269daeed5cbfdd912c118e926Brian Paul      /* generate image[level+1] from image[level] */
16443893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      const struct gl_texture_image *srcImage;
16453893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      struct gl_texture_image *dstImage;
16463893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint srcWidth, srcHeight, srcDepth;
16473893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint dstWidth, dstHeight, dstDepth;
16483893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint border, bytesPerTexel;
16493893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      GLint t;
16503893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16513893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcImage = texObj->Image[level];
16523893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      ASSERT(srcImage);
16533893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcWidth = srcImage->Width;
16543893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcHeight = srcImage->Height;
16553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      srcDepth = srcImage->Depth;
16563893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      border = srcImage->Border;
16573893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      bytesPerTexel = srcImage->TexFormat->TexelBytes;
16583893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16593893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      /* compute next (level+1) image size */
16603893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcWidth - 2 * border > 1) {
16613893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
16623893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16633893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
16643893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstWidth = srcWidth; /* can't go smaller */
16653893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16663893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcHeight - 2 * border > 1) {
16673893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
16683893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16693893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
16703893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstHeight = srcHeight; /* can't go smaller */
16713893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16723893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (srcDepth - 2 * border > 1) {
16733893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
16743893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16753893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      else {
16763893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         dstDepth = srcDepth; /* can't go smaller */
16773893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16783893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
16793893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      if (dstWidth == srcWidth &&
16803893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul          dstHeight == srcHeight &&
16813893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul          dstDepth == srcDepth) {
16823893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         /* all done */
16833893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         return;
16843893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul      }
16853893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
1686d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* get dest gl_texture_image */
1687d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage = _mesa_select_tex_image(ctx, texUnit, target, level+1);
1688d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      if (!dstImage) {
1689d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         dstImage = _mesa_alloc_texture_image();
16903893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         if (!dstImage) {
16913893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul            _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
16923893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul            return;
16933893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul         }
1694d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_set_tex_image(texObj, target, level + 1, dstImage);
1695d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
16963893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul
1697d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* Free old image data */
1698d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      if (dstImage->Data)
1699d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         MESA_PBUFFER_FREE(dstImage->Data);
1700d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
1701d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* initialize new image */
1702d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      _mesa_init_teximage_fields(ctx, t, dstImage, dstWidth, dstHeight,
1703d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                                 dstDepth, border, srcImage->Format);
1704d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->DriverData = NULL;
1705d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->TexFormat = srcImage->TexFormat;
1706d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->FetchTexel = srcImage->FetchTexel;
1707d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      ASSERT(dstImage->TexFormat);
1708d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      ASSERT(dstImage->FetchTexel);
1709d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
1710d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
1711d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
1712d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /* alloc new image buffer */
1713d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
1714d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                                          * bytesPerTexel);
1715d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      if (!dstImage->Data) {
1716d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1717d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         return;
1718d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
1719d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul
1720d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      /*
1721d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul       * We use simple 2x2 averaging to compute the next mipmap level.
1722d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul       */
1723d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      switch (target) {
1724d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_1D:
1725d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         make_1d_mipmap(srcImage->TexFormat, border,
1726d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        srcWidth, (const GLubyte *) srcImage->Data,
1727d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        dstWidth, (GLubyte *) dstImage->Data);
1728d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         break;
1729d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_2D:
1730d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
1731d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
1732d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
1733d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
1734d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
1735d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
1736d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         make_2d_mipmap(srcImage->TexFormat, border,
1737d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        srcWidth, srcHeight, (const GLubyte *) srcImage->Data,
1738d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        dstWidth, dstHeight, (GLubyte *) dstImage->Data);
1739d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         break;
1740d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_3D:
1741d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         make_3d_mipmap(srcImage->TexFormat, border,
1742d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        srcWidth, srcHeight, srcDepth,
1743d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        (const GLubyte *) srcImage->Data,
1744d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        dstWidth, dstHeight, dstDepth,
1745d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul                        (GLubyte *) dstImage->Data);
1746d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         break;
1747d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      case GL_TEXTURE_RECTANGLE_NV:
1748d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         /* no mipmaps, do nothing */
1749d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         break;
1750d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      default:
1751d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
1752d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul         return;
1753d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul      }
1754d5bbbd41c431ad93c0867d5b0b234426d8570499Brian Paul   } /* loop over mipmap levels */
17553893e638e6521b9c070e01c0b31d22754ff97a88Brian Paul}
1756