Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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