Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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