Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.1
  4.  *
  5.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a
  8.  * copy of this software and associated documentation files (the "Software"),
  9.  * to deal in the Software without restriction, including without limitation
  10.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11.  * and/or sell copies of the Software, and to permit persons to whom the
  12.  * Software is furnished to do so, subject to the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice shall be included
  15.  * in all copies or substantial portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  20.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  21.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  22.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. /**
  27.  * \file mipmap.c  mipmap generation and teximage resizing functions.
  28.  */
  29.  
  30. #include "imports.h"
  31. #include "formats.h"
  32. #include "mipmap.h"
  33. #include "teximage.h"
  34. #include "texstore.h"
  35. #include "image.h"
  36.  
  37.  
  38.  
  39. static GLint
  40. bytes_per_pixel(GLenum datatype, GLuint comps)
  41. {
  42.    GLint b = _mesa_sizeof_packed_type(datatype);
  43.    assert(b >= 0);
  44.  
  45.    if (_mesa_type_is_packed(datatype))
  46.        return b;
  47.    else
  48.        return b * comps;
  49. }
  50.  
  51.  
  52. /**
  53.  * \name Support macros for do_row and do_row_3d
  54.  *
  55.  * The macro madness is here for two reasons.  First, it compacts the code
  56.  * slightly.  Second, it makes it much easier to adjust the specifics of the
  57.  * filter to tune the rounding characteristics.
  58.  */
  59. /*@{*/
  60. #define DECLARE_ROW_POINTERS(t, e) \
  61.       const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
  62.       const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
  63.       const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
  64.       const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
  65.       t(*dst)[e] = (t(*)[e]) dstRow
  66.  
  67. #define DECLARE_ROW_POINTERS0(t) \
  68.       const t *rowA = (const t *) srcRowA; \
  69.       const t *rowB = (const t *) srcRowB; \
  70.       const t *rowC = (const t *) srcRowC; \
  71.       const t *rowD = (const t *) srcRowD; \
  72.       t *dst = (t *) dstRow
  73.  
  74. #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
  75.    ((unsigned) Aj + (unsigned) Ak \
  76.     + (unsigned) Bj + (unsigned) Bk \
  77.     + (unsigned) Cj + (unsigned) Ck \
  78.     + (unsigned) Dj + (unsigned) Dk \
  79.     + 4) >> 3
  80.  
  81. #define FILTER_3D(e) \
  82.    do { \
  83.       dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
  84.                                 rowB[j][e], rowB[k][e], \
  85.                                 rowC[j][e], rowC[k][e], \
  86.                                 rowD[j][e], rowD[k][e]); \
  87.    } while(0)
  88.  
  89. #define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
  90.    (Aj + Ak \
  91.     + Bj + Bk \
  92.     + Cj + Ck \
  93.     + Dj + Dk \
  94.     + 4) / 8
  95.  
  96. #define FILTER_3D_SIGNED(e) \
  97.    do { \
  98.       dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
  99.                                        rowB[j][e], rowB[k][e], \
  100.                                        rowC[j][e], rowC[k][e], \
  101.                                        rowD[j][e], rowD[k][e]); \
  102.    } while(0)
  103.  
  104. #define FILTER_F_3D(e) \
  105.    do { \
  106.       dst[i][e] = (rowA[j][e] + rowA[k][e] \
  107.                    + rowB[j][e] + rowB[k][e] \
  108.                    + rowC[j][e] + rowC[k][e] \
  109.                    + rowD[j][e] + rowD[k][e]) * 0.125F; \
  110.    } while(0)
  111.  
  112. #define FILTER_HF_3D(e) \
  113.    do { \
  114.       const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
  115.       const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
  116.       const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
  117.       const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
  118.       const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
  119.       const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
  120.       const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
  121.       const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
  122.       dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
  123.                                       * 0.125F); \
  124.    } while(0)
  125. /*@}*/
  126.  
  127.  
  128. /**
  129.  * Average together two rows of a source image to produce a single new
  130.  * row in the dest image.  It's legal for the two source rows to point
  131.  * to the same data.  The source width must be equal to either the
  132.  * dest width or two times the dest width.
  133.  * \param datatype  GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
  134.  * \param comps  number of components per pixel (1..4)
  135.  */
  136. static void
  137. do_row(GLenum datatype, GLuint comps, GLint srcWidth,
  138.        const GLvoid *srcRowA, const GLvoid *srcRowB,
  139.        GLint dstWidth, GLvoid *dstRow)
  140. {
  141.    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
  142.    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
  143.  
  144.    ASSERT(comps >= 1);
  145.    ASSERT(comps <= 4);
  146.  
  147.    /* This assertion is no longer valid with non-power-of-2 textures
  148.    assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
  149.    */
  150.  
  151.    if (datatype == GL_UNSIGNED_BYTE && comps == 4) {
  152.       GLuint i, j, k;
  153.       const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA;
  154.       const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB;
  155.       GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow;
  156.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  157.            i++, j += colStride, k += colStride) {
  158.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  159.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  160.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  161.          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  162.       }
  163.    }
  164.    else if (datatype == GL_UNSIGNED_BYTE && comps == 3) {
  165.       GLuint i, j, k;
  166.       const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA;
  167.       const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB;
  168.       GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow;
  169.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  170.            i++, j += colStride, k += colStride) {
  171.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  172.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  173.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  174.       }
  175.    }
  176.    else if (datatype == GL_UNSIGNED_BYTE && comps == 2) {
  177.       GLuint i, j, k;
  178.       const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA;
  179.       const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB;
  180.       GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow;
  181.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  182.            i++, j += colStride, k += colStride) {
  183.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
  184.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
  185.       }
  186.    }
  187.    else if (datatype == GL_UNSIGNED_BYTE && comps == 1) {
  188.       GLuint i, j, k;
  189.       const GLubyte *rowA = (const GLubyte *) srcRowA;
  190.       const GLubyte *rowB = (const GLubyte *) srcRowB;
  191.       GLubyte *dst = (GLubyte *) dstRow;
  192.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  193.            i++, j += colStride, k += colStride) {
  194.          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
  195.       }
  196.    }
  197.  
  198.    else if (datatype == GL_BYTE && comps == 4) {
  199.       GLuint i, j, k;
  200.       const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA;
  201.       const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB;
  202.       GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow;
  203.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  204.            i++, j += colStride, k += colStride) {
  205.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  206.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  207.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  208.          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  209.       }
  210.    }
  211.    else if (datatype == GL_BYTE && comps == 3) {
  212.       GLuint i, j, k;
  213.       const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA;
  214.       const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB;
  215.       GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow;
  216.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  217.            i++, j += colStride, k += colStride) {
  218.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  219.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  220.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  221.       }
  222.    }
  223.    else if (datatype == GL_BYTE && comps == 2) {
  224.       GLuint i, j, k;
  225.       const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
  226.       const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
  227.       GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
  228.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  229.            i++, j += colStride, k += colStride) {
  230.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  231.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  232.       }
  233.    }
  234.    else if (datatype == GL_BYTE && comps == 1) {
  235.       GLuint i, j, k;
  236.       const GLbyte *rowA = (const GLbyte *) srcRowA;
  237.       const GLbyte *rowB = (const GLbyte *) srcRowB;
  238.       GLbyte *dst = (GLbyte *) dstRow;
  239.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  240.            i++, j += colStride, k += colStride) {
  241.          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
  242.       }
  243.    }
  244.  
  245.    else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
  246.       GLuint i, j, k;
  247.       const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
  248.       const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB;
  249.       GLushort(*dst)[4] = (GLushort(*)[4]) dstRow;
  250.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  251.            i++, j += colStride, k += colStride) {
  252.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  253.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  254.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  255.          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  256.       }
  257.    }
  258.    else if (datatype == GL_UNSIGNED_SHORT && comps == 3) {
  259.       GLuint i, j, k;
  260.       const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA;
  261.       const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB;
  262.       GLushort(*dst)[3] = (GLushort(*)[3]) dstRow;
  263.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  264.            i++, j += colStride, k += colStride) {
  265.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  266.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  267.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  268.       }
  269.    }
  270.    else if (datatype == GL_UNSIGNED_SHORT && comps == 2) {
  271.       GLuint i, j, k;
  272.       const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA;
  273.       const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB;
  274.       GLushort(*dst)[2] = (GLushort(*)[2]) dstRow;
  275.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  276.            i++, j += colStride, k += colStride) {
  277.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  278.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  279.       }
  280.    }
  281.    else if (datatype == GL_UNSIGNED_SHORT && comps == 1) {
  282.       GLuint i, j, k;
  283.       const GLushort *rowA = (const GLushort *) srcRowA;
  284.       const GLushort *rowB = (const GLushort *) srcRowB;
  285.       GLushort *dst = (GLushort *) dstRow;
  286.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  287.            i++, j += colStride, k += colStride) {
  288.          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
  289.       }
  290.    }
  291.  
  292.    else if (datatype == GL_SHORT && comps == 4) {
  293.       GLuint i, j, k;
  294.       const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA;
  295.       const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB;
  296.       GLshort(*dst)[4] = (GLshort(*)[4]) dstRow;
  297.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  298.            i++, j += colStride, k += colStride) {
  299.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  300.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  301.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  302.          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
  303.       }
  304.    }
  305.    else if (datatype == GL_SHORT && comps == 3) {
  306.       GLuint i, j, k;
  307.       const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA;
  308.       const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB;
  309.       GLshort(*dst)[3] = (GLshort(*)[3]) dstRow;
  310.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  311.            i++, j += colStride, k += colStride) {
  312.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  313.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  314.          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
  315.       }
  316.    }
  317.    else if (datatype == GL_SHORT && comps == 2) {
  318.       GLuint i, j, k;
  319.       const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA;
  320.       const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB;
  321.       GLshort(*dst)[2] = (GLshort(*)[2]) dstRow;
  322.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  323.            i++, j += colStride, k += colStride) {
  324.          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
  325.          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
  326.       }
  327.    }
  328.    else if (datatype == GL_SHORT && comps == 1) {
  329.       GLuint i, j, k;
  330.       const GLshort *rowA = (const GLshort *) srcRowA;
  331.       const GLshort *rowB = (const GLshort *) srcRowB;
  332.       GLshort *dst = (GLshort *) dstRow;
  333.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  334.            i++, j += colStride, k += colStride) {
  335.          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
  336.       }
  337.    }
  338.  
  339.    else if (datatype == GL_FLOAT && comps == 4) {
  340.       GLuint i, j, k;
  341.       const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
  342.       const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB;
  343.       GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow;
  344.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  345.            i++, j += colStride, k += colStride) {
  346.          dst[i][0] = (rowA[j][0] + rowA[k][0] +
  347.                       rowB[j][0] + rowB[k][0]) * 0.25F;
  348.          dst[i][1] = (rowA[j][1] + rowA[k][1] +
  349.                       rowB[j][1] + rowB[k][1]) * 0.25F;
  350.          dst[i][2] = (rowA[j][2] + rowA[k][2] +
  351.                       rowB[j][2] + rowB[k][2]) * 0.25F;
  352.          dst[i][3] = (rowA[j][3] + rowA[k][3] +
  353.                       rowB[j][3] + rowB[k][3]) * 0.25F;
  354.       }
  355.    }
  356.    else if (datatype == GL_FLOAT && comps == 3) {
  357.       GLuint i, j, k;
  358.       const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA;
  359.       const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB;
  360.       GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow;
  361.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  362.            i++, j += colStride, k += colStride) {
  363.          dst[i][0] = (rowA[j][0] + rowA[k][0] +
  364.                       rowB[j][0] + rowB[k][0]) * 0.25F;
  365.          dst[i][1] = (rowA[j][1] + rowA[k][1] +
  366.                       rowB[j][1] + rowB[k][1]) * 0.25F;
  367.          dst[i][2] = (rowA[j][2] + rowA[k][2] +
  368.                       rowB[j][2] + rowB[k][2]) * 0.25F;
  369.       }
  370.    }
  371.    else if (datatype == GL_FLOAT && comps == 2) {
  372.       GLuint i, j, k;
  373.       const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA;
  374.       const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB;
  375.       GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow;
  376.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  377.            i++, j += colStride, k += colStride) {
  378.          dst[i][0] = (rowA[j][0] + rowA[k][0] +
  379.                       rowB[j][0] + rowB[k][0]) * 0.25F;
  380.          dst[i][1] = (rowA[j][1] + rowA[k][1] +
  381.                       rowB[j][1] + rowB[k][1]) * 0.25F;
  382.       }
  383.    }
  384.    else if (datatype == GL_FLOAT && comps == 1) {
  385.       GLuint i, j, k;
  386.       const GLfloat *rowA = (const GLfloat *) srcRowA;
  387.       const GLfloat *rowB = (const GLfloat *) srcRowB;
  388.       GLfloat *dst = (GLfloat *) dstRow;
  389.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  390.            i++, j += colStride, k += colStride) {
  391.          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
  392.       }
  393.    }
  394.  
  395.    else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) {
  396.       GLuint i, j, k, comp;
  397.       const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA;
  398.       const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB;
  399.       GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow;
  400.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  401.            i++, j += colStride, k += colStride) {
  402.          for (comp = 0; comp < 4; comp++) {
  403.             GLfloat aj, ak, bj, bk;
  404.             aj = _mesa_half_to_float(rowA[j][comp]);
  405.             ak = _mesa_half_to_float(rowA[k][comp]);
  406.             bj = _mesa_half_to_float(rowB[j][comp]);
  407.             bk = _mesa_half_to_float(rowB[k][comp]);
  408.             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
  409.          }
  410.       }
  411.    }
  412.    else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) {
  413.       GLuint i, j, k, comp;
  414.       const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA;
  415.       const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB;
  416.       GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow;
  417.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  418.            i++, j += colStride, k += colStride) {
  419.          for (comp = 0; comp < 3; comp++) {
  420.             GLfloat aj, ak, bj, bk;
  421.             aj = _mesa_half_to_float(rowA[j][comp]);
  422.             ak = _mesa_half_to_float(rowA[k][comp]);
  423.             bj = _mesa_half_to_float(rowB[j][comp]);
  424.             bk = _mesa_half_to_float(rowB[k][comp]);
  425.             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
  426.          }
  427.       }
  428.    }
  429.    else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) {
  430.       GLuint i, j, k, comp;
  431.       const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA;
  432.       const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB;
  433.       GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow;
  434.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  435.            i++, j += colStride, k += colStride) {
  436.          for (comp = 0; comp < 2; comp++) {
  437.             GLfloat aj, ak, bj, bk;
  438.             aj = _mesa_half_to_float(rowA[j][comp]);
  439.             ak = _mesa_half_to_float(rowA[k][comp]);
  440.             bj = _mesa_half_to_float(rowB[j][comp]);
  441.             bk = _mesa_half_to_float(rowB[k][comp]);
  442.             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
  443.          }
  444.       }
  445.    }
  446.    else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) {
  447.       GLuint i, j, k;
  448.       const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
  449.       const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
  450.       GLhalfARB *dst = (GLhalfARB *) dstRow;
  451.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  452.            i++, j += colStride, k += colStride) {
  453.          GLfloat aj, ak, bj, bk;
  454.          aj = _mesa_half_to_float(rowA[j]);
  455.          ak = _mesa_half_to_float(rowA[k]);
  456.          bj = _mesa_half_to_float(rowB[j]);
  457.          bk = _mesa_half_to_float(rowB[k]);
  458.          dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
  459.       }
  460.    }
  461.  
  462.    else if (datatype == GL_UNSIGNED_INT && comps == 1) {
  463.       GLuint i, j, k;
  464.       const GLuint *rowA = (const GLuint *) srcRowA;
  465.       const GLuint *rowB = (const GLuint *) srcRowB;
  466.       GLuint *dst = (GLuint *) dstRow;
  467.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  468.            i++, j += colStride, k += colStride) {
  469.          dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4);
  470.       }
  471.    }
  472.  
  473.    else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) {
  474.       GLuint i, j, k;
  475.       const GLushort *rowA = (const GLushort *) srcRowA;
  476.       const GLushort *rowB = (const GLushort *) srcRowB;
  477.       GLushort *dst = (GLushort *) dstRow;
  478.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  479.            i++, j += colStride, k += colStride) {
  480.          const GLint rowAr0 = rowA[j] & 0x1f;
  481.          const GLint rowAr1 = rowA[k] & 0x1f;
  482.          const GLint rowBr0 = rowB[j] & 0x1f;
  483.          const GLint rowBr1 = rowB[k] & 0x1f;
  484.          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
  485.          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
  486.          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
  487.          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
  488.          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
  489.          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
  490.          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
  491.          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
  492.          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  493.          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  494.          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  495.          dst[i] = (blue << 11) | (green << 5) | red;
  496.       }
  497.    }
  498.    else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) {
  499.       GLuint i, j, k;
  500.       const GLushort *rowA = (const GLushort *) srcRowA;
  501.       const GLushort *rowB = (const GLushort *) srcRowB;
  502.       GLushort *dst = (GLushort *) dstRow;
  503.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  504.            i++, j += colStride, k += colStride) {
  505.          const GLint rowAr0 = rowA[j] & 0xf;
  506.          const GLint rowAr1 = rowA[k] & 0xf;
  507.          const GLint rowBr0 = rowB[j] & 0xf;
  508.          const GLint rowBr1 = rowB[k] & 0xf;
  509.          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
  510.          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
  511.          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
  512.          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
  513.          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
  514.          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
  515.          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
  516.          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
  517.          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
  518.          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
  519.          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
  520.          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
  521.          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  522.          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  523.          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  524.          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
  525.          dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
  526.       }
  527.    }
  528.    else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) {
  529.       GLuint i, j, k;
  530.       const GLushort *rowA = (const GLushort *) srcRowA;
  531.       const GLushort *rowB = (const GLushort *) srcRowB;
  532.       GLushort *dst = (GLushort *) dstRow;
  533.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  534.            i++, j += colStride, k += colStride) {
  535.          const GLint rowAr0 = rowA[j] & 0x1f;
  536.          const GLint rowAr1 = rowA[k] & 0x1f;
  537.          const GLint rowBr0 = rowB[j] & 0x1f;
  538.          const GLint rowBr1 = rowB[k] & 0x1f;
  539.          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
  540.          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
  541.          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
  542.          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
  543.          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
  544.          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
  545.          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
  546.          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
  547.          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
  548.          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
  549.          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
  550.          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
  551.          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  552.          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  553.          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  554.          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
  555.          dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
  556.       }
  557.    }
  558.    else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) {
  559.       GLuint i, j, k;
  560.       const GLushort *rowA = (const GLushort *) srcRowA;
  561.       const GLushort *rowB = (const GLushort *) srcRowB;
  562.       GLushort *dst = (GLushort *) dstRow;
  563.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  564.            i++, j += colStride, k += colStride) {
  565.          const GLint rowAr0 = (rowA[j] >> 11) & 0x1f;
  566.          const GLint rowAr1 = (rowA[k] >> 11) & 0x1f;
  567.          const GLint rowBr0 = (rowB[j] >> 11) & 0x1f;
  568.          const GLint rowBr1 = (rowB[k] >> 11) & 0x1f;
  569.          const GLint rowAg0 = (rowA[j] >> 6) & 0x1f;
  570.          const GLint rowAg1 = (rowA[k] >> 6) & 0x1f;
  571.          const GLint rowBg0 = (rowB[j] >> 6) & 0x1f;
  572.          const GLint rowBg1 = (rowB[k] >> 6) & 0x1f;
  573.          const GLint rowAb0 = (rowA[j] >> 1) & 0x1f;
  574.          const GLint rowAb1 = (rowA[k] >> 1) & 0x1f;
  575.          const GLint rowBb0 = (rowB[j] >> 1) & 0x1f;
  576.          const GLint rowBb1 = (rowB[k] >> 1) & 0x1f;
  577.          const GLint rowAa0 = (rowA[j] & 0x1);
  578.          const GLint rowAa1 = (rowA[k] & 0x1);
  579.          const GLint rowBa0 = (rowB[j] & 0x1);
  580.          const GLint rowBa1 = (rowB[k] & 0x1);
  581.          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  582.          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  583.          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  584.          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
  585.          dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha;
  586.       }
  587.    }
  588.  
  589.    else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) {
  590.       GLuint i, j, k;
  591.       const GLubyte *rowA = (const GLubyte *) srcRowA;
  592.       const GLubyte *rowB = (const GLubyte *) srcRowB;
  593.       GLubyte *dst = (GLubyte *) dstRow;
  594.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  595.            i++, j += colStride, k += colStride) {
  596.          const GLint rowAr0 = rowA[j] & 0x3;
  597.          const GLint rowAr1 = rowA[k] & 0x3;
  598.          const GLint rowBr0 = rowB[j] & 0x3;
  599.          const GLint rowBr1 = rowB[k] & 0x3;
  600.          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
  601.          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
  602.          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
  603.          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
  604.          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
  605.          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
  606.          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
  607.          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
  608.          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
  609.          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
  610.          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
  611.          dst[i] = (blue << 5) | (green << 2) | red;
  612.       }
  613.    }
  614.    else {
  615.       _mesa_problem(NULL, "bad format in do_row()");
  616.    }
  617. }
  618.  
  619.  
  620. /**
  621.  * Average together four rows of a source image to produce a single new
  622.  * row in the dest image.  It's legal for the two source rows to point
  623.  * to the same data.  The source width must be equal to either the
  624.  * dest width or two times the dest width.
  625.  *
  626.  * \param datatype  GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
  627.  *                  \c GL_FLOAT, etc.
  628.  * \param comps     number of components per pixel (1..4)
  629.  * \param srcWidth  Width of a row in the source data
  630.  * \param srcRowA   Pointer to one of the rows of source data
  631.  * \param srcRowB   Pointer to one of the rows of source data
  632.  * \param srcRowC   Pointer to one of the rows of source data
  633.  * \param srcRowD   Pointer to one of the rows of source data
  634.  * \param dstWidth  Width of a row in the destination data
  635.  * \param srcRowA   Pointer to the row of destination data
  636.  */
  637. static void
  638. do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
  639.           const GLvoid *srcRowA, const GLvoid *srcRowB,
  640.           const GLvoid *srcRowC, const GLvoid *srcRowD,
  641.           GLint dstWidth, GLvoid *dstRow)
  642. {
  643.    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
  644.    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
  645.    GLuint i, j, k;
  646.  
  647.    ASSERT(comps >= 1);
  648.    ASSERT(comps <= 4);
  649.  
  650.    if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) {
  651.       DECLARE_ROW_POINTERS(GLubyte, 4);
  652.  
  653.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  654.            i++, j += colStride, k += colStride) {
  655.          FILTER_3D(0);
  656.          FILTER_3D(1);
  657.          FILTER_3D(2);
  658.          FILTER_3D(3);
  659.       }
  660.    }
  661.    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) {
  662.       DECLARE_ROW_POINTERS(GLubyte, 3);
  663.  
  664.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  665.            i++, j += colStride, k += colStride) {
  666.          FILTER_3D(0);
  667.          FILTER_3D(1);
  668.          FILTER_3D(2);
  669.       }
  670.    }
  671.    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) {
  672.       DECLARE_ROW_POINTERS(GLubyte, 2);
  673.  
  674.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  675.            i++, j += colStride, k += colStride) {
  676.          FILTER_3D(0);
  677.          FILTER_3D(1);
  678.       }
  679.    }
  680.    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) {
  681.       DECLARE_ROW_POINTERS(GLubyte, 1);
  682.  
  683.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  684.            i++, j += colStride, k += colStride) {
  685.          FILTER_3D(0);
  686.       }
  687.    }
  688.    else if ((datatype == GL_BYTE) && (comps == 4)) {
  689.       DECLARE_ROW_POINTERS(GLbyte, 4);
  690.  
  691.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  692.            i++, j += colStride, k += colStride) {
  693.          FILTER_3D_SIGNED(0);
  694.          FILTER_3D_SIGNED(1);
  695.          FILTER_3D_SIGNED(2);
  696.          FILTER_3D_SIGNED(3);
  697.       }
  698.    }
  699.    else if ((datatype == GL_BYTE) && (comps == 3)) {
  700.       DECLARE_ROW_POINTERS(GLbyte, 3);
  701.  
  702.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  703.            i++, j += colStride, k += colStride) {
  704.          FILTER_3D_SIGNED(0);
  705.          FILTER_3D_SIGNED(1);
  706.          FILTER_3D_SIGNED(2);
  707.       }
  708.    }
  709.    else if ((datatype == GL_BYTE) && (comps == 2)) {
  710.       DECLARE_ROW_POINTERS(GLbyte, 2);
  711.  
  712.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  713.            i++, j += colStride, k += colStride) {
  714.          FILTER_3D_SIGNED(0);
  715.          FILTER_3D_SIGNED(1);
  716.        }
  717.    }
  718.    else if ((datatype == GL_BYTE) && (comps == 1)) {
  719.       DECLARE_ROW_POINTERS(GLbyte, 1);
  720.  
  721.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  722.            i++, j += colStride, k += colStride) {
  723.          FILTER_3D_SIGNED(0);
  724.       }
  725.    }
  726.    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
  727.       DECLARE_ROW_POINTERS(GLushort, 4);
  728.  
  729.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  730.            i++, j += colStride, k += colStride) {
  731.          FILTER_3D(0);
  732.          FILTER_3D(1);
  733.          FILTER_3D(2);
  734.          FILTER_3D(3);
  735.       }
  736.    }
  737.    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) {
  738.       DECLARE_ROW_POINTERS(GLushort, 3);
  739.  
  740.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  741.            i++, j += colStride, k += colStride) {
  742.          FILTER_3D(0);
  743.          FILTER_3D(1);
  744.          FILTER_3D(2);
  745.       }
  746.    }
  747.    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) {
  748.       DECLARE_ROW_POINTERS(GLushort, 2);
  749.  
  750.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  751.            i++, j += colStride, k += colStride) {
  752.          FILTER_3D(0);
  753.          FILTER_3D(1);
  754.       }
  755.    }
  756.    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) {
  757.       DECLARE_ROW_POINTERS(GLushort, 1);
  758.  
  759.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  760.            i++, j += colStride, k += colStride) {
  761.          FILTER_3D(0);
  762.       }
  763.    }
  764.    else if ((datatype == GL_SHORT) && (comps == 4)) {
  765.       DECLARE_ROW_POINTERS(GLshort, 4);
  766.  
  767.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  768.            i++, j += colStride, k += colStride) {
  769.          FILTER_3D(0);
  770.          FILTER_3D(1);
  771.          FILTER_3D(2);
  772.          FILTER_3D(3);
  773.       }
  774.    }
  775.    else if ((datatype == GL_SHORT) && (comps == 3)) {
  776.       DECLARE_ROW_POINTERS(GLshort, 3);
  777.  
  778.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  779.            i++, j += colStride, k += colStride) {
  780.          FILTER_3D(0);
  781.          FILTER_3D(1);
  782.          FILTER_3D(2);
  783.       }
  784.    }
  785.    else if ((datatype == GL_SHORT) && (comps == 2)) {
  786.       DECLARE_ROW_POINTERS(GLshort, 2);
  787.  
  788.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  789.            i++, j += colStride, k += colStride) {
  790.          FILTER_3D(0);
  791.          FILTER_3D(1);
  792.       }
  793.    }
  794.    else if ((datatype == GL_SHORT) && (comps == 1)) {
  795.       DECLARE_ROW_POINTERS(GLshort, 1);
  796.  
  797.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  798.            i++, j += colStride, k += colStride) {
  799.          FILTER_3D(0);
  800.       }
  801.    }
  802.    else if ((datatype == GL_FLOAT) && (comps == 4)) {
  803.       DECLARE_ROW_POINTERS(GLfloat, 4);
  804.  
  805.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  806.            i++, j += colStride, k += colStride) {
  807.          FILTER_F_3D(0);
  808.          FILTER_F_3D(1);
  809.          FILTER_F_3D(2);
  810.          FILTER_F_3D(3);
  811.       }
  812.    }
  813.    else if ((datatype == GL_FLOAT) && (comps == 3)) {
  814.       DECLARE_ROW_POINTERS(GLfloat, 3);
  815.  
  816.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  817.            i++, j += colStride, k += colStride) {
  818.          FILTER_F_3D(0);
  819.          FILTER_F_3D(1);
  820.          FILTER_F_3D(2);
  821.       }
  822.    }
  823.    else if ((datatype == GL_FLOAT) && (comps == 2)) {
  824.       DECLARE_ROW_POINTERS(GLfloat, 2);
  825.  
  826.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  827.            i++, j += colStride, k += colStride) {
  828.          FILTER_F_3D(0);
  829.          FILTER_F_3D(1);
  830.       }
  831.    }
  832.    else if ((datatype == GL_FLOAT) && (comps == 1)) {
  833.       DECLARE_ROW_POINTERS(GLfloat, 1);
  834.  
  835.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  836.            i++, j += colStride, k += colStride) {
  837.          FILTER_F_3D(0);
  838.       }
  839.    }
  840.    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) {
  841.       DECLARE_ROW_POINTERS(GLhalfARB, 4);
  842.  
  843.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  844.            i++, j += colStride, k += colStride) {
  845.          FILTER_HF_3D(0);
  846.          FILTER_HF_3D(1);
  847.          FILTER_HF_3D(2);
  848.          FILTER_HF_3D(3);
  849.       }
  850.    }
  851.    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
  852.       DECLARE_ROW_POINTERS(GLhalfARB, 4);
  853.  
  854.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  855.            i++, j += colStride, k += colStride) {
  856.          FILTER_HF_3D(0);
  857.          FILTER_HF_3D(1);
  858.          FILTER_HF_3D(2);
  859.       }
  860.    }
  861.    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
  862.       DECLARE_ROW_POINTERS(GLhalfARB, 4);
  863.  
  864.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  865.            i++, j += colStride, k += colStride) {
  866.          FILTER_HF_3D(0);
  867.          FILTER_HF_3D(1);
  868.       }
  869.    }
  870.    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
  871.       DECLARE_ROW_POINTERS(GLhalfARB, 4);
  872.  
  873.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  874.            i++, j += colStride, k += colStride) {
  875.          FILTER_HF_3D(0);
  876.       }
  877.    }
  878.    else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) {
  879.       const GLuint *rowA = (const GLuint *) srcRowA;
  880.       const GLuint *rowB = (const GLuint *) srcRowB;
  881.       const GLuint *rowC = (const GLuint *) srcRowC;
  882.       const GLuint *rowD = (const GLuint *) srcRowD;
  883.       GLfloat *dst = (GLfloat *) dstRow;
  884.  
  885.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  886.            i++, j += colStride, k += colStride) {
  887.          const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
  888.                                + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
  889.                                + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
  890.                                + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
  891.          dst[i] = (GLfloat)((double) tmp * 0.125);
  892.       }
  893.    }
  894.    else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) {
  895.       DECLARE_ROW_POINTERS0(GLushort);
  896.  
  897.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  898.            i++, j += colStride, k += colStride) {
  899.          const GLint rowAr0 = rowA[j] & 0x1f;
  900.          const GLint rowAr1 = rowA[k] & 0x1f;
  901.          const GLint rowBr0 = rowB[j] & 0x1f;
  902.          const GLint rowBr1 = rowB[k] & 0x1f;
  903.          const GLint rowCr0 = rowC[j] & 0x1f;
  904.          const GLint rowCr1 = rowC[k] & 0x1f;
  905.          const GLint rowDr0 = rowD[j] & 0x1f;
  906.          const GLint rowDr1 = rowD[k] & 0x1f;
  907.          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
  908.          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
  909.          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
  910.          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
  911.          const GLint rowCg0 = (rowC[j] >> 5) & 0x3f;
  912.          const GLint rowCg1 = (rowC[k] >> 5) & 0x3f;
  913.          const GLint rowDg0 = (rowD[j] >> 5) & 0x3f;
  914.          const GLint rowDg1 = (rowD[k] >> 5) & 0x3f;
  915.          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
  916.          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
  917.          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
  918.          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
  919.          const GLint rowCb0 = (rowC[j] >> 11) & 0x1f;
  920.          const GLint rowCb1 = (rowC[k] >> 11) & 0x1f;
  921.          const GLint rowDb0 = (rowD[j] >> 11) & 0x1f;
  922.          const GLint rowDb1 = (rowD[k] >> 11) & 0x1f;
  923.          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  924.                                        rowCr0, rowCr1, rowDr0, rowDr1);
  925.          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  926.                                        rowCg0, rowCg1, rowDg0, rowDg1);
  927.          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  928.                                        rowCb0, rowCb1, rowDb0, rowDb1);
  929.          dst[i] = (b << 11) | (g << 5) | r;
  930.       }
  931.    }
  932.    else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) {
  933.       DECLARE_ROW_POINTERS0(GLushort);
  934.  
  935.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  936.            i++, j += colStride, k += colStride) {
  937.          const GLint rowAr0 = rowA[j] & 0xf;
  938.          const GLint rowAr1 = rowA[k] & 0xf;
  939.          const GLint rowBr0 = rowB[j] & 0xf;
  940.          const GLint rowBr1 = rowB[k] & 0xf;
  941.          const GLint rowCr0 = rowC[j] & 0xf;
  942.          const GLint rowCr1 = rowC[k] & 0xf;
  943.          const GLint rowDr0 = rowD[j] & 0xf;
  944.          const GLint rowDr1 = rowD[k] & 0xf;
  945.          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
  946.          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
  947.          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
  948.          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
  949.          const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
  950.          const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
  951.          const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
  952.          const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
  953.          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
  954.          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
  955.          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
  956.          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
  957.          const GLint rowCb0 = (rowC[j] >> 8) & 0xf;
  958.          const GLint rowCb1 = (rowC[k] >> 8) & 0xf;
  959.          const GLint rowDb0 = (rowD[j] >> 8) & 0xf;
  960.          const GLint rowDb1 = (rowD[k] >> 8) & 0xf;
  961.          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
  962.          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
  963.          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
  964.          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
  965.          const GLint rowCa0 = (rowC[j] >> 12) & 0xf;
  966.          const GLint rowCa1 = (rowC[k] >> 12) & 0xf;
  967.          const GLint rowDa0 = (rowD[j] >> 12) & 0xf;
  968.          const GLint rowDa1 = (rowD[k] >> 12) & 0xf;
  969.          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  970.                                        rowCr0, rowCr1, rowDr0, rowDr1);
  971.          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  972.                                        rowCg0, rowCg1, rowDg0, rowDg1);
  973.          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  974.                                        rowCb0, rowCb1, rowDb0, rowDb1);
  975.          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
  976.                                        rowCa0, rowCa1, rowDa0, rowDa1);
  977.  
  978.          dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
  979.       }
  980.    }
  981.    else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) {
  982.       DECLARE_ROW_POINTERS0(GLushort);
  983.  
  984.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  985.            i++, j += colStride, k += colStride) {
  986.          const GLint rowAr0 = rowA[j] & 0x1f;
  987.          const GLint rowAr1 = rowA[k] & 0x1f;
  988.          const GLint rowBr0 = rowB[j] & 0x1f;
  989.          const GLint rowBr1 = rowB[k] & 0x1f;
  990.          const GLint rowCr0 = rowC[j] & 0x1f;
  991.          const GLint rowCr1 = rowC[k] & 0x1f;
  992.          const GLint rowDr0 = rowD[j] & 0x1f;
  993.          const GLint rowDr1 = rowD[k] & 0x1f;
  994.          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
  995.          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
  996.          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
  997.          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
  998.          const GLint rowCg0 = (rowC[j] >> 5) & 0x1f;
  999.          const GLint rowCg1 = (rowC[k] >> 5) & 0x1f;
  1000.          const GLint rowDg0 = (rowD[j] >> 5) & 0x1f;
  1001.          const GLint rowDg1 = (rowD[k] >> 5) & 0x1f;
  1002.          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
  1003.          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
  1004.          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
  1005.          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
  1006.          const GLint rowCb0 = (rowC[j] >> 10) & 0x1f;
  1007.          const GLint rowCb1 = (rowC[k] >> 10) & 0x1f;
  1008.          const GLint rowDb0 = (rowD[j] >> 10) & 0x1f;
  1009.          const GLint rowDb1 = (rowD[k] >> 10) & 0x1f;
  1010.          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
  1011.          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
  1012.          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
  1013.          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
  1014.          const GLint rowCa0 = (rowC[j] >> 15) & 0x1;
  1015.          const GLint rowCa1 = (rowC[k] >> 15) & 0x1;
  1016.          const GLint rowDa0 = (rowD[j] >> 15) & 0x1;
  1017.          const GLint rowDa1 = (rowD[k] >> 15) & 0x1;
  1018.          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  1019.                                        rowCr0, rowCr1, rowDr0, rowDr1);
  1020.          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  1021.                                        rowCg0, rowCg1, rowDg0, rowDg1);
  1022.          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  1023.                                        rowCb0, rowCb1, rowDb0, rowDb1);
  1024.          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
  1025.                                        rowCa0, rowCa1, rowDa0, rowDa1);
  1026.  
  1027.          dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
  1028.       }
  1029.    }
  1030.    else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) {
  1031.       DECLARE_ROW_POINTERS0(GLushort);
  1032.  
  1033.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1034.            i++, j += colStride, k += colStride) {
  1035.          const GLint rowAr0 = (rowA[j] >> 11) & 0x1f;
  1036.          const GLint rowAr1 = (rowA[k] >> 11) & 0x1f;
  1037.          const GLint rowBr0 = (rowB[j] >> 11) & 0x1f;
  1038.          const GLint rowBr1 = (rowB[k] >> 11) & 0x1f;
  1039.          const GLint rowCr0 = (rowC[j] >> 11) & 0x1f;
  1040.          const GLint rowCr1 = (rowC[k] >> 11) & 0x1f;
  1041.          const GLint rowDr0 = (rowD[j] >> 11) & 0x1f;
  1042.          const GLint rowDr1 = (rowD[k] >> 11) & 0x1f;
  1043.          const GLint rowAg0 = (rowA[j] >> 6) & 0x1f;
  1044.          const GLint rowAg1 = (rowA[k] >> 6) & 0x1f;
  1045.          const GLint rowBg0 = (rowB[j] >> 6) & 0x1f;
  1046.          const GLint rowBg1 = (rowB[k] >> 6) & 0x1f;
  1047.          const GLint rowCg0 = (rowC[j] >> 6) & 0x1f;
  1048.          const GLint rowCg1 = (rowC[k] >> 6) & 0x1f;
  1049.          const GLint rowDg0 = (rowD[j] >> 6) & 0x1f;
  1050.          const GLint rowDg1 = (rowD[k] >> 6) & 0x1f;
  1051.          const GLint rowAb0 = (rowA[j] >> 1) & 0x1f;
  1052.          const GLint rowAb1 = (rowA[k] >> 1) & 0x1f;
  1053.          const GLint rowBb0 = (rowB[j] >> 1) & 0x1f;
  1054.          const GLint rowBb1 = (rowB[k] >> 1) & 0x1f;
  1055.          const GLint rowCb0 = (rowC[j] >> 1) & 0x1f;
  1056.          const GLint rowCb1 = (rowC[k] >> 1) & 0x1f;
  1057.          const GLint rowDb0 = (rowD[j] >> 1) & 0x1f;
  1058.          const GLint rowDb1 = (rowD[k] >> 1) & 0x1f;
  1059.          const GLint rowAa0 = (rowA[j] & 0x1);
  1060.          const GLint rowAa1 = (rowA[k] & 0x1);
  1061.          const GLint rowBa0 = (rowB[j] & 0x1);
  1062.          const GLint rowBa1 = (rowB[k] & 0x1);
  1063.          const GLint rowCa0 = (rowC[j] & 0x1);
  1064.          const GLint rowCa1 = (rowC[k] & 0x1);
  1065.          const GLint rowDa0 = (rowD[j] & 0x1);
  1066.          const GLint rowDa1 = (rowD[k] & 0x1);
  1067.          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  1068.                                        rowCr0, rowCr1, rowDr0, rowDr1);
  1069.          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  1070.                                        rowCg0, rowCg1, rowDg0, rowDg1);
  1071.          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  1072.                                        rowCb0, rowCb1, rowDb0, rowDb1);
  1073.          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
  1074.                                        rowCa0, rowCa1, rowDa0, rowDa1);
  1075.  
  1076.          dst[i] = (r << 11) | (g << 6) | (b << 1) | a;
  1077.       }
  1078.    }
  1079.    else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
  1080.       DECLARE_ROW_POINTERS0(GLubyte);
  1081.  
  1082.       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
  1083.            i++, j += colStride, k += colStride) {
  1084.          const GLint rowAr0 = rowA[j] & 0x3;
  1085.          const GLint rowAr1 = rowA[k] & 0x3;
  1086.          const GLint rowBr0 = rowB[j] & 0x3;
  1087.          const GLint rowBr1 = rowB[k] & 0x3;
  1088.          const GLint rowCr0 = rowC[j] & 0x3;
  1089.          const GLint rowCr1 = rowC[k] & 0x3;
  1090.          const GLint rowDr0 = rowD[j] & 0x3;
  1091.          const GLint rowDr1 = rowD[k] & 0x3;
  1092.          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
  1093.          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
  1094.          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
  1095.          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
  1096.          const GLint rowCg0 = (rowC[j] >> 2) & 0x7;
  1097.          const GLint rowCg1 = (rowC[k] >> 2) & 0x7;
  1098.          const GLint rowDg0 = (rowD[j] >> 2) & 0x7;
  1099.          const GLint rowDg1 = (rowD[k] >> 2) & 0x7;
  1100.          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
  1101.          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
  1102.          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
  1103.          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
  1104.          const GLint rowCb0 = (rowC[j] >> 5) & 0x7;
  1105.          const GLint rowCb1 = (rowC[k] >> 5) & 0x7;
  1106.          const GLint rowDb0 = (rowD[j] >> 5) & 0x7;
  1107.          const GLint rowDb1 = (rowD[k] >> 5) & 0x7;
  1108.          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
  1109.                                        rowCr0, rowCr1, rowDr0, rowDr1);
  1110.          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
  1111.                                        rowCg0, rowCg1, rowDg0, rowDg1);
  1112.          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
  1113.                                        rowCb0, rowCb1, rowDb0, rowDb1);
  1114.          dst[i] = (b << 5) | (g << 2) | r;
  1115.       }
  1116.    }
  1117.    else {
  1118.       _mesa_problem(NULL, "bad format in do_row()");
  1119.    }
  1120. }
  1121.  
  1122.  
  1123. /*
  1124.  * These functions generate a 1/2-size mipmap image from a source image.
  1125.  * Texture borders are handled by copying or averaging the source image's
  1126.  * border texels, depending on the scale-down factor.
  1127.  */
  1128.  
  1129. static void
  1130. make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
  1131.                GLint srcWidth, const GLubyte *srcPtr,
  1132.                GLint dstWidth, GLubyte *dstPtr)
  1133. {
  1134.    const GLint bpt = bytes_per_pixel(datatype, comps);
  1135.    const GLubyte *src;
  1136.    GLubyte *dst;
  1137.  
  1138.    /* skip the border pixel, if any */
  1139.    src = srcPtr + border * bpt;
  1140.    dst = dstPtr + border * bpt;
  1141.  
  1142.    /* we just duplicate the input row, kind of hack, saves code */
  1143.    do_row(datatype, comps, srcWidth - 2 * border, src, src,
  1144.           dstWidth - 2 * border, dst);
  1145.  
  1146.    if (border) {
  1147.       /* copy left-most pixel from source */
  1148.       assert(dstPtr);
  1149.       assert(srcPtr);
  1150.       memcpy(dstPtr, srcPtr, bpt);
  1151.       /* copy right-most pixel from source */
  1152.       memcpy(dstPtr + (dstWidth - 1) * bpt,
  1153.              srcPtr + (srcWidth - 1) * bpt,
  1154.              bpt);
  1155.    }
  1156. }
  1157.  
  1158.  
  1159. static void
  1160. make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
  1161.                GLint srcWidth, GLint srcHeight,
  1162.                const GLubyte *srcPtr, GLint srcRowStride,
  1163.                GLint dstWidth, GLint dstHeight,
  1164.                GLubyte *dstPtr, GLint dstRowStride)
  1165. {
  1166.    const GLint bpt = bytes_per_pixel(datatype, comps);
  1167.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1168.    const GLint dstWidthNB = dstWidth - 2 * border;
  1169.    const GLint dstHeightNB = dstHeight - 2 * border;
  1170.    const GLint srcRowBytes = bpt * srcRowStride;
  1171.    const GLint dstRowBytes = bpt * dstRowStride;
  1172.    const GLubyte *srcA, *srcB;
  1173.    GLubyte *dst;
  1174.    GLint row, srcRowStep;
  1175.  
  1176.    /* Compute src and dst pointers, skipping any border */
  1177.    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
  1178.    if (srcHeight > 1 && srcHeight > dstHeight) {
  1179.       /* sample from two source rows */
  1180.       srcB = srcA + srcRowBytes;
  1181.       srcRowStep = 2;
  1182.    }
  1183.    else {
  1184.       /* sample from one source row */
  1185.       srcB = srcA;
  1186.       srcRowStep = 1;
  1187.    }
  1188.  
  1189.    dst = dstPtr + border * ((dstWidth + 1) * bpt);
  1190.  
  1191.    for (row = 0; row < dstHeightNB; row++) {
  1192.       do_row(datatype, comps, srcWidthNB, srcA, srcB,
  1193.              dstWidthNB, dst);
  1194.       srcA += srcRowStep * srcRowBytes;
  1195.       srcB += srcRowStep * srcRowBytes;
  1196.       dst += dstRowBytes;
  1197.    }
  1198.  
  1199.    /* This is ugly but probably won't be used much */
  1200.    if (border > 0) {
  1201.       /* fill in dest border */
  1202.       /* lower-left border pixel */
  1203.       assert(dstPtr);
  1204.       assert(srcPtr);
  1205.       memcpy(dstPtr, srcPtr, bpt);
  1206.       /* lower-right border pixel */
  1207.       memcpy(dstPtr + (dstWidth - 1) * bpt,
  1208.              srcPtr + (srcWidth - 1) * bpt, bpt);
  1209.       /* upper-left border pixel */
  1210.       memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt,
  1211.              srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
  1212.       /* upper-right border pixel */
  1213.       memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt,
  1214.              srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
  1215.       /* lower border */
  1216.       do_row(datatype, comps, srcWidthNB,
  1217.              srcPtr + bpt,
  1218.              srcPtr + bpt,
  1219.              dstWidthNB, dstPtr + bpt);
  1220.       /* upper border */
  1221.       do_row(datatype, comps, srcWidthNB,
  1222.              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1223.              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1224.              dstWidthNB,
  1225.              dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
  1226.       /* left and right borders */
  1227.       if (srcHeight == dstHeight) {
  1228.          /* copy border pixel from src to dst */
  1229.          for (row = 1; row < srcHeight; row++) {
  1230.             memcpy(dstPtr + dstWidth * row * bpt,
  1231.                    srcPtr + srcWidth * row * bpt, bpt);
  1232.             memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
  1233.                    srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
  1234.          }
  1235.       }
  1236.       else {
  1237.          /* average two src pixels each dest pixel */
  1238.          for (row = 0; row < dstHeightNB; row += 2) {
  1239.             do_row(datatype, comps, 1,
  1240.                    srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
  1241.                    srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
  1242.                    1, dstPtr + (dstWidth * row + 1) * bpt);
  1243.             do_row(datatype, comps, 1,
  1244.                    srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
  1245.                    srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
  1246.                    1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
  1247.          }
  1248.       }
  1249.    }
  1250. }
  1251.  
  1252.  
  1253. static void
  1254. make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
  1255.                GLint srcWidth, GLint srcHeight, GLint srcDepth,
  1256.                const GLubyte *srcPtr, GLint srcRowStride,
  1257.                GLint dstWidth, GLint dstHeight, GLint dstDepth,
  1258.                GLubyte *dstPtr, GLint dstRowStride)
  1259. {
  1260.    const GLint bpt = bytes_per_pixel(datatype, comps);
  1261.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1262.    const GLint srcDepthNB = srcDepth - 2 * border;
  1263.    const GLint dstWidthNB = dstWidth - 2 * border;
  1264.    const GLint dstHeightNB = dstHeight - 2 * border;
  1265.    const GLint dstDepthNB = dstDepth - 2 * border;
  1266.    GLint img, row;
  1267.    GLint bytesPerSrcImage, bytesPerDstImage;
  1268.    GLint bytesPerSrcRow, bytesPerDstRow;
  1269.    GLint srcImageOffset, srcRowOffset;
  1270.  
  1271.    (void) srcDepthNB; /* silence warnings */
  1272.  
  1273.  
  1274.    bytesPerSrcImage = srcWidth * srcHeight * bpt;
  1275.    bytesPerDstImage = dstWidth * dstHeight * bpt;
  1276.  
  1277.    bytesPerSrcRow = srcWidth * bpt;
  1278.    bytesPerDstRow = dstWidth * bpt;
  1279.  
  1280.    /* Offset between adjacent src images to be averaged together */
  1281.    srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
  1282.  
  1283.    /* Offset between adjacent src rows to be averaged together */
  1284.    srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
  1285.  
  1286.    /*
  1287.     * Need to average together up to 8 src pixels for each dest pixel.
  1288.     * Break that down into 3 operations:
  1289.     *   1. take two rows from source image and average them together.
  1290.     *   2. take two rows from next source image and average them together.
  1291.     *   3. take the two averaged rows and average them for the final dst row.
  1292.     */
  1293.  
  1294.    /*
  1295.    printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
  1296.           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
  1297.    */
  1298.  
  1299.    for (img = 0; img < dstDepthNB; img++) {
  1300.       /* first source image pointer, skipping border */
  1301.       const GLubyte *imgSrcA = srcPtr
  1302.          + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
  1303.          + img * (bytesPerSrcImage + srcImageOffset);
  1304.       /* second source image pointer, skipping border */
  1305.       const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
  1306.       /* address of the dest image, skipping border */
  1307.       GLubyte *imgDst = dstPtr
  1308.          + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
  1309.          + img * bytesPerDstImage;
  1310.  
  1311.       /* setup the four source row pointers and the dest row pointer */
  1312.       const GLubyte *srcImgARowA = imgSrcA;
  1313.       const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
  1314.       const GLubyte *srcImgBRowA = imgSrcB;
  1315.       const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
  1316.       GLubyte *dstImgRow = imgDst;
  1317.  
  1318.       for (row = 0; row < dstHeightNB; row++) {
  1319.          do_row_3D(datatype, comps, srcWidthNB,
  1320.                    srcImgARowA, srcImgARowB,
  1321.                    srcImgBRowA, srcImgBRowB,
  1322.                    dstWidthNB, dstImgRow);
  1323.  
  1324.          /* advance to next rows */
  1325.          srcImgARowA += bytesPerSrcRow + srcRowOffset;
  1326.          srcImgARowB += bytesPerSrcRow + srcRowOffset;
  1327.          srcImgBRowA += bytesPerSrcRow + srcRowOffset;
  1328.          srcImgBRowB += bytesPerSrcRow + srcRowOffset;
  1329.          dstImgRow += bytesPerDstRow;
  1330.       }
  1331.    }
  1332.  
  1333.  
  1334.    /* Luckily we can leverage the make_2d_mipmap() function here! */
  1335.    if (border > 0) {
  1336.       /* do front border image */
  1337.       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
  1338.                      dstWidth, dstHeight, dstPtr, dstRowStride);
  1339.       /* do back border image */
  1340.       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
  1341.                      srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
  1342.                      dstWidth, dstHeight,
  1343.                      dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
  1344.       /* do four remaining border edges that span the image slices */
  1345.       if (srcDepth == dstDepth) {
  1346.          /* just copy border pixels from src to dst */
  1347.          for (img = 0; img < dstDepthNB; img++) {
  1348.             const GLubyte *src;
  1349.             GLubyte *dst;
  1350.  
  1351.             /* do border along [img][row=0][col=0] */
  1352.             src = srcPtr + (img + 1) * bytesPerSrcImage;
  1353.             dst = dstPtr + (img + 1) * bytesPerDstImage;
  1354.             memcpy(dst, src, bpt);
  1355.  
  1356.             /* do border along [img][row=dstHeight-1][col=0] */
  1357.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1358.                          + (srcHeight - 1) * bytesPerSrcRow;
  1359.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1360.                          + (dstHeight - 1) * bytesPerDstRow;
  1361.             memcpy(dst, src, bpt);
  1362.  
  1363.             /* do border along [img][row=0][col=dstWidth-1] */
  1364.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1365.                          + (srcWidth - 1) * bpt;
  1366.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1367.                          + (dstWidth - 1) * bpt;
  1368.             memcpy(dst, src, bpt);
  1369.  
  1370.             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
  1371.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1372.                          + (bytesPerSrcImage - bpt);
  1373.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1374.                          + (bytesPerDstImage - bpt);
  1375.             memcpy(dst, src, bpt);
  1376.          }
  1377.       }
  1378.       else {
  1379.          /* average border pixels from adjacent src image pairs */
  1380.          ASSERT(srcDepthNB == 2 * dstDepthNB);
  1381.          for (img = 0; img < dstDepthNB; img++) {
  1382.             const GLubyte *src;
  1383.             GLubyte *dst;
  1384.  
  1385.             /* do border along [img][row=0][col=0] */
  1386.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
  1387.             dst = dstPtr + (img + 1) * bytesPerDstImage;
  1388.             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
  1389.  
  1390.             /* do border along [img][row=dstHeight-1][col=0] */
  1391.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1392.                          + (srcHeight - 1) * bytesPerSrcRow;
  1393.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1394.                          + (dstHeight - 1) * bytesPerDstRow;
  1395.             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
  1396.  
  1397.             /* do border along [img][row=0][col=dstWidth-1] */
  1398.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1399.                          + (srcWidth - 1) * bpt;
  1400.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1401.                          + (dstWidth - 1) * bpt;
  1402.             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
  1403.  
  1404.             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
  1405.             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
  1406.                          + (bytesPerSrcImage - bpt);
  1407.             dst = dstPtr + (img + 1) * bytesPerDstImage
  1408.                          + (bytesPerDstImage - bpt);
  1409.             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
  1410.          }
  1411.       }
  1412.    }
  1413. }
  1414.  
  1415.  
  1416. static void
  1417. make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
  1418.                      GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride,
  1419.                      GLint dstWidth, GLint dstHeight,
  1420.                      GLubyte *dstPtr, GLuint dstRowStride )
  1421. {
  1422.    const GLint bpt = bytes_per_pixel(datatype, comps);
  1423.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1424.    const GLint dstWidthNB = dstWidth - 2 * border;
  1425.    const GLint dstHeightNB = dstHeight - 2 * border;
  1426.    const GLint srcRowBytes = bpt * srcRowStride;
  1427.    const GLint dstRowBytes = bpt * dstRowStride;
  1428.    const GLubyte *src;
  1429.    GLubyte *dst;
  1430.    GLint row;
  1431.  
  1432.    /* Compute src and dst pointers, skipping any border */
  1433.    src = srcPtr + border * ((srcWidth + 1) * bpt);
  1434.    dst = dstPtr + border * ((dstWidth + 1) * bpt);
  1435.  
  1436.    for (row = 0; row < dstHeightNB; row++) {
  1437.       do_row(datatype, comps, srcWidthNB, src, src,
  1438.              dstWidthNB, dst);
  1439.       src += srcRowBytes;
  1440.       dst += dstRowBytes;
  1441.    }
  1442.  
  1443.    if (border) {
  1444.       /* copy left-most pixel from source */
  1445.       assert(dstPtr);
  1446.       assert(srcPtr);
  1447.       memcpy(dstPtr, srcPtr, bpt);
  1448.       /* copy right-most pixel from source */
  1449.       memcpy(dstPtr + (dstWidth - 1) * bpt,
  1450.              srcPtr + (srcWidth - 1) * bpt,
  1451.              bpt);
  1452.    }
  1453. }
  1454.  
  1455.  
  1456. /**
  1457.  * \bug
  1458.  * There is quite a bit of refactoring that could be done with this function
  1459.  * and \c make_2d_mipmap.
  1460.  */
  1461. static void
  1462. make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
  1463.                      GLint srcWidth, GLint srcHeight,
  1464.                      const GLubyte *srcPtr, GLint srcRowStride,
  1465.                      GLint dstWidth, GLint dstHeight, GLint dstDepth,
  1466.                      GLubyte *dstPtr, GLint dstRowStride)
  1467. {
  1468.    const GLint bpt = bytes_per_pixel(datatype, comps);
  1469.    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
  1470.    const GLint dstWidthNB = dstWidth - 2 * border;
  1471.    const GLint dstHeightNB = dstHeight - 2 * border;
  1472.    const GLint dstDepthNB = dstDepth - 2 * border;
  1473.    const GLint srcRowBytes = bpt * srcRowStride;
  1474.    const GLint dstRowBytes = bpt * dstRowStride;
  1475.    const GLubyte *srcA, *srcB;
  1476.    GLubyte *dst;
  1477.    GLint layer;
  1478.    GLint row;
  1479.  
  1480.    /* Compute src and dst pointers, skipping any border */
  1481.    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
  1482.    if (srcHeight > 1)
  1483.       srcB = srcA + srcRowBytes;
  1484.    else
  1485.       srcB = srcA;
  1486.    dst = dstPtr + border * ((dstWidth + 1) * bpt);
  1487.  
  1488.    for (layer = 0; layer < dstDepthNB; layer++) {
  1489.       for (row = 0; row < dstHeightNB; row++) {
  1490.          do_row(datatype, comps, srcWidthNB, srcA, srcB,
  1491.                 dstWidthNB, dst);
  1492.          srcA += 2 * srcRowBytes;
  1493.          srcB += 2 * srcRowBytes;
  1494.          dst += dstRowBytes;
  1495.       }
  1496.  
  1497.       /* This is ugly but probably won't be used much */
  1498.       if (border > 0) {
  1499.          /* fill in dest border */
  1500.          /* lower-left border pixel */
  1501.          assert(dstPtr);
  1502.          assert(srcPtr);
  1503.          memcpy(dstPtr, srcPtr, bpt);
  1504.          /* lower-right border pixel */
  1505.          memcpy(dstPtr + (dstWidth - 1) * bpt,
  1506.                 srcPtr + (srcWidth - 1) * bpt, bpt);
  1507.          /* upper-left border pixel */
  1508.          memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt,
  1509.                 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
  1510.          /* upper-right border pixel */
  1511.          memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt,
  1512.                 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
  1513.          /* lower border */
  1514.          do_row(datatype, comps, srcWidthNB,
  1515.                 srcPtr + bpt,
  1516.                 srcPtr + bpt,
  1517.                 dstWidthNB, dstPtr + bpt);
  1518.          /* upper border */
  1519.          do_row(datatype, comps, srcWidthNB,
  1520.                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1521.                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
  1522.                 dstWidthNB,
  1523.                 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
  1524.          /* left and right borders */
  1525.          if (srcHeight == dstHeight) {
  1526.             /* copy border pixel from src to dst */
  1527.             for (row = 1; row < srcHeight; row++) {
  1528.                memcpy(dstPtr + dstWidth * row * bpt,
  1529.                       srcPtr + srcWidth * row * bpt, bpt);
  1530.                memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
  1531.                       srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
  1532.             }
  1533.          }
  1534.          else {
  1535.             /* average two src pixels each dest pixel */
  1536.             for (row = 0; row < dstHeightNB; row += 2) {
  1537.                do_row(datatype, comps, 1,
  1538.                       srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
  1539.                       srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
  1540.                       1, dstPtr + (dstWidth * row + 1) * bpt);
  1541.                do_row(datatype, comps, 1,
  1542.                       srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
  1543.                       srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
  1544.                       1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
  1545.             }
  1546.          }
  1547.       }
  1548.    }
  1549. }
  1550.  
  1551.  
  1552. /**
  1553.  * Down-sample a texture image to produce the next lower mipmap level.
  1554.  * \param comps  components per texel (1, 2, 3 or 4)
  1555.  * \param srcRowStride  stride between source rows, in texels
  1556.  * \param dstRowStride  stride between destination rows, in texels
  1557.  */
  1558. void
  1559. _mesa_generate_mipmap_level(GLenum target,
  1560.                             GLenum datatype, GLuint comps,
  1561.                             GLint border,
  1562.                             GLint srcWidth, GLint srcHeight, GLint srcDepth,
  1563.                             const GLubyte *srcData,
  1564.                             GLint srcRowStride,
  1565.                             GLint dstWidth, GLint dstHeight, GLint dstDepth,
  1566.                             GLubyte *dstData,
  1567.                             GLint dstRowStride)
  1568. {
  1569.    /*
  1570.     * We use simple 2x2 averaging to compute the next mipmap level.
  1571.     */
  1572.    switch (target) {
  1573.    case GL_TEXTURE_1D:
  1574.       make_1d_mipmap(datatype, comps, border,
  1575.                      srcWidth, srcData,
  1576.                      dstWidth, dstData);
  1577.       break;
  1578.    case GL_TEXTURE_2D:
  1579.    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
  1580.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
  1581.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
  1582.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
  1583.    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
  1584.    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
  1585.       make_2d_mipmap(datatype, comps, border,
  1586.                      srcWidth, srcHeight, srcData, srcRowStride,
  1587.                      dstWidth, dstHeight, dstData, dstRowStride);
  1588.       break;
  1589.    case GL_TEXTURE_3D:
  1590.       make_3d_mipmap(datatype, comps, border,
  1591.                      srcWidth, srcHeight, srcDepth,
  1592.                      srcData, srcRowStride,
  1593.                      dstWidth, dstHeight, dstDepth,
  1594.                      dstData, dstRowStride);
  1595.       break;
  1596.    case GL_TEXTURE_1D_ARRAY_EXT:
  1597.       make_1d_stack_mipmap(datatype, comps, border,
  1598.                            srcWidth, srcData, srcRowStride,
  1599.                            dstWidth, dstHeight,
  1600.                            dstData, dstRowStride);
  1601.       break;
  1602.    case GL_TEXTURE_2D_ARRAY_EXT:
  1603.       make_2d_stack_mipmap(datatype, comps, border,
  1604.                            srcWidth, srcHeight,
  1605.                            srcData, srcRowStride,
  1606.                            dstWidth, dstHeight,
  1607.                            dstDepth, dstData, dstRowStride);
  1608.       break;
  1609.    case GL_TEXTURE_RECTANGLE_NV:
  1610.       /* no mipmaps, do nothing */
  1611.       break;
  1612.    default:
  1613.       _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
  1614.       return;
  1615.    }
  1616. }
  1617.  
  1618.  
  1619. /**
  1620.  * compute next (level+1) image size
  1621.  * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
  1622.  */
  1623. static GLboolean
  1624. next_mipmap_level_size(GLenum target, GLint border,
  1625.                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
  1626.                        GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
  1627. {
  1628.    if (srcWidth - 2 * border > 1) {
  1629.       *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
  1630.    }
  1631.    else {
  1632.       *dstWidth = srcWidth; /* can't go smaller */
  1633.    }
  1634.  
  1635.    if ((srcHeight - 2 * border > 1) &&
  1636.        (target != GL_TEXTURE_1D_ARRAY_EXT)) {
  1637.       *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
  1638.    }
  1639.    else {
  1640.       *dstHeight = srcHeight; /* can't go smaller */
  1641.    }
  1642.  
  1643.    if ((srcDepth - 2 * border > 1) &&
  1644.        (target != GL_TEXTURE_2D_ARRAY_EXT)) {
  1645.       *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
  1646.    }
  1647.    else {
  1648.       *dstDepth = srcDepth; /* can't go smaller */
  1649.    }
  1650.  
  1651.    if (*dstWidth == srcWidth &&
  1652.        *dstHeight == srcHeight &&
  1653.        *dstDepth == srcDepth) {
  1654.       return GL_FALSE;
  1655.    }
  1656.    else {
  1657.       return GL_TRUE;
  1658.    }
  1659. }
  1660.  
  1661.  
  1662.  
  1663.  
  1664. /**
  1665.  * Automatic mipmap generation.
  1666.  * This is the fallback/default function for ctx->Driver.GenerateMipmap().
  1667.  * Generate a complete set of mipmaps from texObj's BaseLevel image.
  1668.  * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
  1669.  * For cube maps, target will be one of
  1670.  * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
  1671.  */
  1672. void
  1673. _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
  1674.                       struct gl_texture_object *texObj)
  1675. {
  1676.    const struct gl_texture_image *srcImage;
  1677.    gl_format convertFormat;
  1678.    const GLubyte *srcData = NULL;
  1679.    GLubyte *dstData = NULL;
  1680.    GLint level, maxLevels;
  1681.    GLenum datatype;
  1682.    GLuint comps;
  1683.  
  1684.    ASSERT(texObj);
  1685.    srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
  1686.    ASSERT(srcImage);
  1687.  
  1688.    maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
  1689.    ASSERT(maxLevels > 0);  /* bad target */
  1690.  
  1691.    /* Find convertFormat - the format that do_row() will process */
  1692.  
  1693.    if (_mesa_is_format_compressed(srcImage->TexFormat)) {
  1694.       /* setup for compressed textures - need to allocate temporary
  1695.        * image buffers to hold uncompressed images.
  1696.        */
  1697.       GLuint row;
  1698.       GLint  components, size;
  1699.       GLchan *dst;
  1700.  
  1701.       assert(texObj->Target == GL_TEXTURE_2D ||
  1702.              texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
  1703.  
  1704.       if (srcImage->_BaseFormat == GL_RGB) {
  1705.          convertFormat = MESA_FORMAT_RGB888;
  1706.          components = 3;
  1707.       }
  1708.       else if (srcImage->_BaseFormat == GL_RGBA) {
  1709.          convertFormat = MESA_FORMAT_RGBA8888;
  1710.          components = 4;
  1711.       }
  1712.       else {
  1713.          _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
  1714.          return;
  1715.       }
  1716.  
  1717.       /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
  1718.       size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
  1719.          * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
  1720.       /* 20 extra bytes, just be safe when calling last FetchTexel */
  1721.       srcData = (GLubyte *) malloc(size);
  1722.       if (!srcData) {
  1723.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
  1724.          return;
  1725.       }
  1726.       dstData = (GLubyte *) malloc(size / 2);  /* 1/4 would probably be OK */
  1727.       if (!dstData) {
  1728.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
  1729.          free((void *) srcData);
  1730.          return;
  1731.       }
  1732.  
  1733.       /* decompress base image here */
  1734.       dst = (GLchan *) srcData;
  1735.       for (row = 0; row < srcImage->Height; row++) {
  1736.          GLuint col;
  1737.          for (col = 0; col < srcImage->Width; col++) {
  1738.             srcImage->FetchTexelc(srcImage, col, row, 0, dst);
  1739.             dst += components;
  1740.          }
  1741.       }
  1742.    }
  1743.    else {
  1744.       /* uncompressed */
  1745.       convertFormat = srcImage->TexFormat;
  1746.    }
  1747.  
  1748.    _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
  1749.  
  1750.    for (level = texObj->BaseLevel; level < texObj->MaxLevel
  1751.            && level < maxLevels - 1; level++) {
  1752.       /* generate image[level+1] from image[level] */
  1753.       const struct gl_texture_image *srcImage;
  1754.       struct gl_texture_image *dstImage;
  1755.       GLint srcWidth, srcHeight, srcDepth;
  1756.       GLint dstWidth, dstHeight, dstDepth;
  1757.       GLint border;
  1758.       GLboolean nextLevel;
  1759.  
  1760.       /* get src image parameters */
  1761.       srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
  1762.       ASSERT(srcImage);
  1763.       srcWidth = srcImage->Width;
  1764.       srcHeight = srcImage->Height;
  1765.       srcDepth = srcImage->Depth;
  1766.       border = srcImage->Border;
  1767.  
  1768.       nextLevel = next_mipmap_level_size(target, border,
  1769.                                          srcWidth, srcHeight, srcDepth,
  1770.                                          &dstWidth, &dstHeight, &dstDepth);
  1771.       if (!nextLevel) {
  1772.          /* all done */
  1773.          if (_mesa_is_format_compressed(srcImage->TexFormat)) {
  1774.             free((void *) srcData);
  1775.             free(dstData);
  1776.          }
  1777.          return;
  1778.       }
  1779.  
  1780.       /* get dest gl_texture_image */
  1781.       dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
  1782.       if (!dstImage) {
  1783.          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  1784.          return;
  1785.       }
  1786.  
  1787.       /* Free old image data */
  1788.       if (dstImage->Data)
  1789.          ctx->Driver.FreeTexImageData(ctx, dstImage);
  1790.  
  1791.       /* initialize new image */
  1792.       _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
  1793.                                  dstDepth, border, srcImage->InternalFormat,
  1794.                                  srcImage->TexFormat);
  1795.       dstImage->DriverData = NULL;
  1796.       dstImage->FetchTexelc = srcImage->FetchTexelc;
  1797.       dstImage->FetchTexelf = srcImage->FetchTexelf;
  1798.  
  1799.       /* Alloc new teximage data buffer */
  1800.       {
  1801.          GLuint size = _mesa_format_image_size(dstImage->TexFormat,
  1802.                                                dstWidth, dstHeight, dstDepth);
  1803.          dstImage->Data = _mesa_alloc_texmemory(size);
  1804.          if (!dstImage->Data) {
  1805.             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
  1806.             return;
  1807.          }
  1808.       }
  1809.  
  1810.       /* Setup src and dest data pointers */
  1811.       if (_mesa_is_format_compressed(dstImage->TexFormat)) {
  1812.          /* srcData and dstData are already set */
  1813.          ASSERT(srcData);
  1814.          ASSERT(dstData);
  1815.       }
  1816.       else {
  1817.          srcData = (const GLubyte *) srcImage->Data;
  1818.          dstData = (GLubyte *) dstImage->Data;
  1819.       }
  1820.  
  1821.       ASSERT(dstImage->TexFormat);
  1822.       ASSERT(dstImage->FetchTexelc);
  1823.       ASSERT(dstImage->FetchTexelf);
  1824.  
  1825.       _mesa_generate_mipmap_level(target, datatype, comps, border,
  1826.                                   srcWidth, srcHeight, srcDepth,
  1827.                                   srcData, srcImage->RowStride,
  1828.                                   dstWidth, dstHeight, dstDepth,
  1829.                                   dstData, dstImage->RowStride);
  1830.  
  1831.  
  1832.       if (_mesa_is_format_compressed(dstImage->TexFormat)) {
  1833.          GLubyte *temp;
  1834.          /* compress image from dstData into dstImage->Data */
  1835.          const GLenum srcFormat = _mesa_get_format_base_format(convertFormat);
  1836.          GLint dstRowStride
  1837.             = _mesa_format_row_stride(dstImage->TexFormat, dstWidth);
  1838.          ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
  1839.  
  1840.          _mesa_texstore(ctx, 2, dstImage->_BaseFormat,
  1841.                         dstImage->TexFormat,
  1842.                         dstImage->Data,
  1843.                         0, 0, 0, /* dstX/Y/Zoffset */
  1844.                         dstRowStride, 0, /* strides */
  1845.                         dstWidth, dstHeight, 1, /* size */
  1846.                         srcFormat, CHAN_TYPE,
  1847.                         dstData, /* src data, actually */
  1848.                         &ctx->DefaultPacking);
  1849.  
  1850.          /* swap src and dest pointers */
  1851.          temp = (GLubyte *) srcData;
  1852.          srcData = dstData;
  1853.          dstData = temp;
  1854.       }
  1855.  
  1856.    } /* loop over mipmap levels */
  1857. }
  1858.  
  1859.  
  1860. /**
  1861.  * Helper function for drivers which need to rescale texture images to
  1862.  * certain aspect ratios.
  1863.  * Nearest filtering only (for broken hardware that can't support
  1864.  * all aspect ratios).  This can be made a lot faster, but I don't
  1865.  * really care enough...
  1866.  */
  1867. void
  1868. _mesa_rescale_teximage2d(GLuint bytesPerPixel,
  1869.                          GLuint srcStrideInPixels,
  1870.                          GLuint dstRowStride,
  1871.                          GLint srcWidth, GLint srcHeight,
  1872.                          GLint dstWidth, GLint dstHeight,
  1873.                          const GLvoid *srcImage, GLvoid *dstImage)
  1874. {
  1875.    GLint row, col;
  1876.  
  1877. #define INNER_LOOP( TYPE, HOP, WOP )                                    \
  1878.    for ( row = 0 ; row < dstHeight ; row++ ) {                          \
  1879.       GLint srcRow = row HOP hScale;                                    \
  1880.       for ( col = 0 ; col < dstWidth ; col++ ) {                        \
  1881.          GLint srcCol = col WOP wScale;                                 \
  1882.          dst[col] = src[srcRow * srcStrideInPixels + srcCol];           \
  1883.       }                                                                 \
  1884.       dst = (TYPE *) ((GLubyte *) dst + dstRowStride);                  \
  1885.    }                                                                    \
  1886.  
  1887. #define RESCALE_IMAGE( TYPE )                                           \
  1888. do {                                                                    \
  1889.    const TYPE *src = (const TYPE *)srcImage;                            \
  1890.    TYPE *dst = (TYPE *)dstImage;                                        \
  1891.                                                                         \
  1892.    if ( srcHeight < dstHeight ) {                                       \
  1893.       const GLint hScale = dstHeight / srcHeight;                       \
  1894.       if ( srcWidth < dstWidth ) {                                      \
  1895.          const GLint wScale = dstWidth / srcWidth;                      \
  1896.          INNER_LOOP( TYPE, /, / );                                      \
  1897.       }                                                                 \
  1898.       else {                                                            \
  1899.          const GLint wScale = srcWidth / dstWidth;                      \
  1900.          INNER_LOOP( TYPE, /, * );                                      \
  1901.       }                                                                 \
  1902.    }                                                                    \
  1903.    else {                                                               \
  1904.       const GLint hScale = srcHeight / dstHeight;                       \
  1905.       if ( srcWidth < dstWidth ) {                                      \
  1906.          const GLint wScale = dstWidth / srcWidth;                      \
  1907.          INNER_LOOP( TYPE, *, / );                                      \
  1908.       }                                                                 \
  1909.       else {                                                            \
  1910.          const GLint wScale = srcWidth / dstWidth;                      \
  1911.          INNER_LOOP( TYPE, *, * );                                      \
  1912.       }                                                                 \
  1913.    }                                                                    \
  1914. } while (0)
  1915.  
  1916.    switch ( bytesPerPixel ) {
  1917.    case 4:
  1918.       RESCALE_IMAGE( GLuint );
  1919.       break;
  1920.  
  1921.    case 2:
  1922.       RESCALE_IMAGE( GLushort );
  1923.       break;
  1924.  
  1925.    case 1:
  1926.       RESCALE_IMAGE( GLubyte );
  1927.       break;
  1928.    default:
  1929.       _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
  1930.    }
  1931. }
  1932.  
  1933.  
  1934. /**
  1935.  * Upscale an image by replication, not (typical) stretching.
  1936.  * We use this when the image width or height is less than a
  1937.  * certain size (4, 8) and we need to upscale an image.
  1938.  */
  1939. void
  1940. _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight,
  1941.                          GLsizei outWidth, GLsizei outHeight,
  1942.                          GLint comps, const GLchan *src, GLint srcRowStride,
  1943.                          GLchan *dest )
  1944. {
  1945.    GLint i, j, k;
  1946.  
  1947.    ASSERT(outWidth >= inWidth);
  1948.    ASSERT(outHeight >= inHeight);
  1949. #if 0
  1950.    ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
  1951.    ASSERT((outWidth & 3) == 0);
  1952.    ASSERT((outHeight & 3) == 0);
  1953. #endif
  1954.  
  1955.    for (i = 0; i < outHeight; i++) {
  1956.       const GLint ii = i % inHeight;
  1957.       for (j = 0; j < outWidth; j++) {
  1958.          const GLint jj = j % inWidth;
  1959.          for (k = 0; k < comps; k++) {
  1960.             dest[(i * outWidth + j) * comps + k]
  1961.                = src[ii * srcRowStride + jj * comps + k];
  1962.          }
  1963.       }
  1964.    }
  1965. }
  1966.  
  1967.