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