1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
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.
23 */
24
25
26 /**
27 * \file mipmap.c mipmap generation and teximage resizing functions.
28 */
29
30 #include "errors.h"
31
32 #include "formats.h"
33 #include "glformats.h"
34 #include "mipmap.h"
35 #include "mtypes.h"
36 #include "teximage.h"
37 #include "texobj.h"
38 #include "texstore.h"
39 #include "image.h"
40 #include "macros.h"
41 #include "util/half_float.h"
42 #include "util/format_rgb9e5.h"
43 #include "util/format_r11g11b10f.h"
44
45 #include "state_tracker/st_cb_texture.h"
46
47 /**
48 * Compute the expected number of mipmap levels in the texture given
49 * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
50 * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap
51 * levels should be generated.
52 */
53 unsigned
_mesa_compute_num_levels(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target)54 _mesa_compute_num_levels(struct gl_context *ctx,
55 struct gl_texture_object *texObj,
56 GLenum target)
57 {
58 const struct gl_texture_image *baseImage;
59 GLuint numLevels;
60
61 baseImage = _mesa_get_tex_image(ctx, texObj, target, texObj->Attrib.BaseLevel);
62
63 numLevels = texObj->Attrib.BaseLevel + baseImage->MaxNumLevels;
64 numLevels = MIN2(numLevels, (GLuint) texObj->Attrib.MaxLevel + 1);
65 if (texObj->Immutable)
66 numLevels = MIN2(numLevels, texObj->Attrib.NumLevels);
67 assert(numLevels >= 1);
68
69 return numLevels;
70 }
71
72 static GLint
bytes_per_pixel(GLenum datatype,GLuint comps)73 bytes_per_pixel(GLenum datatype, GLuint comps)
74 {
75 GLint b;
76
77 if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA ||
78 datatype == GL_UNSIGNED_INT_24_8_MESA)
79 return 4;
80
81 b = _mesa_sizeof_packed_type(datatype);
82 assert(b >= 0);
83
84 if (_mesa_type_is_packed(datatype))
85 return b;
86 else
87 return b * comps;
88 }
89
90
91 /**
92 * \name Support macros for do_row and do_row_3d
93 *
94 * The macro madness is here for two reasons. First, it compacts the code
95 * slightly. Second, it makes it much easier to adjust the specifics of the
96 * filter to tune the rounding characteristics.
97 */
98 /*@{*/
99 #define DECLARE_ROW_POINTERS(t, e) \
100 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
101 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
102 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
103 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
104 t(*dst)[e] = (t(*)[e]) dstRow
105
106 #define DECLARE_ROW_POINTERS0(t) \
107 const t *rowA = (const t *) srcRowA; \
108 const t *rowB = (const t *) srcRowB; \
109 const t *rowC = (const t *) srcRowC; \
110 const t *rowD = (const t *) srcRowD; \
111 t *dst = (t *) dstRow
112
113 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
114 ((unsigned) Aj + (unsigned) Ak \
115 + (unsigned) Bj + (unsigned) Bk \
116 + (unsigned) Cj + (unsigned) Ck \
117 + (unsigned) Dj + (unsigned) Dk \
118 + 4) >> 3
119
120 #define FILTER_3D(e) \
121 do { \
122 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
123 rowB[j][e], rowB[k][e], \
124 rowC[j][e], rowC[k][e], \
125 rowD[j][e], rowD[k][e]); \
126 } while(0)
127
128 #define FILTER_SUM_3D_SIGNED(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
129 (Aj + Ak \
130 + Bj + Bk \
131 + Cj + Ck \
132 + Dj + Dk \
133 + 4) / 8
134
135 #define FILTER_3D_SIGNED(e) \
136 do { \
137 dst[i][e] = FILTER_SUM_3D_SIGNED(rowA[j][e], rowA[k][e], \
138 rowB[j][e], rowB[k][e], \
139 rowC[j][e], rowC[k][e], \
140 rowD[j][e], rowD[k][e]); \
141 } while(0)
142
143 #define FILTER_F_3D(e) \
144 do { \
145 dst[i][e] = (rowA[j][e] + rowA[k][e] \
146 + rowB[j][e] + rowB[k][e] \
147 + rowC[j][e] + rowC[k][e] \
148 + rowD[j][e] + rowD[k][e]) * 0.125F; \
149 } while(0)
150
151 #define FILTER_HF_3D(e) \
152 do { \
153 const GLfloat aj = _mesa_half_to_float(rowA[j][e]); \
154 const GLfloat ak = _mesa_half_to_float(rowA[k][e]); \
155 const GLfloat bj = _mesa_half_to_float(rowB[j][e]); \
156 const GLfloat bk = _mesa_half_to_float(rowB[k][e]); \
157 const GLfloat cj = _mesa_half_to_float(rowC[j][e]); \
158 const GLfloat ck = _mesa_half_to_float(rowC[k][e]); \
159 const GLfloat dj = _mesa_half_to_float(rowD[j][e]); \
160 const GLfloat dk = _mesa_half_to_float(rowD[k][e]); \
161 dst[i][e] = _mesa_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
162 * 0.125F); \
163 } while(0)
164 /*@}*/
165
166
167 /**
168 * Average together two rows of a source image to produce a single new
169 * row in the dest image. It's legal for the two source rows to point
170 * to the same data. The source width must be equal to either the
171 * dest width or two times the dest width.
172 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
173 * \param comps number of components per pixel (1..4)
174 */
175 static void
do_row(GLenum datatype,GLuint comps,GLint srcWidth,const GLvoid * srcRowA,const GLvoid * srcRowB,GLint dstWidth,GLvoid * dstRow)176 do_row(GLenum datatype, GLuint comps, GLint srcWidth,
177 const GLvoid *srcRowA, const GLvoid *srcRowB,
178 GLint dstWidth, GLvoid *dstRow)
179 {
180 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
181 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
182
183 assert(comps >= 1);
184 assert(comps <= 4);
185
186 /* This assertion is no longer valid with non-power-of-2 textures
187 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
188 */
189
190 if (datatype == GL_UNSIGNED_BYTE && comps == 4) {
191 GLuint i, j, k;
192 const GLubyte(*rowA)[4] = (const GLubyte(*)[4]) srcRowA;
193 const GLubyte(*rowB)[4] = (const GLubyte(*)[4]) srcRowB;
194 GLubyte(*dst)[4] = (GLubyte(*)[4]) dstRow;
195 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
196 i++, j += colStride, k += colStride) {
197 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
198 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
199 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
200 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
201 }
202 }
203 else if (datatype == GL_UNSIGNED_BYTE && comps == 3) {
204 GLuint i, j, k;
205 const GLubyte(*rowA)[3] = (const GLubyte(*)[3]) srcRowA;
206 const GLubyte(*rowB)[3] = (const GLubyte(*)[3]) srcRowB;
207 GLubyte(*dst)[3] = (GLubyte(*)[3]) dstRow;
208 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
209 i++, j += colStride, k += colStride) {
210 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
211 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
212 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
213 }
214 }
215 else if (datatype == GL_UNSIGNED_BYTE && comps == 2) {
216 GLuint i, j, k;
217 const GLubyte(*rowA)[2] = (const GLubyte(*)[2]) srcRowA;
218 const GLubyte(*rowB)[2] = (const GLubyte(*)[2]) srcRowB;
219 GLubyte(*dst)[2] = (GLubyte(*)[2]) 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]) >> 2;
223 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
224 }
225 }
226 else if (datatype == GL_UNSIGNED_BYTE && comps == 1) {
227 GLuint i, j, k;
228 const GLubyte *rowA = (const GLubyte *) srcRowA;
229 const GLubyte *rowB = (const GLubyte *) srcRowB;
230 GLubyte *dst = (GLubyte *) dstRow;
231 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
232 i++, j += colStride, k += colStride) {
233 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
234 }
235 }
236
237 else if (datatype == GL_BYTE && comps == 4) {
238 GLuint i, j, k;
239 const GLbyte(*rowA)[4] = (const GLbyte(*)[4]) srcRowA;
240 const GLbyte(*rowB)[4] = (const GLbyte(*)[4]) srcRowB;
241 GLbyte(*dst)[4] = (GLbyte(*)[4]) dstRow;
242 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
243 i++, j += colStride, k += colStride) {
244 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
245 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
246 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
247 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
248 }
249 }
250 else if (datatype == GL_BYTE && comps == 3) {
251 GLuint i, j, k;
252 const GLbyte(*rowA)[3] = (const GLbyte(*)[3]) srcRowA;
253 const GLbyte(*rowB)[3] = (const GLbyte(*)[3]) srcRowB;
254 GLbyte(*dst)[3] = (GLbyte(*)[3]) dstRow;
255 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
256 i++, j += colStride, k += colStride) {
257 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
258 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
259 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
260 }
261 }
262 else if (datatype == GL_BYTE && comps == 2) {
263 GLuint i, j, k;
264 const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
265 const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
266 GLbyte(*dst)[2] = (GLbyte(*)[2]) 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 }
272 }
273 else if (datatype == GL_BYTE && comps == 1) {
274 GLuint i, j, k;
275 const GLbyte *rowA = (const GLbyte *) srcRowA;
276 const GLbyte *rowB = (const GLbyte *) srcRowB;
277 GLbyte *dst = (GLbyte *) dstRow;
278 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
279 i++, j += colStride, k += colStride) {
280 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
281 }
282 }
283
284 else if (datatype == GL_UNSIGNED_SHORT && comps == 4) {
285 GLuint i, j, k;
286 const GLushort(*rowA)[4] = (const GLushort(*)[4]) srcRowA;
287 const GLushort(*rowB)[4] = (const GLushort(*)[4]) srcRowB;
288 GLushort(*dst)[4] = (GLushort(*)[4]) dstRow;
289 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
290 i++, j += colStride, k += colStride) {
291 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
292 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
293 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
294 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
295 }
296 }
297 else if (datatype == GL_UNSIGNED_SHORT && comps == 3) {
298 GLuint i, j, k;
299 const GLushort(*rowA)[3] = (const GLushort(*)[3]) srcRowA;
300 const GLushort(*rowB)[3] = (const GLushort(*)[3]) srcRowB;
301 GLushort(*dst)[3] = (GLushort(*)[3]) dstRow;
302 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
303 i++, j += colStride, k += colStride) {
304 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
305 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
306 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
307 }
308 }
309 else if (datatype == GL_UNSIGNED_SHORT && comps == 2) {
310 GLuint i, j, k;
311 const GLushort(*rowA)[2] = (const GLushort(*)[2]) srcRowA;
312 const GLushort(*rowB)[2] = (const GLushort(*)[2]) srcRowB;
313 GLushort(*dst)[2] = (GLushort(*)[2]) 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 }
319 }
320 else if (datatype == GL_UNSIGNED_SHORT && comps == 1) {
321 GLuint i, j, k;
322 const GLushort *rowA = (const GLushort *) srcRowA;
323 const GLushort *rowB = (const GLushort *) srcRowB;
324 GLushort *dst = (GLushort *) dstRow;
325 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
326 i++, j += colStride, k += colStride) {
327 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
328 }
329 }
330
331 else if (datatype == GL_SHORT && comps == 4) {
332 GLuint i, j, k;
333 const GLshort(*rowA)[4] = (const GLshort(*)[4]) srcRowA;
334 const GLshort(*rowB)[4] = (const GLshort(*)[4]) srcRowB;
335 GLshort(*dst)[4] = (GLshort(*)[4]) dstRow;
336 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
337 i++, j += colStride, k += colStride) {
338 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
339 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
340 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
341 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
342 }
343 }
344 else if (datatype == GL_SHORT && comps == 3) {
345 GLuint i, j, k;
346 const GLshort(*rowA)[3] = (const GLshort(*)[3]) srcRowA;
347 const GLshort(*rowB)[3] = (const GLshort(*)[3]) srcRowB;
348 GLshort(*dst)[3] = (GLshort(*)[3]) dstRow;
349 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
350 i++, j += colStride, k += colStride) {
351 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
352 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
353 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
354 }
355 }
356 else if (datatype == GL_SHORT && comps == 2) {
357 GLuint i, j, k;
358 const GLshort(*rowA)[2] = (const GLshort(*)[2]) srcRowA;
359 const GLshort(*rowB)[2] = (const GLshort(*)[2]) srcRowB;
360 GLshort(*dst)[2] = (GLshort(*)[2]) dstRow;
361 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
362 i++, j += colStride, k += colStride) {
363 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
364 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
365 }
366 }
367 else if (datatype == GL_SHORT && comps == 1) {
368 GLuint i, j, k;
369 const GLshort *rowA = (const GLshort *) srcRowA;
370 const GLshort *rowB = (const GLshort *) srcRowB;
371 GLshort *dst = (GLshort *) dstRow;
372 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
373 i++, j += colStride, k += colStride) {
374 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
375 }
376 }
377
378 else if (datatype == GL_FLOAT && comps == 4) {
379 GLuint i, j, k;
380 const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
381 const GLfloat(*rowB)[4] = (const GLfloat(*)[4]) srcRowB;
382 GLfloat(*dst)[4] = (GLfloat(*)[4]) dstRow;
383 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
384 i++, j += colStride, k += colStride) {
385 dst[i][0] = (rowA[j][0] + rowA[k][0] +
386 rowB[j][0] + rowB[k][0]) * 0.25F;
387 dst[i][1] = (rowA[j][1] + rowA[k][1] +
388 rowB[j][1] + rowB[k][1]) * 0.25F;
389 dst[i][2] = (rowA[j][2] + rowA[k][2] +
390 rowB[j][2] + rowB[k][2]) * 0.25F;
391 dst[i][3] = (rowA[j][3] + rowA[k][3] +
392 rowB[j][3] + rowB[k][3]) * 0.25F;
393 }
394 }
395 else if (datatype == GL_FLOAT && comps == 3) {
396 GLuint i, j, k;
397 const GLfloat(*rowA)[3] = (const GLfloat(*)[3]) srcRowA;
398 const GLfloat(*rowB)[3] = (const GLfloat(*)[3]) srcRowB;
399 GLfloat(*dst)[3] = (GLfloat(*)[3]) dstRow;
400 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
401 i++, j += colStride, k += colStride) {
402 dst[i][0] = (rowA[j][0] + rowA[k][0] +
403 rowB[j][0] + rowB[k][0]) * 0.25F;
404 dst[i][1] = (rowA[j][1] + rowA[k][1] +
405 rowB[j][1] + rowB[k][1]) * 0.25F;
406 dst[i][2] = (rowA[j][2] + rowA[k][2] +
407 rowB[j][2] + rowB[k][2]) * 0.25F;
408 }
409 }
410 else if (datatype == GL_FLOAT && comps == 2) {
411 GLuint i, j, k;
412 const GLfloat(*rowA)[2] = (const GLfloat(*)[2]) srcRowA;
413 const GLfloat(*rowB)[2] = (const GLfloat(*)[2]) srcRowB;
414 GLfloat(*dst)[2] = (GLfloat(*)[2]) dstRow;
415 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
416 i++, j += colStride, k += colStride) {
417 dst[i][0] = (rowA[j][0] + rowA[k][0] +
418 rowB[j][0] + rowB[k][0]) * 0.25F;
419 dst[i][1] = (rowA[j][1] + rowA[k][1] +
420 rowB[j][1] + rowB[k][1]) * 0.25F;
421 }
422 }
423 else if (datatype == GL_FLOAT && comps == 1) {
424 GLuint i, j, k;
425 const GLfloat *rowA = (const GLfloat *) srcRowA;
426 const GLfloat *rowB = (const GLfloat *) srcRowB;
427 GLfloat *dst = (GLfloat *) dstRow;
428 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
429 i++, j += colStride, k += colStride) {
430 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
431 }
432 }
433
434 else if (datatype == GL_HALF_FLOAT_ARB && comps == 4) {
435 GLuint i, j, k, comp;
436 const GLhalfARB(*rowA)[4] = (const GLhalfARB(*)[4]) srcRowA;
437 const GLhalfARB(*rowB)[4] = (const GLhalfARB(*)[4]) srcRowB;
438 GLhalfARB(*dst)[4] = (GLhalfARB(*)[4]) dstRow;
439 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
440 i++, j += colStride, k += colStride) {
441 for (comp = 0; comp < 4; comp++) {
442 GLfloat aj, ak, bj, bk;
443 aj = _mesa_half_to_float(rowA[j][comp]);
444 ak = _mesa_half_to_float(rowA[k][comp]);
445 bj = _mesa_half_to_float(rowB[j][comp]);
446 bk = _mesa_half_to_float(rowB[k][comp]);
447 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
448 }
449 }
450 }
451 else if (datatype == GL_HALF_FLOAT_ARB && comps == 3) {
452 GLuint i, j, k, comp;
453 const GLhalfARB(*rowA)[3] = (const GLhalfARB(*)[3]) srcRowA;
454 const GLhalfARB(*rowB)[3] = (const GLhalfARB(*)[3]) srcRowB;
455 GLhalfARB(*dst)[3] = (GLhalfARB(*)[3]) dstRow;
456 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
457 i++, j += colStride, k += colStride) {
458 for (comp = 0; comp < 3; comp++) {
459 GLfloat aj, ak, bj, bk;
460 aj = _mesa_half_to_float(rowA[j][comp]);
461 ak = _mesa_half_to_float(rowA[k][comp]);
462 bj = _mesa_half_to_float(rowB[j][comp]);
463 bk = _mesa_half_to_float(rowB[k][comp]);
464 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
465 }
466 }
467 }
468 else if (datatype == GL_HALF_FLOAT_ARB && comps == 2) {
469 GLuint i, j, k, comp;
470 const GLhalfARB(*rowA)[2] = (const GLhalfARB(*)[2]) srcRowA;
471 const GLhalfARB(*rowB)[2] = (const GLhalfARB(*)[2]) srcRowB;
472 GLhalfARB(*dst)[2] = (GLhalfARB(*)[2]) dstRow;
473 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
474 i++, j += colStride, k += colStride) {
475 for (comp = 0; comp < 2; comp++) {
476 GLfloat aj, ak, bj, bk;
477 aj = _mesa_half_to_float(rowA[j][comp]);
478 ak = _mesa_half_to_float(rowA[k][comp]);
479 bj = _mesa_half_to_float(rowB[j][comp]);
480 bk = _mesa_half_to_float(rowB[k][comp]);
481 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
482 }
483 }
484 }
485 else if (datatype == GL_HALF_FLOAT_ARB && comps == 1) {
486 GLuint i, j, k;
487 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
488 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
489 GLhalfARB *dst = (GLhalfARB *) dstRow;
490 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
491 i++, j += colStride, k += colStride) {
492 GLfloat aj, ak, bj, bk;
493 aj = _mesa_half_to_float(rowA[j]);
494 ak = _mesa_half_to_float(rowA[k]);
495 bj = _mesa_half_to_float(rowB[j]);
496 bk = _mesa_half_to_float(rowB[k]);
497 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
498 }
499 }
500
501 else if (datatype == GL_UNSIGNED_INT && comps == 1) {
502 GLuint i, j, k;
503 const GLuint *rowA = (const GLuint *) srcRowA;
504 const GLuint *rowB = (const GLuint *) srcRowB;
505 GLuint *dst = (GLuint *) dstRow;
506 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
507 i++, j += colStride, k += colStride) {
508 dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
509 }
510 }
511
512 else if (datatype == GL_UNSIGNED_SHORT_5_6_5 && comps == 3) {
513 GLuint i, j, k;
514 const GLushort *rowA = (const GLushort *) srcRowA;
515 const GLushort *rowB = (const GLushort *) srcRowB;
516 GLushort *dst = (GLushort *) dstRow;
517 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
518 i++, j += colStride, k += colStride) {
519 const GLint rowAr0 = rowA[j] & 0x1f;
520 const GLint rowAr1 = rowA[k] & 0x1f;
521 const GLint rowBr0 = rowB[j] & 0x1f;
522 const GLint rowBr1 = rowB[k] & 0x1f;
523 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
524 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
525 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
526 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
527 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
528 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
529 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
530 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
531 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
532 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
533 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
534 dst[i] = (blue << 11) | (green << 5) | red;
535 }
536 }
537 else if (datatype == GL_UNSIGNED_SHORT_4_4_4_4 && comps == 4) {
538 GLuint i, j, k;
539 const GLushort *rowA = (const GLushort *) srcRowA;
540 const GLushort *rowB = (const GLushort *) srcRowB;
541 GLushort *dst = (GLushort *) dstRow;
542 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
543 i++, j += colStride, k += colStride) {
544 const GLint rowAr0 = rowA[j] & 0xf;
545 const GLint rowAr1 = rowA[k] & 0xf;
546 const GLint rowBr0 = rowB[j] & 0xf;
547 const GLint rowBr1 = rowB[k] & 0xf;
548 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
549 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
550 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
551 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
552 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
553 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
554 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
555 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
556 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
557 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
558 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
559 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
560 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
561 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
562 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
563 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
564 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
565 }
566 }
567 else if (datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV && comps == 4) {
568 GLuint i, j, k;
569 const GLushort *rowA = (const GLushort *) srcRowA;
570 const GLushort *rowB = (const GLushort *) srcRowB;
571 GLushort *dst = (GLushort *) dstRow;
572 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
573 i++, j += colStride, k += colStride) {
574 const GLint rowAr0 = rowA[j] & 0x1f;
575 const GLint rowAr1 = rowA[k] & 0x1f;
576 const GLint rowBr0 = rowB[j] & 0x1f;
577 const GLint rowBr1 = rowB[k] & 0x1f;
578 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
579 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
580 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
581 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
582 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
583 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
584 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
585 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
586 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
587 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
588 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
589 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
590 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
591 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
592 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
593 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
594 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
595 }
596 }
597 else if (datatype == GL_UNSIGNED_SHORT_5_5_5_1 && comps == 4) {
598 GLuint i, j, k;
599 const GLushort *rowA = (const GLushort *) srcRowA;
600 const GLushort *rowB = (const GLushort *) srcRowB;
601 GLushort *dst = (GLushort *) dstRow;
602 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
603 i++, j += colStride, k += colStride) {
604 const GLint rowAr0 = (rowA[j] >> 11) & 0x1f;
605 const GLint rowAr1 = (rowA[k] >> 11) & 0x1f;
606 const GLint rowBr0 = (rowB[j] >> 11) & 0x1f;
607 const GLint rowBr1 = (rowB[k] >> 11) & 0x1f;
608 const GLint rowAg0 = (rowA[j] >> 6) & 0x1f;
609 const GLint rowAg1 = (rowA[k] >> 6) & 0x1f;
610 const GLint rowBg0 = (rowB[j] >> 6) & 0x1f;
611 const GLint rowBg1 = (rowB[k] >> 6) & 0x1f;
612 const GLint rowAb0 = (rowA[j] >> 1) & 0x1f;
613 const GLint rowAb1 = (rowA[k] >> 1) & 0x1f;
614 const GLint rowBb0 = (rowB[j] >> 1) & 0x1f;
615 const GLint rowBb1 = (rowB[k] >> 1) & 0x1f;
616 const GLint rowAa0 = (rowA[j] & 0x1);
617 const GLint rowAa1 = (rowA[k] & 0x1);
618 const GLint rowBa0 = (rowB[j] & 0x1);
619 const GLint rowBa1 = (rowB[k] & 0x1);
620 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
621 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
622 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
623 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
624 dst[i] = (red << 11) | (green << 6) | (blue << 1) | alpha;
625 }
626 }
627
628 else if (datatype == GL_UNSIGNED_BYTE_3_3_2 && comps == 3) {
629 GLuint i, j, k;
630 const GLubyte *rowA = (const GLubyte *) srcRowA;
631 const GLubyte *rowB = (const GLubyte *) srcRowB;
632 GLubyte *dst = (GLubyte *) dstRow;
633 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
634 i++, j += colStride, k += colStride) {
635 const GLint rowAr0 = rowA[j] & 0x3;
636 const GLint rowAr1 = rowA[k] & 0x3;
637 const GLint rowBr0 = rowB[j] & 0x3;
638 const GLint rowBr1 = rowB[k] & 0x3;
639 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
640 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
641 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
642 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
643 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
644 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
645 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
646 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
647 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
648 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
649 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
650 dst[i] = (blue << 5) | (green << 2) | red;
651 }
652 }
653
654 else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) {
655 GLuint i, j, k;
656 const GLubyte *rowA = (const GLubyte *) srcRowA;
657 const GLubyte *rowB = (const GLubyte *) srcRowB;
658 GLubyte *dst = (GLubyte *) dstRow;
659 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
660 i++, j += colStride, k += colStride) {
661 const GLint rowAr0 = rowA[j] & 0xf;
662 const GLint rowAr1 = rowA[k] & 0xf;
663 const GLint rowBr0 = rowB[j] & 0xf;
664 const GLint rowBr1 = rowB[k] & 0xf;
665 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
666 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
667 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
668 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
669 const GLint r = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
670 const GLint g = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
671 dst[i] = (g << 4) | r;
672 }
673 }
674
675 else if (datatype == GL_UNSIGNED_INT_2_10_10_10_REV && comps == 4) {
676 GLuint i, j, k;
677 const GLuint *rowA = (const GLuint *) srcRowA;
678 const GLuint *rowB = (const GLuint *) srcRowB;
679 GLuint *dst = (GLuint *) dstRow;
680 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
681 i++, j += colStride, k += colStride) {
682 const GLint rowAr0 = rowA[j] & 0x3ff;
683 const GLint rowAr1 = rowA[k] & 0x3ff;
684 const GLint rowBr0 = rowB[j] & 0x3ff;
685 const GLint rowBr1 = rowB[k] & 0x3ff;
686 const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff;
687 const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff;
688 const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff;
689 const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff;
690 const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff;
691 const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff;
692 const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff;
693 const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff;
694 const GLint rowAa0 = (rowA[j] >> 30) & 0x3;
695 const GLint rowAa1 = (rowA[k] >> 30) & 0x3;
696 const GLint rowBa0 = (rowB[j] >> 30) & 0x3;
697 const GLint rowBa1 = (rowB[k] >> 30) & 0x3;
698 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
699 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
700 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
701 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
702 dst[i] = (alpha << 30) | (blue << 20) | (green << 10) | red;
703 }
704 }
705
706 else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) {
707 GLuint i, j, k;
708 const GLuint *rowA = (const GLuint*) srcRowA;
709 const GLuint *rowB = (const GLuint*) srcRowB;
710 GLuint *dst = (GLuint*)dstRow;
711 GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3];
712 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
713 i++, j += colStride, k += colStride) {
714 rgb9e5_to_float3(rowA[j], rowAj);
715 rgb9e5_to_float3(rowB[j], rowBj);
716 rgb9e5_to_float3(rowA[k], rowAk);
717 rgb9e5_to_float3(rowB[k], rowBk);
718 res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F;
719 res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F;
720 res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F;
721 dst[i] = float3_to_rgb9e5(res);
722 }
723 }
724
725 else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) {
726 GLuint i, j, k;
727 const GLuint *rowA = (const GLuint*) srcRowA;
728 const GLuint *rowB = (const GLuint*) srcRowB;
729 GLuint *dst = (GLuint*)dstRow;
730 GLfloat res[3], rowAj[3], rowBj[3], rowAk[3], rowBk[3];
731 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
732 i++, j += colStride, k += colStride) {
733 r11g11b10f_to_float3(rowA[j], rowAj);
734 r11g11b10f_to_float3(rowB[j], rowBj);
735 r11g11b10f_to_float3(rowA[k], rowAk);
736 r11g11b10f_to_float3(rowB[k], rowBk);
737 res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0]) * 0.25F;
738 res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1]) * 0.25F;
739 res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2]) * 0.25F;
740 dst[i] = float3_to_r11g11b10f(res);
741 }
742 }
743
744 else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) {
745 GLuint i, j, k;
746 const GLfloat *rowA = (const GLfloat *) srcRowA;
747 const GLfloat *rowB = (const GLfloat *) srcRowB;
748 GLfloat *dst = (GLfloat *) dstRow;
749 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
750 i++, j += colStride, k += colStride) {
751 dst[i*2] = (rowA[j*2] + rowA[k*2] + rowB[j*2] + rowB[k*2]) * 0.25F;
752 }
753 }
754
755 else if (datatype == GL_UNSIGNED_INT_24_8_MESA && comps == 2) {
756 GLuint i, j, k;
757 const GLuint *rowA = (const GLuint *) srcRowA;
758 const GLuint *rowB = (const GLuint *) srcRowB;
759 GLuint *dst = (GLuint *) dstRow;
760 /* note: averaging stencil values seems weird, but what else? */
761 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
762 i++, j += colStride, k += colStride) {
763 GLuint z = (((rowA[j] >> 8) + (rowA[k] >> 8) +
764 (rowB[j] >> 8) + (rowB[k] >> 8)) / 4) << 8;
765 GLuint s = ((rowA[j] & 0xff) + (rowA[k] & 0xff) +
766 (rowB[j] & 0xff) + (rowB[k] & 0xff)) / 4;
767 dst[i] = z | s;
768 }
769 }
770 else if (datatype == GL_UNSIGNED_INT_8_24_REV_MESA && comps == 2) {
771 GLuint i, j, k;
772 const GLuint *rowA = (const GLuint *) srcRowA;
773 const GLuint *rowB = (const GLuint *) srcRowB;
774 GLuint *dst = (GLuint *) dstRow;
775 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
776 i++, j += colStride, k += colStride) {
777 GLuint z = ((rowA[j] & 0xffffff) + (rowA[k] & 0xffffff) +
778 (rowB[j] & 0xffffff) + (rowB[k] & 0xffffff)) / 4;
779 GLuint s = (((rowA[j] >> 24) + (rowA[k] >> 24) +
780 (rowB[j] >> 24) + (rowB[k] >> 24)) / 4) << 24;
781 dst[i] = z | s;
782 }
783 }
784
785 else {
786 unreachable("bad format in do_row()");
787 }
788 }
789
790
791 /**
792 * Average together four rows of a source image to produce a single new
793 * row in the dest image. It's legal for the two source rows to point
794 * to the same data. The source width must be equal to either the
795 * dest width or two times the dest width.
796 *
797 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
798 * \c GL_FLOAT, etc.
799 * \param comps number of components per pixel (1..4)
800 * \param srcWidth Width of a row in the source data
801 * \param srcRowA Pointer to one of the rows of source data
802 * \param srcRowB Pointer to one of the rows of source data
803 * \param srcRowC Pointer to one of the rows of source data
804 * \param srcRowD Pointer to one of the rows of source data
805 * \param dstWidth Width of a row in the destination data
806 * \param srcRowA Pointer to the row of destination data
807 */
808 static void
do_row_3D(GLenum datatype,GLuint comps,GLint srcWidth,const GLvoid * srcRowA,const GLvoid * srcRowB,const GLvoid * srcRowC,const GLvoid * srcRowD,GLint dstWidth,GLvoid * dstRow)809 do_row_3D(GLenum datatype, GLuint comps, GLint srcWidth,
810 const GLvoid *srcRowA, const GLvoid *srcRowB,
811 const GLvoid *srcRowC, const GLvoid *srcRowD,
812 GLint dstWidth, GLvoid *dstRow)
813 {
814 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
815 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
816 GLuint i, j, k;
817
818 assert(comps >= 1);
819 assert(comps <= 4);
820
821 if ((datatype == GL_UNSIGNED_BYTE) && (comps == 4)) {
822 DECLARE_ROW_POINTERS(GLubyte, 4);
823
824 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
825 i++, j += colStride, k += colStride) {
826 FILTER_3D(0);
827 FILTER_3D(1);
828 FILTER_3D(2);
829 FILTER_3D(3);
830 }
831 }
832 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 3)) {
833 DECLARE_ROW_POINTERS(GLubyte, 3);
834
835 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
836 i++, j += colStride, k += colStride) {
837 FILTER_3D(0);
838 FILTER_3D(1);
839 FILTER_3D(2);
840 }
841 }
842 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 2)) {
843 DECLARE_ROW_POINTERS(GLubyte, 2);
844
845 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
846 i++, j += colStride, k += colStride) {
847 FILTER_3D(0);
848 FILTER_3D(1);
849 }
850 }
851 else if ((datatype == GL_UNSIGNED_BYTE) && (comps == 1)) {
852 DECLARE_ROW_POINTERS(GLubyte, 1);
853
854 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
855 i++, j += colStride, k += colStride) {
856 FILTER_3D(0);
857 }
858 }
859 else if ((datatype == GL_BYTE) && (comps == 4)) {
860 DECLARE_ROW_POINTERS(GLbyte, 4);
861
862 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
863 i++, j += colStride, k += colStride) {
864 FILTER_3D_SIGNED(0);
865 FILTER_3D_SIGNED(1);
866 FILTER_3D_SIGNED(2);
867 FILTER_3D_SIGNED(3);
868 }
869 }
870 else if ((datatype == GL_BYTE) && (comps == 3)) {
871 DECLARE_ROW_POINTERS(GLbyte, 3);
872
873 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
874 i++, j += colStride, k += colStride) {
875 FILTER_3D_SIGNED(0);
876 FILTER_3D_SIGNED(1);
877 FILTER_3D_SIGNED(2);
878 }
879 }
880 else if ((datatype == GL_BYTE) && (comps == 2)) {
881 DECLARE_ROW_POINTERS(GLbyte, 2);
882
883 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
884 i++, j += colStride, k += colStride) {
885 FILTER_3D_SIGNED(0);
886 FILTER_3D_SIGNED(1);
887 }
888 }
889 else if ((datatype == GL_BYTE) && (comps == 1)) {
890 DECLARE_ROW_POINTERS(GLbyte, 1);
891
892 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
893 i++, j += colStride, k += colStride) {
894 FILTER_3D_SIGNED(0);
895 }
896 }
897 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 4)) {
898 DECLARE_ROW_POINTERS(GLushort, 4);
899
900 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
901 i++, j += colStride, k += colStride) {
902 FILTER_3D(0);
903 FILTER_3D(1);
904 FILTER_3D(2);
905 FILTER_3D(3);
906 }
907 }
908 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 3)) {
909 DECLARE_ROW_POINTERS(GLushort, 3);
910
911 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
912 i++, j += colStride, k += colStride) {
913 FILTER_3D(0);
914 FILTER_3D(1);
915 FILTER_3D(2);
916 }
917 }
918 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 2)) {
919 DECLARE_ROW_POINTERS(GLushort, 2);
920
921 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
922 i++, j += colStride, k += colStride) {
923 FILTER_3D(0);
924 FILTER_3D(1);
925 }
926 }
927 else if ((datatype == GL_UNSIGNED_SHORT) && (comps == 1)) {
928 DECLARE_ROW_POINTERS(GLushort, 1);
929
930 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
931 i++, j += colStride, k += colStride) {
932 FILTER_3D(0);
933 }
934 }
935 else if ((datatype == GL_SHORT) && (comps == 4)) {
936 DECLARE_ROW_POINTERS(GLshort, 4);
937
938 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
939 i++, j += colStride, k += colStride) {
940 FILTER_3D(0);
941 FILTER_3D(1);
942 FILTER_3D(2);
943 FILTER_3D(3);
944 }
945 }
946 else if ((datatype == GL_SHORT) && (comps == 3)) {
947 DECLARE_ROW_POINTERS(GLshort, 3);
948
949 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
950 i++, j += colStride, k += colStride) {
951 FILTER_3D(0);
952 FILTER_3D(1);
953 FILTER_3D(2);
954 }
955 }
956 else if ((datatype == GL_SHORT) && (comps == 2)) {
957 DECLARE_ROW_POINTERS(GLshort, 2);
958
959 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
960 i++, j += colStride, k += colStride) {
961 FILTER_3D(0);
962 FILTER_3D(1);
963 }
964 }
965 else if ((datatype == GL_SHORT) && (comps == 1)) {
966 DECLARE_ROW_POINTERS(GLshort, 1);
967
968 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
969 i++, j += colStride, k += colStride) {
970 FILTER_3D(0);
971 }
972 }
973 else if ((datatype == GL_FLOAT) && (comps == 4)) {
974 DECLARE_ROW_POINTERS(GLfloat, 4);
975
976 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
977 i++, j += colStride, k += colStride) {
978 FILTER_F_3D(0);
979 FILTER_F_3D(1);
980 FILTER_F_3D(2);
981 FILTER_F_3D(3);
982 }
983 }
984 else if ((datatype == GL_FLOAT) && (comps == 3)) {
985 DECLARE_ROW_POINTERS(GLfloat, 3);
986
987 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
988 i++, j += colStride, k += colStride) {
989 FILTER_F_3D(0);
990 FILTER_F_3D(1);
991 FILTER_F_3D(2);
992 }
993 }
994 else if ((datatype == GL_FLOAT) && (comps == 2)) {
995 DECLARE_ROW_POINTERS(GLfloat, 2);
996
997 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
998 i++, j += colStride, k += colStride) {
999 FILTER_F_3D(0);
1000 FILTER_F_3D(1);
1001 }
1002 }
1003 else if ((datatype == GL_FLOAT) && (comps == 1)) {
1004 DECLARE_ROW_POINTERS(GLfloat, 1);
1005
1006 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1007 i++, j += colStride, k += colStride) {
1008 FILTER_F_3D(0);
1009 }
1010 }
1011 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 4)) {
1012 DECLARE_ROW_POINTERS(GLhalfARB, 4);
1013
1014 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1015 i++, j += colStride, k += colStride) {
1016 FILTER_HF_3D(0);
1017 FILTER_HF_3D(1);
1018 FILTER_HF_3D(2);
1019 FILTER_HF_3D(3);
1020 }
1021 }
1022 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 3)) {
1023 DECLARE_ROW_POINTERS(GLhalfARB, 3);
1024
1025 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1026 i++, j += colStride, k += colStride) {
1027 FILTER_HF_3D(0);
1028 FILTER_HF_3D(1);
1029 FILTER_HF_3D(2);
1030 }
1031 }
1032 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 2)) {
1033 DECLARE_ROW_POINTERS(GLhalfARB, 2);
1034
1035 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1036 i++, j += colStride, k += colStride) {
1037 FILTER_HF_3D(0);
1038 FILTER_HF_3D(1);
1039 }
1040 }
1041 else if ((datatype == GL_HALF_FLOAT_ARB) && (comps == 1)) {
1042 DECLARE_ROW_POINTERS(GLhalfARB, 1);
1043
1044 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1045 i++, j += colStride, k += colStride) {
1046 FILTER_HF_3D(0);
1047 }
1048 }
1049 else if ((datatype == GL_UNSIGNED_INT) && (comps == 1)) {
1050 const GLuint *rowA = (const GLuint *) srcRowA;
1051 const GLuint *rowB = (const GLuint *) srcRowB;
1052 const GLuint *rowC = (const GLuint *) srcRowC;
1053 const GLuint *rowD = (const GLuint *) srcRowD;
1054 GLfloat *dst = (GLfloat *) dstRow;
1055
1056 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1057 i++, j += colStride, k += colStride) {
1058 const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
1059 + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
1060 + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
1061 + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
1062 dst[i] = (GLfloat)((double) tmp * 0.125);
1063 }
1064 }
1065 else if ((datatype == GL_UNSIGNED_SHORT_5_6_5) && (comps == 3)) {
1066 DECLARE_ROW_POINTERS0(GLushort);
1067
1068 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1069 i++, j += colStride, k += colStride) {
1070 const GLint rowAr0 = rowA[j] & 0x1f;
1071 const GLint rowAr1 = rowA[k] & 0x1f;
1072 const GLint rowBr0 = rowB[j] & 0x1f;
1073 const GLint rowBr1 = rowB[k] & 0x1f;
1074 const GLint rowCr0 = rowC[j] & 0x1f;
1075 const GLint rowCr1 = rowC[k] & 0x1f;
1076 const GLint rowDr0 = rowD[j] & 0x1f;
1077 const GLint rowDr1 = rowD[k] & 0x1f;
1078 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
1079 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
1080 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
1081 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
1082 const GLint rowCg0 = (rowC[j] >> 5) & 0x3f;
1083 const GLint rowCg1 = (rowC[k] >> 5) & 0x3f;
1084 const GLint rowDg0 = (rowD[j] >> 5) & 0x3f;
1085 const GLint rowDg1 = (rowD[k] >> 5) & 0x3f;
1086 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
1087 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
1088 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
1089 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
1090 const GLint rowCb0 = (rowC[j] >> 11) & 0x1f;
1091 const GLint rowCb1 = (rowC[k] >> 11) & 0x1f;
1092 const GLint rowDb0 = (rowD[j] >> 11) & 0x1f;
1093 const GLint rowDb1 = (rowD[k] >> 11) & 0x1f;
1094 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1095 rowCr0, rowCr1, rowDr0, rowDr1);
1096 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1097 rowCg0, rowCg1, rowDg0, rowDg1);
1098 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1099 rowCb0, rowCb1, rowDb0, rowDb1);
1100 dst[i] = (b << 11) | (g << 5) | r;
1101 }
1102 }
1103 else if ((datatype == GL_UNSIGNED_SHORT_4_4_4_4) && (comps == 4)) {
1104 DECLARE_ROW_POINTERS0(GLushort);
1105
1106 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1107 i++, j += colStride, k += colStride) {
1108 const GLint rowAr0 = rowA[j] & 0xf;
1109 const GLint rowAr1 = rowA[k] & 0xf;
1110 const GLint rowBr0 = rowB[j] & 0xf;
1111 const GLint rowBr1 = rowB[k] & 0xf;
1112 const GLint rowCr0 = rowC[j] & 0xf;
1113 const GLint rowCr1 = rowC[k] & 0xf;
1114 const GLint rowDr0 = rowD[j] & 0xf;
1115 const GLint rowDr1 = rowD[k] & 0xf;
1116 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
1117 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
1118 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
1119 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
1120 const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
1121 const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
1122 const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
1123 const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
1124 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
1125 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
1126 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
1127 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
1128 const GLint rowCb0 = (rowC[j] >> 8) & 0xf;
1129 const GLint rowCb1 = (rowC[k] >> 8) & 0xf;
1130 const GLint rowDb0 = (rowD[j] >> 8) & 0xf;
1131 const GLint rowDb1 = (rowD[k] >> 8) & 0xf;
1132 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
1133 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
1134 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
1135 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
1136 const GLint rowCa0 = (rowC[j] >> 12) & 0xf;
1137 const GLint rowCa1 = (rowC[k] >> 12) & 0xf;
1138 const GLint rowDa0 = (rowD[j] >> 12) & 0xf;
1139 const GLint rowDa1 = (rowD[k] >> 12) & 0xf;
1140 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1141 rowCr0, rowCr1, rowDr0, rowDr1);
1142 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1143 rowCg0, rowCg1, rowDg0, rowDg1);
1144 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1145 rowCb0, rowCb1, rowDb0, rowDb1);
1146 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
1147 rowCa0, rowCa1, rowDa0, rowDa1);
1148
1149 dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
1150 }
1151 }
1152 else if ((datatype == GL_UNSIGNED_SHORT_1_5_5_5_REV) && (comps == 4)) {
1153 DECLARE_ROW_POINTERS0(GLushort);
1154
1155 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1156 i++, j += colStride, k += colStride) {
1157 const GLint rowAr0 = rowA[j] & 0x1f;
1158 const GLint rowAr1 = rowA[k] & 0x1f;
1159 const GLint rowBr0 = rowB[j] & 0x1f;
1160 const GLint rowBr1 = rowB[k] & 0x1f;
1161 const GLint rowCr0 = rowC[j] & 0x1f;
1162 const GLint rowCr1 = rowC[k] & 0x1f;
1163 const GLint rowDr0 = rowD[j] & 0x1f;
1164 const GLint rowDr1 = rowD[k] & 0x1f;
1165 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
1166 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
1167 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
1168 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
1169 const GLint rowCg0 = (rowC[j] >> 5) & 0x1f;
1170 const GLint rowCg1 = (rowC[k] >> 5) & 0x1f;
1171 const GLint rowDg0 = (rowD[j] >> 5) & 0x1f;
1172 const GLint rowDg1 = (rowD[k] >> 5) & 0x1f;
1173 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
1174 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
1175 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
1176 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
1177 const GLint rowCb0 = (rowC[j] >> 10) & 0x1f;
1178 const GLint rowCb1 = (rowC[k] >> 10) & 0x1f;
1179 const GLint rowDb0 = (rowD[j] >> 10) & 0x1f;
1180 const GLint rowDb1 = (rowD[k] >> 10) & 0x1f;
1181 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
1182 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
1183 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
1184 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
1185 const GLint rowCa0 = (rowC[j] >> 15) & 0x1;
1186 const GLint rowCa1 = (rowC[k] >> 15) & 0x1;
1187 const GLint rowDa0 = (rowD[j] >> 15) & 0x1;
1188 const GLint rowDa1 = (rowD[k] >> 15) & 0x1;
1189 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1190 rowCr0, rowCr1, rowDr0, rowDr1);
1191 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1192 rowCg0, rowCg1, rowDg0, rowDg1);
1193 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1194 rowCb0, rowCb1, rowDb0, rowDb1);
1195 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
1196 rowCa0, rowCa1, rowDa0, rowDa1);
1197
1198 dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
1199 }
1200 }
1201 else if ((datatype == GL_UNSIGNED_SHORT_5_5_5_1) && (comps == 4)) {
1202 DECLARE_ROW_POINTERS0(GLushort);
1203
1204 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1205 i++, j += colStride, k += colStride) {
1206 const GLint rowAr0 = (rowA[j] >> 11) & 0x1f;
1207 const GLint rowAr1 = (rowA[k] >> 11) & 0x1f;
1208 const GLint rowBr0 = (rowB[j] >> 11) & 0x1f;
1209 const GLint rowBr1 = (rowB[k] >> 11) & 0x1f;
1210 const GLint rowCr0 = (rowC[j] >> 11) & 0x1f;
1211 const GLint rowCr1 = (rowC[k] >> 11) & 0x1f;
1212 const GLint rowDr0 = (rowD[j] >> 11) & 0x1f;
1213 const GLint rowDr1 = (rowD[k] >> 11) & 0x1f;
1214 const GLint rowAg0 = (rowA[j] >> 6) & 0x1f;
1215 const GLint rowAg1 = (rowA[k] >> 6) & 0x1f;
1216 const GLint rowBg0 = (rowB[j] >> 6) & 0x1f;
1217 const GLint rowBg1 = (rowB[k] >> 6) & 0x1f;
1218 const GLint rowCg0 = (rowC[j] >> 6) & 0x1f;
1219 const GLint rowCg1 = (rowC[k] >> 6) & 0x1f;
1220 const GLint rowDg0 = (rowD[j] >> 6) & 0x1f;
1221 const GLint rowDg1 = (rowD[k] >> 6) & 0x1f;
1222 const GLint rowAb0 = (rowA[j] >> 1) & 0x1f;
1223 const GLint rowAb1 = (rowA[k] >> 1) & 0x1f;
1224 const GLint rowBb0 = (rowB[j] >> 1) & 0x1f;
1225 const GLint rowBb1 = (rowB[k] >> 1) & 0x1f;
1226 const GLint rowCb0 = (rowC[j] >> 1) & 0x1f;
1227 const GLint rowCb1 = (rowC[k] >> 1) & 0x1f;
1228 const GLint rowDb0 = (rowD[j] >> 1) & 0x1f;
1229 const GLint rowDb1 = (rowD[k] >> 1) & 0x1f;
1230 const GLint rowAa0 = (rowA[j] & 0x1);
1231 const GLint rowAa1 = (rowA[k] & 0x1);
1232 const GLint rowBa0 = (rowB[j] & 0x1);
1233 const GLint rowBa1 = (rowB[k] & 0x1);
1234 const GLint rowCa0 = (rowC[j] & 0x1);
1235 const GLint rowCa1 = (rowC[k] & 0x1);
1236 const GLint rowDa0 = (rowD[j] & 0x1);
1237 const GLint rowDa1 = (rowD[k] & 0x1);
1238 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1239 rowCr0, rowCr1, rowDr0, rowDr1);
1240 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1241 rowCg0, rowCg1, rowDg0, rowDg1);
1242 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1243 rowCb0, rowCb1, rowDb0, rowDb1);
1244 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
1245 rowCa0, rowCa1, rowDa0, rowDa1);
1246
1247 dst[i] = (r << 11) | (g << 6) | (b << 1) | a;
1248 }
1249 }
1250 else if ((datatype == GL_UNSIGNED_BYTE_3_3_2) && (comps == 3)) {
1251 DECLARE_ROW_POINTERS0(GLubyte);
1252
1253 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1254 i++, j += colStride, k += colStride) {
1255 const GLint rowAr0 = rowA[j] & 0x3;
1256 const GLint rowAr1 = rowA[k] & 0x3;
1257 const GLint rowBr0 = rowB[j] & 0x3;
1258 const GLint rowBr1 = rowB[k] & 0x3;
1259 const GLint rowCr0 = rowC[j] & 0x3;
1260 const GLint rowCr1 = rowC[k] & 0x3;
1261 const GLint rowDr0 = rowD[j] & 0x3;
1262 const GLint rowDr1 = rowD[k] & 0x3;
1263 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
1264 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
1265 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
1266 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
1267 const GLint rowCg0 = (rowC[j] >> 2) & 0x7;
1268 const GLint rowCg1 = (rowC[k] >> 2) & 0x7;
1269 const GLint rowDg0 = (rowD[j] >> 2) & 0x7;
1270 const GLint rowDg1 = (rowD[k] >> 2) & 0x7;
1271 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
1272 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
1273 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
1274 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
1275 const GLint rowCb0 = (rowC[j] >> 5) & 0x7;
1276 const GLint rowCb1 = (rowC[k] >> 5) & 0x7;
1277 const GLint rowDb0 = (rowD[j] >> 5) & 0x7;
1278 const GLint rowDb1 = (rowD[k] >> 5) & 0x7;
1279 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1280 rowCr0, rowCr1, rowDr0, rowDr1);
1281 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1282 rowCg0, rowCg1, rowDg0, rowDg1);
1283 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1284 rowCb0, rowCb1, rowDb0, rowDb1);
1285 dst[i] = (b << 5) | (g << 2) | r;
1286 }
1287 }
1288 else if (datatype == MESA_UNSIGNED_BYTE_4_4 && comps == 2) {
1289 DECLARE_ROW_POINTERS0(GLubyte);
1290
1291 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1292 i++, j += colStride, k += colStride) {
1293 const GLint rowAr0 = rowA[j] & 0xf;
1294 const GLint rowAr1 = rowA[k] & 0xf;
1295 const GLint rowBr0 = rowB[j] & 0xf;
1296 const GLint rowBr1 = rowB[k] & 0xf;
1297 const GLint rowCr0 = rowC[j] & 0xf;
1298 const GLint rowCr1 = rowC[k] & 0xf;
1299 const GLint rowDr0 = rowD[j] & 0xf;
1300 const GLint rowDr1 = rowD[k] & 0xf;
1301 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
1302 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
1303 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
1304 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
1305 const GLint rowCg0 = (rowC[j] >> 4) & 0xf;
1306 const GLint rowCg1 = (rowC[k] >> 4) & 0xf;
1307 const GLint rowDg0 = (rowD[j] >> 4) & 0xf;
1308 const GLint rowDg1 = (rowD[k] >> 4) & 0xf;
1309 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1310 rowCr0, rowCr1, rowDr0, rowDr1);
1311 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1312 rowCg0, rowCg1, rowDg0, rowDg1);
1313 dst[i] = (g << 4) | r;
1314 }
1315 }
1316 else if ((datatype == GL_UNSIGNED_INT_2_10_10_10_REV) && (comps == 4)) {
1317 DECLARE_ROW_POINTERS0(GLuint);
1318
1319 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1320 i++, j += colStride, k += colStride) {
1321 const GLint rowAr0 = rowA[j] & 0x3ff;
1322 const GLint rowAr1 = rowA[k] & 0x3ff;
1323 const GLint rowBr0 = rowB[j] & 0x3ff;
1324 const GLint rowBr1 = rowB[k] & 0x3ff;
1325 const GLint rowCr0 = rowC[j] & 0x3ff;
1326 const GLint rowCr1 = rowC[k] & 0x3ff;
1327 const GLint rowDr0 = rowD[j] & 0x3ff;
1328 const GLint rowDr1 = rowD[k] & 0x3ff;
1329 const GLint rowAg0 = (rowA[j] >> 10) & 0x3ff;
1330 const GLint rowAg1 = (rowA[k] >> 10) & 0x3ff;
1331 const GLint rowBg0 = (rowB[j] >> 10) & 0x3ff;
1332 const GLint rowBg1 = (rowB[k] >> 10) & 0x3ff;
1333 const GLint rowCg0 = (rowC[j] >> 10) & 0x3ff;
1334 const GLint rowCg1 = (rowC[k] >> 10) & 0x3ff;
1335 const GLint rowDg0 = (rowD[j] >> 10) & 0x3ff;
1336 const GLint rowDg1 = (rowD[k] >> 10) & 0x3ff;
1337 const GLint rowAb0 = (rowA[j] >> 20) & 0x3ff;
1338 const GLint rowAb1 = (rowA[k] >> 20) & 0x3ff;
1339 const GLint rowBb0 = (rowB[j] >> 20) & 0x3ff;
1340 const GLint rowBb1 = (rowB[k] >> 20) & 0x3ff;
1341 const GLint rowCb0 = (rowC[j] >> 20) & 0x3ff;
1342 const GLint rowCb1 = (rowC[k] >> 20) & 0x3ff;
1343 const GLint rowDb0 = (rowD[j] >> 20) & 0x3ff;
1344 const GLint rowDb1 = (rowD[k] >> 20) & 0x3ff;
1345 const GLint rowAa0 = (rowA[j] >> 30) & 0x3;
1346 const GLint rowAa1 = (rowA[k] >> 30) & 0x3;
1347 const GLint rowBa0 = (rowB[j] >> 30) & 0x3;
1348 const GLint rowBa1 = (rowB[k] >> 30) & 0x3;
1349 const GLint rowCa0 = (rowC[j] >> 30) & 0x3;
1350 const GLint rowCa1 = (rowC[k] >> 30) & 0x3;
1351 const GLint rowDa0 = (rowD[j] >> 30) & 0x3;
1352 const GLint rowDa1 = (rowD[k] >> 30) & 0x3;
1353 const GLint r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
1354 rowCr0, rowCr1, rowDr0, rowDr1);
1355 const GLint g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
1356 rowCg0, rowCg1, rowDg0, rowDg1);
1357 const GLint b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
1358 rowCb0, rowCb1, rowDb0, rowDb1);
1359 const GLint a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
1360 rowCa0, rowCa1, rowDa0, rowDa1);
1361
1362 dst[i] = (a << 30) | (b << 20) | (g << 10) | r;
1363 }
1364 }
1365
1366 else if (datatype == GL_UNSIGNED_INT_5_9_9_9_REV && comps == 3) {
1367 DECLARE_ROW_POINTERS0(GLuint);
1368
1369 GLfloat res[3];
1370 GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3];
1371 GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3];
1372
1373 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1374 i++, j += colStride, k += colStride) {
1375 rgb9e5_to_float3(rowA[j], rowAj);
1376 rgb9e5_to_float3(rowB[j], rowBj);
1377 rgb9e5_to_float3(rowC[j], rowCj);
1378 rgb9e5_to_float3(rowD[j], rowDj);
1379 rgb9e5_to_float3(rowA[k], rowAk);
1380 rgb9e5_to_float3(rowB[k], rowBk);
1381 rgb9e5_to_float3(rowC[k], rowCk);
1382 rgb9e5_to_float3(rowD[k], rowDk);
1383 res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] +
1384 rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F;
1385 res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] +
1386 rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F;
1387 res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] +
1388 rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F;
1389 dst[i] = float3_to_rgb9e5(res);
1390 }
1391 }
1392
1393 else if (datatype == GL_UNSIGNED_INT_10F_11F_11F_REV && comps == 3) {
1394 DECLARE_ROW_POINTERS0(GLuint);
1395
1396 GLfloat res[3];
1397 GLfloat rowAj[3], rowBj[3], rowCj[3], rowDj[3];
1398 GLfloat rowAk[3], rowBk[3], rowCk[3], rowDk[3];
1399
1400 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1401 i++, j += colStride, k += colStride) {
1402 r11g11b10f_to_float3(rowA[j], rowAj);
1403 r11g11b10f_to_float3(rowB[j], rowBj);
1404 r11g11b10f_to_float3(rowC[j], rowCj);
1405 r11g11b10f_to_float3(rowD[j], rowDj);
1406 r11g11b10f_to_float3(rowA[k], rowAk);
1407 r11g11b10f_to_float3(rowB[k], rowBk);
1408 r11g11b10f_to_float3(rowC[k], rowCk);
1409 r11g11b10f_to_float3(rowD[k], rowDk);
1410 res[0] = (rowAj[0] + rowAk[0] + rowBj[0] + rowBk[0] +
1411 rowCj[0] + rowCk[0] + rowDj[0] + rowDk[0]) * 0.125F;
1412 res[1] = (rowAj[1] + rowAk[1] + rowBj[1] + rowBk[1] +
1413 rowCj[1] + rowCk[1] + rowDj[1] + rowDk[1]) * 0.125F;
1414 res[2] = (rowAj[2] + rowAk[2] + rowBj[2] + rowBk[2] +
1415 rowCj[2] + rowCk[2] + rowDj[2] + rowDk[2]) * 0.125F;
1416 dst[i] = float3_to_r11g11b10f(res);
1417 }
1418 }
1419
1420 else if (datatype == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && comps == 1) {
1421 DECLARE_ROW_POINTERS(GLfloat, 2);
1422
1423 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1424 i++, j += colStride, k += colStride) {
1425 FILTER_F_3D(0);
1426 }
1427 }
1428
1429 else {
1430 unreachable("bad format in do_row()");
1431 }
1432 }
1433
1434
1435 /*
1436 * These functions generate a 1/2-size mipmap image from a source image.
1437 * Texture borders are handled by copying or averaging the source image's
1438 * border texels, depending on the scale-down factor.
1439 */
1440
1441 static void
make_1d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,const GLubyte * srcPtr,GLint dstWidth,GLubyte * dstPtr)1442 make_1d_mipmap(GLenum datatype, GLuint comps, GLint border,
1443 GLint srcWidth, const GLubyte *srcPtr,
1444 GLint dstWidth, GLubyte *dstPtr)
1445 {
1446 const GLint bpt = bytes_per_pixel(datatype, comps);
1447 const GLubyte *src;
1448 GLubyte *dst;
1449
1450 /* skip the border pixel, if any */
1451 src = srcPtr + border * bpt;
1452 dst = dstPtr + border * bpt;
1453
1454 /* we just duplicate the input row, kind of hack, saves code */
1455 do_row(datatype, comps, srcWidth - 2 * border, src, src,
1456 dstWidth - 2 * border, dst);
1457
1458 if (border) {
1459 /* copy left-most pixel from source */
1460 assert(dstPtr);
1461 assert(srcPtr);
1462 memcpy(dstPtr, srcPtr, bpt);
1463 /* copy right-most pixel from source */
1464 memcpy(dstPtr + (dstWidth - 1) * bpt,
1465 srcPtr + (srcWidth - 1) * bpt,
1466 bpt);
1467 }
1468 }
1469
1470
1471 static void
make_2d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,const GLubyte * srcPtr,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLubyte * dstPtr,GLint dstRowStride)1472 make_2d_mipmap(GLenum datatype, GLuint comps, GLint border,
1473 GLint srcWidth, GLint srcHeight,
1474 const GLubyte *srcPtr, GLint srcRowStride,
1475 GLint dstWidth, GLint dstHeight,
1476 GLubyte *dstPtr, GLint dstRowStride)
1477 {
1478 const GLint bpt = bytes_per_pixel(datatype, comps);
1479 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1480 const GLint dstWidthNB = dstWidth - 2 * border;
1481 const GLint dstHeightNB = dstHeight - 2 * border;
1482 const GLubyte *srcA, *srcB;
1483 GLubyte *dst;
1484 GLint row, srcRowStep;
1485
1486 /* Compute src and dst pointers, skipping any border */
1487 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1488 if (srcHeight > 1 && srcHeight > dstHeight) {
1489 /* sample from two source rows */
1490 srcB = srcA + srcRowStride;
1491 srcRowStep = 2;
1492 }
1493 else {
1494 /* sample from one source row */
1495 srcB = srcA;
1496 srcRowStep = 1;
1497 }
1498
1499 dst = dstPtr + border * ((dstWidth + 1) * bpt);
1500
1501 for (row = 0; row < dstHeightNB; row++) {
1502 do_row(datatype, comps, srcWidthNB, srcA, srcB,
1503 dstWidthNB, dst);
1504 srcA += srcRowStep * srcRowStride;
1505 srcB += srcRowStep * srcRowStride;
1506 dst += dstRowStride;
1507 }
1508
1509 /* This is ugly but probably won't be used much */
1510 if (border > 0) {
1511 /* fill in dest border */
1512 /* lower-left border pixel */
1513 assert(dstPtr);
1514 assert(srcPtr);
1515 memcpy(dstPtr, srcPtr, bpt);
1516 /* lower-right border pixel */
1517 memcpy(dstPtr + (dstWidth - 1) * bpt,
1518 srcPtr + (srcWidth - 1) * bpt, bpt);
1519 /* upper-left border pixel */
1520 memcpy(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1521 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1522 /* upper-right border pixel */
1523 memcpy(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1524 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1525 /* lower border */
1526 do_row(datatype, comps, srcWidthNB,
1527 srcPtr + bpt,
1528 srcPtr + bpt,
1529 dstWidthNB, dstPtr + bpt);
1530 /* upper border */
1531 do_row(datatype, comps, srcWidthNB,
1532 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1533 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1534 dstWidthNB,
1535 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1536 /* left and right borders */
1537 if (srcHeight == dstHeight) {
1538 /* copy border pixel from src to dst */
1539 for (row = 1; row < srcHeight; row++) {
1540 memcpy(dstPtr + dstWidth * row * bpt,
1541 srcPtr + srcWidth * row * bpt, bpt);
1542 memcpy(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
1543 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
1544 }
1545 }
1546 else {
1547 /* average two src pixels each dest pixel */
1548 for (row = 0; row < dstHeightNB; row += 2) {
1549 do_row(datatype, comps, 1,
1550 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
1551 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1552 1, dstPtr + (dstWidth * row + 1) * bpt);
1553 do_row(datatype, comps, 1,
1554 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
1555 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1556 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1557 }
1558 }
1559 }
1560 }
1561
1562
1563 static void
make_3d_mipmap(GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,const GLubyte ** srcPtr,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLint dstDepth,GLubyte ** dstPtr,GLint dstRowStride)1564 make_3d_mipmap(GLenum datatype, GLuint comps, GLint border,
1565 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1566 const GLubyte **srcPtr, GLint srcRowStride,
1567 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1568 GLubyte **dstPtr, GLint dstRowStride)
1569 {
1570 const GLint bpt = bytes_per_pixel(datatype, comps);
1571 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1572 const GLint srcDepthNB = srcDepth - 2 * border;
1573 const GLint dstWidthNB = dstWidth - 2 * border;
1574 const GLint dstHeightNB = dstHeight - 2 * border;
1575 const GLint dstDepthNB = dstDepth - 2 * border;
1576 GLint img, row;
1577 GLint bytesPerSrcImage, bytesPerDstImage;
1578 GLint srcImageOffset, srcRowOffset;
1579
1580 (void) srcDepthNB; /* silence warnings */
1581
1582 bytesPerSrcImage = srcRowStride * srcHeight * bpt;
1583 bytesPerDstImage = dstRowStride * dstHeight * bpt;
1584
1585 /* Offset between adjacent src images to be averaged together */
1586 srcImageOffset = (srcDepth == dstDepth) ? 0 : 1;
1587
1588 /* Offset between adjacent src rows to be averaged together */
1589 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
1590
1591 /*
1592 * Need to average together up to 8 src pixels for each dest pixel.
1593 * Break that down into 3 operations:
1594 * 1. take two rows from source image and average them together.
1595 * 2. take two rows from next source image and average them together.
1596 * 3. take the two averaged rows and average them for the final dst row.
1597 */
1598
1599 /*
1600 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1601 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1602 */
1603
1604 for (img = 0; img < dstDepthNB; img++) {
1605 /* first source image pointer, skipping border */
1606 const GLubyte *imgSrcA = srcPtr[img * 2 + border]
1607 + srcRowStride * border + bpt * border;
1608 /* second source image pointer, skipping border */
1609 const GLubyte *imgSrcB = srcPtr[img * 2 + srcImageOffset + border]
1610 + srcRowStride * border + bpt * border;
1611
1612 /* address of the dest image, skipping border */
1613 GLubyte *imgDst = dstPtr[img + border]
1614 + dstRowStride * border + bpt * border;
1615
1616 /* setup the four source row pointers and the dest row pointer */
1617 const GLubyte *srcImgARowA = imgSrcA;
1618 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
1619 const GLubyte *srcImgBRowA = imgSrcB;
1620 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1621 GLubyte *dstImgRow = imgDst;
1622
1623 for (row = 0; row < dstHeightNB; row++) {
1624 do_row_3D(datatype, comps, srcWidthNB,
1625 srcImgARowA, srcImgARowB,
1626 srcImgBRowA, srcImgBRowB,
1627 dstWidthNB, dstImgRow);
1628
1629 /* advance to next rows */
1630 srcImgARowA += srcRowStride + srcRowOffset;
1631 srcImgARowB += srcRowStride + srcRowOffset;
1632 srcImgBRowA += srcRowStride + srcRowOffset;
1633 srcImgBRowB += srcRowStride + srcRowOffset;
1634 dstImgRow += dstRowStride;
1635 }
1636 }
1637
1638
1639 /* Luckily we can leverage the make_2d_mipmap() function here! */
1640 if (border > 0) {
1641 /* do front border image */
1642 make_2d_mipmap(datatype, comps, 1,
1643 srcWidth, srcHeight, srcPtr[0], srcRowStride,
1644 dstWidth, dstHeight, dstPtr[0], dstRowStride);
1645 /* do back border image */
1646 make_2d_mipmap(datatype, comps, 1,
1647 srcWidth, srcHeight, srcPtr[srcDepth - 1], srcRowStride,
1648 dstWidth, dstHeight, dstPtr[dstDepth - 1], dstRowStride);
1649
1650 /* do four remaining border edges that span the image slices */
1651 if (srcDepth == dstDepth) {
1652 /* just copy border pixels from src to dst */
1653 for (img = 0; img < dstDepthNB; img++) {
1654 const GLubyte *src;
1655 GLubyte *dst;
1656
1657 /* do border along [img][row=0][col=0] */
1658 src = srcPtr[img * 2];
1659 dst = dstPtr[img];
1660 memcpy(dst, src, bpt);
1661
1662 /* do border along [img][row=dstHeight-1][col=0] */
1663 src = srcPtr[img * 2] + (srcHeight - 1) * srcRowStride;
1664 dst = dstPtr[img] + (dstHeight - 1) * dstRowStride;
1665 memcpy(dst, src, bpt);
1666
1667 /* do border along [img][row=0][col=dstWidth-1] */
1668 src = srcPtr[img * 2] + (srcWidth - 1) * bpt;
1669 dst = dstPtr[img] + (dstWidth - 1) * bpt;
1670 memcpy(dst, src, bpt);
1671
1672 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1673 src = srcPtr[img * 2] + (bytesPerSrcImage - bpt);
1674 dst = dstPtr[img] + (bytesPerDstImage - bpt);
1675 memcpy(dst, src, bpt);
1676 }
1677 }
1678 else {
1679 /* average border pixels from adjacent src image pairs */
1680 assert(srcDepthNB == 2 * dstDepthNB);
1681 for (img = 0; img < dstDepthNB; img++) {
1682 const GLubyte *srcA, *srcB;
1683 GLubyte *dst;
1684
1685 /* do border along [img][row=0][col=0] */
1686 srcA = srcPtr[img * 2 + 0];
1687 srcB = srcPtr[img * 2 + srcImageOffset];
1688 dst = dstPtr[img];
1689 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1690
1691 /* do border along [img][row=dstHeight-1][col=0] */
1692 srcA = srcPtr[img * 2 + 0]
1693 + (srcHeight - 1) * srcRowStride;
1694 srcB = srcPtr[img * 2 + srcImageOffset]
1695 + (srcHeight - 1) * srcRowStride;
1696 dst = dstPtr[img] + (dstHeight - 1) * dstRowStride;
1697 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1698
1699 /* do border along [img][row=0][col=dstWidth-1] */
1700 srcA = srcPtr[img * 2 + 0] + (srcWidth - 1) * bpt;
1701 srcB = srcPtr[img * 2 + srcImageOffset] + (srcWidth - 1) * bpt;
1702 dst = dstPtr[img] + (dstWidth - 1) * bpt;
1703 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1704
1705 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1706 srcA = srcPtr[img * 2 + 0] + (bytesPerSrcImage - bpt);
1707 srcB = srcPtr[img * 2 + srcImageOffset] + (bytesPerSrcImage - bpt);
1708 dst = dstPtr[img] + (bytesPerDstImage - bpt);
1709 do_row(datatype, comps, 1, srcA, srcB, 1, dst);
1710 }
1711 }
1712 }
1713 }
1714
1715
1716 /**
1717 * Down-sample a texture image to produce the next lower mipmap level.
1718 * \param comps components per texel (1, 2, 3 or 4)
1719 * \param srcData array[slice] of pointers to source image slices
1720 * \param dstData array[slice] of pointers to dest image slices
1721 * \param srcRowStride stride between source rows, in bytes
1722 * \param dstRowStride stride between destination rows, in bytes
1723 */
1724 static void
_mesa_generate_mipmap_level(GLenum target,GLenum datatype,GLuint comps,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,const GLubyte ** srcData,GLint srcRowStride,GLint dstWidth,GLint dstHeight,GLint dstDepth,GLubyte ** dstData,GLint dstRowStride)1725 _mesa_generate_mipmap_level(GLenum target,
1726 GLenum datatype, GLuint comps,
1727 GLint border,
1728 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1729 const GLubyte **srcData,
1730 GLint srcRowStride,
1731 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1732 GLubyte **dstData,
1733 GLint dstRowStride)
1734 {
1735 int i;
1736
1737 switch (target) {
1738 case GL_TEXTURE_1D:
1739 make_1d_mipmap(datatype, comps, border,
1740 srcWidth, srcData[0],
1741 dstWidth, dstData[0]);
1742 break;
1743 case GL_TEXTURE_2D:
1744 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1745 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1746 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1747 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1748 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1749 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1750 make_2d_mipmap(datatype, comps, border,
1751 srcWidth, srcHeight, srcData[0], srcRowStride,
1752 dstWidth, dstHeight, dstData[0], dstRowStride);
1753 break;
1754 case GL_TEXTURE_3D:
1755 make_3d_mipmap(datatype, comps, border,
1756 srcWidth, srcHeight, srcDepth,
1757 srcData, srcRowStride,
1758 dstWidth, dstHeight, dstDepth,
1759 dstData, dstRowStride);
1760 break;
1761 case GL_TEXTURE_1D_ARRAY_EXT:
1762 assert(srcHeight == 1);
1763 assert(dstHeight == 1);
1764 for (i = 0; i < dstDepth; i++) {
1765 make_1d_mipmap(datatype, comps, border,
1766 srcWidth, srcData[i],
1767 dstWidth, dstData[i]);
1768 }
1769 break;
1770 case GL_TEXTURE_2D_ARRAY_EXT:
1771 case GL_TEXTURE_CUBE_MAP_ARRAY:
1772 for (i = 0; i < dstDepth; i++) {
1773 make_2d_mipmap(datatype, comps, border,
1774 srcWidth, srcHeight, srcData[i], srcRowStride,
1775 dstWidth, dstHeight, dstData[i], dstRowStride);
1776 }
1777 break;
1778 case GL_TEXTURE_RECTANGLE_NV:
1779 case GL_TEXTURE_EXTERNAL_OES:
1780 /* no mipmaps, do nothing */
1781 break;
1782 default:
1783 unreachable("bad tex target in _mesa_generate_mipmaps");
1784 }
1785 }
1786
1787
1788 /**
1789 * compute next (level+1) image size
1790 * \return GL_FALSE if no smaller size can be generated (eg. src is 1x1x1 size)
1791 */
1792 GLboolean
_mesa_next_mipmap_level_size(GLenum target,GLint border,GLint srcWidth,GLint srcHeight,GLint srcDepth,GLint * dstWidth,GLint * dstHeight,GLint * dstDepth)1793 _mesa_next_mipmap_level_size(GLenum target, GLint border,
1794 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1795 GLint *dstWidth, GLint *dstHeight, GLint *dstDepth)
1796 {
1797 if (srcWidth - 2 * border > 1) {
1798 *dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1799 }
1800 else {
1801 *dstWidth = srcWidth; /* can't go smaller */
1802 }
1803
1804 if ((srcHeight - 2 * border > 1) &&
1805 target != GL_TEXTURE_1D_ARRAY_EXT &&
1806 target != GL_PROXY_TEXTURE_1D_ARRAY_EXT) {
1807 *dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1808 }
1809 else {
1810 *dstHeight = srcHeight; /* can't go smaller */
1811 }
1812
1813 if ((srcDepth - 2 * border > 1) &&
1814 target != GL_TEXTURE_2D_ARRAY_EXT &&
1815 target != GL_PROXY_TEXTURE_2D_ARRAY_EXT &&
1816 target != GL_TEXTURE_CUBE_MAP_ARRAY &&
1817 target != GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) {
1818 *dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1819 }
1820 else {
1821 *dstDepth = srcDepth; /* can't go smaller */
1822 }
1823
1824 if (*dstWidth == srcWidth &&
1825 *dstHeight == srcHeight &&
1826 *dstDepth == srcDepth) {
1827 return GL_FALSE;
1828 }
1829 else {
1830 return GL_TRUE;
1831 }
1832 }
1833
1834
1835 /**
1836 * Helper function for mipmap generation.
1837 * Make sure the specified destination mipmap level is the right size/format
1838 * for mipmap generation. If not, (re) allocate it.
1839 * \return GL_TRUE if successful, GL_FALSE if mipmap generation should stop
1840 */
1841 static GLboolean
prepare_mipmap_level(struct gl_context * ctx,struct gl_texture_object * texObj,GLuint level,GLsizei width,GLsizei height,GLsizei depth,GLsizei border,GLenum intFormat,mesa_format format)1842 prepare_mipmap_level(struct gl_context *ctx,
1843 struct gl_texture_object *texObj, GLuint level,
1844 GLsizei width, GLsizei height, GLsizei depth,
1845 GLsizei border, GLenum intFormat, mesa_format format)
1846 {
1847 const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
1848 GLuint face;
1849
1850 if (texObj->Immutable) {
1851 /* The texture was created with glTexStorage() so the number/size of
1852 * mipmap levels is fixed and the storage for all images is already
1853 * allocated.
1854 */
1855 if (!texObj->Image[0][level]) {
1856 /* No more levels to create - we're done */
1857 return GL_FALSE;
1858 }
1859 else {
1860 /* Nothing to do - the texture memory must have already been
1861 * allocated to the right size so we're all set.
1862 */
1863 return GL_TRUE;
1864 }
1865 }
1866
1867 for (face = 0; face < numFaces; face++) {
1868 struct gl_texture_image *dstImage;
1869 const GLenum target = _mesa_cube_face_target(texObj->Target, face);
1870
1871 dstImage = _mesa_get_tex_image(ctx, texObj, target, level);
1872 if (!dstImage) {
1873 /* out of memory */
1874 return GL_FALSE;
1875 }
1876
1877 if (dstImage->Width != width ||
1878 dstImage->Height != height ||
1879 dstImage->Depth != depth ||
1880 dstImage->Border != border ||
1881 dstImage->InternalFormat != intFormat ||
1882 dstImage->TexFormat != format) {
1883 /* need to (re)allocate image */
1884 st_FreeTextureImageBuffer(ctx, dstImage);
1885
1886 _mesa_init_teximage_fields(ctx, dstImage,
1887 width, height, depth,
1888 border, intFormat, format);
1889
1890 st_AllocTextureImageBuffer(ctx, dstImage);
1891
1892 /* in case the mipmap level is part of an FBO: */
1893 _mesa_update_fbo_texture(ctx, texObj, face, level);
1894
1895 ctx->NewState |= _NEW_TEXTURE_OBJECT;
1896 ctx->PopAttribState |= GL_TEXTURE_BIT;
1897 }
1898 }
1899
1900 return GL_TRUE;
1901 }
1902
1903
1904 /**
1905 * Prepare all mipmap levels beyond 'baseLevel' for mipmap generation.
1906 * When finished, all the gl_texture_image structures for the smaller
1907 * mipmap levels will be consistent with the base level (in terms of
1908 * dimensions, format, etc).
1909 */
1910 void
_mesa_prepare_mipmap_levels(struct gl_context * ctx,struct gl_texture_object * texObj,unsigned baseLevel,unsigned maxLevel)1911 _mesa_prepare_mipmap_levels(struct gl_context *ctx,
1912 struct gl_texture_object *texObj,
1913 unsigned baseLevel, unsigned maxLevel)
1914 {
1915 const struct gl_texture_image *baseImage =
1916 _mesa_select_tex_image(texObj, texObj->Target, baseLevel);
1917
1918 if (baseImage == NULL)
1919 return;
1920
1921 const GLint border = 0;
1922 GLint width = baseImage->Width;
1923 GLint height = baseImage->Height;
1924 GLint depth = baseImage->Depth;
1925 const GLenum intFormat = baseImage->InternalFormat;
1926 const mesa_format texFormat = baseImage->TexFormat;
1927 GLint newWidth, newHeight, newDepth;
1928
1929 /* Prepare baseLevel + 1, baseLevel + 2, ... */
1930 for (unsigned level = baseLevel + 1; level <= maxLevel; level++) {
1931 if (!_mesa_next_mipmap_level_size(texObj->Target, border,
1932 width, height, depth,
1933 &newWidth, &newHeight, &newDepth)) {
1934 /* all done */
1935 break;
1936 }
1937
1938 if (!prepare_mipmap_level(ctx, texObj, level,
1939 newWidth, newHeight, newDepth,
1940 border, intFormat, texFormat)) {
1941 break;
1942 }
1943
1944 width = newWidth;
1945 height = newHeight;
1946 depth = newDepth;
1947 }
1948 }
1949
1950
1951 static void
generate_mipmap_uncompressed(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,const struct gl_texture_image * srcImage,GLuint maxLevel)1952 generate_mipmap_uncompressed(struct gl_context *ctx, GLenum target,
1953 struct gl_texture_object *texObj,
1954 const struct gl_texture_image *srcImage,
1955 GLuint maxLevel)
1956 {
1957 GLuint level;
1958 GLenum datatype;
1959 GLuint comps;
1960
1961 _mesa_uncompressed_format_to_type_and_comps(srcImage->TexFormat, &datatype, &comps);
1962
1963 for (level = texObj->Attrib.BaseLevel; level < maxLevel; level++) {
1964 /* generate image[level+1] from image[level] */
1965 struct gl_texture_image *srcImage, *dstImage;
1966 GLint srcRowStride, dstRowStride;
1967 GLint srcWidth, srcHeight, srcDepth;
1968 GLint dstWidth, dstHeight, dstDepth;
1969 GLint border;
1970 GLint slice;
1971 GLubyte **srcMaps, **dstMaps;
1972 GLboolean success = GL_TRUE;
1973
1974 /* get src image parameters */
1975 srcImage = _mesa_select_tex_image(texObj, target, level);
1976 assert(srcImage);
1977 srcWidth = srcImage->Width;
1978 srcHeight = srcImage->Height;
1979 srcDepth = srcImage->Depth;
1980 border = srcImage->Border;
1981
1982 /* get dest gl_texture_image */
1983 dstImage = _mesa_select_tex_image(texObj, target, level + 1);
1984 if (!dstImage) {
1985 break;
1986 }
1987 dstWidth = dstImage->Width;
1988 dstHeight = dstImage->Height;
1989 dstDepth = dstImage->Depth;
1990
1991 if (target == GL_TEXTURE_1D_ARRAY) {
1992 srcDepth = srcHeight;
1993 dstDepth = dstHeight;
1994 srcHeight = 1;
1995 dstHeight = 1;
1996 }
1997
1998 /* Map src texture image slices */
1999 srcMaps = calloc(srcDepth, sizeof(GLubyte *));
2000 if (srcMaps) {
2001 for (slice = 0; slice < srcDepth; slice++) {
2002 st_MapTextureImage(ctx, srcImage, slice,
2003 0, 0, srcWidth, srcHeight,
2004 GL_MAP_READ_BIT,
2005 &srcMaps[slice], &srcRowStride);
2006 if (!srcMaps[slice]) {
2007 success = GL_FALSE;
2008 break;
2009 }
2010 }
2011 }
2012 else {
2013 success = GL_FALSE;
2014 }
2015
2016 /* Map dst texture image slices */
2017 dstMaps = calloc(dstDepth, sizeof(GLubyte *));
2018 if (dstMaps) {
2019 for (slice = 0; slice < dstDepth; slice++) {
2020 st_MapTextureImage(ctx, dstImage, slice,
2021 0, 0, dstWidth, dstHeight,
2022 GL_MAP_WRITE_BIT,
2023 &dstMaps[slice], &dstRowStride);
2024 if (!dstMaps[slice]) {
2025 success = GL_FALSE;
2026 break;
2027 }
2028 }
2029 }
2030 else {
2031 success = GL_FALSE;
2032 }
2033
2034 if (success) {
2035 /* generate one mipmap level (for 1D/2D/3D/array/etc texture) */
2036 _mesa_generate_mipmap_level(target, datatype, comps, border,
2037 srcWidth, srcHeight, srcDepth,
2038 (const GLubyte **) srcMaps, srcRowStride,
2039 dstWidth, dstHeight, dstDepth,
2040 dstMaps, dstRowStride);
2041 }
2042
2043 /* Unmap src image slices */
2044 if (srcMaps) {
2045 for (slice = 0; slice < srcDepth; slice++) {
2046 if (srcMaps[slice]) {
2047 st_UnmapTextureImage(ctx, srcImage, slice);
2048 }
2049 }
2050 free(srcMaps);
2051 }
2052
2053 /* Unmap dst image slices */
2054 if (dstMaps) {
2055 for (slice = 0; slice < dstDepth; slice++) {
2056 if (dstMaps[slice]) {
2057 st_UnmapTextureImage(ctx, dstImage, slice);
2058 }
2059 }
2060 free(dstMaps);
2061 }
2062
2063 if (!success) {
2064 _mesa_error(ctx, GL_OUT_OF_MEMORY, "mipmap generation");
2065 break;
2066 }
2067 } /* loop over mipmap levels */
2068 }
2069
2070
2071 static void
generate_mipmap_compressed(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,struct gl_texture_image * srcImage,GLuint maxLevel)2072 generate_mipmap_compressed(struct gl_context *ctx, GLenum target,
2073 struct gl_texture_object *texObj,
2074 struct gl_texture_image *srcImage,
2075 GLuint maxLevel)
2076 {
2077 GLuint level;
2078 mesa_format temp_format;
2079 GLint components;
2080 GLuint temp_src_row_stride, temp_src_img_stride; /* in bytes */
2081 GLubyte *temp_src = NULL, *temp_dst = NULL;
2082 GLenum temp_datatype;
2083 GLenum temp_base_format;
2084 GLubyte **temp_src_slices = NULL, **temp_dst_slices = NULL;
2085
2086 /* only two types of compressed textures at this time */
2087 assert(texObj->Target == GL_TEXTURE_2D ||
2088 texObj->Target == GL_TEXTURE_2D_ARRAY ||
2089 texObj->Target == GL_TEXTURE_CUBE_MAP ||
2090 texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY);
2091
2092 /*
2093 * Choose a format for the temporary, uncompressed base image.
2094 * Then, get number of components, choose temporary image datatype,
2095 * and get base format.
2096 */
2097 temp_format = _mesa_get_uncompressed_format(srcImage->TexFormat);
2098
2099 components = _mesa_format_num_components(temp_format);
2100
2101 switch (_mesa_get_format_datatype(srcImage->TexFormat)) {
2102 case GL_FLOAT:
2103 temp_datatype = GL_FLOAT;
2104 break;
2105 case GL_SIGNED_NORMALIZED:
2106 /* Revisit this if we get compressed formats with >8 bits per component */
2107 temp_datatype = GL_BYTE;
2108 break;
2109 default:
2110 temp_datatype = GL_UNSIGNED_BYTE;
2111 }
2112
2113 temp_base_format = _mesa_get_format_base_format(temp_format);
2114
2115
2116 /* allocate storage for the temporary, uncompressed image */
2117 temp_src_row_stride = _mesa_format_row_stride(temp_format, srcImage->Width);
2118 temp_src_img_stride = _mesa_format_image_size(temp_format, srcImage->Width,
2119 srcImage->Height, 1);
2120 temp_src = malloc(temp_src_img_stride * srcImage->Depth);
2121
2122 /* Allocate storage for arrays of slice pointers */
2123 temp_src_slices = malloc(srcImage->Depth * sizeof(GLubyte *));
2124 temp_dst_slices = malloc(srcImage->Depth * sizeof(GLubyte *));
2125
2126 if (!temp_src || !temp_src_slices || !temp_dst_slices) {
2127 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
2128 goto end;
2129 }
2130
2131 /* decompress base image to the temporary src buffer */
2132 {
2133 /* save pixel packing mode */
2134 struct gl_pixelstore_attrib save = ctx->Pack;
2135 /* use default/tight packing parameters */
2136 ctx->Pack = ctx->DefaultPacking;
2137
2138 /* Get the uncompressed image */
2139 assert(srcImage->Level == texObj->Attrib.BaseLevel);
2140 st_GetTexSubImage(ctx,
2141 0, 0, 0,
2142 srcImage->Width, srcImage->Height,
2143 srcImage->Depth,
2144 temp_base_format, temp_datatype,
2145 temp_src, srcImage);
2146 /* restore packing mode */
2147 ctx->Pack = save;
2148 }
2149
2150 for (level = texObj->Attrib.BaseLevel; level < maxLevel; level++) {
2151 /* generate image[level+1] from image[level] */
2152 const struct gl_texture_image *srcImage;
2153 struct gl_texture_image *dstImage;
2154 GLint srcWidth, srcHeight, srcDepth;
2155 GLint dstWidth, dstHeight, dstDepth;
2156 GLint border;
2157 GLuint temp_dst_row_stride, temp_dst_img_stride; /* in bytes */
2158 GLint i;
2159
2160 /* get src image parameters */
2161 srcImage = _mesa_select_tex_image(texObj, target, level);
2162 assert(srcImage);
2163 srcWidth = srcImage->Width;
2164 srcHeight = srcImage->Height;
2165 srcDepth = srcImage->Depth;
2166 border = srcImage->Border;
2167
2168 /* get dest gl_texture_image */
2169 dstImage = _mesa_select_tex_image(texObj, target, level + 1);
2170 if (!dstImage) {
2171 break;
2172 }
2173 dstWidth = dstImage->Width;
2174 dstHeight = dstImage->Height;
2175 dstDepth = dstImage->Depth;
2176
2177 /* Compute dst image strides and alloc memory on first iteration */
2178 temp_dst_row_stride = _mesa_format_row_stride(temp_format, dstWidth);
2179 temp_dst_img_stride = _mesa_format_image_size(temp_format, dstWidth,
2180 dstHeight, 1);
2181 if (!temp_dst) {
2182 temp_dst = malloc(temp_dst_img_stride * dstDepth);
2183 if (!temp_dst) {
2184 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
2185 goto end;
2186 }
2187 }
2188
2189 /* for 2D arrays, setup array[depth] of slice pointers */
2190 for (i = 0; i < srcDepth; i++) {
2191 temp_src_slices[i] = temp_src + temp_src_img_stride * i;
2192 }
2193 for (i = 0; i < dstDepth; i++) {
2194 temp_dst_slices[i] = temp_dst + temp_dst_img_stride * i;
2195 }
2196
2197 /* Rescale src image to dest image.
2198 * This will loop over the slices of a 2D array.
2199 */
2200 _mesa_generate_mipmap_level(target, temp_datatype, components, border,
2201 srcWidth, srcHeight, srcDepth,
2202 (const GLubyte **) temp_src_slices,
2203 temp_src_row_stride,
2204 dstWidth, dstHeight, dstDepth,
2205 temp_dst_slices, temp_dst_row_stride);
2206
2207 /* The image space was allocated above so use glTexSubImage now */
2208 st_TexSubImage(ctx, 2, dstImage,
2209 0, 0, 0, dstWidth, dstHeight, dstDepth,
2210 temp_base_format, temp_datatype,
2211 temp_dst, &ctx->DefaultPacking);
2212
2213 /* swap src and dest pointers */
2214 {
2215 GLubyte *temp = temp_src;
2216 temp_src = temp_dst;
2217 temp_dst = temp;
2218 temp_src_row_stride = temp_dst_row_stride;
2219 temp_src_img_stride = temp_dst_img_stride;
2220 }
2221 } /* loop over mipmap levels */
2222
2223 end:
2224 free(temp_src);
2225 free(temp_dst);
2226 free(temp_src_slices);
2227 free(temp_dst_slices);
2228 }
2229
2230 /**
2231 * Automatic mipmap generation.
2232 * This is the fallback/default function for mipmap generation.
2233 * Generate a complete set of mipmaps from texObj's BaseLevel image.
2234 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
2235 * For cube maps, target will be one of
2236 * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
2237 */
2238 void
_mesa_generate_mipmap(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj)2239 _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
2240 struct gl_texture_object *texObj)
2241 {
2242 struct gl_texture_image *srcImage;
2243 GLint maxLevel;
2244
2245 assert(texObj);
2246 srcImage = _mesa_select_tex_image(texObj, target, texObj->Attrib.BaseLevel);
2247 assert(srcImage);
2248
2249 maxLevel = _mesa_max_texture_levels(ctx, texObj->Target) - 1;
2250 assert(maxLevel >= 0); /* bad target */
2251
2252 maxLevel = MIN2(maxLevel, texObj->Attrib.MaxLevel);
2253
2254 _mesa_prepare_mipmap_levels(ctx, texObj, texObj->Attrib.BaseLevel, maxLevel);
2255
2256 if (_mesa_is_format_compressed(srcImage->TexFormat)) {
2257 generate_mipmap_compressed(ctx, target, texObj, srcImage, maxLevel);
2258 } else {
2259 generate_mipmap_uncompressed(ctx, target, texObj, srcImage, maxLevel);
2260 }
2261 }
2262