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