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