1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /**
27 * \file mipmap.c mipmap generation and teximage resizing functions.
28 */
29
30 #include "imports.h"
31 #include "formats.h"
32 #include "glformats.h"
33 #include "mipmap.h"
34 #include "mtypes.h"
35 #include "teximage.h"
36 #include "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
bytes_per_pixel(GLenum datatype,GLuint comps)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
do_row(GLenum datatype,GLuint comps,GLint srcWidth,const GLvoid * srcRowA,const GLvoid * srcRowB,GLint dstWidth,GLvoid * dstRow)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
do_row_3D(GLenum datatype,GLuint comps,GLint srcWidth,const GLvoid * srcRowA,const GLvoid * srcRowB,const GLvoid * srcRowC,const GLvoid * srcRowD,GLint dstWidth,GLvoid * dstRow)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
make_1d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,const GLubyte * srcPtr,GLint dstWidth,GLubyte * dstPtr)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
make_2d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,const GLubyte * srcPtr,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLubyte * dstPtr,GLint dstRowStride)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
make_3d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,const GLubyte ** srcPtr,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLint dstDepth,GLubyte ** dstPtr,GLint dstRowStride)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 bytesPerSrcRow, bytesPerDstRow;
1552 GLint srcImageOffset, srcRowOffset;
1553
1554 (void) srcDepthNB; /* silence warnings */
1555
1556
1557 bytesPerSrcImage = srcWidth * srcHeight * bpt;
1558 bytesPerDstImage = dstWidth * dstHeight * bpt;
1559
1560 bytesPerSrcRow = srcWidth * bpt;
1561 bytesPerDstRow = dstWidth * bpt;
1562
1563 /* Offset between adjacent src images to be averaged together */
1564 srcImageOffset = (srcDepth == dstDepth) ? 0 : 1;
1565
1566 /* Offset between adjacent src rows to be averaged together */
1567 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
1568
1569 /*
1570 * Need to average together up to 8 src pixels for each dest pixel.
1571 * Break that down into 3 operations:
1572 * 1. take two rows from source image and average them together.
1573 * 2. take two rows from next source image and average them together.
1574 * 3. take the two averaged rows and average them for the final dst row.
1575 */
1576
1577 /*
1578 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1579 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1580 */
1581
1582 for (img = 0; img < dstDepthNB; img++) {
1583 /* first source image pointer, skipping border */
1584 const GLubyte *imgSrcA = srcPtr[img * 2 + border]
1585 + bytesPerSrcRow * border + bpt * border;
1586 /* second source image pointer, skipping border */
1587 const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border]
1588 + bytesPerSrcRow * border + bpt * border;
1589
1590 /* address of the dest image, skipping border */
1591 GLubyte *imgDst = dstPtr[img + border]
1592 + bytesPerDstRow * border + bpt * border;
1593
1594 /* setup the four source row pointers and the dest row pointer */
1595 const GLubyte *srcImgARowA = imgSrcA;
1596 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
1597 const GLubyte *srcImgBRowA = imgSrcB;
1598 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1599 GLubyte *dstImgRow = imgDst;
1600
1601 for (row = 0; row < dstHeightNB; row++) {
1602 do_row_3D(datatype, comps, srcWidthNB,
1603 srcImgARowA, srcImgARowB,
1604 srcImgBRowA, srcImgBRowB,
1605 dstWidthNB, dstImgRow);
1606
1607 /* advance to next rows */
1608 srcImgARowA += bytesPerSrcRow + srcRowOffset;
1609 srcImgARowB += bytesPerSrcRow + srcRowOffset;
1610 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
1611 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
1612 dstImgRow += bytesPerDstRow;
1613 }
1614 }
1615
1616
1617 /* Luckily we can leverage the make_2d_mipmap() function here! */
1618 if (border > 0) {
1619 /* do front border image */
1620 make_2d_mipmap(datatype, comps, 1,
1621 srcWidth, srcHeight, srcPtr[0], srcRowStride,
1622 dstWidth, dstHeight, dstPtr[0], dstRowStride);
1623 /* do back border image */
1624 make_2d_mipmap(datatype, comps, 1,
1625 srcWidth, srcHeight, srcPtr[srcDepth - 1], srcRowStride,
1626 dstWidth, dstHeight, dstPtr[dstDepth - 1], dstRowStride);
1627
1628 /* do four remaining border edges that span the image slices */
1629 if (srcDepth == dstDepth) {
1630 /* just copy border pixels from src to dst */
1631 for (img = 0; img < dstDepthNB; img++) {
1632 const GLubyte *src;
1633 GLubyte *dst;
1634
1635 /* do border along [img][row=0][col=0] */
1636 src = srcPtr[img * 2];
1637 dst = dstPtr[img];
1638 memcpy(dst, src, bpt);
1639
1640 /* do border along [img][row=dstHeight-1][col=0] */
1641 src = srcPtr[img * 2] + (srcHeight - 1) * bytesPerSrcRow;
1642 dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
1643 memcpy(dst, src, bpt);
1644
1645 /* do border along [img][row=0][col=dstWidth-1] */
1646 src = srcPtr[img * 2] + (srcWidth - 1) * bpt;
1647 dst = dstPtr[img] + (dstWidth - 1) * bpt;
1648 memcpy(dst, src, bpt);
1649
1650 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1651 src = srcPtr[img * 2] + (bytesPerSrcImage - bpt);
1652 dst = dstPtr[img] + (bytesPerDstImage - bpt);
1653 memcpy(dst, src, bpt);
1654 }
1655 }
1656 else {
1657 /* average border pixels from adjacent src image pairs */
1658 ASSERT(srcDepthNB == 2 * dstDepthNB);
1659 for (img = 0; img < dstDepthNB; img++) {
1660 const GLubyte *srcA, *srcB;
1661 GLubyte *dst;
1662
1663 /* do border along [img][row=0][col=0] */
1664 srcA = srcPtr[img * 2 + 0];
1665 srcB = srcPtr[img * 2 + srcImageOffset];
1666 dst = dstPtr[img];
1667 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1668
1669 /* do border along [img][row=dstHeight-1][col=0] */
1670 srcA = srcPtr[img * 2 + 0]
1671 + (srcHeight - 1) * bytesPerSrcRow;
1672 srcB = srcPtr[img * 2 + srcImageOffset]
1673 + (srcHeight - 1) * bytesPerSrcRow;
1674 dst = dstPtr[img] + (dstHeight - 1) * bytesPerDstRow;
1675 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1676
1677 /* do border along [img][row=0][col=dstWidth-1] */
1678 srcA = srcPtr[img * 2 + 0] + (srcWidth - 1) * bpt;
1679 srcB = srcPtr[img * 2 + srcImageOffset] + (srcWidth - 1) * bpt;
1680 dst = dstPtr[img] + (dstWidth - 1) * bpt;
1681 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1682
1683 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1684 srcA = srcPtr[img * 2 + 0] + (bytesPerSrcImage - bpt);
1685 srcB = srcPtr[img * 2 + srcImageOffset] + (bytesPerSrcImage - bpt);
1686 dst = dstPtr[img] + (bytesPerDstImage - bpt);
1687 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1688 }
1689 }
1690 }
1691 }
1692
1693
1694 /**
1695 * Down-sample a texture image to produce the next lower mipmap level.
1696 * \param comps components per texel (1, 2, 3 or 4)
1697 * \param srcData array[slice] of pointers to source image slices
1698 * \param dstData array[slice] of pointers to dest image slices
1699 * \param srcRowStride stride between source rows, in bytes
1700 * \param dstRowStride stride between destination rows, in bytes
1701 */
1702 void
_mesa_generate_mipmap_level(GLenum target,GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,const GLubyte ** srcData,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLint dstDepth,GLubyte ** dstData,GLint dstRowStride)1703 _mesa_generate_mipmap_level(GLenum target,
1704 GLenum datatype, GLuint comps,
1705 GLint border,
1706 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1707 const GLubyte **srcData,
1708 GLint srcRowStride,
1709 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1710 GLubyte **dstData,
1711 GLint dstRowStride)
1712 {
1713 int i;
1714
1715 switch (target) {
1716 case GL_TEXTURE_1D:
1717 make_1d_mipmap(datatype, comps, border,
1718 srcWidth, srcData[0],
1719 dstWidth, dstData[0]);
1720 break;
1721 case GL_TEXTURE_2D:
1722 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
1723 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
1724 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
1725 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
1726 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
1727 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
1728 make_2d_mipmap(datatype, comps, border,
1729 srcWidth, srcHeight, srcData[0], srcRowStride,
1730 dstWidth, dstHeight, dstData[0], dstRowStride);
1731 break;
1732 case GL_TEXTURE_3D:
1733 make_3d_mipmap(datatype, comps, border,
1734 srcWidth, srcHeight, srcDepth,
1735 srcData, srcRowStride,
1736 dstWidth, dstHeight, dstDepth,
1737 dstData, dstRowStride);
1738 break;
1739 case GL_TEXTURE_1D_ARRAY_EXT:
1740 assert(srcHeight == 1);
1741 assert(dstHeight == 1);
1742 for (i = 0; i < dstDepth; i++) {
1743 make_1d_mipmap(datatype, comps, border,
1744 srcWidth, srcData[i],
1745 dstWidth, dstData[i]);
1746 }
1747 break;
1748 case GL_TEXTURE_2D_ARRAY_EXT:
1749 for (i = 0; i < dstDepth; i++) {
1750 make_2d_mipmap(datatype, comps, border,
1751 srcWidth, srcHeight, srcData[i], srcRowStride,
1752 dstWidth, dstHeight, dstData[i], dstRowStride);
1753 }
1754 break;
1755 case GL_TEXTURE_RECTANGLE_NV:
1756 case GL_TEXTURE_EXTERNAL_OES:
1757 /* no mipmaps, do nothing */
1758 break;
1759 default:
1760 _mesa_problem(NULL, "bad tex target in _mesa_generate_mipmaps");
1761 return;
1762 }
1763 }
1764
1765
1766 /**
1767 * compute next (level+1) image size
1768 * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1769 */
1770 static GLboolean
next_mipmap_level_size(GLenum target,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,GLint * dstWidth,GLint * dstHeight,GLint * dstDepth)1771 next_mipmap_level_size(GLenum target, GLint border,
1772 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1773 GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
1774 {
1775 if (srcWidth - 2 * border > 1) {
1776 *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1777 }
1778 else {
1779 *dstWidth = srcWidth; /* can't go smaller */
1780 }
1781
1782 if ((srcHeight - 2 * border > 1) &&
1783 (target != GL_TEXTURE_1D_ARRAY_EXT)) {
1784 *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1785 }
1786 else {
1787 *dstHeight = srcHeight; /* can't go smaller */
1788 }
1789
1790 if ((srcDepth - 2 * border > 1) &&
1791 (target != GL_TEXTURE_2D_ARRAY_EXT)) {
1792 *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1793 }
1794 else {
1795 *dstDepth = srcDepth; /* can't go smaller */
1796 }
1797
1798 if (*dstWidth == srcWidth &&
1799 *dstHeight == srcHeight &&
1800 *dstDepth == srcDepth) {
1801 return GL_FALSE;
1802 }
1803 else {
1804 return GL_TRUE;
1805 }
1806 }
1807
1808
1809 /**
1810 * Helper function for mipmap generation.
1811 * Make sure the specified destination mipmap level is the right size/format
1812 * for mipmap generation. If not, (re) allocate it.
1813 * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop
1814 */
1815 GLboolean
_mesa_prepare_mipmap_level(struct gl_context * ctx,struct gl_texture_object * texObj,GLuint level,GLsizei width,GLsizei height,GLsizei depth,GLsizei border,GLenum intFormat,gl_format format)1816 _mesa_prepare_mipmap_level(struct gl_context *ctx,
1817 struct gl_texture_object *texObj, GLuint level,
1818 GLsizei width, GLsizei height, GLsizei depth,
1819 GLsizei border, GLenum intFormat, gl_format format)
1820 {
1821 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1822 GLuint face;
1823
1824 if (texObj->Immutable) {
1825 /* The texture was created with glTexStorage() so the number/size of
1826 * mipmap levels is fixed and the storage for all images is already
1827 * allocated.
1828 */
1829 if (!texObj->Image[0][level]) {
1830 /* No more levels to create - we're done */
1831 return GL_FALSE;
1832 }
1833 else {
1834 /* Nothing to do - the texture memory must have already been
1835 * allocated to the right size so we're all set.
1836 */
1837 return GL_TRUE;
1838 }
1839 }
1840
1841 for (face = 0; face < numFaces; face++) {
1842 struct gl_texture_image *dstImage;
1843 GLenum target;
1844
1845 if (numFaces == 1)
1846 target = texObj->Target;
1847 else
1848 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
1849
1850 dstImage = _mesa_get_tex_image(ctx, texObj, target, level);
1851 if (!dstImage) {
1852 /* out of memory */
1853 return GL_FALSE;
1854 }
1855
1856 if (dstImage->Width != width ||
1857 dstImage->Height != height ||
1858 dstImage->Depth != depth ||
1859 dstImage->Border != border ||
1860 dstImage->InternalFormat != intFormat ||
1861 dstImage->TexFormat != format) {
1862 /* need to (re)allocate image */
1863 ctx->Driver.FreeTextureImageBuffer(ctx, dstImage);
1864
1865 _mesa_init_teximage_fields(ctx, dstImage,
1866 width, height, depth,
1867 border, intFormat, format);
1868
1869 ctx->Driver.AllocTextureImageBuffer(ctx, dstImage);
1870
1871 /* in case the mipmap level is part of an FBO: */
1872 _mesa_update_fbo_texture(ctx, texObj, face, level);
1873
1874 ctx->NewState |= _NEW_TEXTURE;
1875 }
1876 }
1877
1878 return GL_TRUE;
1879 }
1880
1881
1882 static void
generate_mipmap_uncompressed(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,const struct gl_texture_image * srcImage,GLuint maxLevel)1883 generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
1884 struct gl_texture_object *texObj,
1885 const struct gl_texture_image *srcImage,
1886 GLuint maxLevel)
1887 {
1888 GLint level;
1889 GLenum datatype;
1890 GLuint comps;
1891
1892 _mesa_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps);
1893
1894 for (level = texObj->BaseLevel; level < maxLevel; level++) {
1895 /* generate image[level+1] from image[level] */
1896 struct gl_texture_image *srcImage, *dstImage;
1897 GLint srcRowStride, dstRowStride;
1898 GLint srcWidth, srcHeight, srcDepth;
1899 GLint dstWidth, dstHeight, dstDepth;
1900 GLint border;
1901 GLint slice;
1902 GLboolean nextLevel;
1903 GLubyte **srcMaps, **dstMaps;
1904 GLboolean success = GL_TRUE;
1905
1906 /* get src image parameters */
1907 srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
1908 ASSERT(srcImage);
1909 srcWidth = srcImage->Width;
1910 srcHeight = srcImage->Height;
1911 srcDepth = srcImage->Depth;
1912 border = srcImage->Border;
1913
1914 nextLevel = next_mipmap_level_size(target, border,
1915 srcWidth, srcHeight, srcDepth,
1916 &dstWidth, &dstHeight, &dstDepth);
1917 if (!nextLevel)
1918 return;
1919
1920 if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1,
1921 dstWidth, dstHeight, dstDepth,
1922 border, srcImage->InternalFormat,
1923 srcImage->TexFormat)) {
1924 return;
1925 }
1926
1927 /* get dest gl_texture_image */
1928 dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
1929 if (!dstImage) {
1930 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1931 return;
1932 }
1933
1934 if (target == GL_TEXTURE_1D_ARRAY) {
1935 srcDepth = srcHeight;
1936 dstDepth = dstHeight;
1937 srcHeight = 1;
1938 dstHeight = 1;
1939 }
1940
1941 /* Map src texture image slices */
1942 srcMaps = (GLubyte **) calloc(srcDepth, sizeof(GLubyte *));
1943 if (srcMaps) {
1944 for (slice = 0; slice < srcDepth; slice++) {
1945 ctx->Driver.MapTextureImage(ctx, srcImage, slice,
1946 0, 0, srcWidth, srcHeight,
1947 GL_MAP_READ_BIT,
1948 &srcMaps[slice], &srcRowStride);
1949 if (!srcMaps[slice]) {
1950 success = GL_FALSE;
1951 break;
1952 }
1953 }
1954 }
1955 else {
1956 success = GL_FALSE;
1957 }
1958
1959 /* Map dst texture image slices */
1960 dstMaps = (GLubyte **) calloc(dstDepth, sizeof(GLubyte *));
1961 if (dstMaps) {
1962 for (slice = 0; slice < dstDepth; slice++) {
1963 ctx->Driver.MapTextureImage(ctx, dstImage, slice,
1964 0, 0, dstWidth, dstHeight,
1965 GL_MAP_WRITE_BIT,
1966 &dstMaps[slice], &dstRowStride);
1967 if (!dstMaps[slice]) {
1968 success = GL_FALSE;
1969 break;
1970 }
1971 }
1972 }
1973 else {
1974 success = GL_FALSE;
1975 }
1976
1977 if (success) {
1978 /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */
1979 _mesa_generate_mipmap_level(target, datatype, comps, border,
1980 srcWidth, srcHeight, srcDepth,
1981 (const GLubyte **) srcMaps, srcRowStride,
1982 dstWidth, dstHeight, dstDepth,
1983 dstMaps, dstRowStride);
1984 }
1985
1986 /* Unmap src image slices */
1987 if (srcMaps) {
1988 for (slice = 0; slice < srcDepth; slice++) {
1989 if (srcMaps[slice]) {
1990 ctx->Driver.UnmapTextureImage(ctx, srcImage, slice);
1991 }
1992 }
1993 free(srcMaps);
1994 }
1995
1996 /* Unmap dst image slices */
1997 if (dstMaps) {
1998 for (slice = 0; slice < dstDepth; slice++) {
1999 if (dstMaps[slice]) {
2000 ctx->Driver.UnmapTextureImage(ctx, dstImage, slice);
2001 }
2002 }
2003 free(dstMaps);
2004 }
2005
2006 if (!success) {
2007 _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation");
2008 break;
2009 }
2010 } /* loop over mipmap levels */
2011 }
2012
2013
2014 static void
generate_mipmap_compressed(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,struct gl_texture_image * srcImage,GLuint maxLevel)2015 generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
2016 struct gl_texture_object *texObj,
2017 struct gl_texture_image *srcImage,
2018 GLuint maxLevel)
2019 {
2020 GLint level;
2021 gl_format temp_format;
2022 GLint components;
2023 GLuint temp_src_stride; /* in bytes */
2024 GLubyte *temp_src = NULL, *temp_dst = NULL;
2025 GLenum temp_datatype;
2026 GLenum temp_base_format;
2027
2028 /* only two types of compressed textures at this time */
2029 assert(texObj->Target == GL_TEXTURE_2D ||
2030 texObj->Target == GL_TEXTURE_CUBE_MAP_ARB);
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 /* Revisit this if we get compressed formats with >8 bits per component */
2042 if (_mesa_get_format_datatype(srcImage->TexFormat)
2043 == GL_SIGNED_NORMALIZED) {
2044 temp_datatype = GL_BYTE;
2045 }
2046 else {
2047 temp_datatype = GL_UNSIGNED_BYTE;
2048 }
2049
2050 temp_base_format = _mesa_get_format_base_format(temp_format);
2051
2052
2053 /* allocate storage for the temporary, uncompressed image */
2054 /* 20 extra bytes, just be safe when calling last FetchTexel */
2055 temp_src_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
2056 temp_src = (GLubyte *) malloc(temp_src_stride * srcImage->Height + 20);
2057 if (!temp_src) {
2058 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
2059 return;
2060 }
2061
2062 /* decompress base image to the temporary */
2063 {
2064 /* save pixel packing mode */
2065 struct gl_pixelstore_attrib save = ctx->Pack;
2066 /* use default/tight packing parameters */
2067 ctx->Pack = ctx->DefaultPacking;
2068
2069 /* Get the uncompressed image */
2070 assert(srcImage->Level == texObj->BaseLevel);
2071 ctx->Driver.GetTexImage(ctx,
2072 temp_base_format, temp_datatype,
2073 temp_src, srcImage);
2074 /* restore packing mode */
2075 ctx->Pack = save;
2076 }
2077
2078
2079 for (level = texObj->BaseLevel; level < maxLevel; level++) {
2080 /* generate image[level+1] from image[level] */
2081 const struct gl_texture_image *srcImage;
2082 struct gl_texture_image *dstImage;
2083 GLint srcWidth, srcHeight, srcDepth;
2084 GLint dstWidth, dstHeight, dstDepth;
2085 GLint border;
2086 GLboolean nextLevel;
2087 GLuint temp_dst_stride; /* in bytes */
2088
2089 /* get src image parameters */
2090 srcImage = _mesa_select_tex_image(ctx, texObj, target, level);
2091 ASSERT(srcImage);
2092 srcWidth = srcImage->Width;
2093 srcHeight = srcImage->Height;
2094 srcDepth = srcImage->Depth;
2095 border = srcImage->Border;
2096
2097 nextLevel = next_mipmap_level_size(target, border,
2098 srcWidth, srcHeight, srcDepth,
2099 &dstWidth, &dstHeight, &dstDepth);
2100 if (!nextLevel)
2101 break;
2102
2103 temp_dst_stride = _mesa_format_row_stride(temp_format, dstWidth);
2104 if (!temp_dst) {
2105 temp_dst = (GLubyte *) malloc(temp_dst_stride * dstHeight);
2106 if (!temp_dst) {
2107 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
2108 break;
2109 }
2110 }
2111
2112 /* get dest gl_texture_image */
2113 dstImage = _mesa_get_tex_image(ctx, texObj, target, level + 1);
2114 if (!dstImage) {
2115 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
2116 free(temp_dst);
2117 return;
2118 }
2119
2120 /* rescale src image to dest image */
2121 _mesa_generate_mipmap_level(target, temp_datatype, components, border,
2122 srcWidth, srcHeight, srcDepth,
2123 (const GLubyte **) &temp_src,
2124 temp_src_stride,
2125 dstWidth, dstHeight, dstDepth,
2126 &temp_dst, temp_dst_stride);
2127
2128 if (!_mesa_prepare_mipmap_level(ctx, texObj, level + 1,
2129 dstWidth, dstHeight, dstDepth,
2130 border, srcImage->InternalFormat,
2131 srcImage->TexFormat)) {
2132 free(temp_dst);
2133 return;
2134 }
2135
2136 /* The image space was allocated above so use glTexSubImage now */
2137 ctx->Driver.TexSubImage(ctx, 2, dstImage,
2138 0, 0, 0, dstWidth, dstHeight, 1,
2139 temp_base_format, temp_datatype,
2140 temp_dst, &ctx->DefaultPacking);
2141
2142 /* swap src and dest pointers */
2143 {
2144 GLubyte *temp = temp_src;
2145 temp_src = temp_dst;
2146 temp_dst = temp;
2147 temp_src_stride = temp_dst_stride;
2148 }
2149 } /* loop over mipmap levels */
2150
2151 free(temp_src);
2152 free(temp_dst);
2153 }
2154
2155 /**
2156 * Automatic mipmap generation.
2157 * This is the fallback/default function for ctx->Driver.GenerateMipmap().
2158 * Generate a complete set of mipmaps from texObj's BaseLevel image.
2159 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
2160 * For cube maps, target will be one of
2161 * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
2162 */
2163 void
_mesa_generate_mipmap(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj)2164 _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
2165 struct gl_texture_object *texObj)
2166 {
2167 struct gl_texture_image *srcImage;
2168 GLint maxLevel;
2169
2170 ASSERT(texObj);
2171 srcImage = _mesa_select_tex_image(ctx, texObj, target, texObj->BaseLevel);
2172 ASSERT(srcImage);
2173
2174 maxLevel = _mesa_max_texture_levels(ctx, texObj->Target) - 1;
2175 ASSERT(maxLevel >= 0); /* bad target */
2176
2177 maxLevel = MIN2(maxLevel, texObj->MaxLevel);
2178
2179 if (_mesa_is_format_compressed(srcImage->TexFormat)) {
2180 generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel);
2181 } else {
2182 generate_mipmap_uncompressed(ctx, target, texObj, srcImage, maxLevel);
2183 }
2184 }
2185