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