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