gallium: remove pipe_buffer from surfaces
[mesa.git] / src / gallium / auxiliary / util / u_gen_mipmap.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 * Copyright 2008 VMware, Inc. All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 /**
30 * @file
31 * Mipmap generation utility
32 *
33 * @author Brian Paul
34 */
35
36
37 #include "pipe/p_context.h"
38 #include "pipe/p_debug.h"
39 #include "pipe/p_defines.h"
40 #include "pipe/p_inlines.h"
41 #include "pipe/p_shader_tokens.h"
42
43 #include "util/u_memory.h"
44 #include "util/u_draw_quad.h"
45 #include "util/u_gen_mipmap.h"
46 #include "util/u_simple_shaders.h"
47
48 #include "tgsi/tgsi_build.h"
49 #include "tgsi/tgsi_dump.h"
50 #include "tgsi/tgsi_parse.h"
51
52 #include "cso_cache/cso_context.h"
53
54
55 struct gen_mipmap_state
56 {
57 struct pipe_context *pipe;
58 struct cso_context *cso;
59
60 struct pipe_blend_state blend;
61 struct pipe_depth_stencil_alpha_state depthstencil;
62 struct pipe_rasterizer_state rasterizer;
63 struct pipe_sampler_state sampler;
64 struct pipe_viewport_state viewport;
65
66 struct pipe_shader_state vert_shader;
67 struct pipe_shader_state frag_shader;
68 void *vs;
69 void *fs;
70
71 struct pipe_buffer *vbuf; /**< quad vertices */
72 unsigned vbuf_slot;
73
74 float vertices[4][2][4]; /**< vertex/texcoords for quad */
75 };
76
77
78
79 enum dtype
80 {
81 UBYTE,
82 UBYTE_3_3_2,
83 USHORT,
84 USHORT_4_4_4_4,
85 USHORT_5_6_5,
86 USHORT_1_5_5_5_REV,
87 UINT,
88 FLOAT,
89 HALF_FLOAT
90 };
91
92
93 typedef ushort half_float;
94
95
96 static half_float
97 float_to_half(float f)
98 {
99 /* XXX fix this */
100 return 0;
101 }
102
103 static float
104 half_to_float(half_float h)
105 {
106 /* XXX fix this */
107 return 0.0f;
108 }
109
110
111
112
113 /**
114 * \name Support macros for do_row and do_row_3d
115 *
116 * The macro madness is here for two reasons. First, it compacts the code
117 * slightly. Second, it makes it much easier to adjust the specifics of the
118 * filter to tune the rounding characteristics.
119 */
120 /*@{*/
121 #define DECLARE_ROW_POINTERS(t, e) \
122 const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
123 const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
124 const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
125 const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
126 t(*dst)[e] = (t(*)[e]) dstRow
127
128 #define DECLARE_ROW_POINTERS0(t) \
129 const t *rowA = (const t *) srcRowA; \
130 const t *rowB = (const t *) srcRowB; \
131 const t *rowC = (const t *) srcRowC; \
132 const t *rowD = (const t *) srcRowD; \
133 t *dst = (t *) dstRow
134
135 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
136 ((unsigned) Aj + (unsigned) Ak \
137 + (unsigned) Bj + (unsigned) Bk \
138 + (unsigned) Cj + (unsigned) Ck \
139 + (unsigned) Dj + (unsigned) Dk \
140 + 4) >> 3
141
142 #define FILTER_3D(e) \
143 do { \
144 dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
145 rowB[j][e], rowB[k][e], \
146 rowC[j][e], rowC[k][e], \
147 rowD[j][e], rowD[k][e]); \
148 } while(0)
149
150 #define FILTER_F_3D(e) \
151 do { \
152 dst[i][e] = (rowA[j][e] + rowA[k][e] \
153 + rowB[j][e] + rowB[k][e] \
154 + rowC[j][e] + rowC[k][e] \
155 + rowD[j][e] + rowD[k][e]) * 0.125F; \
156 } while(0)
157
158 #define FILTER_HF_3D(e) \
159 do { \
160 const float aj = half_to_float(rowA[j][e]); \
161 const float ak = half_to_float(rowA[k][e]); \
162 const float bj = half_to_float(rowB[j][e]); \
163 const float bk = half_to_float(rowB[k][e]); \
164 const float cj = half_to_float(rowC[j][e]); \
165 const float ck = half_to_float(rowC[k][e]); \
166 const float dj = half_to_float(rowD[j][e]); \
167 const float dk = half_to_float(rowD[k][e]); \
168 dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
169 * 0.125F); \
170 } while(0)
171 /*@}*/
172
173
174 /**
175 * Average together two rows of a source image to produce a single new
176 * row in the dest image. It's legal for the two source rows to point
177 * to the same data. The source width must be equal to either the
178 * dest width or two times the dest width.
179 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
180 * \param comps number of components per pixel (1..4)
181 */
182 static void
183 do_row(enum dtype datatype, uint comps, int srcWidth,
184 const void *srcRowA, const void *srcRowB,
185 int dstWidth, void *dstRow)
186 {
187 const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
188 const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
189
190 assert(comps >= 1);
191 assert(comps <= 4);
192
193 /* This assertion is no longer valid with non-power-of-2 textures
194 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
195 */
196
197 if (datatype == UBYTE && comps == 4) {
198 uint i, j, k;
199 const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
200 const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
201 ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
202 for (i = j = 0, k = k0; i < (uint) dstWidth;
203 i++, j += colStride, k += colStride) {
204 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
205 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
206 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
207 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
208 }
209 }
210 else if (datatype == UBYTE && comps == 3) {
211 uint i, j, k;
212 const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
213 const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
214 ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
215 for (i = j = 0, k = k0; i < (uint) dstWidth;
216 i++, j += colStride, k += colStride) {
217 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
218 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
219 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
220 }
221 }
222 else if (datatype == UBYTE && comps == 2) {
223 uint i, j, k;
224 const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
225 const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
226 ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
227 for (i = j = 0, k = k0; i < (uint) dstWidth;
228 i++, j += colStride, k += colStride) {
229 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
230 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
231 }
232 }
233 else if (datatype == UBYTE && comps == 1) {
234 uint i, j, k;
235 const ubyte *rowA = (const ubyte *) srcRowA;
236 const ubyte *rowB = (const ubyte *) srcRowB;
237 ubyte *dst = (ubyte *) dstRow;
238 for (i = j = 0, k = k0; i < (uint) dstWidth;
239 i++, j += colStride, k += colStride) {
240 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
241 }
242 }
243
244 else if (datatype == USHORT && comps == 4) {
245 uint i, j, k;
246 const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
247 const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
248 ushort(*dst)[4] = (ushort(*)[4]) dstRow;
249 for (i = j = 0, k = k0; i < (uint) dstWidth;
250 i++, j += colStride, k += colStride) {
251 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
252 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
253 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
254 dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
255 }
256 }
257 else if (datatype == USHORT && comps == 3) {
258 uint i, j, k;
259 const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
260 const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
261 ushort(*dst)[3] = (ushort(*)[3]) dstRow;
262 for (i = j = 0, k = k0; i < (uint) dstWidth;
263 i++, j += colStride, k += colStride) {
264 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
265 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
266 dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
267 }
268 }
269 else if (datatype == USHORT && comps == 2) {
270 uint i, j, k;
271 const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
272 const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
273 ushort(*dst)[2] = (ushort(*)[2]) dstRow;
274 for (i = j = 0, k = k0; i < (uint) dstWidth;
275 i++, j += colStride, k += colStride) {
276 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
277 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
278 }
279 }
280 else if (datatype == USHORT && comps == 1) {
281 uint i, j, k;
282 const ushort *rowA = (const ushort *) srcRowA;
283 const ushort *rowB = (const ushort *) srcRowB;
284 ushort *dst = (ushort *) dstRow;
285 for (i = j = 0, k = k0; i < (uint) dstWidth;
286 i++, j += colStride, k += colStride) {
287 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
288 }
289 }
290
291 else if (datatype == FLOAT && comps == 4) {
292 uint i, j, k;
293 const float(*rowA)[4] = (const float(*)[4]) srcRowA;
294 const float(*rowB)[4] = (const float(*)[4]) srcRowB;
295 float(*dst)[4] = (float(*)[4]) dstRow;
296 for (i = j = 0, k = k0; i < (uint) dstWidth;
297 i++, j += colStride, k += colStride) {
298 dst[i][0] = (rowA[j][0] + rowA[k][0] +
299 rowB[j][0] + rowB[k][0]) * 0.25F;
300 dst[i][1] = (rowA[j][1] + rowA[k][1] +
301 rowB[j][1] + rowB[k][1]) * 0.25F;
302 dst[i][2] = (rowA[j][2] + rowA[k][2] +
303 rowB[j][2] + rowB[k][2]) * 0.25F;
304 dst[i][3] = (rowA[j][3] + rowA[k][3] +
305 rowB[j][3] + rowB[k][3]) * 0.25F;
306 }
307 }
308 else if (datatype == FLOAT && comps == 3) {
309 uint i, j, k;
310 const float(*rowA)[3] = (const float(*)[3]) srcRowA;
311 const float(*rowB)[3] = (const float(*)[3]) srcRowB;
312 float(*dst)[3] = (float(*)[3]) dstRow;
313 for (i = j = 0, k = k0; i < (uint) dstWidth;
314 i++, j += colStride, k += colStride) {
315 dst[i][0] = (rowA[j][0] + rowA[k][0] +
316 rowB[j][0] + rowB[k][0]) * 0.25F;
317 dst[i][1] = (rowA[j][1] + rowA[k][1] +
318 rowB[j][1] + rowB[k][1]) * 0.25F;
319 dst[i][2] = (rowA[j][2] + rowA[k][2] +
320 rowB[j][2] + rowB[k][2]) * 0.25F;
321 }
322 }
323 else if (datatype == FLOAT && comps == 2) {
324 uint i, j, k;
325 const float(*rowA)[2] = (const float(*)[2]) srcRowA;
326 const float(*rowB)[2] = (const float(*)[2]) srcRowB;
327 float(*dst)[2] = (float(*)[2]) dstRow;
328 for (i = j = 0, k = k0; i < (uint) dstWidth;
329 i++, j += colStride, k += colStride) {
330 dst[i][0] = (rowA[j][0] + rowA[k][0] +
331 rowB[j][0] + rowB[k][0]) * 0.25F;
332 dst[i][1] = (rowA[j][1] + rowA[k][1] +
333 rowB[j][1] + rowB[k][1]) * 0.25F;
334 }
335 }
336 else if (datatype == FLOAT && comps == 1) {
337 uint i, j, k;
338 const float *rowA = (const float *) srcRowA;
339 const float *rowB = (const float *) srcRowB;
340 float *dst = (float *) dstRow;
341 for (i = j = 0, k = k0; i < (uint) dstWidth;
342 i++, j += colStride, k += colStride) {
343 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
344 }
345 }
346
347 #if 0
348 else if (datatype == HALF_FLOAT && comps == 4) {
349 uint i, j, k, comp;
350 const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
351 const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
352 half_float(*dst)[4] = (half_float(*)[4]) dstRow;
353 for (i = j = 0, k = k0; i < (uint) dstWidth;
354 i++, j += colStride, k += colStride) {
355 for (comp = 0; comp < 4; comp++) {
356 float aj, ak, bj, bk;
357 aj = half_to_float(rowA[j][comp]);
358 ak = half_to_float(rowA[k][comp]);
359 bj = half_to_float(rowB[j][comp]);
360 bk = half_to_float(rowB[k][comp]);
361 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
362 }
363 }
364 }
365 else if (datatype == HALF_FLOAT && comps == 3) {
366 uint i, j, k, comp;
367 const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
368 const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
369 half_float(*dst)[3] = (half_float(*)[3]) dstRow;
370 for (i = j = 0, k = k0; i < (uint) dstWidth;
371 i++, j += colStride, k += colStride) {
372 for (comp = 0; comp < 3; comp++) {
373 float aj, ak, bj, bk;
374 aj = half_to_float(rowA[j][comp]);
375 ak = half_to_float(rowA[k][comp]);
376 bj = half_to_float(rowB[j][comp]);
377 bk = half_to_float(rowB[k][comp]);
378 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
379 }
380 }
381 }
382 else if (datatype == HALF_FLOAT && comps == 2) {
383 uint i, j, k, comp;
384 const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
385 const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
386 half_float(*dst)[2] = (half_float(*)[2]) dstRow;
387 for (i = j = 0, k = k0; i < (uint) dstWidth;
388 i++, j += colStride, k += colStride) {
389 for (comp = 0; comp < 2; comp++) {
390 float aj, ak, bj, bk;
391 aj = half_to_float(rowA[j][comp]);
392 ak = half_to_float(rowA[k][comp]);
393 bj = half_to_float(rowB[j][comp]);
394 bk = half_to_float(rowB[k][comp]);
395 dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
396 }
397 }
398 }
399 else if (datatype == HALF_FLOAT && comps == 1) {
400 uint i, j, k;
401 const half_float *rowA = (const half_float *) srcRowA;
402 const half_float *rowB = (const half_float *) srcRowB;
403 half_float *dst = (half_float *) dstRow;
404 for (i = j = 0, k = k0; i < (uint) dstWidth;
405 i++, j += colStride, k += colStride) {
406 float aj, ak, bj, bk;
407 aj = half_to_float(rowA[j]);
408 ak = half_to_float(rowA[k]);
409 bj = half_to_float(rowB[j]);
410 bk = half_to_float(rowB[k]);
411 dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
412 }
413 }
414 #endif
415
416 else if (datatype == UINT && comps == 1) {
417 uint i, j, k;
418 const uint *rowA = (const uint *) srcRowA;
419 const uint *rowB = (const uint *) srcRowB;
420 uint *dst = (uint *) dstRow;
421 for (i = j = 0, k = k0; i < (uint) dstWidth;
422 i++, j += colStride, k += colStride) {
423 dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
424 }
425 }
426
427 else if (datatype == USHORT_5_6_5 && comps == 3) {
428 uint i, j, k;
429 const ushort *rowA = (const ushort *) srcRowA;
430 const ushort *rowB = (const ushort *) srcRowB;
431 ushort *dst = (ushort *) dstRow;
432 for (i = j = 0, k = k0; i < (uint) dstWidth;
433 i++, j += colStride, k += colStride) {
434 const int rowAr0 = rowA[j] & 0x1f;
435 const int rowAr1 = rowA[k] & 0x1f;
436 const int rowBr0 = rowB[j] & 0x1f;
437 const int rowBr1 = rowB[k] & 0x1f;
438 const int rowAg0 = (rowA[j] >> 5) & 0x3f;
439 const int rowAg1 = (rowA[k] >> 5) & 0x3f;
440 const int rowBg0 = (rowB[j] >> 5) & 0x3f;
441 const int rowBg1 = (rowB[k] >> 5) & 0x3f;
442 const int rowAb0 = (rowA[j] >> 11) & 0x1f;
443 const int rowAb1 = (rowA[k] >> 11) & 0x1f;
444 const int rowBb0 = (rowB[j] >> 11) & 0x1f;
445 const int rowBb1 = (rowB[k] >> 11) & 0x1f;
446 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
447 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
448 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
449 dst[i] = (blue << 11) | (green << 5) | red;
450 }
451 }
452 else if (datatype == USHORT_4_4_4_4 && comps == 4) {
453 uint i, j, k;
454 const ushort *rowA = (const ushort *) srcRowA;
455 const ushort *rowB = (const ushort *) srcRowB;
456 ushort *dst = (ushort *) dstRow;
457 for (i = j = 0, k = k0; i < (uint) dstWidth;
458 i++, j += colStride, k += colStride) {
459 const int rowAr0 = rowA[j] & 0xf;
460 const int rowAr1 = rowA[k] & 0xf;
461 const int rowBr0 = rowB[j] & 0xf;
462 const int rowBr1 = rowB[k] & 0xf;
463 const int rowAg0 = (rowA[j] >> 4) & 0xf;
464 const int rowAg1 = (rowA[k] >> 4) & 0xf;
465 const int rowBg0 = (rowB[j] >> 4) & 0xf;
466 const int rowBg1 = (rowB[k] >> 4) & 0xf;
467 const int rowAb0 = (rowA[j] >> 8) & 0xf;
468 const int rowAb1 = (rowA[k] >> 8) & 0xf;
469 const int rowBb0 = (rowB[j] >> 8) & 0xf;
470 const int rowBb1 = (rowB[k] >> 8) & 0xf;
471 const int rowAa0 = (rowA[j] >> 12) & 0xf;
472 const int rowAa1 = (rowA[k] >> 12) & 0xf;
473 const int rowBa0 = (rowB[j] >> 12) & 0xf;
474 const int rowBa1 = (rowB[k] >> 12) & 0xf;
475 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
476 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
477 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
478 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
479 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
480 }
481 }
482 else if (datatype == USHORT_1_5_5_5_REV && comps == 4) {
483 uint i, j, k;
484 const ushort *rowA = (const ushort *) srcRowA;
485 const ushort *rowB = (const ushort *) srcRowB;
486 ushort *dst = (ushort *) dstRow;
487 for (i = j = 0, k = k0; i < (uint) dstWidth;
488 i++, j += colStride, k += colStride) {
489 const int rowAr0 = rowA[j] & 0x1f;
490 const int rowAr1 = rowA[k] & 0x1f;
491 const int rowBr0 = rowB[j] & 0x1f;
492 const int rowBr1 = rowB[k] & 0x1f;
493 const int rowAg0 = (rowA[j] >> 5) & 0x1f;
494 const int rowAg1 = (rowA[k] >> 5) & 0x1f;
495 const int rowBg0 = (rowB[j] >> 5) & 0x1f;
496 const int rowBg1 = (rowB[k] >> 5) & 0x1f;
497 const int rowAb0 = (rowA[j] >> 10) & 0x1f;
498 const int rowAb1 = (rowA[k] >> 10) & 0x1f;
499 const int rowBb0 = (rowB[j] >> 10) & 0x1f;
500 const int rowBb1 = (rowB[k] >> 10) & 0x1f;
501 const int rowAa0 = (rowA[j] >> 15) & 0x1;
502 const int rowAa1 = (rowA[k] >> 15) & 0x1;
503 const int rowBa0 = (rowB[j] >> 15) & 0x1;
504 const int rowBa1 = (rowB[k] >> 15) & 0x1;
505 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
506 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
507 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
508 const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
509 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
510 }
511 }
512 else if (datatype == UBYTE_3_3_2 && comps == 3) {
513 uint i, j, k;
514 const ubyte *rowA = (const ubyte *) srcRowA;
515 const ubyte *rowB = (const ubyte *) srcRowB;
516 ubyte *dst = (ubyte *) dstRow;
517 for (i = j = 0, k = k0; i < (uint) dstWidth;
518 i++, j += colStride, k += colStride) {
519 const int rowAr0 = rowA[j] & 0x3;
520 const int rowAr1 = rowA[k] & 0x3;
521 const int rowBr0 = rowB[j] & 0x3;
522 const int rowBr1 = rowB[k] & 0x3;
523 const int rowAg0 = (rowA[j] >> 2) & 0x7;
524 const int rowAg1 = (rowA[k] >> 2) & 0x7;
525 const int rowBg0 = (rowB[j] >> 2) & 0x7;
526 const int rowBg1 = (rowB[k] >> 2) & 0x7;
527 const int rowAb0 = (rowA[j] >> 5) & 0x7;
528 const int rowAb1 = (rowA[k] >> 5) & 0x7;
529 const int rowBb0 = (rowB[j] >> 5) & 0x7;
530 const int rowBb1 = (rowB[k] >> 5) & 0x7;
531 const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
532 const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
533 const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
534 dst[i] = (blue << 5) | (green << 2) | red;
535 }
536 }
537 else {
538 debug_printf("bad format in do_row()");
539 }
540 }
541
542
543 /**
544 * Average together four rows of a source image to produce a single new
545 * row in the dest image. It's legal for the two source rows to point
546 * to the same data. The source width must be equal to either the
547 * dest width or two times the dest width.
548 *
549 * \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
550 * \c GL_FLOAT, etc.
551 * \param comps number of components per pixel (1..4)
552 * \param srcWidth Width of a row in the source data
553 * \param srcRowA Pointer to one of the rows of source data
554 * \param srcRowB Pointer to one of the rows of source data
555 * \param srcRowC Pointer to one of the rows of source data
556 * \param srcRowD Pointer to one of the rows of source data
557 * \param dstWidth Width of a row in the destination data
558 * \param srcRowA Pointer to the row of destination data
559 */
560 static void
561 do_row_3D(enum dtype datatype, uint comps, int srcWidth,
562 const void *srcRowA, const void *srcRowB,
563 const void *srcRowC, const void *srcRowD,
564 int dstWidth, void *dstRow)
565 {
566 const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
567 const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
568 uint i, j, k;
569
570 assert(comps >= 1);
571 assert(comps <= 4);
572
573 if ((datatype == UBYTE) && (comps == 4)) {
574 DECLARE_ROW_POINTERS(ubyte, 4);
575
576 for (i = j = 0, k = k0; i < (uint) dstWidth;
577 i++, j += colStride, k += colStride) {
578 FILTER_3D(0);
579 FILTER_3D(1);
580 FILTER_3D(2);
581 FILTER_3D(3);
582 }
583 }
584 else if ((datatype == UBYTE) && (comps == 3)) {
585 DECLARE_ROW_POINTERS(ubyte, 3);
586
587 for (i = j = 0, k = k0; i < (uint) dstWidth;
588 i++, j += colStride, k += colStride) {
589 FILTER_3D(0);
590 FILTER_3D(1);
591 FILTER_3D(2);
592 }
593 }
594 else if ((datatype == UBYTE) && (comps == 2)) {
595 DECLARE_ROW_POINTERS(ubyte, 2);
596
597 for (i = j = 0, k = k0; i < (uint) dstWidth;
598 i++, j += colStride, k += colStride) {
599 FILTER_3D(0);
600 FILTER_3D(1);
601 }
602 }
603 else if ((datatype == UBYTE) && (comps == 1)) {
604 DECLARE_ROW_POINTERS(ubyte, 1);
605
606 for (i = j = 0, k = k0; i < (uint) dstWidth;
607 i++, j += colStride, k += colStride) {
608 FILTER_3D(0);
609 }
610 }
611 else if ((datatype == USHORT) && (comps == 4)) {
612 DECLARE_ROW_POINTERS(ushort, 4);
613
614 for (i = j = 0, k = k0; i < (uint) dstWidth;
615 i++, j += colStride, k += colStride) {
616 FILTER_3D(0);
617 FILTER_3D(1);
618 FILTER_3D(2);
619 FILTER_3D(3);
620 }
621 }
622 else if ((datatype == USHORT) && (comps == 3)) {
623 DECLARE_ROW_POINTERS(ushort, 3);
624
625 for (i = j = 0, k = k0; i < (uint) dstWidth;
626 i++, j += colStride, k += colStride) {
627 FILTER_3D(0);
628 FILTER_3D(1);
629 FILTER_3D(2);
630 }
631 }
632 else if ((datatype == USHORT) && (comps == 2)) {
633 DECLARE_ROW_POINTERS(ushort, 2);
634
635 for (i = j = 0, k = k0; i < (uint) dstWidth;
636 i++, j += colStride, k += colStride) {
637 FILTER_3D(0);
638 FILTER_3D(1);
639 }
640 }
641 else if ((datatype == USHORT) && (comps == 1)) {
642 DECLARE_ROW_POINTERS(ushort, 1);
643
644 for (i = j = 0, k = k0; i < (uint) dstWidth;
645 i++, j += colStride, k += colStride) {
646 FILTER_3D(0);
647 }
648 }
649 else if ((datatype == FLOAT) && (comps == 4)) {
650 DECLARE_ROW_POINTERS(float, 4);
651
652 for (i = j = 0, k = k0; i < (uint) dstWidth;
653 i++, j += colStride, k += colStride) {
654 FILTER_F_3D(0);
655 FILTER_F_3D(1);
656 FILTER_F_3D(2);
657 FILTER_F_3D(3);
658 }
659 }
660 else if ((datatype == FLOAT) && (comps == 3)) {
661 DECLARE_ROW_POINTERS(float, 3);
662
663 for (i = j = 0, k = k0; i < (uint) dstWidth;
664 i++, j += colStride, k += colStride) {
665 FILTER_F_3D(0);
666 FILTER_F_3D(1);
667 FILTER_F_3D(2);
668 }
669 }
670 else if ((datatype == FLOAT) && (comps == 2)) {
671 DECLARE_ROW_POINTERS(float, 2);
672
673 for (i = j = 0, k = k0; i < (uint) dstWidth;
674 i++, j += colStride, k += colStride) {
675 FILTER_F_3D(0);
676 FILTER_F_3D(1);
677 }
678 }
679 else if ((datatype == FLOAT) && (comps == 1)) {
680 DECLARE_ROW_POINTERS(float, 1);
681
682 for (i = j = 0, k = k0; i < (uint) dstWidth;
683 i++, j += colStride, k += colStride) {
684 FILTER_F_3D(0);
685 }
686 }
687 else if ((datatype == HALF_FLOAT) && (comps == 4)) {
688 DECLARE_ROW_POINTERS(half_float, 4);
689
690 for (i = j = 0, k = k0; i < (uint) dstWidth;
691 i++, j += colStride, k += colStride) {
692 FILTER_HF_3D(0);
693 FILTER_HF_3D(1);
694 FILTER_HF_3D(2);
695 FILTER_HF_3D(3);
696 }
697 }
698 else if ((datatype == HALF_FLOAT) && (comps == 3)) {
699 DECLARE_ROW_POINTERS(half_float, 4);
700
701 for (i = j = 0, k = k0; i < (uint) dstWidth;
702 i++, j += colStride, k += colStride) {
703 FILTER_HF_3D(0);
704 FILTER_HF_3D(1);
705 FILTER_HF_3D(2);
706 }
707 }
708 else if ((datatype == HALF_FLOAT) && (comps == 2)) {
709 DECLARE_ROW_POINTERS(half_float, 4);
710
711 for (i = j = 0, k = k0; i < (uint) dstWidth;
712 i++, j += colStride, k += colStride) {
713 FILTER_HF_3D(0);
714 FILTER_HF_3D(1);
715 }
716 }
717 else if ((datatype == HALF_FLOAT) && (comps == 1)) {
718 DECLARE_ROW_POINTERS(half_float, 4);
719
720 for (i = j = 0, k = k0; i < (uint) dstWidth;
721 i++, j += colStride, k += colStride) {
722 FILTER_HF_3D(0);
723 }
724 }
725 else if ((datatype == UINT) && (comps == 1)) {
726 const uint *rowA = (const uint *) srcRowA;
727 const uint *rowB = (const uint *) srcRowB;
728 const uint *rowC = (const uint *) srcRowC;
729 const uint *rowD = (const uint *) srcRowD;
730 float *dst = (float *) dstRow;
731
732 for (i = j = 0, k = k0; i < (uint) dstWidth;
733 i++, j += colStride, k += colStride) {
734 const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
735 + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
736 + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
737 + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
738 dst[i] = (float)((double) tmp * 0.125);
739 }
740 }
741 else if ((datatype == USHORT_5_6_5) && (comps == 3)) {
742 DECLARE_ROW_POINTERS0(ushort);
743
744 for (i = j = 0, k = k0; i < (uint) dstWidth;
745 i++, j += colStride, k += colStride) {
746 const int rowAr0 = rowA[j] & 0x1f;
747 const int rowAr1 = rowA[k] & 0x1f;
748 const int rowBr0 = rowB[j] & 0x1f;
749 const int rowBr1 = rowB[k] & 0x1f;
750 const int rowCr0 = rowC[j] & 0x1f;
751 const int rowCr1 = rowC[k] & 0x1f;
752 const int rowDr0 = rowD[j] & 0x1f;
753 const int rowDr1 = rowD[k] & 0x1f;
754 const int rowAg0 = (rowA[j] >> 5) & 0x3f;
755 const int rowAg1 = (rowA[k] >> 5) & 0x3f;
756 const int rowBg0 = (rowB[j] >> 5) & 0x3f;
757 const int rowBg1 = (rowB[k] >> 5) & 0x3f;
758 const int rowCg0 = (rowC[j] >> 5) & 0x3f;
759 const int rowCg1 = (rowC[k] >> 5) & 0x3f;
760 const int rowDg0 = (rowD[j] >> 5) & 0x3f;
761 const int rowDg1 = (rowD[k] >> 5) & 0x3f;
762 const int rowAb0 = (rowA[j] >> 11) & 0x1f;
763 const int rowAb1 = (rowA[k] >> 11) & 0x1f;
764 const int rowBb0 = (rowB[j] >> 11) & 0x1f;
765 const int rowBb1 = (rowB[k] >> 11) & 0x1f;
766 const int rowCb0 = (rowC[j] >> 11) & 0x1f;
767 const int rowCb1 = (rowC[k] >> 11) & 0x1f;
768 const int rowDb0 = (rowD[j] >> 11) & 0x1f;
769 const int rowDb1 = (rowD[k] >> 11) & 0x1f;
770 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
771 rowCr0, rowCr1, rowDr0, rowDr1);
772 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
773 rowCg0, rowCg1, rowDg0, rowDg1);
774 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
775 rowCb0, rowCb1, rowDb0, rowDb1);
776 dst[i] = (b << 11) | (g << 5) | r;
777 }
778 }
779 else if ((datatype == USHORT_4_4_4_4) && (comps == 4)) {
780 DECLARE_ROW_POINTERS0(ushort);
781
782 for (i = j = 0, k = k0; i < (uint) dstWidth;
783 i++, j += colStride, k += colStride) {
784 const int rowAr0 = rowA[j] & 0xf;
785 const int rowAr1 = rowA[k] & 0xf;
786 const int rowBr0 = rowB[j] & 0xf;
787 const int rowBr1 = rowB[k] & 0xf;
788 const int rowCr0 = rowC[j] & 0xf;
789 const int rowCr1 = rowC[k] & 0xf;
790 const int rowDr0 = rowD[j] & 0xf;
791 const int rowDr1 = rowD[k] & 0xf;
792 const int rowAg0 = (rowA[j] >> 4) & 0xf;
793 const int rowAg1 = (rowA[k] >> 4) & 0xf;
794 const int rowBg0 = (rowB[j] >> 4) & 0xf;
795 const int rowBg1 = (rowB[k] >> 4) & 0xf;
796 const int rowCg0 = (rowC[j] >> 4) & 0xf;
797 const int rowCg1 = (rowC[k] >> 4) & 0xf;
798 const int rowDg0 = (rowD[j] >> 4) & 0xf;
799 const int rowDg1 = (rowD[k] >> 4) & 0xf;
800 const int rowAb0 = (rowA[j] >> 8) & 0xf;
801 const int rowAb1 = (rowA[k] >> 8) & 0xf;
802 const int rowBb0 = (rowB[j] >> 8) & 0xf;
803 const int rowBb1 = (rowB[k] >> 8) & 0xf;
804 const int rowCb0 = (rowC[j] >> 8) & 0xf;
805 const int rowCb1 = (rowC[k] >> 8) & 0xf;
806 const int rowDb0 = (rowD[j] >> 8) & 0xf;
807 const int rowDb1 = (rowD[k] >> 8) & 0xf;
808 const int rowAa0 = (rowA[j] >> 12) & 0xf;
809 const int rowAa1 = (rowA[k] >> 12) & 0xf;
810 const int rowBa0 = (rowB[j] >> 12) & 0xf;
811 const int rowBa1 = (rowB[k] >> 12) & 0xf;
812 const int rowCa0 = (rowC[j] >> 12) & 0xf;
813 const int rowCa1 = (rowC[k] >> 12) & 0xf;
814 const int rowDa0 = (rowD[j] >> 12) & 0xf;
815 const int rowDa1 = (rowD[k] >> 12) & 0xf;
816 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
817 rowCr0, rowCr1, rowDr0, rowDr1);
818 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
819 rowCg0, rowCg1, rowDg0, rowDg1);
820 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
821 rowCb0, rowCb1, rowDb0, rowDb1);
822 const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
823 rowCa0, rowCa1, rowDa0, rowDa1);
824
825 dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
826 }
827 }
828 else if ((datatype == USHORT_1_5_5_5_REV) && (comps == 4)) {
829 DECLARE_ROW_POINTERS0(ushort);
830
831 for (i = j = 0, k = k0; i < (uint) dstWidth;
832 i++, j += colStride, k += colStride) {
833 const int rowAr0 = rowA[j] & 0x1f;
834 const int rowAr1 = rowA[k] & 0x1f;
835 const int rowBr0 = rowB[j] & 0x1f;
836 const int rowBr1 = rowB[k] & 0x1f;
837 const int rowCr0 = rowC[j] & 0x1f;
838 const int rowCr1 = rowC[k] & 0x1f;
839 const int rowDr0 = rowD[j] & 0x1f;
840 const int rowDr1 = rowD[k] & 0x1f;
841 const int rowAg0 = (rowA[j] >> 5) & 0x1f;
842 const int rowAg1 = (rowA[k] >> 5) & 0x1f;
843 const int rowBg0 = (rowB[j] >> 5) & 0x1f;
844 const int rowBg1 = (rowB[k] >> 5) & 0x1f;
845 const int rowCg0 = (rowC[j] >> 5) & 0x1f;
846 const int rowCg1 = (rowC[k] >> 5) & 0x1f;
847 const int rowDg0 = (rowD[j] >> 5) & 0x1f;
848 const int rowDg1 = (rowD[k] >> 5) & 0x1f;
849 const int rowAb0 = (rowA[j] >> 10) & 0x1f;
850 const int rowAb1 = (rowA[k] >> 10) & 0x1f;
851 const int rowBb0 = (rowB[j] >> 10) & 0x1f;
852 const int rowBb1 = (rowB[k] >> 10) & 0x1f;
853 const int rowCb0 = (rowC[j] >> 10) & 0x1f;
854 const int rowCb1 = (rowC[k] >> 10) & 0x1f;
855 const int rowDb0 = (rowD[j] >> 10) & 0x1f;
856 const int rowDb1 = (rowD[k] >> 10) & 0x1f;
857 const int rowAa0 = (rowA[j] >> 15) & 0x1;
858 const int rowAa1 = (rowA[k] >> 15) & 0x1;
859 const int rowBa0 = (rowB[j] >> 15) & 0x1;
860 const int rowBa1 = (rowB[k] >> 15) & 0x1;
861 const int rowCa0 = (rowC[j] >> 15) & 0x1;
862 const int rowCa1 = (rowC[k] >> 15) & 0x1;
863 const int rowDa0 = (rowD[j] >> 15) & 0x1;
864 const int rowDa1 = (rowD[k] >> 15) & 0x1;
865 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
866 rowCr0, rowCr1, rowDr0, rowDr1);
867 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
868 rowCg0, rowCg1, rowDg0, rowDg1);
869 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
870 rowCb0, rowCb1, rowDb0, rowDb1);
871 const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
872 rowCa0, rowCa1, rowDa0, rowDa1);
873
874 dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
875 }
876 }
877 else if ((datatype == UBYTE_3_3_2) && (comps == 3)) {
878 DECLARE_ROW_POINTERS0(ushort);
879
880 for (i = j = 0, k = k0; i < (uint) dstWidth;
881 i++, j += colStride, k += colStride) {
882 const int rowAr0 = rowA[j] & 0x3;
883 const int rowAr1 = rowA[k] & 0x3;
884 const int rowBr0 = rowB[j] & 0x3;
885 const int rowBr1 = rowB[k] & 0x3;
886 const int rowCr0 = rowC[j] & 0x3;
887 const int rowCr1 = rowC[k] & 0x3;
888 const int rowDr0 = rowD[j] & 0x3;
889 const int rowDr1 = rowD[k] & 0x3;
890 const int rowAg0 = (rowA[j] >> 2) & 0x7;
891 const int rowAg1 = (rowA[k] >> 2) & 0x7;
892 const int rowBg0 = (rowB[j] >> 2) & 0x7;
893 const int rowBg1 = (rowB[k] >> 2) & 0x7;
894 const int rowCg0 = (rowC[j] >> 2) & 0x7;
895 const int rowCg1 = (rowC[k] >> 2) & 0x7;
896 const int rowDg0 = (rowD[j] >> 2) & 0x7;
897 const int rowDg1 = (rowD[k] >> 2) & 0x7;
898 const int rowAb0 = (rowA[j] >> 5) & 0x7;
899 const int rowAb1 = (rowA[k] >> 5) & 0x7;
900 const int rowBb0 = (rowB[j] >> 5) & 0x7;
901 const int rowBb1 = (rowB[k] >> 5) & 0x7;
902 const int rowCb0 = (rowC[j] >> 5) & 0x7;
903 const int rowCb1 = (rowC[k] >> 5) & 0x7;
904 const int rowDb0 = (rowD[j] >> 5) & 0x7;
905 const int rowDb1 = (rowD[k] >> 5) & 0x7;
906 const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
907 rowCr0, rowCr1, rowDr0, rowDr1);
908 const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
909 rowCg0, rowCg1, rowDg0, rowDg1);
910 const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
911 rowCb0, rowCb1, rowDb0, rowDb1);
912 dst[i] = (b << 5) | (g << 2) | r;
913 }
914 }
915 else {
916 debug_printf("bad format in do_row_3D()");
917 }
918 }
919
920
921
922 static void
923 format_to_type_comps(enum pipe_format pformat,
924 enum dtype *datatype, uint *comps)
925 {
926 switch (pformat) {
927 case PIPE_FORMAT_A8R8G8B8_UNORM:
928 case PIPE_FORMAT_X8R8G8B8_UNORM:
929 case PIPE_FORMAT_B8G8R8A8_UNORM:
930 case PIPE_FORMAT_B8G8R8X8_UNORM:
931 *datatype = UBYTE;
932 *comps = 4;
933 return;
934 case PIPE_FORMAT_A1R5G5B5_UNORM:
935 *datatype = USHORT_1_5_5_5_REV;
936 *comps = 4;
937 return;
938 case PIPE_FORMAT_A4R4G4B4_UNORM:
939 *datatype = USHORT_4_4_4_4;
940 *comps = 4;
941 return;
942 case PIPE_FORMAT_R5G6B5_UNORM:
943 *datatype = USHORT_5_6_5;
944 *comps = 3;
945 return;
946 case PIPE_FORMAT_L8_UNORM:
947 case PIPE_FORMAT_A8_UNORM:
948 case PIPE_FORMAT_I8_UNORM:
949 *datatype = UBYTE;
950 *comps = 1;
951 return;
952 case PIPE_FORMAT_A8L8_UNORM:
953 *datatype = UBYTE;
954 *comps = 2;
955 return;
956 default:
957 assert(0);
958 *datatype = UBYTE;
959 *comps = 0;
960 break;
961 }
962 }
963
964
965 static void
966 reduce_1d(enum pipe_format pformat,
967 int srcWidth, const ubyte *srcPtr,
968 int dstWidth, ubyte *dstPtr)
969 {
970 enum dtype datatype;
971 uint comps;
972
973 format_to_type_comps(pformat, &datatype, &comps);
974
975 /* we just duplicate the input row, kind of hack, saves code */
976 do_row(datatype, comps,
977 srcWidth, srcPtr, srcPtr,
978 dstWidth, dstPtr);
979 }
980
981
982 /**
983 * Strides are in bytes. If zero, it'll be computed as width * bpp.
984 */
985 static void
986 reduce_2d(enum pipe_format pformat,
987 int srcWidth, int srcHeight,
988 int srcRowStride, const ubyte *srcPtr,
989 int dstWidth, int dstHeight,
990 int dstRowStride, ubyte *dstPtr)
991 {
992 enum dtype datatype;
993 uint comps;
994 const int bpt = pf_get_size(pformat);
995 const ubyte *srcA, *srcB;
996 ubyte *dst;
997 int row;
998
999 format_to_type_comps(pformat, &datatype, &comps);
1000
1001 if (!srcRowStride)
1002 srcRowStride = bpt * srcWidth;
1003
1004 if (!dstRowStride)
1005 dstRowStride = bpt * dstWidth;
1006
1007 /* Compute src and dst pointers */
1008 srcA = srcPtr;
1009 if (srcHeight > 1)
1010 srcB = srcA + srcRowStride;
1011 else
1012 srcB = srcA;
1013 dst = dstPtr;
1014
1015 for (row = 0; row < dstHeight; row++) {
1016 do_row(datatype, comps,
1017 srcWidth, srcA, srcB,
1018 dstWidth, dst);
1019 srcA += 2 * srcRowStride;
1020 srcB += 2 * srcRowStride;
1021 dst += dstRowStride;
1022 }
1023 }
1024
1025
1026 static void
1027 reduce_3d(enum pipe_format pformat,
1028 int srcWidth, int srcHeight, int srcDepth,
1029 int srcRowStride, const ubyte *srcPtr,
1030 int dstWidth, int dstHeight, int dstDepth,
1031 int dstRowStride, ubyte *dstPtr)
1032 {
1033 const int bpt = pf_get_size(pformat);
1034 const int border = 0;
1035 int img, row;
1036 int bytesPerSrcImage, bytesPerDstImage;
1037 int bytesPerSrcRow, bytesPerDstRow;
1038 int srcImageOffset, srcRowOffset;
1039 enum dtype datatype;
1040 uint comps;
1041
1042 format_to_type_comps(pformat, &datatype, &comps);
1043
1044 bytesPerSrcImage = srcWidth * srcHeight * bpt;
1045 bytesPerDstImage = dstWidth * dstHeight * bpt;
1046
1047 bytesPerSrcRow = srcWidth * bpt;
1048 bytesPerDstRow = dstWidth * bpt;
1049
1050 /* Offset between adjacent src images to be averaged together */
1051 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
1052
1053 /* Offset between adjacent src rows to be averaged together */
1054 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
1055
1056 /*
1057 * Need to average together up to 8 src pixels for each dest pixel.
1058 * Break that down into 3 operations:
1059 * 1. take two rows from source image and average them together.
1060 * 2. take two rows from next source image and average them together.
1061 * 3. take the two averaged rows and average them for the final dst row.
1062 */
1063
1064 /*
1065 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1066 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1067 */
1068
1069 for (img = 0; img < dstDepth; img++) {
1070 /* first source image pointer, skipping border */
1071 const ubyte *imgSrcA = srcPtr
1072 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
1073 + img * (bytesPerSrcImage + srcImageOffset);
1074 /* second source image pointer, skipping border */
1075 const ubyte *imgSrcB = imgSrcA + srcImageOffset;
1076 /* address of the dest image, skipping border */
1077 ubyte *imgDst = dstPtr
1078 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
1079 + img * bytesPerDstImage;
1080
1081 /* setup the four source row pointers and the dest row pointer */
1082 const ubyte *srcImgARowA = imgSrcA;
1083 const ubyte *srcImgARowB = imgSrcA + srcRowOffset;
1084 const ubyte *srcImgBRowA = imgSrcB;
1085 const ubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1086 ubyte *dstImgRow = imgDst;
1087
1088 for (row = 0; row < dstHeight; row++) {
1089 do_row_3D(datatype, comps, srcWidth,
1090 srcImgARowA, srcImgARowB,
1091 srcImgBRowA, srcImgBRowB,
1092 dstWidth, dstImgRow);
1093
1094 /* advance to next rows */
1095 srcImgARowA += bytesPerSrcRow + srcRowOffset;
1096 srcImgARowB += bytesPerSrcRow + srcRowOffset;
1097 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
1098 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
1099 dstImgRow += bytesPerDstRow;
1100 }
1101 }
1102 }
1103
1104
1105
1106
1107 static void
1108 make_1d_mipmap(struct gen_mipmap_state *ctx,
1109 struct pipe_texture *pt,
1110 uint face, uint baseLevel, uint lastLevel)
1111 {
1112 struct pipe_context *pipe = ctx->pipe;
1113 struct pipe_screen *screen = pipe->screen;
1114 const uint zslice = 0;
1115 uint dstLevel;
1116
1117 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1118 const uint srcLevel = dstLevel - 1;
1119 struct pipe_surface *srcSurf, *dstSurf;
1120 void *srcMap, *dstMap;
1121
1122 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
1123 PIPE_BUFFER_USAGE_CPU_READ);
1124
1125 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
1126 PIPE_BUFFER_USAGE_CPU_WRITE);
1127
1128 srcMap = ((ubyte *) pipe_surface_map(srcSurf,
1129 PIPE_BUFFER_USAGE_CPU_READ)
1130 + srcSurf->offset);
1131 dstMap = ((ubyte *) pipe_surface_map(dstSurf,
1132 PIPE_BUFFER_USAGE_CPU_WRITE)
1133 + dstSurf->offset);
1134
1135 reduce_1d(pt->format,
1136 srcSurf->width, srcMap,
1137 dstSurf->width, dstMap);
1138
1139 pipe_surface_unmap(srcSurf);
1140 pipe_surface_unmap(dstSurf);
1141
1142 pipe_surface_reference(&srcSurf, NULL);
1143 pipe_surface_reference(&dstSurf, NULL);
1144 }
1145 }
1146
1147
1148 static void
1149 make_2d_mipmap(struct gen_mipmap_state *ctx,
1150 struct pipe_texture *pt,
1151 uint face, uint baseLevel, uint lastLevel)
1152 {
1153 struct pipe_context *pipe = ctx->pipe;
1154 struct pipe_screen *screen = pipe->screen;
1155 const uint zslice = 0;
1156 uint dstLevel;
1157
1158 assert(pt->block.width == 1);
1159 assert(pt->block.height == 1);
1160
1161 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1162 const uint srcLevel = dstLevel - 1;
1163 struct pipe_surface *srcSurf, *dstSurf;
1164 ubyte *srcMap, *dstMap;
1165
1166 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
1167 PIPE_BUFFER_USAGE_CPU_READ);
1168 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
1169 PIPE_BUFFER_USAGE_CPU_WRITE);
1170
1171 srcMap = ((ubyte *) pipe_surface_map(srcSurf,
1172 PIPE_BUFFER_USAGE_CPU_READ)
1173 + srcSurf->offset);
1174 dstMap = ((ubyte *) pipe_surface_map(dstSurf,
1175 PIPE_BUFFER_USAGE_CPU_WRITE)
1176 + dstSurf->offset);
1177
1178 reduce_2d(pt->format,
1179 srcSurf->width, srcSurf->height,
1180 srcSurf->stride, srcMap,
1181 dstSurf->width, dstSurf->height,
1182 dstSurf->stride, dstMap);
1183
1184 pipe_surface_unmap(srcSurf);
1185 pipe_surface_unmap(dstSurf);
1186
1187 pipe_surface_reference(&srcSurf, NULL);
1188 pipe_surface_reference(&dstSurf, NULL);
1189 }
1190 }
1191
1192
1193 static void
1194 make_3d_mipmap(struct gen_mipmap_state *ctx,
1195 struct pipe_texture *pt,
1196 uint face, uint baseLevel, uint lastLevel)
1197 {
1198 struct pipe_context *pipe = ctx->pipe;
1199 struct pipe_screen *screen = pipe->screen;
1200 uint dstLevel, zslice = 0;
1201
1202 assert(pt->block.width == 1);
1203 assert(pt->block.height == 1);
1204
1205 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1206 const uint srcLevel = dstLevel - 1;
1207 struct pipe_surface *srcSurf, *dstSurf;
1208 ubyte *srcMap, *dstMap;
1209
1210 srcSurf = screen->get_tex_surface(screen, pt, face, srcLevel, zslice,
1211 PIPE_BUFFER_USAGE_CPU_READ);
1212 dstSurf = screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
1213 PIPE_BUFFER_USAGE_CPU_WRITE);
1214
1215 srcMap = ((ubyte *) pipe_surface_map(srcSurf,
1216 PIPE_BUFFER_USAGE_CPU_READ)
1217 + srcSurf->offset);
1218 dstMap = ((ubyte *) pipe_surface_map(dstSurf,
1219 PIPE_BUFFER_USAGE_CPU_WRITE)
1220 + dstSurf->offset);
1221
1222 #if 0
1223 reduce_3d(pt->format,
1224 srcSurf->width, srcSurf->height,
1225 srcSurf->stride, srcMap,
1226 dstSurf->width, dstSurf->height,
1227 dstSurf->stride, dstMap);
1228 #else
1229 (void) reduce_3d;
1230 #endif
1231
1232 pipe_surface_unmap(srcSurf);
1233 pipe_surface_unmap(dstSurf);
1234
1235 pipe_surface_reference(&srcSurf, NULL);
1236 pipe_surface_reference(&dstSurf, NULL);
1237 }
1238 }
1239
1240
1241 static void
1242 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
1243 struct pipe_texture *pt,
1244 uint face, uint baseLevel, uint lastLevel)
1245 {
1246 switch (pt->target) {
1247 case PIPE_TEXTURE_1D:
1248 make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
1249 break;
1250 case PIPE_TEXTURE_2D:
1251 case PIPE_TEXTURE_CUBE:
1252 make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
1253 break;
1254 case PIPE_TEXTURE_3D:
1255 make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
1256 break;
1257 default:
1258 assert(0);
1259 }
1260 }
1261
1262
1263 /**
1264 * Create a mipmap generation context.
1265 * The idea is to create one of these and re-use it each time we need to
1266 * generate a mipmap.
1267 */
1268 struct gen_mipmap_state *
1269 util_create_gen_mipmap(struct pipe_context *pipe,
1270 struct cso_context *cso)
1271 {
1272 struct gen_mipmap_state *ctx;
1273 uint i;
1274
1275 ctx = CALLOC_STRUCT(gen_mipmap_state);
1276 if (!ctx)
1277 return NULL;
1278
1279 ctx->pipe = pipe;
1280 ctx->cso = cso;
1281
1282 /* disabled blending/masking */
1283 memset(&ctx->blend, 0, sizeof(ctx->blend));
1284 ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
1285 ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
1286 ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
1287 ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
1288 ctx->blend.colormask = PIPE_MASK_RGBA;
1289
1290 /* no-op depth/stencil/alpha */
1291 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
1292
1293 /* rasterizer */
1294 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
1295 ctx->rasterizer.front_winding = PIPE_WINDING_CW;
1296 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
1297 ctx->rasterizer.bypass_clipping = 1;
1298 /*ctx->rasterizer.bypass_vs = 1;*/
1299 ctx->rasterizer.gl_rasterization_rules = 1;
1300
1301 /* sampler state */
1302 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
1303 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1304 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1305 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1306 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
1307 ctx->sampler.normalized_coords = 1;
1308
1309 /* viewport state (identity, verts are in wincoords) */
1310 ctx->viewport.scale[0] = 1.0;
1311 ctx->viewport.scale[1] = 1.0;
1312 ctx->viewport.scale[2] = 1.0;
1313 ctx->viewport.scale[3] = 1.0;
1314 ctx->viewport.translate[0] = 0.0;
1315 ctx->viewport.translate[1] = 0.0;
1316 ctx->viewport.translate[2] = 0.0;
1317 ctx->viewport.translate[3] = 0.0;
1318
1319 /* vertex shader */
1320 {
1321 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
1322 TGSI_SEMANTIC_GENERIC };
1323 const uint semantic_indexes[] = { 0, 0 };
1324 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
1325 semantic_indexes,
1326 &ctx->vert_shader);
1327 }
1328
1329 /* fragment shader */
1330 ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
1331
1332 /* vertex data that doesn't change */
1333 for (i = 0; i < 4; i++) {
1334 ctx->vertices[i][0][2] = 0.0f; /* z */
1335 ctx->vertices[i][0][3] = 1.0f; /* w */
1336 ctx->vertices[i][1][2] = 0.0f; /* r */
1337 ctx->vertices[i][1][3] = 1.0f; /* q */
1338 }
1339
1340 /* Note: the actual vertex buffer is allocated as needed below */
1341
1342 return ctx;
1343 }
1344
1345
1346 /**
1347 * Get next "slot" of vertex space in the vertex buffer.
1348 * We're allocating one large vertex buffer and using it piece by piece.
1349 */
1350 static unsigned
1351 get_next_slot(struct gen_mipmap_state *ctx)
1352 {
1353 const unsigned max_slots = 4096 / sizeof ctx->vertices;
1354
1355 if (ctx->vbuf_slot >= max_slots)
1356 util_gen_mipmap_flush( ctx );
1357
1358 if (!ctx->vbuf) {
1359 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
1360 32,
1361 PIPE_BUFFER_USAGE_VERTEX,
1362 max_slots * sizeof ctx->vertices);
1363 }
1364
1365 return ctx->vbuf_slot++ * sizeof ctx->vertices;
1366 }
1367
1368
1369 static unsigned
1370 set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
1371 {
1372 void *buf;
1373 unsigned offset;
1374
1375 ctx->vertices[0][0][0] = 0.0f; /*x*/
1376 ctx->vertices[0][0][1] = 0.0f; /*y*/
1377 ctx->vertices[0][1][0] = 0.0f; /*s*/
1378 ctx->vertices[0][1][1] = 0.0f; /*t*/
1379
1380 ctx->vertices[1][0][0] = width;
1381 ctx->vertices[1][0][1] = 0.0f;
1382 ctx->vertices[1][1][0] = 1.0f;
1383 ctx->vertices[1][1][1] = 0.0f;
1384
1385 ctx->vertices[2][0][0] = width;
1386 ctx->vertices[2][0][1] = height;
1387 ctx->vertices[2][1][0] = 1.0f;
1388 ctx->vertices[2][1][1] = 1.0f;
1389
1390 ctx->vertices[3][0][0] = 0.0f;
1391 ctx->vertices[3][0][1] = height;
1392 ctx->vertices[3][1][0] = 0.0f;
1393 ctx->vertices[3][1][1] = 1.0f;
1394
1395 offset = get_next_slot( ctx );
1396
1397 buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
1398 PIPE_BUFFER_USAGE_CPU_WRITE);
1399
1400 memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
1401
1402 pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
1403
1404 return offset;
1405 }
1406
1407
1408
1409 /**
1410 * Destroy a mipmap generation context
1411 */
1412 void
1413 util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
1414 {
1415 struct pipe_context *pipe = ctx->pipe;
1416
1417 pipe->delete_vs_state(pipe, ctx->vs);
1418 pipe->delete_fs_state(pipe, ctx->fs);
1419
1420 FREE((void*) ctx->vert_shader.tokens);
1421 FREE((void*) ctx->frag_shader.tokens);
1422
1423 pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
1424
1425 FREE(ctx);
1426 }
1427
1428
1429
1430 /* Release vertex buffer at end of frame to avoid synchronous
1431 * rendering.
1432 */
1433 void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
1434 {
1435 pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
1436 ctx->vbuf_slot = 0;
1437 }
1438
1439
1440 /**
1441 * Generate mipmap images. It's assumed all needed texture memory is
1442 * already allocated.
1443 *
1444 * \param pt the texture to generate mipmap levels for
1445 * \param face which cube face to generate mipmaps for (0 for non-cube maps)
1446 * \param baseLevel the first mipmap level to use as a src
1447 * \param lastLevel the last mipmap level to generate
1448 * \param filter the minification filter used to generate mipmap levels with
1449 * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
1450 */
1451 void
1452 util_gen_mipmap(struct gen_mipmap_state *ctx,
1453 struct pipe_texture *pt,
1454 uint face, uint baseLevel, uint lastLevel, uint filter)
1455 {
1456 struct pipe_context *pipe = ctx->pipe;
1457 struct pipe_screen *screen = pipe->screen;
1458 struct pipe_framebuffer_state fb;
1459 uint dstLevel;
1460 uint zslice = 0;
1461 uint offset;
1462
1463 /* check if we can render in the texture's format */
1464 if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
1465 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
1466 fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
1467 return;
1468 }
1469
1470 /* save state (restored below) */
1471 cso_save_blend(ctx->cso);
1472 cso_save_depth_stencil_alpha(ctx->cso);
1473 cso_save_rasterizer(ctx->cso);
1474 cso_save_samplers(ctx->cso);
1475 cso_save_sampler_textures(ctx->cso);
1476 cso_save_framebuffer(ctx->cso);
1477 cso_save_fragment_shader(ctx->cso);
1478 cso_save_vertex_shader(ctx->cso);
1479 cso_save_viewport(ctx->cso);
1480
1481 /* bind our state */
1482 cso_set_blend(ctx->cso, &ctx->blend);
1483 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
1484 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
1485 cso_set_viewport(ctx->cso, &ctx->viewport);
1486
1487 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
1488 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
1489
1490 /* init framebuffer state */
1491 memset(&fb, 0, sizeof(fb));
1492 fb.nr_cbufs = 1;
1493
1494 /* set min/mag to same filter for faster sw speed */
1495 ctx->sampler.mag_img_filter = filter;
1496 ctx->sampler.min_img_filter = filter;
1497
1498 /*
1499 * XXX for small mipmap levels, it may be faster to use the software
1500 * fallback path...
1501 */
1502 for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1503 const uint srcLevel = dstLevel - 1;
1504
1505 struct pipe_surface *surf =
1506 screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
1507 PIPE_BUFFER_USAGE_GPU_WRITE);
1508
1509 /*
1510 * Setup framebuffer / dest surface
1511 */
1512 fb.cbufs[0] = surf;
1513 fb.width = pt->width[dstLevel];
1514 fb.height = pt->height[dstLevel];
1515 cso_set_framebuffer(ctx->cso, &fb);
1516
1517 /*
1518 * Setup sampler state
1519 * Note: we should only have to set the min/max LOD clamps to ensure
1520 * we grab texels from the right mipmap level. But some hardware
1521 * has trouble with min clamping so we also set the lod_bias to
1522 * try to work around that.
1523 */
1524 ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
1525 ctx->sampler.lod_bias = (float) srcLevel;
1526 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
1527 cso_single_sampler_done(ctx->cso);
1528
1529 cso_set_sampler_textures(ctx->cso, 1, &pt);
1530
1531 /* quad coords in window coords (bypassing clipping, viewport mapping) */
1532 offset = set_vertex_data(ctx,
1533 (float) pt->width[dstLevel],
1534 (float) pt->height[dstLevel]);
1535
1536 util_draw_vertex_buffer(ctx->pipe,
1537 ctx->vbuf,
1538 offset,
1539 PIPE_PRIM_TRIANGLE_FAN,
1540 4, /* verts */
1541 2); /* attribs/vert */
1542
1543 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
1544
1545 /* need to signal that the texture has changed _after_ rendering to it */
1546 pipe_surface_reference( &surf, NULL );
1547 }
1548
1549 /* restore state we changed */
1550 cso_restore_blend(ctx->cso);
1551 cso_restore_depth_stencil_alpha(ctx->cso);
1552 cso_restore_rasterizer(ctx->cso);
1553 cso_restore_samplers(ctx->cso);
1554 cso_restore_sampler_textures(ctx->cso);
1555 cso_restore_framebuffer(ctx->cso);
1556 cso_restore_fragment_shader(ctx->cso);
1557 cso_restore_vertex_shader(ctx->cso);
1558 cso_restore_viewport(ctx->cso);
1559 }