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