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