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_util.h"
41 #include "pipe/p_winsys.h"
42 #include "pipe/p_shader_tokens.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/util/tgsi_build.h"
49 #include "tgsi/util/tgsi_dump.h"
50 #include "tgsi/util/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;*/
65 struct pipe_sampler_state
*vs
;
66 struct pipe_sampler_state
*fs
;
85 typedef ushort half_float
;
90 float_to_half(float f
);
93 half_to_float(half_float h
);
98 * Average together two rows of a source image to produce a single new
99 * row in the dest image. It's legal for the two source rows to point
100 * to the same data. The source width must be equal to either the
101 * dest width or two times the dest width.
102 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
103 * \param comps number of components per pixel (1..4)
106 do_row(enum dtype datatype
, uint comps
, int srcWidth
,
107 const void *srcRowA
, const void *srcRowB
,
108 int dstWidth
, void *dstRow
)
110 const uint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
111 const uint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
116 /* This assertion is no longer valid with non-power-of-2 textures
117 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
120 if (datatype
== UBYTE
&& comps
== 4) {
122 const ubyte(*rowA
)[4] = (const ubyte(*)[4]) srcRowA
;
123 const ubyte(*rowB
)[4] = (const ubyte(*)[4]) srcRowB
;
124 ubyte(*dst
)[4] = (ubyte(*)[4]) dstRow
;
125 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
126 i
++, j
+= colStride
, k
+= colStride
) {
127 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
128 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
129 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
130 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
133 else if (datatype
== UBYTE
&& comps
== 3) {
135 const ubyte(*rowA
)[3] = (const ubyte(*)[3]) srcRowA
;
136 const ubyte(*rowB
)[3] = (const ubyte(*)[3]) srcRowB
;
137 ubyte(*dst
)[3] = (ubyte(*)[3]) dstRow
;
138 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
139 i
++, j
+= colStride
, k
+= colStride
) {
140 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
141 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
142 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
145 else if (datatype
== UBYTE
&& comps
== 2) {
147 const ubyte(*rowA
)[2] = (const ubyte(*)[2]) srcRowA
;
148 const ubyte(*rowB
)[2] = (const ubyte(*)[2]) srcRowB
;
149 ubyte(*dst
)[2] = (ubyte(*)[2]) dstRow
;
150 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
151 i
++, j
+= colStride
, k
+= colStride
) {
152 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
153 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
156 else if (datatype
== UBYTE
&& comps
== 1) {
158 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
159 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
160 ubyte
*dst
= (ubyte
*) dstRow
;
161 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
162 i
++, j
+= colStride
, k
+= colStride
) {
163 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
167 else if (datatype
== USHORT
&& comps
== 4) {
169 const ushort(*rowA
)[4] = (const ushort(*)[4]) srcRowA
;
170 const ushort(*rowB
)[4] = (const ushort(*)[4]) srcRowB
;
171 ushort(*dst
)[4] = (ushort(*)[4]) dstRow
;
172 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
173 i
++, j
+= colStride
, k
+= colStride
) {
174 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
175 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
176 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
177 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
180 else if (datatype
== USHORT
&& comps
== 3) {
182 const ushort(*rowA
)[3] = (const ushort(*)[3]) srcRowA
;
183 const ushort(*rowB
)[3] = (const ushort(*)[3]) srcRowB
;
184 ushort(*dst
)[3] = (ushort(*)[3]) 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;
192 else if (datatype
== USHORT
&& comps
== 2) {
194 const ushort(*rowA
)[2] = (const ushort(*)[2]) srcRowA
;
195 const ushort(*rowB
)[2] = (const ushort(*)[2]) srcRowB
;
196 ushort(*dst
)[2] = (ushort(*)[2]) dstRow
;
197 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
198 i
++, j
+= colStride
, k
+= colStride
) {
199 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
200 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
203 else if (datatype
== USHORT
&& comps
== 1) {
205 const ushort
*rowA
= (const ushort
*) srcRowA
;
206 const ushort
*rowB
= (const ushort
*) srcRowB
;
207 ushort
*dst
= (ushort
*) dstRow
;
208 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
209 i
++, j
+= colStride
, k
+= colStride
) {
210 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
214 else if (datatype
== FLOAT
&& comps
== 4) {
216 const float(*rowA
)[4] = (const float(*)[4]) srcRowA
;
217 const float(*rowB
)[4] = (const float(*)[4]) srcRowB
;
218 float(*dst
)[4] = (float(*)[4]) dstRow
;
219 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
220 i
++, j
+= colStride
, k
+= colStride
) {
221 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
222 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
223 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
224 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
225 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
226 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
227 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
228 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
231 else if (datatype
== FLOAT
&& comps
== 3) {
233 const float(*rowA
)[3] = (const float(*)[3]) srcRowA
;
234 const float(*rowB
)[3] = (const float(*)[3]) srcRowB
;
235 float(*dst
)[3] = (float(*)[3]) dstRow
;
236 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
237 i
++, j
+= colStride
, k
+= colStride
) {
238 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
239 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
240 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
241 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
242 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
243 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
246 else if (datatype
== FLOAT
&& comps
== 2) {
248 const float(*rowA
)[2] = (const float(*)[2]) srcRowA
;
249 const float(*rowB
)[2] = (const float(*)[2]) srcRowB
;
250 float(*dst
)[2] = (float(*)[2]) dstRow
;
251 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
252 i
++, j
+= colStride
, k
+= colStride
) {
253 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
254 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
255 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
256 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
259 else if (datatype
== FLOAT
&& comps
== 1) {
261 const float *rowA
= (const float *) srcRowA
;
262 const float *rowB
= (const float *) srcRowB
;
263 float *dst
= (float *) dstRow
;
264 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
265 i
++, j
+= colStride
, k
+= colStride
) {
266 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
271 else if (datatype
== HALF_FLOAT
&& comps
== 4) {
273 const half_float(*rowA
)[4] = (const half_float(*)[4]) srcRowA
;
274 const half_float(*rowB
)[4] = (const half_float(*)[4]) srcRowB
;
275 half_float(*dst
)[4] = (half_float(*)[4]) dstRow
;
276 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
277 i
++, j
+= colStride
, k
+= colStride
) {
278 for (comp
= 0; comp
< 4; comp
++) {
279 float aj
, ak
, bj
, bk
;
280 aj
= half_to_float(rowA
[j
][comp
]);
281 ak
= half_to_float(rowA
[k
][comp
]);
282 bj
= half_to_float(rowB
[j
][comp
]);
283 bk
= half_to_float(rowB
[k
][comp
]);
284 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
288 else if (datatype
== HALF_FLOAT
&& comps
== 3) {
290 const half_float(*rowA
)[3] = (const half_float(*)[3]) srcRowA
;
291 const half_float(*rowB
)[3] = (const half_float(*)[3]) srcRowB
;
292 half_float(*dst
)[3] = (half_float(*)[3]) dstRow
;
293 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
294 i
++, j
+= colStride
, k
+= colStride
) {
295 for (comp
= 0; comp
< 3; comp
++) {
296 float aj
, ak
, bj
, bk
;
297 aj
= half_to_float(rowA
[j
][comp
]);
298 ak
= half_to_float(rowA
[k
][comp
]);
299 bj
= half_to_float(rowB
[j
][comp
]);
300 bk
= half_to_float(rowB
[k
][comp
]);
301 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
305 else if (datatype
== HALF_FLOAT
&& comps
== 2) {
307 const half_float(*rowA
)[2] = (const half_float(*)[2]) srcRowA
;
308 const half_float(*rowB
)[2] = (const half_float(*)[2]) srcRowB
;
309 half_float(*dst
)[2] = (half_float(*)[2]) dstRow
;
310 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
311 i
++, j
+= colStride
, k
+= colStride
) {
312 for (comp
= 0; comp
< 2; comp
++) {
313 float aj
, ak
, bj
, bk
;
314 aj
= half_to_float(rowA
[j
][comp
]);
315 ak
= half_to_float(rowA
[k
][comp
]);
316 bj
= half_to_float(rowB
[j
][comp
]);
317 bk
= half_to_float(rowB
[k
][comp
]);
318 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
322 else if (datatype
== HALF_FLOAT
&& comps
== 1) {
324 const half_float
*rowA
= (const half_float
*) srcRowA
;
325 const half_float
*rowB
= (const half_float
*) srcRowB
;
326 half_float
*dst
= (half_float
*) dstRow
;
327 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
328 i
++, j
+= colStride
, k
+= colStride
) {
329 float aj
, ak
, bj
, bk
;
330 aj
= half_to_float(rowA
[j
]);
331 ak
= half_to_float(rowA
[k
]);
332 bj
= half_to_float(rowB
[j
]);
333 bk
= half_to_float(rowB
[k
]);
334 dst
[i
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
339 else if (datatype
== UINT
&& comps
== 1) {
341 const uint
*rowA
= (const uint
*) srcRowA
;
342 const uint
*rowB
= (const uint
*) srcRowB
;
343 uint
*dst
= (uint
*) dstRow
;
344 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
345 i
++, j
+= colStride
, k
+= colStride
) {
346 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
350 else if (datatype
== USHORT_5_6_5
&& comps
== 3) {
352 const ushort
*rowA
= (const ushort
*) srcRowA
;
353 const ushort
*rowB
= (const ushort
*) srcRowB
;
354 ushort
*dst
= (ushort
*) dstRow
;
355 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
356 i
++, j
+= colStride
, k
+= colStride
) {
357 const int rowAr0
= rowA
[j
] & 0x1f;
358 const int rowAr1
= rowA
[k
] & 0x1f;
359 const int rowBr0
= rowB
[j
] & 0x1f;
360 const int rowBr1
= rowB
[k
] & 0x1f;
361 const int rowAg0
= (rowA
[j
] >> 5) & 0x3f;
362 const int rowAg1
= (rowA
[k
] >> 5) & 0x3f;
363 const int rowBg0
= (rowB
[j
] >> 5) & 0x3f;
364 const int rowBg1
= (rowB
[k
] >> 5) & 0x3f;
365 const int rowAb0
= (rowA
[j
] >> 11) & 0x1f;
366 const int rowAb1
= (rowA
[k
] >> 11) & 0x1f;
367 const int rowBb0
= (rowB
[j
] >> 11) & 0x1f;
368 const int rowBb1
= (rowB
[k
] >> 11) & 0x1f;
369 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
370 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
371 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
372 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
375 else if (datatype
== USHORT_4_4_4_4
&& comps
== 4) {
377 const ushort
*rowA
= (const ushort
*) srcRowA
;
378 const ushort
*rowB
= (const ushort
*) srcRowB
;
379 ushort
*dst
= (ushort
*) dstRow
;
380 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
381 i
++, j
+= colStride
, k
+= colStride
) {
382 const int rowAr0
= rowA
[j
] & 0xf;
383 const int rowAr1
= rowA
[k
] & 0xf;
384 const int rowBr0
= rowB
[j
] & 0xf;
385 const int rowBr1
= rowB
[k
] & 0xf;
386 const int rowAg0
= (rowA
[j
] >> 4) & 0xf;
387 const int rowAg1
= (rowA
[k
] >> 4) & 0xf;
388 const int rowBg0
= (rowB
[j
] >> 4) & 0xf;
389 const int rowBg1
= (rowB
[k
] >> 4) & 0xf;
390 const int rowAb0
= (rowA
[j
] >> 8) & 0xf;
391 const int rowAb1
= (rowA
[k
] >> 8) & 0xf;
392 const int rowBb0
= (rowB
[j
] >> 8) & 0xf;
393 const int rowBb1
= (rowB
[k
] >> 8) & 0xf;
394 const int rowAa0
= (rowA
[j
] >> 12) & 0xf;
395 const int rowAa1
= (rowA
[k
] >> 12) & 0xf;
396 const int rowBa0
= (rowB
[j
] >> 12) & 0xf;
397 const int rowBa1
= (rowB
[k
] >> 12) & 0xf;
398 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
399 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
400 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
401 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
402 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
405 else if (datatype
== USHORT_1_5_5_5_REV
&& comps
== 4) {
407 const ushort
*rowA
= (const ushort
*) srcRowA
;
408 const ushort
*rowB
= (const ushort
*) srcRowB
;
409 ushort
*dst
= (ushort
*) dstRow
;
410 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
411 i
++, j
+= colStride
, k
+= colStride
) {
412 const int rowAr0
= rowA
[j
] & 0x1f;
413 const int rowAr1
= rowA
[k
] & 0x1f;
414 const int rowBr0
= rowB
[j
] & 0x1f;
415 const int rowBr1
= rowB
[k
] & 0xf;
416 const int rowAg0
= (rowA
[j
] >> 5) & 0x1f;
417 const int rowAg1
= (rowA
[k
] >> 5) & 0x1f;
418 const int rowBg0
= (rowB
[j
] >> 5) & 0x1f;
419 const int rowBg1
= (rowB
[k
] >> 5) & 0x1f;
420 const int rowAb0
= (rowA
[j
] >> 10) & 0x1f;
421 const int rowAb1
= (rowA
[k
] >> 10) & 0x1f;
422 const int rowBb0
= (rowB
[j
] >> 10) & 0x1f;
423 const int rowBb1
= (rowB
[k
] >> 10) & 0x1f;
424 const int rowAa0
= (rowA
[j
] >> 15) & 0x1;
425 const int rowAa1
= (rowA
[k
] >> 15) & 0x1;
426 const int rowBa0
= (rowB
[j
] >> 15) & 0x1;
427 const int rowBa1
= (rowB
[k
] >> 15) & 0x1;
428 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
429 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
430 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
431 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
432 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
435 else if (datatype
== UBYTE_3_3_2
&& comps
== 3) {
437 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
438 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
439 ubyte
*dst
= (ubyte
*) dstRow
;
440 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
441 i
++, j
+= colStride
, k
+= colStride
) {
442 const int rowAr0
= rowA
[j
] & 0x3;
443 const int rowAr1
= rowA
[k
] & 0x3;
444 const int rowBr0
= rowB
[j
] & 0x3;
445 const int rowBr1
= rowB
[k
] & 0x3;
446 const int rowAg0
= (rowA
[j
] >> 2) & 0x7;
447 const int rowAg1
= (rowA
[k
] >> 2) & 0x7;
448 const int rowBg0
= (rowB
[j
] >> 2) & 0x7;
449 const int rowBg1
= (rowB
[k
] >> 2) & 0x7;
450 const int rowAb0
= (rowA
[j
] >> 5) & 0x7;
451 const int rowAb1
= (rowA
[k
] >> 5) & 0x7;
452 const int rowBb0
= (rowB
[j
] >> 5) & 0x7;
453 const int rowBb1
= (rowB
[k
] >> 5) & 0x7;
454 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
455 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
456 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
457 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
461 debug_printf("bad format in do_row()");
467 format_to_type_comps(enum pipe_format pformat
,
468 enum dtype
*datatype
, uint
*comps
)
471 case PIPE_FORMAT_A8R8G8B8_UNORM
:
472 case PIPE_FORMAT_B8G8R8A8_UNORM
:
476 case PIPE_FORMAT_A1R5G5B5_UNORM
:
477 *datatype
= USHORT_1_5_5_5_REV
;
480 case PIPE_FORMAT_A4R4G4B4_UNORM
:
481 *datatype
= USHORT_4_4_4_4
;
484 case PIPE_FORMAT_R5G6B5_UNORM
:
485 *datatype
= USHORT_5_6_5
;
488 case PIPE_FORMAT_U_L8
:
489 case PIPE_FORMAT_U_A8
:
490 case PIPE_FORMAT_U_I8
:
494 case PIPE_FORMAT_U_A8_L8
:
505 reduce_1d(enum pipe_format pformat
,
506 int srcWidth
, const ubyte
*srcPtr
,
507 int dstWidth
, ubyte
*dstPtr
)
512 format_to_type_comps(pformat
, &datatype
, &comps
);
514 /* we just duplicate the input row, kind of hack, saves code */
515 do_row(datatype
, comps
,
516 srcWidth
, srcPtr
, srcPtr
,
522 * Strides are in bytes. If zero, it'll be computed as width * bpp.
525 reduce_2d(enum pipe_format pformat
,
526 int srcWidth
, int srcHeight
,
527 int srcRowStride
, const ubyte
*srcPtr
,
528 int dstWidth
, int dstHeight
,
529 int dstRowStride
, ubyte
*dstPtr
)
533 const int bpt
= pf_get_size(pformat
);
534 const ubyte
*srcA
, *srcB
;
538 format_to_type_comps(pformat
, &datatype
, &comps
);
541 srcRowStride
= bpt
* srcWidth
;
544 dstRowStride
= bpt
* dstWidth
;
546 /* Compute src and dst pointers */
549 srcB
= srcA
+ srcRowStride
;
554 for (row
= 0; row
< dstHeight
; row
++) {
555 do_row(datatype
, comps
,
556 srcWidth
, srcA
, srcB
,
558 srcA
+= 2 * srcRowStride
;
559 srcB
+= 2 * srcRowStride
;
566 make_1d_mipmap(struct gen_mipmap_state
*ctx
,
567 struct pipe_texture
*pt
,
568 uint face
, uint baseLevel
, uint lastLevel
)
570 struct pipe_context
*pipe
= ctx
->pipe
;
571 struct pipe_screen
*screen
= pipe
->screen
;
572 struct pipe_winsys
*winsys
= pipe
->winsys
;
573 const uint zslice
= 0;
576 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
577 const uint srcLevel
= dstLevel
- 1;
578 struct pipe_surface
*srcSurf
, *dstSurf
;
579 void *srcMap
, *dstMap
;
581 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
);
582 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
584 srcMap
= ((ubyte
*) winsys
->buffer_map(winsys
, srcSurf
->buffer
,
585 PIPE_BUFFER_USAGE_CPU_READ
)
587 dstMap
= ((ubyte
*) winsys
->buffer_map(winsys
, dstSurf
->buffer
,
588 PIPE_BUFFER_USAGE_CPU_WRITE
)
591 reduce_1d(pt
->format
,
592 srcSurf
->width
, srcMap
,
593 dstSurf
->width
, dstMap
);
595 winsys
->buffer_unmap(winsys
, srcSurf
->buffer
);
596 winsys
->buffer_unmap(winsys
, dstSurf
->buffer
);
598 pipe_surface_reference(&srcSurf
, NULL
);
599 pipe_surface_reference(&dstSurf
, NULL
);
605 make_2d_mipmap(struct gen_mipmap_state
*ctx
,
606 struct pipe_texture
*pt
,
607 uint face
, uint baseLevel
, uint lastLevel
)
609 struct pipe_context
*pipe
= ctx
->pipe
;
610 struct pipe_screen
*screen
= pipe
->screen
;
611 struct pipe_winsys
*winsys
= pipe
->winsys
;
612 const uint zslice
= 0;
614 const int bpt
= pf_get_size(pt
->format
);
616 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
617 const uint srcLevel
= dstLevel
- 1;
618 struct pipe_surface
*srcSurf
, *dstSurf
;
619 ubyte
*srcMap
, *dstMap
;
621 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
);
622 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
624 srcMap
= ((ubyte
*) winsys
->buffer_map(winsys
, srcSurf
->buffer
,
625 PIPE_BUFFER_USAGE_CPU_READ
)
627 dstMap
= ((ubyte
*) winsys
->buffer_map(winsys
, dstSurf
->buffer
,
628 PIPE_BUFFER_USAGE_CPU_WRITE
)
631 reduce_2d(pt
->format
,
632 srcSurf
->width
, srcSurf
->height
,
633 srcSurf
->pitch
* bpt
, srcMap
,
634 dstSurf
->width
, dstSurf
->height
,
635 dstSurf
->pitch
* bpt
, dstMap
);
637 winsys
->buffer_unmap(winsys
, srcSurf
->buffer
);
638 winsys
->buffer_unmap(winsys
, dstSurf
->buffer
);
640 pipe_surface_reference(&srcSurf
, NULL
);
641 pipe_surface_reference(&dstSurf
, NULL
);
647 make_3d_mipmap(struct gen_mipmap_state
*ctx
,
648 struct pipe_texture
*pt
,
649 uint face
, uint baseLevel
, uint lastLevel
)
655 fallback_gen_mipmap(struct gen_mipmap_state
*ctx
,
656 struct pipe_texture
*pt
,
657 uint face
, uint baseLevel
, uint lastLevel
)
659 switch (pt
->target
) {
660 case PIPE_TEXTURE_1D
:
661 make_1d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
663 case PIPE_TEXTURE_2D
:
664 case PIPE_TEXTURE_CUBE
:
665 make_2d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
667 case PIPE_TEXTURE_3D
:
668 make_3d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
677 * Create a mipmap generation context.
678 * The idea is to create one of these and re-use it each time we need to
681 struct gen_mipmap_state
*
682 util_create_gen_mipmap(struct pipe_context
*pipe
,
683 struct cso_context
*cso
)
685 struct gen_mipmap_state
*ctx
;
687 ctx
= CALLOC_STRUCT(gen_mipmap_state
);
694 /* disabled blending/masking */
695 memset(&ctx
->blend
, 0, sizeof(ctx
->blend
));
696 ctx
->blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
697 ctx
->blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
698 ctx
->blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
699 ctx
->blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
700 ctx
->blend
.colormask
= PIPE_MASK_RGBA
;
702 /* no-op depth/stencil/alpha */
703 memset(&ctx
->depthstencil
, 0, sizeof(ctx
->depthstencil
));
706 memset(&ctx
->rasterizer
, 0, sizeof(ctx
->rasterizer
));
707 ctx
->rasterizer
.front_winding
= PIPE_WINDING_CW
;
708 ctx
->rasterizer
.cull_mode
= PIPE_WINDING_NONE
;
709 ctx
->rasterizer
.bypass_clipping
= 1; /* bypasses viewport too */
710 /*ctx->rasterizer.bypass_vs = 1;*/
713 memset(&ctx
->sampler
, 0, sizeof(ctx
->sampler
));
714 ctx
->sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
715 ctx
->sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
716 ctx
->sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
717 ctx
->sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
718 ctx
->sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
719 ctx
->sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
720 ctx
->sampler
.normalized_coords
= 1;
725 ctx
->viewport
.scale
[0] = 1.0;
726 ctx
->viewport
.scale
[1] = 1.0;
727 ctx
->viewport
.scale
[2] = 1.0;
728 ctx
->viewport
.scale
[3] = 1.0;
729 ctx
->viewport
.translate
[0] = 0.0;
730 ctx
->viewport
.translate
[1] = 0.0;
731 ctx
->viewport
.translate
[2] = 0.0;
732 ctx
->viewport
.translate
[3] = 0.0;
737 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
738 TGSI_SEMANTIC_GENERIC
};
739 const uint semantic_indexes
[] = { 0, 0 };
740 ctx
->vs
= util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
744 /* fragment shader */
745 ctx
->fs
= util_make_fragment_tex_shader(pipe
);
752 * Destroy a mipmap generation context
755 util_destroy_gen_mipmap(struct gen_mipmap_state
*ctx
)
757 struct pipe_context
*pipe
= ctx
->pipe
;
759 pipe
->delete_vs_state(pipe
, ctx
->vs
);
760 pipe
->delete_fs_state(pipe
, ctx
->fs
);
768 simple_viewport(struct pipe_context
*pipe
, uint width
, uint height
)
770 struct pipe_viewport_state vp
;
772 vp
.scale
[0] = 0.5 * width
;
773 vp
.scale
[1] = -0.5 * height
;
776 vp
.translate
[0] = 0.5 * width
;
777 vp
.translate
[1] = 0.5 * height
;
778 vp
.translate
[2] = 0.0;
779 vp
.translate
[3] = 0.0;
781 pipe
->set_viewport_state(pipe
, &vp
);
787 * Generate mipmap images. It's assumed all needed texture memory is
790 * \param pt the texture to generate mipmap levels for
791 * \param face which cube face to generate mipmaps for (0 for non-cube maps)
792 * \param baseLevel the first mipmap level to use as a src
793 * \param lastLevel the last mipmap level to generate
796 util_gen_mipmap(struct gen_mipmap_state
*ctx
,
797 struct pipe_texture
*pt
,
798 uint face
, uint baseLevel
, uint lastLevel
)
800 struct pipe_context
*pipe
= ctx
->pipe
;
801 struct pipe_screen
*screen
= pipe
->screen
;
802 struct pipe_framebuffer_state fb
;
806 /* check if we can render in the texture's format */
807 if (!screen
->is_format_supported(screen
, pt
->format
, PIPE_SURFACE
)) {
808 fallback_gen_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
812 /* save state (restored below) */
813 cso_save_blend(ctx
->cso
);
814 cso_save_depth_stencil_alpha(ctx
->cso
);
815 cso_save_rasterizer(ctx
->cso
);
816 cso_save_samplers(ctx
->cso
);
817 cso_save_sampler_textures(ctx
->cso
);
818 cso_save_framebuffer(ctx
->cso
);
821 cso_set_blend(ctx
->cso
, &ctx
->blend
);
822 cso_set_depth_stencil_alpha(ctx
->cso
, &ctx
->depthstencil
);
823 cso_set_rasterizer(ctx
->cso
, &ctx
->rasterizer
);
825 pipe
->bind_vs_state(pipe
, ctx
->vs
);
826 pipe
->bind_fs_state(pipe
, ctx
->fs
);
828 pipe
->set_viewport_state(pipe
, &ctx
->viewport
);
831 /* init framebuffer state */
832 memset(&fb
, 0, sizeof(fb
));
836 * XXX for small mipmap levels, it may be faster to use the software
839 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
840 const uint srcLevel
= dstLevel
- 1;
843 * Setup framebuffer / dest surface
845 fb
.cbufs
[0] = screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
846 cso_set_framebuffer(ctx
->cso
, &fb
);
849 * Setup sampler state
850 * Note: we should only have to set the min/max LOD clamps to ensure
851 * we grab texels from the right mipmap level. But some hardware
852 * has trouble with min clamping so we also set the lod_bias to
853 * try to work around that.
855 ctx
->sampler
.min_lod
= ctx
->sampler
.max_lod
= (float) srcLevel
;
856 ctx
->sampler
.lod_bias
= (float) srcLevel
;
857 cso_single_sampler(ctx
->cso
, 0, &ctx
->sampler
);
858 cso_single_sampler_done(ctx
->cso
);
860 simple_viewport(pipe
, pt
->width
[dstLevel
], pt
->height
[dstLevel
]);
863 pipe
->set_sampler_textures(pipe
, 1, &pt
);
865 /* quad coords in window coords (bypassing clipping, viewport mapping) */
866 util_draw_texquad(pipe
,
867 0.0F
, 0.0F
, /* x0, y0 */
868 (float) pt
->width
[dstLevel
], /* x1 */
869 (float) pt
->height
[dstLevel
], /* y1 */
873 pipe
->flush(pipe
, PIPE_FLUSH_WAIT
);
875 /* need to signal that the texture has changed _after_ rendering to it */
876 pipe
->texture_update(pipe
, pt
, face
, (1 << dstLevel
));
879 /* restore state we changed */
880 cso_restore_blend(ctx
->cso
);
881 cso_restore_depth_stencil_alpha(ctx
->cso
);
882 cso_restore_rasterizer(ctx
->cso
);
883 cso_restore_samplers(ctx
->cso
);
884 cso_restore_sampler_textures(ctx
->cso
);
885 cso_restore_framebuffer(ctx
->cso
);