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.
38 #include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
39 #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
44 bytes_per_pixel(GLenum datatype
, GLuint comps
)
46 GLint b
= _mesa_sizeof_packed_type(datatype
);
49 if (_mesa_type_is_packed(datatype
))
57 * \name Support macros for do_row and do_row_3d
59 * The macro madness is here for two reasons. First, it compacts the code
60 * slightly. Second, it makes it much easier to adjust the specifics of the
61 * filter to tune the rounding characteristics.
64 #define DECLARE_ROW_POINTERS(t, e) \
65 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
66 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
67 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
68 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
69 t(*dst)[e] = (t(*)[e]) dstRow
71 #define DECLARE_ROW_POINTERS0(t) \
72 const t *rowA = (const t *) srcRowA; \
73 const t *rowB = (const t *) srcRowB; \
74 const t *rowC = (const t *) srcRowC; \
75 const t *rowD = (const t *) srcRowD; \
78 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
79 ((unsigned) Aj + (unsigned) Ak \
80 + (unsigned) Bj + (unsigned) Bk \
81 + (unsigned) Cj + (unsigned) Ck \
82 + (unsigned) Dj + (unsigned) Dk \
85 #define FILTER_3D(e) \
87 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
88 rowB[j][e], rowB[k][e], \
89 rowC[j][e], rowC[k][e], \
90 rowD[j][e], rowD[k][e]); \
93 #define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
100 #define FILTER_3D_SIGNED(e) \
102 dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
103 rowB[j][e], rowB[k][e], \
104 rowC[j][e], rowC[k][e], \
105 rowD[j][e], rowD[k][e]); \
108 #define FILTER_F_3D(e) \
110 dst[i][e] = (rowA[j][e] + rowA[k][e] \
111 + rowB[j][e] + rowB[k][e] \
112 + rowC[j][e] + rowC[k][e] \
113 + rowD[j][e] + rowD[k][e]) * 0.125F; \
116 #define FILTER_HF_3D(e) \
118 const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
119 const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
120 const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
121 const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
122 const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
123 const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
124 const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
125 const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
126 dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
133 * Average together two rows of a source image to produce a single new
134 * row in the dest image. It's legal for the two source rows to point
135 * to the same data. The source width must be equal to either the
136 * dest width or two times the dest width.
137 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
138 * \param comps number of components per pixel (1..4)
141 do_row(GLenum datatype
, GLuint comps
, GLint srcWidth
,
142 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
143 GLint dstWidth
, GLvoid
*dstRow
)
145 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
146 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
151 /* This assertion is no longer valid with non-power-of-2 textures
152 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
155 if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 4) {
157 const GLubyte(*rowA
)[4] = (const GLubyte(*)[4]) srcRowA
;
158 const GLubyte(*rowB
)[4] = (const GLubyte(*)[4]) srcRowB
;
159 GLubyte(*dst
)[4] = (GLubyte(*)[4]) dstRow
;
160 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
161 i
++, j
+= colStride
, k
+= colStride
) {
162 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
163 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
164 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
165 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
168 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 3) {
170 const GLubyte(*rowA
)[3] = (const GLubyte(*)[3]) srcRowA
;
171 const GLubyte(*rowB
)[3] = (const GLubyte(*)[3]) srcRowB
;
172 GLubyte(*dst
)[3] = (GLubyte(*)[3]) dstRow
;
173 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
174 i
++, j
+= colStride
, k
+= colStride
) {
175 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
176 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
177 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
180 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 2) {
182 const GLubyte(*rowA
)[2] = (const GLubyte(*)[2]) srcRowA
;
183 const GLubyte(*rowB
)[2] = (const GLubyte(*)[2]) srcRowB
;
184 GLubyte(*dst
)[2] = (GLubyte(*)[2]) dstRow
;
185 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
186 i
++, j
+= colStride
, k
+= colStride
) {
187 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
188 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
191 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 1) {
193 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
194 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
195 GLubyte
*dst
= (GLubyte
*) dstRow
;
196 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
197 i
++, j
+= colStride
, k
+= colStride
) {
198 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
202 else if (datatype
== GL_BYTE
&& comps
== 4) {
204 const GLbyte(*rowA
)[4] = (const GLbyte(*)[4]) srcRowA
;
205 const GLbyte(*rowB
)[4] = (const GLbyte(*)[4]) srcRowB
;
206 GLbyte(*dst
)[4] = (GLbyte(*)[4]) dstRow
;
207 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
208 i
++, j
+= colStride
, k
+= colStride
) {
209 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
210 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
211 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
212 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
215 else if (datatype
== GL_BYTE
&& comps
== 3) {
217 const GLbyte(*rowA
)[3] = (const GLbyte(*)[3]) srcRowA
;
218 const GLbyte(*rowB
)[3] = (const GLbyte(*)[3]) srcRowB
;
219 GLbyte(*dst
)[3] = (GLbyte(*)[3]) dstRow
;
220 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
221 i
++, j
+= colStride
, k
+= colStride
) {
222 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
223 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
224 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
227 else if (datatype
== GL_BYTE
&& comps
== 2) {
229 const GLbyte(*rowA
)[2] = (const GLbyte(*)[2]) srcRowA
;
230 const GLbyte(*rowB
)[2] = (const GLbyte(*)[2]) srcRowB
;
231 GLbyte(*dst
)[2] = (GLbyte(*)[2]) dstRow
;
232 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
233 i
++, j
+= colStride
, k
+= colStride
) {
234 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
235 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
238 else if (datatype
== GL_BYTE
&& comps
== 1) {
240 const GLbyte
*rowA
= (const GLbyte
*) srcRowA
;
241 const GLbyte
*rowB
= (const GLbyte
*) srcRowB
;
242 GLbyte
*dst
= (GLbyte
*) dstRow
;
243 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
244 i
++, j
+= colStride
, k
+= colStride
) {
245 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
249 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 4) {
251 const GLushort(*rowA
)[4] = (const GLushort(*)[4]) srcRowA
;
252 const GLushort(*rowB
)[4] = (const GLushort(*)[4]) srcRowB
;
253 GLushort(*dst
)[4] = (GLushort(*)[4]) dstRow
;
254 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
255 i
++, j
+= colStride
, k
+= colStride
) {
256 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
257 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
258 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
259 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
262 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 3) {
264 const GLushort(*rowA
)[3] = (const GLushort(*)[3]) srcRowA
;
265 const GLushort(*rowB
)[3] = (const GLushort(*)[3]) srcRowB
;
266 GLushort(*dst
)[3] = (GLushort(*)[3]) dstRow
;
267 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
268 i
++, j
+= colStride
, k
+= colStride
) {
269 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
270 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
271 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
274 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 2) {
276 const GLushort(*rowA
)[2] = (const GLushort(*)[2]) srcRowA
;
277 const GLushort(*rowB
)[2] = (const GLushort(*)[2]) srcRowB
;
278 GLushort(*dst
)[2] = (GLushort(*)[2]) dstRow
;
279 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
280 i
++, j
+= colStride
, k
+= colStride
) {
281 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
282 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
285 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 1) {
287 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
288 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
289 GLushort
*dst
= (GLushort
*) dstRow
;
290 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
291 i
++, j
+= colStride
, k
+= colStride
) {
292 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
296 else if (datatype
== GL_SHORT
&& comps
== 4) {
298 const GLshort(*rowA
)[4] = (const GLshort(*)[4]) srcRowA
;
299 const GLshort(*rowB
)[4] = (const GLshort(*)[4]) srcRowB
;
300 GLshort(*dst
)[4] = (GLshort(*)[4]) dstRow
;
301 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
302 i
++, j
+= colStride
, k
+= colStride
) {
303 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
304 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
305 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
306 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
309 else if (datatype
== GL_SHORT
&& comps
== 3) {
311 const GLshort(*rowA
)[3] = (const GLshort(*)[3]) srcRowA
;
312 const GLshort(*rowB
)[3] = (const GLshort(*)[3]) srcRowB
;
313 GLshort(*dst
)[3] = (GLshort(*)[3]) dstRow
;
314 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
315 i
++, j
+= colStride
, k
+= colStride
) {
316 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
317 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
318 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
321 else if (datatype
== GL_SHORT
&& comps
== 2) {
323 const GLshort(*rowA
)[2] = (const GLshort(*)[2]) srcRowA
;
324 const GLshort(*rowB
)[2] = (const GLshort(*)[2]) srcRowB
;
325 GLshort(*dst
)[2] = (GLshort(*)[2]) dstRow
;
326 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
327 i
++, j
+= colStride
, k
+= colStride
) {
328 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
329 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
332 else if (datatype
== GL_SHORT
&& comps
== 1) {
334 const GLshort
*rowA
= (const GLshort
*) srcRowA
;
335 const GLshort
*rowB
= (const GLshort
*) srcRowB
;
336 GLshort
*dst
= (GLshort
*) dstRow
;
337 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
338 i
++, j
+= colStride
, k
+= colStride
) {
339 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
343 else if (datatype
== GL_FLOAT
&& comps
== 4) {
345 const GLfloat(*rowA
)[4] = (const GLfloat(*)[4]) srcRowA
;
346 const GLfloat(*rowB
)[4] = (const GLfloat(*)[4]) srcRowB
;
347 GLfloat(*dst
)[4] = (GLfloat(*)[4]) dstRow
;
348 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
349 i
++, j
+= colStride
, k
+= colStride
) {
350 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
351 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
352 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
353 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
354 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
355 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
356 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
357 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
360 else if (datatype
== GL_FLOAT
&& comps
== 3) {
362 const GLfloat(*rowA
)[3] = (const GLfloat(*)[3]) srcRowA
;
363 const GLfloat(*rowB
)[3] = (const GLfloat(*)[3]) srcRowB
;
364 GLfloat(*dst
)[3] = (GLfloat(*)[3]) dstRow
;
365 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
366 i
++, j
+= colStride
, k
+= colStride
) {
367 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
368 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
369 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
370 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
371 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
372 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
375 else if (datatype
== GL_FLOAT
&& comps
== 2) {
377 const GLfloat(*rowA
)[2] = (const GLfloat(*)[2]) srcRowA
;
378 const GLfloat(*rowB
)[2] = (const GLfloat(*)[2]) srcRowB
;
379 GLfloat(*dst
)[2] = (GLfloat(*)[2]) dstRow
;
380 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
381 i
++, j
+= colStride
, k
+= colStride
) {
382 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
383 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
384 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
385 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
388 else if (datatype
== GL_FLOAT
&& comps
== 1) {
390 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
391 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
392 GLfloat
*dst
= (GLfloat
*) dstRow
;
393 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
394 i
++, j
+= colStride
, k
+= colStride
) {
395 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
399 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 4) {
400 GLuint i
, j
, k
, comp
;
401 const GLhalfARB(*rowA
)[4] = (const GLhalfARB(*)[4]) srcRowA
;
402 const GLhalfARB(*rowB
)[4] = (const GLhalfARB(*)[4]) srcRowB
;
403 GLhalfARB(*dst
)[4] = (GLhalfARB(*)[4]) dstRow
;
404 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
405 i
++, j
+= colStride
, k
+= colStride
) {
406 for (comp
= 0; comp
< 4; comp
++) {
407 GLfloat aj
, ak
, bj
, bk
;
408 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
409 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
410 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
411 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
412 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
416 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 3) {
417 GLuint i
, j
, k
, comp
;
418 const GLhalfARB(*rowA
)[3] = (const GLhalfARB(*)[3]) srcRowA
;
419 const GLhalfARB(*rowB
)[3] = (const GLhalfARB(*)[3]) srcRowB
;
420 GLhalfARB(*dst
)[3] = (GLhalfARB(*)[3]) dstRow
;
421 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
422 i
++, j
+= colStride
, k
+= colStride
) {
423 for (comp
= 0; comp
< 3; comp
++) {
424 GLfloat aj
, ak
, bj
, bk
;
425 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
426 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
427 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
428 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
429 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
433 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 2) {
434 GLuint i
, j
, k
, comp
;
435 const GLhalfARB(*rowA
)[2] = (const GLhalfARB(*)[2]) srcRowA
;
436 const GLhalfARB(*rowB
)[2] = (const GLhalfARB(*)[2]) srcRowB
;
437 GLhalfARB(*dst
)[2] = (GLhalfARB(*)[2]) dstRow
;
438 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
439 i
++, j
+= colStride
, k
+= colStride
) {
440 for (comp
= 0; comp
< 2; comp
++) {
441 GLfloat aj
, ak
, bj
, bk
;
442 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
443 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
444 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
445 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
446 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
450 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 1) {
452 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
453 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
454 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
455 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
456 i
++, j
+= colStride
, k
+= colStride
) {
457 GLfloat aj
, ak
, bj
, bk
;
458 aj
= _mesa_half_to_float(rowA
[j
]);
459 ak
= _mesa_half_to_float(rowA
[k
]);
460 bj
= _mesa_half_to_float(rowB
[j
]);
461 bk
= _mesa_half_to_float(rowB
[k
]);
462 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
466 else if (datatype
== GL_UNSIGNED_INT
&& comps
== 1) {
468 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
469 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
470 GLuint
*dst
= (GLuint
*) dstRow
;
471 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
472 i
++, j
+= colStride
, k
+= colStride
) {
473 dst
[i
] = (GLfloat
)(rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4);
477 else if (datatype
== GL_UNSIGNED_SHORT_5_6_5
&& comps
== 3) {
479 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
480 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
481 GLushort
*dst
= (GLushort
*) dstRow
;
482 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
483 i
++, j
+= colStride
, k
+= colStride
) {
484 const GLint rowAr0
= rowA
[j
] & 0x1f;
485 const GLint rowAr1
= rowA
[k
] & 0x1f;
486 const GLint rowBr0
= rowB
[j
] & 0x1f;
487 const GLint rowBr1
= rowB
[k
] & 0x1f;
488 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
489 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
490 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
491 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
492 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
493 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
494 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
495 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
496 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
497 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
498 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
499 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
502 else if (datatype
== GL_UNSIGNED_SHORT_4_4_4_4
&& comps
== 4) {
504 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
505 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
506 GLushort
*dst
= (GLushort
*) dstRow
;
507 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
508 i
++, j
+= colStride
, k
+= colStride
) {
509 const GLint rowAr0
= rowA
[j
] & 0xf;
510 const GLint rowAr1
= rowA
[k
] & 0xf;
511 const GLint rowBr0
= rowB
[j
] & 0xf;
512 const GLint rowBr1
= rowB
[k
] & 0xf;
513 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
514 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
515 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
516 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
517 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
518 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
519 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
520 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
521 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
522 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
523 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
524 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
525 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
526 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
527 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
528 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
529 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
532 else if (datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
&& comps
== 4) {
534 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
535 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
536 GLushort
*dst
= (GLushort
*) dstRow
;
537 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
538 i
++, j
+= colStride
, k
+= colStride
) {
539 const GLint rowAr0
= rowA
[j
] & 0x1f;
540 const GLint rowAr1
= rowA
[k
] & 0x1f;
541 const GLint rowBr0
= rowB
[j
] & 0x1f;
542 const GLint rowBr1
= rowB
[k
] & 0x1f;
543 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
544 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
545 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
546 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
547 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
548 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
549 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
550 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
551 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
552 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
553 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
554 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
555 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
556 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
557 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
558 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
559 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
562 else if (datatype
== GL_UNSIGNED_SHORT_5_5_5_1
&& comps
== 4) {
564 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
565 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
566 GLushort
*dst
= (GLushort
*) dstRow
;
567 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
568 i
++, j
+= colStride
, k
+= colStride
) {
569 const GLint rowAr0
= (rowA
[j
] >> 11) & 0x1f;
570 const GLint rowAr1
= (rowA
[k
] >> 11) & 0x1f;
571 const GLint rowBr0
= (rowB
[j
] >> 11) & 0x1f;
572 const GLint rowBr1
= (rowB
[k
] >> 11) & 0x1f;
573 const GLint rowAg0
= (rowA
[j
] >> 6) & 0x1f;
574 const GLint rowAg1
= (rowA
[k
] >> 6) & 0x1f;
575 const GLint rowBg0
= (rowB
[j
] >> 6) & 0x1f;
576 const GLint rowBg1
= (rowB
[k
] >> 6) & 0x1f;
577 const GLint rowAb0
= (rowA
[j
] >> 1) & 0x1f;
578 const GLint rowAb1
= (rowA
[k
] >> 1) & 0x1f;
579 const GLint rowBb0
= (rowB
[j
] >> 1) & 0x1f;
580 const GLint rowBb1
= (rowB
[k
] >> 1) & 0x1f;
581 const GLint rowAa0
= (rowA
[j
] & 0x1);
582 const GLint rowAa1
= (rowA
[k
] & 0x1);
583 const GLint rowBa0
= (rowB
[j
] & 0x1);
584 const GLint rowBa1
= (rowB
[k
] & 0x1);
585 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
586 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
587 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
588 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
589 dst
[i
] = (red
<< 11) | (green
<< 6) | (blue
<< 1) | alpha
;
593 else if (datatype
== GL_UNSIGNED_BYTE_3_3_2
&& comps
== 3) {
595 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
596 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
597 GLubyte
*dst
= (GLubyte
*) dstRow
;
598 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
599 i
++, j
+= colStride
, k
+= colStride
) {
600 const GLint rowAr0
= rowA
[j
] & 0x3;
601 const GLint rowAr1
= rowA
[k
] & 0x3;
602 const GLint rowBr0
= rowB
[j
] & 0x3;
603 const GLint rowBr1
= rowB
[k
] & 0x3;
604 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
605 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
606 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
607 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
608 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
609 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
610 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
611 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
612 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
613 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
614 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
615 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
619 else if (datatype
== MESA_UNSIGNED_BYTE_4_4
&& comps
== 2) {
621 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
622 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
623 GLubyte
*dst
= (GLubyte
*) dstRow
;
624 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
625 i
++, j
+= colStride
, k
+= colStride
) {
626 const GLint rowAr0
= rowA
[j
] & 0xf;
627 const GLint rowAr1
= rowA
[k
] & 0xf;
628 const GLint rowBr0
= rowB
[j
] & 0xf;
629 const GLint rowBr1
= rowB
[k
] & 0xf;
630 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
631 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
632 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
633 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
634 const GLint r
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
635 const GLint g
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
636 dst
[i
] = (g
<< 4) | r
;
640 else if (datatype
== GL_UNSIGNED_INT_2_10_10_10_REV
&& comps
== 4) {
642 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
643 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
644 GLuint
*dst
= (GLuint
*) dstRow
;
645 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
646 i
++, j
+= colStride
, k
+= colStride
) {
647 const GLint rowAr0
= rowA
[j
] & 0x3ff;
648 const GLint rowAr1
= rowA
[k
] & 0x3ff;
649 const GLint rowBr0
= rowB
[j
] & 0x3ff;
650 const GLint rowBr1
= rowB
[k
] & 0x3ff;
651 const GLint rowAg0
= (rowA
[j
] >> 10) & 0x3ff;
652 const GLint rowAg1
= (rowA
[k
] >> 10) & 0x3ff;
653 const GLint rowBg0
= (rowB
[j
] >> 10) & 0x3ff;
654 const GLint rowBg1
= (rowB
[k
] >> 10) & 0x3ff;
655 const GLint rowAb0
= (rowA
[j
] >> 20) & 0x3ff;
656 const GLint rowAb1
= (rowA
[k
] >> 20) & 0x3ff;
657 const GLint rowBb0
= (rowB
[j
] >> 20) & 0x3ff;
658 const GLint rowBb1
= (rowB
[k
] >> 20) & 0x3ff;
659 const GLint rowAa0
= (rowA
[j
] >> 30) & 0x3;
660 const GLint rowAa1
= (rowA
[k
] >> 30) & 0x3;
661 const GLint rowBa0
= (rowB
[j
] >> 30) & 0x3;
662 const GLint rowBa1
= (rowB
[k
] >> 30) & 0x3;
663 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
664 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
665 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
666 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
667 dst
[i
] = (alpha
<< 30) | (blue
<< 20) | (green
<< 10) | red
;
671 else if (datatype
== GL_UNSIGNED_INT_5_9_9_9_REV
&& comps
== 3) {
673 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
674 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
675 GLuint
*dst
= (GLuint
*)dstRow
;
676 GLfloat res
[3], rowAj
[3], rowBj
[3], rowAk
[3], rowBk
[3];
677 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
678 i
++, j
+= colStride
, k
+= colStride
) {
679 rgb9e5_to_float3(rowA
[j
], rowAj
);
680 rgb9e5_to_float3(rowB
[j
], rowBj
);
681 rgb9e5_to_float3(rowA
[k
], rowAk
);
682 rgb9e5_to_float3(rowB
[k
], rowBk
);
683 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0]) * 0.25F
;
684 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1]) * 0.25F
;
685 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2]) * 0.25F
;
686 dst
[i
] = float3_to_rgb9e5(res
);
690 else if (datatype
== GL_UNSIGNED_INT_10F_11F_11F_REV
&& comps
== 3) {
692 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
693 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
694 GLuint
*dst
= (GLuint
*)dstRow
;
695 GLfloat res
[3], rowAj
[3], rowBj
[3], rowAk
[3], rowBk
[3];
696 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
697 i
++, j
+= colStride
, k
+= colStride
) {
698 r11g11b10f_to_float3(rowA
[j
], rowAj
);
699 r11g11b10f_to_float3(rowB
[j
], rowBj
);
700 r11g11b10f_to_float3(rowA
[k
], rowAk
);
701 r11g11b10f_to_float3(rowB
[k
], rowBk
);
702 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0]) * 0.25F
;
703 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1]) * 0.25F
;
704 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2]) * 0.25F
;
705 dst
[i
] = float3_to_r11g11b10f(res
);
710 _mesa_problem(NULL
, "bad format in do_row()");
716 * Average together four rows of a source image to produce a single new
717 * row in the dest image. It's legal for the two source rows to point
718 * to the same data. The source width must be equal to either the
719 * dest width or two times the dest width.
721 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
723 * \param comps number of components per pixel (1..4)
724 * \param srcWidth Width of a row in the source data
725 * \param srcRowA Pointer to one of the rows of source data
726 * \param srcRowB Pointer to one of the rows of source data
727 * \param srcRowC Pointer to one of the rows of source data
728 * \param srcRowD Pointer to one of the rows of source data
729 * \param dstWidth Width of a row in the destination data
730 * \param srcRowA Pointer to the row of destination data
733 do_row_3D(GLenum datatype
, GLuint comps
, GLint srcWidth
,
734 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
735 const GLvoid
*srcRowC
, const GLvoid
*srcRowD
,
736 GLint dstWidth
, GLvoid
*dstRow
)
738 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
739 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
745 if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 4)) {
746 DECLARE_ROW_POINTERS(GLubyte
, 4);
748 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
749 i
++, j
+= colStride
, k
+= colStride
) {
756 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 3)) {
757 DECLARE_ROW_POINTERS(GLubyte
, 3);
759 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
760 i
++, j
+= colStride
, k
+= colStride
) {
766 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 2)) {
767 DECLARE_ROW_POINTERS(GLubyte
, 2);
769 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
770 i
++, j
+= colStride
, k
+= colStride
) {
775 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 1)) {
776 DECLARE_ROW_POINTERS(GLubyte
, 1);
778 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
779 i
++, j
+= colStride
, k
+= colStride
) {
783 else if ((datatype
== GL_BYTE
) && (comps
== 4)) {
784 DECLARE_ROW_POINTERS(GLbyte
, 4);
786 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
787 i
++, j
+= colStride
, k
+= colStride
) {
794 else if ((datatype
== GL_BYTE
) && (comps
== 3)) {
795 DECLARE_ROW_POINTERS(GLbyte
, 3);
797 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
798 i
++, j
+= colStride
, k
+= colStride
) {
804 else if ((datatype
== GL_BYTE
) && (comps
== 2)) {
805 DECLARE_ROW_POINTERS(GLbyte
, 2);
807 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
808 i
++, j
+= colStride
, k
+= colStride
) {
813 else if ((datatype
== GL_BYTE
) && (comps
== 1)) {
814 DECLARE_ROW_POINTERS(GLbyte
, 1);
816 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
817 i
++, j
+= colStride
, k
+= colStride
) {
821 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 4)) {
822 DECLARE_ROW_POINTERS(GLushort
, 4);
824 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
825 i
++, j
+= colStride
, k
+= colStride
) {
832 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 3)) {
833 DECLARE_ROW_POINTERS(GLushort
, 3);
835 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
836 i
++, j
+= colStride
, k
+= colStride
) {
842 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 2)) {
843 DECLARE_ROW_POINTERS(GLushort
, 2);
845 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
846 i
++, j
+= colStride
, k
+= colStride
) {
851 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 1)) {
852 DECLARE_ROW_POINTERS(GLushort
, 1);
854 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
855 i
++, j
+= colStride
, k
+= colStride
) {
859 else if ((datatype
== GL_SHORT
) && (comps
== 4)) {
860 DECLARE_ROW_POINTERS(GLshort
, 4);
862 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
863 i
++, j
+= colStride
, k
+= colStride
) {
870 else if ((datatype
== GL_SHORT
) && (comps
== 3)) {
871 DECLARE_ROW_POINTERS(GLshort
, 3);
873 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
874 i
++, j
+= colStride
, k
+= colStride
) {
880 else if ((datatype
== GL_SHORT
) && (comps
== 2)) {
881 DECLARE_ROW_POINTERS(GLshort
, 2);
883 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
884 i
++, j
+= colStride
, k
+= colStride
) {
889 else if ((datatype
== GL_SHORT
) && (comps
== 1)) {
890 DECLARE_ROW_POINTERS(GLshort
, 1);
892 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
893 i
++, j
+= colStride
, k
+= colStride
) {
897 else if ((datatype
== GL_FLOAT
) && (comps
== 4)) {
898 DECLARE_ROW_POINTERS(GLfloat
, 4);
900 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
901 i
++, j
+= colStride
, k
+= colStride
) {
908 else if ((datatype
== GL_FLOAT
) && (comps
== 3)) {
909 DECLARE_ROW_POINTERS(GLfloat
, 3);
911 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
912 i
++, j
+= colStride
, k
+= colStride
) {
918 else if ((datatype
== GL_FLOAT
) && (comps
== 2)) {
919 DECLARE_ROW_POINTERS(GLfloat
, 2);
921 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
922 i
++, j
+= colStride
, k
+= colStride
) {
927 else if ((datatype
== GL_FLOAT
) && (comps
== 1)) {
928 DECLARE_ROW_POINTERS(GLfloat
, 1);
930 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
931 i
++, j
+= colStride
, k
+= colStride
) {
935 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 4)) {
936 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
938 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
939 i
++, j
+= colStride
, k
+= colStride
) {
946 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 3)) {
947 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
949 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
950 i
++, j
+= colStride
, k
+= colStride
) {
956 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 2)) {
957 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
959 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
960 i
++, j
+= colStride
, k
+= colStride
) {
965 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 1)) {
966 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
968 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
969 i
++, j
+= colStride
, k
+= colStride
) {
973 else if ((datatype
== GL_UNSIGNED_INT
) && (comps
== 1)) {
974 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
975 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
976 const GLuint
*rowC
= (const GLuint
*) srcRowC
;
977 const GLuint
*rowD
= (const GLuint
*) srcRowD
;
978 GLfloat
*dst
= (GLfloat
*) dstRow
;
980 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
981 i
++, j
+= colStride
, k
+= colStride
) {
982 const uint64_t tmp
= (((uint64_t) rowA
[j
] + (uint64_t) rowA
[k
])
983 + ((uint64_t) rowB
[j
] + (uint64_t) rowB
[k
])
984 + ((uint64_t) rowC
[j
] + (uint64_t) rowC
[k
])
985 + ((uint64_t) rowD
[j
] + (uint64_t) rowD
[k
]));
986 dst
[i
] = (GLfloat
)((double) tmp
* 0.125);
989 else if ((datatype
== GL_UNSIGNED_SHORT_5_6_5
) && (comps
== 3)) {
990 DECLARE_ROW_POINTERS0(GLushort
);
992 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
993 i
++, j
+= colStride
, k
+= colStride
) {
994 const GLint rowAr0
= rowA
[j
] & 0x1f;
995 const GLint rowAr1
= rowA
[k
] & 0x1f;
996 const GLint rowBr0
= rowB
[j
] & 0x1f;
997 const GLint rowBr1
= rowB
[k
] & 0x1f;
998 const GLint rowCr0
= rowC
[j
] & 0x1f;
999 const GLint rowCr1
= rowC
[k
] & 0x1f;
1000 const GLint rowDr0
= rowD
[j
] & 0x1f;
1001 const GLint rowDr1
= rowD
[k
] & 0x1f;
1002 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
1003 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
1004 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
1005 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
1006 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x3f;
1007 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x3f;
1008 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x3f;
1009 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x3f;
1010 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
1011 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
1012 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
1013 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
1014 const GLint rowCb0
= (rowC
[j
] >> 11) & 0x1f;
1015 const GLint rowCb1
= (rowC
[k
] >> 11) & 0x1f;
1016 const GLint rowDb0
= (rowD
[j
] >> 11) & 0x1f;
1017 const GLint rowDb1
= (rowD
[k
] >> 11) & 0x1f;
1018 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1019 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1020 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1021 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1022 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1023 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1024 dst
[i
] = (b
<< 11) | (g
<< 5) | r
;
1027 else if ((datatype
== GL_UNSIGNED_SHORT_4_4_4_4
) && (comps
== 4)) {
1028 DECLARE_ROW_POINTERS0(GLushort
);
1030 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1031 i
++, j
+= colStride
, k
+= colStride
) {
1032 const GLint rowAr0
= rowA
[j
] & 0xf;
1033 const GLint rowAr1
= rowA
[k
] & 0xf;
1034 const GLint rowBr0
= rowB
[j
] & 0xf;
1035 const GLint rowBr1
= rowB
[k
] & 0xf;
1036 const GLint rowCr0
= rowC
[j
] & 0xf;
1037 const GLint rowCr1
= rowC
[k
] & 0xf;
1038 const GLint rowDr0
= rowD
[j
] & 0xf;
1039 const GLint rowDr1
= rowD
[k
] & 0xf;
1040 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
1041 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
1042 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
1043 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
1044 const GLint rowCg0
= (rowC
[j
] >> 4) & 0xf;
1045 const GLint rowCg1
= (rowC
[k
] >> 4) & 0xf;
1046 const GLint rowDg0
= (rowD
[j
] >> 4) & 0xf;
1047 const GLint rowDg1
= (rowD
[k
] >> 4) & 0xf;
1048 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
1049 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
1050 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
1051 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
1052 const GLint rowCb0
= (rowC
[j
] >> 8) & 0xf;
1053 const GLint rowCb1
= (rowC
[k
] >> 8) & 0xf;
1054 const GLint rowDb0
= (rowD
[j
] >> 8) & 0xf;
1055 const GLint rowDb1
= (rowD
[k
] >> 8) & 0xf;
1056 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
1057 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
1058 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
1059 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
1060 const GLint rowCa0
= (rowC
[j
] >> 12) & 0xf;
1061 const GLint rowCa1
= (rowC
[k
] >> 12) & 0xf;
1062 const GLint rowDa0
= (rowD
[j
] >> 12) & 0xf;
1063 const GLint rowDa1
= (rowD
[k
] >> 12) & 0xf;
1064 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1065 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1066 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1067 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1068 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1069 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1070 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1071 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1073 dst
[i
] = (a
<< 12) | (b
<< 8) | (g
<< 4) | r
;
1076 else if ((datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) && (comps
== 4)) {
1077 DECLARE_ROW_POINTERS0(GLushort
);
1079 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1080 i
++, j
+= colStride
, k
+= colStride
) {
1081 const GLint rowAr0
= rowA
[j
] & 0x1f;
1082 const GLint rowAr1
= rowA
[k
] & 0x1f;
1083 const GLint rowBr0
= rowB
[j
] & 0x1f;
1084 const GLint rowBr1
= rowB
[k
] & 0x1f;
1085 const GLint rowCr0
= rowC
[j
] & 0x1f;
1086 const GLint rowCr1
= rowC
[k
] & 0x1f;
1087 const GLint rowDr0
= rowD
[j
] & 0x1f;
1088 const GLint rowDr1
= rowD
[k
] & 0x1f;
1089 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
1090 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
1091 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
1092 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
1093 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x1f;
1094 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x1f;
1095 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x1f;
1096 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x1f;
1097 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
1098 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
1099 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
1100 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
1101 const GLint rowCb0
= (rowC
[j
] >> 10) & 0x1f;
1102 const GLint rowCb1
= (rowC
[k
] >> 10) & 0x1f;
1103 const GLint rowDb0
= (rowD
[j
] >> 10) & 0x1f;
1104 const GLint rowDb1
= (rowD
[k
] >> 10) & 0x1f;
1105 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
1106 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
1107 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
1108 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
1109 const GLint rowCa0
= (rowC
[j
] >> 15) & 0x1;
1110 const GLint rowCa1
= (rowC
[k
] >> 15) & 0x1;
1111 const GLint rowDa0
= (rowD
[j
] >> 15) & 0x1;
1112 const GLint rowDa1
= (rowD
[k
] >> 15) & 0x1;
1113 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1114 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1115 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1116 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1117 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1118 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1119 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1120 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1122 dst
[i
] = (a
<< 15) | (b
<< 10) | (g
<< 5) | r
;
1125 else if ((datatype
== GL_UNSIGNED_SHORT_5_5_5_1
) && (comps
== 4)) {
1126 DECLARE_ROW_POINTERS0(GLushort
);
1128 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1129 i
++, j
+= colStride
, k
+= colStride
) {
1130 const GLint rowAr0
= (rowA
[j
] >> 11) & 0x1f;
1131 const GLint rowAr1
= (rowA
[k
] >> 11) & 0x1f;
1132 const GLint rowBr0
= (rowB
[j
] >> 11) & 0x1f;
1133 const GLint rowBr1
= (rowB
[k
] >> 11) & 0x1f;
1134 const GLint rowCr0
= (rowC
[j
] >> 11) & 0x1f;
1135 const GLint rowCr1
= (rowC
[k
] >> 11) & 0x1f;
1136 const GLint rowDr0
= (rowD
[j
] >> 11) & 0x1f;
1137 const GLint rowDr1
= (rowD
[k
] >> 11) & 0x1f;
1138 const GLint rowAg0
= (rowA
[j
] >> 6) & 0x1f;
1139 const GLint rowAg1
= (rowA
[k
] >> 6) & 0x1f;
1140 const GLint rowBg0
= (rowB
[j
] >> 6) & 0x1f;
1141 const GLint rowBg1
= (rowB
[k
] >> 6) & 0x1f;
1142 const GLint rowCg0
= (rowC
[j
] >> 6) & 0x1f;
1143 const GLint rowCg1
= (rowC
[k
] >> 6) & 0x1f;
1144 const GLint rowDg0
= (rowD
[j
] >> 6) & 0x1f;
1145 const GLint rowDg1
= (rowD
[k
] >> 6) & 0x1f;
1146 const GLint rowAb0
= (rowA
[j
] >> 1) & 0x1f;
1147 const GLint rowAb1
= (rowA
[k
] >> 1) & 0x1f;
1148 const GLint rowBb0
= (rowB
[j
] >> 1) & 0x1f;
1149 const GLint rowBb1
= (rowB
[k
] >> 1) & 0x1f;
1150 const GLint rowCb0
= (rowC
[j
] >> 1) & 0x1f;
1151 const GLint rowCb1
= (rowC
[k
] >> 1) & 0x1f;
1152 const GLint rowDb0
= (rowD
[j
] >> 1) & 0x1f;
1153 const GLint rowDb1
= (rowD
[k
] >> 1) & 0x1f;
1154 const GLint rowAa0
= (rowA
[j
] & 0x1);
1155 const GLint rowAa1
= (rowA
[k
] & 0x1);
1156 const GLint rowBa0
= (rowB
[j
] & 0x1);
1157 const GLint rowBa1
= (rowB
[k
] & 0x1);
1158 const GLint rowCa0
= (rowC
[j
] & 0x1);
1159 const GLint rowCa1
= (rowC
[k
] & 0x1);
1160 const GLint rowDa0
= (rowD
[j
] & 0x1);
1161 const GLint rowDa1
= (rowD
[k
] & 0x1);
1162 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1163 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1164 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1165 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1166 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1167 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1168 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1169 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1171 dst
[i
] = (r
<< 11) | (g
<< 6) | (b
<< 1) | a
;
1174 else if ((datatype
== GL_UNSIGNED_BYTE_3_3_2
) && (comps
== 3)) {
1175 DECLARE_ROW_POINTERS0(GLubyte
);
1177 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1178 i
++, j
+= colStride
, k
+= colStride
) {
1179 const GLint rowAr0
= rowA
[j
] & 0x3;
1180 const GLint rowAr1
= rowA
[k
] & 0x3;
1181 const GLint rowBr0
= rowB
[j
] & 0x3;
1182 const GLint rowBr1
= rowB
[k
] & 0x3;
1183 const GLint rowCr0
= rowC
[j
] & 0x3;
1184 const GLint rowCr1
= rowC
[k
] & 0x3;
1185 const GLint rowDr0
= rowD
[j
] & 0x3;
1186 const GLint rowDr1
= rowD
[k
] & 0x3;
1187 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
1188 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
1189 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
1190 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
1191 const GLint rowCg0
= (rowC
[j
] >> 2) & 0x7;
1192 const GLint rowCg1
= (rowC
[k
] >> 2) & 0x7;
1193 const GLint rowDg0
= (rowD
[j
] >> 2) & 0x7;
1194 const GLint rowDg1
= (rowD
[k
] >> 2) & 0x7;
1195 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
1196 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
1197 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
1198 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
1199 const GLint rowCb0
= (rowC
[j
] >> 5) & 0x7;
1200 const GLint rowCb1
= (rowC
[k
] >> 5) & 0x7;
1201 const GLint rowDb0
= (rowD
[j
] >> 5) & 0x7;
1202 const GLint rowDb1
= (rowD
[k
] >> 5) & 0x7;
1203 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1204 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1205 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1206 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1207 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1208 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1209 dst
[i
] = (b
<< 5) | (g
<< 2) | r
;
1212 else if (datatype
== MESA_UNSIGNED_BYTE_4_4
&& comps
== 2) {
1213 DECLARE_ROW_POINTERS0(GLubyte
);
1215 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1216 i
++, j
+= colStride
, k
+= colStride
) {
1217 const GLint rowAr0
= rowA
[j
] & 0xf;
1218 const GLint rowAr1
= rowA
[k
] & 0xf;
1219 const GLint rowBr0
= rowB
[j
] & 0xf;
1220 const GLint rowBr1
= rowB
[k
] & 0xf;
1221 const GLint rowCr0
= rowC
[j
] & 0xf;
1222 const GLint rowCr1
= rowC
[k
] & 0xf;
1223 const GLint rowDr0
= rowD
[j
] & 0xf;
1224 const GLint rowDr1
= rowD
[k
] & 0xf;
1225 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
1226 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
1227 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
1228 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
1229 const GLint rowCg0
= (rowC
[j
] >> 4) & 0xf;
1230 const GLint rowCg1
= (rowC
[k
] >> 4) & 0xf;
1231 const GLint rowDg0
= (rowD
[j
] >> 4) & 0xf;
1232 const GLint rowDg1
= (rowD
[k
] >> 4) & 0xf;
1233 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1234 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1235 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1236 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1237 dst
[i
] = (g
<< 4) | r
;
1240 else if ((datatype
== GL_UNSIGNED_INT_2_10_10_10_REV
) && (comps
== 4)) {
1241 DECLARE_ROW_POINTERS0(GLuint
);
1243 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1244 i
++, j
+= colStride
, k
+= colStride
) {
1245 const GLint rowAr0
= rowA
[j
] & 0x3ff;
1246 const GLint rowAr1
= rowA
[k
] & 0x3ff;
1247 const GLint rowBr0
= rowB
[j
] & 0x3ff;
1248 const GLint rowBr1
= rowB
[k
] & 0x3ff;
1249 const GLint rowCr0
= rowC
[j
] & 0x3ff;
1250 const GLint rowCr1
= rowC
[k
] & 0x3ff;
1251 const GLint rowDr0
= rowD
[j
] & 0x3ff;
1252 const GLint rowDr1
= rowD
[k
] & 0x3ff;
1253 const GLint rowAg0
= (rowA
[j
] >> 10) & 0x3ff;
1254 const GLint rowAg1
= (rowA
[k
] >> 10) & 0x3ff;
1255 const GLint rowBg0
= (rowB
[j
] >> 10) & 0x3ff;
1256 const GLint rowBg1
= (rowB
[k
] >> 10) & 0x3ff;
1257 const GLint rowCg0
= (rowC
[j
] >> 10) & 0x3ff;
1258 const GLint rowCg1
= (rowC
[k
] >> 10) & 0x3ff;
1259 const GLint rowDg0
= (rowD
[j
] >> 10) & 0x3ff;
1260 const GLint rowDg1
= (rowD
[k
] >> 10) & 0x3ff;
1261 const GLint rowAb0
= (rowA
[j
] >> 20) & 0x3ff;
1262 const GLint rowAb1
= (rowA
[k
] >> 20) & 0x3ff;
1263 const GLint rowBb0
= (rowB
[j
] >> 20) & 0x3ff;
1264 const GLint rowBb1
= (rowB
[k
] >> 20) & 0x3ff;
1265 const GLint rowCb0
= (rowC
[j
] >> 20) & 0x3ff;
1266 const GLint rowCb1
= (rowC
[k
] >> 20) & 0x3ff;
1267 const GLint rowDb0
= (rowD
[j
] >> 20) & 0x3ff;
1268 const GLint rowDb1
= (rowD
[k
] >> 20) & 0x3ff;
1269 const GLint rowAa0
= (rowA
[j
] >> 30) & 0x3;
1270 const GLint rowAa1
= (rowA
[k
] >> 30) & 0x3;
1271 const GLint rowBa0
= (rowB
[j
] >> 30) & 0x3;
1272 const GLint rowBa1
= (rowB
[k
] >> 30) & 0x3;
1273 const GLint rowCa0
= (rowC
[j
] >> 30) & 0x3;
1274 const GLint rowCa1
= (rowC
[k
] >> 30) & 0x3;
1275 const GLint rowDa0
= (rowD
[j
] >> 30) & 0x3;
1276 const GLint rowDa1
= (rowD
[k
] >> 30) & 0x3;
1277 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1278 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1279 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1280 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1281 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1282 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1283 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1284 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1286 dst
[i
] = (a
<< 30) | (b
<< 20) | (g
<< 10) | r
;
1290 else if (datatype
== GL_UNSIGNED_INT_5_9_9_9_REV
&& comps
== 3) {
1291 DECLARE_ROW_POINTERS0(GLuint
);
1294 GLfloat rowAj
[3], rowBj
[3], rowCj
[3], rowDj
[3];
1295 GLfloat rowAk
[3], rowBk
[3], rowCk
[3], rowDk
[3];
1297 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1298 i
++, j
+= colStride
, k
+= colStride
) {
1299 rgb9e5_to_float3(rowA
[j
], rowAj
);
1300 rgb9e5_to_float3(rowB
[j
], rowBj
);
1301 rgb9e5_to_float3(rowC
[j
], rowCj
);
1302 rgb9e5_to_float3(rowD
[j
], rowDj
);
1303 rgb9e5_to_float3(rowA
[k
], rowAk
);
1304 rgb9e5_to_float3(rowB
[k
], rowBk
);
1305 rgb9e5_to_float3(rowC
[k
], rowCk
);
1306 rgb9e5_to_float3(rowD
[k
], rowDk
);
1307 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0] +
1308 rowCj
[0] + rowCk
[0] + rowDj
[0] + rowDk
[0]) * 0.125F
;
1309 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1] +
1310 rowCj
[1] + rowCk
[1] + rowDj
[1] + rowDk
[1]) * 0.125F
;
1311 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2] +
1312 rowCj
[2] + rowCk
[2] + rowDj
[2] + rowDk
[2]) * 0.125F
;
1313 dst
[i
] = float3_to_rgb9e5(res
);
1317 else if (datatype
== GL_UNSIGNED_INT_10F_11F_11F_REV
&& comps
== 3) {
1318 DECLARE_ROW_POINTERS0(GLuint
);
1321 GLfloat rowAj
[3], rowBj
[3], rowCj
[3], rowDj
[3];
1322 GLfloat rowAk
[3], rowBk
[3], rowCk
[3], rowDk
[3];
1324 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1325 i
++, j
+= colStride
, k
+= colStride
) {
1326 r11g11b10f_to_float3(rowA
[j
], rowAj
);
1327 r11g11b10f_to_float3(rowB
[j
], rowBj
);
1328 r11g11b10f_to_float3(rowC
[j
], rowCj
);
1329 r11g11b10f_to_float3(rowD
[j
], rowDj
);
1330 r11g11b10f_to_float3(rowA
[k
], rowAk
);
1331 r11g11b10f_to_float3(rowB
[k
], rowBk
);
1332 r11g11b10f_to_float3(rowC
[k
], rowCk
);
1333 r11g11b10f_to_float3(rowD
[k
], rowDk
);
1334 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0] +
1335 rowCj
[0] + rowCk
[0] + rowDj
[0] + rowDk
[0]) * 0.125F
;
1336 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1] +
1337 rowCj
[1] + rowCk
[1] + rowDj
[1] + rowDk
[1]) * 0.125F
;
1338 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2] +
1339 rowCj
[2] + rowCk
[2] + rowDj
[2] + rowDk
[2]) * 0.125F
;
1340 dst
[i
] = float3_to_r11g11b10f(res
);
1345 _mesa_problem(NULL
, "bad format in do_row()");
1351 * These functions generate a 1/2-size mipmap image from a source image.
1352 * Texture borders are handled by copying or averaging the source image's
1353 * border texels, depending on the scale-down factor.
1357 make_1d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1358 GLint srcWidth
, const GLubyte
*srcPtr
,
1359 GLint dstWidth
, GLubyte
*dstPtr
)
1361 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1365 /* skip the border pixel, if any */
1366 src
= srcPtr
+ border
* bpt
;
1367 dst
= dstPtr
+ border
* bpt
;
1369 /* we just duplicate the input row, kind of hack, saves code */
1370 do_row(datatype
, comps
, srcWidth
- 2 * border
, src
, src
,
1371 dstWidth
- 2 * border
, dst
);
1374 /* copy left-most pixel from source */
1377 memcpy(dstPtr
, srcPtr
, bpt
);
1378 /* copy right-most pixel from source */
1379 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1380 srcPtr
+ (srcWidth
- 1) * bpt
,
1387 make_2d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1388 GLint srcWidth
, GLint srcHeight
,
1389 const GLubyte
*srcPtr
, GLint srcRowStride
,
1390 GLint dstWidth
, GLint dstHeight
,
1391 GLubyte
*dstPtr
, GLint dstRowStride
)
1393 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1394 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1395 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1396 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1397 const GLint srcRowBytes
= bpt
* srcRowStride
;
1398 const GLint dstRowBytes
= bpt
* dstRowStride
;
1399 const GLubyte
*srcA
, *srcB
;
1401 GLint row
, srcRowStep
;
1403 /* Compute src and dst pointers, skipping any border */
1404 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1405 if (srcHeight
> 1 && srcHeight
> dstHeight
) {
1406 /* sample from two source rows */
1407 srcB
= srcA
+ srcRowBytes
;
1411 /* sample from one source row */
1416 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1418 for (row
= 0; row
< dstHeightNB
; row
++) {
1419 do_row(datatype
, comps
, srcWidthNB
, srcA
, srcB
,
1421 srcA
+= srcRowStep
* srcRowBytes
;
1422 srcB
+= srcRowStep
* srcRowBytes
;
1426 /* This is ugly but probably won't be used much */
1428 /* fill in dest border */
1429 /* lower-left border pixel */
1432 memcpy(dstPtr
, srcPtr
, bpt
);
1433 /* lower-right border pixel */
1434 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1435 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
1436 /* upper-left border pixel */
1437 memcpy(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
1438 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
1439 /* upper-right border pixel */
1440 memcpy(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
1441 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
1443 do_row(datatype
, comps
, srcWidthNB
,
1446 dstWidthNB
, dstPtr
+ bpt
);
1448 do_row(datatype
, comps
, srcWidthNB
,
1449 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1450 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1452 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
1453 /* left and right borders */
1454 if (srcHeight
== dstHeight
) {
1455 /* copy border pixel from src to dst */
1456 for (row
= 1; row
< srcHeight
; row
++) {
1457 memcpy(dstPtr
+ dstWidth
* row
* bpt
,
1458 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
1459 memcpy(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
1460 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
1464 /* average two src pixels each dest pixel */
1465 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
1466 do_row(datatype
, comps
, 1,
1467 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
1468 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
1469 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
1470 do_row(datatype
, comps
, 1,
1471 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
1472 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
1473 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
1481 make_3d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1482 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1483 const GLubyte
*srcPtr
, GLint srcRowStride
,
1484 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1485 GLubyte
*dstPtr
, GLint dstRowStride
)
1487 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1488 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1489 const GLint srcDepthNB
= srcDepth
- 2 * border
;
1490 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1491 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1492 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1494 GLint bytesPerSrcImage
, bytesPerDstImage
;
1495 GLint bytesPerSrcRow
, bytesPerDstRow
;
1496 GLint srcImageOffset
, srcRowOffset
;
1498 (void) srcDepthNB
; /* silence warnings */
1501 bytesPerSrcImage
= srcWidth
* srcHeight
* bpt
;
1502 bytesPerDstImage
= dstWidth
* dstHeight
* bpt
;
1504 bytesPerSrcRow
= srcWidth
* bpt
;
1505 bytesPerDstRow
= dstWidth
* bpt
;
1507 /* Offset between adjacent src images to be averaged together */
1508 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : bytesPerSrcImage
;
1510 /* Offset between adjacent src rows to be averaged together */
1511 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcWidth
* bpt
;
1514 * Need to average together up to 8 src pixels for each dest pixel.
1515 * Break that down into 3 operations:
1516 * 1. take two rows from source image and average them together.
1517 * 2. take two rows from next source image and average them together.
1518 * 3. take the two averaged rows and average them for the final dst row.
1522 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1523 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1526 for (img
= 0; img
< dstDepthNB
; img
++) {
1527 /* first source image pointer, skipping border */
1528 const GLubyte
*imgSrcA
= srcPtr
1529 + (bytesPerSrcImage
+ bytesPerSrcRow
+ border
) * bpt
* border
1530 + img
* (bytesPerSrcImage
+ srcImageOffset
);
1531 /* second source image pointer, skipping border */
1532 const GLubyte
*imgSrcB
= imgSrcA
+ srcImageOffset
;
1533 /* address of the dest image, skipping border */
1534 GLubyte
*imgDst
= dstPtr
1535 + (bytesPerDstImage
+ bytesPerDstRow
+ border
) * bpt
* border
1536 + img
* bytesPerDstImage
;
1538 /* setup the four source row pointers and the dest row pointer */
1539 const GLubyte
*srcImgARowA
= imgSrcA
;
1540 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
1541 const GLubyte
*srcImgBRowA
= imgSrcB
;
1542 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
1543 GLubyte
*dstImgRow
= imgDst
;
1545 for (row
= 0; row
< dstHeightNB
; row
++) {
1546 do_row_3D(datatype
, comps
, srcWidthNB
,
1547 srcImgARowA
, srcImgARowB
,
1548 srcImgBRowA
, srcImgBRowB
,
1549 dstWidthNB
, dstImgRow
);
1551 /* advance to next rows */
1552 srcImgARowA
+= bytesPerSrcRow
+ srcRowOffset
;
1553 srcImgARowB
+= bytesPerSrcRow
+ srcRowOffset
;
1554 srcImgBRowA
+= bytesPerSrcRow
+ srcRowOffset
;
1555 srcImgBRowB
+= bytesPerSrcRow
+ srcRowOffset
;
1556 dstImgRow
+= bytesPerDstRow
;
1561 /* Luckily we can leverage the make_2d_mipmap() function here! */
1563 /* do front border image */
1564 make_2d_mipmap(datatype
, comps
, 1, srcWidth
, srcHeight
, srcPtr
, srcRowStride
,
1565 dstWidth
, dstHeight
, dstPtr
, dstRowStride
);
1566 /* do back border image */
1567 make_2d_mipmap(datatype
, comps
, 1, srcWidth
, srcHeight
,
1568 srcPtr
+ bytesPerSrcImage
* (srcDepth
- 1), srcRowStride
,
1569 dstWidth
, dstHeight
,
1570 dstPtr
+ bytesPerDstImage
* (dstDepth
- 1), dstRowStride
);
1571 /* do four remaining border edges that span the image slices */
1572 if (srcDepth
== dstDepth
) {
1573 /* just copy border pixels from src to dst */
1574 for (img
= 0; img
< dstDepthNB
; img
++) {
1578 /* do border along [img][row=0][col=0] */
1579 src
= srcPtr
+ (img
+ 1) * bytesPerSrcImage
;
1580 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1581 memcpy(dst
, src
, bpt
);
1583 /* do border along [img][row=dstHeight-1][col=0] */
1584 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1585 + (srcHeight
- 1) * bytesPerSrcRow
;
1586 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1587 + (dstHeight
- 1) * bytesPerDstRow
;
1588 memcpy(dst
, src
, bpt
);
1590 /* do border along [img][row=0][col=dstWidth-1] */
1591 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1592 + (srcWidth
- 1) * bpt
;
1593 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1594 + (dstWidth
- 1) * bpt
;
1595 memcpy(dst
, src
, bpt
);
1597 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1598 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1599 + (bytesPerSrcImage
- bpt
);
1600 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1601 + (bytesPerDstImage
- bpt
);
1602 memcpy(dst
, src
, bpt
);
1606 /* average border pixels from adjacent src image pairs */
1607 ASSERT(srcDepthNB
== 2 * dstDepthNB
);
1608 for (img
= 0; img
< dstDepthNB
; img
++) {
1612 /* do border along [img][row=0][col=0] */
1613 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
;
1614 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
;
1615 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1617 /* do border along [img][row=dstHeight-1][col=0] */
1618 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1619 + (srcHeight
- 1) * bytesPerSrcRow
;
1620 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1621 + (dstHeight
- 1) * bytesPerDstRow
;
1622 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1624 /* do border along [img][row=0][col=dstWidth-1] */
1625 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1626 + (srcWidth
- 1) * bpt
;
1627 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1628 + (dstWidth
- 1) * bpt
;
1629 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1631 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1632 src
= srcPtr
+ (img
* 2 + 1) * bytesPerSrcImage
1633 + (bytesPerSrcImage
- bpt
);
1634 dst
= dstPtr
+ (img
+ 1) * bytesPerDstImage
1635 + (bytesPerDstImage
- bpt
);
1636 do_row(datatype
, comps
, 1, src
, src
+ srcImageOffset
, 1, dst
);
1644 make_1d_stack_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1645 GLint srcWidth
, const GLubyte
*srcPtr
, GLuint srcRowStride
,
1646 GLint dstWidth
, GLint dstHeight
,
1647 GLubyte
*dstPtr
, GLuint dstRowStride
)
1649 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1650 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1651 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1652 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1653 const GLint srcRowBytes
= bpt
* srcRowStride
;
1654 const GLint dstRowBytes
= bpt
* dstRowStride
;
1659 /* Compute src and dst pointers, skipping any border */
1660 src
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1661 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1663 for (row
= 0; row
< dstHeightNB
; row
++) {
1664 do_row(datatype
, comps
, srcWidthNB
, src
, src
,
1671 /* copy left-most pixel from source */
1674 memcpy(dstPtr
, srcPtr
, bpt
);
1675 /* copy right-most pixel from source */
1676 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1677 srcPtr
+ (srcWidth
- 1) * bpt
,
1685 * There is quite a bit of refactoring that could be done with this function
1686 * and \c make_2d_mipmap.
1689 make_2d_stack_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1690 GLint srcWidth
, GLint srcHeight
,
1691 const GLubyte
*srcPtr
, GLint srcRowStride
,
1692 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1693 GLubyte
*dstPtr
, GLint dstRowStride
)
1695 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1696 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1697 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1698 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1699 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1700 const GLint srcRowBytes
= bpt
* srcRowStride
;
1701 const GLint dstRowBytes
= bpt
* dstRowStride
;
1702 const GLubyte
*srcA
, *srcB
;
1707 /* Compute src and dst pointers, skipping any border */
1708 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1710 srcB
= srcA
+ srcRowBytes
;
1713 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1715 for (layer
= 0; layer
< dstDepthNB
; layer
++) {
1716 for (row
= 0; row
< dstHeightNB
; row
++) {
1717 do_row(datatype
, comps
, srcWidthNB
, srcA
, srcB
,
1719 srcA
+= 2 * srcRowBytes
;
1720 srcB
+= 2 * srcRowBytes
;
1724 /* This is ugly but probably won't be used much */
1726 /* fill in dest border */
1727 /* lower-left border pixel */
1730 memcpy(dstPtr
, srcPtr
, bpt
);
1731 /* lower-right border pixel */
1732 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1733 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
1734 /* upper-left border pixel */
1735 memcpy(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
1736 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
1737 /* upper-right border pixel */
1738 memcpy(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
1739 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
1741 do_row(datatype
, comps
, srcWidthNB
,
1744 dstWidthNB
, dstPtr
+ bpt
);
1746 do_row(datatype
, comps
, srcWidthNB
,
1747 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1748 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1750 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
1751 /* left and right borders */
1752 if (srcHeight
== dstHeight
) {
1753 /* copy border pixel from src to dst */
1754 for (row
= 1; row
< srcHeight
; row
++) {
1755 memcpy(dstPtr
+ dstWidth
* row
* bpt
,
1756 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
1757 memcpy(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
1758 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
1762 /* average two src pixels each dest pixel */
1763 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
1764 do_row(datatype
, comps
, 1,
1765 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
1766 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
1767 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
1768 do_row(datatype
, comps
, 1,
1769 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
1770 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
1771 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
1780 * Down-sample a texture image to produce the next lower mipmap level.
1781 * \param comps components per texel (1, 2, 3 or 4)
1782 * \param srcRowStride stride between source rows, in texels
1783 * \param dstRowStride stride between destination rows, in texels
1786 _mesa_generate_mipmap_level(GLenum target
,
1787 GLenum datatype
, GLuint comps
,
1789 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1790 const GLubyte
*srcData
,
1792 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1797 * We use simple 2x2 averaging to compute the next mipmap level.
1801 make_1d_mipmap(datatype
, comps
, border
,
1806 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
1807 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
1808 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
1809 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
1810 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
1811 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
1812 make_2d_mipmap(datatype
, comps
, border
,
1813 srcWidth
, srcHeight
, srcData
, srcRowStride
,
1814 dstWidth
, dstHeight
, dstData
, dstRowStride
);
1817 make_3d_mipmap(datatype
, comps
, border
,
1818 srcWidth
, srcHeight
, srcDepth
,
1819 srcData
, srcRowStride
,
1820 dstWidth
, dstHeight
, dstDepth
,
1821 dstData
, dstRowStride
);
1823 case GL_TEXTURE_1D_ARRAY_EXT
:
1824 make_1d_stack_mipmap(datatype
, comps
, border
,
1825 srcWidth
, srcData
, srcRowStride
,
1826 dstWidth
, dstHeight
,
1827 dstData
, dstRowStride
);
1829 case GL_TEXTURE_2D_ARRAY_EXT
:
1830 make_2d_stack_mipmap(datatype
, comps
, border
,
1831 srcWidth
, srcHeight
,
1832 srcData
, srcRowStride
,
1833 dstWidth
, dstHeight
,
1834 dstDepth
, dstData
, dstRowStride
);
1836 case GL_TEXTURE_RECTANGLE_NV
:
1837 /* no mipmaps, do nothing */
1840 _mesa_problem(NULL
, "bad dimensions in _mesa_generate_mipmaps");
1847 * compute next (level+1) image size
1848 * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1851 next_mipmap_level_size(GLenum target
, GLint border
,
1852 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1853 GLint
*dstWidth
, GLint
*dstHeight
, GLint
*dstDepth
)
1855 if (srcWidth
- 2 * border
> 1) {
1856 *dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
1859 *dstWidth
= srcWidth
; /* can't go smaller */
1862 if ((srcHeight
- 2 * border
> 1) &&
1863 (target
!= GL_TEXTURE_1D_ARRAY_EXT
)) {
1864 *dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
1867 *dstHeight
= srcHeight
; /* can't go smaller */
1870 if ((srcDepth
- 2 * border
> 1) &&
1871 (target
!= GL_TEXTURE_2D_ARRAY_EXT
)) {
1872 *dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
1875 *dstDepth
= srcDepth
; /* can't go smaller */
1878 if (*dstWidth
== srcWidth
&&
1879 *dstHeight
== srcHeight
&&
1880 *dstDepth
== srcDepth
) {
1889 generate_mipmap_uncompressed(struct gl_context
*ctx
, GLenum target
,
1890 struct gl_texture_object
*texObj
,
1891 const struct gl_texture_image
*srcImage
,
1898 _mesa_format_to_type_and_comps(srcImage
->TexFormat
, &datatype
, &comps
);
1900 for (level
= texObj
->BaseLevel
; level
< maxLevel
; level
++) {
1901 /* generate image[level+1] from image[level] */
1902 const struct gl_texture_image
*srcImage
;
1903 struct gl_texture_image
*dstImage
;
1904 GLint srcWidth
, srcHeight
, srcDepth
;
1905 GLint dstWidth
, dstHeight
, dstDepth
;
1907 GLboolean nextLevel
;
1909 /* get src image parameters */
1910 srcImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
1912 srcWidth
= srcImage
->Width
;
1913 srcHeight
= srcImage
->Height
;
1914 srcDepth
= srcImage
->Depth
;
1915 border
= srcImage
->Border
;
1917 nextLevel
= next_mipmap_level_size(target
, border
,
1918 srcWidth
, srcHeight
, srcDepth
,
1919 &dstWidth
, &dstHeight
, &dstDepth
);
1923 /* get dest gl_texture_image */
1924 dstImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
+ 1);
1926 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1930 /* Free old image data */
1932 ctx
->Driver
.FreeTexImageData(ctx
, dstImage
);
1934 /* initialize new image */
1935 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
1936 dstDepth
, border
, srcImage
->InternalFormat
,
1937 srcImage
->TexFormat
);
1938 dstImage
->DriverData
= NULL
;
1939 dstImage
->FetchTexelc
= srcImage
->FetchTexelc
;
1940 dstImage
->FetchTexelf
= srcImage
->FetchTexelf
;
1942 /* Alloc new teximage data buffer */
1944 GLuint size
= _mesa_format_image_size(dstImage
->TexFormat
,
1945 dstWidth
, dstHeight
, dstDepth
);
1946 dstImage
->Data
= _mesa_alloc_texmemory(size
);
1947 if (!dstImage
->Data
) {
1948 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
1953 ASSERT(dstImage
->TexFormat
);
1954 ASSERT(dstImage
->FetchTexelc
);
1955 ASSERT(dstImage
->FetchTexelf
);
1957 _mesa_generate_mipmap_level(target
, datatype
, comps
, border
,
1958 srcWidth
, srcHeight
, srcDepth
,
1959 srcImage
->Data
, srcImage
->RowStride
,
1960 dstWidth
, dstHeight
, dstDepth
,
1961 dstImage
->Data
, dstImage
->RowStride
);
1963 } /* loop over mipmap levels */
1967 generate_mipmap_compressed(struct gl_context
*ctx
, GLenum target
,
1968 struct gl_texture_object
*texObj
,
1969 const struct gl_texture_image
*srcImage
,
1973 gl_format temp_format
;
1978 GLuint temp_src_stride
, temp_dst_stride
; /* in bytes */
1979 GLchan
*temp_src
= NULL
, *temp_dst
= NULL
;
1981 /* Choose the format we will do _mesa_generate_mipmap_level() in,
1982 * and uncompress the firstImage into a temporary of that format.
1984 assert(texObj
->Target
== GL_TEXTURE_2D
||
1985 texObj
->Target
== GL_TEXTURE_CUBE_MAP_ARB
);
1987 if (srcImage
->_BaseFormat
== GL_RGB
) {
1988 temp_format
= MESA_FORMAT_RGB888
;
1990 } else if (srcImage
->_BaseFormat
== GL_RED
) {
1991 temp_format
= MESA_FORMAT_R8
;
1993 } else if (srcImage
->_BaseFormat
== GL_RG
) {
1994 temp_format
= MESA_FORMAT_RG88
;
1996 } else if (srcImage
->_BaseFormat
== GL_RGBA
) {
1997 temp_format
= MESA_FORMAT_RGBA8888
;
1999 } else if (srcImage
->_BaseFormat
== GL_LUMINANCE
) {
2000 temp_format
= MESA_FORMAT_L8
;
2002 } else if (srcImage
->_BaseFormat
== GL_LUMINANCE_ALPHA
) {
2003 temp_format
= MESA_FORMAT_AL88
;
2006 _mesa_problem(ctx
, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
2010 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
2011 temp_src_stride
= _mesa_format_row_stride(temp_format
, srcImage
->Width
);
2012 /* 20 extra bytes, just be safe when calling last FetchTexel */
2013 temp_src
= (GLubyte
*) malloc(temp_src_stride
* srcImage
->Height
+ 20);
2015 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
2019 /* decompress base image to the temporary */
2020 for (row
= 0; row
< srcImage
->Height
; row
++) {
2022 GLchan
*dst
= (GLchan
*) temp_src
+ temp_src_stride
* row
;
2023 for (col
= 0; col
< srcImage
->Width
; col
++) {
2024 srcImage
->FetchTexelc(srcImage
, col
, row
, 0, dst
);
2029 _mesa_format_to_type_and_comps(temp_format
, &datatype
, &comps
);
2031 for (level
= texObj
->BaseLevel
; level
< maxLevel
; level
++) {
2032 /* generate image[level+1] from image[level] */
2033 const struct gl_texture_image
*srcImage
;
2034 struct gl_texture_image
*dstImage
;
2035 GLint srcWidth
, srcHeight
, srcDepth
;
2036 GLint dstWidth
, dstHeight
, dstDepth
;
2038 GLboolean nextLevel
;
2040 /* get src image parameters */
2041 srcImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
2043 srcWidth
= srcImage
->Width
;
2044 srcHeight
= srcImage
->Height
;
2045 srcDepth
= srcImage
->Depth
;
2046 border
= srcImage
->Border
;
2048 nextLevel
= next_mipmap_level_size(target
, border
,
2049 srcWidth
, srcHeight
, srcDepth
,
2050 &dstWidth
, &dstHeight
, &dstDepth
);
2054 temp_dst_stride
= _mesa_format_row_stride(temp_format
, dstWidth
);
2056 temp_dst
= (GLubyte
*) malloc(temp_dst_stride
* dstHeight
);
2058 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
2063 /* get dest gl_texture_image */
2064 dstImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
+ 1);
2066 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generating mipmaps");
2070 _mesa_generate_mipmap_level(target
, datatype
, comps
, border
,
2071 srcWidth
, srcHeight
, srcDepth
,
2072 temp_src
, temp_src_stride
/ components
,
2073 dstWidth
, dstHeight
, dstDepth
,
2074 temp_dst
, temp_dst_stride
/ components
);
2076 /* initialize new image */
2077 _mesa_init_teximage_fields(ctx
, target
, dstImage
, dstWidth
, dstHeight
,
2078 dstDepth
, border
, srcImage
->InternalFormat
,
2079 srcImage
->TexFormat
);
2081 ctx
->Driver
.TexImage2D(ctx
, target
, level
+ 1,
2082 srcImage
->InternalFormat
,
2083 dstWidth
, dstHeight
, border
,
2084 _mesa_get_format_base_format(temp_format
),
2086 temp_dst
, &ctx
->DefaultPacking
, texObj
, dstImage
);
2088 /* swap src and dest pointers */
2090 GLchan
*temp
= temp_src
;
2091 temp_src
= temp_dst
;
2094 temp_src_stride
= temp_dst_stride
;
2096 } /* loop over mipmap levels */
2098 free((void *) temp_src
);
2103 * Automatic mipmap generation.
2104 * This is the fallback/default function for ctx->Driver.GenerateMipmap().
2105 * Generate a complete set of mipmaps from texObj's BaseLevel image.
2106 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
2107 * For cube maps, target will be one of
2108 * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
2111 _mesa_generate_mipmap(struct gl_context
*ctx
, GLenum target
,
2112 struct gl_texture_object
*texObj
)
2114 const struct gl_texture_image
*srcImage
;
2118 srcImage
= _mesa_select_tex_image(ctx
, texObj
, target
, texObj
->BaseLevel
);
2121 maxLevel
= _mesa_max_texture_levels(ctx
, texObj
->Target
) - 1;
2122 ASSERT(maxLevel
>= 0); /* bad target */
2124 maxLevel
= MIN2(maxLevel
, texObj
->MaxLevel
);
2126 if (_mesa_is_format_compressed(srcImage
->TexFormat
)) {
2127 generate_mipmap_compressed(ctx
, target
, texObj
, srcImage
, maxLevel
);
2129 generate_mipmap_uncompressed(ctx
, target
, texObj
, srcImage
, maxLevel
);
2135 * Helper function for drivers which need to rescale texture images to
2136 * certain aspect ratios.
2137 * Nearest filtering only (for broken hardware that can't support
2138 * all aspect ratios). This can be made a lot faster, but I don't
2139 * really care enough...
2142 _mesa_rescale_teximage2d(GLuint bytesPerPixel
,
2143 GLuint srcStrideInPixels
,
2144 GLuint dstRowStride
,
2145 GLint srcWidth
, GLint srcHeight
,
2146 GLint dstWidth
, GLint dstHeight
,
2147 const GLvoid
*srcImage
, GLvoid
*dstImage
)
2151 #define INNER_LOOP( TYPE, HOP, WOP ) \
2152 for ( row = 0 ; row < dstHeight ; row++ ) { \
2153 GLint srcRow = row HOP hScale; \
2154 for ( col = 0 ; col < dstWidth ; col++ ) { \
2155 GLint srcCol = col WOP wScale; \
2156 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
2158 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
2161 #define RESCALE_IMAGE( TYPE ) \
2163 const TYPE *src = (const TYPE *)srcImage; \
2164 TYPE *dst = (TYPE *)dstImage; \
2166 if ( srcHeight < dstHeight ) { \
2167 const GLint hScale = dstHeight / srcHeight; \
2168 if ( srcWidth < dstWidth ) { \
2169 const GLint wScale = dstWidth / srcWidth; \
2170 INNER_LOOP( TYPE, /, / ); \
2173 const GLint wScale = srcWidth / dstWidth; \
2174 INNER_LOOP( TYPE, /, * ); \
2178 const GLint hScale = srcHeight / dstHeight; \
2179 if ( srcWidth < dstWidth ) { \
2180 const GLint wScale = dstWidth / srcWidth; \
2181 INNER_LOOP( TYPE, *, / ); \
2184 const GLint wScale = srcWidth / dstWidth; \
2185 INNER_LOOP( TYPE, *, * ); \
2190 switch ( bytesPerPixel
) {
2192 RESCALE_IMAGE( GLuint
);
2196 RESCALE_IMAGE( GLushort
);
2200 RESCALE_IMAGE( GLubyte
);
2203 _mesa_problem(NULL
,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
2209 * Upscale an image by replication, not (typical) stretching.
2210 * We use this when the image width or height is less than a
2211 * certain size (4, 8) and we need to upscale an image.
2214 _mesa_upscale_teximage2d(GLsizei inWidth
, GLsizei inHeight
,
2215 GLsizei outWidth
, GLsizei outHeight
,
2216 GLint comps
, const GLchan
*src
, GLint srcRowStride
,
2221 ASSERT(outWidth
>= inWidth
);
2222 ASSERT(outHeight
>= inHeight
);
2224 ASSERT(inWidth
== 1 || inWidth
== 2 || inHeight
== 1 || inHeight
== 2);
2225 ASSERT((outWidth
& 3) == 0);
2226 ASSERT((outHeight
& 3) == 0);
2229 for (i
= 0; i
< outHeight
; i
++) {
2230 const GLint ii
= i
% inHeight
;
2231 for (j
= 0; j
< outWidth
; j
++) {
2232 const GLint jj
= j
% inWidth
;
2233 for (k
= 0; k
< comps
; k
++) {
2234 dest
[(i
* outWidth
+ j
) * comps
+ k
]
2235 = src
[ii
* srcRowStride
+ jj
* comps
+ k
];