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