1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 * Mipmap generation utility
36 #include "pipe/p_context.h"
37 #include "pipe/p_debug.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_inlines.h"
40 #include "pipe/p_winsys.h"
41 #include "pipe/p_shader_tokens.h"
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"
48 #include "tgsi/tgsi_build.h"
49 #include "tgsi/tgsi_dump.h"
50 #include "tgsi/tgsi_parse.h"
52 #include "cso_cache/cso_context.h"
55 struct gen_mipmap_state
57 struct pipe_context
*pipe
;
58 struct cso_context
*cso
;
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
;
66 struct pipe_shader_state vert_shader
;
67 struct pipe_shader_state frag_shader
;
71 struct pipe_buffer
*vbuf
; /**< quad vertices */
72 float vertices
[4][2][4]; /**< vertex/texcoords for quad */
91 typedef ushort half_float
;
96 float_to_half(float f
);
99 half_to_float(half_float h
);
104 * Average together two rows of a source image to produce a single new
105 * row in the dest image. It's legal for the two source rows to point
106 * to the same data. The source width must be equal to either the
107 * dest width or two times the dest width.
108 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
109 * \param comps number of components per pixel (1..4)
112 do_row(enum dtype datatype
, uint comps
, int srcWidth
,
113 const void *srcRowA
, const void *srcRowB
,
114 int dstWidth
, void *dstRow
)
116 const uint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
117 const uint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
122 /* This assertion is no longer valid with non-power-of-2 textures
123 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
126 if (datatype
== UBYTE
&& comps
== 4) {
128 const ubyte(*rowA
)[4] = (const ubyte(*)[4]) srcRowA
;
129 const ubyte(*rowB
)[4] = (const ubyte(*)[4]) srcRowB
;
130 ubyte(*dst
)[4] = (ubyte(*)[4]) dstRow
;
131 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
132 i
++, j
+= colStride
, k
+= colStride
) {
133 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
134 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
135 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
136 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
139 else if (datatype
== UBYTE
&& comps
== 3) {
141 const ubyte(*rowA
)[3] = (const ubyte(*)[3]) srcRowA
;
142 const ubyte(*rowB
)[3] = (const ubyte(*)[3]) srcRowB
;
143 ubyte(*dst
)[3] = (ubyte(*)[3]) dstRow
;
144 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
145 i
++, j
+= colStride
, k
+= colStride
) {
146 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
147 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
148 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
151 else if (datatype
== UBYTE
&& comps
== 2) {
153 const ubyte(*rowA
)[2] = (const ubyte(*)[2]) srcRowA
;
154 const ubyte(*rowB
)[2] = (const ubyte(*)[2]) srcRowB
;
155 ubyte(*dst
)[2] = (ubyte(*)[2]) dstRow
;
156 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
157 i
++, j
+= colStride
, k
+= colStride
) {
158 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
159 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
162 else if (datatype
== UBYTE
&& comps
== 1) {
164 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
165 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
166 ubyte
*dst
= (ubyte
*) dstRow
;
167 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
168 i
++, j
+= colStride
, k
+= colStride
) {
169 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
173 else if (datatype
== USHORT
&& comps
== 4) {
175 const ushort(*rowA
)[4] = (const ushort(*)[4]) srcRowA
;
176 const ushort(*rowB
)[4] = (const ushort(*)[4]) srcRowB
;
177 ushort(*dst
)[4] = (ushort(*)[4]) dstRow
;
178 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
179 i
++, j
+= colStride
, k
+= colStride
) {
180 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
181 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
182 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
183 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
186 else if (datatype
== USHORT
&& comps
== 3) {
188 const ushort(*rowA
)[3] = (const ushort(*)[3]) srcRowA
;
189 const ushort(*rowB
)[3] = (const ushort(*)[3]) srcRowB
;
190 ushort(*dst
)[3] = (ushort(*)[3]) dstRow
;
191 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
192 i
++, j
+= colStride
, k
+= colStride
) {
193 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
194 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
195 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
198 else if (datatype
== USHORT
&& comps
== 2) {
200 const ushort(*rowA
)[2] = (const ushort(*)[2]) srcRowA
;
201 const ushort(*rowB
)[2] = (const ushort(*)[2]) srcRowB
;
202 ushort(*dst
)[2] = (ushort(*)[2]) dstRow
;
203 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
204 i
++, j
+= colStride
, k
+= colStride
) {
205 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
206 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
209 else if (datatype
== USHORT
&& comps
== 1) {
211 const ushort
*rowA
= (const ushort
*) srcRowA
;
212 const ushort
*rowB
= (const ushort
*) srcRowB
;
213 ushort
*dst
= (ushort
*) dstRow
;
214 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
215 i
++, j
+= colStride
, k
+= colStride
) {
216 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
220 else if (datatype
== FLOAT
&& comps
== 4) {
222 const float(*rowA
)[4] = (const float(*)[4]) srcRowA
;
223 const float(*rowB
)[4] = (const float(*)[4]) srcRowB
;
224 float(*dst
)[4] = (float(*)[4]) dstRow
;
225 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
226 i
++, j
+= colStride
, k
+= colStride
) {
227 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
228 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
229 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
230 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
231 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
232 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
233 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
234 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
237 else if (datatype
== FLOAT
&& comps
== 3) {
239 const float(*rowA
)[3] = (const float(*)[3]) srcRowA
;
240 const float(*rowB
)[3] = (const float(*)[3]) srcRowB
;
241 float(*dst
)[3] = (float(*)[3]) dstRow
;
242 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
243 i
++, j
+= colStride
, k
+= colStride
) {
244 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
245 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
246 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
247 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
248 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
249 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
252 else if (datatype
== FLOAT
&& comps
== 2) {
254 const float(*rowA
)[2] = (const float(*)[2]) srcRowA
;
255 const float(*rowB
)[2] = (const float(*)[2]) srcRowB
;
256 float(*dst
)[2] = (float(*)[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] +
260 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
261 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
262 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
265 else if (datatype
== FLOAT
&& comps
== 1) {
267 const float *rowA
= (const float *) srcRowA
;
268 const float *rowB
= (const float *) srcRowB
;
269 float *dst
= (float *) dstRow
;
270 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
271 i
++, j
+= colStride
, k
+= colStride
) {
272 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
277 else if (datatype
== HALF_FLOAT
&& comps
== 4) {
279 const half_float(*rowA
)[4] = (const half_float(*)[4]) srcRowA
;
280 const half_float(*rowB
)[4] = (const half_float(*)[4]) srcRowB
;
281 half_float(*dst
)[4] = (half_float(*)[4]) dstRow
;
282 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
283 i
++, j
+= colStride
, k
+= colStride
) {
284 for (comp
= 0; comp
< 4; comp
++) {
285 float aj
, ak
, bj
, bk
;
286 aj
= half_to_float(rowA
[j
][comp
]);
287 ak
= half_to_float(rowA
[k
][comp
]);
288 bj
= half_to_float(rowB
[j
][comp
]);
289 bk
= half_to_float(rowB
[k
][comp
]);
290 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
294 else if (datatype
== HALF_FLOAT
&& comps
== 3) {
296 const half_float(*rowA
)[3] = (const half_float(*)[3]) srcRowA
;
297 const half_float(*rowB
)[3] = (const half_float(*)[3]) srcRowB
;
298 half_float(*dst
)[3] = (half_float(*)[3]) dstRow
;
299 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
300 i
++, j
+= colStride
, k
+= colStride
) {
301 for (comp
= 0; comp
< 3; comp
++) {
302 float aj
, ak
, bj
, bk
;
303 aj
= half_to_float(rowA
[j
][comp
]);
304 ak
= half_to_float(rowA
[k
][comp
]);
305 bj
= half_to_float(rowB
[j
][comp
]);
306 bk
= half_to_float(rowB
[k
][comp
]);
307 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
311 else if (datatype
== HALF_FLOAT
&& comps
== 2) {
313 const half_float(*rowA
)[2] = (const half_float(*)[2]) srcRowA
;
314 const half_float(*rowB
)[2] = (const half_float(*)[2]) srcRowB
;
315 half_float(*dst
)[2] = (half_float(*)[2]) dstRow
;
316 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
317 i
++, j
+= colStride
, k
+= colStride
) {
318 for (comp
= 0; comp
< 2; comp
++) {
319 float aj
, ak
, bj
, bk
;
320 aj
= half_to_float(rowA
[j
][comp
]);
321 ak
= half_to_float(rowA
[k
][comp
]);
322 bj
= half_to_float(rowB
[j
][comp
]);
323 bk
= half_to_float(rowB
[k
][comp
]);
324 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
328 else if (datatype
== HALF_FLOAT
&& comps
== 1) {
330 const half_float
*rowA
= (const half_float
*) srcRowA
;
331 const half_float
*rowB
= (const half_float
*) srcRowB
;
332 half_float
*dst
= (half_float
*) dstRow
;
333 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
334 i
++, j
+= colStride
, k
+= colStride
) {
335 float aj
, ak
, bj
, bk
;
336 aj
= half_to_float(rowA
[j
]);
337 ak
= half_to_float(rowA
[k
]);
338 bj
= half_to_float(rowB
[j
]);
339 bk
= half_to_float(rowB
[k
]);
340 dst
[i
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
345 else if (datatype
== UINT
&& comps
== 1) {
347 const uint
*rowA
= (const uint
*) srcRowA
;
348 const uint
*rowB
= (const uint
*) srcRowB
;
349 uint
*dst
= (uint
*) dstRow
;
350 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
351 i
++, j
+= colStride
, k
+= colStride
) {
352 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
356 else if (datatype
== USHORT_5_6_5
&& comps
== 3) {
358 const ushort
*rowA
= (const ushort
*) srcRowA
;
359 const ushort
*rowB
= (const ushort
*) srcRowB
;
360 ushort
*dst
= (ushort
*) dstRow
;
361 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
362 i
++, j
+= colStride
, k
+= colStride
) {
363 const int rowAr0
= rowA
[j
] & 0x1f;
364 const int rowAr1
= rowA
[k
] & 0x1f;
365 const int rowBr0
= rowB
[j
] & 0x1f;
366 const int rowBr1
= rowB
[k
] & 0x1f;
367 const int rowAg0
= (rowA
[j
] >> 5) & 0x3f;
368 const int rowAg1
= (rowA
[k
] >> 5) & 0x3f;
369 const int rowBg0
= (rowB
[j
] >> 5) & 0x3f;
370 const int rowBg1
= (rowB
[k
] >> 5) & 0x3f;
371 const int rowAb0
= (rowA
[j
] >> 11) & 0x1f;
372 const int rowAb1
= (rowA
[k
] >> 11) & 0x1f;
373 const int rowBb0
= (rowB
[j
] >> 11) & 0x1f;
374 const int rowBb1
= (rowB
[k
] >> 11) & 0x1f;
375 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
376 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
377 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
378 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
381 else if (datatype
== USHORT_4_4_4_4
&& comps
== 4) {
383 const ushort
*rowA
= (const ushort
*) srcRowA
;
384 const ushort
*rowB
= (const ushort
*) srcRowB
;
385 ushort
*dst
= (ushort
*) dstRow
;
386 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
387 i
++, j
+= colStride
, k
+= colStride
) {
388 const int rowAr0
= rowA
[j
] & 0xf;
389 const int rowAr1
= rowA
[k
] & 0xf;
390 const int rowBr0
= rowB
[j
] & 0xf;
391 const int rowBr1
= rowB
[k
] & 0xf;
392 const int rowAg0
= (rowA
[j
] >> 4) & 0xf;
393 const int rowAg1
= (rowA
[k
] >> 4) & 0xf;
394 const int rowBg0
= (rowB
[j
] >> 4) & 0xf;
395 const int rowBg1
= (rowB
[k
] >> 4) & 0xf;
396 const int rowAb0
= (rowA
[j
] >> 8) & 0xf;
397 const int rowAb1
= (rowA
[k
] >> 8) & 0xf;
398 const int rowBb0
= (rowB
[j
] >> 8) & 0xf;
399 const int rowBb1
= (rowB
[k
] >> 8) & 0xf;
400 const int rowAa0
= (rowA
[j
] >> 12) & 0xf;
401 const int rowAa1
= (rowA
[k
] >> 12) & 0xf;
402 const int rowBa0
= (rowB
[j
] >> 12) & 0xf;
403 const int rowBa1
= (rowB
[k
] >> 12) & 0xf;
404 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
405 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
406 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
407 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
408 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
411 else if (datatype
== USHORT_1_5_5_5_REV
&& comps
== 4) {
413 const ushort
*rowA
= (const ushort
*) srcRowA
;
414 const ushort
*rowB
= (const ushort
*) srcRowB
;
415 ushort
*dst
= (ushort
*) dstRow
;
416 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
417 i
++, j
+= colStride
, k
+= colStride
) {
418 const int rowAr0
= rowA
[j
] & 0x1f;
419 const int rowAr1
= rowA
[k
] & 0x1f;
420 const int rowBr0
= rowB
[j
] & 0x1f;
421 const int rowBr1
= rowB
[k
] & 0xf;
422 const int rowAg0
= (rowA
[j
] >> 5) & 0x1f;
423 const int rowAg1
= (rowA
[k
] >> 5) & 0x1f;
424 const int rowBg0
= (rowB
[j
] >> 5) & 0x1f;
425 const int rowBg1
= (rowB
[k
] >> 5) & 0x1f;
426 const int rowAb0
= (rowA
[j
] >> 10) & 0x1f;
427 const int rowAb1
= (rowA
[k
] >> 10) & 0x1f;
428 const int rowBb0
= (rowB
[j
] >> 10) & 0x1f;
429 const int rowBb1
= (rowB
[k
] >> 10) & 0x1f;
430 const int rowAa0
= (rowA
[j
] >> 15) & 0x1;
431 const int rowAa1
= (rowA
[k
] >> 15) & 0x1;
432 const int rowBa0
= (rowB
[j
] >> 15) & 0x1;
433 const int rowBa1
= (rowB
[k
] >> 15) & 0x1;
434 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
435 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
436 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
437 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
438 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
441 else if (datatype
== UBYTE_3_3_2
&& comps
== 3) {
443 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
444 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
445 ubyte
*dst
= (ubyte
*) dstRow
;
446 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
447 i
++, j
+= colStride
, k
+= colStride
) {
448 const int rowAr0
= rowA
[j
] & 0x3;
449 const int rowAr1
= rowA
[k
] & 0x3;
450 const int rowBr0
= rowB
[j
] & 0x3;
451 const int rowBr1
= rowB
[k
] & 0x3;
452 const int rowAg0
= (rowA
[j
] >> 2) & 0x7;
453 const int rowAg1
= (rowA
[k
] >> 2) & 0x7;
454 const int rowBg0
= (rowB
[j
] >> 2) & 0x7;
455 const int rowBg1
= (rowB
[k
] >> 2) & 0x7;
456 const int rowAb0
= (rowA
[j
] >> 5) & 0x7;
457 const int rowAb1
= (rowA
[k
] >> 5) & 0x7;
458 const int rowBb0
= (rowB
[j
] >> 5) & 0x7;
459 const int rowBb1
= (rowB
[k
] >> 5) & 0x7;
460 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
461 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
462 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
463 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
467 debug_printf("bad format in do_row()");
473 format_to_type_comps(enum pipe_format pformat
,
474 enum dtype
*datatype
, uint
*comps
)
477 case PIPE_FORMAT_A8R8G8B8_UNORM
:
478 case PIPE_FORMAT_X8R8G8B8_UNORM
:
479 case PIPE_FORMAT_B8G8R8A8_UNORM
:
480 case PIPE_FORMAT_B8G8R8X8_UNORM
:
484 case PIPE_FORMAT_A1R5G5B5_UNORM
:
485 *datatype
= USHORT_1_5_5_5_REV
;
488 case PIPE_FORMAT_A4R4G4B4_UNORM
:
489 *datatype
= USHORT_4_4_4_4
;
492 case PIPE_FORMAT_R5G6B5_UNORM
:
493 *datatype
= USHORT_5_6_5
;
496 case PIPE_FORMAT_L8_UNORM
:
497 case PIPE_FORMAT_A8_UNORM
:
498 case PIPE_FORMAT_I8_UNORM
:
502 case PIPE_FORMAT_A8L8_UNORM
:
516 reduce_1d(enum pipe_format pformat
,
517 int srcWidth
, const ubyte
*srcPtr
,
518 int dstWidth
, ubyte
*dstPtr
)
523 format_to_type_comps(pformat
, &datatype
, &comps
);
525 /* we just duplicate the input row, kind of hack, saves code */
526 do_row(datatype
, comps
,
527 srcWidth
, srcPtr
, srcPtr
,
533 * Strides are in bytes. If zero, it'll be computed as width * bpp.
536 reduce_2d(enum pipe_format pformat
,
537 int srcWidth
, int srcHeight
,
538 int srcRowStride
, const ubyte
*srcPtr
,
539 int dstWidth
, int dstHeight
,
540 int dstRowStride
, ubyte
*dstPtr
)
544 const int bpt
= pf_get_size(pformat
);
545 const ubyte
*srcA
, *srcB
;
549 format_to_type_comps(pformat
, &datatype
, &comps
);
552 srcRowStride
= bpt
* srcWidth
;
555 dstRowStride
= bpt
* dstWidth
;
557 /* Compute src and dst pointers */
560 srcB
= srcA
+ srcRowStride
;
565 for (row
= 0; row
< dstHeight
; row
++) {
566 do_row(datatype
, comps
,
567 srcWidth
, srcA
, srcB
,
569 srcA
+= 2 * srcRowStride
;
570 srcB
+= 2 * srcRowStride
;
577 make_1d_mipmap(struct gen_mipmap_state
*ctx
,
578 struct pipe_texture
*pt
,
579 uint face
, uint baseLevel
, uint lastLevel
)
581 struct pipe_context
*pipe
= ctx
->pipe
;
582 struct pipe_screen
*screen
= pipe
->screen
;
583 const uint zslice
= 0;
586 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
587 const uint srcLevel
= dstLevel
- 1;
588 struct pipe_surface
*srcSurf
, *dstSurf
;
589 void *srcMap
, *dstMap
;
591 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
,
592 PIPE_BUFFER_USAGE_CPU_READ
);
594 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
,
595 PIPE_BUFFER_USAGE_CPU_WRITE
);
597 srcMap
= ((ubyte
*) pipe_buffer_map(screen
, srcSurf
->buffer
,
598 PIPE_BUFFER_USAGE_CPU_READ
)
600 dstMap
= ((ubyte
*) pipe_buffer_map(screen
, dstSurf
->buffer
,
601 PIPE_BUFFER_USAGE_CPU_WRITE
)
604 reduce_1d(pt
->format
,
605 srcSurf
->width
, srcMap
,
606 dstSurf
->width
, dstMap
);
608 pipe_buffer_unmap(screen
, srcSurf
->buffer
);
609 pipe_buffer_unmap(screen
, dstSurf
->buffer
);
611 pipe_surface_reference(&srcSurf
, NULL
);
612 pipe_surface_reference(&dstSurf
, NULL
);
618 make_2d_mipmap(struct gen_mipmap_state
*ctx
,
619 struct pipe_texture
*pt
,
620 uint face
, uint baseLevel
, uint lastLevel
)
622 struct pipe_context
*pipe
= ctx
->pipe
;
623 struct pipe_screen
*screen
= pipe
->screen
;
624 const uint zslice
= 0;
627 assert(pt
->block
.width
== 1);
628 assert(pt
->block
.height
== 1);
630 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
631 const uint srcLevel
= dstLevel
- 1;
632 struct pipe_surface
*srcSurf
, *dstSurf
;
633 ubyte
*srcMap
, *dstMap
;
635 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
,
636 PIPE_BUFFER_USAGE_CPU_READ
);
637 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
,
638 PIPE_BUFFER_USAGE_CPU_WRITE
);
640 srcMap
= ((ubyte
*) pipe_buffer_map(screen
, srcSurf
->buffer
,
641 PIPE_BUFFER_USAGE_CPU_READ
)
643 dstMap
= ((ubyte
*) pipe_buffer_map(screen
, dstSurf
->buffer
,
644 PIPE_BUFFER_USAGE_CPU_WRITE
)
647 reduce_2d(pt
->format
,
648 srcSurf
->width
, srcSurf
->height
,
649 srcSurf
->stride
, srcMap
,
650 dstSurf
->width
, dstSurf
->height
,
651 dstSurf
->stride
, dstMap
);
653 pipe_buffer_unmap(screen
, srcSurf
->buffer
);
654 pipe_buffer_unmap(screen
, dstSurf
->buffer
);
656 pipe_surface_reference(&srcSurf
, NULL
);
657 pipe_surface_reference(&dstSurf
, NULL
);
663 make_3d_mipmap(struct gen_mipmap_state
*ctx
,
664 struct pipe_texture
*pt
,
665 uint face
, uint baseLevel
, uint lastLevel
)
671 fallback_gen_mipmap(struct gen_mipmap_state
*ctx
,
672 struct pipe_texture
*pt
,
673 uint face
, uint baseLevel
, uint lastLevel
)
675 switch (pt
->target
) {
676 case PIPE_TEXTURE_1D
:
677 make_1d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
679 case PIPE_TEXTURE_2D
:
680 case PIPE_TEXTURE_CUBE
:
681 make_2d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
683 case PIPE_TEXTURE_3D
:
684 make_3d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
693 * Create a mipmap generation context.
694 * The idea is to create one of these and re-use it each time we need to
697 struct gen_mipmap_state
*
698 util_create_gen_mipmap(struct pipe_context
*pipe
,
699 struct cso_context
*cso
)
701 struct gen_mipmap_state
*ctx
;
704 ctx
= CALLOC_STRUCT(gen_mipmap_state
);
711 /* disabled blending/masking */
712 memset(&ctx
->blend
, 0, sizeof(ctx
->blend
));
713 ctx
->blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
714 ctx
->blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
715 ctx
->blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
716 ctx
->blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
717 ctx
->blend
.colormask
= PIPE_MASK_RGBA
;
719 /* no-op depth/stencil/alpha */
720 memset(&ctx
->depthstencil
, 0, sizeof(ctx
->depthstencil
));
723 memset(&ctx
->rasterizer
, 0, sizeof(ctx
->rasterizer
));
724 ctx
->rasterizer
.front_winding
= PIPE_WINDING_CW
;
725 ctx
->rasterizer
.cull_mode
= PIPE_WINDING_NONE
;
726 ctx
->rasterizer
.bypass_clipping
= 1;
727 /*ctx->rasterizer.bypass_vs = 1;*/
728 ctx
->rasterizer
.gl_rasterization_rules
= 1;
731 memset(&ctx
->sampler
, 0, sizeof(ctx
->sampler
));
732 ctx
->sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
733 ctx
->sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
734 ctx
->sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
735 ctx
->sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
736 ctx
->sampler
.normalized_coords
= 1;
738 /* viewport state (identity, verts are in wincoords) */
739 ctx
->viewport
.scale
[0] = 1.0;
740 ctx
->viewport
.scale
[1] = 1.0;
741 ctx
->viewport
.scale
[2] = 1.0;
742 ctx
->viewport
.scale
[3] = 1.0;
743 ctx
->viewport
.translate
[0] = 0.0;
744 ctx
->viewport
.translate
[1] = 0.0;
745 ctx
->viewport
.translate
[2] = 0.0;
746 ctx
->viewport
.translate
[3] = 0.0;
750 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
751 TGSI_SEMANTIC_GENERIC
};
752 const uint semantic_indexes
[] = { 0, 0 };
753 ctx
->vs
= util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
758 /* fragment shader */
759 ctx
->fs
= util_make_fragment_tex_shader(pipe
, &ctx
->frag_shader
);
761 ctx
->vbuf
= pipe_buffer_create(pipe
->screen
,
763 PIPE_BUFFER_USAGE_VERTEX
,
764 sizeof(ctx
->vertices
));
770 /* vertex data that doesn't change */
771 for (i
= 0; i
< 4; i
++) {
772 ctx
->vertices
[i
][0][2] = 0.0f
; /* z */
773 ctx
->vertices
[i
][0][3] = 1.0f
; /* w */
774 ctx
->vertices
[i
][1][2] = 0.0f
; /* r */
775 ctx
->vertices
[i
][1][3] = 1.0f
; /* q */
783 set_vertex_data(struct gen_mipmap_state
*ctx
, float width
, float height
)
787 ctx
->vertices
[0][0][0] = 0.0f
; /*x*/
788 ctx
->vertices
[0][0][1] = 0.0f
; /*y*/
789 ctx
->vertices
[0][1][0] = 0.0f
; /*s*/
790 ctx
->vertices
[0][1][1] = 0.0f
; /*t*/
792 ctx
->vertices
[1][0][0] = width
;
793 ctx
->vertices
[1][0][1] = 0.0f
;
794 ctx
->vertices
[1][1][0] = 1.0f
;
795 ctx
->vertices
[1][1][1] = 0.0f
;
797 ctx
->vertices
[2][0][0] = width
;
798 ctx
->vertices
[2][0][1] = height
;
799 ctx
->vertices
[2][1][0] = 1.0f
;
800 ctx
->vertices
[2][1][1] = 1.0f
;
802 ctx
->vertices
[3][0][0] = 0.0f
;
803 ctx
->vertices
[3][0][1] = height
;
804 ctx
->vertices
[3][1][0] = 0.0f
;
805 ctx
->vertices
[3][1][1] = 1.0f
;
807 buf
= pipe_buffer_map(ctx
->pipe
->screen
, ctx
->vbuf
,
808 PIPE_BUFFER_USAGE_CPU_WRITE
);
810 memcpy(buf
, ctx
->vertices
, sizeof(ctx
->vertices
));
812 pipe_buffer_unmap(ctx
->pipe
->screen
, ctx
->vbuf
);
818 * Destroy a mipmap generation context
821 util_destroy_gen_mipmap(struct gen_mipmap_state
*ctx
)
823 struct pipe_context
*pipe
= ctx
->pipe
;
825 pipe
->delete_vs_state(pipe
, ctx
->vs
);
826 pipe
->delete_fs_state(pipe
, ctx
->fs
);
828 FREE((void*) ctx
->vert_shader
.tokens
);
829 FREE((void*) ctx
->frag_shader
.tokens
);
831 pipe_buffer_reference(pipe
->screen
, &ctx
->vbuf
, NULL
);
838 * Generate mipmap images. It's assumed all needed texture memory is
841 * \param pt the texture to generate mipmap levels for
842 * \param face which cube face to generate mipmaps for (0 for non-cube maps)
843 * \param baseLevel the first mipmap level to use as a src
844 * \param lastLevel the last mipmap level to generate
845 * \param filter the minification filter used to generate mipmap levels with
846 * \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
849 util_gen_mipmap(struct gen_mipmap_state
*ctx
,
850 struct pipe_texture
*pt
,
851 uint face
, uint baseLevel
, uint lastLevel
, uint filter
)
853 struct pipe_context
*pipe
= ctx
->pipe
;
854 struct pipe_screen
*screen
= pipe
->screen
;
855 struct pipe_framebuffer_state fb
;
859 /* check if we can render in the texture's format */
860 if (!screen
->is_format_supported(screen
, pt
->format
, PIPE_TEXTURE_2D
,
861 PIPE_TEXTURE_USAGE_RENDER_TARGET
, 0)) {
862 fallback_gen_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
866 /* save state (restored below) */
867 cso_save_blend(ctx
->cso
);
868 cso_save_depth_stencil_alpha(ctx
->cso
);
869 cso_save_rasterizer(ctx
->cso
);
870 cso_save_samplers(ctx
->cso
);
871 cso_save_sampler_textures(ctx
->cso
);
872 cso_save_framebuffer(ctx
->cso
);
873 cso_save_fragment_shader(ctx
->cso
);
874 cso_save_vertex_shader(ctx
->cso
);
875 cso_save_viewport(ctx
->cso
);
878 cso_set_blend(ctx
->cso
, &ctx
->blend
);
879 cso_set_depth_stencil_alpha(ctx
->cso
, &ctx
->depthstencil
);
880 cso_set_rasterizer(ctx
->cso
, &ctx
->rasterizer
);
881 cso_set_viewport(ctx
->cso
, &ctx
->viewport
);
883 cso_set_fragment_shader_handle(ctx
->cso
, ctx
->fs
);
884 cso_set_vertex_shader_handle(ctx
->cso
, ctx
->vs
);
886 /* init framebuffer state */
887 memset(&fb
, 0, sizeof(fb
));
890 /* set min/mag to same filter for faster sw speed */
891 ctx
->sampler
.mag_img_filter
= filter
;
892 ctx
->sampler
.min_img_filter
= filter
;
895 * XXX for small mipmap levels, it may be faster to use the software
898 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
899 const uint srcLevel
= dstLevel
- 1;
901 struct pipe_surface
*surf
=
902 screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
,
903 PIPE_BUFFER_USAGE_GPU_WRITE
);
906 * Setup framebuffer / dest surface
909 fb
.width
= pt
->width
[dstLevel
];
910 fb
.height
= pt
->height
[dstLevel
];
911 cso_set_framebuffer(ctx
->cso
, &fb
);
914 * Setup sampler state
915 * Note: we should only have to set the min/max LOD clamps to ensure
916 * we grab texels from the right mipmap level. But some hardware
917 * has trouble with min clamping so we also set the lod_bias to
918 * try to work around that.
920 ctx
->sampler
.min_lod
= ctx
->sampler
.max_lod
= (float) srcLevel
;
921 ctx
->sampler
.lod_bias
= (float) srcLevel
;
922 cso_single_sampler(ctx
->cso
, 0, &ctx
->sampler
);
923 cso_single_sampler_done(ctx
->cso
);
925 cso_set_sampler_textures(ctx
->cso
, 1, &pt
);
927 /* quad coords in window coords (bypassing clipping, viewport mapping) */
929 (float) pt
->width
[dstLevel
],
930 (float) pt
->height
[dstLevel
]);
931 util_draw_vertex_buffer(ctx
->pipe
, ctx
->vbuf
,
932 PIPE_PRIM_TRIANGLE_FAN
,
934 2); /* attribs/vert */
936 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
938 /* need to signal that the texture has changed _after_ rendering to it */
939 pipe_surface_reference( &surf
, NULL
);
942 /* restore state we changed */
943 cso_restore_blend(ctx
->cso
);
944 cso_restore_depth_stencil_alpha(ctx
->cso
);
945 cso_restore_rasterizer(ctx
->cso
);
946 cso_restore_samplers(ctx
->cso
);
947 cso_restore_sampler_textures(ctx
->cso
);
948 cso_restore_framebuffer(ctx
->cso
);
949 cso_restore_fragment_shader(ctx
->cso
);
950 cso_restore_vertex_shader(ctx
->cso
);
951 cso_restore_viewport(ctx
->cso
);