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