2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
27 * \file mipmap.c mipmap generation and teximage resizing functions.
32 #include "glformats.h"
40 #include "util/half_float.h"
41 #include "util/format_rgb9e5.h"
42 #include "util/format_r11g11b10f.h"
46 * Compute the expected number of mipmap levels in the texture given
47 * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
48 * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap
49 * levels should be generated.
52 _mesa_compute_num_levels(struct gl_context
*ctx
,
53 struct gl_texture_object
*texObj
,
56 const struct gl_texture_image
*baseImage
;
59 baseImage
= _mesa_get_tex_image(ctx
, texObj
, target
, texObj
->BaseLevel
);
61 numLevels
= texObj
->BaseLevel
+ baseImage
->MaxNumLevels
;
62 numLevels
= MIN2(numLevels
, (GLuint
) texObj
->MaxLevel
+ 1);
63 if (texObj
->Immutable
)
64 numLevels
= MIN2(numLevels
, texObj
->NumLevels
);
65 assert(numLevels
>= 1);
71 bytes_per_pixel(GLenum datatype
, GLuint comps
)
75 if (datatype
== GL_UNSIGNED_INT_8_24_REV_MESA
||
76 datatype
== GL_UNSIGNED_INT_24_8_MESA
)
79 b
= _mesa_sizeof_packed_type(datatype
);
82 if (_mesa_type_is_packed(datatype
))
90 * \name Support macros for do_row and do_row_3d
92 * The macro madness is here for two reasons. First, it compacts the code
93 * slightly. Second, it makes it much easier to adjust the specifics of the
94 * filter to tune the rounding characteristics.
97 #define DECLARE_ROW_POINTERS(t, e) \
98 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
99 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
100 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
101 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
102 t(*dst)[e] = (t(*)[e]) dstRow
104 #define DECLARE_ROW_POINTERS0(t) \
105 const t *rowA = (const t *) srcRowA; \
106 const t *rowB = (const t *) srcRowB; \
107 const t *rowC = (const t *) srcRowC; \
108 const t *rowD = (const t *) srcRowD; \
109 t *dst = (t *) dstRow
111 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
112 ((unsigned) Aj + (unsigned) Ak \
113 + (unsigned) Bj + (unsigned) Bk \
114 + (unsigned) Cj + (unsigned) Ck \
115 + (unsigned) Dj + (unsigned) Dk \
118 #define FILTER_3D(e) \
120 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
121 rowB[j][e], rowB[k][e], \
122 rowC[j][e], rowC[k][e], \
123 rowD[j][e], rowD[k][e]); \
126 #define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
133 #define FILTER_3D_SIGNED(e) \
135 dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
136 rowB[j][e], rowB[k][e], \
137 rowC[j][e], rowC[k][e], \
138 rowD[j][e], rowD[k][e]); \
141 #define FILTER_F_3D(e) \
143 dst[i][e] = (rowA[j][e] + rowA[k][e] \
144 + rowB[j][e] + rowB[k][e] \
145 + rowC[j][e] + rowC[k][e] \
146 + rowD[j][e] + rowD[k][e]) * 0.125F; \
149 #define FILTER_HF_3D(e) \
151 const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
152 const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
153 const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
154 const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
155 const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
156 const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
157 const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
158 const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
159 dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
166 * Average together two rows of a source image to produce a single new
167 * row in the dest image. It's legal for the two source rows to point
168 * to the same data. The source width must be equal to either the
169 * dest width or two times the dest width.
170 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
171 * \param comps number of components per pixel (1..4)
174 do_row(GLenum datatype
, GLuint comps
, GLint srcWidth
,
175 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
176 GLint dstWidth
, GLvoid
*dstRow
)
178 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
179 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
184 /* This assertion is no longer valid with non-power-of-2 textures
185 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
188 if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 4) {
190 const GLubyte(*rowA
)[4] = (const GLubyte(*)[4]) srcRowA
;
191 const GLubyte(*rowB
)[4] = (const GLubyte(*)[4]) srcRowB
;
192 GLubyte(*dst
)[4] = (GLubyte(*)[4]) dstRow
;
193 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
194 i
++, j
+= colStride
, k
+= colStride
) {
195 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
196 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
197 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
198 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
201 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 3) {
203 const GLubyte(*rowA
)[3] = (const GLubyte(*)[3]) srcRowA
;
204 const GLubyte(*rowB
)[3] = (const GLubyte(*)[3]) srcRowB
;
205 GLubyte(*dst
)[3] = (GLubyte(*)[3]) dstRow
;
206 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
207 i
++, j
+= colStride
, k
+= colStride
) {
208 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
209 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
210 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
213 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 2) {
215 const GLubyte(*rowA
)[2] = (const GLubyte(*)[2]) srcRowA
;
216 const GLubyte(*rowB
)[2] = (const GLubyte(*)[2]) srcRowB
;
217 GLubyte(*dst
)[2] = (GLubyte(*)[2]) dstRow
;
218 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
219 i
++, j
+= colStride
, k
+= colStride
) {
220 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
221 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
224 else if (datatype
== GL_UNSIGNED_BYTE
&& comps
== 1) {
226 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
227 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
228 GLubyte
*dst
= (GLubyte
*) dstRow
;
229 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
230 i
++, j
+= colStride
, k
+= colStride
) {
231 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
235 else if (datatype
== GL_BYTE
&& comps
== 4) {
237 const GLbyte(*rowA
)[4] = (const GLbyte(*)[4]) srcRowA
;
238 const GLbyte(*rowB
)[4] = (const GLbyte(*)[4]) srcRowB
;
239 GLbyte(*dst
)[4] = (GLbyte(*)[4]) dstRow
;
240 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
241 i
++, j
+= colStride
, k
+= colStride
) {
242 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
243 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
244 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
245 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
248 else if (datatype
== GL_BYTE
&& comps
== 3) {
250 const GLbyte(*rowA
)[3] = (const GLbyte(*)[3]) srcRowA
;
251 const GLbyte(*rowB
)[3] = (const GLbyte(*)[3]) srcRowB
;
252 GLbyte(*dst
)[3] = (GLbyte(*)[3]) dstRow
;
253 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
254 i
++, j
+= colStride
, k
+= colStride
) {
255 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
256 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
257 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
260 else if (datatype
== GL_BYTE
&& comps
== 2) {
262 const GLbyte(*rowA
)[2] = (const GLbyte(*)[2]) srcRowA
;
263 const GLbyte(*rowB
)[2] = (const GLbyte(*)[2]) srcRowB
;
264 GLbyte(*dst
)[2] = (GLbyte(*)[2]) dstRow
;
265 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
266 i
++, j
+= colStride
, k
+= colStride
) {
267 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
268 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
271 else if (datatype
== GL_BYTE
&& comps
== 1) {
273 const GLbyte
*rowA
= (const GLbyte
*) srcRowA
;
274 const GLbyte
*rowB
= (const GLbyte
*) srcRowB
;
275 GLbyte
*dst
= (GLbyte
*) dstRow
;
276 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
277 i
++, j
+= colStride
, k
+= colStride
) {
278 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
282 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 4) {
284 const GLushort(*rowA
)[4] = (const GLushort(*)[4]) srcRowA
;
285 const GLushort(*rowB
)[4] = (const GLushort(*)[4]) srcRowB
;
286 GLushort(*dst
)[4] = (GLushort(*)[4]) dstRow
;
287 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
288 i
++, j
+= colStride
, k
+= colStride
) {
289 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
290 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
291 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
292 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
295 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 3) {
297 const GLushort(*rowA
)[3] = (const GLushort(*)[3]) srcRowA
;
298 const GLushort(*rowB
)[3] = (const GLushort(*)[3]) srcRowB
;
299 GLushort(*dst
)[3] = (GLushort(*)[3]) dstRow
;
300 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
301 i
++, j
+= colStride
, k
+= colStride
) {
302 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
303 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
304 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
307 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 2) {
309 const GLushort(*rowA
)[2] = (const GLushort(*)[2]) srcRowA
;
310 const GLushort(*rowB
)[2] = (const GLushort(*)[2]) srcRowB
;
311 GLushort(*dst
)[2] = (GLushort(*)[2]) dstRow
;
312 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
313 i
++, j
+= colStride
, k
+= colStride
) {
314 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
315 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
318 else if (datatype
== GL_UNSIGNED_SHORT
&& comps
== 1) {
320 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
321 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
322 GLushort
*dst
= (GLushort
*) dstRow
;
323 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
324 i
++, j
+= colStride
, k
+= colStride
) {
325 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
329 else if (datatype
== GL_SHORT
&& comps
== 4) {
331 const GLshort(*rowA
)[4] = (const GLshort(*)[4]) srcRowA
;
332 const GLshort(*rowB
)[4] = (const GLshort(*)[4]) srcRowB
;
333 GLshort(*dst
)[4] = (GLshort(*)[4]) dstRow
;
334 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
335 i
++, j
+= colStride
, k
+= colStride
) {
336 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
337 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
338 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
339 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
342 else if (datatype
== GL_SHORT
&& comps
== 3) {
344 const GLshort(*rowA
)[3] = (const GLshort(*)[3]) srcRowA
;
345 const GLshort(*rowB
)[3] = (const GLshort(*)[3]) srcRowB
;
346 GLshort(*dst
)[3] = (GLshort(*)[3]) dstRow
;
347 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
348 i
++, j
+= colStride
, k
+= colStride
) {
349 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
350 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
351 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
354 else if (datatype
== GL_SHORT
&& comps
== 2) {
356 const GLshort(*rowA
)[2] = (const GLshort(*)[2]) srcRowA
;
357 const GLshort(*rowB
)[2] = (const GLshort(*)[2]) srcRowB
;
358 GLshort(*dst
)[2] = (GLshort(*)[2]) dstRow
;
359 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
360 i
++, j
+= colStride
, k
+= colStride
) {
361 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
362 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
365 else if (datatype
== GL_SHORT
&& comps
== 1) {
367 const GLshort
*rowA
= (const GLshort
*) srcRowA
;
368 const GLshort
*rowB
= (const GLshort
*) srcRowB
;
369 GLshort
*dst
= (GLshort
*) dstRow
;
370 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
371 i
++, j
+= colStride
, k
+= colStride
) {
372 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
376 else if (datatype
== GL_FLOAT
&& comps
== 4) {
378 const GLfloat(*rowA
)[4] = (const GLfloat(*)[4]) srcRowA
;
379 const GLfloat(*rowB
)[4] = (const GLfloat(*)[4]) srcRowB
;
380 GLfloat(*dst
)[4] = (GLfloat(*)[4]) dstRow
;
381 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
382 i
++, j
+= colStride
, k
+= colStride
) {
383 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
384 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
385 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
386 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
387 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
388 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
389 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
390 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
393 else if (datatype
== GL_FLOAT
&& comps
== 3) {
395 const GLfloat(*rowA
)[3] = (const GLfloat(*)[3]) srcRowA
;
396 const GLfloat(*rowB
)[3] = (const GLfloat(*)[3]) srcRowB
;
397 GLfloat(*dst
)[3] = (GLfloat(*)[3]) dstRow
;
398 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
399 i
++, j
+= colStride
, k
+= colStride
) {
400 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
401 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
402 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
403 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
404 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
405 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
408 else if (datatype
== GL_FLOAT
&& comps
== 2) {
410 const GLfloat(*rowA
)[2] = (const GLfloat(*)[2]) srcRowA
;
411 const GLfloat(*rowB
)[2] = (const GLfloat(*)[2]) srcRowB
;
412 GLfloat(*dst
)[2] = (GLfloat(*)[2]) dstRow
;
413 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
414 i
++, j
+= colStride
, k
+= colStride
) {
415 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
416 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
417 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
418 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
421 else if (datatype
== GL_FLOAT
&& comps
== 1) {
423 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
424 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
425 GLfloat
*dst
= (GLfloat
*) dstRow
;
426 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
427 i
++, j
+= colStride
, k
+= colStride
) {
428 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
432 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 4) {
433 GLuint i
, j
, k
, comp
;
434 const GLhalfARB(*rowA
)[4] = (const GLhalfARB(*)[4]) srcRowA
;
435 const GLhalfARB(*rowB
)[4] = (const GLhalfARB(*)[4]) srcRowB
;
436 GLhalfARB(*dst
)[4] = (GLhalfARB(*)[4]) dstRow
;
437 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
438 i
++, j
+= colStride
, k
+= colStride
) {
439 for (comp
= 0; comp
< 4; comp
++) {
440 GLfloat aj
, ak
, bj
, bk
;
441 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
442 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
443 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
444 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
445 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
449 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 3) {
450 GLuint i
, j
, k
, comp
;
451 const GLhalfARB(*rowA
)[3] = (const GLhalfARB(*)[3]) srcRowA
;
452 const GLhalfARB(*rowB
)[3] = (const GLhalfARB(*)[3]) srcRowB
;
453 GLhalfARB(*dst
)[3] = (GLhalfARB(*)[3]) dstRow
;
454 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
455 i
++, j
+= colStride
, k
+= colStride
) {
456 for (comp
= 0; comp
< 3; comp
++) {
457 GLfloat aj
, ak
, bj
, bk
;
458 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
459 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
460 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
461 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
462 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
466 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 2) {
467 GLuint i
, j
, k
, comp
;
468 const GLhalfARB(*rowA
)[2] = (const GLhalfARB(*)[2]) srcRowA
;
469 const GLhalfARB(*rowB
)[2] = (const GLhalfARB(*)[2]) srcRowB
;
470 GLhalfARB(*dst
)[2] = (GLhalfARB(*)[2]) dstRow
;
471 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
472 i
++, j
+= colStride
, k
+= colStride
) {
473 for (comp
= 0; comp
< 2; comp
++) {
474 GLfloat aj
, ak
, bj
, bk
;
475 aj
= _mesa_half_to_float(rowA
[j
][comp
]);
476 ak
= _mesa_half_to_float(rowA
[k
][comp
]);
477 bj
= _mesa_half_to_float(rowB
[j
][comp
]);
478 bk
= _mesa_half_to_float(rowB
[k
][comp
]);
479 dst
[i
][comp
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
483 else if (datatype
== GL_HALF_FLOAT_ARB
&& comps
== 1) {
485 const GLhalfARB
*rowA
= (const GLhalfARB
*) srcRowA
;
486 const GLhalfARB
*rowB
= (const GLhalfARB
*) srcRowB
;
487 GLhalfARB
*dst
= (GLhalfARB
*) dstRow
;
488 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
489 i
++, j
+= colStride
, k
+= colStride
) {
490 GLfloat aj
, ak
, bj
, bk
;
491 aj
= _mesa_half_to_float(rowA
[j
]);
492 ak
= _mesa_half_to_float(rowA
[k
]);
493 bj
= _mesa_half_to_float(rowB
[j
]);
494 bk
= _mesa_half_to_float(rowB
[k
]);
495 dst
[i
] = _mesa_float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
499 else if (datatype
== GL_UNSIGNED_INT
&& comps
== 1) {
501 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
502 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
503 GLuint
*dst
= (GLuint
*) dstRow
;
504 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
505 i
++, j
+= colStride
, k
+= colStride
) {
506 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
510 else if (datatype
== GL_UNSIGNED_SHORT_5_6_5
&& comps
== 3) {
512 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
513 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
514 GLushort
*dst
= (GLushort
*) dstRow
;
515 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
516 i
++, j
+= colStride
, k
+= colStride
) {
517 const GLint rowAr0
= rowA
[j
] & 0x1f;
518 const GLint rowAr1
= rowA
[k
] & 0x1f;
519 const GLint rowBr0
= rowB
[j
] & 0x1f;
520 const GLint rowBr1
= rowB
[k
] & 0x1f;
521 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
522 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
523 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
524 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
525 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
526 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
527 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
528 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
529 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
530 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
531 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
532 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
535 else if (datatype
== GL_UNSIGNED_SHORT_4_4_4_4
&& comps
== 4) {
537 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
538 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
539 GLushort
*dst
= (GLushort
*) dstRow
;
540 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
541 i
++, j
+= colStride
, k
+= colStride
) {
542 const GLint rowAr0
= rowA
[j
] & 0xf;
543 const GLint rowAr1
= rowA
[k
] & 0xf;
544 const GLint rowBr0
= rowB
[j
] & 0xf;
545 const GLint rowBr1
= rowB
[k
] & 0xf;
546 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
547 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
548 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
549 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
550 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
551 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
552 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
553 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
554 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
555 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
556 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
557 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
558 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
559 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
560 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
561 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
562 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
565 else if (datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
&& comps
== 4) {
567 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
568 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
569 GLushort
*dst
= (GLushort
*) dstRow
;
570 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
571 i
++, j
+= colStride
, k
+= colStride
) {
572 const GLint rowAr0
= rowA
[j
] & 0x1f;
573 const GLint rowAr1
= rowA
[k
] & 0x1f;
574 const GLint rowBr0
= rowB
[j
] & 0x1f;
575 const GLint rowBr1
= rowB
[k
] & 0x1f;
576 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
577 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
578 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
579 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
580 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
581 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
582 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
583 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
584 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
585 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
586 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
587 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
588 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
589 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
590 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
591 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
592 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
595 else if (datatype
== GL_UNSIGNED_SHORT_5_5_5_1
&& comps
== 4) {
597 const GLushort
*rowA
= (const GLushort
*) srcRowA
;
598 const GLushort
*rowB
= (const GLushort
*) srcRowB
;
599 GLushort
*dst
= (GLushort
*) dstRow
;
600 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
601 i
++, j
+= colStride
, k
+= colStride
) {
602 const GLint rowAr0
= (rowA
[j
] >> 11) & 0x1f;
603 const GLint rowAr1
= (rowA
[k
] >> 11) & 0x1f;
604 const GLint rowBr0
= (rowB
[j
] >> 11) & 0x1f;
605 const GLint rowBr1
= (rowB
[k
] >> 11) & 0x1f;
606 const GLint rowAg0
= (rowA
[j
] >> 6) & 0x1f;
607 const GLint rowAg1
= (rowA
[k
] >> 6) & 0x1f;
608 const GLint rowBg0
= (rowB
[j
] >> 6) & 0x1f;
609 const GLint rowBg1
= (rowB
[k
] >> 6) & 0x1f;
610 const GLint rowAb0
= (rowA
[j
] >> 1) & 0x1f;
611 const GLint rowAb1
= (rowA
[k
] >> 1) & 0x1f;
612 const GLint rowBb0
= (rowB
[j
] >> 1) & 0x1f;
613 const GLint rowBb1
= (rowB
[k
] >> 1) & 0x1f;
614 const GLint rowAa0
= (rowA
[j
] & 0x1);
615 const GLint rowAa1
= (rowA
[k
] & 0x1);
616 const GLint rowBa0
= (rowB
[j
] & 0x1);
617 const GLint rowBa1
= (rowB
[k
] & 0x1);
618 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
619 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
620 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
621 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
622 dst
[i
] = (red
<< 11) | (green
<< 6) | (blue
<< 1) | alpha
;
626 else if (datatype
== GL_UNSIGNED_BYTE_3_3_2
&& comps
== 3) {
628 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
629 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
630 GLubyte
*dst
= (GLubyte
*) dstRow
;
631 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
632 i
++, j
+= colStride
, k
+= colStride
) {
633 const GLint rowAr0
= rowA
[j
] & 0x3;
634 const GLint rowAr1
= rowA
[k
] & 0x3;
635 const GLint rowBr0
= rowB
[j
] & 0x3;
636 const GLint rowBr1
= rowB
[k
] & 0x3;
637 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
638 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
639 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
640 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
641 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
642 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
643 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
644 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
645 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
646 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
647 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
648 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
652 else if (datatype
== MESA_UNSIGNED_BYTE_4_4
&& comps
== 2) {
654 const GLubyte
*rowA
= (const GLubyte
*) srcRowA
;
655 const GLubyte
*rowB
= (const GLubyte
*) srcRowB
;
656 GLubyte
*dst
= (GLubyte
*) dstRow
;
657 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
658 i
++, j
+= colStride
, k
+= colStride
) {
659 const GLint rowAr0
= rowA
[j
] & 0xf;
660 const GLint rowAr1
= rowA
[k
] & 0xf;
661 const GLint rowBr0
= rowB
[j
] & 0xf;
662 const GLint rowBr1
= rowB
[k
] & 0xf;
663 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
664 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
665 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
666 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
667 const GLint r
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
668 const GLint g
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
669 dst
[i
] = (g
<< 4) | r
;
673 else if (datatype
== GL_UNSIGNED_INT_2_10_10_10_REV
&& comps
== 4) {
675 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
676 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
677 GLuint
*dst
= (GLuint
*) dstRow
;
678 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
679 i
++, j
+= colStride
, k
+= colStride
) {
680 const GLint rowAr0
= rowA
[j
] & 0x3ff;
681 const GLint rowAr1
= rowA
[k
] & 0x3ff;
682 const GLint rowBr0
= rowB
[j
] & 0x3ff;
683 const GLint rowBr1
= rowB
[k
] & 0x3ff;
684 const GLint rowAg0
= (rowA
[j
] >> 10) & 0x3ff;
685 const GLint rowAg1
= (rowA
[k
] >> 10) & 0x3ff;
686 const GLint rowBg0
= (rowB
[j
] >> 10) & 0x3ff;
687 const GLint rowBg1
= (rowB
[k
] >> 10) & 0x3ff;
688 const GLint rowAb0
= (rowA
[j
] >> 20) & 0x3ff;
689 const GLint rowAb1
= (rowA
[k
] >> 20) & 0x3ff;
690 const GLint rowBb0
= (rowB
[j
] >> 20) & 0x3ff;
691 const GLint rowBb1
= (rowB
[k
] >> 20) & 0x3ff;
692 const GLint rowAa0
= (rowA
[j
] >> 30) & 0x3;
693 const GLint rowAa1
= (rowA
[k
] >> 30) & 0x3;
694 const GLint rowBa0
= (rowB
[j
] >> 30) & 0x3;
695 const GLint rowBa1
= (rowB
[k
] >> 30) & 0x3;
696 const GLint red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
697 const GLint green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
698 const GLint blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
699 const GLint alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
700 dst
[i
] = (alpha
<< 30) | (blue
<< 20) | (green
<< 10) | red
;
704 else if (datatype
== GL_UNSIGNED_INT_5_9_9_9_REV
&& comps
== 3) {
706 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
707 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
708 GLuint
*dst
= (GLuint
*)dstRow
;
709 GLfloat res
[3], rowAj
[3], rowBj
[3], rowAk
[3], rowBk
[3];
710 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
711 i
++, j
+= colStride
, k
+= colStride
) {
712 rgb9e5_to_float3(rowA
[j
], rowAj
);
713 rgb9e5_to_float3(rowB
[j
], rowBj
);
714 rgb9e5_to_float3(rowA
[k
], rowAk
);
715 rgb9e5_to_float3(rowB
[k
], rowBk
);
716 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0]) * 0.25F
;
717 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1]) * 0.25F
;
718 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2]) * 0.25F
;
719 dst
[i
] = float3_to_rgb9e5(res
);
723 else if (datatype
== GL_UNSIGNED_INT_10F_11F_11F_REV
&& comps
== 3) {
725 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
726 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
727 GLuint
*dst
= (GLuint
*)dstRow
;
728 GLfloat res
[3], rowAj
[3], rowBj
[3], rowAk
[3], rowBk
[3];
729 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
730 i
++, j
+= colStride
, k
+= colStride
) {
731 r11g11b10f_to_float3(rowA
[j
], rowAj
);
732 r11g11b10f_to_float3(rowB
[j
], rowBj
);
733 r11g11b10f_to_float3(rowA
[k
], rowAk
);
734 r11g11b10f_to_float3(rowB
[k
], rowBk
);
735 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0]) * 0.25F
;
736 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1]) * 0.25F
;
737 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2]) * 0.25F
;
738 dst
[i
] = float3_to_r11g11b10f(res
);
742 else if (datatype
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
&& comps
== 1) {
744 const GLfloat
*rowA
= (const GLfloat
*) srcRowA
;
745 const GLfloat
*rowB
= (const GLfloat
*) srcRowB
;
746 GLfloat
*dst
= (GLfloat
*) dstRow
;
747 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
748 i
++, j
+= colStride
, k
+= colStride
) {
749 dst
[i
*2] = (rowA
[j
*2] + rowA
[k
*2] + rowB
[j
*2] + rowB
[k
*2]) * 0.25F
;
753 else if (datatype
== GL_UNSIGNED_INT_24_8_MESA
&& comps
== 2) {
755 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
756 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
757 GLuint
*dst
= (GLuint
*) dstRow
;
758 /* note: averaging stencil values seems weird, but what else? */
759 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
760 i
++, j
+= colStride
, k
+= colStride
) {
761 GLuint z
= (((rowA
[j
] >> 8) + (rowA
[k
] >> 8) +
762 (rowB
[j
] >> 8) + (rowB
[k
] >> 8)) / 4) << 8;
763 GLuint s
= ((rowA
[j
] & 0xff) + (rowA
[k
] & 0xff) +
764 (rowB
[j
] & 0xff) + (rowB
[k
] & 0xff)) / 4;
768 else if (datatype
== GL_UNSIGNED_INT_8_24_REV_MESA
&& comps
== 2) {
770 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
771 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
772 GLuint
*dst
= (GLuint
*) dstRow
;
773 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
774 i
++, j
+= colStride
, k
+= colStride
) {
775 GLuint z
= ((rowA
[j
] & 0xffffff) + (rowA
[k
] & 0xffffff) +
776 (rowB
[j
] & 0xffffff) + (rowB
[k
] & 0xffffff)) / 4;
777 GLuint s
= (((rowA
[j
] >> 24) + (rowA
[k
] >> 24) +
778 (rowB
[j
] >> 24) + (rowB
[k
] >> 24)) / 4) << 24;
784 unreachable("bad format in do_row()");
790 * Average together four rows of a source image to produce a single new
791 * row in the dest image. It's legal for the two source rows to point
792 * to the same data. The source width must be equal to either the
793 * dest width or two times the dest width.
795 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
797 * \param comps number of components per pixel (1..4)
798 * \param srcWidth Width of a row in the source data
799 * \param srcRowA Pointer to one of the rows of source data
800 * \param srcRowB Pointer to one of the rows of source data
801 * \param srcRowC Pointer to one of the rows of source data
802 * \param srcRowD Pointer to one of the rows of source data
803 * \param dstWidth Width of a row in the destination data
804 * \param srcRowA Pointer to the row of destination data
807 do_row_3D(GLenum datatype
, GLuint comps
, GLint srcWidth
,
808 const GLvoid
*srcRowA
, const GLvoid
*srcRowB
,
809 const GLvoid
*srcRowC
, const GLvoid
*srcRowD
,
810 GLint dstWidth
, GLvoid
*dstRow
)
812 const GLuint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
813 const GLuint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
819 if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 4)) {
820 DECLARE_ROW_POINTERS(GLubyte
, 4);
822 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
823 i
++, j
+= colStride
, k
+= colStride
) {
830 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 3)) {
831 DECLARE_ROW_POINTERS(GLubyte
, 3);
833 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
834 i
++, j
+= colStride
, k
+= colStride
) {
840 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 2)) {
841 DECLARE_ROW_POINTERS(GLubyte
, 2);
843 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
844 i
++, j
+= colStride
, k
+= colStride
) {
849 else if ((datatype
== GL_UNSIGNED_BYTE
) && (comps
== 1)) {
850 DECLARE_ROW_POINTERS(GLubyte
, 1);
852 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
853 i
++, j
+= colStride
, k
+= colStride
) {
857 else if ((datatype
== GL_BYTE
) && (comps
== 4)) {
858 DECLARE_ROW_POINTERS(GLbyte
, 4);
860 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
861 i
++, j
+= colStride
, k
+= colStride
) {
868 else if ((datatype
== GL_BYTE
) && (comps
== 3)) {
869 DECLARE_ROW_POINTERS(GLbyte
, 3);
871 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
872 i
++, j
+= colStride
, k
+= colStride
) {
878 else if ((datatype
== GL_BYTE
) && (comps
== 2)) {
879 DECLARE_ROW_POINTERS(GLbyte
, 2);
881 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
882 i
++, j
+= colStride
, k
+= colStride
) {
887 else if ((datatype
== GL_BYTE
) && (comps
== 1)) {
888 DECLARE_ROW_POINTERS(GLbyte
, 1);
890 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
891 i
++, j
+= colStride
, k
+= colStride
) {
895 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 4)) {
896 DECLARE_ROW_POINTERS(GLushort
, 4);
898 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
899 i
++, j
+= colStride
, k
+= colStride
) {
906 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 3)) {
907 DECLARE_ROW_POINTERS(GLushort
, 3);
909 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
910 i
++, j
+= colStride
, k
+= colStride
) {
916 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 2)) {
917 DECLARE_ROW_POINTERS(GLushort
, 2);
919 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
920 i
++, j
+= colStride
, k
+= colStride
) {
925 else if ((datatype
== GL_UNSIGNED_SHORT
) && (comps
== 1)) {
926 DECLARE_ROW_POINTERS(GLushort
, 1);
928 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
929 i
++, j
+= colStride
, k
+= colStride
) {
933 else if ((datatype
== GL_SHORT
) && (comps
== 4)) {
934 DECLARE_ROW_POINTERS(GLshort
, 4);
936 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
937 i
++, j
+= colStride
, k
+= colStride
) {
944 else if ((datatype
== GL_SHORT
) && (comps
== 3)) {
945 DECLARE_ROW_POINTERS(GLshort
, 3);
947 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
948 i
++, j
+= colStride
, k
+= colStride
) {
954 else if ((datatype
== GL_SHORT
) && (comps
== 2)) {
955 DECLARE_ROW_POINTERS(GLshort
, 2);
957 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
958 i
++, j
+= colStride
, k
+= colStride
) {
963 else if ((datatype
== GL_SHORT
) && (comps
== 1)) {
964 DECLARE_ROW_POINTERS(GLshort
, 1);
966 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
967 i
++, j
+= colStride
, k
+= colStride
) {
971 else if ((datatype
== GL_FLOAT
) && (comps
== 4)) {
972 DECLARE_ROW_POINTERS(GLfloat
, 4);
974 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
975 i
++, j
+= colStride
, k
+= colStride
) {
982 else if ((datatype
== GL_FLOAT
) && (comps
== 3)) {
983 DECLARE_ROW_POINTERS(GLfloat
, 3);
985 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
986 i
++, j
+= colStride
, k
+= colStride
) {
992 else if ((datatype
== GL_FLOAT
) && (comps
== 2)) {
993 DECLARE_ROW_POINTERS(GLfloat
, 2);
995 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
996 i
++, j
+= colStride
, k
+= colStride
) {
1001 else if ((datatype
== GL_FLOAT
) && (comps
== 1)) {
1002 DECLARE_ROW_POINTERS(GLfloat
, 1);
1004 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1005 i
++, j
+= colStride
, k
+= colStride
) {
1009 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 4)) {
1010 DECLARE_ROW_POINTERS(GLhalfARB
, 4);
1012 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1013 i
++, j
+= colStride
, k
+= colStride
) {
1020 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 3)) {
1021 DECLARE_ROW_POINTERS(GLhalfARB
, 3);
1023 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1024 i
++, j
+= colStride
, k
+= colStride
) {
1030 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 2)) {
1031 DECLARE_ROW_POINTERS(GLhalfARB
, 2);
1033 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1034 i
++, j
+= colStride
, k
+= colStride
) {
1039 else if ((datatype
== GL_HALF_FLOAT_ARB
) && (comps
== 1)) {
1040 DECLARE_ROW_POINTERS(GLhalfARB
, 1);
1042 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1043 i
++, j
+= colStride
, k
+= colStride
) {
1047 else if ((datatype
== GL_UNSIGNED_INT
) && (comps
== 1)) {
1048 const GLuint
*rowA
= (const GLuint
*) srcRowA
;
1049 const GLuint
*rowB
= (const GLuint
*) srcRowB
;
1050 const GLuint
*rowC
= (const GLuint
*) srcRowC
;
1051 const GLuint
*rowD
= (const GLuint
*) srcRowD
;
1052 GLfloat
*dst
= (GLfloat
*) dstRow
;
1054 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1055 i
++, j
+= colStride
, k
+= colStride
) {
1056 const uint64_t tmp
= (((uint64_t) rowA
[j
] + (uint64_t) rowA
[k
])
1057 + ((uint64_t) rowB
[j
] + (uint64_t) rowB
[k
])
1058 + ((uint64_t) rowC
[j
] + (uint64_t) rowC
[k
])
1059 + ((uint64_t) rowD
[j
] + (uint64_t) rowD
[k
]));
1060 dst
[i
] = (GLfloat
)((double) tmp
* 0.125);
1063 else if ((datatype
== GL_UNSIGNED_SHORT_5_6_5
) && (comps
== 3)) {
1064 DECLARE_ROW_POINTERS0(GLushort
);
1066 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1067 i
++, j
+= colStride
, k
+= colStride
) {
1068 const GLint rowAr0
= rowA
[j
] & 0x1f;
1069 const GLint rowAr1
= rowA
[k
] & 0x1f;
1070 const GLint rowBr0
= rowB
[j
] & 0x1f;
1071 const GLint rowBr1
= rowB
[k
] & 0x1f;
1072 const GLint rowCr0
= rowC
[j
] & 0x1f;
1073 const GLint rowCr1
= rowC
[k
] & 0x1f;
1074 const GLint rowDr0
= rowD
[j
] & 0x1f;
1075 const GLint rowDr1
= rowD
[k
] & 0x1f;
1076 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x3f;
1077 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x3f;
1078 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x3f;
1079 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x3f;
1080 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x3f;
1081 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x3f;
1082 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x3f;
1083 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x3f;
1084 const GLint rowAb0
= (rowA
[j
] >> 11) & 0x1f;
1085 const GLint rowAb1
= (rowA
[k
] >> 11) & 0x1f;
1086 const GLint rowBb0
= (rowB
[j
] >> 11) & 0x1f;
1087 const GLint rowBb1
= (rowB
[k
] >> 11) & 0x1f;
1088 const GLint rowCb0
= (rowC
[j
] >> 11) & 0x1f;
1089 const GLint rowCb1
= (rowC
[k
] >> 11) & 0x1f;
1090 const GLint rowDb0
= (rowD
[j
] >> 11) & 0x1f;
1091 const GLint rowDb1
= (rowD
[k
] >> 11) & 0x1f;
1092 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1093 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1094 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1095 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1096 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1097 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1098 dst
[i
] = (b
<< 11) | (g
<< 5) | r
;
1101 else if ((datatype
== GL_UNSIGNED_SHORT_4_4_4_4
) && (comps
== 4)) {
1102 DECLARE_ROW_POINTERS0(GLushort
);
1104 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1105 i
++, j
+= colStride
, k
+= colStride
) {
1106 const GLint rowAr0
= rowA
[j
] & 0xf;
1107 const GLint rowAr1
= rowA
[k
] & 0xf;
1108 const GLint rowBr0
= rowB
[j
] & 0xf;
1109 const GLint rowBr1
= rowB
[k
] & 0xf;
1110 const GLint rowCr0
= rowC
[j
] & 0xf;
1111 const GLint rowCr1
= rowC
[k
] & 0xf;
1112 const GLint rowDr0
= rowD
[j
] & 0xf;
1113 const GLint rowDr1
= rowD
[k
] & 0xf;
1114 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
1115 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
1116 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
1117 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
1118 const GLint rowCg0
= (rowC
[j
] >> 4) & 0xf;
1119 const GLint rowCg1
= (rowC
[k
] >> 4) & 0xf;
1120 const GLint rowDg0
= (rowD
[j
] >> 4) & 0xf;
1121 const GLint rowDg1
= (rowD
[k
] >> 4) & 0xf;
1122 const GLint rowAb0
= (rowA
[j
] >> 8) & 0xf;
1123 const GLint rowAb1
= (rowA
[k
] >> 8) & 0xf;
1124 const GLint rowBb0
= (rowB
[j
] >> 8) & 0xf;
1125 const GLint rowBb1
= (rowB
[k
] >> 8) & 0xf;
1126 const GLint rowCb0
= (rowC
[j
] >> 8) & 0xf;
1127 const GLint rowCb1
= (rowC
[k
] >> 8) & 0xf;
1128 const GLint rowDb0
= (rowD
[j
] >> 8) & 0xf;
1129 const GLint rowDb1
= (rowD
[k
] >> 8) & 0xf;
1130 const GLint rowAa0
= (rowA
[j
] >> 12) & 0xf;
1131 const GLint rowAa1
= (rowA
[k
] >> 12) & 0xf;
1132 const GLint rowBa0
= (rowB
[j
] >> 12) & 0xf;
1133 const GLint rowBa1
= (rowB
[k
] >> 12) & 0xf;
1134 const GLint rowCa0
= (rowC
[j
] >> 12) & 0xf;
1135 const GLint rowCa1
= (rowC
[k
] >> 12) & 0xf;
1136 const GLint rowDa0
= (rowD
[j
] >> 12) & 0xf;
1137 const GLint rowDa1
= (rowD
[k
] >> 12) & 0xf;
1138 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1139 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1140 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1141 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1142 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1143 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1144 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1145 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1147 dst
[i
] = (a
<< 12) | (b
<< 8) | (g
<< 4) | r
;
1150 else if ((datatype
== GL_UNSIGNED_SHORT_1_5_5_5_REV
) && (comps
== 4)) {
1151 DECLARE_ROW_POINTERS0(GLushort
);
1153 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1154 i
++, j
+= colStride
, k
+= colStride
) {
1155 const GLint rowAr0
= rowA
[j
] & 0x1f;
1156 const GLint rowAr1
= rowA
[k
] & 0x1f;
1157 const GLint rowBr0
= rowB
[j
] & 0x1f;
1158 const GLint rowBr1
= rowB
[k
] & 0x1f;
1159 const GLint rowCr0
= rowC
[j
] & 0x1f;
1160 const GLint rowCr1
= rowC
[k
] & 0x1f;
1161 const GLint rowDr0
= rowD
[j
] & 0x1f;
1162 const GLint rowDr1
= rowD
[k
] & 0x1f;
1163 const GLint rowAg0
= (rowA
[j
] >> 5) & 0x1f;
1164 const GLint rowAg1
= (rowA
[k
] >> 5) & 0x1f;
1165 const GLint rowBg0
= (rowB
[j
] >> 5) & 0x1f;
1166 const GLint rowBg1
= (rowB
[k
] >> 5) & 0x1f;
1167 const GLint rowCg0
= (rowC
[j
] >> 5) & 0x1f;
1168 const GLint rowCg1
= (rowC
[k
] >> 5) & 0x1f;
1169 const GLint rowDg0
= (rowD
[j
] >> 5) & 0x1f;
1170 const GLint rowDg1
= (rowD
[k
] >> 5) & 0x1f;
1171 const GLint rowAb0
= (rowA
[j
] >> 10) & 0x1f;
1172 const GLint rowAb1
= (rowA
[k
] >> 10) & 0x1f;
1173 const GLint rowBb0
= (rowB
[j
] >> 10) & 0x1f;
1174 const GLint rowBb1
= (rowB
[k
] >> 10) & 0x1f;
1175 const GLint rowCb0
= (rowC
[j
] >> 10) & 0x1f;
1176 const GLint rowCb1
= (rowC
[k
] >> 10) & 0x1f;
1177 const GLint rowDb0
= (rowD
[j
] >> 10) & 0x1f;
1178 const GLint rowDb1
= (rowD
[k
] >> 10) & 0x1f;
1179 const GLint rowAa0
= (rowA
[j
] >> 15) & 0x1;
1180 const GLint rowAa1
= (rowA
[k
] >> 15) & 0x1;
1181 const GLint rowBa0
= (rowB
[j
] >> 15) & 0x1;
1182 const GLint rowBa1
= (rowB
[k
] >> 15) & 0x1;
1183 const GLint rowCa0
= (rowC
[j
] >> 15) & 0x1;
1184 const GLint rowCa1
= (rowC
[k
] >> 15) & 0x1;
1185 const GLint rowDa0
= (rowD
[j
] >> 15) & 0x1;
1186 const GLint rowDa1
= (rowD
[k
] >> 15) & 0x1;
1187 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1188 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1189 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1190 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1191 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1192 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1193 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1194 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1196 dst
[i
] = (a
<< 15) | (b
<< 10) | (g
<< 5) | r
;
1199 else if ((datatype
== GL_UNSIGNED_SHORT_5_5_5_1
) && (comps
== 4)) {
1200 DECLARE_ROW_POINTERS0(GLushort
);
1202 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1203 i
++, j
+= colStride
, k
+= colStride
) {
1204 const GLint rowAr0
= (rowA
[j
] >> 11) & 0x1f;
1205 const GLint rowAr1
= (rowA
[k
] >> 11) & 0x1f;
1206 const GLint rowBr0
= (rowB
[j
] >> 11) & 0x1f;
1207 const GLint rowBr1
= (rowB
[k
] >> 11) & 0x1f;
1208 const GLint rowCr0
= (rowC
[j
] >> 11) & 0x1f;
1209 const GLint rowCr1
= (rowC
[k
] >> 11) & 0x1f;
1210 const GLint rowDr0
= (rowD
[j
] >> 11) & 0x1f;
1211 const GLint rowDr1
= (rowD
[k
] >> 11) & 0x1f;
1212 const GLint rowAg0
= (rowA
[j
] >> 6) & 0x1f;
1213 const GLint rowAg1
= (rowA
[k
] >> 6) & 0x1f;
1214 const GLint rowBg0
= (rowB
[j
] >> 6) & 0x1f;
1215 const GLint rowBg1
= (rowB
[k
] >> 6) & 0x1f;
1216 const GLint rowCg0
= (rowC
[j
] >> 6) & 0x1f;
1217 const GLint rowCg1
= (rowC
[k
] >> 6) & 0x1f;
1218 const GLint rowDg0
= (rowD
[j
] >> 6) & 0x1f;
1219 const GLint rowDg1
= (rowD
[k
] >> 6) & 0x1f;
1220 const GLint rowAb0
= (rowA
[j
] >> 1) & 0x1f;
1221 const GLint rowAb1
= (rowA
[k
] >> 1) & 0x1f;
1222 const GLint rowBb0
= (rowB
[j
] >> 1) & 0x1f;
1223 const GLint rowBb1
= (rowB
[k
] >> 1) & 0x1f;
1224 const GLint rowCb0
= (rowC
[j
] >> 1) & 0x1f;
1225 const GLint rowCb1
= (rowC
[k
] >> 1) & 0x1f;
1226 const GLint rowDb0
= (rowD
[j
] >> 1) & 0x1f;
1227 const GLint rowDb1
= (rowD
[k
] >> 1) & 0x1f;
1228 const GLint rowAa0
= (rowA
[j
] & 0x1);
1229 const GLint rowAa1
= (rowA
[k
] & 0x1);
1230 const GLint rowBa0
= (rowB
[j
] & 0x1);
1231 const GLint rowBa1
= (rowB
[k
] & 0x1);
1232 const GLint rowCa0
= (rowC
[j
] & 0x1);
1233 const GLint rowCa1
= (rowC
[k
] & 0x1);
1234 const GLint rowDa0
= (rowD
[j
] & 0x1);
1235 const GLint rowDa1
= (rowD
[k
] & 0x1);
1236 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1237 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1238 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1239 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1240 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1241 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1242 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1243 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1245 dst
[i
] = (r
<< 11) | (g
<< 6) | (b
<< 1) | a
;
1248 else if ((datatype
== GL_UNSIGNED_BYTE_3_3_2
) && (comps
== 3)) {
1249 DECLARE_ROW_POINTERS0(GLubyte
);
1251 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1252 i
++, j
+= colStride
, k
+= colStride
) {
1253 const GLint rowAr0
= rowA
[j
] & 0x3;
1254 const GLint rowAr1
= rowA
[k
] & 0x3;
1255 const GLint rowBr0
= rowB
[j
] & 0x3;
1256 const GLint rowBr1
= rowB
[k
] & 0x3;
1257 const GLint rowCr0
= rowC
[j
] & 0x3;
1258 const GLint rowCr1
= rowC
[k
] & 0x3;
1259 const GLint rowDr0
= rowD
[j
] & 0x3;
1260 const GLint rowDr1
= rowD
[k
] & 0x3;
1261 const GLint rowAg0
= (rowA
[j
] >> 2) & 0x7;
1262 const GLint rowAg1
= (rowA
[k
] >> 2) & 0x7;
1263 const GLint rowBg0
= (rowB
[j
] >> 2) & 0x7;
1264 const GLint rowBg1
= (rowB
[k
] >> 2) & 0x7;
1265 const GLint rowCg0
= (rowC
[j
] >> 2) & 0x7;
1266 const GLint rowCg1
= (rowC
[k
] >> 2) & 0x7;
1267 const GLint rowDg0
= (rowD
[j
] >> 2) & 0x7;
1268 const GLint rowDg1
= (rowD
[k
] >> 2) & 0x7;
1269 const GLint rowAb0
= (rowA
[j
] >> 5) & 0x7;
1270 const GLint rowAb1
= (rowA
[k
] >> 5) & 0x7;
1271 const GLint rowBb0
= (rowB
[j
] >> 5) & 0x7;
1272 const GLint rowBb1
= (rowB
[k
] >> 5) & 0x7;
1273 const GLint rowCb0
= (rowC
[j
] >> 5) & 0x7;
1274 const GLint rowCb1
= (rowC
[k
] >> 5) & 0x7;
1275 const GLint rowDb0
= (rowD
[j
] >> 5) & 0x7;
1276 const GLint rowDb1
= (rowD
[k
] >> 5) & 0x7;
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 dst
[i
] = (b
<< 5) | (g
<< 2) | r
;
1286 else if (datatype
== MESA_UNSIGNED_BYTE_4_4
&& comps
== 2) {
1287 DECLARE_ROW_POINTERS0(GLubyte
);
1289 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1290 i
++, j
+= colStride
, k
+= colStride
) {
1291 const GLint rowAr0
= rowA
[j
] & 0xf;
1292 const GLint rowAr1
= rowA
[k
] & 0xf;
1293 const GLint rowBr0
= rowB
[j
] & 0xf;
1294 const GLint rowBr1
= rowB
[k
] & 0xf;
1295 const GLint rowCr0
= rowC
[j
] & 0xf;
1296 const GLint rowCr1
= rowC
[k
] & 0xf;
1297 const GLint rowDr0
= rowD
[j
] & 0xf;
1298 const GLint rowDr1
= rowD
[k
] & 0xf;
1299 const GLint rowAg0
= (rowA
[j
] >> 4) & 0xf;
1300 const GLint rowAg1
= (rowA
[k
] >> 4) & 0xf;
1301 const GLint rowBg0
= (rowB
[j
] >> 4) & 0xf;
1302 const GLint rowBg1
= (rowB
[k
] >> 4) & 0xf;
1303 const GLint rowCg0
= (rowC
[j
] >> 4) & 0xf;
1304 const GLint rowCg1
= (rowC
[k
] >> 4) & 0xf;
1305 const GLint rowDg0
= (rowD
[j
] >> 4) & 0xf;
1306 const GLint rowDg1
= (rowD
[k
] >> 4) & 0xf;
1307 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1308 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1309 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1310 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1311 dst
[i
] = (g
<< 4) | r
;
1314 else if ((datatype
== GL_UNSIGNED_INT_2_10_10_10_REV
) && (comps
== 4)) {
1315 DECLARE_ROW_POINTERS0(GLuint
);
1317 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1318 i
++, j
+= colStride
, k
+= colStride
) {
1319 const GLint rowAr0
= rowA
[j
] & 0x3ff;
1320 const GLint rowAr1
= rowA
[k
] & 0x3ff;
1321 const GLint rowBr0
= rowB
[j
] & 0x3ff;
1322 const GLint rowBr1
= rowB
[k
] & 0x3ff;
1323 const GLint rowCr0
= rowC
[j
] & 0x3ff;
1324 const GLint rowCr1
= rowC
[k
] & 0x3ff;
1325 const GLint rowDr0
= rowD
[j
] & 0x3ff;
1326 const GLint rowDr1
= rowD
[k
] & 0x3ff;
1327 const GLint rowAg0
= (rowA
[j
] >> 10) & 0x3ff;
1328 const GLint rowAg1
= (rowA
[k
] >> 10) & 0x3ff;
1329 const GLint rowBg0
= (rowB
[j
] >> 10) & 0x3ff;
1330 const GLint rowBg1
= (rowB
[k
] >> 10) & 0x3ff;
1331 const GLint rowCg0
= (rowC
[j
] >> 10) & 0x3ff;
1332 const GLint rowCg1
= (rowC
[k
] >> 10) & 0x3ff;
1333 const GLint rowDg0
= (rowD
[j
] >> 10) & 0x3ff;
1334 const GLint rowDg1
= (rowD
[k
] >> 10) & 0x3ff;
1335 const GLint rowAb0
= (rowA
[j
] >> 20) & 0x3ff;
1336 const GLint rowAb1
= (rowA
[k
] >> 20) & 0x3ff;
1337 const GLint rowBb0
= (rowB
[j
] >> 20) & 0x3ff;
1338 const GLint rowBb1
= (rowB
[k
] >> 20) & 0x3ff;
1339 const GLint rowCb0
= (rowC
[j
] >> 20) & 0x3ff;
1340 const GLint rowCb1
= (rowC
[k
] >> 20) & 0x3ff;
1341 const GLint rowDb0
= (rowD
[j
] >> 20) & 0x3ff;
1342 const GLint rowDb1
= (rowD
[k
] >> 20) & 0x3ff;
1343 const GLint rowAa0
= (rowA
[j
] >> 30) & 0x3;
1344 const GLint rowAa1
= (rowA
[k
] >> 30) & 0x3;
1345 const GLint rowBa0
= (rowB
[j
] >> 30) & 0x3;
1346 const GLint rowBa1
= (rowB
[k
] >> 30) & 0x3;
1347 const GLint rowCa0
= (rowC
[j
] >> 30) & 0x3;
1348 const GLint rowCa1
= (rowC
[k
] >> 30) & 0x3;
1349 const GLint rowDa0
= (rowD
[j
] >> 30) & 0x3;
1350 const GLint rowDa1
= (rowD
[k
] >> 30) & 0x3;
1351 const GLint r
= FILTER_SUM_3D(rowAr0
, rowAr1
, rowBr0
, rowBr1
,
1352 rowCr0
, rowCr1
, rowDr0
, rowDr1
);
1353 const GLint g
= FILTER_SUM_3D(rowAg0
, rowAg1
, rowBg0
, rowBg1
,
1354 rowCg0
, rowCg1
, rowDg0
, rowDg1
);
1355 const GLint b
= FILTER_SUM_3D(rowAb0
, rowAb1
, rowBb0
, rowBb1
,
1356 rowCb0
, rowCb1
, rowDb0
, rowDb1
);
1357 const GLint a
= FILTER_SUM_3D(rowAa0
, rowAa1
, rowBa0
, rowBa1
,
1358 rowCa0
, rowCa1
, rowDa0
, rowDa1
);
1360 dst
[i
] = (a
<< 30) | (b
<< 20) | (g
<< 10) | r
;
1364 else if (datatype
== GL_UNSIGNED_INT_5_9_9_9_REV
&& comps
== 3) {
1365 DECLARE_ROW_POINTERS0(GLuint
);
1368 GLfloat rowAj
[3], rowBj
[3], rowCj
[3], rowDj
[3];
1369 GLfloat rowAk
[3], rowBk
[3], rowCk
[3], rowDk
[3];
1371 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1372 i
++, j
+= colStride
, k
+= colStride
) {
1373 rgb9e5_to_float3(rowA
[j
], rowAj
);
1374 rgb9e5_to_float3(rowB
[j
], rowBj
);
1375 rgb9e5_to_float3(rowC
[j
], rowCj
);
1376 rgb9e5_to_float3(rowD
[j
], rowDj
);
1377 rgb9e5_to_float3(rowA
[k
], rowAk
);
1378 rgb9e5_to_float3(rowB
[k
], rowBk
);
1379 rgb9e5_to_float3(rowC
[k
], rowCk
);
1380 rgb9e5_to_float3(rowD
[k
], rowDk
);
1381 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0] +
1382 rowCj
[0] + rowCk
[0] + rowDj
[0] + rowDk
[0]) * 0.125F
;
1383 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1] +
1384 rowCj
[1] + rowCk
[1] + rowDj
[1] + rowDk
[1]) * 0.125F
;
1385 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2] +
1386 rowCj
[2] + rowCk
[2] + rowDj
[2] + rowDk
[2]) * 0.125F
;
1387 dst
[i
] = float3_to_rgb9e5(res
);
1391 else if (datatype
== GL_UNSIGNED_INT_10F_11F_11F_REV
&& comps
== 3) {
1392 DECLARE_ROW_POINTERS0(GLuint
);
1395 GLfloat rowAj
[3], rowBj
[3], rowCj
[3], rowDj
[3];
1396 GLfloat rowAk
[3], rowBk
[3], rowCk
[3], rowDk
[3];
1398 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1399 i
++, j
+= colStride
, k
+= colStride
) {
1400 r11g11b10f_to_float3(rowA
[j
], rowAj
);
1401 r11g11b10f_to_float3(rowB
[j
], rowBj
);
1402 r11g11b10f_to_float3(rowC
[j
], rowCj
);
1403 r11g11b10f_to_float3(rowD
[j
], rowDj
);
1404 r11g11b10f_to_float3(rowA
[k
], rowAk
);
1405 r11g11b10f_to_float3(rowB
[k
], rowBk
);
1406 r11g11b10f_to_float3(rowC
[k
], rowCk
);
1407 r11g11b10f_to_float3(rowD
[k
], rowDk
);
1408 res
[0] = (rowAj
[0] + rowAk
[0] + rowBj
[0] + rowBk
[0] +
1409 rowCj
[0] + rowCk
[0] + rowDj
[0] + rowDk
[0]) * 0.125F
;
1410 res
[1] = (rowAj
[1] + rowAk
[1] + rowBj
[1] + rowBk
[1] +
1411 rowCj
[1] + rowCk
[1] + rowDj
[1] + rowDk
[1]) * 0.125F
;
1412 res
[2] = (rowAj
[2] + rowAk
[2] + rowBj
[2] + rowBk
[2] +
1413 rowCj
[2] + rowCk
[2] + rowDj
[2] + rowDk
[2]) * 0.125F
;
1414 dst
[i
] = float3_to_r11g11b10f(res
);
1418 else if (datatype
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
&& comps
== 1) {
1419 DECLARE_ROW_POINTERS(GLfloat
, 2);
1421 for (i
= j
= 0, k
= k0
; i
< (GLuint
) dstWidth
;
1422 i
++, j
+= colStride
, k
+= colStride
) {
1428 unreachable("bad format in do_row()");
1434 * These functions generate a 1/2-size mipmap image from a source image.
1435 * Texture borders are handled by copying or averaging the source image's
1436 * border texels, depending on the scale-down factor.
1440 make_1d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1441 GLint srcWidth
, const GLubyte
*srcPtr
,
1442 GLint dstWidth
, GLubyte
*dstPtr
)
1444 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1448 /* skip the border pixel, if any */
1449 src
= srcPtr
+ border
* bpt
;
1450 dst
= dstPtr
+ border
* bpt
;
1452 /* we just duplicate the input row, kind of hack, saves code */
1453 do_row(datatype
, comps
, srcWidth
- 2 * border
, src
, src
,
1454 dstWidth
- 2 * border
, dst
);
1457 /* copy left-most pixel from source */
1460 memcpy(dstPtr
, srcPtr
, bpt
);
1461 /* copy right-most pixel from source */
1462 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1463 srcPtr
+ (srcWidth
- 1) * bpt
,
1470 make_2d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1471 GLint srcWidth
, GLint srcHeight
,
1472 const GLubyte
*srcPtr
, GLint srcRowStride
,
1473 GLint dstWidth
, GLint dstHeight
,
1474 GLubyte
*dstPtr
, GLint dstRowStride
)
1476 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1477 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1478 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1479 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1480 const GLubyte
*srcA
, *srcB
;
1482 GLint row
, srcRowStep
;
1484 /* Compute src and dst pointers, skipping any border */
1485 srcA
= srcPtr
+ border
* ((srcWidth
+ 1) * bpt
);
1486 if (srcHeight
> 1 && srcHeight
> dstHeight
) {
1487 /* sample from two source rows */
1488 srcB
= srcA
+ srcRowStride
;
1492 /* sample from one source row */
1497 dst
= dstPtr
+ border
* ((dstWidth
+ 1) * bpt
);
1499 for (row
= 0; row
< dstHeightNB
; row
++) {
1500 do_row(datatype
, comps
, srcWidthNB
, srcA
, srcB
,
1502 srcA
+= srcRowStep
* srcRowStride
;
1503 srcB
+= srcRowStep
* srcRowStride
;
1504 dst
+= dstRowStride
;
1507 /* This is ugly but probably won't be used much */
1509 /* fill in dest border */
1510 /* lower-left border pixel */
1513 memcpy(dstPtr
, srcPtr
, bpt
);
1514 /* lower-right border pixel */
1515 memcpy(dstPtr
+ (dstWidth
- 1) * bpt
,
1516 srcPtr
+ (srcWidth
- 1) * bpt
, bpt
);
1517 /* upper-left border pixel */
1518 memcpy(dstPtr
+ dstWidth
* (dstHeight
- 1) * bpt
,
1519 srcPtr
+ srcWidth
* (srcHeight
- 1) * bpt
, bpt
);
1520 /* upper-right border pixel */
1521 memcpy(dstPtr
+ (dstWidth
* dstHeight
- 1) * bpt
,
1522 srcPtr
+ (srcWidth
* srcHeight
- 1) * bpt
, bpt
);
1524 do_row(datatype
, comps
, srcWidthNB
,
1527 dstWidthNB
, dstPtr
+ bpt
);
1529 do_row(datatype
, comps
, srcWidthNB
,
1530 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1531 srcPtr
+ (srcWidth
* (srcHeight
- 1) + 1) * bpt
,
1533 dstPtr
+ (dstWidth
* (dstHeight
- 1) + 1) * bpt
);
1534 /* left and right borders */
1535 if (srcHeight
== dstHeight
) {
1536 /* copy border pixel from src to dst */
1537 for (row
= 1; row
< srcHeight
; row
++) {
1538 memcpy(dstPtr
+ dstWidth
* row
* bpt
,
1539 srcPtr
+ srcWidth
* row
* bpt
, bpt
);
1540 memcpy(dstPtr
+ (dstWidth
* row
+ dstWidth
- 1) * bpt
,
1541 srcPtr
+ (srcWidth
* row
+ srcWidth
- 1) * bpt
, bpt
);
1545 /* average two src pixels each dest pixel */
1546 for (row
= 0; row
< dstHeightNB
; row
+= 2) {
1547 do_row(datatype
, comps
, 1,
1548 srcPtr
+ (srcWidth
* (row
* 2 + 1)) * bpt
,
1549 srcPtr
+ (srcWidth
* (row
* 2 + 2)) * bpt
,
1550 1, dstPtr
+ (dstWidth
* row
+ 1) * bpt
);
1551 do_row(datatype
, comps
, 1,
1552 srcPtr
+ (srcWidth
* (row
* 2 + 1) + srcWidth
- 1) * bpt
,
1553 srcPtr
+ (srcWidth
* (row
* 2 + 2) + srcWidth
- 1) * bpt
,
1554 1, dstPtr
+ (dstWidth
* row
+ 1 + dstWidth
- 1) * bpt
);
1562 make_3d_mipmap(GLenum datatype
, GLuint comps
, GLint border
,
1563 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1564 const GLubyte
**srcPtr
, GLint srcRowStride
,
1565 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1566 GLubyte
**dstPtr
, GLint dstRowStride
)
1568 const GLint bpt
= bytes_per_pixel(datatype
, comps
);
1569 const GLint srcWidthNB
= srcWidth
- 2 * border
; /* sizes w/out border */
1570 const GLint srcDepthNB
= srcDepth
- 2 * border
;
1571 const GLint dstWidthNB
= dstWidth
- 2 * border
;
1572 const GLint dstHeightNB
= dstHeight
- 2 * border
;
1573 const GLint dstDepthNB
= dstDepth
- 2 * border
;
1575 GLint bytesPerSrcImage
, bytesPerDstImage
;
1576 GLint srcImageOffset
, srcRowOffset
;
1578 (void) srcDepthNB
; /* silence warnings */
1580 bytesPerSrcImage
= srcRowStride
* srcHeight
* bpt
;
1581 bytesPerDstImage
= dstRowStride
* dstHeight
* bpt
;
1583 /* Offset between adjacent src images to be averaged together */
1584 srcImageOffset
= (srcDepth
== dstDepth
) ? 0 : 1;
1586 /* Offset between adjacent src rows to be averaged together */
1587 srcRowOffset
= (srcHeight
== dstHeight
) ? 0 : srcRowStride
;
1590 * Need to average together up to 8 src pixels for each dest pixel.
1591 * Break that down into 3 operations:
1592 * 1. take two rows from source image and average them together.
1593 * 2. take two rows from next source image and average them together.
1594 * 3. take the two averaged rows and average them for the final dst row.
1598 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1599 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1602 for (img
= 0; img
< dstDepthNB
; img
++) {
1603 /* first source image pointer, skipping border */
1604 const GLubyte
*imgSrcA
= srcPtr
[img
* 2 + border
]
1605 + srcRowStride
* border
+ bpt
* border
;
1606 /* second source image pointer, skipping border */
1607 const GLubyte
*imgSrcB
= srcPtr
[img
* 2 + srcImageOffset
+ border
]
1608 + srcRowStride
* border
+ bpt
* border
;
1610 /* address of the dest image, skipping border */
1611 GLubyte
*imgDst
= dstPtr
[img
+ border
]
1612 + dstRowStride
* border
+ bpt
* border
;
1614 /* setup the four source row pointers and the dest row pointer */
1615 const GLubyte
*srcImgARowA
= imgSrcA
;
1616 const GLubyte
*srcImgARowB
= imgSrcA
+ srcRowOffset
;
1617 const GLubyte
*srcImgBRowA
= imgSrcB
;
1618 const GLubyte
*srcImgBRowB
= imgSrcB
+ srcRowOffset
;
1619 GLubyte
*dstImgRow
= imgDst
;
1621 for (row
= 0; row
< dstHeightNB
; row
++) {
1622 do_row_3D(datatype
, comps
, srcWidthNB
,
1623 srcImgARowA
, srcImgARowB
,
1624 srcImgBRowA
, srcImgBRowB
,
1625 dstWidthNB
, dstImgRow
);
1627 /* advance to next rows */
1628 srcImgARowA
+= srcRowStride
+ srcRowOffset
;
1629 srcImgARowB
+= srcRowStride
+ srcRowOffset
;
1630 srcImgBRowA
+= srcRowStride
+ srcRowOffset
;
1631 srcImgBRowB
+= srcRowStride
+ srcRowOffset
;
1632 dstImgRow
+= dstRowStride
;
1637 /* Luckily we can leverage the make_2d_mipmap() function here! */
1639 /* do front border image */
1640 make_2d_mipmap(datatype
, comps
, 1,
1641 srcWidth
, srcHeight
, srcPtr
[0], srcRowStride
,
1642 dstWidth
, dstHeight
, dstPtr
[0], dstRowStride
);
1643 /* do back border image */
1644 make_2d_mipmap(datatype
, comps
, 1,
1645 srcWidth
, srcHeight
, srcPtr
[srcDepth
- 1], srcRowStride
,
1646 dstWidth
, dstHeight
, dstPtr
[dstDepth
- 1], dstRowStride
);
1648 /* do four remaining border edges that span the image slices */
1649 if (srcDepth
== dstDepth
) {
1650 /* just copy border pixels from src to dst */
1651 for (img
= 0; img
< dstDepthNB
; img
++) {
1655 /* do border along [img][row=0][col=0] */
1656 src
= srcPtr
[img
* 2];
1658 memcpy(dst
, src
, bpt
);
1660 /* do border along [img][row=dstHeight-1][col=0] */
1661 src
= srcPtr
[img
* 2] + (srcHeight
- 1) * srcRowStride
;
1662 dst
= dstPtr
[img
] + (dstHeight
- 1) * dstRowStride
;
1663 memcpy(dst
, src
, bpt
);
1665 /* do border along [img][row=0][col=dstWidth-1] */
1666 src
= srcPtr
[img
* 2] + (srcWidth
- 1) * bpt
;
1667 dst
= dstPtr
[img
] + (dstWidth
- 1) * bpt
;
1668 memcpy(dst
, src
, bpt
);
1670 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1671 src
= srcPtr
[img
* 2] + (bytesPerSrcImage
- bpt
);
1672 dst
= dstPtr
[img
] + (bytesPerDstImage
- bpt
);
1673 memcpy(dst
, src
, bpt
);
1677 /* average border pixels from adjacent src image pairs */
1678 assert(srcDepthNB
== 2 * dstDepthNB
);
1679 for (img
= 0; img
< dstDepthNB
; img
++) {
1680 const GLubyte
*srcA
, *srcB
;
1683 /* do border along [img][row=0][col=0] */
1684 srcA
= srcPtr
[img
* 2 + 0];
1685 srcB
= srcPtr
[img
* 2 + srcImageOffset
];
1687 do_row(datatype
, comps
, 1, srcA
, srcB
, 1, dst
);
1689 /* do border along [img][row=dstHeight-1][col=0] */
1690 srcA
= srcPtr
[img
* 2 + 0]
1691 + (srcHeight
- 1) * srcRowStride
;
1692 srcB
= srcPtr
[img
* 2 + srcImageOffset
]
1693 + (srcHeight
- 1) * srcRowStride
;
1694 dst
= dstPtr
[img
] + (dstHeight
- 1) * dstRowStride
;
1695 do_row(datatype
, comps
, 1, srcA
, srcB
, 1, dst
);
1697 /* do border along [img][row=0][col=dstWidth-1] */
1698 srcA
= srcPtr
[img
* 2 + 0] + (srcWidth
- 1) * bpt
;
1699 srcB
= srcPtr
[img
* 2 + srcImageOffset
] + (srcWidth
- 1) * bpt
;
1700 dst
= dstPtr
[img
] + (dstWidth
- 1) * bpt
;
1701 do_row(datatype
, comps
, 1, srcA
, srcB
, 1, dst
);
1703 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1704 srcA
= srcPtr
[img
* 2 + 0] + (bytesPerSrcImage
- bpt
);
1705 srcB
= srcPtr
[img
* 2 + srcImageOffset
] + (bytesPerSrcImage
- bpt
);
1706 dst
= dstPtr
[img
] + (bytesPerDstImage
- bpt
);
1707 do_row(datatype
, comps
, 1, srcA
, srcB
, 1, dst
);
1715 * Down-sample a texture image to produce the next lower mipmap level.
1716 * \param comps components per texel (1, 2, 3 or 4)
1717 * \param srcData array[slice] of pointers to source image slices
1718 * \param dstData array[slice] of pointers to dest image slices
1719 * \param srcRowStride stride between source rows, in bytes
1720 * \param dstRowStride stride between destination rows, in bytes
1723 _mesa_generate_mipmap_level(GLenum target
,
1724 GLenum datatype
, GLuint comps
,
1726 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1727 const GLubyte
**srcData
,
1729 GLint dstWidth
, GLint dstHeight
, GLint dstDepth
,
1737 make_1d_mipmap(datatype
, comps
, border
,
1738 srcWidth
, srcData
[0],
1739 dstWidth
, dstData
[0]);
1742 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
1743 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
1744 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
1745 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
1746 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
1747 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
1748 make_2d_mipmap(datatype
, comps
, border
,
1749 srcWidth
, srcHeight
, srcData
[0], srcRowStride
,
1750 dstWidth
, dstHeight
, dstData
[0], dstRowStride
);
1753 make_3d_mipmap(datatype
, comps
, border
,
1754 srcWidth
, srcHeight
, srcDepth
,
1755 srcData
, srcRowStride
,
1756 dstWidth
, dstHeight
, dstDepth
,
1757 dstData
, dstRowStride
);
1759 case GL_TEXTURE_1D_ARRAY_EXT
:
1760 assert(srcHeight
== 1);
1761 assert(dstHeight
== 1);
1762 for (i
= 0; i
< dstDepth
; i
++) {
1763 make_1d_mipmap(datatype
, comps
, border
,
1764 srcWidth
, srcData
[i
],
1765 dstWidth
, dstData
[i
]);
1768 case GL_TEXTURE_2D_ARRAY_EXT
:
1769 case GL_TEXTURE_CUBE_MAP_ARRAY
:
1770 for (i
= 0; i
< dstDepth
; i
++) {
1771 make_2d_mipmap(datatype
, comps
, border
,
1772 srcWidth
, srcHeight
, srcData
[i
], srcRowStride
,
1773 dstWidth
, dstHeight
, dstData
[i
], dstRowStride
);
1776 case GL_TEXTURE_RECTANGLE_NV
:
1777 case GL_TEXTURE_EXTERNAL_OES
:
1778 /* no mipmaps, do nothing */
1781 unreachable("bad tex target in _mesa_generate_mipmaps");
1787 * compute next (level+1) image size
1788 * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1791 _mesa_next_mipmap_level_size(GLenum target
, GLint border
,
1792 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
1793 GLint
*dstWidth
, GLint
*dstHeight
, GLint
*dstDepth
)
1795 if (srcWidth
- 2 * border
> 1) {
1796 *dstWidth
= (srcWidth
- 2 * border
) / 2 + 2 * border
;
1799 *dstWidth
= srcWidth
; /* can't go smaller */
1802 if ((srcHeight
- 2 * border
> 1) &&
1803 target
!= GL_TEXTURE_1D_ARRAY_EXT
&&
1804 target
!= GL_PROXY_TEXTURE_1D_ARRAY_EXT
) {
1805 *dstHeight
= (srcHeight
- 2 * border
) / 2 + 2 * border
;
1808 *dstHeight
= srcHeight
; /* can't go smaller */
1811 if ((srcDepth
- 2 * border
> 1) &&
1812 target
!= GL_TEXTURE_2D_ARRAY_EXT
&&
1813 target
!= GL_PROXY_TEXTURE_2D_ARRAY_EXT
&&
1814 target
!= GL_TEXTURE_CUBE_MAP_ARRAY
&&
1815 target
!= GL_PROXY_TEXTURE_CUBE_MAP_ARRAY
) {
1816 *dstDepth
= (srcDepth
- 2 * border
) / 2 + 2 * border
;
1819 *dstDepth
= srcDepth
; /* can't go smaller */
1822 if (*dstWidth
== srcWidth
&&
1823 *dstHeight
== srcHeight
&&
1824 *dstDepth
== srcDepth
) {
1834 * Helper function for mipmap generation.
1835 * Make sure the specified destination mipmap level is the right size/format
1836 * for mipmap generation. If not, (re) allocate it.
1837 * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop
1840 prepare_mipmap_level(struct gl_context
*ctx
,
1841 struct gl_texture_object
*texObj
, GLuint level
,
1842 GLsizei width
, GLsizei height
, GLsizei depth
,
1843 GLsizei border
, GLenum intFormat
, mesa_format format
)
1845 const GLuint numFaces
= _mesa_num_tex_faces(texObj
->Target
);
1848 if (texObj
->Immutable
) {
1849 /* The texture was created with glTexStorage() so the number/size of
1850 * mipmap levels is fixed and the storage for all images is already
1853 if (!texObj
->Image
[0][level
]) {
1854 /* No more levels to create - we're done */
1858 /* Nothing to do - the texture memory must have already been
1859 * allocated to the right size so we're all set.
1865 for (face
= 0; face
< numFaces
; face
++) {
1866 struct gl_texture_image
*dstImage
;
1867 const GLenum target
= _mesa_cube_face_target(texObj
->Target
, face
);
1869 dstImage
= _mesa_get_tex_image(ctx
, texObj
, target
, level
);
1875 if (dstImage
->Width
!= width
||
1876 dstImage
->Height
!= height
||
1877 dstImage
->Depth
!= depth
||
1878 dstImage
->Border
!= border
||
1879 dstImage
->InternalFormat
!= intFormat
||
1880 dstImage
->TexFormat
!= format
) {
1881 /* need to (re)allocate image */
1882 ctx
->Driver
.FreeTextureImageBuffer(ctx
, dstImage
);
1884 _mesa_init_teximage_fields(ctx
, dstImage
,
1885 width
, height
, depth
,
1886 border
, intFormat
, format
);
1888 ctx
->Driver
.AllocTextureImageBuffer(ctx
, dstImage
);
1890 /* in case the mipmap level is part of an FBO: */
1891 _mesa_update_fbo_texture(ctx
, texObj
, face
, level
);
1893 ctx
->NewState
|= _NEW_TEXTURE_OBJECT
;
1902 * Prepare all mipmap levels beyond 'baseLevel' for mipmap generation.
1903 * When finished, all the gl_texture_image structures for the smaller
1904 * mipmap levels will be consistent with the base level (in terms of
1905 * dimensions, format, etc).
1908 _mesa_prepare_mipmap_levels(struct gl_context
*ctx
,
1909 struct gl_texture_object
*texObj
,
1910 unsigned baseLevel
, unsigned maxLevel
)
1912 const struct gl_texture_image
*baseImage
=
1913 _mesa_select_tex_image(texObj
, texObj
->Target
, baseLevel
);
1914 const GLint border
= 0;
1915 GLint width
= baseImage
->Width
;
1916 GLint height
= baseImage
->Height
;
1917 GLint depth
= baseImage
->Depth
;
1918 const GLenum intFormat
= baseImage
->InternalFormat
;
1919 const mesa_format texFormat
= baseImage
->TexFormat
;
1920 GLint newWidth
, newHeight
, newDepth
;
1922 /* Prepare baseLevel + 1, baseLevel + 2, ... */
1923 for (unsigned level
= baseLevel
+ 1; level
<= maxLevel
; level
++) {
1924 if (!_mesa_next_mipmap_level_size(texObj
->Target
, border
,
1925 width
, height
, depth
,
1926 &newWidth
, &newHeight
, &newDepth
)) {
1931 if (!prepare_mipmap_level(ctx
, texObj
, level
,
1932 newWidth
, newHeight
, newDepth
,
1933 border
, intFormat
, texFormat
)) {
1945 generate_mipmap_uncompressed(struct gl_context
*ctx
, GLenum target
,
1946 struct gl_texture_object
*texObj
,
1947 const struct gl_texture_image
*srcImage
,
1954 _mesa_uncompressed_format_to_type_and_comps(srcImage
->TexFormat
, &datatype
, &comps
);
1956 for (level
= texObj
->BaseLevel
; level
< maxLevel
; level
++) {
1957 /* generate image[level+1] from image[level] */
1958 struct gl_texture_image
*srcImage
, *dstImage
;
1959 GLint srcRowStride
, dstRowStride
;
1960 GLint srcWidth
, srcHeight
, srcDepth
;
1961 GLint dstWidth
, dstHeight
, dstDepth
;
1964 GLubyte
**srcMaps
, **dstMaps
;
1965 GLboolean success
= GL_TRUE
;
1967 /* get src image parameters */
1968 srcImage
= _mesa_select_tex_image(texObj
, target
, level
);
1970 srcWidth
= srcImage
->Width
;
1971 srcHeight
= srcImage
->Height
;
1972 srcDepth
= srcImage
->Depth
;
1973 border
= srcImage
->Border
;
1975 /* get dest gl_texture_image */
1976 dstImage
= _mesa_select_tex_image(texObj
, target
, level
+ 1);
1980 dstWidth
= dstImage
->Width
;
1981 dstHeight
= dstImage
->Height
;
1982 dstDepth
= dstImage
->Depth
;
1984 if (target
== GL_TEXTURE_1D_ARRAY
) {
1985 srcDepth
= srcHeight
;
1986 dstDepth
= dstHeight
;
1991 /* Map src texture image slices */
1992 srcMaps
= calloc(srcDepth
, sizeof(GLubyte
*));
1994 for (slice
= 0; slice
< srcDepth
; slice
++) {
1995 ctx
->Driver
.MapTextureImage(ctx
, srcImage
, slice
,
1996 0, 0, srcWidth
, srcHeight
,
1998 &srcMaps
[slice
], &srcRowStride
);
1999 if (!srcMaps
[slice
]) {
2009 /* Map dst texture image slices */
2010 dstMaps
= calloc(dstDepth
, sizeof(GLubyte
*));
2012 for (slice
= 0; slice
< dstDepth
; slice
++) {
2013 ctx
->Driver
.MapTextureImage(ctx
, dstImage
, slice
,
2014 0, 0, dstWidth
, dstHeight
,
2016 &dstMaps
[slice
], &dstRowStride
);
2017 if (!dstMaps
[slice
]) {
2028 /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */
2029 _mesa_generate_mipmap_level(target
, datatype
, comps
, border
,
2030 srcWidth
, srcHeight
, srcDepth
,
2031 (const GLubyte
**) srcMaps
, srcRowStride
,
2032 dstWidth
, dstHeight
, dstDepth
,
2033 dstMaps
, dstRowStride
);
2036 /* Unmap src image slices */
2038 for (slice
= 0; slice
< srcDepth
; slice
++) {
2039 if (srcMaps
[slice
]) {
2040 ctx
->Driver
.UnmapTextureImage(ctx
, srcImage
, slice
);
2046 /* Unmap dst image slices */
2048 for (slice
= 0; slice
< dstDepth
; slice
++) {
2049 if (dstMaps
[slice
]) {
2050 ctx
->Driver
.UnmapTextureImage(ctx
, dstImage
, slice
);
2057 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "mipmap generation");
2060 } /* loop over mipmap levels */
2065 generate_mipmap_compressed(struct gl_context
*ctx
, GLenum target
,
2066 struct gl_texture_object
*texObj
,
2067 struct gl_texture_image
*srcImage
,
2071 mesa_format temp_format
;
2073 GLuint temp_src_row_stride
, temp_src_img_stride
; /* in bytes */
2074 GLubyte
*temp_src
= NULL
, *temp_dst
= NULL
;
2075 GLenum temp_datatype
;
2076 GLenum temp_base_format
;
2077 GLubyte
**temp_src_slices
= NULL
, **temp_dst_slices
= NULL
;
2079 /* only two types of compressed textures at this time */
2080 assert(texObj
->Target
== GL_TEXTURE_2D
||
2081 texObj
->Target
== GL_TEXTURE_2D_ARRAY
||
2082 texObj
->Target
== GL_TEXTURE_CUBE_MAP
||
2083 texObj
->Target
== GL_TEXTURE_CUBE_MAP_ARRAY
);
2086 * Choose a format for the temporary, uncompressed base image.
2087 * Then, get number of components, choose temporary image datatype,
2088 * and get base format.
2090 temp_format
= _mesa_get_uncompressed_format(srcImage
->TexFormat
);
2092 components
= _mesa_format_num_components(temp_format
);
2094 switch (_mesa_get_format_datatype(srcImage
->TexFormat
)) {
2096 temp_datatype
= GL_FLOAT
;
2098 case GL_SIGNED_NORMALIZED
:
2099 /* Revisit this if we get compressed formats with >8 bits per component */
2100 temp_datatype
= GL_BYTE
;
2103 temp_datatype
= GL_UNSIGNED_BYTE
;
2106 temp_base_format
= _mesa_get_format_base_format(temp_format
);
2109 /* allocate storage for the temporary, uncompressed image */
2110 temp_src_row_stride
= _mesa_format_row_stride(temp_format
, srcImage
->Width
);
2111 temp_src_img_stride
= _mesa_format_image_size(temp_format
, srcImage
->Width
,
2112 srcImage
->Height
, 1);
2113 temp_src
= malloc(temp_src_img_stride
* srcImage
->Depth
);
2115 /* Allocate storage for arrays of slice pointers */
2116 temp_src_slices
= malloc(srcImage
->Depth
* sizeof(GLubyte
*));
2117 temp_dst_slices
= malloc(srcImage
->Depth
* sizeof(GLubyte
*));
2119 if (!temp_src
|| !temp_src_slices
|| !temp_dst_slices
) {
2120 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
2124 /* decompress base image to the temporary src buffer */
2126 /* save pixel packing mode */
2127 struct gl_pixelstore_attrib save
= ctx
->Pack
;
2128 /* use default/tight packing parameters */
2129 ctx
->Pack
= ctx
->DefaultPacking
;
2131 /* Get the uncompressed image */
2132 assert(srcImage
->Level
== texObj
->BaseLevel
);
2133 ctx
->Driver
.GetTexSubImage(ctx
,
2135 srcImage
->Width
, srcImage
->Height
,
2137 temp_base_format
, temp_datatype
,
2138 temp_src
, srcImage
);
2139 /* restore packing mode */
2143 for (level
= texObj
->BaseLevel
; level
< maxLevel
; level
++) {
2144 /* generate image[level+1] from image[level] */
2145 const struct gl_texture_image
*srcImage
;
2146 struct gl_texture_image
*dstImage
;
2147 GLint srcWidth
, srcHeight
, srcDepth
;
2148 GLint dstWidth
, dstHeight
, dstDepth
;
2150 GLuint temp_dst_row_stride
, temp_dst_img_stride
; /* in bytes */
2153 /* get src image parameters */
2154 srcImage
= _mesa_select_tex_image(texObj
, target
, level
);
2156 srcWidth
= srcImage
->Width
;
2157 srcHeight
= srcImage
->Height
;
2158 srcDepth
= srcImage
->Depth
;
2159 border
= srcImage
->Border
;
2161 /* get dest gl_texture_image */
2162 dstImage
= _mesa_select_tex_image(texObj
, target
, level
+ 1);
2166 dstWidth
= dstImage
->Width
;
2167 dstHeight
= dstImage
->Height
;
2168 dstDepth
= dstImage
->Depth
;
2170 /* Compute dst image strides and alloc memory on first iteration */
2171 temp_dst_row_stride
= _mesa_format_row_stride(temp_format
, dstWidth
);
2172 temp_dst_img_stride
= _mesa_format_image_size(temp_format
, dstWidth
,
2175 temp_dst
= malloc(temp_dst_img_stride
* dstDepth
);
2177 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "generate mipmaps");
2182 /* for 2D arrays, setup array[depth] of slice pointers */
2183 for (i
= 0; i
< srcDepth
; i
++) {
2184 temp_src_slices
[i
] = temp_src
+ temp_src_img_stride
* i
;
2186 for (i
= 0; i
< dstDepth
; i
++) {
2187 temp_dst_slices
[i
] = temp_dst
+ temp_dst_img_stride
* i
;
2190 /* Rescale src image to dest image.
2191 * This will loop over the slices of a 2D array.
2193 _mesa_generate_mipmap_level(target
, temp_datatype
, components
, border
,
2194 srcWidth
, srcHeight
, srcDepth
,
2195 (const GLubyte
**) temp_src_slices
,
2196 temp_src_row_stride
,
2197 dstWidth
, dstHeight
, dstDepth
,
2198 temp_dst_slices
, temp_dst_row_stride
);
2200 /* The image space was allocated above so use glTexSubImage now */
2201 ctx
->Driver
.TexSubImage(ctx
, 2, dstImage
,
2202 0, 0, 0, dstWidth
, dstHeight
, dstDepth
,
2203 temp_base_format
, temp_datatype
,
2204 temp_dst
, &ctx
->DefaultPacking
);
2206 /* swap src and dest pointers */
2208 GLubyte
*temp
= temp_src
;
2209 temp_src
= temp_dst
;
2211 temp_src_row_stride
= temp_dst_row_stride
;
2212 temp_src_img_stride
= temp_dst_img_stride
;
2214 } /* loop over mipmap levels */
2219 free(temp_src_slices
);
2220 free(temp_dst_slices
);
2224 * Automatic mipmap generation.
2225 * This is the fallback/default function for ctx->Driver.GenerateMipmap().
2226 * Generate a complete set of mipmaps from texObj's BaseLevel image.
2227 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
2228 * For cube maps, target will be one of
2229 * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
2232 _mesa_generate_mipmap(struct gl_context
*ctx
, GLenum target
,
2233 struct gl_texture_object
*texObj
)
2235 struct gl_texture_image
*srcImage
;
2239 srcImage
= _mesa_select_tex_image(texObj
, target
, texObj
->BaseLevel
);
2242 maxLevel
= _mesa_max_texture_levels(ctx
, texObj
->Target
) - 1;
2243 assert(maxLevel
>= 0); /* bad target */
2245 maxLevel
= MIN2(maxLevel
, texObj
->MaxLevel
);
2247 _mesa_prepare_mipmap_levels(ctx
, texObj
, texObj
->BaseLevel
, maxLevel
);
2249 if (_mesa_is_format_compressed(srcImage
->TexFormat
)) {
2250 generate_mipmap_compressed(ctx
, target
, texObj
, srcImage
, maxLevel
);
2252 generate_mipmap_uncompressed(ctx
, target
, texObj
, srcImage
, maxLevel
);