ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

mipmap.c
Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00030 #include "imports.h"
00031 #include "mipmap.h"
00032 #include "texcompress.h"
00033 #include "texformat.h"
00034 #include "teximage.h"
00035 #include "image.h"
00036 
00037 
00038 
00039 static GLint
00040 bytes_per_pixel(GLenum datatype, GLuint comps)
00041 {
00042    GLint b = _mesa_sizeof_packed_type(datatype);
00043    assert(b >= 0);
00044 
00045    if (_mesa_type_is_packed(datatype))
00046        return b;
00047    else
00048        return b * comps;
00049 }
00050 
00051 
00060 #define DECLARE_ROW_POINTERS(t, e) \
00061       const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
00062       const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
00063       const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
00064       const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
00065       t(*dst)[e] = (t(*)[e]) dstRow
00066 
00067 #define DECLARE_ROW_POINTERS0(t) \
00068       const t *rowA = (const t *) srcRowA; \
00069       const t *rowB = (const t *) srcRowB; \
00070       const t *rowC = (const t *) srcRowC; \
00071       const t *rowD = (const t *) srcRowD; \
00072       t *dst = (t *) dstRow
00073 
00074 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
00075    ((unsigned) Aj + (unsigned) Ak \
00076     + (unsigned) Bj + (unsigned) Bk \
00077     + (unsigned) Cj + (unsigned) Ck \
00078     + (unsigned) Dj + (unsigned) Dk \
00079     + 4) >> 3
00080 
00081 #define FILTER_3D(e) \
00082    do { \
00083       dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
00084                                 rowB[j][e], rowB[k][e], \
00085                                 rowC[j][e], rowC[k][e], \
00086                                 rowD[j][e], rowD[k][e]); \
00087    } while(0)
00088    
00089 #define FILTER_F_3D(e) \
00090    do { \
00091       dst[i][e] = (rowA[j][e] + rowA[k][e] \
00092                    + rowB[j][e] + rowB[k][e] \
00093                    + rowC[j][e] + rowC[k][e] \
00094                    + rowD[j][e] + rowD[k][e]) * 0.125F; \
00095    } while(0)
00096 
00097 #define FILTER_HF_3D(e) \
00098    do { \
00099       const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
00100       const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
00101       const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
00102       const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
00103       const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
00104       const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
00105       const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
00106       const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
00107       dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
00108                                       * 0.125F); \
00109    } while(0)
00110 
00121 static void
00122 do_row(GLenum datatype, GLuint comps, GLint srcWidth,
00123        const GLvoid *srcRowA, const GLvoid *srcRowB,
00124        GLint dstWidth, GLvoid *dstRow)
00125 {
00126    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
00127    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
00128 
00129    ASSERT(comps >= 1);
00130    ASSERT(comps <= 4);
00131 
00132    /* This assertion is no longer valid with non-power-of-2 textures
00133    assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
00134    */
00135 
00136    if (datatype == GL_UNSIGNED_BYTE && comps == 4) {
00137       GLuint i, j, k;
00138       const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA;
00139       const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB;
00140       GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow;
00141       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00142            i++, j += colStride, k += colStride) {
00143          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00144          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00145          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00146          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
00147       }
00148    }
00149    else if (datatype == GL_UNSIGNED_BYTE && comps == 3) {
00150       GLuint i, j, k;
00151       const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA;
00152       const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB;
00153       GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow;
00154       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00155            i++, j += colStride, k += colStride) {
00156          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00157          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00158          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00159       }
00160    }
00161    else if (datatype == GL_UNSIGNED_BYTE && comps == 2) {
00162       GLuint i, j, k;
00163       const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA;
00164       const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB;
00165       GLubyte(*dst)[2] = (GLubyte(*)[2]) dstRow;
00166       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00167            i++, j += colStride, k += colStride) {
00168          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
00169          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
00170       }
00171    }
00172    else if (datatype == GL_UNSIGNED_BYTE && comps == 1) {
00173       GLuint i, j, k;
00174       const GLubyte *rowA = (const GLubyte *) srcRowA;
00175       const GLubyte *rowB = (const GLubyte *) srcRowB;
00176       GLubyte *dst = (GLubyte *) dstRow;
00177       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00178            i++, j += colStride, k += colStride) {
00179          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
00180       }
00181    }
00182 
00183    else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
00184       GLuint i, j, k;
00185       const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
00186       const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB;
00187       GLushort(*dst)[4] = (GLushort(*)[4]) dstRow;
00188       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00189            i++, j += colStride, k += colStride) {
00190          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00191          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00192          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00193          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
00194       }
00195    }
00196    else if (datatype == GL_UNSIGNED_SHORT && comps == 3) {
00197       GLuint i, j, k;
00198       const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA;
00199       const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB;
00200       GLushort(*dst)[3] = (GLushort(*)[3]) dstRow;
00201       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00202            i++, j += colStride, k += colStride) {
00203          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00204          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00205          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
00206       }
00207    }
00208    else if (datatype == GL_UNSIGNED_SHORT && comps == 2) {
00209       GLuint i, j, k;
00210       const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA;
00211       const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB;
00212       GLushort(*dst)[2] = (GLushort(*)[2]) dstRow;
00213       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00214            i++, j += colStride, k += colStride) {
00215          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
00216          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
00217       }
00218    }
00219    else if (datatype == GL_UNSIGNED_SHORT && comps == 1) {
00220       GLuint i, j, k;
00221       const GLushort *rowA = (const GLushort *) srcRowA;
00222       const GLushort *rowB = (const GLushort *) srcRowB;
00223       GLushort *dst = (GLushort *) dstRow;
00224       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00225            i++, j += colStride, k += colStride) {
00226          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
00227       }
00228    }
00229 
00230    else if (datatype == GL_FLOAT && comps == 4) {
00231       GLuint i, j, k;
00232       const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
00233       const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB;
00234       GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow;
00235       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00236            i++, j += colStride, k += colStride) {
00237          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00238                       rowB[j][0] + rowB[k][0]) * 0.25F;
00239          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00240                       rowB[j][1] + rowB[k][1]) * 0.25F;
00241          dst[i][2] = (rowA[j][2] + rowA[k][2] +
00242                       rowB[j][2] + rowB[k][2]) * 0.25F;
00243          dst[i][3] = (rowA[j][3] + rowA[k][3] +
00244                       rowB[j][3] + rowB[k][3]) * 0.25F;
00245       }
00246    }
00247    else if (datatype == GL_FLOAT && comps == 3) {
00248       GLuint i, j, k;
00249       const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA;
00250       const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB;
00251       GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow;
00252       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00253            i++, j += colStride, k += colStride) {
00254          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00255                       rowB[j][0] + rowB[k][0]) * 0.25F;
00256          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00257                       rowB[j][1] + rowB[k][1]) * 0.25F;
00258          dst[i][2] = (rowA[j][2] + rowA[k][2] +
00259                       rowB[j][2] + rowB[k][2]) * 0.25F;
00260       }
00261    }
00262    else if (datatype == GL_FLOAT && comps == 2) {
00263       GLuint i, j, k;
00264       const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA;
00265       const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB;
00266       GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow;
00267       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00268            i++, j += colStride, k += colStride) {
00269          dst[i][0] = (rowA[j][0] + rowA[k][0] +
00270                       rowB[j][0] + rowB[k][0]) * 0.25F;
00271          dst[i][1] = (rowA[j][1] + rowA[k][1] +
00272                       rowB[j][1] + rowB[k][1]) * 0.25F;
00273       }
00274    }
00275    else if (datatype == GL_FLOAT && comps == 1) {
00276       GLuint i, j, k;
00277       const GLfloat *rowA = (const GLfloat *) srcRowA;
00278       const GLfloat *rowB = (const GLfloat *) srcRowB;
00279       GLfloat *dst = (GLfloat *) dstRow;
00280       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00281            i++, j += colStride, k += colStride) {
00282          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
00283       }
00284    }
00285 
00286    else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) {
00287       GLuint i, j, k, comp;
00288       const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA;
00289       const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB;
00290       GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow;
00291       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00292            i++, j += colStride, k += colStride) {
00293          for (comp = 0; comp < 4; comp++) {
00294             GLfloat aj, ak, bj, bk;
00295             aj = _mesa_half_to_float(rowA[j][comp]);
00296             ak = _mesa_half_to_float(rowA[k][comp]);
00297             bj = _mesa_half_to_float(rowB[j][comp]);
00298             bk = _mesa_half_to_float(rowB[k][comp]);
00299             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
00300          }
00301       }
00302    }
00303    else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) {
00304       GLuint i, j, k, comp;
00305       const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA;
00306       const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB;
00307       GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow;
00308       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00309            i++, j += colStride, k += colStride) {
00310          for (comp = 0; comp < 3; comp++) {
00311             GLfloat aj, ak, bj, bk;
00312             aj = _mesa_half_to_float(rowA[j][comp]);
00313             ak = _mesa_half_to_float(rowA[k][comp]);
00314             bj = _mesa_half_to_float(rowB[j][comp]);
00315             bk = _mesa_half_to_float(rowB[k][comp]);
00316             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
00317          }
00318       }
00319    }
00320    else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) {
00321       GLuint i, j, k, comp;
00322       const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA;
00323       const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB;
00324       GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow;
00325       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00326            i++, j += colStride, k += colStride) {
00327          for (comp = 0; comp < 2; comp++) {
00328             GLfloat aj, ak, bj, bk;
00329             aj = _mesa_half_to_float(rowA[j][comp]);
00330             ak = _mesa_half_to_float(rowA[k][comp]);
00331             bj = _mesa_half_to_float(rowB[j][comp]);
00332             bk = _mesa_half_to_float(rowB[k][comp]);
00333             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
00334          }
00335       }
00336    }
00337    else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) {
00338       GLuint i, j, k;
00339       const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
00340       const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
00341       GLhalfARB *dst = (GLhalfARB *) dstRow;
00342       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00343            i++, j += colStride, k += colStride) {
00344          GLfloat aj, ak, bj, bk;
00345          aj = _mesa_half_to_float(rowA[j]);
00346          ak = _mesa_half_to_float(rowA[k]);
00347          bj = _mesa_half_to_float(rowB[j]);
00348          bk = _mesa_half_to_float(rowB[k]);
00349          dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
00350       }
00351    }
00352 
00353    else if (datatype == GL_UNSIGNED_INT && comps == 1) {
00354       GLuint i, j, k;
00355       const GLuint *rowA = (const GLuint *) srcRowA;
00356       const GLuint *rowB = (const GLuint *) srcRowB;
00357       GLfloat *dst = (GLfloat *) dstRow;
00358       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00359            i++, j += colStride, k += colStride) {
00360          dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4);
00361       }
00362    }
00363 
00364    else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) {
00365       GLuint i, j, k;
00366       const GLushort *rowA = (const GLushort *) srcRowA;
00367       const GLushort *rowB = (const GLushort *) srcRowB;
00368       GLushort *dst = (GLushort *) dstRow;
00369       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00370            i++, j += colStride, k += colStride) {
00371          const GLint rowAr0 = rowA[j] & 0x1f;
00372          const GLint rowAr1 = rowA[k] & 0x1f;
00373          const GLint rowBr0 = rowB[j] & 0x1f;
00374          const GLint rowBr1 = rowB[k] & 0x1f;
00375          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
00376          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
00377          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
00378          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
00379          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
00380          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
00381          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
00382          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
00383          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00384          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00385          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00386          dst[i] = (blue << 11) | (green << 5) | red;
00387       }
00388    }
00389    else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) {
00390       GLuint i, j, k;
00391       const GLushort *rowA = (const GLushort *) srcRowA;
00392       const GLushort *rowB = (const GLushort *) srcRowB;
00393       GLushort *dst = (GLushort *) dstRow;
00394       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00395            i++, j += colStride, k += colStride) {
00396          const GLint rowAr0 = rowA[j] & 0xf;
00397          const GLint rowAr1 = rowA[k] & 0xf;
00398          const GLint rowBr0 = rowB[j] & 0xf;
00399          const GLint rowBr1 = rowB[k] & 0xf;
00400          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
00401          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
00402          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
00403          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
00404          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
00405          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
00406          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
00407          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
00408          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
00409          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
00410          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
00411          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
00412          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00413          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00414          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00415          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
00416          dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
00417       }
00418    }
00419    else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) {
00420       GLuint i, j, k;
00421       const GLushort *rowA = (const GLushort *) srcRowA;
00422       const GLushort *rowB = (const GLushort *) srcRowB;
00423       GLushort *dst = (GLushort *) dstRow;
00424       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00425            i++, j += colStride, k += colStride) {
00426          const GLint rowAr0 = rowA[j] & 0x1f;
00427          const GLint rowAr1 = rowA[k] & 0x1f;
00428          const GLint rowBr0 = rowB[j] & 0x1f;
00429          const GLint rowBr1 = rowB[k] & 0x1f;
00430          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
00431          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
00432          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
00433          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
00434          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
00435          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
00436          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
00437          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
00438          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
00439          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
00440          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
00441          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
00442          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00443          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00444          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00445          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
00446          dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
00447       }
00448    }
00449    else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) {
00450       GLuint i, j, k;
00451       const GLubyte *rowA = (const GLubyte *) srcRowA;
00452       const GLubyte *rowB = (const GLubyte *) srcRowB;
00453       GLubyte *dst = (GLubyte *) dstRow;
00454       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00455            i++, j += colStride, k += colStride) {
00456          const GLint rowAr0 = rowA[j] & 0x3;
00457          const GLint rowAr1 = rowA[k] & 0x3;
00458          const GLint rowBr0 = rowB[j] & 0x3;
00459          const GLint rowBr1 = rowB[k] & 0x3;
00460          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
00461          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
00462          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
00463          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
00464          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
00465          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
00466          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
00467          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
00468          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
00469          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
00470          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
00471          dst[i] = (blue << 5) | (green << 2) | red;
00472       }
00473    }
00474    else {
00475       _mesa_problem(NULL, "bad format in do_row()");
00476    }
00477 }
00478 
00479 
00497 static void
00498 do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
00499           const GLvoid *srcRowA, const GLvoid *srcRowB,
00500           const GLvoid *srcRowC, const GLvoid *srcRowD,
00501           GLint dstWidth, GLvoid *dstRow)
00502 {
00503    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
00504    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
00505    GLuint i, j, k;
00506 
00507    ASSERT(comps >= 1);
00508    ASSERT(comps <= 4);
00509 
00510    if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) {
00511       DECLARE_ROW_POINTERS(GLubyte, 4);
00512 
00513       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00514            i++, j += colStride, k += colStride) {
00515          FILTER_3D(0);
00516          FILTER_3D(1);
00517          FILTER_3D(2);
00518          FILTER_3D(3);
00519       }
00520    }
00521    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) {
00522       DECLARE_ROW_POINTERS(GLubyte, 3);
00523 
00524       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00525            i++, j += colStride, k += colStride) {
00526          FILTER_3D(0);
00527          FILTER_3D(1);
00528          FILTER_3D(2);
00529       }
00530    }
00531    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) {
00532       DECLARE_ROW_POINTERS(GLubyte, 2);
00533 
00534       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00535            i++, j += colStride, k += colStride) {
00536          FILTER_3D(0);
00537          FILTER_3D(1);
00538       }
00539    }
00540    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) {
00541       DECLARE_ROW_POINTERS(GLubyte, 1);
00542 
00543       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00544            i++, j += colStride, k += colStride) {
00545          FILTER_3D(0);
00546       }
00547    }
00548    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
00549       DECLARE_ROW_POINTERS(GLushort, 4);
00550 
00551       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00552            i++, j += colStride, k += colStride) {
00553          FILTER_3D(0);
00554          FILTER_3D(1);
00555          FILTER_3D(2);
00556          FILTER_3D(3);
00557       }
00558    }
00559    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) {
00560       DECLARE_ROW_POINTERS(GLushort, 3);
00561 
00562       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00563            i++, j += colStride, k += colStride) {
00564          FILTER_3D(0);
00565          FILTER_3D(1);
00566          FILTER_3D(2);
00567       }
00568    }
00569    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) {
00570       DECLARE_ROW_POINTERS(GLushort, 2);
00571 
00572       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00573            i++, j += colStride, k += colStride) {
00574          FILTER_3D(0);
00575          FILTER_3D(1);
00576       }
00577    }
00578    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) {
00579       DECLARE_ROW_POINTERS(GLushort, 1);
00580 
00581       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00582            i++, j += colStride, k += colStride) {
00583          FILTER_3D(0);
00584       }
00585    }
00586    else if ((datatype == GL_FLOAT) && (comps == 4)) {
00587       DECLARE_ROW_POINTERS(GLfloat, 4);
00588 
00589       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00590            i++, j += colStride, k += colStride) {
00591          FILTER_F_3D(0);
00592          FILTER_F_3D(1);
00593          FILTER_F_3D(2);
00594          FILTER_F_3D(3);
00595       }
00596    }
00597    else if ((datatype == GL_FLOAT) && (comps == 3)) {
00598       DECLARE_ROW_POINTERS(GLfloat, 3);
00599 
00600       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00601            i++, j += colStride, k += colStride) {
00602          FILTER_F_3D(0);
00603          FILTER_F_3D(1);
00604          FILTER_F_3D(2);
00605       }
00606    }
00607    else if ((datatype == GL_FLOAT) && (comps == 2)) {
00608       DECLARE_ROW_POINTERS(GLfloat, 2);
00609 
00610       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00611            i++, j += colStride, k += colStride) {
00612          FILTER_F_3D(0);
00613          FILTER_F_3D(1);
00614       }
00615    }
00616    else if ((datatype == GL_FLOAT) && (comps == 1)) {
00617       DECLARE_ROW_POINTERS(GLfloat, 1);
00618 
00619       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00620            i++, j += colStride, k += colStride) {
00621          FILTER_F_3D(0);
00622       }
00623    }
00624    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) {
00625       DECLARE_ROW_POINTERS(GLhalfARB, 4);
00626 
00627       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00628            i++, j += colStride, k += colStride) {
00629          FILTER_HF_3D(0);
00630          FILTER_HF_3D(1);
00631          FILTER_HF_3D(2);
00632          FILTER_HF_3D(3);
00633       }
00634    }
00635    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
00636       DECLARE_ROW_POINTERS(GLhalfARB, 4);
00637 
00638       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00639            i++, j += colStride, k += colStride) {
00640          FILTER_HF_3D(0);
00641          FILTER_HF_3D(1);
00642          FILTER_HF_3D(2);
00643       }
00644    }
00645    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
00646       DECLARE_ROW_POINTERS(GLhalfARB, 4);
00647 
00648       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00649            i++, j += colStride, k += colStride) {
00650          FILTER_HF_3D(0);
00651          FILTER_HF_3D(1);
00652       }
00653    }
00654    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
00655       DECLARE_ROW_POINTERS(GLhalfARB, 4);
00656 
00657       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00658            i++, j += colStride, k += colStride) {
00659          FILTER_HF_3D(0);
00660       }
00661    }
00662    else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) {
00663       const GLuint *rowA = (const GLuint *) srcRowA;
00664       const GLuint *rowB = (const GLuint *) srcRowB;
00665       const GLuint *rowC = (const GLuint *) srcRowC;
00666       const GLuint *rowD = (const GLuint *) srcRowD;
00667       GLfloat *dst = (GLfloat *) dstRow;
00668 
00669       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00670            i++, j += colStride, k += colStride) {
00671          const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
00672                                + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
00673                                + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
00674                                + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
00675          dst[i] = (GLfloat)((double) tmp * 0.125);
00676       }
00677    }
00678    else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) {
00679       DECLARE_ROW_POINTERS0(GLushort);
00680 
00681       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00682            i++, j += colStride, k += colStride) {
00683          const GLint rowAr0 = rowA[j] & 0x1f;
00684          const GLint rowAr1 = rowA[k] & 0x1f;
00685          const GLint rowBr0 = rowB[j] & 0x1f;
00686          const GLint rowBr1 = rowB[k] & 0x1f;
00687          const GLint rowCr0 = rowC[j] & 0x1f;
00688          const GLint rowCr1 = rowC[k] & 0x1f;
00689          const GLint rowDr0 = rowD[j] & 0x1f;
00690          const GLint rowDr1 = rowD[k] & 0x1f;
00691          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
00692          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
00693          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
00694          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
00695          const GLint rowCg0 = (rowC[j] >> 5) & 0x3f;
00696          const GLint rowCg1 = (rowC[k] >> 5) & 0x3f;
00697          const GLint rowDg0 = (rowD[j] >> 5) & 0x3f;
00698          const GLint rowDg1 = (rowD[k] >> 5) & 0x3f;
00699          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
00700          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
00701          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
00702          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
00703          const GLint rowCb0 = (rowC[j] >> 11) & 0x1f;
00704          const GLint rowCb1 = (rowC[k] >> 11) & 0x1f;
00705          const GLint rowDb0 = (rowD[j] >> 11) & 0x1f;
00706          const GLint rowDb1 = (rowD[k] >> 11) & 0x1f;
00707          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
00708                                        rowCr0, rowCr1, rowDr0, rowDr1);
00709          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
00710                                        rowCg0, rowCg1, rowDg0, rowDg1);
00711          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
00712                                        rowCb0, rowCb1, rowDb0, rowDb1);
00713          dst[i] = (b << 11) | (g << 5) | r;
00714       }
00715    }
00716    else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) {
00717       DECLARE_ROW_POINTERS0(GLushort);
00718 
00719       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00720            i++, j += colStride, k += colStride) {
00721          const GLint rowAr0 = rowA[j] & 0xf;
00722          const GLint rowAr1 = rowA[k] & 0xf;
00723          const GLint rowBr0 = rowB[j] & 0xf;
00724          const GLint rowBr1 = rowB[k] & 0xf;
00725          const GLint rowCr0 = rowC[j] & 0xf;
00726          const GLint rowCr1 = rowC[k] & 0xf;
00727          const GLint rowDr0 = rowD[j] & 0xf;
00728          const GLint rowDr1 = rowD[k] & 0xf;
00729          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
00730          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
00731          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
00732          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
00733          const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
00734          const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
00735          const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
00736          const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
00737          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
00738          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
00739          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
00740          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
00741          const GLint rowCb0 = (rowC[j] >> 8) & 0xf;
00742          const GLint rowCb1 = (rowC[k] >> 8) & 0xf;
00743          const GLint rowDb0 = (rowD[j] >> 8) & 0xf;
00744          const GLint rowDb1 = (rowD[k] >> 8) & 0xf;
00745          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
00746          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
00747          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
00748          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
00749          const GLint rowCa0 = (rowC[j] >> 12) & 0xf;
00750          const GLint rowCa1 = (rowC[k] >> 12) & 0xf;
00751          const GLint rowDa0 = (rowD[j] >> 12) & 0xf;
00752          const GLint rowDa1 = (rowD[k] >> 12) & 0xf;
00753          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
00754                                        rowCr0, rowCr1, rowDr0, rowDr1);
00755          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
00756                                        rowCg0, rowCg1, rowDg0, rowDg1);
00757          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
00758                                        rowCb0, rowCb1, rowDb0, rowDb1);
00759          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
00760                                        rowCa0, rowCa1, rowDa0, rowDa1);
00761 
00762          dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
00763       }
00764    }
00765    else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) {
00766       DECLARE_ROW_POINTERS0(GLushort);
00767 
00768       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00769            i++, j += colStride, k += colStride) {
00770          const GLint rowAr0 = rowA[j] & 0x1f;
00771          const GLint rowAr1 = rowA[k] & 0x1f;
00772          const GLint rowBr0 = rowB[j] & 0x1f;
00773          const GLint rowBr1 = rowB[k] & 0x1f;
00774          const GLint rowCr0 = rowC[j] & 0x1f;
00775          const GLint rowCr1 = rowC[k] & 0x1f;
00776          const GLint rowDr0 = rowD[j] & 0x1f;
00777          const GLint rowDr1 = rowD[k] & 0x1f;
00778          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
00779          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
00780          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
00781          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
00782          const GLint rowCg0 = (rowC[j] >> 5) & 0x1f;
00783          const GLint rowCg1 = (rowC[k] >> 5) & 0x1f;
00784          const GLint rowDg0 = (rowD[j] >> 5) & 0x1f;
00785          const GLint rowDg1 = (rowD[k] >> 5) & 0x1f;
00786          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
00787          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
00788          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
00789          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
00790          const GLint rowCb0 = (rowC[j] >> 10) & 0x1f;
00791          const GLint rowCb1 = (rowC[k] >> 10) & 0x1f;
00792          const GLint rowDb0 = (rowD[j] >> 10) & 0x1f;
00793          const GLint rowDb1 = (rowD[k] >> 10) & 0x1f;
00794          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
00795          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
00796          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
00797          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
00798          const GLint rowCa0 = (rowC[j] >> 15) & 0x1;
00799          const GLint rowCa1 = (rowC[k] >> 15) & 0x1;
00800          const GLint rowDa0 = (rowD[j] >> 15) & 0x1;
00801          const GLint rowDa1 = (rowD[k] >> 15) & 0x1;
00802          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
00803                                        rowCr0, rowCr1, rowDr0, rowDr1);
00804          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
00805                                        rowCg0, rowCg1, rowDg0, rowDg1);
00806          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
00807                                        rowCb0, rowCb1, rowDb0, rowDb1);
00808          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
00809                                        rowCa0, rowCa1, rowDa0, rowDa1);
00810 
00811          dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
00812       }
00813    }
00814    else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
00815       DECLARE_ROW_POINTERS0(GLushort);
00816 
00817       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
00818            i++, j += colStride, k += colStride) {
00819          const GLint rowAr0 = rowA[j] & 0x3;
00820          const GLint rowAr1 = rowA[k] & 0x3;
00821          const GLint rowBr0 = rowB[j] & 0x3;
00822          const GLint rowBr1 = rowB[k] & 0x3;
00823          const GLint rowCr0 = rowC[j] & 0x3;
00824          const GLint rowCr1 = rowC[k] & 0x3;
00825          const GLint rowDr0 = rowD[j] & 0x3;
00826          const GLint rowDr1 = rowD[k] & 0x3;
00827          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
00828          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
00829          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
00830          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
00831          const GLint rowCg0 = (rowC[j] >> 2) & 0x7;
00832          const GLint rowCg1 = (rowC[k] >> 2) & 0x7;
00833          const GLint rowDg0 = (rowD[j] >> 2) & 0x7;
00834          const GLint rowDg1 = (rowD[k] >> 2) & 0x7;
00835          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
00836          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
00837          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
00838          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
00839          const GLint rowCb0 = (rowC[j] >> 5) & 0x7;
00840          const GLint rowCb1 = (rowC[k] >> 5) & 0x7;
00841          const GLint rowDb0 = (rowD[j] >> 5) & 0x7;
00842          const GLint rowDb1 = (rowD[k] >> 5) & 0x7;
00843          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
00844                                        rowCr0, rowCr1, rowDr0, rowDr1);
00845          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
00846                                        rowCg0, rowCg1, rowDg0, rowDg1);
00847          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
00848                                        rowCb0, rowCb1, rowDb0, rowDb1);
00849          dst[i] = (b << 5) | (g << 2) | r;
00850       }
00851    }
00852    else {
00853       _mesa_problem(NULL, "bad format in do_row()");
00854    }
00855 }
00856 
00857 
00858 /*
00859  * These functions generate a 1/2-size mipmap image from a source image.
00860  * Texture borders are handled by copying or averaging the source image's
00861  * border texels, depending on the scale-down factor.
00862  */
00863 
00864 static void
00865 make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
00866                GLint srcWidth, const GLubyte *srcPtr,
00867                GLint dstWidth, GLubyte *dstPtr)
00868 {
00869    const GLint bpt = bytes_per_pixel(datatype, comps);
00870    const GLubyte *src;
00871    GLubyte *dst;
00872 
00873    /* skip the border pixel, if any */
00874    src = srcPtr + border * bpt;
00875    dst = dstPtr + border * bpt;
00876 
00877    /* we just duplicate the input row, kind of hack, saves code */
00878    do_row(datatype, comps, srcWidth - 2 * border, src, src,
00879           dstWidth - 2 * border, dst);
00880 
00881    if (border) {
00882       /* copy left-most pixel from source */
00883       MEMCPY(dstPtr, srcPtr, bpt);
00884       /* copy right-most pixel from source */
00885       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
00886              srcPtr + (srcWidth - 1) * bpt,
00887              bpt);
00888    }
00889 }
00890 
00891 
00892 static void
00893 make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
00894                GLint srcWidth, GLint srcHeight,
00895            const GLubyte *srcPtr, GLint srcRowStride,
00896                GLint dstWidth, GLint dstHeight,
00897            GLubyte *dstPtr, GLint dstRowStride)
00898 {
00899    const GLint bpt = bytes_per_pixel(datatype, comps);
00900    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
00901    const GLint dstWidthNB = dstWidth - 2 * border;
00902    const GLint dstHeightNB = dstHeight - 2 * border;
00903    const GLint srcRowBytes = bpt * srcRowStride;
00904    const GLint dstRowBytes = bpt * dstRowStride;
00905    const GLubyte *srcA, *srcB;
00906    GLubyte *dst;
00907    GLint row;
00908 
00909    /* Compute src and dst pointers, skipping any border */
00910    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
00911    if (srcHeight > 1) 
00912       srcB = srcA + srcRowBytes;
00913    else
00914       srcB = srcA;
00915    dst = dstPtr + border * ((dstWidth + 1) * bpt);
00916 
00917    for (row = 0; row < dstHeightNB; row++) {
00918       do_row(datatype, comps, srcWidthNB, srcA, srcB,
00919              dstWidthNB, dst);
00920       srcA += 2 * srcRowBytes;
00921       srcB += 2 * srcRowBytes;
00922       dst += dstRowBytes;
00923    }
00924 
00925    /* This is ugly but probably won't be used much */
00926    if (border > 0) {
00927       /* fill in dest border */
00928       /* lower-left border pixel */
00929       MEMCPY(dstPtr, srcPtr, bpt);
00930       /* lower-right border pixel */
00931       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
00932              srcPtr + (srcWidth - 1) * bpt, bpt);
00933       /* upper-left border pixel */
00934       MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
00935              srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
00936       /* upper-right border pixel */
00937       MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
00938              srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
00939       /* lower border */
00940       do_row(datatype, comps, srcWidthNB,
00941              srcPtr + bpt,
00942              srcPtr + bpt,
00943              dstWidthNB, dstPtr + bpt);
00944       /* upper border */
00945       do_row(datatype, comps, srcWidthNB,
00946              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
00947              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
00948              dstWidthNB,
00949              dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
00950       /* left and right borders */
00951       if (srcHeight == dstHeight) {
00952          /* copy border pixel from src to dst */
00953          for (row = 1; row < srcHeight; row++) {
00954             MEMCPY(dstPtr + dstWidth * row * bpt,
00955                    srcPtr + srcWidth * row * bpt, bpt);
00956             MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
00957                    srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
00958          }
00959       }
00960       else {
00961          /* average two src pixels each dest pixel */
00962          for (row = 0; row < dstHeightNB; row += 2) {
00963             do_row(datatype, comps, 1,
00964                    srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
00965                    srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
00966                    1, dstPtr + (dstWidth * row + 1) * bpt);
00967             do_row(datatype, comps, 1,
00968                    srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
00969                    srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
00970                    1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
00971          }
00972       }
00973    }
00974 }
00975 
00976 
00977 static void
00978 make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
00979                GLint srcWidth, GLint srcHeight, GLint srcDepth,
00980                const GLubyte *srcPtr, GLint srcRowStride,
00981                GLint dstWidth, GLint dstHeight, GLint dstDepth,
00982                GLubyte *dstPtr, GLint dstRowStride)
00983 {
00984    const GLint bpt = bytes_per_pixel(datatype, comps);
00985    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
00986    const GLint srcDepthNB = srcDepth - 2 * border;
00987    const GLint dstWidthNB = dstWidth - 2 * border;
00988    const GLint dstHeightNB = dstHeight - 2 * border;
00989    const GLint dstDepthNB = dstDepth - 2 * border;
00990    GLint img, row;
00991    GLint bytesPerSrcImage, bytesPerDstImage;
00992    GLint bytesPerSrcRow, bytesPerDstRow;
00993    GLint srcImageOffset, srcRowOffset;
00994 
00995    (void) srcDepthNB; /* silence warnings */
00996 
00997 
00998    bytesPerSrcImage = srcWidth * srcHeight * bpt;
00999    bytesPerDstImage = dstWidth * dstHeight * bpt;
01000 
01001    bytesPerSrcRow = srcWidth * bpt;
01002    bytesPerDstRow = dstWidth * bpt;
01003 
01004    /* Offset between adjacent src images to be averaged together */
01005    srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
01006 
01007    /* Offset between adjacent src rows to be averaged together */
01008    srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
01009 
01010    /*
01011     * Need to average together up to 8 src pixels for each dest pixel.
01012     * Break that down into 3 operations:
01013     *   1. take two rows from source image and average them together.
01014     *   2. take two rows from next source image and average them together.
01015     *   3. take the two averaged rows and average them for the final dst row.
01016     */
01017 
01018    /*
01019    _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
01020           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
01021    */
01022 
01023    for (img = 0; img < dstDepthNB; img++) {
01024       /* first source image pointer, skipping border */
01025       const GLubyte *imgSrcA = srcPtr
01026          + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
01027          + img * (bytesPerSrcImage + srcImageOffset);
01028       /* second source image pointer, skipping border */
01029       const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
01030       /* address of the dest image, skipping border */
01031       GLubyte *imgDst = dstPtr
01032          + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
01033          + img * bytesPerDstImage;
01034 
01035       /* setup the four source row pointers and the dest row pointer */
01036       const GLubyte *srcImgARowA = imgSrcA;
01037       const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
01038       const GLubyte *srcImgBRowA = imgSrcB;
01039       const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
01040       GLubyte *dstImgRow = imgDst;
01041 
01042       for (row = 0; row < dstHeightNB; row++) {
01043          do_row_3D(datatype, comps, srcWidthNB, 
01044                    srcImgARowA, srcImgARowB,
01045                    srcImgBRowA, srcImgBRowB,
01046                    dstWidthNB, dstImgRow);
01047 
01048          /* advance to next rows */
01049          srcImgARowA += bytesPerSrcRow + srcRowOffset;
01050          srcImgARowB += bytesPerSrcRow + srcRowOffset;
01051          srcImgBRowA += bytesPerSrcRow + srcRowOffset;
01052          srcImgBRowB += bytesPerSrcRow + srcRowOffset;
01053          dstImgRow += bytesPerDstRow;
01054       }
01055    }
01056 
01057 
01058    /* Luckily we can leverage the make_2d_mipmap() function here! */
01059    if (border > 0) {
01060       /* do front border image */
01061       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
01062                      dstWidth, dstHeight, dstPtr, dstRowStride);
01063       /* do back border image */
01064       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
01065                      srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
01066                      dstWidth, dstHeight,
01067                      dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
01068       /* do four remaining border edges that span the image slices */
01069       if (srcDepth == dstDepth) {
01070          /* just copy border pixels from src to dst */
01071          for (img = 0; img < dstDepthNB; img++) {
01072             const GLubyte *src;
01073             GLubyte *dst;
01074 
01075             /* do border along [img][row=0][col=0] */
01076             src = srcPtr + (img + 1) * bytesPerSrcImage;
01077             dst = dstPtr + (img + 1) * bytesPerDstImage;
01078             MEMCPY(dst, src, bpt);
01079 
01080             /* do border along [img][row=dstHeight-1][col=0] */
01081             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01082                          + (srcHeight - 1) * bytesPerSrcRow;
01083             dst = dstPtr + (img + 1) * bytesPerDstImage
01084                          + (dstHeight - 1) * bytesPerDstRow;
01085             MEMCPY(dst, src, bpt);
01086 
01087             /* do border along [img][row=0][col=dstWidth-1] */
01088             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01089                          + (srcWidth - 1) * bpt;
01090             dst = dstPtr + (img + 1) * bytesPerDstImage
01091                          + (dstWidth - 1) * bpt;
01092             MEMCPY(dst, src, bpt);
01093 
01094             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
01095             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01096                          + (bytesPerSrcImage - bpt);
01097             dst = dstPtr + (img + 1) * bytesPerDstImage
01098                          + (bytesPerDstImage - bpt);
01099             MEMCPY(dst, src, bpt);
01100          }
01101       }
01102       else {
01103          /* average border pixels from adjacent src image pairs */
01104          ASSERT(srcDepthNB == 2 * dstDepthNB);
01105          for (img = 0; img < dstDepthNB; img++) {
01106             const GLubyte *src;
01107             GLubyte *dst;
01108 
01109             /* do border along [img][row=0][col=0] */
01110             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
01111             dst = dstPtr + (img + 1) * bytesPerDstImage;
01112             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
01113 
01114             /* do border along [img][row=dstHeight-1][col=0] */
01115             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01116                          + (srcHeight - 1) * bytesPerSrcRow;
01117             dst = dstPtr + (img + 1) * bytesPerDstImage
01118                          + (dstHeight - 1) * bytesPerDstRow;
01119             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
01120 
01121             /* do border along [img][row=0][col=dstWidth-1] */
01122             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01123                          + (srcWidth - 1) * bpt;
01124             dst = dstPtr + (img + 1) * bytesPerDstImage
01125                          + (dstWidth - 1) * bpt;
01126             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
01127 
01128             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
01129             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
01130                          + (bytesPerSrcImage - bpt);
01131             dst = dstPtr + (img + 1) * bytesPerDstImage
01132                          + (bytesPerDstImage - bpt);
01133             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
01134          }
01135       }
01136    }
01137 }
01138 
01139 
01140 static void
01141 make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
01142                      GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride,
01143                      GLint dstWidth, GLint dstHeight,
01144              GLubyte *dstPtr, GLuint dstRowStride )
01145 {
01146    const GLint bpt = bytes_per_pixel(datatype, comps);
01147    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
01148    const GLint dstWidthNB = dstWidth - 2 * border;
01149    const GLint dstHeightNB = dstHeight - 2 * border;
01150    const GLint srcRowBytes = bpt * srcRowStride;
01151    const GLint dstRowBytes = bpt * dstRowStride;
01152    const GLubyte *src;
01153    GLubyte *dst;
01154    GLint row;
01155 
01156    /* Compute src and dst pointers, skipping any border */
01157    src = srcPtr + border * ((srcWidth + 1) * bpt);
01158    dst = dstPtr + border * ((dstWidth + 1) * bpt);
01159 
01160    for (row = 0; row < dstHeightNB; row++) {
01161       do_row(datatype, comps, srcWidthNB, src, src,
01162              dstWidthNB, dst);
01163       src += srcRowBytes;
01164       dst += dstRowBytes;
01165    }
01166 
01167    if (border) {
01168       /* copy left-most pixel from source */
01169       MEMCPY(dstPtr, srcPtr, bpt);
01170       /* copy right-most pixel from source */
01171       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
01172              srcPtr + (srcWidth - 1) * bpt,
01173              bpt);
01174    }
01175 }
01176 
01177 
01183 static void
01184 make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
01185                      GLint srcWidth, GLint srcHeight,
01186              const GLubyte *srcPtr, GLint srcRowStride,
01187                      GLint dstWidth, GLint dstHeight, GLint dstDepth,
01188                      GLubyte *dstPtr, GLint dstRowStride)
01189 {
01190    const GLint bpt = bytes_per_pixel(datatype, comps);
01191    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
01192    const GLint dstWidthNB = dstWidth - 2 * border;
01193    const GLint dstHeightNB = dstHeight - 2 * border;
01194    const GLint dstDepthNB = dstDepth - 2 * border;
01195    const GLint srcRowBytes = bpt * srcRowStride;
01196    const GLint dstRowBytes = bpt * dstRowStride;
01197    const GLubyte *srcA, *srcB;
01198    GLubyte *dst;
01199    GLint layer;
01200    GLint row;
01201 
01202    /* Compute src and dst pointers, skipping any border */
01203    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
01204    if (srcHeight > 1) 
01205       srcB = srcA + srcRowBytes;
01206    else
01207       srcB = srcA;
01208    dst = dstPtr + border * ((dstWidth + 1) * bpt);
01209 
01210    for (layer = 0; layer < dstDepthNB; layer++) {
01211       for (row = 0; row < dstHeightNB; row++) {
01212          do_row(datatype, comps, srcWidthNB, srcA, srcB,
01213                 dstWidthNB, dst);
01214          srcA += 2 * srcRowBytes;
01215          srcB += 2 * srcRowBytes;
01216          dst += dstRowBytes;
01217       }
01218 
01219       /* This is ugly but probably won't be used much */
01220       if (border > 0) {
01221          /* fill in dest border */
01222          /* lower-left border pixel */
01223          MEMCPY(dstPtr, srcPtr, bpt);
01224          /* lower-right border pixel */
01225          MEMCPY(dstPtr + (dstWidth - 1) * bpt,
01226                 srcPtr + (srcWidth - 1) * bpt, bpt);
01227          /* upper-left border pixel */
01228          MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
01229                 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
01230          /* upper-right border pixel */
01231          MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
01232                 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
01233          /* lower border */
01234          do_row(datatype, comps, srcWidthNB,
01235                 srcPtr + bpt,
01236                 srcPtr + bpt,
01237                 dstWidthNB, dstPtr + bpt);
01238          /* upper border */
01239          do_row(datatype, comps, srcWidthNB,
01240                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
01241                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
01242                 dstWidthNB,
01243                 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
01244          /* left and right borders */
01245          if (srcHeight == dstHeight) {
01246             /* copy border pixel from src to dst */
01247             for (row = 1; row < srcHeight; row++) {
01248                MEMCPY(dstPtr + dstWidth * row * bpt,
01249                       srcPtr + srcWidth * row * bpt, bpt);
01250                MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
01251                       srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
01252             }
01253          }
01254          else {
01255             /* average two src pixels each dest pixel */
01256             for (row = 0; row < dstHeightNB; row += 2) {
01257                do_row(datatype, comps, 1,
01258                       srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
01259                       srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
01260                       1, dstPtr + (dstWidth * row + 1) * bpt);
01261                do_row(datatype, comps, 1,
01262                       srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
01263                       srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
01264                       1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
01265             }
01266          }
01267       }
01268    }
01269 }
01270 
01271 
01275 void
01276 _mesa_generate_mipmap_level(GLenum target,
01277                             GLenum datatype, GLuint comps,
01278                             GLint border,
01279                             GLint srcWidth, GLint srcHeight, GLint srcDepth,
01280                             const GLubyte *srcData,
01281                             GLint srcRowStride,
01282                             GLint dstWidth, GLint dstHeight, GLint dstDepth,
01283                             GLubyte *dstData,
01284                             GLint dstRowStride)
01285 {
01286    /*
01287     * We use simple 2x2 averaging to compute the next mipmap level.
01288     */
01289    switch (target) {
01290    case GL_TEXTURE_1D:
01291       make_1d_mipmap(datatype, comps, border,
01292                      srcWidth, srcData,
01293                      dstWidth, dstData);
01294       break;
01295    case GL_TEXTURE_2D:
01296    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
01297    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
01298    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
01299    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
01300    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
01301    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
01302       make_2d_mipmap(datatype, comps, border,
01303                      srcWidth, srcHeight, srcData, srcRowStride,
01304                      dstWidth, dstHeight, dstData, dstRowStride);
01305       break;
01306    case GL_TEXTURE_3D:
01307       make_3d_mipmap(datatype, comps, border,
01308                      srcWidth, srcHeight, srcDepth,
01309                      srcData, srcRowStride,
01310                      dstWidth, dstHeight, dstDepth,
01311                      dstData, dstRowStride);
01312       break;
01313    case GL_TEXTURE_1D_ARRAY_EXT:
01314       make_1d_stack_mipmap(datatype, comps, border,
01315                            srcWidth, srcData, srcRowStride,
01316                            dstWidth, dstHeight,
01317                            dstData, dstRowStride);
01318       break;
01319    case GL_TEXTURE_2D_ARRAY_EXT:
01320       make_2d_stack_mipmap(datatype, comps, border,
01321                            srcWidth, srcHeight,
01322                            srcData, srcRowStride,
01323                            dstWidth, dstHeight,
01324                            dstDepth, dstData, dstRowStride);
01325       break;
01326    case GL_TEXTURE_RECTANGLE_NV:
01327       /* no mipmaps, do nothing */
01328       break;
01329    default:
01330       _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
01331       return;
01332    }
01333 }
01334 
01335 
01340 static GLboolean
01341 next_mipmap_level_size(GLenum target, GLint border,
01342                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
01343                        GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
01344 {
01345    if (srcWidth - 2 * border > 1) {
01346       *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
01347    }
01348    else {
01349       *dstWidth = srcWidth; /* can't go smaller */
01350    }
01351 
01352    if ((srcHeight - 2 * border > 1) && 
01353        (target != GL_TEXTURE_1D_ARRAY_EXT)) {
01354       *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
01355    }
01356    else {
01357       *dstHeight = srcHeight; /* can't go smaller */
01358    }
01359 
01360    if ((srcDepth - 2 * border > 1) &&
01361        (target != GL_TEXTURE_2D_ARRAY_EXT)) {
01362       *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
01363    }
01364    else {
01365       *dstDepth = srcDepth; /* can't go smaller */
01366    }
01367 
01368    if (*dstWidth == srcWidth &&
01369        *dstHeight == srcHeight &&
01370        *dstDepth == srcDepth) {
01371       return GL_FALSE;
01372    }
01373    else {
01374       return GL_TRUE;
01375    }
01376 }
01377 
01378 
01379 
01380 
01386 void
01387 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
01388                       struct gl_texture_object *texObj)
01389 {
01390    const struct gl_texture_image *srcImage;
01391    const struct gl_texture_format *convertFormat;
01392    const GLubyte *srcData = NULL;
01393    GLubyte *dstData = NULL;
01394    GLint level, maxLevels;
01395    GLenum datatype;
01396    GLuint comps;
01397 
01398    ASSERT(texObj);
01399    /* XXX choose cube map face here??? */
01400    srcImage = texObj->Image[0][texObj->BaseLevel];
01401    ASSERT(srcImage);
01402 
01403    maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
01404    ASSERT(maxLevels > 0);  /* bad target */
01405 
01406    /* Find convertFormat - the format that do_row() will process */
01407    if (srcImage->IsCompressed) {
01408       /* setup for compressed textures */
01409       GLuint row;
01410       GLint  components, size;
01411       GLchan *dst;
01412 
01413       assert(texObj->Target == GL_TEXTURE_2D ||
01414              texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
01415 
01416       if (srcImage->_BaseFormat == GL_RGB) {
01417          convertFormat = &_mesa_texformat_rgb;
01418          components = 3;
01419       }
01420       else if (srcImage->_BaseFormat == GL_RGBA) {
01421          convertFormat = &_mesa_texformat_rgba;
01422          components = 4;
01423       }
01424       else {
01425          _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
01426          return;
01427       }
01428 
01429       /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
01430       size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
01431          * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
01432       /* 20 extra bytes, just be safe when calling last FetchTexel */
01433       srcData = (GLubyte *) _mesa_malloc(size);
01434       if (!srcData) {
01435          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
01436          return;
01437       }
01438       dstData = (GLubyte *) _mesa_malloc(size / 2);  /* 1/4 would probably be OK */
01439       if (!dstData) {
01440          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
01441          _mesa_free((void *) srcData);
01442          return;
01443       }
01444 
01445       /* decompress base image here */
01446       dst = (GLchan *) srcData;
01447       for (row = 0; row < srcImage->Height; row++) {
01448          GLuint col;
01449          for (col = 0; col < srcImage->Width; col++) {
01450             srcImage->FetchTexelc(srcImage, col, row, 0, dst);
01451             dst += components;
01452          }
01453       }
01454    }
01455    else {
01456       /* uncompressed */
01457       convertFormat = srcImage->TexFormat;
01458    }
01459 
01460    _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
01461 
01462    for (level = texObj->BaseLevel; level < texObj->MaxLevel
01463            && level < maxLevels - 1; level++) {
01464       /* generate image[level+1] from image[level] */
01465       const struct gl_texture_image *srcImage;
01466       struct gl_texture_image *dstImage;
01467       GLint srcWidth, srcHeight, srcDepth;
01468       GLint dstWidth, dstHeight, dstDepth;
01469       GLint border, bytesPerTexel;
01470       GLboolean nextLevel;
01471 
01472       /* get src image parameters */
01473       srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
01474       ASSERT(srcImage);
01475       srcWidth = srcImage->Width;
01476       srcHeight = srcImage->Height;
01477       srcDepth = srcImage->Depth;
01478       border = srcImage->Border;
01479 
01480       nextLevel = next_mipmap_level_size(target, border,
01481                                          srcWidth, srcHeight, srcDepth,
01482                                          &dstWidth, &dstHeight, &dstDepth);
01483       if (!nextLevel) {
01484          /* all done */
01485          if (srcImage->IsCompressed) {
01486             _mesa_free((void *) srcData);
01487             _mesa_free(dstData);
01488          }
01489          return;
01490       }
01491 
01492       /* get dest gl_texture_image */
01493       dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
01494       if (!dstImage) {
01495          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
01496          return;
01497       }
01498 
01499       if (dstImage->ImageOffsets)
01500          _mesa_free(dstImage->ImageOffsets);
01501 
01502       /* Free old image data */
01503       if (dstImage->Data)
01504          ctx->Driver.FreeTexImageData(ctx, dstImage);
01505 
01506       /* initialize new image */
01507       _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
01508                                  dstDepth, border, srcImage->InternalFormat);
01509       dstImage->DriverData = NULL;
01510       dstImage->TexFormat = srcImage->TexFormat;
01511       dstImage->FetchTexelc = srcImage->FetchTexelc;
01512       dstImage->FetchTexelf = srcImage->FetchTexelf;
01513       dstImage->IsCompressed = srcImage->IsCompressed;
01514       if (dstImage->IsCompressed) {
01515          dstImage->CompressedSize
01516             = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width,
01517                                               dstImage->Height,
01518                                               dstImage->Depth,
01519                                               dstImage->TexFormat->MesaFormat);
01520          ASSERT(dstImage->CompressedSize > 0);
01521       }
01522 
01523       ASSERT(dstImage->TexFormat);
01524       ASSERT(dstImage->FetchTexelc);
01525       ASSERT(dstImage->FetchTexelf);
01526 
01527       /* Alloc new teximage data buffer.
01528        * Setup src and dest data pointers.
01529        */
01530       if (dstImage->IsCompressed) {
01531          dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize);
01532          if (!dstImage->Data) {
01533             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
01534             return;
01535          }
01536          /* srcData and dstData are already set */
01537          ASSERT(srcData);
01538          ASSERT(dstData);
01539       }
01540       else {
01541          bytesPerTexel = dstImage->TexFormat->TexelBytes;
01542          ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
01543          dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight
01544                                                 * dstDepth * bytesPerTexel);
01545          if (!dstImage->Data) {
01546             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
01547             return;
01548          }
01549          srcData = (const GLubyte *) srcImage->Data;
01550          dstData = (GLubyte *) dstImage->Data;
01551       }
01552 
01553       _mesa_generate_mipmap_level(target, datatype, comps, border,
01554                                   srcWidth, srcHeight, srcDepth, 
01555                                   srcData, srcImage->RowStride,
01556                                   dstWidth, dstHeight, dstDepth, 
01557                                   dstData, dstImage->RowStride);
01558 
01559 
01560       if (dstImage->IsCompressed) {
01561          GLubyte *temp;
01562          /* compress image from dstData into dstImage->Data */
01563          const GLenum srcFormat = convertFormat->BaseFormat;
01564          GLint dstRowStride
01565             = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth);
01566          ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
01567          dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat,
01568                                          dstImage->TexFormat,
01569                                          dstImage->Data,
01570                                          0, 0, 0, /* dstX/Y/Zoffset */
01571                                          dstRowStride, 0, /* strides */
01572                                          dstWidth, dstHeight, 1, /* size */
01573                                          srcFormat, CHAN_TYPE,
01574                                          dstData, /* src data, actually */
01575                                          &ctx->DefaultPacking);
01576          /* swap src and dest pointers */
01577          temp = (GLubyte *) srcData;
01578          srcData = dstData;
01579          dstData = temp;
01580       }
01581 
01582    } /* loop over mipmap levels */
01583 }
01584 
01585 
01593 void
01594 _mesa_rescale_teximage2d(GLuint bytesPerPixel,
01595              GLuint srcStrideInPixels,
01596              GLuint dstRowStride,
01597              GLint srcWidth, GLint srcHeight,
01598              GLint dstWidth, GLint dstHeight,
01599              const GLvoid *srcImage, GLvoid *dstImage)
01600 {
01601    GLint row, col;
01602 
01603 #define INNER_LOOP( TYPE, HOP, WOP )                    \
01604    for ( row = 0 ; row < dstHeight ; row++ ) {              \
01605       GLint srcRow = row HOP hScale;                    \
01606       for ( col = 0 ; col < dstWidth ; col++ ) {            \
01607      GLint srcCol = col WOP wScale;                 \
01608      dst[col] = src[srcRow * srcStrideInPixels + srcCol];       \
01609       }                                 \
01610       dst = (TYPE *) ((GLubyte *) dst + dstRowStride);          \
01611    }                                    \
01612 
01613 #define RESCALE_IMAGE( TYPE )                       \
01614 do {                                    \
01615    const TYPE *src = (const TYPE *)srcImage;                \
01616    TYPE *dst = (TYPE *)dstImage;                    \
01617                                     \
01618    if ( srcHeight < dstHeight ) {                   \
01619       const GLint hScale = dstHeight / srcHeight;           \
01620       if ( srcWidth < dstWidth ) {                  \
01621      const GLint wScale = dstWidth / srcWidth;          \
01622      INNER_LOOP( TYPE, /, / );                  \
01623       }                                 \
01624       else {                                \
01625      const GLint wScale = srcWidth / dstWidth;          \
01626      INNER_LOOP( TYPE, /, * );                  \
01627       }                                 \
01628    }                                    \
01629    else {                               \
01630       const GLint hScale = srcHeight / dstHeight;           \
01631       if ( srcWidth < dstWidth ) {                  \
01632      const GLint wScale = dstWidth / srcWidth;          \
01633      INNER_LOOP( TYPE, *, / );                  \
01634       }                                 \
01635       else {                                \
01636      const GLint wScale = srcWidth / dstWidth;          \
01637      INNER_LOOP( TYPE, *, * );                  \
01638       }                                 \
01639    }                                    \
01640 } while (0)
01641 
01642    switch ( bytesPerPixel ) {
01643    case 4:
01644       RESCALE_IMAGE( GLuint );
01645       break;
01646 
01647    case 2:
01648       RESCALE_IMAGE( GLushort );
01649       break;
01650 
01651    case 1:
01652       RESCALE_IMAGE( GLubyte );
01653       break;
01654    default:
01655       _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
01656    }
01657 }
01658 
01659 
01665 void
01666 _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight,
01667                          GLsizei outWidth, GLsizei outHeight,
01668                          GLint comps, const GLchan *src, GLint srcRowStride,
01669                          GLchan *dest )
01670 {
01671    GLint i, j, k;
01672 
01673    ASSERT(outWidth >= inWidth);
01674    ASSERT(outHeight >= inHeight);
01675 #if 0
01676    ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
01677    ASSERT((outWidth & 3) == 0);
01678    ASSERT((outHeight & 3) == 0);
01679 #endif
01680 
01681    for (i = 0; i < outHeight; i++) {
01682       const GLint ii = i % inHeight;
01683       for (j = 0; j < outWidth; j++) {
01684          const GLint jj = j % inWidth;
01685          for (k = 0; k < comps; k++) {
01686             dest[(i * outWidth + j) * comps + k]
01687                = src[ii * srcRowStride + jj * comps + k];
01688          }
01689       }
01690    }
01691 }
01692 

Generated on Sun May 27 2012 04:20:22 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.