OSDN Git Service

Merge branch 'radeon-rewrite' of git+ssh://agd5f@git.freedesktop.org/git/mesa/mesa...
[android-x86/external-mesa.git] / src / mesa / main / mipmap.c
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 "mipmap.h"
32 #include "texcompress.h"
33 #include "texformat.h"
34 #include "teximage.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    else if (datatype == GL_FLOAT && comps == 4) {
292       GLuint i, j, k;
293       const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
294       const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB;
295       GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow;
296       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
297            i++, j += colStride, k += colStride) {
298          dst[i][0] = (rowA[j][0] + rowA[k][0] +
299                       rowB[j][0] + rowB[k][0]) * 0.25F;
300          dst[i][1] = (rowA[j][1] + rowA[k][1] +
301                       rowB[j][1] + rowB[k][1]) * 0.25F;
302          dst[i][2] = (rowA[j][2] + rowA[k][2] +
303                       rowB[j][2] + rowB[k][2]) * 0.25F;
304          dst[i][3] = (rowA[j][3] + rowA[k][3] +
305                       rowB[j][3] + rowB[k][3]) * 0.25F;
306       }
307    }
308    else if (datatype == GL_FLOAT && comps == 3) {
309       GLuint i, j, k;
310       const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA;
311       const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB;
312       GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow;
313       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
314            i++, j += colStride, k += colStride) {
315          dst[i][0] = (rowA[j][0] + rowA[k][0] +
316                       rowB[j][0] + rowB[k][0]) * 0.25F;
317          dst[i][1] = (rowA[j][1] + rowA[k][1] +
318                       rowB[j][1] + rowB[k][1]) * 0.25F;
319          dst[i][2] = (rowA[j][2] + rowA[k][2] +
320                       rowB[j][2] + rowB[k][2]) * 0.25F;
321       }
322    }
323    else if (datatype == GL_FLOAT && comps == 2) {
324       GLuint i, j, k;
325       const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA;
326       const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB;
327       GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow;
328       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
329            i++, j += colStride, k += colStride) {
330          dst[i][0] = (rowA[j][0] + rowA[k][0] +
331                       rowB[j][0] + rowB[k][0]) * 0.25F;
332          dst[i][1] = (rowA[j][1] + rowA[k][1] +
333                       rowB[j][1] + rowB[k][1]) * 0.25F;
334       }
335    }
336    else if (datatype == GL_FLOAT && comps == 1) {
337       GLuint i, j, k;
338       const GLfloat *rowA = (const GLfloat *) srcRowA;
339       const GLfloat *rowB = (const GLfloat *) srcRowB;
340       GLfloat *dst = (GLfloat *) dstRow;
341       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
342            i++, j += colStride, k += colStride) {
343          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
344       }
345    }
346
347    else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) {
348       GLuint i, j, k, comp;
349       const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA;
350       const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB;
351       GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow;
352       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
353            i++, j += colStride, k += colStride) {
354          for (comp = 0; comp < 4; comp++) {
355             GLfloat aj, ak, bj, bk;
356             aj = _mesa_half_to_float(rowA[j][comp]);
357             ak = _mesa_half_to_float(rowA[k][comp]);
358             bj = _mesa_half_to_float(rowB[j][comp]);
359             bk = _mesa_half_to_float(rowB[k][comp]);
360             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
361          }
362       }
363    }
364    else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) {
365       GLuint i, j, k, comp;
366       const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA;
367       const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB;
368       GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow;
369       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
370            i++, j += colStride, k += colStride) {
371          for (comp = 0; comp < 3; comp++) {
372             GLfloat aj, ak, bj, bk;
373             aj = _mesa_half_to_float(rowA[j][comp]);
374             ak = _mesa_half_to_float(rowA[k][comp]);
375             bj = _mesa_half_to_float(rowB[j][comp]);
376             bk = _mesa_half_to_float(rowB[k][comp]);
377             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
378          }
379       }
380    }
381    else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) {
382       GLuint i, j, k, comp;
383       const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA;
384       const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB;
385       GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow;
386       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
387            i++, j += colStride, k += colStride) {
388          for (comp = 0; comp < 2; comp++) {
389             GLfloat aj, ak, bj, bk;
390             aj = _mesa_half_to_float(rowA[j][comp]);
391             ak = _mesa_half_to_float(rowA[k][comp]);
392             bj = _mesa_half_to_float(rowB[j][comp]);
393             bk = _mesa_half_to_float(rowB[k][comp]);
394             dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
395          }
396       }
397    }
398    else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) {
399       GLuint i, j, k;
400       const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
401       const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
402       GLhalfARB *dst = (GLhalfARB *) dstRow;
403       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
404            i++, j += colStride, k += colStride) {
405          GLfloat aj, ak, bj, bk;
406          aj = _mesa_half_to_float(rowA[j]);
407          ak = _mesa_half_to_float(rowA[k]);
408          bj = _mesa_half_to_float(rowB[j]);
409          bk = _mesa_half_to_float(rowB[k]);
410          dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
411       }
412    }
413
414    else if (datatype == GL_UNSIGNED_INT && comps == 1) {
415       GLuint i, j, k;
416       const GLuint *rowA = (const GLuint *) srcRowA;
417       const GLuint *rowB = (const GLuint *) srcRowB;
418       GLfloat *dst = (GLfloat *) dstRow;
419       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
420            i++, j += colStride, k += colStride) {
421          dst[i] = (GLfloat)(rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4);
422       }
423    }
424
425    else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) {
426       GLuint i, j, k;
427       const GLushort *rowA = (const GLushort *) srcRowA;
428       const GLushort *rowB = (const GLushort *) srcRowB;
429       GLushort *dst = (GLushort *) dstRow;
430       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
431            i++, j += colStride, k += colStride) {
432          const GLint rowAr0 = rowA[j] & 0x1f;
433          const GLint rowAr1 = rowA[k] & 0x1f;
434          const GLint rowBr0 = rowB[j] & 0x1f;
435          const GLint rowBr1 = rowB[k] & 0x1f;
436          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
437          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
438          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
439          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
440          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
441          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
442          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
443          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
444          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
445          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
446          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
447          dst[i] = (blue << 11) | (green << 5) | red;
448       }
449    }
450    else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) {
451       GLuint i, j, k;
452       const GLushort *rowA = (const GLushort *) srcRowA;
453       const GLushort *rowB = (const GLushort *) srcRowB;
454       GLushort *dst = (GLushort *) dstRow;
455       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
456            i++, j += colStride, k += colStride) {
457          const GLint rowAr0 = rowA[j] & 0xf;
458          const GLint rowAr1 = rowA[k] & 0xf;
459          const GLint rowBr0 = rowB[j] & 0xf;
460          const GLint rowBr1 = rowB[k] & 0xf;
461          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
462          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
463          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
464          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
465          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
466          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
467          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
468          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
469          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
470          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
471          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
472          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
473          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
474          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
475          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
476          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
477          dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
478       }
479    }
480    else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) {
481       GLuint i, j, k;
482       const GLushort *rowA = (const GLushort *) srcRowA;
483       const GLushort *rowB = (const GLushort *) srcRowB;
484       GLushort *dst = (GLushort *) dstRow;
485       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
486            i++, j += colStride, k += colStride) {
487          const GLint rowAr0 = rowA[j] & 0x1f;
488          const GLint rowAr1 = rowA[k] & 0x1f;
489          const GLint rowBr0 = rowB[j] & 0x1f;
490          const GLint rowBr1 = rowB[k] & 0x1f;
491          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
492          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
493          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
494          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
495          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
496          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
497          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
498          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
499          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
500          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
501          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
502          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
503          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
504          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
505          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
506          const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
507          dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
508       }
509    }
510    else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) {
511       GLuint i, j, k;
512       const GLubyte *rowA = (const GLubyte *) srcRowA;
513       const GLubyte *rowB = (const GLubyte *) srcRowB;
514       GLubyte *dst = (GLubyte *) dstRow;
515       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
516            i++, j += colStride, k += colStride) {
517          const GLint rowAr0 = rowA[j] & 0x3;
518          const GLint rowAr1 = rowA[k] & 0x3;
519          const GLint rowBr0 = rowB[j] & 0x3;
520          const GLint rowBr1 = rowB[k] & 0x3;
521          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
522          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
523          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
524          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
525          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
526          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
527          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
528          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
529          const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
530          const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
531          const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
532          dst[i] = (blue << 5) | (green << 2) | red;
533       }
534    }
535    else {
536       _mesa_problem(NULL, "bad format in do_row()");
537    }
538 }
539
540
541 /**
542  * Average together four rows of a source image to produce a single new
543  * row in the dest image.  It's legal for the two source rows to point
544  * to the same data.  The source width must be equal to either the
545  * dest width or two times the dest width.
546  *
547  * \param datatype  GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
548  *                  \c GL_FLOAT, etc.
549  * \param comps     number of components per pixel (1..4)
550  * \param srcWidth  Width of a row in the source data
551  * \param srcRowA   Pointer to one of the rows of source data
552  * \param srcRowB   Pointer to one of the rows of source data
553  * \param srcRowC   Pointer to one of the rows of source data
554  * \param srcRowD   Pointer to one of the rows of source data
555  * \param dstWidth  Width of a row in the destination data
556  * \param srcRowA   Pointer to the row of destination data
557  */
558 static void
559 do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
560           const GLvoid *srcRowA, const GLvoid *srcRowB,
561           const GLvoid *srcRowC, const GLvoid *srcRowD,
562           GLint dstWidth, GLvoid *dstRow)
563 {
564    const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
565    const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
566    GLuint i, j, k;
567
568    ASSERT(comps >= 1);
569    ASSERT(comps <= 4);
570
571    if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) {
572       DECLARE_ROW_POINTERS(GLubyte, 4);
573
574       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
575            i++, j += colStride, k += colStride) {
576          FILTER_3D(0);
577          FILTER_3D(1);
578          FILTER_3D(2);
579          FILTER_3D(3);
580       }
581    }
582    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) {
583       DECLARE_ROW_POINTERS(GLubyte, 3);
584
585       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
586            i++, j += colStride, k += colStride) {
587          FILTER_3D(0);
588          FILTER_3D(1);
589          FILTER_3D(2);
590       }
591    }
592    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) {
593       DECLARE_ROW_POINTERS(GLubyte, 2);
594
595       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
596            i++, j += colStride, k += colStride) {
597          FILTER_3D(0);
598          FILTER_3D(1);
599       }
600    }
601    else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) {
602       DECLARE_ROW_POINTERS(GLubyte, 1);
603
604       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
605            i++, j += colStride, k += colStride) {
606          FILTER_3D(0);
607       }
608    }
609    if ((datatype == GL_BYTE) && (comps == 4)) {
610       DECLARE_ROW_POINTERS(GLbyte, 4);
611
612       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
613            i++, j += colStride, k += colStride) {
614          FILTER_3D_SIGNED(0);
615          FILTER_3D_SIGNED(1);
616          FILTER_3D_SIGNED(2);
617          FILTER_3D_SIGNED(3);
618       }
619    }
620    else if ((datatype == GL_BYTE) && (comps == 3)) {
621       DECLARE_ROW_POINTERS(GLbyte, 3);
622
623       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
624            i++, j += colStride, k += colStride) {
625          FILTER_3D_SIGNED(0);
626          FILTER_3D_SIGNED(1);
627          FILTER_3D_SIGNED(2);
628       }
629    }
630    else if ((datatype == GL_BYTE) && (comps == 2)) {
631       DECLARE_ROW_POINTERS(GLbyte, 2);
632
633       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
634            i++, j += colStride, k += colStride) {
635          FILTER_3D_SIGNED(0);
636          FILTER_3D_SIGNED(1);
637        }
638    }
639    else if ((datatype == GL_BYTE) && (comps == 1)) {
640       DECLARE_ROW_POINTERS(GLbyte, 1);
641
642       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
643            i++, j += colStride, k += colStride) {
644          FILTER_3D_SIGNED(0);
645       }
646    }
647    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
648       DECLARE_ROW_POINTERS(GLushort, 4);
649
650       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
651            i++, j += colStride, k += colStride) {
652          FILTER_3D(0);
653          FILTER_3D(1);
654          FILTER_3D(2);
655          FILTER_3D(3);
656       }
657    }
658    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) {
659       DECLARE_ROW_POINTERS(GLushort, 3);
660
661       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
662            i++, j += colStride, k += colStride) {
663          FILTER_3D(0);
664          FILTER_3D(1);
665          FILTER_3D(2);
666       }
667    }
668    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) {
669       DECLARE_ROW_POINTERS(GLushort, 2);
670
671       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
672            i++, j += colStride, k += colStride) {
673          FILTER_3D(0);
674          FILTER_3D(1);
675       }
676    }
677    else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) {
678       DECLARE_ROW_POINTERS(GLushort, 1);
679
680       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
681            i++, j += colStride, k += colStride) {
682          FILTER_3D(0);
683       }
684    }
685    else if ((datatype == GL_FLOAT) && (comps == 4)) {
686       DECLARE_ROW_POINTERS(GLfloat, 4);
687
688       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
689            i++, j += colStride, k += colStride) {
690          FILTER_F_3D(0);
691          FILTER_F_3D(1);
692          FILTER_F_3D(2);
693          FILTER_F_3D(3);
694       }
695    }
696    else if ((datatype == GL_FLOAT) && (comps == 3)) {
697       DECLARE_ROW_POINTERS(GLfloat, 3);
698
699       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
700            i++, j += colStride, k += colStride) {
701          FILTER_F_3D(0);
702          FILTER_F_3D(1);
703          FILTER_F_3D(2);
704       }
705    }
706    else if ((datatype == GL_FLOAT) && (comps == 2)) {
707       DECLARE_ROW_POINTERS(GLfloat, 2);
708
709       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
710            i++, j += colStride, k += colStride) {
711          FILTER_F_3D(0);
712          FILTER_F_3D(1);
713       }
714    }
715    else if ((datatype == GL_FLOAT) && (comps == 1)) {
716       DECLARE_ROW_POINTERS(GLfloat, 1);
717
718       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
719            i++, j += colStride, k += colStride) {
720          FILTER_F_3D(0);
721       }
722    }
723    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) {
724       DECLARE_ROW_POINTERS(GLhalfARB, 4);
725
726       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
727            i++, j += colStride, k += colStride) {
728          FILTER_HF_3D(0);
729          FILTER_HF_3D(1);
730          FILTER_HF_3D(2);
731          FILTER_HF_3D(3);
732       }
733    }
734    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
735       DECLARE_ROW_POINTERS(GLhalfARB, 4);
736
737       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
738            i++, j += colStride, k += colStride) {
739          FILTER_HF_3D(0);
740          FILTER_HF_3D(1);
741          FILTER_HF_3D(2);
742       }
743    }
744    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
745       DECLARE_ROW_POINTERS(GLhalfARB, 4);
746
747       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
748            i++, j += colStride, k += colStride) {
749          FILTER_HF_3D(0);
750          FILTER_HF_3D(1);
751       }
752    }
753    else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
754       DECLARE_ROW_POINTERS(GLhalfARB, 4);
755
756       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
757            i++, j += colStride, k += colStride) {
758          FILTER_HF_3D(0);
759       }
760    }
761    else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) {
762       const GLuint *rowA = (const GLuint *) srcRowA;
763       const GLuint *rowB = (const GLuint *) srcRowB;
764       const GLuint *rowC = (const GLuint *) srcRowC;
765       const GLuint *rowD = (const GLuint *) srcRowD;
766       GLfloat *dst = (GLfloat *) dstRow;
767
768       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
769            i++, j += colStride, k += colStride) {
770          const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
771                                + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
772                                + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
773                                + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
774          dst[i] = (GLfloat)((double) tmp * 0.125);
775       }
776    }
777    else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) {
778       DECLARE_ROW_POINTERS0(GLushort);
779
780       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
781            i++, j += colStride, k += colStride) {
782          const GLint rowAr0 = rowA[j] & 0x1f;
783          const GLint rowAr1 = rowA[k] & 0x1f;
784          const GLint rowBr0 = rowB[j] & 0x1f;
785          const GLint rowBr1 = rowB[k] & 0x1f;
786          const GLint rowCr0 = rowC[j] & 0x1f;
787          const GLint rowCr1 = rowC[k] & 0x1f;
788          const GLint rowDr0 = rowD[j] & 0x1f;
789          const GLint rowDr1 = rowD[k] & 0x1f;
790          const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
791          const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
792          const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
793          const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
794          const GLint rowCg0 = (rowC[j] >> 5) & 0x3f;
795          const GLint rowCg1 = (rowC[k] >> 5) & 0x3f;
796          const GLint rowDg0 = (rowD[j] >> 5) & 0x3f;
797          const GLint rowDg1 = (rowD[k] >> 5) & 0x3f;
798          const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
799          const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
800          const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
801          const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
802          const GLint rowCb0 = (rowC[j] >> 11) & 0x1f;
803          const GLint rowCb1 = (rowC[k] >> 11) & 0x1f;
804          const GLint rowDb0 = (rowD[j] >> 11) & 0x1f;
805          const GLint rowDb1 = (rowD[k] >> 11) & 0x1f;
806          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
807                                        rowCr0, rowCr1, rowDr0, rowDr1);
808          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
809                                        rowCg0, rowCg1, rowDg0, rowDg1);
810          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
811                                        rowCb0, rowCb1, rowDb0, rowDb1);
812          dst[i] = (b << 11) | (g << 5) | r;
813       }
814    }
815    else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) {
816       DECLARE_ROW_POINTERS0(GLushort);
817
818       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
819            i++, j += colStride, k += colStride) {
820          const GLint rowAr0 = rowA[j] & 0xf;
821          const GLint rowAr1 = rowA[k] & 0xf;
822          const GLint rowBr0 = rowB[j] & 0xf;
823          const GLint rowBr1 = rowB[k] & 0xf;
824          const GLint rowCr0 = rowC[j] & 0xf;
825          const GLint rowCr1 = rowC[k] & 0xf;
826          const GLint rowDr0 = rowD[j] & 0xf;
827          const GLint rowDr1 = rowD[k] & 0xf;
828          const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
829          const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
830          const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
831          const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
832          const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
833          const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
834          const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
835          const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
836          const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
837          const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
838          const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
839          const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
840          const GLint rowCb0 = (rowC[j] >> 8) & 0xf;
841          const GLint rowCb1 = (rowC[k] >> 8) & 0xf;
842          const GLint rowDb0 = (rowD[j] >> 8) & 0xf;
843          const GLint rowDb1 = (rowD[k] >> 8) & 0xf;
844          const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
845          const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
846          const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
847          const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
848          const GLint rowCa0 = (rowC[j] >> 12) & 0xf;
849          const GLint rowCa1 = (rowC[k] >> 12) & 0xf;
850          const GLint rowDa0 = (rowD[j] >> 12) & 0xf;
851          const GLint rowDa1 = (rowD[k] >> 12) & 0xf;
852          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
853                                        rowCr0, rowCr1, rowDr0, rowDr1);
854          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
855                                        rowCg0, rowCg1, rowDg0, rowDg1);
856          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
857                                        rowCb0, rowCb1, rowDb0, rowDb1);
858          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
859                                        rowCa0, rowCa1, rowDa0, rowDa1);
860
861          dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
862       }
863    }
864    else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) {
865       DECLARE_ROW_POINTERS0(GLushort);
866
867       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
868            i++, j += colStride, k += colStride) {
869          const GLint rowAr0 = rowA[j] & 0x1f;
870          const GLint rowAr1 = rowA[k] & 0x1f;
871          const GLint rowBr0 = rowB[j] & 0x1f;
872          const GLint rowBr1 = rowB[k] & 0x1f;
873          const GLint rowCr0 = rowC[j] & 0x1f;
874          const GLint rowCr1 = rowC[k] & 0x1f;
875          const GLint rowDr0 = rowD[j] & 0x1f;
876          const GLint rowDr1 = rowD[k] & 0x1f;
877          const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
878          const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
879          const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
880          const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
881          const GLint rowCg0 = (rowC[j] >> 5) & 0x1f;
882          const GLint rowCg1 = (rowC[k] >> 5) & 0x1f;
883          const GLint rowDg0 = (rowD[j] >> 5) & 0x1f;
884          const GLint rowDg1 = (rowD[k] >> 5) & 0x1f;
885          const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
886          const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
887          const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
888          const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
889          const GLint rowCb0 = (rowC[j] >> 10) & 0x1f;
890          const GLint rowCb1 = (rowC[k] >> 10) & 0x1f;
891          const GLint rowDb0 = (rowD[j] >> 10) & 0x1f;
892          const GLint rowDb1 = (rowD[k] >> 10) & 0x1f;
893          const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
894          const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
895          const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
896          const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
897          const GLint rowCa0 = (rowC[j] >> 15) & 0x1;
898          const GLint rowCa1 = (rowC[k] >> 15) & 0x1;
899          const GLint rowDa0 = (rowD[j] >> 15) & 0x1;
900          const GLint rowDa1 = (rowD[k] >> 15) & 0x1;
901          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
902                                        rowCr0, rowCr1, rowDr0, rowDr1);
903          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
904                                        rowCg0, rowCg1, rowDg0, rowDg1);
905          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
906                                        rowCb0, rowCb1, rowDb0, rowDb1);
907          const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
908                                        rowCa0, rowCa1, rowDa0, rowDa1);
909
910          dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
911       }
912    }
913    else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
914       DECLARE_ROW_POINTERS0(GLushort);
915
916       for (i = j = 0, k = k0; i < (GLuint) dstWidth;
917            i++, j += colStride, k += colStride) {
918          const GLint rowAr0 = rowA[j] & 0x3;
919          const GLint rowAr1 = rowA[k] & 0x3;
920          const GLint rowBr0 = rowB[j] & 0x3;
921          const GLint rowBr1 = rowB[k] & 0x3;
922          const GLint rowCr0 = rowC[j] & 0x3;
923          const GLint rowCr1 = rowC[k] & 0x3;
924          const GLint rowDr0 = rowD[j] & 0x3;
925          const GLint rowDr1 = rowD[k] & 0x3;
926          const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
927          const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
928          const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
929          const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
930          const GLint rowCg0 = (rowC[j] >> 2) & 0x7;
931          const GLint rowCg1 = (rowC[k] >> 2) & 0x7;
932          const GLint rowDg0 = (rowD[j] >> 2) & 0x7;
933          const GLint rowDg1 = (rowD[k] >> 2) & 0x7;
934          const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
935          const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
936          const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
937          const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
938          const GLint rowCb0 = (rowC[j] >> 5) & 0x7;
939          const GLint rowCb1 = (rowC[k] >> 5) & 0x7;
940          const GLint rowDb0 = (rowD[j] >> 5) & 0x7;
941          const GLint rowDb1 = (rowD[k] >> 5) & 0x7;
942          const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
943                                        rowCr0, rowCr1, rowDr0, rowDr1);
944          const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
945                                        rowCg0, rowCg1, rowDg0, rowDg1);
946          const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
947                                        rowCb0, rowCb1, rowDb0, rowDb1);
948          dst[i] = (b << 5) | (g << 2) | r;
949       }
950    }
951    else {
952       _mesa_problem(NULL, "bad format in do_row()");
953    }
954 }
955
956
957 /*
958  * These functions generate a 1/2-size mipmap image from a source image.
959  * Texture borders are handled by copying or averaging the source image's
960  * border texels, depending on the scale-down factor.
961  */
962
963 static void
964 make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
965                GLint srcWidth, const GLubyte *srcPtr,
966                GLint dstWidth, GLubyte *dstPtr)
967 {
968    const GLint bpt = bytes_per_pixel(datatype, comps);
969    const GLubyte *src;
970    GLubyte *dst;
971
972    /* skip the border pixel, if any */
973    src = srcPtr + border * bpt;
974    dst = dstPtr + border * bpt;
975
976    /* we just duplicate the input row, kind of hack, saves code */
977    do_row(datatype, comps, srcWidth - 2 * border, src, src,
978           dstWidth - 2 * border, dst);
979
980    if (border) {
981       /* copy left-most pixel from source */
982       MEMCPY(dstPtr, srcPtr, bpt);
983       /* copy right-most pixel from source */
984       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
985              srcPtr + (srcWidth - 1) * bpt,
986              bpt);
987    }
988 }
989
990
991 static void
992 make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
993                GLint srcWidth, GLint srcHeight,
994                const GLubyte *srcPtr, GLint srcRowStride,
995                GLint dstWidth, GLint dstHeight,
996                GLubyte *dstPtr, GLint dstRowStride)
997 {
998    const GLint bpt = bytes_per_pixel(datatype, comps);
999    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
1000    const GLint dstWidthNB = dstWidth - 2 * border;
1001    const GLint dstHeightNB = dstHeight - 2 * border;
1002    const GLint srcRowBytes = bpt * srcRowStride;
1003    const GLint dstRowBytes = bpt * dstRowStride;
1004    const GLubyte *srcA, *srcB;
1005    GLubyte *dst;
1006    GLint row;
1007
1008    /* Compute src and dst pointers, skipping any border */
1009    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1010    if (srcHeight > 1) 
1011       srcB = srcA + srcRowBytes;
1012    else
1013       srcB = srcA;
1014    dst = dstPtr + border * ((dstWidth + 1) * bpt);
1015
1016    for (row = 0; row < dstHeightNB; row++) {
1017       do_row(datatype, comps, srcWidthNB, srcA, srcB,
1018              dstWidthNB, dst);
1019       srcA += 2 * srcRowBytes;
1020       srcB += 2 * srcRowBytes;
1021       dst += dstRowBytes;
1022    }
1023
1024    /* This is ugly but probably won't be used much */
1025    if (border > 0) {
1026       /* fill in dest border */
1027       /* lower-left border pixel */
1028       MEMCPY(dstPtr, srcPtr, bpt);
1029       /* lower-right border pixel */
1030       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1031              srcPtr + (srcWidth - 1) * bpt, bpt);
1032       /* upper-left border pixel */
1033       MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1034              srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1035       /* upper-right border pixel */
1036       MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1037              srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1038       /* lower border */
1039       do_row(datatype, comps, srcWidthNB,
1040              srcPtr + bpt,
1041              srcPtr + bpt,
1042              dstWidthNB, dstPtr + bpt);
1043       /* upper border */
1044       do_row(datatype, comps, srcWidthNB,
1045              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1046              srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1047              dstWidthNB,
1048              dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1049       /* left and right borders */
1050       if (srcHeight == dstHeight) {
1051          /* copy border pixel from src to dst */
1052          for (row = 1; row < srcHeight; row++) {
1053             MEMCPY(dstPtr + dstWidth * row * bpt,
1054                    srcPtr + srcWidth * row * bpt, bpt);
1055             MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
1056                    srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
1057          }
1058       }
1059       else {
1060          /* average two src pixels each dest pixel */
1061          for (row = 0; row < dstHeightNB; row += 2) {
1062             do_row(datatype, comps, 1,
1063                    srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
1064                    srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1065                    1, dstPtr + (dstWidth * row + 1) * bpt);
1066             do_row(datatype, comps, 1,
1067                    srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
1068                    srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1069                    1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1070          }
1071       }
1072    }
1073 }
1074
1075
1076 static void
1077 make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
1078                GLint srcWidth, GLint srcHeight, GLint srcDepth,
1079                const GLubyte *srcPtr, GLint srcRowStride,
1080                GLint dstWidth, GLint dstHeight, GLint dstDepth,
1081                GLubyte *dstPtr, GLint dstRowStride)
1082 {
1083    const GLint bpt = bytes_per_pixel(datatype, comps);
1084    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
1085    const GLint srcDepthNB = srcDepth - 2 * border;
1086    const GLint dstWidthNB = dstWidth - 2 * border;
1087    const GLint dstHeightNB = dstHeight - 2 * border;
1088    const GLint dstDepthNB = dstDepth - 2 * border;
1089    GLint img, row;
1090    GLint bytesPerSrcImage, bytesPerDstImage;
1091    GLint bytesPerSrcRow, bytesPerDstRow;
1092    GLint srcImageOffset, srcRowOffset;
1093
1094    (void) srcDepthNB; /* silence warnings */
1095
1096
1097    bytesPerSrcImage = srcWidth * srcHeight * bpt;
1098    bytesPerDstImage = dstWidth * dstHeight * bpt;
1099
1100    bytesPerSrcRow = srcWidth * bpt;
1101    bytesPerDstRow = dstWidth * bpt;
1102
1103    /* Offset between adjacent src images to be averaged together */
1104    srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
1105
1106    /* Offset between adjacent src rows to be averaged together */
1107    srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
1108
1109    /*
1110     * Need to average together up to 8 src pixels for each dest pixel.
1111     * Break that down into 3 operations:
1112     *   1. take two rows from source image and average them together.
1113     *   2. take two rows from next source image and average them together.
1114     *   3. take the two averaged rows and average them for the final dst row.
1115     */
1116
1117    /*
1118    _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
1119           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1120    */
1121
1122    for (img = 0; img < dstDepthNB; img++) {
1123       /* first source image pointer, skipping border */
1124       const GLubyte *imgSrcA = srcPtr
1125          + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
1126          + img * (bytesPerSrcImage + srcImageOffset);
1127       /* second source image pointer, skipping border */
1128       const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
1129       /* address of the dest image, skipping border */
1130       GLubyte *imgDst = dstPtr
1131          + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
1132          + img * bytesPerDstImage;
1133
1134       /* setup the four source row pointers and the dest row pointer */
1135       const GLubyte *srcImgARowA = imgSrcA;
1136       const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
1137       const GLubyte *srcImgBRowA = imgSrcB;
1138       const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1139       GLubyte *dstImgRow = imgDst;
1140
1141       for (row = 0; row < dstHeightNB; row++) {
1142          do_row_3D(datatype, comps, srcWidthNB, 
1143                    srcImgARowA, srcImgARowB,
1144                    srcImgBRowA, srcImgBRowB,
1145                    dstWidthNB, dstImgRow);
1146
1147          /* advance to next rows */
1148          srcImgARowA += bytesPerSrcRow + srcRowOffset;
1149          srcImgARowB += bytesPerSrcRow + srcRowOffset;
1150          srcImgBRowA += bytesPerSrcRow + srcRowOffset;
1151          srcImgBRowB += bytesPerSrcRow + srcRowOffset;
1152          dstImgRow += bytesPerDstRow;
1153       }
1154    }
1155
1156
1157    /* Luckily we can leverage the make_2d_mipmap() function here! */
1158    if (border > 0) {
1159       /* do front border image */
1160       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight, srcPtr, srcRowStride,
1161                      dstWidth, dstHeight, dstPtr, dstRowStride);
1162       /* do back border image */
1163       make_2d_mipmap(datatype, comps, 1, srcWidth, srcHeight,
1164                      srcPtr + bytesPerSrcImage * (srcDepth - 1), srcRowStride,
1165                      dstWidth, dstHeight,
1166                      dstPtr + bytesPerDstImage * (dstDepth - 1), dstRowStride);
1167       /* do four remaining border edges that span the image slices */
1168       if (srcDepth == dstDepth) {
1169          /* just copy border pixels from src to dst */
1170          for (img = 0; img < dstDepthNB; img++) {
1171             const GLubyte *src;
1172             GLubyte *dst;
1173
1174             /* do border along [img][row=0][col=0] */
1175             src = srcPtr + (img + 1) * bytesPerSrcImage;
1176             dst = dstPtr + (img + 1) * bytesPerDstImage;
1177             MEMCPY(dst, src, bpt);
1178
1179             /* do border along [img][row=dstHeight-1][col=0] */
1180             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1181                          + (srcHeight - 1) * bytesPerSrcRow;
1182             dst = dstPtr + (img + 1) * bytesPerDstImage
1183                          + (dstHeight - 1) * bytesPerDstRow;
1184             MEMCPY(dst, src, bpt);
1185
1186             /* do border along [img][row=0][col=dstWidth-1] */
1187             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1188                          + (srcWidth - 1) * bpt;
1189             dst = dstPtr + (img + 1) * bytesPerDstImage
1190                          + (dstWidth - 1) * bpt;
1191             MEMCPY(dst, src, bpt);
1192
1193             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1194             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1195                          + (bytesPerSrcImage - bpt);
1196             dst = dstPtr + (img + 1) * bytesPerDstImage
1197                          + (bytesPerDstImage - bpt);
1198             MEMCPY(dst, src, bpt);
1199          }
1200       }
1201       else {
1202          /* average border pixels from adjacent src image pairs */
1203          ASSERT(srcDepthNB == 2 * dstDepthNB);
1204          for (img = 0; img < dstDepthNB; img++) {
1205             const GLubyte *src;
1206             GLubyte *dst;
1207
1208             /* do border along [img][row=0][col=0] */
1209             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
1210             dst = dstPtr + (img + 1) * bytesPerDstImage;
1211             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
1212
1213             /* do border along [img][row=dstHeight-1][col=0] */
1214             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1215                          + (srcHeight - 1) * bytesPerSrcRow;
1216             dst = dstPtr + (img + 1) * bytesPerDstImage
1217                          + (dstHeight - 1) * bytesPerDstRow;
1218             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
1219
1220             /* do border along [img][row=0][col=dstWidth-1] */
1221             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1222                          + (srcWidth - 1) * bpt;
1223             dst = dstPtr + (img + 1) * bytesPerDstImage
1224                          + (dstWidth - 1) * bpt;
1225             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
1226
1227             /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1228             src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1229                          + (bytesPerSrcImage - bpt);
1230             dst = dstPtr + (img + 1) * bytesPerDstImage
1231                          + (bytesPerDstImage - bpt);
1232             do_row(datatype, comps, 1, src, src + srcImageOffset, 1, dst);
1233          }
1234       }
1235    }
1236 }
1237
1238
1239 static void
1240 make_1d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
1241                      GLint srcWidth, const GLubyte *srcPtr, GLuint srcRowStride,
1242                      GLint dstWidth, GLint dstHeight,
1243                      GLubyte *dstPtr, GLuint dstRowStride )
1244 {
1245    const GLint bpt = bytes_per_pixel(datatype, comps);
1246    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
1247    const GLint dstWidthNB = dstWidth - 2 * border;
1248    const GLint dstHeightNB = dstHeight - 2 * border;
1249    const GLint srcRowBytes = bpt * srcRowStride;
1250    const GLint dstRowBytes = bpt * dstRowStride;
1251    const GLubyte *src;
1252    GLubyte *dst;
1253    GLint row;
1254
1255    /* Compute src and dst pointers, skipping any border */
1256    src = srcPtr + border * ((srcWidth + 1) * bpt);
1257    dst = dstPtr + border * ((dstWidth + 1) * bpt);
1258
1259    for (row = 0; row < dstHeightNB; row++) {
1260       do_row(datatype, comps, srcWidthNB, src, src,
1261              dstWidthNB, dst);
1262       src += srcRowBytes;
1263       dst += dstRowBytes;
1264    }
1265
1266    if (border) {
1267       /* copy left-most pixel from source */
1268       MEMCPY(dstPtr, srcPtr, bpt);
1269       /* copy right-most pixel from source */
1270       MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1271              srcPtr + (srcWidth - 1) * bpt,
1272              bpt);
1273    }
1274 }
1275
1276
1277 /**
1278  * \bug
1279  * There is quite a bit of refactoring that could be done with this function
1280  * and \c make_2d_mipmap.
1281  */
1282 static void
1283 make_2d_stack_mipmap(GLenum datatype, GLuint comps, GLint border,
1284                      GLint srcWidth, GLint srcHeight,
1285                      const GLubyte *srcPtr, GLint srcRowStride,
1286                      GLint dstWidth, GLint dstHeight, GLint dstDepth,
1287                      GLubyte *dstPtr, GLint dstRowStride)
1288 {
1289    const GLint bpt = bytes_per_pixel(datatype, comps);
1290    const GLint srcWidthNB = srcWidth - 2 * border;  /* sizes w/out border */
1291    const GLint dstWidthNB = dstWidth - 2 * border;
1292    const GLint dstHeightNB = dstHeight - 2 * border;
1293    const GLint dstDepthNB = dstDepth - 2 * border;
1294    const GLint srcRowBytes = bpt * srcRowStride;
1295    const GLint dstRowBytes = bpt * dstRowStride;
1296    const GLubyte *srcA, *srcB;
1297    GLubyte *dst;
1298    GLint layer;
1299    GLint row;
1300
1301    /* Compute src and dst pointers, skipping any border */
1302    srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1303    if (srcHeight > 1) 
1304       srcB = srcA + srcRowBytes;
1305    else
1306       srcB = srcA;
1307    dst = dstPtr + border * ((dstWidth + 1) * bpt);
1308
1309    for (layer = 0; layer < dstDepthNB; layer++) {
1310       for (row = 0; row < dstHeightNB; row++) {
1311          do_row(datatype, comps, srcWidthNB, srcA, srcB,
1312                 dstWidthNB, dst);
1313          srcA += 2 * srcRowBytes;
1314          srcB += 2 * srcRowBytes;
1315          dst += dstRowBytes;
1316       }
1317
1318       /* This is ugly but probably won't be used much */
1319       if (border > 0) {
1320          /* fill in dest border */
1321          /* lower-left border pixel */
1322          MEMCPY(dstPtr, srcPtr, bpt);
1323          /* lower-right border pixel */
1324          MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1325                 srcPtr + (srcWidth - 1) * bpt, bpt);
1326          /* upper-left border pixel */
1327          MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1328                 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1329          /* upper-right border pixel */
1330          MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1331                 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1332          /* lower border */
1333          do_row(datatype, comps, srcWidthNB,
1334                 srcPtr + bpt,
1335                 srcPtr + bpt,
1336                 dstWidthNB, dstPtr + bpt);
1337          /* upper border */
1338          do_row(datatype, comps, srcWidthNB,
1339                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1340                 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1341                 dstWidthNB,
1342                 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1343          /* left and right borders */
1344          if (srcHeight == dstHeight) {
1345             /* copy border pixel from src to dst */
1346             for (row = 1; row < srcHeight; row++) {
1347                MEMCPY(dstPtr + dstWidth * row * bpt,
1348                       srcPtr + srcWidth * row * bpt, bpt);
1349                MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
1350                       srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
1351             }
1352          }
1353          else {
1354             /* average two src pixels each dest pixel */
1355             for (row = 0; row < dstHeightNB; row += 2) {
1356                do_row(datatype, comps, 1,
1357                       srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
1358                       srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1359                       1, dstPtr + (dstWidth * row + 1) * bpt);
1360                do_row(datatype, comps, 1,
1361                       srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
1362                       srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1363                       1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1364             }
1365          }
1366       }
1367    }
1368 }
1369
1370
1371 /**
1372  * Down-sample a texture image to produce the next lower mipmap level.
1373  */
1374 void
1375 _mesa_generate_mipmap_level(GLenum target,
1376                             GLenum datatype, GLuint comps,
1377                             GLint border,
1378                             GLint srcWidth, GLint srcHeight, GLint srcDepth,
1379                             const GLubyte *srcData,
1380                             GLint srcRowStride,
1381                             GLint dstWidth, GLint dstHeight, GLint dstDepth,
1382                             GLubyte *dstData,
1383                             GLint dstRowStride)
1384 {
1385    /*
1386     * We use simple 2x2 averaging to compute the next mipmap level.
1387     */
1388    switch (target) {
1389    case GL_TEXTURE_1D:
1390       make_1d_mipmap(datatype, comps, border,
1391                      srcWidth, srcData,
1392                      dstWidth, dstData);
1393       break;
1394    case GL_TEXTURE_2D:
1395    case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
1396    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
1397    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
1398    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
1399    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
1400    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
1401       make_2d_mipmap(datatype, comps, border,
1402                      srcWidth, srcHeight, srcData, srcRowStride,
1403                      dstWidth, dstHeight, dstData, dstRowStride);
1404       break;
1405    case GL_TEXTURE_3D:
1406       make_3d_mipmap(datatype, comps, border,
1407                      srcWidth, srcHeight, srcDepth,
1408                      srcData, srcRowStride,
1409                      dstWidth, dstHeight, dstDepth,
1410                      dstData, dstRowStride);
1411       break;
1412    case GL_TEXTURE_1D_ARRAY_EXT:
1413       make_1d_stack_mipmap(datatype, comps, border,
1414                            srcWidth, srcData, srcRowStride,
1415                            dstWidth, dstHeight,
1416                            dstData, dstRowStride);
1417       break;
1418    case GL_TEXTURE_2D_ARRAY_EXT:
1419       make_2d_stack_mipmap(datatype, comps, border,
1420                            srcWidth, srcHeight,
1421                            srcData, srcRowStride,
1422                            dstWidth, dstHeight,
1423                            dstDepth, dstData, dstRowStride);
1424       break;
1425    case GL_TEXTURE_RECTANGLE_NV:
1426       /* no mipmaps, do nothing */
1427       break;
1428    default:
1429       _mesa_problem(NULL, "bad dimensions in _mesa_generate_mipmaps");
1430       return;
1431    }
1432 }
1433
1434
1435 /**
1436  * compute next (level+1) image size
1437  * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1438  */
1439 static GLboolean
1440 next_mipmap_level_size(GLenum target, GLint border,
1441                        GLint srcWidth, GLint srcHeight, GLint srcDepth,
1442                        GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
1443 {
1444    if (srcWidth - 2 * border > 1) {
1445       *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1446    }
1447    else {
1448       *dstWidth = srcWidth; /* can't go smaller */
1449    }
1450
1451    if ((srcHeight - 2 * border > 1) && 
1452        (target != GL_TEXTURE_1D_ARRAY_EXT)) {
1453       *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1454    }
1455    else {
1456       *dstHeight = srcHeight; /* can't go smaller */
1457    }
1458
1459    if ((srcDepth - 2 * border > 1) &&
1460        (target != GL_TEXTURE_2D_ARRAY_EXT)) {
1461       *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1462    }
1463    else {
1464       *dstDepth = srcDepth; /* can't go smaller */
1465    }
1466
1467    if (*dstWidth == srcWidth &&
1468        *dstHeight == srcHeight &&
1469        *dstDepth == srcDepth) {
1470       return GL_FALSE;
1471    }
1472    else {
1473       return GL_TRUE;
1474    }
1475 }
1476
1477
1478
1479
1480 /**
1481  * For GL_SGIX_generate_mipmap:
1482  * Generate a complete set of mipmaps from texObj's base-level image.
1483  * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1484  */
1485 void
1486 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
1487                       struct gl_texture_object *texObj)
1488 {
1489    const struct gl_texture_image *srcImage;
1490    const struct gl_texture_format *convertFormat;
1491    const GLubyte *srcData = NULL;
1492    GLubyte *dstData = NULL;
1493    GLint level, maxLevels;
1494    GLenum datatype;
1495    GLuint comps;
1496
1497    ASSERT(texObj);
1498    /* XXX choose cube map face here??? */
1499    srcImage = texObj->Image[0][texObj->BaseLevel];
1500    ASSERT(srcImage);
1501
1502    maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
1503    ASSERT(maxLevels > 0);  /* bad target */
1504
1505    /* Find convertFormat - the format that do_row() will process */
1506    if (srcImage->IsCompressed) {
1507       /* setup for compressed textures */
1508       GLuint row;
1509       GLint  components, size;
1510       GLchan *dst;
1511
1512       assert(texObj->Target == GL_TEXTURE_2D ||
1513              texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
1514
1515       if (srcImage->_BaseFormat == GL_RGB) {
1516          convertFormat = &_mesa_texformat_rgb;
1517          components = 3;
1518       }
1519       else if (srcImage->_BaseFormat == GL_RGBA) {
1520          convertFormat = &_mesa_texformat_rgba;
1521          components = 4;
1522       }
1523       else {
1524          _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
1525          return;
1526       }
1527
1528       /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
1529       size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
1530          * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
1531       /* 20 extra bytes, just be safe when calling last FetchTexel */
1532       srcData = (GLubyte *) _mesa_malloc(size);
1533       if (!srcData) {
1534          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
1535          return;
1536       }
1537       dstData = (GLubyte *) _mesa_malloc(size / 2);  /* 1/4 would probably be OK */
1538       if (!dstData) {
1539          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
1540          _mesa_free((void *) srcData);
1541          return;
1542       }
1543
1544       /* decompress base image here */
1545       dst = (GLchan *) srcData;
1546       for (row = 0; row < srcImage->Height; row++) {
1547          GLuint col;
1548          for (col = 0; col < srcImage->Width; col++) {
1549             srcImage->FetchTexelc(srcImage, col, row, 0, dst);
1550             dst += components;
1551          }
1552       }
1553    }
1554    else {
1555       /* uncompressed */
1556       convertFormat = srcImage->TexFormat;
1557    }
1558
1559    _mesa_format_to_type_and_comps(convertFormat, &datatype, &comps);
1560
1561    for (level = texObj->BaseLevel; level < texObj->MaxLevel
1562            && level < maxLevels - 1; level++) {
1563       /* generate image[level+1] from image[level] */
1564       const struct gl_texture_image *srcImage;
1565       struct gl_texture_image *dstImage;
1566       GLint srcWidth, srcHeight, srcDepth;
1567       GLint dstWidth, dstHeight, dstDepth;
1568       GLint border, bytesPerTexel;
1569       GLboolean nextLevel;
1570
1571       /* get src image parameters */
1572       srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
1573       ASSERT(srcImage);
1574       srcWidth = srcImage->Width;
1575       srcHeight = srcImage->Height;
1576       srcDepth = srcImage->Depth;
1577       border = srcImage->Border;
1578
1579       nextLevel = next_mipmap_level_size(target, border,
1580                                          srcWidth, srcHeight, srcDepth,
1581                                          &dstWidth, &dstHeight, &dstDepth);
1582       if (!nextLevel) {
1583          /* all done */
1584          if (srcImage->IsCompressed) {
1585             _mesa_free((void *) srcData);
1586             _mesa_free(dstData);
1587          }
1588          return;
1589       }
1590
1591       /* get dest gl_texture_image */
1592       dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
1593       if (!dstImage) {
1594          _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1595          return;
1596       }
1597
1598       if (dstImage->ImageOffsets)
1599          _mesa_free(dstImage->ImageOffsets);
1600
1601       /* Free old image data */
1602       if (dstImage->Data)
1603          ctx->Driver.FreeTexImageData(ctx, dstImage);
1604
1605       /* initialize new image */
1606       _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
1607                                  dstDepth, border, srcImage->InternalFormat);
1608       dstImage->DriverData = NULL;
1609       dstImage->TexFormat = srcImage->TexFormat;
1610       dstImage->FetchTexelc = srcImage->FetchTexelc;
1611       dstImage->FetchTexelf = srcImage->FetchTexelf;
1612       dstImage->IsCompressed = srcImage->IsCompressed;
1613       if (dstImage->IsCompressed) {
1614          dstImage->CompressedSize
1615             = ctx->Driver.CompressedTextureSize(ctx, dstImage->Width,
1616                                               dstImage->Height,
1617                                               dstImage->Depth,
1618                                               dstImage->TexFormat->MesaFormat);
1619          ASSERT(dstImage->CompressedSize > 0);
1620       }
1621
1622       ASSERT(dstImage->TexFormat);
1623       ASSERT(dstImage->FetchTexelc);
1624       ASSERT(dstImage->FetchTexelf);
1625
1626       /* Alloc new teximage data buffer.
1627        * Setup src and dest data pointers.
1628        */
1629       if (dstImage->IsCompressed) {
1630          dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize);
1631          if (!dstImage->Data) {
1632             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1633             return;
1634          }
1635          /* srcData and dstData are already set */
1636          ASSERT(srcData);
1637          ASSERT(dstData);
1638       }
1639       else {
1640          bytesPerTexel = dstImage->TexFormat->TexelBytes;
1641          ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
1642          dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight
1643                                                 * dstDepth * bytesPerTexel);
1644          if (!dstImage->Data) {
1645             _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1646             return;
1647          }
1648          srcData = (const GLubyte *) srcImage->Data;
1649          dstData = (GLubyte *) dstImage->Data;
1650       }
1651
1652       _mesa_generate_mipmap_level(target, datatype, comps, border,
1653                                   srcWidth, srcHeight, srcDepth, 
1654                                   srcData, srcImage->RowStride,
1655                                   dstWidth, dstHeight, dstDepth, 
1656                                   dstData, dstImage->RowStride);
1657
1658
1659       if (dstImage->IsCompressed) {
1660          GLubyte *temp;
1661          /* compress image from dstData into dstImage->Data */
1662          const GLenum srcFormat = convertFormat->BaseFormat;
1663          GLint dstRowStride
1664             = _mesa_compressed_row_stride(dstImage->TexFormat->MesaFormat, dstWidth);
1665          ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
1666          dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat,
1667                                          dstImage->TexFormat,
1668                                          dstImage->Data,
1669                                          0, 0, 0, /* dstX/Y/Zoffset */
1670                                          dstRowStride, 0, /* strides */
1671                                          dstWidth, dstHeight, 1, /* size */
1672                                          srcFormat, CHAN_TYPE,
1673                                          dstData, /* src data, actually */
1674                                          &ctx->DefaultPacking);
1675          /* swap src and dest pointers */
1676          temp = (GLubyte *) srcData;
1677          srcData = dstData;
1678          dstData = temp;
1679       }
1680
1681    } /* loop over mipmap levels */
1682 }
1683
1684
1685 /**
1686  * Helper function for drivers which need to rescale texture images to
1687  * certain aspect ratios.
1688  * Nearest filtering only (for broken hardware that can't support
1689  * all aspect ratios).  This can be made a lot faster, but I don't
1690  * really care enough...
1691  */
1692 void
1693 _mesa_rescale_teximage2d(GLuint bytesPerPixel,
1694                          GLuint srcStrideInPixels,
1695                          GLuint dstRowStride,
1696                          GLint srcWidth, GLint srcHeight,
1697                          GLint dstWidth, GLint dstHeight,
1698                          const GLvoid *srcImage, GLvoid *dstImage)
1699 {
1700    GLint row, col;
1701
1702 #define INNER_LOOP( TYPE, HOP, WOP )                                    \
1703    for ( row = 0 ; row < dstHeight ; row++ ) {                          \
1704       GLint srcRow = row HOP hScale;                                    \
1705       for ( col = 0 ; col < dstWidth ; col++ ) {                        \
1706          GLint srcCol = col WOP wScale;                                 \
1707          dst[col] = src[srcRow * srcStrideInPixels + srcCol];           \
1708       }                                                                 \
1709       dst = (TYPE *) ((GLubyte *) dst + dstRowStride);                  \
1710    }                                                                    \
1711
1712 #define RESCALE_IMAGE( TYPE )                                           \
1713 do {                                                                    \
1714    const TYPE *src = (const TYPE *)srcImage;                            \
1715    TYPE *dst = (TYPE *)dstImage;                                        \
1716                                                                         \
1717    if ( srcHeight < dstHeight ) {                                       \
1718       const GLint hScale = dstHeight / srcHeight;                       \
1719       if ( srcWidth < dstWidth ) {                                      \
1720          const GLint wScale = dstWidth / srcWidth;                      \
1721          INNER_LOOP( TYPE, /, / );                                      \
1722       }                                                                 \
1723       else {                                                            \
1724          const GLint wScale = srcWidth / dstWidth;                      \
1725          INNER_LOOP( TYPE, /, * );                                      \
1726       }                                                                 \
1727    }                                                                    \
1728    else {                                                               \
1729       const GLint hScale = srcHeight / dstHeight;                       \
1730       if ( srcWidth < dstWidth ) {                                      \
1731          const GLint wScale = dstWidth / srcWidth;                      \
1732          INNER_LOOP( TYPE, *, / );                                      \
1733       }                                                                 \
1734       else {                                                            \
1735          const GLint wScale = srcWidth / dstWidth;                      \
1736          INNER_LOOP( TYPE, *, * );                                      \
1737       }                                                                 \
1738    }                                                                    \
1739 } while (0)
1740
1741    switch ( bytesPerPixel ) {
1742    case 4:
1743       RESCALE_IMAGE( GLuint );
1744       break;
1745
1746    case 2:
1747       RESCALE_IMAGE( GLushort );
1748       break;
1749
1750    case 1:
1751       RESCALE_IMAGE( GLubyte );
1752       break;
1753    default:
1754       _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
1755    }
1756 }
1757
1758
1759 /**
1760  * Upscale an image by replication, not (typical) stretching.
1761  * We use this when the image width or height is less than a
1762  * certain size (4, 8) and we need to upscale an image.
1763  */
1764 void
1765 _mesa_upscale_teximage2d(GLsizei inWidth, GLsizei inHeight,
1766                          GLsizei outWidth, GLsizei outHeight,
1767                          GLint comps, const GLchan *src, GLint srcRowStride,
1768                          GLchan *dest )
1769 {
1770    GLint i, j, k;
1771
1772    ASSERT(outWidth >= inWidth);
1773    ASSERT(outHeight >= inHeight);
1774 #if 0
1775    ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
1776    ASSERT((outWidth & 3) == 0);
1777    ASSERT((outHeight & 3) == 0);
1778 #endif
1779
1780    for (i = 0; i < outHeight; i++) {
1781       const GLint ii = i % inHeight;
1782       for (j = 0; j < outWidth; j++) {
1783          const GLint jj = j % inWidth;
1784          for (k = 0; k < comps; k++) {
1785             dest[(i * outWidth + j) * comps + k]
1786                = src[ii * srcRowStride + jj * comps + k];
1787          }
1788       }
1789    }
1790 }
1791