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