Tizen 2.1 base
[sdk/emulator/qemu.git] / gl / mesa / 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 "util/u_debug.h"
39 #include "pipe/p_defines.h"
40 #include "util/u_inlines.h"
41 #include "pipe/p_shader_tokens.h"
42 #include "pipe/p_state.h"
43
44 #include "util/u_format.h"
45 #include "util/u_memory.h"
46 #include "util/u_draw_quad.h"
47 #include "util/u_gen_mipmap.h"
48 #include "util/u_simple_shaders.h"
49 #include "util/u_math.h"
50 #include "util/u_texture.h"
51 #include "util/u_half.h"
52 #include "util/u_surface.h"
53
54 #include "cso_cache/cso_context.h"
55
56
57 struct gen_mipmap_state
58 {
59    struct pipe_context *pipe;
60    struct cso_context *cso;
61
62    struct pipe_blend_state blend;
63    struct pipe_depth_stencil_alpha_state depthstencil;
64    struct pipe_rasterizer_state rasterizer;
65    struct pipe_sampler_state sampler;
66    struct pipe_vertex_element velem[2];
67
68    void *vs;
69    void *fs[TGSI_TEXTURE_COUNT]; /**< Not all are used, but simplifies code */
70
71    struct pipe_resource *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    DTYPE_UBYTE,
82    DTYPE_UBYTE_3_3_2,
83    DTYPE_USHORT,
84    DTYPE_USHORT_4_4_4_4,
85    DTYPE_USHORT_5_6_5,
86    DTYPE_USHORT_1_5_5_5_REV,
87    DTYPE_UINT,
88    DTYPE_FLOAT,
89    DTYPE_HALF_FLOAT
90 };
91
92
93 typedef uint16_t half_float;
94
95
96 /**
97  * \name Support macros for do_row and do_row_3d
98  *
99  * The macro madness is here for two reasons.  First, it compacts the code
100  * slightly.  Second, it makes it much easier to adjust the specifics of the
101  * filter to tune the rounding characteristics.
102  */
103 /*@{*/
104 #define DECLARE_ROW_POINTERS(t, e) \
105       const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
106       const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
107       const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
108       const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
109       t(*dst)[e] = (t(*)[e]) dstRow
110
111 #define DECLARE_ROW_POINTERS0(t) \
112       const t *rowA = (const t *) srcRowA; \
113       const t *rowB = (const t *) srcRowB; \
114       const t *rowC = (const t *) srcRowC; \
115       const t *rowD = (const t *) srcRowD; \
116       t *dst = (t *) dstRow
117
118 #define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
119    ((unsigned) Aj + (unsigned) Ak \
120     + (unsigned) Bj + (unsigned) Bk \
121     + (unsigned) Cj + (unsigned) Ck \
122     + (unsigned) Dj + (unsigned) Dk \
123     + 4) >> 3
124
125 #define FILTER_3D(e) \
126    do { \
127       dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
128                                 rowB[j][e], rowB[k][e], \
129                                 rowC[j][e], rowC[k][e], \
130                                 rowD[j][e], rowD[k][e]); \
131    } while(0)
132
133 #define FILTER_F_3D(e) \
134    do { \
135       dst[i][e] = (rowA[j][e] + rowA[k][e] \
136                    + rowB[j][e] + rowB[k][e] \
137                    + rowC[j][e] + rowC[k][e] \
138                    + rowD[j][e] + rowD[k][e]) * 0.125F; \
139    } while(0)
140
141 #define FILTER_HF_3D(e) \
142    do { \
143       const float aj = util_half_to_float(rowA[j][e]); \
144       const float ak = util_half_to_float(rowA[k][e]); \
145       const float bj = util_half_to_float(rowB[j][e]); \
146       const float bk = util_half_to_float(rowB[k][e]); \
147       const float cj = util_half_to_float(rowC[j][e]); \
148       const float ck = util_half_to_float(rowC[k][e]); \
149       const float dj = util_half_to_float(rowD[j][e]); \
150       const float dk = util_half_to_float(rowD[k][e]); \
151       dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
152                                       * 0.125F); \
153    } while(0)
154 /*@}*/
155
156
157 /**
158  * Average together two rows of a source image to produce a single new
159  * row in the dest image.  It's legal for the two source rows to point
160  * to the same data.  The source width must be equal to either the
161  * dest width or two times the dest width.
162  * \param datatype  GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
163  * \param comps  number of components per pixel (1..4)
164  */
165 static void
166 do_row(enum dtype datatype, uint comps, int srcWidth,
167        const void *srcRowA, const void *srcRowB,
168        int dstWidth, void *dstRow)
169 {
170    const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
171    const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
172
173    assert(comps >= 1);
174    assert(comps <= 4);
175
176    /* This assertion is no longer valid with non-power-of-2 textures
177    assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
178    */
179
180    if (datatype == DTYPE_UBYTE && comps == 4) {
181       uint i, j, k;
182       const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
183       const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
184       ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
185       for (i = j = 0, k = k0; i < (uint) dstWidth;
186            i++, j += colStride, k += colStride) {
187          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
188          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
189          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
190          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
191       }
192    }
193    else if (datatype == DTYPE_UBYTE && comps == 3) {
194       uint i, j, k;
195       const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
196       const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
197       ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
198       for (i = j = 0, k = k0; i < (uint) dstWidth;
199            i++, j += colStride, k += colStride) {
200          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
201          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
202          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
203       }
204    }
205    else if (datatype == DTYPE_UBYTE && comps == 2) {
206       uint i, j, k;
207       const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
208       const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
209       ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
210       for (i = j = 0, k = k0; i < (uint) dstWidth;
211            i++, j += colStride, k += colStride) {
212          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
213          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
214       }
215    }
216    else if (datatype == DTYPE_UBYTE && comps == 1) {
217       uint i, j, k;
218       const ubyte *rowA = (const ubyte *) srcRowA;
219       const ubyte *rowB = (const ubyte *) srcRowB;
220       ubyte *dst = (ubyte *) dstRow;
221       for (i = j = 0, k = k0; i < (uint) dstWidth;
222            i++, j += colStride, k += colStride) {
223          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
224       }
225    }
226
227    else if (datatype == DTYPE_USHORT && comps == 4) {
228       uint i, j, k;
229       const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
230       const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
231       ushort(*dst)[4] = (ushort(*)[4]) dstRow;
232       for (i = j = 0, k = k0; i < (uint) dstWidth;
233            i++, j += colStride, k += colStride) {
234          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
235          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
236          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
237          dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
238       }
239    }
240    else if (datatype == DTYPE_USHORT && comps == 3) {
241       uint i, j, k;
242       const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
243       const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
244       ushort(*dst)[3] = (ushort(*)[3]) dstRow;
245       for (i = j = 0, k = k0; i < (uint) dstWidth;
246            i++, j += colStride, k += colStride) {
247          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
248          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
249          dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
250       }
251    }
252    else if (datatype == DTYPE_USHORT && comps == 2) {
253       uint i, j, k;
254       const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
255       const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
256       ushort(*dst)[2] = (ushort(*)[2]) dstRow;
257       for (i = j = 0, k = k0; i < (uint) dstWidth;
258            i++, j += colStride, k += colStride) {
259          dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
260          dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
261       }
262    }
263    else if (datatype == DTYPE_USHORT && comps == 1) {
264       uint i, j, k;
265       const ushort *rowA = (const ushort *) srcRowA;
266       const ushort *rowB = (const ushort *) srcRowB;
267       ushort *dst = (ushort *) dstRow;
268       for (i = j = 0, k = k0; i < (uint) dstWidth;
269            i++, j += colStride, k += colStride) {
270          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
271       }
272    }
273
274    else if (datatype == DTYPE_FLOAT && comps == 4) {
275       uint i, j, k;
276       const float(*rowA)[4] = (const float(*)[4]) srcRowA;
277       const float(*rowB)[4] = (const float(*)[4]) srcRowB;
278       float(*dst)[4] = (float(*)[4]) dstRow;
279       for (i = j = 0, k = k0; i < (uint) dstWidth;
280            i++, j += colStride, k += colStride) {
281          dst[i][0] = (rowA[j][0] + rowA[k][0] +
282                       rowB[j][0] + rowB[k][0]) * 0.25F;
283          dst[i][1] = (rowA[j][1] + rowA[k][1] +
284                       rowB[j][1] + rowB[k][1]) * 0.25F;
285          dst[i][2] = (rowA[j][2] + rowA[k][2] +
286                       rowB[j][2] + rowB[k][2]) * 0.25F;
287          dst[i][3] = (rowA[j][3] + rowA[k][3] +
288                       rowB[j][3] + rowB[k][3]) * 0.25F;
289       }
290    }
291    else if (datatype == DTYPE_FLOAT && comps == 3) {
292       uint i, j, k;
293       const float(*rowA)[3] = (const float(*)[3]) srcRowA;
294       const float(*rowB)[3] = (const float(*)[3]) srcRowB;
295       float(*dst)[3] = (float(*)[3]) 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       }
305    }
306    else if (datatype == DTYPE_FLOAT && comps == 2) {
307       uint i, j, k;
308       const float(*rowA)[2] = (const float(*)[2]) srcRowA;
309       const float(*rowB)[2] = (const float(*)[2]) srcRowB;
310       float(*dst)[2] = (float(*)[2]) dstRow;
311       for (i = j = 0, k = k0; i < (uint) dstWidth;
312            i++, j += colStride, k += colStride) {
313          dst[i][0] = (rowA[j][0] + rowA[k][0] +
314                       rowB[j][0] + rowB[k][0]) * 0.25F;
315          dst[i][1] = (rowA[j][1] + rowA[k][1] +
316                       rowB[j][1] + rowB[k][1]) * 0.25F;
317       }
318    }
319    else if (datatype == DTYPE_FLOAT && comps == 1) {
320       uint i, j, k;
321       const float *rowA = (const float *) srcRowA;
322       const float *rowB = (const float *) srcRowB;
323       float *dst = (float *) dstRow;
324       for (i = j = 0, k = k0; i < (uint) dstWidth;
325            i++, j += colStride, k += colStride) {
326          dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
327       }
328    }
329
330    else if (datatype == DTYPE_HALF_FLOAT && comps == 4) {
331       uint i, j, k, comp;
332       const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
333       const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
334       half_float(*dst)[4] = (half_float(*)[4]) dstRow;
335       for (i = j = 0, k = k0; i < (uint) dstWidth;
336            i++, j += colStride, k += colStride) {
337          for (comp = 0; comp < 4; comp++) {
338             float aj, ak, bj, bk;
339             aj = util_half_to_float(rowA[j][comp]);
340             ak = util_half_to_float(rowA[k][comp]);
341             bj = util_half_to_float(rowB[j][comp]);
342             bk = util_half_to_float(rowB[k][comp]);
343             dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
344          }
345       }
346    }
347    else if (datatype == DTYPE_HALF_FLOAT && comps == 3) {
348       uint i, j, k, comp;
349       const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
350       const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
351       half_float(*dst)[3] = (half_float(*)[3]) dstRow;
352       for (i = j = 0, k = k0; i < (uint) dstWidth;
353            i++, j += colStride, k += colStride) {
354          for (comp = 0; comp < 3; comp++) {
355             float aj, ak, bj, bk;
356             aj = util_half_to_float(rowA[j][comp]);
357             ak = util_half_to_float(rowA[k][comp]);
358             bj = util_half_to_float(rowB[j][comp]);
359             bk = util_half_to_float(rowB[k][comp]);
360             dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
361          }
362       }
363    }
364    else if (datatype == DTYPE_HALF_FLOAT && comps == 2) {
365       uint i, j, k, comp;
366       const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
367       const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
368       half_float(*dst)[2] = (half_float(*)[2]) dstRow;
369       for (i = j = 0, k = k0; i < (uint) dstWidth;
370            i++, j += colStride, k += colStride) {
371          for (comp = 0; comp < 2; comp++) {
372             float aj, ak, bj, bk;
373             aj = util_half_to_float(rowA[j][comp]);
374             ak = util_half_to_float(rowA[k][comp]);
375             bj = util_half_to_float(rowB[j][comp]);
376             bk = util_half_to_float(rowB[k][comp]);
377             dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
378          }
379       }
380    }
381    else if (datatype == DTYPE_HALF_FLOAT && comps == 1) {
382       uint i, j, k;
383       const half_float *rowA = (const half_float *) srcRowA;
384       const half_float *rowB = (const half_float *) srcRowB;
385       half_float *dst = (half_float *) dstRow;
386       for (i = j = 0, k = k0; i < (uint) dstWidth;
387            i++, j += colStride, k += colStride) {
388          float aj, ak, bj, bk;
389          aj = util_half_to_float(rowA[j]);
390          ak = util_half_to_float(rowA[k]);
391          bj = util_half_to_float(rowB[j]);
392          bk = util_half_to_float(rowB[k]);
393          dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
394       }
395    }
396
397    else if (datatype == DTYPE_UINT && comps == 1) {
398       uint i, j, k;
399       const uint *rowA = (const uint *) srcRowA;
400       const uint *rowB = (const uint *) srcRowB;
401       uint *dst = (uint *) dstRow;
402       for (i = j = 0, k = k0; i < (uint) dstWidth;
403            i++, j += colStride, k += colStride) {
404          dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
405       }
406    }
407
408    else if (datatype == DTYPE_USHORT_5_6_5 && comps == 3) {
409       uint i, j, k;
410       const ushort *rowA = (const ushort *) srcRowA;
411       const ushort *rowB = (const ushort *) srcRowB;
412       ushort *dst = (ushort *) dstRow;
413       for (i = j = 0, k = k0; i < (uint) dstWidth;
414            i++, j += colStride, k += colStride) {
415          const int rowAr0 = rowA[j] & 0x1f;
416          const int rowAr1 = rowA[k] & 0x1f;
417          const int rowBr0 = rowB[j] & 0x1f;
418          const int rowBr1 = rowB[k] & 0x1f;
419          const int rowAg0 = (rowA[j] >> 5) & 0x3f;
420          const int rowAg1 = (rowA[k] >> 5) & 0x3f;
421          const int rowBg0 = (rowB[j] >> 5) & 0x3f;
422          const int rowBg1 = (rowB[k] >> 5) & 0x3f;
423          const int rowAb0 = (rowA[j] >> 11) & 0x1f;
424          const int rowAb1 = (rowA[k] >> 11) & 0x1f;
425          const int rowBb0 = (rowB[j] >> 11) & 0x1f;
426          const int rowBb1 = (rowB[k] >> 11) & 0x1f;
427          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
428          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
429          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
430          dst[i] = (blue << 11) | (green << 5) | red;
431       }
432    }
433    else if (datatype == DTYPE_USHORT_4_4_4_4 && comps == 4) {
434       uint i, j, k;
435       const ushort *rowA = (const ushort *) srcRowA;
436       const ushort *rowB = (const ushort *) srcRowB;
437       ushort *dst = (ushort *) dstRow;
438       for (i = j = 0, k = k0; i < (uint) dstWidth;
439            i++, j += colStride, k += colStride) {
440          const int rowAr0 = rowA[j] & 0xf;
441          const int rowAr1 = rowA[k] & 0xf;
442          const int rowBr0 = rowB[j] & 0xf;
443          const int rowBr1 = rowB[k] & 0xf;
444          const int rowAg0 = (rowA[j] >> 4) & 0xf;
445          const int rowAg1 = (rowA[k] >> 4) & 0xf;
446          const int rowBg0 = (rowB[j] >> 4) & 0xf;
447          const int rowBg1 = (rowB[k] >> 4) & 0xf;
448          const int rowAb0 = (rowA[j] >> 8) & 0xf;
449          const int rowAb1 = (rowA[k] >> 8) & 0xf;
450          const int rowBb0 = (rowB[j] >> 8) & 0xf;
451          const int rowBb1 = (rowB[k] >> 8) & 0xf;
452          const int rowAa0 = (rowA[j] >> 12) & 0xf;
453          const int rowAa1 = (rowA[k] >> 12) & 0xf;
454          const int rowBa0 = (rowB[j] >> 12) & 0xf;
455          const int rowBa1 = (rowB[k] >> 12) & 0xf;
456          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
457          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
458          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
459          const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
460          dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
461       }
462    }
463    else if (datatype == DTYPE_USHORT_1_5_5_5_REV && comps == 4) {
464       uint i, j, k;
465       const ushort *rowA = (const ushort *) srcRowA;
466       const ushort *rowB = (const ushort *) srcRowB;
467       ushort *dst = (ushort *) dstRow;
468       for (i = j = 0, k = k0; i < (uint) dstWidth;
469            i++, j += colStride, k += colStride) {
470          const int rowAr0 = rowA[j] & 0x1f;
471          const int rowAr1 = rowA[k] & 0x1f;
472          const int rowBr0 = rowB[j] & 0x1f;
473          const int rowBr1 = rowB[k] & 0x1f;
474          const int rowAg0 = (rowA[j] >> 5) & 0x1f;
475          const int rowAg1 = (rowA[k] >> 5) & 0x1f;
476          const int rowBg0 = (rowB[j] >> 5) & 0x1f;
477          const int rowBg1 = (rowB[k] >> 5) & 0x1f;
478          const int rowAb0 = (rowA[j] >> 10) & 0x1f;
479          const int rowAb1 = (rowA[k] >> 10) & 0x1f;
480          const int rowBb0 = (rowB[j] >> 10) & 0x1f;
481          const int rowBb1 = (rowB[k] >> 10) & 0x1f;
482          const int rowAa0 = (rowA[j] >> 15) & 0x1;
483          const int rowAa1 = (rowA[k] >> 15) & 0x1;
484          const int rowBa0 = (rowB[j] >> 15) & 0x1;
485          const int rowBa1 = (rowB[k] >> 15) & 0x1;
486          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
487          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
488          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
489          const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
490          dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
491       }
492    }
493    else if (datatype == DTYPE_UBYTE_3_3_2 && comps == 3) {
494       uint i, j, k;
495       const ubyte *rowA = (const ubyte *) srcRowA;
496       const ubyte *rowB = (const ubyte *) srcRowB;
497       ubyte *dst = (ubyte *) dstRow;
498       for (i = j = 0, k = k0; i < (uint) dstWidth;
499            i++, j += colStride, k += colStride) {
500          const int rowAr0 = rowA[j] & 0x3;
501          const int rowAr1 = rowA[k] & 0x3;
502          const int rowBr0 = rowB[j] & 0x3;
503          const int rowBr1 = rowB[k] & 0x3;
504          const int rowAg0 = (rowA[j] >> 2) & 0x7;
505          const int rowAg1 = (rowA[k] >> 2) & 0x7;
506          const int rowBg0 = (rowB[j] >> 2) & 0x7;
507          const int rowBg1 = (rowB[k] >> 2) & 0x7;
508          const int rowAb0 = (rowA[j] >> 5) & 0x7;
509          const int rowAb1 = (rowA[k] >> 5) & 0x7;
510          const int rowBb0 = (rowB[j] >> 5) & 0x7;
511          const int rowBb1 = (rowB[k] >> 5) & 0x7;
512          const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
513          const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
514          const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
515          dst[i] = (blue << 5) | (green << 2) | red;
516       }
517    }
518    else {
519       debug_printf("bad format in do_row()");
520    }
521 }
522
523
524 /**
525  * Average together four rows of a source image to produce a single new
526  * row in the dest image.  It's legal for the two source rows to point
527  * to the same data.  The source width must be equal to either the
528  * dest width or two times the dest width.
529  *
530  * \param datatype  GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
531  *                  \c GL_FLOAT, etc.
532  * \param comps     number of components per pixel (1..4)
533  * \param srcWidth  Width of a row in the source data
534  * \param srcRowA   Pointer to one of the rows of source data
535  * \param srcRowB   Pointer to one of the rows of source data
536  * \param srcRowC   Pointer to one of the rows of source data
537  * \param srcRowD   Pointer to one of the rows of source data
538  * \param dstWidth  Width of a row in the destination data
539  * \param srcRowA   Pointer to the row of destination data
540  */
541 static void
542 do_row_3D(enum dtype datatype, uint comps, int srcWidth,
543           const void *srcRowA, const void *srcRowB,
544           const void *srcRowC, const void *srcRowD,
545           int dstWidth, void *dstRow)
546 {
547    const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
548    const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
549    uint i, j, k;
550
551    assert(comps >= 1);
552    assert(comps <= 4);
553
554    if ((datatype == DTYPE_UBYTE) && (comps == 4)) {
555       DECLARE_ROW_POINTERS(ubyte, 4);
556
557       for (i = j = 0, k = k0; i < (uint) dstWidth;
558            i++, j += colStride, k += colStride) {
559          FILTER_3D(0);
560          FILTER_3D(1);
561          FILTER_3D(2);
562          FILTER_3D(3);
563       }
564    }
565    else if ((datatype == DTYPE_UBYTE) && (comps == 3)) {
566       DECLARE_ROW_POINTERS(ubyte, 3);
567
568       for (i = j = 0, k = k0; i < (uint) dstWidth;
569            i++, j += colStride, k += colStride) {
570          FILTER_3D(0);
571          FILTER_3D(1);
572          FILTER_3D(2);
573       }
574    }
575    else if ((datatype == DTYPE_UBYTE) && (comps == 2)) {
576       DECLARE_ROW_POINTERS(ubyte, 2);
577
578       for (i = j = 0, k = k0; i < (uint) dstWidth;
579            i++, j += colStride, k += colStride) {
580          FILTER_3D(0);
581          FILTER_3D(1);
582       }
583    }
584    else if ((datatype == DTYPE_UBYTE) && (comps == 1)) {
585       DECLARE_ROW_POINTERS(ubyte, 1);
586
587       for (i = j = 0, k = k0; i < (uint) dstWidth;
588            i++, j += colStride, k += colStride) {
589          FILTER_3D(0);
590       }
591    }
592    else if ((datatype == DTYPE_USHORT) && (comps == 4)) {
593       DECLARE_ROW_POINTERS(ushort, 4);
594
595       for (i = j = 0, k = k0; i < (uint) dstWidth;
596            i++, j += colStride, k += colStride) {
597          FILTER_3D(0);
598          FILTER_3D(1);
599          FILTER_3D(2);
600          FILTER_3D(3);
601       }
602    }
603    else if ((datatype == DTYPE_USHORT) && (comps == 3)) {
604       DECLARE_ROW_POINTERS(ushort, 3);
605
606       for (i = j = 0, k = k0; i < (uint) dstWidth;
607            i++, j += colStride, k += colStride) {
608          FILTER_3D(0);
609          FILTER_3D(1);
610          FILTER_3D(2);
611       }
612    }
613    else if ((datatype == DTYPE_USHORT) && (comps == 2)) {
614       DECLARE_ROW_POINTERS(ushort, 2);
615
616       for (i = j = 0, k = k0; i < (uint) dstWidth;
617            i++, j += colStride, k += colStride) {
618          FILTER_3D(0);
619          FILTER_3D(1);
620       }
621    }
622    else if ((datatype == DTYPE_USHORT) && (comps == 1)) {
623       DECLARE_ROW_POINTERS(ushort, 1);
624
625       for (i = j = 0, k = k0; i < (uint) dstWidth;
626            i++, j += colStride, k += colStride) {
627          FILTER_3D(0);
628       }
629    }
630    else if ((datatype == DTYPE_FLOAT) && (comps == 4)) {
631       DECLARE_ROW_POINTERS(float, 4);
632
633       for (i = j = 0, k = k0; i < (uint) dstWidth;
634            i++, j += colStride, k += colStride) {
635          FILTER_F_3D(0);
636          FILTER_F_3D(1);
637          FILTER_F_3D(2);
638          FILTER_F_3D(3);
639       }
640    }
641    else if ((datatype == DTYPE_FLOAT) && (comps == 3)) {
642       DECLARE_ROW_POINTERS(float, 3);
643
644       for (i = j = 0, k = k0; i < (uint) dstWidth;
645            i++, j += colStride, k += colStride) {
646          FILTER_F_3D(0);
647          FILTER_F_3D(1);
648          FILTER_F_3D(2);
649       }
650    }
651    else if ((datatype == DTYPE_FLOAT) && (comps == 2)) {
652       DECLARE_ROW_POINTERS(float, 2);
653
654       for (i = j = 0, k = k0; i < (uint) dstWidth;
655            i++, j += colStride, k += colStride) {
656          FILTER_F_3D(0);
657          FILTER_F_3D(1);
658       }
659    }
660    else if ((datatype == DTYPE_FLOAT) && (comps == 1)) {
661       DECLARE_ROW_POINTERS(float, 1);
662
663       for (i = j = 0, k = k0; i < (uint) dstWidth;
664            i++, j += colStride, k += colStride) {
665          FILTER_F_3D(0);
666       }
667    }
668    else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 4)) {
669       DECLARE_ROW_POINTERS(half_float, 4);
670
671       for (i = j = 0, k = k0; i < (uint) dstWidth;
672            i++, j += colStride, k += colStride) {
673          FILTER_HF_3D(0);
674          FILTER_HF_3D(1);
675          FILTER_HF_3D(2);
676          FILTER_HF_3D(3);
677       }
678    }
679    else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 3)) {
680       DECLARE_ROW_POINTERS(half_float, 4);
681
682       for (i = j = 0, k = k0; i < (uint) dstWidth;
683            i++, j += colStride, k += colStride) {
684          FILTER_HF_3D(0);
685          FILTER_HF_3D(1);
686          FILTER_HF_3D(2);
687       }
688    }
689    else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 2)) {
690       DECLARE_ROW_POINTERS(half_float, 4);
691
692       for (i = j = 0, k = k0; i < (uint) dstWidth;
693            i++, j += colStride, k += colStride) {
694          FILTER_HF_3D(0);
695          FILTER_HF_3D(1);
696       }
697    }
698    else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 1)) {
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       }
705    }
706    else if ((datatype == DTYPE_UINT) && (comps == 1)) {
707       const uint *rowA = (const uint *) srcRowA;
708       const uint *rowB = (const uint *) srcRowB;
709       const uint *rowC = (const uint *) srcRowC;
710       const uint *rowD = (const uint *) srcRowD;
711       float *dst = (float *) dstRow;
712
713       for (i = j = 0, k = k0; i < (uint) dstWidth;
714            i++, j += colStride, k += colStride) {
715          const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
716                                + ((uint64_t) rowB[j] + (uint64_t) rowB[k])
717                                + ((uint64_t) rowC[j] + (uint64_t) rowC[k])
718                                + ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
719          dst[i] = (float)((double) tmp * 0.125);
720       }
721    }
722    else if ((datatype == DTYPE_USHORT_5_6_5) && (comps == 3)) {
723       DECLARE_ROW_POINTERS0(ushort);
724
725       for (i = j = 0, k = k0; i < (uint) dstWidth;
726            i++, j += colStride, k += colStride) {
727          const int rowAr0 = rowA[j] & 0x1f;
728          const int rowAr1 = rowA[k] & 0x1f;
729          const int rowBr0 = rowB[j] & 0x1f;
730          const int rowBr1 = rowB[k] & 0x1f;
731          const int rowCr0 = rowC[j] & 0x1f;
732          const int rowCr1 = rowC[k] & 0x1f;
733          const int rowDr0 = rowD[j] & 0x1f;
734          const int rowDr1 = rowD[k] & 0x1f;
735          const int rowAg0 = (rowA[j] >> 5) & 0x3f;
736          const int rowAg1 = (rowA[k] >> 5) & 0x3f;
737          const int rowBg0 = (rowB[j] >> 5) & 0x3f;
738          const int rowBg1 = (rowB[k] >> 5) & 0x3f;
739          const int rowCg0 = (rowC[j] >> 5) & 0x3f;
740          const int rowCg1 = (rowC[k] >> 5) & 0x3f;
741          const int rowDg0 = (rowD[j] >> 5) & 0x3f;
742          const int rowDg1 = (rowD[k] >> 5) & 0x3f;
743          const int rowAb0 = (rowA[j] >> 11) & 0x1f;
744          const int rowAb1 = (rowA[k] >> 11) & 0x1f;
745          const int rowBb0 = (rowB[j] >> 11) & 0x1f;
746          const int rowBb1 = (rowB[k] >> 11) & 0x1f;
747          const int rowCb0 = (rowC[j] >> 11) & 0x1f;
748          const int rowCb1 = (rowC[k] >> 11) & 0x1f;
749          const int rowDb0 = (rowD[j] >> 11) & 0x1f;
750          const int rowDb1 = (rowD[k] >> 11) & 0x1f;
751          const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
752                                        rowCr0, rowCr1, rowDr0, rowDr1);
753          const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
754                                        rowCg0, rowCg1, rowDg0, rowDg1);
755          const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
756                                        rowCb0, rowCb1, rowDb0, rowDb1);
757          dst[i] = (b << 11) | (g << 5) | r;
758       }
759    }
760    else if ((datatype == DTYPE_USHORT_4_4_4_4) && (comps == 4)) {
761       DECLARE_ROW_POINTERS0(ushort);
762
763       for (i = j = 0, k = k0; i < (uint) dstWidth;
764            i++, j += colStride, k += colStride) {
765          const int rowAr0 = rowA[j] & 0xf;
766          const int rowAr1 = rowA[k] & 0xf;
767          const int rowBr0 = rowB[j] & 0xf;
768          const int rowBr1 = rowB[k] & 0xf;
769          const int rowCr0 = rowC[j] & 0xf;
770          const int rowCr1 = rowC[k] & 0xf;
771          const int rowDr0 = rowD[j] & 0xf;
772          const int rowDr1 = rowD[k] & 0xf;
773          const int rowAg0 = (rowA[j] >> 4) & 0xf;
774          const int rowAg1 = (rowA[k] >> 4) & 0xf;
775          const int rowBg0 = (rowB[j] >> 4) & 0xf;
776          const int rowBg1 = (rowB[k] >> 4) & 0xf;
777          const int rowCg0 = (rowC[j] >> 4) & 0xf;
778          const int rowCg1 = (rowC[k] >> 4) & 0xf;
779          const int rowDg0 = (rowD[j] >> 4) & 0xf;
780          const int rowDg1 = (rowD[k] >> 4) & 0xf;
781          const int rowAb0 = (rowA[j] >> 8) & 0xf;
782          const int rowAb1 = (rowA[k] >> 8) & 0xf;
783          const int rowBb0 = (rowB[j] >> 8) & 0xf;
784          const int rowBb1 = (rowB[k] >> 8) & 0xf;
785          const int rowCb0 = (rowC[j] >> 8) & 0xf;
786          const int rowCb1 = (rowC[k] >> 8) & 0xf;
787          const int rowDb0 = (rowD[j] >> 8) & 0xf;
788          const int rowDb1 = (rowD[k] >> 8) & 0xf;
789          const int rowAa0 = (rowA[j] >> 12) & 0xf;
790          const int rowAa1 = (rowA[k] >> 12) & 0xf;
791          const int rowBa0 = (rowB[j] >> 12) & 0xf;
792          const int rowBa1 = (rowB[k] >> 12) & 0xf;
793          const int rowCa0 = (rowC[j] >> 12) & 0xf;
794          const int rowCa1 = (rowC[k] >> 12) & 0xf;
795          const int rowDa0 = (rowD[j] >> 12) & 0xf;
796          const int rowDa1 = (rowD[k] >> 12) & 0xf;
797          const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
798                                        rowCr0, rowCr1, rowDr0, rowDr1);
799          const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
800                                        rowCg0, rowCg1, rowDg0, rowDg1);
801          const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
802                                        rowCb0, rowCb1, rowDb0, rowDb1);
803          const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
804                                        rowCa0, rowCa1, rowDa0, rowDa1);
805
806          dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
807       }
808    }
809    else if ((datatype == DTYPE_USHORT_1_5_5_5_REV) && (comps == 4)) {
810       DECLARE_ROW_POINTERS0(ushort);
811
812       for (i = j = 0, k = k0; i < (uint) dstWidth;
813            i++, j += colStride, k += colStride) {
814          const int rowAr0 = rowA[j] & 0x1f;
815          const int rowAr1 = rowA[k] & 0x1f;
816          const int rowBr0 = rowB[j] & 0x1f;
817          const int rowBr1 = rowB[k] & 0x1f;
818          const int rowCr0 = rowC[j] & 0x1f;
819          const int rowCr1 = rowC[k] & 0x1f;
820          const int rowDr0 = rowD[j] & 0x1f;
821          const int rowDr1 = rowD[k] & 0x1f;
822          const int rowAg0 = (rowA[j] >> 5) & 0x1f;
823          const int rowAg1 = (rowA[k] >> 5) & 0x1f;
824          const int rowBg0 = (rowB[j] >> 5) & 0x1f;
825          const int rowBg1 = (rowB[k] >> 5) & 0x1f;
826          const int rowCg0 = (rowC[j] >> 5) & 0x1f;
827          const int rowCg1 = (rowC[k] >> 5) & 0x1f;
828          const int rowDg0 = (rowD[j] >> 5) & 0x1f;
829          const int rowDg1 = (rowD[k] >> 5) & 0x1f;
830          const int rowAb0 = (rowA[j] >> 10) & 0x1f;
831          const int rowAb1 = (rowA[k] >> 10) & 0x1f;
832          const int rowBb0 = (rowB[j] >> 10) & 0x1f;
833          const int rowBb1 = (rowB[k] >> 10) & 0x1f;
834          const int rowCb0 = (rowC[j] >> 10) & 0x1f;
835          const int rowCb1 = (rowC[k] >> 10) & 0x1f;
836          const int rowDb0 = (rowD[j] >> 10) & 0x1f;
837          const int rowDb1 = (rowD[k] >> 10) & 0x1f;
838          const int rowAa0 = (rowA[j] >> 15) & 0x1;
839          const int rowAa1 = (rowA[k] >> 15) & 0x1;
840          const int rowBa0 = (rowB[j] >> 15) & 0x1;
841          const int rowBa1 = (rowB[k] >> 15) & 0x1;
842          const int rowCa0 = (rowC[j] >> 15) & 0x1;
843          const int rowCa1 = (rowC[k] >> 15) & 0x1;
844          const int rowDa0 = (rowD[j] >> 15) & 0x1;
845          const int rowDa1 = (rowD[k] >> 15) & 0x1;
846          const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
847                                        rowCr0, rowCr1, rowDr0, rowDr1);
848          const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
849                                        rowCg0, rowCg1, rowDg0, rowDg1);
850          const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
851                                        rowCb0, rowCb1, rowDb0, rowDb1);
852          const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
853                                        rowCa0, rowCa1, rowDa0, rowDa1);
854
855          dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
856       }
857    }
858    else if ((datatype == DTYPE_UBYTE_3_3_2) && (comps == 3)) {
859       DECLARE_ROW_POINTERS0(ushort);
860
861       for (i = j = 0, k = k0; i < (uint) dstWidth;
862            i++, j += colStride, k += colStride) {
863          const int rowAr0 = rowA[j] & 0x3;
864          const int rowAr1 = rowA[k] & 0x3;
865          const int rowBr0 = rowB[j] & 0x3;
866          const int rowBr1 = rowB[k] & 0x3;
867          const int rowCr0 = rowC[j] & 0x3;
868          const int rowCr1 = rowC[k] & 0x3;
869          const int rowDr0 = rowD[j] & 0x3;
870          const int rowDr1 = rowD[k] & 0x3;
871          const int rowAg0 = (rowA[j] >> 2) & 0x7;
872          const int rowAg1 = (rowA[k] >> 2) & 0x7;
873          const int rowBg0 = (rowB[j] >> 2) & 0x7;
874          const int rowBg1 = (rowB[k] >> 2) & 0x7;
875          const int rowCg0 = (rowC[j] >> 2) & 0x7;
876          const int rowCg1 = (rowC[k] >> 2) & 0x7;
877          const int rowDg0 = (rowD[j] >> 2) & 0x7;
878          const int rowDg1 = (rowD[k] >> 2) & 0x7;
879          const int rowAb0 = (rowA[j] >> 5) & 0x7;
880          const int rowAb1 = (rowA[k] >> 5) & 0x7;
881          const int rowBb0 = (rowB[j] >> 5) & 0x7;
882          const int rowBb1 = (rowB[k] >> 5) & 0x7;
883          const int rowCb0 = (rowC[j] >> 5) & 0x7;
884          const int rowCb1 = (rowC[k] >> 5) & 0x7;
885          const int rowDb0 = (rowD[j] >> 5) & 0x7;
886          const int rowDb1 = (rowD[k] >> 5) & 0x7;
887          const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
888                                        rowCr0, rowCr1, rowDr0, rowDr1);
889          const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
890                                        rowCg0, rowCg1, rowDg0, rowDg1);
891          const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
892                                        rowCb0, rowCb1, rowDb0, rowDb1);
893          dst[i] = (b << 5) | (g << 2) | r;
894       }
895    }
896    else {
897       debug_printf("bad format in do_row_3D()");
898    }
899 }
900
901
902
903 static void
904 format_to_type_comps(enum pipe_format pformat,
905                      enum dtype *datatype, uint *comps)
906 {
907    /* XXX I think this could be implemented in terms of the pf_*() functions */
908    switch (pformat) {
909    case PIPE_FORMAT_B8G8R8A8_UNORM:
910    case PIPE_FORMAT_B8G8R8X8_UNORM:
911    case PIPE_FORMAT_A8R8G8B8_UNORM:
912    case PIPE_FORMAT_X8R8G8B8_UNORM:
913    case PIPE_FORMAT_A8B8G8R8_SRGB:
914    case PIPE_FORMAT_X8B8G8R8_SRGB:
915    case PIPE_FORMAT_B8G8R8A8_SRGB:
916    case PIPE_FORMAT_B8G8R8X8_SRGB:
917    case PIPE_FORMAT_A8R8G8B8_SRGB:
918    case PIPE_FORMAT_X8R8G8B8_SRGB:
919    case PIPE_FORMAT_R8G8B8_SRGB:
920       *datatype = DTYPE_UBYTE;
921       *comps = 4;
922       return;
923    case PIPE_FORMAT_B5G5R5X1_UNORM:
924    case PIPE_FORMAT_B5G5R5A1_UNORM:
925       *datatype = DTYPE_USHORT_1_5_5_5_REV;
926       *comps = 4;
927       return;
928    case PIPE_FORMAT_B4G4R4A4_UNORM:
929       *datatype = DTYPE_USHORT_4_4_4_4;
930       *comps = 4;
931       return;
932    case PIPE_FORMAT_B5G6R5_UNORM:
933       *datatype = DTYPE_USHORT_5_6_5;
934       *comps = 3;
935       return;
936    case PIPE_FORMAT_L8_UNORM:
937    case PIPE_FORMAT_L8_SRGB:
938    case PIPE_FORMAT_A8_UNORM:
939    case PIPE_FORMAT_I8_UNORM:
940       *datatype = DTYPE_UBYTE;
941       *comps = 1;
942       return;
943    case PIPE_FORMAT_L8A8_UNORM:
944    case PIPE_FORMAT_L8A8_SRGB:
945       *datatype = DTYPE_UBYTE;
946       *comps = 2;
947       return;
948    default:
949       assert(0);
950       *datatype = DTYPE_UBYTE;
951       *comps = 0;
952       break;
953    }
954 }
955
956
957 static void
958 reduce_1d(enum pipe_format pformat,
959           int srcWidth, const ubyte *srcPtr,
960           int dstWidth, ubyte *dstPtr)
961 {
962    enum dtype datatype;
963    uint comps;
964
965    format_to_type_comps(pformat, &datatype, &comps);
966
967    /* we just duplicate the input row, kind of hack, saves code */
968    do_row(datatype, comps,
969           srcWidth, srcPtr, srcPtr,
970           dstWidth, dstPtr);
971 }
972
973
974 /**
975  * Strides are in bytes.  If zero, it'll be computed as width * bpp.
976  */
977 static void
978 reduce_2d(enum pipe_format pformat,
979           int srcWidth, int srcHeight,
980           int srcRowStride, const ubyte *srcPtr,
981           int dstWidth, int dstHeight,
982           int dstRowStride, ubyte *dstPtr)
983 {
984    enum dtype datatype;
985    uint comps;
986    const int bpt = util_format_get_blocksize(pformat);
987    const ubyte *srcA, *srcB;
988    ubyte *dst;
989    int row;
990
991    format_to_type_comps(pformat, &datatype, &comps);
992
993    if (!srcRowStride)
994       srcRowStride = bpt * srcWidth;
995
996    if (!dstRowStride)
997       dstRowStride = bpt * dstWidth;
998
999    /* Compute src and dst pointers */
1000    srcA = srcPtr;
1001    if (srcHeight > 1) 
1002       srcB = srcA + srcRowStride;
1003    else
1004       srcB = srcA;
1005    dst = dstPtr;
1006
1007    for (row = 0; row < dstHeight; row++) {
1008       do_row(datatype, comps,
1009              srcWidth, srcA, srcB,
1010              dstWidth, dst);
1011       srcA += 2 * srcRowStride;
1012       srcB += 2 * srcRowStride;
1013       dst += dstRowStride;
1014    }
1015 }
1016
1017
1018 static void
1019 reduce_3d(enum pipe_format pformat,
1020           int srcWidth, int srcHeight, int srcDepth,
1021           int srcRowStride, int srcImageStride, const ubyte *srcPtr,
1022           int dstWidth, int dstHeight, int dstDepth,
1023           int dstRowStride, int dstImageStride, ubyte *dstPtr)
1024 {
1025    const int bpt = util_format_get_blocksize(pformat);
1026    int img, row;
1027    int srcImageOffset, srcRowOffset;
1028    enum dtype datatype;
1029    uint comps;
1030
1031    format_to_type_comps(pformat, &datatype, &comps);
1032
1033    /* XXX I think we should rather assert those strides */
1034    if (!srcImageStride)
1035       srcImageStride = srcWidth * srcHeight * bpt;
1036    if (!dstImageStride)
1037       dstImageStride = dstWidth * dstHeight * bpt;
1038
1039    if (!srcRowStride)
1040       srcRowStride = srcWidth * bpt;
1041    if (!dstRowStride)
1042       dstRowStride = dstWidth * bpt;
1043
1044    /* Offset between adjacent src images to be averaged together */
1045    srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride;
1046
1047    /* Offset between adjacent src rows to be averaged together */
1048    srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
1049
1050    /*
1051     * Need to average together up to 8 src pixels for each dest pixel.
1052     * Break that down into 3 operations:
1053     *   1. take two rows from source image and average them together.
1054     *   2. take two rows from next source image and average them together.
1055     *   3. take the two averaged rows and average them for the final dst row.
1056     */
1057
1058    /*
1059    printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
1060           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1061    */
1062
1063    for (img = 0; img < dstDepth; img++) {
1064       /* first source image pointer */
1065       const ubyte *imgSrcA = srcPtr
1066          + img * (srcImageStride + srcImageOffset);
1067       /* second source image pointer */
1068       const ubyte *imgSrcB = imgSrcA + srcImageOffset;
1069       /* address of the dest image */
1070       ubyte *imgDst = dstPtr + img * dstImageStride;
1071
1072       /* setup the four source row pointers and the dest row pointer */
1073       const ubyte *srcImgARowA = imgSrcA;
1074       const ubyte *srcImgARowB = imgSrcA + srcRowOffset;
1075       const ubyte *srcImgBRowA = imgSrcB;
1076       const ubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1077       ubyte *dstImgRow = imgDst;
1078
1079       for (row = 0; row < dstHeight; row++) {
1080          do_row_3D(datatype, comps, srcWidth, 
1081                    srcImgARowA, srcImgARowB,
1082                    srcImgBRowA, srcImgBRowB,
1083                    dstWidth, dstImgRow);
1084
1085          /* advance to next rows */
1086          srcImgARowA += srcRowStride + srcRowOffset;
1087          srcImgARowB += srcRowStride + srcRowOffset;
1088          srcImgBRowA += srcRowStride + srcRowOffset;
1089          srcImgBRowB += srcRowStride + srcRowOffset;
1090          dstImgRow += dstImageStride;
1091       }
1092    }
1093 }
1094
1095
1096
1097
1098 static void
1099 make_1d_mipmap(struct gen_mipmap_state *ctx,
1100                struct pipe_resource *pt,
1101                uint layer, uint baseLevel, uint lastLevel)
1102 {
1103    struct pipe_context *pipe = ctx->pipe;
1104    uint dstLevel;
1105
1106    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1107       const uint srcLevel = dstLevel - 1;
1108       struct pipe_transfer *srcTrans, *dstTrans;
1109       void *srcMap, *dstMap;
1110
1111       srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
1112                                    PIPE_TRANSFER_READ, 0, 0,
1113                                    u_minify(pt->width0, srcLevel),
1114                                    u_minify(pt->height0, srcLevel));
1115       dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
1116                                    PIPE_TRANSFER_WRITE, 0, 0,
1117                                    u_minify(pt->width0, dstLevel),
1118                                    u_minify(pt->height0, dstLevel));
1119
1120       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
1121       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
1122
1123       reduce_1d(pt->format,
1124                 srcTrans->box.width, srcMap,
1125                 dstTrans->box.width, dstMap);
1126
1127       pipe->transfer_unmap(pipe, srcTrans);
1128       pipe->transfer_unmap(pipe, dstTrans);
1129
1130       pipe->transfer_destroy(pipe, srcTrans);
1131       pipe->transfer_destroy(pipe, dstTrans);
1132    }
1133 }
1134
1135
1136 static void
1137 make_2d_mipmap(struct gen_mipmap_state *ctx,
1138                struct pipe_resource *pt,
1139                uint layer, uint baseLevel, uint lastLevel)
1140 {
1141    struct pipe_context *pipe = ctx->pipe;
1142    uint dstLevel;
1143
1144    assert(util_format_get_blockwidth(pt->format) == 1);
1145    assert(util_format_get_blockheight(pt->format) == 1);
1146
1147    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1148       const uint srcLevel = dstLevel - 1;
1149       struct pipe_transfer *srcTrans, *dstTrans;
1150       ubyte *srcMap, *dstMap;
1151
1152       srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
1153                                    PIPE_TRANSFER_READ, 0, 0,
1154                                    u_minify(pt->width0, srcLevel),
1155                                    u_minify(pt->height0, srcLevel));
1156       dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
1157                                    PIPE_TRANSFER_WRITE, 0, 0,
1158                                    u_minify(pt->width0, dstLevel),
1159                                    u_minify(pt->height0, dstLevel));
1160
1161       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
1162       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
1163
1164       reduce_2d(pt->format,
1165                 srcTrans->box.width, srcTrans->box.height,
1166                 srcTrans->stride, srcMap,
1167                 dstTrans->box.width, dstTrans->box.height,
1168                 dstTrans->stride, dstMap);
1169
1170       pipe->transfer_unmap(pipe, srcTrans);
1171       pipe->transfer_unmap(pipe, dstTrans);
1172
1173       pipe->transfer_destroy(pipe, srcTrans);
1174       pipe->transfer_destroy(pipe, dstTrans);
1175    }
1176 }
1177
1178
1179 /* XXX looks a bit more like it could work now but need to test */
1180 static void
1181 make_3d_mipmap(struct gen_mipmap_state *ctx,
1182                struct pipe_resource *pt,
1183                uint face, uint baseLevel, uint lastLevel)
1184 {
1185    struct pipe_context *pipe = ctx->pipe;
1186    uint dstLevel;
1187    struct pipe_box src_box, dst_box;
1188
1189    assert(util_format_get_blockwidth(pt->format) == 1);
1190    assert(util_format_get_blockheight(pt->format) == 1);
1191
1192    src_box.x = src_box.y = src_box.z = 0;
1193    dst_box.x = dst_box.y = dst_box.z = 0;
1194
1195    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1196       const uint srcLevel = dstLevel - 1;
1197       struct pipe_transfer *srcTrans, *dstTrans;
1198       ubyte *srcMap, *dstMap;
1199       struct pipe_box src_box, dst_box;
1200       src_box.width = u_minify(pt->width0, srcLevel);
1201       src_box.height = u_minify(pt->height0, srcLevel);
1202       src_box.depth = u_minify(pt->depth0, srcLevel);
1203       dst_box.width = u_minify(pt->width0, dstLevel);
1204       dst_box.height = u_minify(pt->height0, dstLevel);
1205       dst_box.depth = u_minify(pt->depth0, dstLevel);
1206
1207       srcTrans = pipe->get_transfer(pipe, pt, srcLevel,
1208                                     PIPE_TRANSFER_READ,
1209                                     &src_box);
1210       dstTrans = pipe->get_transfer(pipe, pt, dstLevel,
1211                                     PIPE_TRANSFER_WRITE,
1212                                     &dst_box);
1213
1214       srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
1215       dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
1216
1217       reduce_3d(pt->format,
1218                 srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth,
1219                 srcTrans->stride, srcTrans->layer_stride, srcMap,
1220                 dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth,
1221                 dstTrans->stride, dstTrans->layer_stride, dstMap);
1222
1223       pipe->transfer_unmap(pipe, srcTrans);
1224       pipe->transfer_unmap(pipe, dstTrans);
1225
1226       pipe->transfer_destroy(pipe, srcTrans);
1227       pipe->transfer_destroy(pipe, dstTrans);
1228    }
1229 }
1230
1231
1232 static void
1233 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
1234                     struct pipe_resource *pt,
1235                     uint layer, uint baseLevel, uint lastLevel)
1236 {
1237    switch (pt->target) {
1238    case PIPE_TEXTURE_1D:
1239       make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
1240       break;
1241    case PIPE_TEXTURE_2D:
1242    case PIPE_TEXTURE_RECT:
1243    case PIPE_TEXTURE_CUBE:
1244       make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
1245       break;
1246    case PIPE_TEXTURE_3D:
1247       make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
1248       break;
1249    default:
1250       assert(0);
1251    }
1252 }
1253
1254
1255 /**
1256  * Create a mipmap generation context.
1257  * The idea is to create one of these and re-use it each time we need to
1258  * generate a mipmap.
1259  */
1260 struct gen_mipmap_state *
1261 util_create_gen_mipmap(struct pipe_context *pipe,
1262                        struct cso_context *cso)
1263 {
1264    struct gen_mipmap_state *ctx;
1265    uint i;
1266
1267    ctx = CALLOC_STRUCT(gen_mipmap_state);
1268    if (!ctx)
1269       return NULL;
1270
1271    ctx->pipe = pipe;
1272    ctx->cso = cso;
1273
1274    /* disabled blending/masking */
1275    memset(&ctx->blend, 0, sizeof(ctx->blend));
1276    ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
1277
1278    /* no-op depth/stencil/alpha */
1279    memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
1280
1281    /* rasterizer */
1282    memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
1283    ctx->rasterizer.cull_face = PIPE_FACE_NONE;
1284    ctx->rasterizer.gl_rasterization_rules = 1;
1285    ctx->rasterizer.depth_clip = 1;
1286
1287    /* sampler state */
1288    memset(&ctx->sampler, 0, sizeof(ctx->sampler));
1289    ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1290    ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1291    ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
1292    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
1293    ctx->sampler.normalized_coords = 1;
1294
1295    /* vertex elements state */
1296    memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
1297    for (i = 0; i < 2; i++) {
1298       ctx->velem[i].src_offset = i * 4 * sizeof(float);
1299       ctx->velem[i].instance_divisor = 0;
1300       ctx->velem[i].vertex_buffer_index = 0;
1301       ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
1302    }
1303
1304    /* vertex data that doesn't change */
1305    for (i = 0; i < 4; i++) {
1306       ctx->vertices[i][0][2] = 0.0f; /* z */
1307       ctx->vertices[i][0][3] = 1.0f; /* w */
1308       ctx->vertices[i][1][3] = 1.0f; /* q */
1309    }
1310
1311    /* Note: the actual vertex buffer is allocated as needed below */
1312
1313    return ctx;
1314 }
1315
1316
1317 /**
1318  * Helper function to set the fragment shaders.
1319  */
1320 static INLINE void
1321 set_fragment_shader(struct gen_mipmap_state *ctx, uint type)
1322 {
1323    if (!ctx->fs[type])
1324       ctx->fs[type] =
1325          util_make_fragment_tex_shader(ctx->pipe, type,
1326                                        TGSI_INTERPOLATE_LINEAR);
1327
1328    cso_set_fragment_shader_handle(ctx->cso, ctx->fs[type]);
1329 }
1330
1331
1332 /**
1333  * Helper function to set the vertex shader.
1334  */
1335 static INLINE void
1336 set_vertex_shader(struct gen_mipmap_state *ctx)
1337 {
1338    /* vertex shader - still required to provide the linkage between
1339     * fragment shader input semantics and vertex_element/buffers.
1340     */
1341    if (!ctx->vs)
1342    {
1343       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
1344                                       TGSI_SEMANTIC_GENERIC };
1345       const uint semantic_indexes[] = { 0, 0 };
1346       ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
1347                                                     semantic_names,
1348                                                     semantic_indexes);
1349    }
1350
1351    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
1352 }
1353
1354
1355 /**
1356  * Get next "slot" of vertex space in the vertex buffer.
1357  * We're allocating one large vertex buffer and using it piece by piece.
1358  */
1359 static unsigned
1360 get_next_slot(struct gen_mipmap_state *ctx)
1361 {
1362    const unsigned max_slots = 4096 / sizeof ctx->vertices;
1363
1364    if (ctx->vbuf_slot >= max_slots) 
1365       util_gen_mipmap_flush( ctx );
1366
1367    if (!ctx->vbuf) {
1368       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
1369                                      PIPE_BIND_VERTEX_BUFFER,
1370                                      PIPE_USAGE_STREAM,
1371                                      max_slots * sizeof ctx->vertices);
1372    }
1373    
1374    return ctx->vbuf_slot++ * sizeof ctx->vertices;
1375 }
1376
1377
1378 static unsigned
1379 set_vertex_data(struct gen_mipmap_state *ctx,
1380                 enum pipe_texture_target tex_target,
1381                 uint layer, float r)
1382 {
1383    unsigned offset;
1384
1385    /* vert[0].position */
1386    ctx->vertices[0][0][0] = -1.0f; /*x*/
1387    ctx->vertices[0][0][1] = -1.0f; /*y*/
1388
1389    /* vert[1].position */
1390    ctx->vertices[1][0][0] = 1.0f;
1391    ctx->vertices[1][0][1] = -1.0f;
1392
1393    /* vert[2].position */
1394    ctx->vertices[2][0][0] = 1.0f;
1395    ctx->vertices[2][0][1] = 1.0f;
1396
1397    /* vert[3].position */
1398    ctx->vertices[3][0][0] = -1.0f;
1399    ctx->vertices[3][0][1] = 1.0f;
1400
1401    /* Setup vertex texcoords.  This is a little tricky for cube maps. */
1402    if (tex_target == PIPE_TEXTURE_CUBE) {
1403       static const float st[4][2] = {
1404          {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
1405       };
1406
1407       util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
1408                                         &ctx->vertices[0][1][0], 8);
1409    }
1410    else if (tex_target == PIPE_TEXTURE_1D_ARRAY) {
1411       /* 1D texture array  */
1412       ctx->vertices[0][1][0] = 0.0f; /*s*/
1413       ctx->vertices[0][1][1] = r; /*t*/
1414       ctx->vertices[0][1][2] = 0.0f;    /*r*/
1415
1416       ctx->vertices[1][1][0] = 1.0f;
1417       ctx->vertices[1][1][1] = r;
1418       ctx->vertices[1][1][2] = 0.0f;
1419
1420       ctx->vertices[2][1][0] = 1.0f;
1421       ctx->vertices[2][1][1] = r;
1422       ctx->vertices[2][1][2] = 0.0f;
1423
1424       ctx->vertices[3][1][0] = 0.0f;
1425       ctx->vertices[3][1][1] = r;
1426       ctx->vertices[3][1][2] = 0.0f;
1427    } else {
1428       /* 1D/2D/3D/2D array */
1429       ctx->vertices[0][1][0] = 0.0f; /*s*/
1430       ctx->vertices[0][1][1] = 0.0f; /*t*/
1431       ctx->vertices[0][1][2] = r;    /*r*/
1432
1433       ctx->vertices[1][1][0] = 1.0f;
1434       ctx->vertices[1][1][1] = 0.0f;
1435       ctx->vertices[1][1][2] = r;
1436
1437       ctx->vertices[2][1][0] = 1.0f;
1438       ctx->vertices[2][1][1] = 1.0f;
1439       ctx->vertices[2][1][2] = r;
1440
1441       ctx->vertices[3][1][0] = 0.0f;
1442       ctx->vertices[3][1][1] = 1.0f;
1443       ctx->vertices[3][1][2] = r;
1444    }
1445
1446    offset = get_next_slot( ctx );
1447
1448    pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
1449                                offset, sizeof(ctx->vertices), ctx->vertices);
1450
1451    return offset;
1452 }
1453
1454
1455
1456 /**
1457  * Destroy a mipmap generation context
1458  */
1459 void
1460 util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
1461 {
1462    struct pipe_context *pipe = ctx->pipe;
1463    unsigned i;
1464
1465    for (i = 0; i < Elements(ctx->fs); i++)
1466       if (ctx->fs[i])
1467          pipe->delete_fs_state(pipe, ctx->fs[i]);
1468
1469    if (ctx->vs)
1470       pipe->delete_vs_state(pipe, ctx->vs);
1471
1472    pipe_resource_reference(&ctx->vbuf, NULL);
1473
1474    FREE(ctx);
1475 }
1476
1477
1478
1479 /* Release vertex buffer at end of frame to avoid synchronous
1480  * rendering.
1481  */
1482 void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
1483 {
1484    pipe_resource_reference(&ctx->vbuf, NULL);
1485    ctx->vbuf_slot = 0;
1486
1487
1488
1489 /**
1490  * Generate mipmap images.  It's assumed all needed texture memory is
1491  * already allocated.
1492  *
1493  * \param psv  the sampler view to the texture to generate mipmap levels for
1494  * \param face  which cube face to generate mipmaps for (0 for non-cube maps)
1495  * \param baseLevel  the first mipmap level to use as a src
1496  * \param lastLevel  the last mipmap level to generate
1497  * \param filter  the minification filter used to generate mipmap levels with
1498  * \param filter  one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
1499  */
1500 void
1501 util_gen_mipmap(struct gen_mipmap_state *ctx,
1502                 struct pipe_sampler_view *psv,
1503                 uint face, uint baseLevel, uint lastLevel, uint filter)
1504 {
1505    struct pipe_context *pipe = ctx->pipe;
1506    struct pipe_screen *screen = pipe->screen;
1507    struct pipe_framebuffer_state fb;
1508    struct pipe_resource *pt = psv->texture;
1509    uint dstLevel;
1510    uint offset;
1511    uint type;
1512
1513    /* The texture object should have room for the levels which we're
1514     * about to generate.
1515     */
1516    assert(lastLevel <= pt->last_level);
1517
1518    /* If this fails, why are we here? */
1519    assert(lastLevel > baseLevel);
1520
1521    assert(filter == PIPE_TEX_FILTER_LINEAR ||
1522           filter == PIPE_TEX_FILTER_NEAREST);
1523
1524    switch (pt->target) {
1525    case PIPE_TEXTURE_1D:
1526       type = TGSI_TEXTURE_1D;
1527       break;
1528    case PIPE_TEXTURE_2D:
1529       type = TGSI_TEXTURE_2D;
1530       break;
1531    case PIPE_TEXTURE_3D:
1532       type = TGSI_TEXTURE_3D;
1533       break;
1534    case PIPE_TEXTURE_CUBE:
1535       type = TGSI_TEXTURE_CUBE;
1536       break;
1537    case PIPE_TEXTURE_1D_ARRAY:
1538       type = TGSI_TEXTURE_1D_ARRAY;
1539       break;
1540    case PIPE_TEXTURE_2D_ARRAY:
1541       type = TGSI_TEXTURE_2D_ARRAY;
1542       break;
1543    default:
1544       assert(0);
1545       type = TGSI_TEXTURE_2D;
1546    }
1547
1548    /* check if we can render in the texture's format */
1549    if (!screen->is_format_supported(screen, psv->format, pt->target,
1550                                     pt->nr_samples, PIPE_BIND_RENDER_TARGET)) {
1551       fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
1552       return;
1553    }
1554
1555    /* save state (restored below) */
1556    cso_save_blend(ctx->cso);
1557    cso_save_depth_stencil_alpha(ctx->cso);
1558    cso_save_rasterizer(ctx->cso);
1559    cso_save_samplers(ctx->cso);
1560    cso_save_fragment_sampler_views(ctx->cso);
1561    cso_save_stream_outputs(ctx->cso);
1562    cso_save_framebuffer(ctx->cso);
1563    cso_save_fragment_shader(ctx->cso);
1564    cso_save_vertex_shader(ctx->cso);
1565    cso_save_geometry_shader(ctx->cso);
1566    cso_save_viewport(ctx->cso);
1567    cso_save_vertex_elements(ctx->cso);
1568
1569    /* bind our state */
1570    cso_set_blend(ctx->cso, &ctx->blend);
1571    cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
1572    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
1573    cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
1574    cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
1575
1576    set_fragment_shader(ctx, type);
1577    set_vertex_shader(ctx);
1578    cso_set_geometry_shader_handle(ctx->cso, NULL);
1579
1580    /* init framebuffer state */
1581    memset(&fb, 0, sizeof(fb));
1582    fb.nr_cbufs = 1;
1583
1584    /* set min/mag to same filter for faster sw speed */
1585    ctx->sampler.mag_img_filter = filter;
1586    ctx->sampler.min_img_filter = filter;
1587
1588    /*
1589     * XXX for small mipmap levels, it may be faster to use the software
1590     * fallback path...
1591     */
1592    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
1593       const uint srcLevel = dstLevel - 1;
1594       struct pipe_viewport_state vp;
1595       unsigned nr_layers, layer, i;
1596       float rcoord = 0.0f;
1597
1598       if (pt->target == PIPE_TEXTURE_3D)
1599          nr_layers = u_minify(pt->depth0, dstLevel);
1600       else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY)
1601          nr_layers = pt->array_size;
1602       else
1603          nr_layers = 1;
1604
1605       for (i = 0; i < nr_layers; i++) {
1606          struct pipe_surface *surf, surf_templ;
1607          if (pt->target == PIPE_TEXTURE_3D) {
1608             /* in theory with geom shaders and driver with full layer support
1609                could do that in one go. */
1610             layer = i;
1611             /* XXX hmm really? */
1612             rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
1613          } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) {
1614             layer = i;
1615             rcoord = (float)layer;
1616          } else
1617             layer = face;
1618
1619          memset(&surf_templ, 0, sizeof(surf_templ));
1620          u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET);
1621          surf_templ.u.tex.level = dstLevel;
1622          surf_templ.u.tex.first_layer = layer;
1623          surf_templ.u.tex.last_layer = layer;
1624          surf = pipe->create_surface(pipe, pt, &surf_templ);
1625
1626          /*
1627           * Setup framebuffer / dest surface
1628           */
1629          fb.cbufs[0] = surf;
1630          fb.width = u_minify(pt->width0, dstLevel);
1631          fb.height = u_minify(pt->height0, dstLevel);
1632          cso_set_framebuffer(ctx->cso, &fb);
1633
1634          /* viewport */
1635          vp.scale[0] = 0.5f * fb.width;
1636          vp.scale[1] = 0.5f * fb.height;
1637          vp.scale[2] = 1.0f;
1638          vp.scale[3] = 1.0f;
1639          vp.translate[0] = 0.5f * fb.width;
1640          vp.translate[1] = 0.5f * fb.height;
1641          vp.translate[2] = 0.0f;
1642          vp.translate[3] = 0.0f;
1643          cso_set_viewport(ctx->cso, &vp);
1644
1645          /*
1646           * Setup sampler state
1647           * Note: we should only have to set the min/max LOD clamps to ensure
1648           * we grab texels from the right mipmap level.  But some hardware
1649           * has trouble with min clamping so we also set the lod_bias to
1650           * try to work around that.
1651           */
1652          ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
1653          ctx->sampler.lod_bias = (float) srcLevel;
1654          cso_single_sampler(ctx->cso, 0, &ctx->sampler);
1655          cso_single_sampler_done(ctx->cso);
1656
1657          cso_set_fragment_sampler_views(ctx->cso, 1, &psv);
1658
1659          /* quad coords in clip coords */
1660          offset = set_vertex_data(ctx,
1661                                   pt->target,
1662                                   face,
1663                                   rcoord);
1664
1665          util_draw_vertex_buffer(ctx->pipe,
1666                                  ctx->cso,
1667                                  ctx->vbuf,
1668                                  offset,
1669                                  PIPE_PRIM_TRIANGLE_FAN,
1670                                  4,  /* verts */
1671                                  2); /* attribs/vert */
1672
1673          /* need to signal that the texture has changed _after_ rendering to it */
1674          pipe_surface_reference( &surf, NULL );
1675       }
1676    }
1677
1678    /* restore state we changed */
1679    cso_restore_blend(ctx->cso);
1680    cso_restore_depth_stencil_alpha(ctx->cso);
1681    cso_restore_rasterizer(ctx->cso);
1682    cso_restore_samplers(ctx->cso);
1683    cso_restore_fragment_sampler_views(ctx->cso);
1684    cso_restore_framebuffer(ctx->cso);
1685    cso_restore_fragment_shader(ctx->cso);
1686    cso_restore_vertex_shader(ctx->cso);
1687    cso_restore_geometry_shader(ctx->cso);
1688    cso_restore_viewport(ctx->cso);
1689    cso_restore_vertex_elements(ctx->cso);
1690    cso_restore_stream_outputs(ctx->cso);
1691 }