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