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