2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
27 * \file mipmap.c mipmap generation and teximage resizing functions.
32 #include "texcompress.h"
33 #include "texformat.h"
40 bytes_per_pixel(GLenum datatype
, GLuint comps
)
42 GLint b
= _mesa_sizeof_packed_type(datatype
);
45 if (_mesa_type_is_packed(datatype
))
53 * \name Support macros for do_row and do_row_3d
55 * The macro madness is here for two reasons. First, it compacts the code
56 * slightly. Second, it makes it much easier to adjust the specifics of the
57 * filter to tune the rounding characteristics.
60 #define DECLARE_ROW_POINTERS(t, e) \
61 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
62 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
63 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
64 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
65 t(*dst)[e] = (t(*)[e]) dstRow
67 #define DECLARE_ROW_POINTERS0(t) \
68 const t *rowA = (const t *) srcRowA; \
69 const t *rowB = (const t *) srcRowB; \
70 const t *rowC = (const t *) srcRowC; \
71 const t *rowD = (const t *) srcRowD; \
74 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
75 ((unsigned) Aj + (unsigned) Ak \
76 + (unsigned) Bj + (unsigned) Bk \
77 + (unsigned) Cj + (unsigned) Ck \
78 + (unsigned) Dj + (unsigned) Dk \
81 #define FILTER_3D(e) \
83 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
84 rowB[j][e], rowB[k][e], \
85 rowC[j][e], rowC[k][e], \
86 rowD[j][e], rowD[k][e]); \
89 #define FILTER_F_3D(e) \
91 dst[i][e] = (rowA[j][e] + rowA[k][e] \
92 + rowB[j][e] + rowB[k][e] \
93 + rowC[j][e] + rowC[k][e] \
94 + rowD[j][e] + rowD[k][e]) * 0.125F; \
97 #define FILTER_HF_3D(e) \
99 const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
100 const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
101 const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
102 const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
103 const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
104 const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
105 const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
106 const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
107 dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
114 * Average together two rows of a source image to produce a single new
115 * row in the dest image. It's legal for the two source rows to point
116 * to the same data. The source width must be equal to either the
117 * dest width or two times the dest width.
118 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
119 * \param comps number of components per pixel (1..4)
122 do_row(GLenum datatype
, GLuint comps
, GLint srcWidth
,
123 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
124 GLint dstWidth
, GLvoid
*dstRow
)
126 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
127 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
132 /* This assertion is no longer valid with non-power-of-2 textures
133 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
136 if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 4) {
138 const GLubyte(*rowA
)[4] = (const GLubyte(*)[4]) srcRowA
;
139 const GLubyte(*rowB
)[4] = (const GLubyte(*)[4]) srcRowB
;
140 GLubyte(*dst
)[4] = (GLubyte(*)[4]) dstRow
;
141 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
142 i
++, j
+= colStride
, k
+= colStride
) {
143 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
144 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
145 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
146 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
149 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 3) {
151 const GLubyte(*rowA
)[3] = (const GLubyte(*)[3]) srcRowA
;
152 const GLubyte(*rowB
)[3] = (const GLubyte(*)[3]) srcRowB
;
153 GLubyte(*dst
)[3] = (GLubyte(*)[3]) dstRow
;
154 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
155 i
++, j
+= colStride
, k
+= colStride
) {
156 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
157 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
158 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
161 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 2) {
163 const GLubyte(*rowA
)[2] = (const GLubyte(*)[2]) srcRowA
;
164 const GLubyte(*rowB
)[2] = (const GLubyte(*)[2]) srcRowB
;
165 GLubyte(*dst
)[2] = (GLubyte(*)[2]) dstRow
;
166 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
167 i
++, j
+= colStride
, k
+= colStride
) {
168 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
169 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
172 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 1) {
174 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
175 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
176 GLubyte
*dst
= (GLubyte
*) dstRow
;
177 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
178 i
++, j
+= colStride
, k
+= colStride
) {
179 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
183 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 4) {
185 const GLushort(*rowA
)[4] = (const GLushort(*)[4]) srcRowA
;
186 const GLushort(*rowB
)[4] = (const GLushort(*)[4]) srcRowB
;
187 GLushort(*dst
)[4] = (GLushort(*)[4]) dstRow
;
188 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
189 i
++, j
+= colStride
, k
+= colStride
) {
190 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
191 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
192 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
193 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
196 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 3) {
198 const GLushort(*rowA
)[3] = (const GLushort(*)[3]) srcRowA
;
199 const GLushort(*rowB
)[3] = (const GLushort(*)[3]) srcRowB
;
200 GLushort(*dst
)[3] = (GLushort(*)[3]) dstRow
;
201 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
202 i
++, j
+= colStride
, k
+= colStride
) {
203 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
204 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
205 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
208 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 2) {
210 const GLushort(*rowA
)[2] = (const GLushort(*)[2]) srcRowA
;
211 const GLushort(*rowB
)[2] = (const GLushort(*)[2]) srcRowB
;
212 GLushort(*dst
)[2] = (GLushort(*)[2]) dstRow
;
213 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
214 i
++, j
+= colStride
, k
+= colStride
) {
215 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
216 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
219 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 1) {
221 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
222 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
223 GLushort
*dst
= (GLushort
*) dstRow
;
224 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
225 i
++, j
+= colStride
, k
+= colStride
) {
226 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
229 else if (datatype
== GL_FLOAT
&& comps
== 4) {
231 const GLfloat(*rowA
)[4] = (const GLfloat(*)[4]) srcRowA
;
232 const GLfloat(*rowB
)[4] = (const GLfloat(*)[4]) srcRowB
;
233 GLfloat(*dst
)[4] = (GLfloat(*)[4]) dstRow
;
234 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
235 i
++, j
+= colStride
, k
+= colStride
) {
236 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
237 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
238 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
239 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
240 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
241 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
242 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
243 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
246 else if (datatype
== GL_FLOAT
&& comps
== 3) {
248 const GLfloat(*rowA
)[3] = (const GLfloat(*)[3]) srcRowA
;
249 const GLfloat(*rowB
)[3] = (const GLfloat(*)[3]) srcRowB
;
250 GLfloat(*dst
)[3] = (GLfloat(*)[3]) dstRow
;
251 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
252 i
++, j
+= colStride
, k
+= colStride
) {
253 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
254 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
255 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
256 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
257 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
258 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
261 else if (datatype
== GL_FLOAT
&& comps
== 2) {
263 const GLfloat(*rowA
)[2] = (const GLfloat(*)[2]) srcRowA
;
264 const GLfloat(*rowB
)[2] = (const GLfloat(*)[2]) srcRowB
;
265 GLfloat(*dst
)[2] = (GLfloat(*)[2]) dstRow
;
266 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
267 i
++, j
+= colStride
, k
+= colStride
) {
268 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
269 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
270 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
271 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
274 else if (datatype
== GL_FLOAT
&& comps
== 1) {
276 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
277 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
278 GLfloat
*dst
= (GLfloat
*) dstRow
;
279 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
280 i
++, j
+= colStride
, k
+= colStride
) {
281 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
285 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 4) {
286 GLuint i
, j
, k
, comp
;
287 const GLhalfARB(*rowA
)[4] = (const GLhalfARB(*)[4]) srcRowA
;
288 const GLhalfARB(*rowB
)[4] = (const GLhalfARB(*)[4]) srcRowB
;
289 GLhalfARB(*dst
)[4] = (GLhalfARB(*)[4]) dstRow
;
290 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
291 i
++, j
+= colStride
, k
+= colStride
) {
292 for (comp
= 0; comp
< 4; comp
++) {
293 GLfloat aj
, ak
, bj
, bk
;
294 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
295 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
296 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
297 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
298 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
302 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 3) {
303 GLuint i
, j
, k
, comp
;
304 const GLhalfARB(*rowA
)[3] = (const GLhalfARB(*)[3]) srcRowA
;
305 const GLhalfARB(*rowB
)[3] = (const GLhalfARB(*)[3]) srcRowB
;
306 GLhalfARB(*dst
)[3] = (GLhalfARB(*)[3]) dstRow
;
307 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
308 i
++, j
+= colStride
, k
+= colStride
) {
309 for (comp
= 0; comp
< 3; comp
++) {
310 GLfloat aj
, ak
, bj
, bk
;
311 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
312 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
313 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
314 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
315 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
319 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 2) {
320 GLuint i
, j
, k
, comp
;
321 const GLhalfARB(*rowA
)[2] = (const GLhalfARB(*)[2]) srcRowA
;
322 const GLhalfARB(*rowB
)[2] = (const GLhalfARB(*)[2]) srcRowB
;
323 GLhalfARB(*dst
)[2] = (GLhalfARB(*)[2]) dstRow
;
324 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
325 i
++, j
+= colStride
, k
+= colStride
) {
326 for (comp
= 0; comp
< 2; comp
++) {
327 GLfloat aj
, ak
, bj
, bk
;
328 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
329 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
330 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
331 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
332 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
336 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 1) {
338 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
339 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
340 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
341 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
342 i
++, j
+= colStride
, k
+= colStride
) {
343 GLfloat aj
, ak
, bj
, bk
;
344 aj
= _mesa_half_to_float(rowA
[j
]);
345 ak
= _mesa_half_to_float(rowA
[k
]);
346 bj
= _mesa_half_to_float(rowB
[j
]);
347 bk
= _mesa_half_to_float(rowB
[k
]);
348 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
352 else if (datatype
== GL_UNSIGNED_INT
&& comps
== 1) {
354 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
355 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
356 GLfloat
*dst
= (GLfloat
*) dstRow
;
357 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
358 i
++, j
+= colStride
, k
+= colStride
) {
359 dst
[i
] = (GLfloat
)(rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4);
363 else if (datatype
== GL_UNSIGNED_SHORT_5_6_5
&& comps
== 3) {
365 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
366 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
367 GLushort
*dst
= (GLushort
*) dstRow
;
368 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
369 i
++, j
+= colStride
, k
+= colStride
) {
370 const GLint rowAr0
= rowA
[j
] & 0x1f;
371 const GLint rowAr1
= rowA
[k
] & 0x1f;
372 const GLint rowBr0
= rowB
[j
] & 0x1f;
373 const GLint rowBr1
= rowB
[k
] & 0x1f;
374 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
375 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
376 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
377 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
378 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
379 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
380 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
381 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
382 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
383 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
384 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
385 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
388 else if (datatype
== GL_UNSIGNED_SHORT_4_4_4_4
&& comps
== 4) {
390 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
391 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
392 GLushort
*dst
= (GLushort
*) dstRow
;
393 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
394 i
++, j
+= colStride
, k
+= colStride
) {
395 const GLint rowAr0
= rowA
[j
] & 0xf;
396 const GLint rowAr1
= rowA
[k
] & 0xf;
397 const GLint rowBr0
= rowB
[j
] & 0xf;
398 const GLint rowBr1
= rowB
[k
] & 0xf;
399 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
400 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
401 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
402 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
403 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
404 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
405 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
406 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
407 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
408 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
409 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
410 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
411 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
412 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
413 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
414 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
415 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
418 else if (datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
&& comps
== 4) {
420 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
421 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
422 GLushort
*dst
= (GLushort
*) dstRow
;
423 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
424 i
++, j
+= colStride
, k
+= colStride
) {
425 const GLint rowAr0
= rowA
[j
] & 0x1f;
426 const GLint rowAr1
= rowA
[k
] & 0x1f;
427 const GLint rowBr0
= rowB
[j
] & 0x1f;
428 const GLint rowBr1
= rowB
[k
] & 0x1f;
429 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
430 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
431 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
432 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
433 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
434 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
435 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
436 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
437 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
438 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
439 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
440 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
441 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
442 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
443 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
444 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
445 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
448 else if (datatype
== GL_UNSIGNED_BYTE_3_3_2
&& comps
== 3) {
450 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
451 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
452 GLubyte
*dst
= (GLubyte
*) dstRow
;
453 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
454 i
++, j
+= colStride
, k
+= colStride
) {
455 const GLint rowAr0
= rowA
[j
] & 0x3;
456 const GLint rowAr1
= rowA
[k
] & 0x3;
457 const GLint rowBr0
= rowB
[j
] & 0x3;
458 const GLint rowBr1
= rowB
[k
] & 0x3;
459 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
460 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
461 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
462 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
463 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
464 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
465 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
466 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
467 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
468 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
469 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
470 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
473 else if (datatype
== GL_BYTE
&& comps
== 2) {
475 const GLbyte(*rowA
)[2] = (const GLbyte(*)[2]) srcRowA
;
476 const GLbyte(*rowB
)[2] = (const GLbyte(*)[2]) srcRowB
;
477 GLbyte(*dst
)[2] = (GLbyte(*)[2]) dstRow
;
478 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
479 i
++, j
+= colStride
, k
+= colStride
) {
480 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
481 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
485 _mesa_problem(NULL
, "bad format in do_row()");
491 * Average together four rows of a source image to produce a single new
492 * row in the dest image. It's legal for the two source rows to point
493 * to the same data. The source width must be equal to either the
494 * dest width or two times the dest width.
496 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
498 * \param comps number of components per pixel (1..4)
499 * \param srcWidth Width of a row in the source data
500 * \param srcRowA Pointer to one of the rows of source data
501 * \param srcRowB Pointer to one of the rows of source data
502 * \param srcRowC Pointer to one of the rows of source data
503 * \param srcRowD Pointer to one of the rows of source data
504 * \param dstWidth Width of a row in the destination data
505 * \param srcRowA Pointer to the row of destination data
508 do_row_3D(GLenum datatype
, GLuint comps
, GLint srcWidth
,
509 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
510 const GLvoid
*srcRowC
, const GLvoid
*srcRowD
,
511 GLint dstWidth
, GLvoid
*dstRow
)
513 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
514 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
520 if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 4)) {
521 DECLARE_ROW_POINTERS(GLubyte
, 4);
523 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
524 i
++, j
+= colStride
, k
+= colStride
) {
531 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 3)) {
532 DECLARE_ROW_POINTERS(GLubyte
, 3);
534 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
535 i
++, j
+= colStride
, k
+= colStride
) {
541 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 2)) {
542 DECLARE_ROW_POINTERS(GLubyte
, 2);
544 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
545 i
++, j
+= colStride
, k
+= colStride
) {
550 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 1)) {
551 DECLARE_ROW_POINTERS(GLubyte
, 1);
553 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
554 i
++, j
+= colStride
, k
+= colStride
) {
558 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 4)) {
559 DECLARE_ROW_POINTERS(GLushort
, 4);
561 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
562 i
++, j
+= colStride
, k
+= colStride
) {
569 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 3)) {
570 DECLARE_ROW_POINTERS(GLushort
, 3);
572 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
573 i
++, j
+= colStride
, k
+= colStride
) {
579 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 2)) {
580 DECLARE_ROW_POINTERS(GLushort
, 2);
582 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
583 i
++, j
+= colStride
, k
+= colStride
) {
588 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 1)) {
589 DECLARE_ROW_POINTERS(GLushort
, 1);
591 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
592 i
++, j
+= colStride
, k
+= colStride
) {
596 else if ((datatype
== GL_FLOAT
) && (comps
== 4)) {
597 DECLARE_ROW_POINTERS(GLfloat
, 4);
599 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
600 i
++, j
+= colStride
, k
+= colStride
) {
607 else if ((datatype
== GL_FLOAT
) && (comps
== 3)) {
608 DECLARE_ROW_POINTERS(GLfloat
, 3);
610 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
611 i
++, j
+= colStride
, k
+= colStride
) {
617 else if ((datatype
== GL_FLOAT
) && (comps
== 2)) {
618 DECLARE_ROW_POINTERS(GLfloat
, 2);
620 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
621 i
++, j
+= colStride
, k
+= colStride
) {
626 else if ((datatype
== GL_FLOAT
) && (comps
== 1)) {
627 DECLARE_ROW_POINTERS(GLfloat
, 1);
629 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
630 i
++, j
+= colStride
, k
+= colStride
) {
634 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 4)) {
635 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
637 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
638 i
++, j
+= colStride
, k
+= colStride
) {
645 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 3)) {
646 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
648 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
649 i
++, j
+= colStride
, k
+= colStride
) {
655 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 2)) {
656 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
658 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
659 i
++, j
+= colStride
, k
+= colStride
) {
664 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 1)) {
665 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
667 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
668 i
++, j
+= colStride
, k
+= colStride
) {
672 else if ((datatype
== GL_UNSIGNED_INT
) && (comps
== 1)) {
673 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
674 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
675 const GLuint
*rowC
= (const GLuint
*) srcRowC
;
676 const GLuint
*rowD
= (const GLuint
*) srcRowD
;
677 GLfloat
*dst
= (GLfloat
*) dstRow
;
679 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
680 i
++, j
+= colStride
, k
+= colStride
) {
681 const uint64_t tmp
= (((uint64_t) rowA
[j
] + (uint64_t) rowA
[k
])
682 + ((uint64_t) rowB
[j
] + (uint64_t) rowB
[k
])
683 + ((uint64_t) rowC
[j
] + (uint64_t) rowC
[k
])
684 + ((uint64_t) rowD
[j
] + (uint64_t) rowD
[k
]));
685 dst
[i
] = (GLfloat
)((double) tmp
* 0.125);
688 else if ((datatype
== GL_UNSIGNED_SHORT_5_6_5
) && (comps
== 3)) {
689 DECLARE_ROW_POINTERS0(GLushort
);
691 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
692 i
++, j
+= colStride
, k
+= colStride
) {
693 const GLint rowAr0
= rowA
[j
] & 0x1f;
694 const GLint rowAr1
= rowA
[k
] & 0x1f;
695 const GLint rowBr0
= rowB
[j
] & 0x1f;
696 const GLint rowBr1
= rowB
[k
] & 0x1f;
697 const GLint rowCr0
= rowC
[j
] & 0x1f;
698 const GLint rowCr1
= rowC
[k
] & 0x1f;
699 const GLint rowDr0
= rowD
[j
] & 0x1f;
700 const GLint rowDr1
= rowD
[k
] & 0x1f;
701 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
702 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
703 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
704 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
705 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x3f;
706 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x3f;
707 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x3f;
708 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x3f;
709 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
710 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
711 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
712 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
713 const GLint rowCb0
= (rowC
[j
] >> 11) & 0x1f;
714 const GLint rowCb1
= (rowC
[k
] >> 11) & 0x1f;
715 const GLint rowDb0
= (rowD
[j
] >> 11) & 0x1f;
716 const GLint rowDb1
= (rowD
[k
] >> 11) & 0x1f;
717 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
718 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
719 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
720 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
721 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
722 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
723 dst
[i
] = (b
<< 11) | (g
<< 5) | r
;
726 else if ((datatype
== GL_UNSIGNED_SHORT_4_4_4_4
) && (comps
== 4)) {
727 DECLARE_ROW_POINTERS0(GLushort
);
729 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
730 i
++, j
+= colStride
, k
+= colStride
) {
731 const GLint rowAr0
= rowA
[j
] & 0xf;
732 const GLint rowAr1
= rowA
[k
] & 0xf;
733 const GLint rowBr0
= rowB
[j
] & 0xf;
734 const GLint rowBr1
= rowB
[k
] & 0xf;
735 const GLint rowCr0
= rowC
[j
] & 0xf;
736 const GLint rowCr1
= rowC
[k
] & 0xf;
737 const GLint rowDr0
= rowD
[j
] & 0xf;
738 const GLint rowDr1
= rowD
[k
] & 0xf;
739 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
740 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
741 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
742 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
743 const GLint rowCg0
= (rowC
[j
] >> 4) & 0xf;
744 const GLint rowCg1
= (rowC
[k
] >> 4) & 0xf;
745 const GLint rowDg0
= (rowD
[j
] >> 4) & 0xf;
746 const GLint rowDg1
= (rowD
[k
] >> 4) & 0xf;
747 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
748 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
749 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
750 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
751 const GLint rowCb0
= (rowC
[j
] >> 8) & 0xf;
752 const GLint rowCb1
= (rowC
[k
] >> 8) & 0xf;
753 const GLint rowDb0
= (rowD
[j
] >> 8) & 0xf;
754 const GLint rowDb1
= (rowD
[k
] >> 8) & 0xf;
755 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
756 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
757 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
758 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
759 const GLint rowCa0
= (rowC
[j
] >> 12) & 0xf;
760 const GLint rowCa1
= (rowC
[k
] >> 12) & 0xf;
761 const GLint rowDa0
= (rowD
[j
] >> 12) & 0xf;
762 const GLint rowDa1
= (rowD
[k
] >> 12) & 0xf;
763 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
764 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
765 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
766 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
767 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
768 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
769 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
770 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
772 dst
[i
] = (a
<< 12) | (b
<< 8) | (g
<< 4) | r
;
775 else if ((datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) && (comps
== 4)) {
776 DECLARE_ROW_POINTERS0(GLushort
);
778 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
779 i
++, j
+= colStride
, k
+= colStride
) {
780 const GLint rowAr0
= rowA
[j
] & 0x1f;
781 const GLint rowAr1
= rowA
[k
] & 0x1f;
782 const GLint rowBr0
= rowB
[j
] & 0x1f;
783 const GLint rowBr1
= rowB
[k
] & 0x1f;
784 const GLint rowCr0
= rowC
[j
] & 0x1f;
785 const GLint rowCr1
= rowC
[k
] & 0x1f;
786 const GLint rowDr0
= rowD
[j
] & 0x1f;
787 const GLint rowDr1
= rowD
[k
] & 0x1f;
788 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
789 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
790 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
791 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
792 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x1f;
793 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x1f;
794 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x1f;
795 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x1f;
796 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
797 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
798 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
799 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
800 const GLint rowCb0
= (rowC
[j
] >> 10) & 0x1f;
801 const GLint rowCb1
= (rowC
[k
] >> 10) & 0x1f;
802 const GLint rowDb0
= (rowD
[j
] >> 10) & 0x1f;
803 const GLint rowDb1
= (rowD
[k
] >> 10) & 0x1f;
804 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
805 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
806 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
807 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
808 const GLint rowCa0
= (rowC
[j
] >> 15) & 0x1;
809 const GLint rowCa1
= (rowC
[k
] >> 15) & 0x1;
810 const GLint rowDa0
= (rowD
[j
] >> 15) & 0x1;
811 const GLint rowDa1
= (rowD
[k
] >> 15) & 0x1;
812 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
813 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
814 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
815 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
816 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
817 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
818 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
819 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
821 dst
[i
] = (a
<< 15) | (b
<< 10) | (g
<< 5) | r
;
824 else if ((datatype
== GL_UNSIGNED_BYTE_3_3_2
) && (comps
== 3)) {
825 DECLARE_ROW_POINTERS0(GLushort
);
827 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
828 i
++, j
+= colStride
, k
+= colStride
) {
829 const GLint rowAr0
= rowA
[j
] & 0x3;
830 const GLint rowAr1
= rowA
[k
] & 0x3;
831 const GLint rowBr0
= rowB
[j
] & 0x3;
832 const GLint rowBr1
= rowB
[k
] & 0x3;
833 const GLint rowCr0
= rowC
[j
] & 0x3;
834 const GLint rowCr1
= rowC
[k
] & 0x3;
835 const GLint rowDr0
= rowD
[j
] & 0x3;
836 const GLint rowDr1
= rowD
[k
] & 0x3;
837 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
838 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
839 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
840 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
841 const GLint rowCg0
= (rowC
[j
] >> 2) & 0x7;
842 const GLint rowCg1
= (rowC
[k
] >> 2) & 0x7;
843 const GLint rowDg0
= (rowD
[j
] >> 2) & 0x7;
844 const GLint rowDg1
= (rowD
[k
] >> 2) & 0x7;
845 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
846 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
847 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
848 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
849 const GLint rowCb0
= (rowC
[j
] >> 5) & 0x7;
850 const GLint rowCb1
= (rowC
[k
] >> 5) & 0x7;
851 const GLint rowDb0
= (rowD
[j
] >> 5) & 0x7;
852 const GLint rowDb1
= (rowD
[k
] >> 5) & 0x7;
853 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
854 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
855 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
856 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
857 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
858 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
859 dst
[i
] = (b
<< 5) | (g
<< 2) | r
;
863 _mesa_problem(NULL
, "bad format in do_row()");
869 * These functions generate a 1/2-size mipmap image from a source image.
870 * Texture borders are handled by copying or averaging the source image's
871 * border texels, depending on the scale-down factor.
875 make_1d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
876 GLint srcWidth
, const GLubyte
*srcPtr
,
877 GLint dstWidth
, GLubyte
*dstPtr
)
879 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
883 /* skip the border pixel, if any */
884 src
= srcPtr
+ border
* bpt
;
885 dst
= dstPtr
+ border
* bpt
;
887 /* we just duplicate the input row, kind of hack, saves code */
888 do_row(datatype
, comps
, srcWidth
- 2 * border
, src
, src
,
889 dstWidth
- 2 * border
, dst
);
892 /* copy left-most pixel from source */
893 MEMCPY(dstPtr
, srcPtr
, bpt
);
894 /* copy right-most pixel from source */
895 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
896 srcPtr
+ (srcWidth
- 1) * bpt
,
903 make_2d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
904 GLint srcWidth
, GLint srcHeight
,
905 const GLubyte
*srcPtr
, GLint srcRowStride
,
906 GLint dstWidth
, GLint dstHeight
,
907 GLubyte
*dstPtr
, GLint dstRowStride
)
909 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
910 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
911 const GLint dstWidthNB
= dstWidth
- 2 * border
;
912 const GLint dstHeightNB
= dstHeight
- 2 * border
;
913 const GLint srcRowBytes
= bpt
* srcRowStride
;
914 const GLint dstRowBytes
= bpt
* dstRowStride
;
915 const GLubyte
*srcA
, *srcB
;
919 /* Compute src and dst pointers, skipping any border */
920 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
922 srcB
= srcA
+ srcRowBytes
;
925 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
927 for (row
= 0; row
< dstHeightNB
; row
++) {
928 do_row(datatype
, comps
, srcWidthNB
, srcA
, srcB
,
930 srcA
+= 2 * srcRowBytes
;
931 srcB
+= 2 * srcRowBytes
;
935 /* This is ugly but probably won't be used much */
937 /* fill in dest border */
938 /* lower-left border pixel */
939 MEMCPY(dstPtr
, srcPtr
, bpt
);
940 /* lower-right border pixel */
941 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
942 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
943 /* upper-left border pixel */
944 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
945 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
946 /* upper-right border pixel */
947 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
948 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
950 do_row(datatype
, comps
, srcWidthNB
,
953 dstWidthNB
, dstPtr
+ bpt
);
955 do_row(datatype
, comps
, srcWidthNB
,
956 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
957 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
959 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
960 /* left and right borders */
961 if (srcHeight
== dstHeight
) {
962 /* copy border pixel from src to dst */
963 for (row
= 1; row
< srcHeight
; row
++) {
964 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
965 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
966 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
967 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
971 /* average two src pixels each dest pixel */
972 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
973 do_row(datatype
, comps
, 1,
974 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
975 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
976 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
977 do_row(datatype
, comps
, 1,
978 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
979 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
980 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
988 make_3d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
989 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
990 const GLubyte
*srcPtr
, GLint srcRowStride
,
991 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
992 GLubyte
*dstPtr
, GLint dstRowStride
)
994 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
995 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
996 const GLint srcDepthNB
= srcDepth
- 2 * border
;
997 const GLint dstWidthNB
= dstWidth
- 2 * border
;
998 const GLint dstHeightNB
= dstHeight
- 2 * border
;
999 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1001 GLint bytesPerSrcImage
, bytesPerDstImage
;
1002 GLint bytesPerSrcRow
, bytesPerDstRow
;
1003 GLint srcImageOffset
, srcRowOffset
;
1005 (void) srcDepthNB
; /* silence warnings */
1008 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
1009 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
1011 bytesPerSrcRow
= srcWidth
* bpt
;
1012 bytesPerDstRow
= dstWidth
* bpt
;
1014 /* Offset between adjacent src images to be averaged together */
1015 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
1017 /* Offset between adjacent src rows to be averaged together */
1018 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
1021 * Need to average together up to 8 src pixels for each dest pixel.
1022 * Break that down into 3 operations:
1023 * 1. take two rows from source image and average them together.
1024 * 2. take two rows from next source image and average them together.
1025 * 3. take the two averaged rows and average them for the final dst row.
1029 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1030 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1033 for (img
= 0; img
< dstDepthNB
; img
++) {
1034 /* first source image pointer, skipping border */
1035 const GLubyte
*imgSrcA
= srcPtr
1036 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
1037 + img
* (bytesPerSrcImage
+ srcImageOffset
);
1038 /* second source image pointer, skipping border */
1039 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
1040 /* address of the dest image, skipping border */
1041 GLubyte
*imgDst
= dstPtr
1042 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
1043 + img
* bytesPerDstImage
;
1045 /* setup the four source row pointers and the dest row pointer */
1046 const GLubyte
*srcImgARowA
= imgSrcA
;
1047 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
1048 const GLubyte
*srcImgBRowA
= imgSrcB
;
1049 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
1050 GLubyte
*dstImgRow
= imgDst
;
1052 for (row
= 0; row
< dstHeightNB
; row
++) {
1053 do_row_3D(datatype
, comps
, srcWidthNB
,
1054 srcImgARowA
, srcImgARowB
,
1055 srcImgBRowA
, srcImgBRowB
,
1056 dstWidthNB
, dstImgRow
);
1058 /* advance to next rows */
1059 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
1060 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
1061 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
1062 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
1063 dstImgRow
+= bytesPerDstRow
;
1068 /* Luckily we can leverage the make_2d_mipmap() function here! */
1070 /* do front border image */
1071 make_2d_mipmap(datatype
, comps
, 1, srcWidth
, srcHeight
, srcPtr
, srcRowStride
,
1072 dstWidth
, dstHeight
, dstPtr
, dstRowStride
);
1073 /* do back border image */
1074 make_2d_mipmap(datatype
, comps
, 1, srcWidth
, srcHeight
,
1075 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1), srcRowStride
,
1076 dstWidth
, dstHeight
,
1077 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1), dstRowStride
);
1078 /* do four remaining border edges that span the image slices */
1079 if (srcDepth
== dstDepth
) {
1080 /* just copy border pixels from src to dst */
1081 for (img
= 0; img
< dstDepthNB
; img
++) {
1085 /* do border along [img][row=0][col=0] */
1086 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
1087 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1088 MEMCPY(dst
, src
, bpt
);
1090 /* do border along [img][row=dstHeight-1][col=0] */
1091 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1092 + (srcHeight
- 1) * bytesPerSrcRow
;
1093 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1094 + (dstHeight
- 1) * bytesPerDstRow
;
1095 MEMCPY(dst
, src
, bpt
);
1097 /* do border along [img][row=0][col=dstWidth-1] */
1098 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1099 + (srcWidth
- 1) * bpt
;
1100 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1101 + (dstWidth
- 1) * bpt
;
1102 MEMCPY(dst
, src
, bpt
);
1104 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1105 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1106 + (bytesPerSrcImage
- bpt
);
1107 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1108 + (bytesPerDstImage
- bpt
);
1109 MEMCPY(dst
, src
, bpt
);
1113 /* average border pixels from adjacent src image pairs */
1114 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
1115 for (img
= 0; img
< dstDepthNB
; img
++) {
1119 /* do border along [img][row=0][col=0] */
1120 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
1121 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1122 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1124 /* do border along [img][row=dstHeight-1][col=0] */
1125 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1126 + (srcHeight
- 1) * bytesPerSrcRow
;
1127 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1128 + (dstHeight
- 1) * bytesPerDstRow
;
1129 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1131 /* do border along [img][row=0][col=dstWidth-1] */
1132 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1133 + (srcWidth
- 1) * bpt
;
1134 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1135 + (dstWidth
- 1) * bpt
;
1136 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1138 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1139 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1140 + (bytesPerSrcImage
- bpt
);
1141 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1142 + (bytesPerDstImage
- bpt
);
1143 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1151 make_1d_stack_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1152 GLint srcWidth
, const GLubyte
*srcPtr
, GLuint srcRowStride
,
1153 GLint dstWidth
, GLint dstHeight
,
1154 GLubyte
*dstPtr
, GLuint dstRowStride
)
1156 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1157 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1158 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1159 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1160 const GLint srcRowBytes
= bpt
* srcRowStride
;
1161 const GLint dstRowBytes
= bpt
* dstRowStride
;
1166 /* Compute src and dst pointers, skipping any border */
1167 src
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1168 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1170 for (row
= 0; row
< dstHeightNB
; row
++) {
1171 do_row(datatype
, comps
, srcWidthNB
, src
, src
,
1178 /* copy left-most pixel from source */
1179 MEMCPY(dstPtr
, srcPtr
, bpt
);
1180 /* copy right-most pixel from source */
1181 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
1182 srcPtr
+ (srcWidth
- 1) * bpt
,
1190 * There is quite a bit of refactoring that could be done with this function
1191 * and \c make_2d_mipmap.
1194 make_2d_stack_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1195 GLint srcWidth
, GLint srcHeight
,
1196 const GLubyte
*srcPtr
, GLint srcRowStride
,
1197 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1198 GLubyte
*dstPtr
, GLint dstRowStride
)
1200 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1201 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1202 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1203 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1204 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1205 const GLint srcRowBytes
= bpt
* srcRowStride
;
1206 const GLint dstRowBytes
= bpt
* dstRowStride
;
1207 const GLubyte
*srcA
, *srcB
;
1212 /* Compute src and dst pointers, skipping any border */
1213 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1215 srcB
= srcA
+ srcRowBytes
;
1218 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1220 for (layer
= 0; layer
< dstDepthNB
; layer
++) {
1221 for (row
= 0; row
< dstHeightNB
; row
++) {
1222 do_row(datatype
, comps
, srcWidthNB
, srcA
, srcB
,
1224 srcA
+= 2 * srcRowBytes
;
1225 srcB
+= 2 * srcRowBytes
;
1229 /* This is ugly but probably won't be used much */
1231 /* fill in dest border */
1232 /* lower-left border pixel */
1233 MEMCPY(dstPtr
, srcPtr
, bpt
);
1234 /* lower-right border pixel */
1235 MEMCPY(dstPtr
+ (dstWidth
- 1) * bpt
,
1236 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
1237 /* upper-left border pixel */
1238 MEMCPY(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
1239 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
1240 /* upper-right border pixel */
1241 MEMCPY(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
1242 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
1244 do_row(datatype
, comps
, srcWidthNB
,
1247 dstWidthNB
, dstPtr
+ bpt
);
1249 do_row(datatype
, comps
, srcWidthNB
,
1250 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1251 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1253 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
1254 /* left and right borders */
1255 if (srcHeight
== dstHeight
) {
1256 /* copy border pixel from src to dst */
1257 for (row
= 1; row
< srcHeight
; row
++) {
1258 MEMCPY(dstPtr
+ dstWidth
* row
* bpt
,
1259 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
1260 MEMCPY(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
1261 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
1265 /* average two src pixels each dest pixel */
1266 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
1267 do_row(datatype
, comps
, 1,
1268 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
1269 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
1270 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
1271 do_row(datatype
, comps
, 1,
1272 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
1273 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
1274 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
1283 * Down-sample a texture image to produce the next lower mipmap level.
1286 _mesa_generate_mipmap_level(GLenum target
,
1287 GLenum datatype
, GLuint comps
,
1289 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1290 const GLubyte
*srcData
,
1292 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1297 * We use simple 2x2 averaging to compute the next mipmap level.
1301 make_1d_mipmap(datatype
, comps
, border
,
1306 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
1307 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
1308 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
1309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
1310 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
1311 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
1312 make_2d_mipmap(datatype
, comps
, border
,
1313 srcWidth
, srcHeight
, srcData
, srcRowStride
,
1314 dstWidth
, dstHeight
, dstData
, dstRowStride
);
1317 make_3d_mipmap(datatype
, comps
, border
,
1318 srcWidth
, srcHeight
, srcDepth
,
1319 srcData
, srcRowStride
,
1320 dstWidth
, dstHeight
, dstDepth
,
1321 dstData
, dstRowStride
);
1323 case GL_TEXTURE_1D_ARRAY_EXT
:
1324 make_1d_stack_mipmap(datatype
, comps
, border
,
1325 srcWidth
, srcData
, srcRowStride
,
1326 dstWidth
, dstHeight
,
1327 dstData
, dstRowStride
);
1329 case GL_TEXTURE_2D_ARRAY_EXT
:
1330 make_2d_stack_mipmap(datatype
, comps
, border
,
1331 srcWidth
, srcHeight
,
1332 srcData
, srcRowStride
,
1333 dstWidth
, dstHeight
,
1334 dstDepth
, dstData
, dstRowStride
);
1336 case GL_TEXTURE_RECTANGLE_NV
:
1337 /* no mipmaps, do nothing */
1340 _mesa_problem(NULL
, "bad dimensions in _mesa_generate_mipmaps");
1347 * compute next (level+1) image size
1348 * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1351 next_mipmap_level_size(GLenum target
, GLint border
,
1352 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1353 GLint
*dstWidth
, GLint
*dstHeight
, GLint
*dstDepth
)
1355 if (srcWidth
- 2 * border
> 1) {
1356 *dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
1359 *dstWidth
= srcWidth
; /* can't go smaller */
1362 if ((srcHeight
- 2 * border
> 1) &&
1363 (target
!= GL_TEXTURE_1D_ARRAY_EXT
)) {
1364 *dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
1367 *dstHeight
= srcHeight
; /* can't go smaller */
1370 if ((srcDepth
- 2 * border
> 1) &&
1371 (target
!= GL_TEXTURE_2D_ARRAY_EXT
)) {
1372 *dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
1375 *dstDepth
= srcDepth
; /* can't go smaller */
1378 if (*dstWidth
== srcWidth
&&
1379 *dstHeight
== srcHeight
&&
1380 *dstDepth
== srcDepth
) {
1392 * For GL_SGIX_generate_mipmap:
1393 * Generate a complete set of mipmaps from texObj's base-level image.
1394 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1397 _mesa_generate_mipmap(GLcontext
*ctx
, GLenum target
,
1398 struct gl_texture_object
*texObj
)
1400 const struct gl_texture_image
*srcImage
;
1401 const struct gl_texture_format
*convertFormat
;
1402 const GLubyte
*srcData
= NULL
;
1403 GLubyte
*dstData
= NULL
;
1404 GLint level
, maxLevels
;
1409 /* XXX choose cube map face here??? */
1410 srcImage
= texObj
->Image
[0][texObj
->BaseLevel
];
1413 maxLevels
= _mesa_max_texture_levels(ctx
, texObj
->Target
);
1414 ASSERT(maxLevels
> 0); /* bad target */
1416 /* Find convertFormat - the format that do_row() will process */
1417 if (srcImage
->IsCompressed
) {
1418 /* setup for compressed textures */
1420 GLint components
, size
;
1423 assert(texObj
->Target
== GL_TEXTURE_2D
||
1424 texObj
->Target
== GL_TEXTURE_CUBE_MAP_ARB
);
1426 if (srcImage
->_BaseFormat
== GL_RGB
) {
1427 convertFormat
= &_mesa_texformat_rgb
;
1430 else if (srcImage
->_BaseFormat
== GL_RGBA
) {
1431 convertFormat
= &_mesa_texformat_rgba
;
1435 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
1439 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
1440 size
= _mesa_bytes_per_pixel(srcImage
->_BaseFormat
, CHAN_TYPE
)
1441 * srcImage
->Width
* srcImage
->Height
* srcImage
->Depth
+ 20;
1442 /* 20 extra bytes, just be safe when calling last FetchTexel */
1443 srcData
= (GLubyte
*) _mesa_malloc(size
);
1445 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
1448 dstData
= (GLubyte
*) _mesa_malloc(size
/ 2); /* 1/4 would probably be OK */
1450 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
1451 _mesa_free((void *) srcData
);
1455 /* decompress base image here */
1456 dst
= (GLchan
*) srcData
;
1457 for (row
= 0; row
< srcImage
->Height
; row
++) {
1459 for (col
= 0; col
< srcImage
->Width
; col
++) {
1460 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
1467 convertFormat
= srcImage
->TexFormat
;
1470 _mesa_format_to_type_and_comps(convertFormat
, &datatype
, &comps
);
1472 for (level
= texObj
->BaseLevel
; level
< texObj
->MaxLevel
1473 && level
< maxLevels
- 1; level
++) {
1474 /* generate image[level+1] from image[level] */
1475 const struct gl_texture_image
*srcImage
;
1476 struct gl_texture_image
*dstImage
;
1477 GLint srcWidth
, srcHeight
, srcDepth
;
1478 GLint dstWidth
, dstHeight
, dstDepth
;
1479 GLint border
, bytesPerTexel
;
1480 GLboolean nextLevel
;
1482 /* get src image parameters */
1483 srcImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
1485 srcWidth
= srcImage
->Width
;
1486 srcHeight
= srcImage
->Height
;
1487 srcDepth
= srcImage
->Depth
;
1488 border
= srcImage
->Border
;
1490 nextLevel
= next_mipmap_level_size(target
, border
,
1491 srcWidth
, srcHeight
, srcDepth
,
1492 &dstWidth
, &dstHeight
, &dstDepth
);
1495 if (srcImage
->IsCompressed
) {
1496 _mesa_free((void *) srcData
);
1497 _mesa_free(dstData
);
1502 /* get dest gl_texture_image */
1503 dstImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
+ 1);
1505 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1509 if (dstImage
->ImageOffsets
)
1510 _mesa_free(dstImage
->ImageOffsets
);
1512 /* Free old image data */
1514 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
1516 /* initialize new image */
1517 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
1518 dstDepth
, border
, srcImage
->InternalFormat
);
1519 dstImage
->DriverData
= NULL
;
1520 dstImage
->TexFormat
= srcImage
->TexFormat
;
1521 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
1522 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
1523 dstImage
->IsCompressed
= srcImage
->IsCompressed
;
1524 if (dstImage
->IsCompressed
) {
1525 dstImage
->CompressedSize
1526 = ctx
->Driver
.CompressedTextureSize(ctx
, dstImage
->Width
,
1529 dstImage
->TexFormat
->MesaFormat
);
1530 ASSERT(dstImage
->CompressedSize
> 0);
1533 ASSERT(dstImage
->TexFormat
);
1534 ASSERT(dstImage
->FetchTexelc
);
1535 ASSERT(dstImage
->FetchTexelf
);
1537 /* Alloc new teximage data buffer.
1538 * Setup src and dest data pointers.
1540 if (dstImage
->IsCompressed
) {
1541 dstImage
->Data
= _mesa_alloc_texmemory(dstImage
->CompressedSize
);
1542 if (!dstImage
->Data
) {
1543 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1546 /* srcData and dstData are already set */
1551 bytesPerTexel
= dstImage
->TexFormat
->TexelBytes
;
1552 ASSERT(dstWidth
* dstHeight
* dstDepth
* bytesPerTexel
> 0);
1553 dstImage
->Data
= _mesa_alloc_texmemory(dstWidth
* dstHeight
1554 * dstDepth
* bytesPerTexel
);
1555 if (!dstImage
->Data
) {
1556 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1559 srcData
= (const GLubyte
*) srcImage
->Data
;
1560 dstData
= (GLubyte
*) dstImage
->Data
;
1563 _mesa_generate_mipmap_level(target
, datatype
, comps
, border
,
1564 srcWidth
, srcHeight
, srcDepth
,
1565 srcData
, srcImage
->RowStride
,
1566 dstWidth
, dstHeight
, dstDepth
,
1567 dstData
, dstImage
->RowStride
);
1570 if (dstImage
->IsCompressed
) {
1572 /* compress image from dstData into dstImage->Data */
1573 const GLenum srcFormat
= convertFormat
->BaseFormat
;
1575 = _mesa_compressed_row_stride(dstImage
->TexFormat
->MesaFormat
, dstWidth
);
1576 ASSERT(srcFormat
== GL_RGB
|| srcFormat
== GL_RGBA
);
1577 dstImage
->TexFormat
->StoreImage(ctx
, 2, dstImage
->_BaseFormat
,
1578 dstImage
->TexFormat
,
1580 0, 0, 0, /* dstX/Y/Zoffset */
1581 dstRowStride
, 0, /* strides */
1582 dstWidth
, dstHeight
, 1, /* size */
1583 srcFormat
, CHAN_TYPE
,
1584 dstData
, /* src data, actually */
1585 &ctx
->DefaultPacking
);
1586 /* swap src and dest pointers */
1587 temp
= (GLubyte
*) srcData
;
1592 } /* loop over mipmap levels */
1597 * Helper function for drivers which need to rescale texture images to
1598 * certain aspect ratios.
1599 * Nearest filtering only (for broken hardware that can't support
1600 * all aspect ratios). This can be made a lot faster, but I don't
1601 * really care enough...
1604 _mesa_rescale_teximage2d(GLuint bytesPerPixel
,
1605 GLuint srcStrideInPixels
,
1606 GLuint dstRowStride
,
1607 GLint srcWidth
, GLint srcHeight
,
1608 GLint dstWidth
, GLint dstHeight
,
1609 const GLvoid
*srcImage
, GLvoid
*dstImage
)
1613 #define INNER_LOOP( TYPE, HOP, WOP ) \
1614 for ( row = 0 ; row < dstHeight ; row++ ) { \
1615 GLint srcRow = row HOP hScale; \
1616 for ( col = 0 ; col < dstWidth ; col++ ) { \
1617 GLint srcCol = col WOP wScale; \
1618 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
1620 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
1623 #define RESCALE_IMAGE( TYPE ) \
1625 const TYPE *src = (const TYPE *)srcImage; \
1626 TYPE *dst = (TYPE *)dstImage; \
1628 if ( srcHeight < dstHeight ) { \
1629 const GLint hScale = dstHeight / srcHeight; \
1630 if ( srcWidth < dstWidth ) { \
1631 const GLint wScale = dstWidth / srcWidth; \
1632 INNER_LOOP( TYPE, /, / ); \
1635 const GLint wScale = srcWidth / dstWidth; \
1636 INNER_LOOP( TYPE, /, * ); \
1640 const GLint hScale = srcHeight / dstHeight; \
1641 if ( srcWidth < dstWidth ) { \
1642 const GLint wScale = dstWidth / srcWidth; \
1643 INNER_LOOP( TYPE, *, / ); \
1646 const GLint wScale = srcWidth / dstWidth; \
1647 INNER_LOOP( TYPE, *, * ); \
1652 switch ( bytesPerPixel
) {
1654 RESCALE_IMAGE( GLuint
);
1658 RESCALE_IMAGE( GLushort
);
1662 RESCALE_IMAGE( GLubyte
);
1665 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
1671 * Upscale an image by replication, not (typical) stretching.
1672 * We use this when the image width or height is less than a
1673 * certain size (4, 8) and we need to upscale an image.
1676 _mesa_upscale_teximage2d(GLsizei inWidth
, GLsizei inHeight
,
1677 GLsizei outWidth
, GLsizei outHeight
,
1678 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
1683 ASSERT(outWidth
>= inWidth
);
1684 ASSERT(outHeight
>= inHeight
);
1686 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
1687 ASSERT((outWidth
& 3) == 0);
1688 ASSERT((outHeight
& 3) == 0);
1691 for (i
= 0; i
< outHeight
; i
++) {
1692 const GLint ii
= i
% inHeight
;
1693 for (j
= 0; j
< outWidth
; j
++) {
1694 const GLint jj
= j
% inWidth
;
1695 for (k
= 0; k
< comps
; k
++) {
1696 dest
[(i
* outWidth
+ j
) * comps
+ k
]
1697 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];