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"
53 struct gen_mipmap_state
55 struct pipe_context
*pipe
;
60 /*struct pipe_viewport_state viewport;*/
61 struct pipe_sampler_state
*vs
;
62 struct pipe_sampler_state
*fs
;
81 typedef ushort half_float
;
86 float_to_half(float f
);
89 half_to_float(half_float h
);
94 * Average together two rows of a source image to produce a single new
95 * row in the dest image. It's legal for the two source rows to point
96 * to the same data. The source width must be equal to either the
97 * dest width or two times the dest width.
98 * \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
99 * \param comps number of components per pixel (1..4)
102 do_row(enum dtype datatype
, uint comps
, int srcWidth
,
103 const void *srcRowA
, const void *srcRowB
,
104 int dstWidth
, void *dstRow
)
106 const uint k0
= (srcWidth
== dstWidth
) ? 0 : 1;
107 const uint colStride
= (srcWidth
== dstWidth
) ? 1 : 2;
112 /* This assertion is no longer valid with non-power-of-2 textures
113 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
116 if (datatype
== UBYTE
&& comps
== 4) {
118 const ubyte(*rowA
)[4] = (const ubyte(*)[4]) srcRowA
;
119 const ubyte(*rowB
)[4] = (const ubyte(*)[4]) srcRowB
;
120 ubyte(*dst
)[4] = (ubyte(*)[4]) dstRow
;
121 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
122 i
++, j
+= colStride
, k
+= colStride
) {
123 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
124 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
125 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
126 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
129 else if (datatype
== UBYTE
&& comps
== 3) {
131 const ubyte(*rowA
)[3] = (const ubyte(*)[3]) srcRowA
;
132 const ubyte(*rowB
)[3] = (const ubyte(*)[3]) srcRowB
;
133 ubyte(*dst
)[3] = (ubyte(*)[3]) dstRow
;
134 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
135 i
++, j
+= colStride
, k
+= colStride
) {
136 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
137 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
138 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
141 else if (datatype
== UBYTE
&& comps
== 2) {
143 const ubyte(*rowA
)[2] = (const ubyte(*)[2]) srcRowA
;
144 const ubyte(*rowB
)[2] = (const ubyte(*)[2]) srcRowB
;
145 ubyte(*dst
)[2] = (ubyte(*)[2]) dstRow
;
146 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
147 i
++, j
+= colStride
, k
+= colStride
) {
148 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) >> 2;
149 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) >> 2;
152 else if (datatype
== UBYTE
&& comps
== 1) {
154 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
155 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
156 ubyte
*dst
= (ubyte
*) dstRow
;
157 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
158 i
++, j
+= colStride
, k
+= colStride
) {
159 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) >> 2;
163 else if (datatype
== USHORT
&& comps
== 4) {
165 const ushort(*rowA
)[4] = (const ushort(*)[4]) srcRowA
;
166 const ushort(*rowB
)[4] = (const ushort(*)[4]) srcRowB
;
167 ushort(*dst
)[4] = (ushort(*)[4]) dstRow
;
168 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
169 i
++, j
+= colStride
, k
+= colStride
) {
170 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
171 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
172 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
173 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] + rowB
[j
][3] + rowB
[k
][3]) / 4;
176 else if (datatype
== USHORT
&& comps
== 3) {
178 const ushort(*rowA
)[3] = (const ushort(*)[3]) srcRowA
;
179 const ushort(*rowB
)[3] = (const ushort(*)[3]) srcRowB
;
180 ushort(*dst
)[3] = (ushort(*)[3]) dstRow
;
181 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
182 i
++, j
+= colStride
, k
+= colStride
) {
183 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
184 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
185 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] + rowB
[j
][2] + rowB
[k
][2]) / 4;
188 else if (datatype
== USHORT
&& comps
== 2) {
190 const ushort(*rowA
)[2] = (const ushort(*)[2]) srcRowA
;
191 const ushort(*rowB
)[2] = (const ushort(*)[2]) srcRowB
;
192 ushort(*dst
)[2] = (ushort(*)[2]) dstRow
;
193 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
194 i
++, j
+= colStride
, k
+= colStride
) {
195 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] + rowB
[j
][0] + rowB
[k
][0]) / 4;
196 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] + rowB
[j
][1] + rowB
[k
][1]) / 4;
199 else if (datatype
== USHORT
&& comps
== 1) {
201 const ushort
*rowA
= (const ushort
*) srcRowA
;
202 const ushort
*rowB
= (const ushort
*) srcRowB
;
203 ushort
*dst
= (ushort
*) dstRow
;
204 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
205 i
++, j
+= colStride
, k
+= colStride
) {
206 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) / 4;
210 else if (datatype
== FLOAT
&& comps
== 4) {
212 const float(*rowA
)[4] = (const float(*)[4]) srcRowA
;
213 const float(*rowB
)[4] = (const float(*)[4]) srcRowB
;
214 float(*dst
)[4] = (float(*)[4]) dstRow
;
215 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
216 i
++, j
+= colStride
, k
+= colStride
) {
217 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
218 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
219 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
220 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
221 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
222 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
223 dst
[i
][3] = (rowA
[j
][3] + rowA
[k
][3] +
224 rowB
[j
][3] + rowB
[k
][3]) * 0.25F
;
227 else if (datatype
== FLOAT
&& comps
== 3) {
229 const float(*rowA
)[3] = (const float(*)[3]) srcRowA
;
230 const float(*rowB
)[3] = (const float(*)[3]) srcRowB
;
231 float(*dst
)[3] = (float(*)[3]) 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] +
235 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
236 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
237 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
238 dst
[i
][2] = (rowA
[j
][2] + rowA
[k
][2] +
239 rowB
[j
][2] + rowB
[k
][2]) * 0.25F
;
242 else if (datatype
== FLOAT
&& comps
== 2) {
244 const float(*rowA
)[2] = (const float(*)[2]) srcRowA
;
245 const float(*rowB
)[2] = (const float(*)[2]) srcRowB
;
246 float(*dst
)[2] = (float(*)[2]) dstRow
;
247 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
248 i
++, j
+= colStride
, k
+= colStride
) {
249 dst
[i
][0] = (rowA
[j
][0] + rowA
[k
][0] +
250 rowB
[j
][0] + rowB
[k
][0]) * 0.25F
;
251 dst
[i
][1] = (rowA
[j
][1] + rowA
[k
][1] +
252 rowB
[j
][1] + rowB
[k
][1]) * 0.25F
;
255 else if (datatype
== FLOAT
&& comps
== 1) {
257 const float *rowA
= (const float *) srcRowA
;
258 const float *rowB
= (const float *) srcRowB
;
259 float *dst
= (float *) dstRow
;
260 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
261 i
++, j
+= colStride
, k
+= colStride
) {
262 dst
[i
] = (rowA
[j
] + rowA
[k
] + rowB
[j
] + rowB
[k
]) * 0.25F
;
267 else if (datatype
== HALF_FLOAT
&& comps
== 4) {
269 const half_float(*rowA
)[4] = (const half_float(*)[4]) srcRowA
;
270 const half_float(*rowB
)[4] = (const half_float(*)[4]) srcRowB
;
271 half_float(*dst
)[4] = (half_float(*)[4]) dstRow
;
272 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
273 i
++, j
+= colStride
, k
+= colStride
) {
274 for (comp
= 0; comp
< 4; comp
++) {
275 float aj
, ak
, bj
, bk
;
276 aj
= half_to_float(rowA
[j
][comp
]);
277 ak
= half_to_float(rowA
[k
][comp
]);
278 bj
= half_to_float(rowB
[j
][comp
]);
279 bk
= half_to_float(rowB
[k
][comp
]);
280 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
284 else if (datatype
== HALF_FLOAT
&& comps
== 3) {
286 const half_float(*rowA
)[3] = (const half_float(*)[3]) srcRowA
;
287 const half_float(*rowB
)[3] = (const half_float(*)[3]) srcRowB
;
288 half_float(*dst
)[3] = (half_float(*)[3]) dstRow
;
289 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
290 i
++, j
+= colStride
, k
+= colStride
) {
291 for (comp
= 0; comp
< 3; comp
++) {
292 float aj
, ak
, bj
, bk
;
293 aj
= half_to_float(rowA
[j
][comp
]);
294 ak
= half_to_float(rowA
[k
][comp
]);
295 bj
= half_to_float(rowB
[j
][comp
]);
296 bk
= half_to_float(rowB
[k
][comp
]);
297 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
301 else if (datatype
== HALF_FLOAT
&& comps
== 2) {
303 const half_float(*rowA
)[2] = (const half_float(*)[2]) srcRowA
;
304 const half_float(*rowB
)[2] = (const half_float(*)[2]) srcRowB
;
305 half_float(*dst
)[2] = (half_float(*)[2]) dstRow
;
306 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
307 i
++, j
+= colStride
, k
+= colStride
) {
308 for (comp
= 0; comp
< 2; comp
++) {
309 float aj
, ak
, bj
, bk
;
310 aj
= half_to_float(rowA
[j
][comp
]);
311 ak
= half_to_float(rowA
[k
][comp
]);
312 bj
= half_to_float(rowB
[j
][comp
]);
313 bk
= half_to_float(rowB
[k
][comp
]);
314 dst
[i
][comp
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
318 else if (datatype
== HALF_FLOAT
&& comps
== 1) {
320 const half_float
*rowA
= (const half_float
*) srcRowA
;
321 const half_float
*rowB
= (const half_float
*) srcRowB
;
322 half_float
*dst
= (half_float
*) dstRow
;
323 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
324 i
++, j
+= colStride
, k
+= colStride
) {
325 float aj
, ak
, bj
, bk
;
326 aj
= half_to_float(rowA
[j
]);
327 ak
= half_to_float(rowA
[k
]);
328 bj
= half_to_float(rowB
[j
]);
329 bk
= half_to_float(rowB
[k
]);
330 dst
[i
] = float_to_half((aj
+ ak
+ bj
+ bk
) * 0.25F
);
335 else if (datatype
== UINT
&& comps
== 1) {
337 const uint
*rowA
= (const uint
*) srcRowA
;
338 const uint
*rowB
= (const uint
*) srcRowB
;
339 uint
*dst
= (uint
*) dstRow
;
340 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
341 i
++, j
+= colStride
, k
+= colStride
) {
342 dst
[i
] = rowA
[j
] / 4 + rowA
[k
] / 4 + rowB
[j
] / 4 + rowB
[k
] / 4;
346 else if (datatype
== USHORT_5_6_5
&& comps
== 3) {
348 const ushort
*rowA
= (const ushort
*) srcRowA
;
349 const ushort
*rowB
= (const ushort
*) srcRowB
;
350 ushort
*dst
= (ushort
*) dstRow
;
351 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
352 i
++, j
+= colStride
, k
+= colStride
) {
353 const int rowAr0
= rowA
[j
] & 0x1f;
354 const int rowAr1
= rowA
[k
] & 0x1f;
355 const int rowBr0
= rowB
[j
] & 0x1f;
356 const int rowBr1
= rowB
[k
] & 0x1f;
357 const int rowAg0
= (rowA
[j
] >> 5) & 0x3f;
358 const int rowAg1
= (rowA
[k
] >> 5) & 0x3f;
359 const int rowBg0
= (rowB
[j
] >> 5) & 0x3f;
360 const int rowBg1
= (rowB
[k
] >> 5) & 0x3f;
361 const int rowAb0
= (rowA
[j
] >> 11) & 0x1f;
362 const int rowAb1
= (rowA
[k
] >> 11) & 0x1f;
363 const int rowBb0
= (rowB
[j
] >> 11) & 0x1f;
364 const int rowBb1
= (rowB
[k
] >> 11) & 0x1f;
365 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
366 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
367 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
368 dst
[i
] = (blue
<< 11) | (green
<< 5) | red
;
371 else if (datatype
== USHORT_4_4_4_4
&& comps
== 4) {
373 const ushort
*rowA
= (const ushort
*) srcRowA
;
374 const ushort
*rowB
= (const ushort
*) srcRowB
;
375 ushort
*dst
= (ushort
*) dstRow
;
376 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
377 i
++, j
+= colStride
, k
+= colStride
) {
378 const int rowAr0
= rowA
[j
] & 0xf;
379 const int rowAr1
= rowA
[k
] & 0xf;
380 const int rowBr0
= rowB
[j
] & 0xf;
381 const int rowBr1
= rowB
[k
] & 0xf;
382 const int rowAg0
= (rowA
[j
] >> 4) & 0xf;
383 const int rowAg1
= (rowA
[k
] >> 4) & 0xf;
384 const int rowBg0
= (rowB
[j
] >> 4) & 0xf;
385 const int rowBg1
= (rowB
[k
] >> 4) & 0xf;
386 const int rowAb0
= (rowA
[j
] >> 8) & 0xf;
387 const int rowAb1
= (rowA
[k
] >> 8) & 0xf;
388 const int rowBb0
= (rowB
[j
] >> 8) & 0xf;
389 const int rowBb1
= (rowB
[k
] >> 8) & 0xf;
390 const int rowAa0
= (rowA
[j
] >> 12) & 0xf;
391 const int rowAa1
= (rowA
[k
] >> 12) & 0xf;
392 const int rowBa0
= (rowB
[j
] >> 12) & 0xf;
393 const int rowBa1
= (rowB
[k
] >> 12) & 0xf;
394 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
395 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
396 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
397 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
398 dst
[i
] = (alpha
<< 12) | (blue
<< 8) | (green
<< 4) | red
;
401 else if (datatype
== USHORT_1_5_5_5_REV
&& comps
== 4) {
403 const ushort
*rowA
= (const ushort
*) srcRowA
;
404 const ushort
*rowB
= (const ushort
*) srcRowB
;
405 ushort
*dst
= (ushort
*) dstRow
;
406 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
407 i
++, j
+= colStride
, k
+= colStride
) {
408 const int rowAr0
= rowA
[j
] & 0x1f;
409 const int rowAr1
= rowA
[k
] & 0x1f;
410 const int rowBr0
= rowB
[j
] & 0x1f;
411 const int rowBr1
= rowB
[k
] & 0xf;
412 const int rowAg0
= (rowA
[j
] >> 5) & 0x1f;
413 const int rowAg1
= (rowA
[k
] >> 5) & 0x1f;
414 const int rowBg0
= (rowB
[j
] >> 5) & 0x1f;
415 const int rowBg1
= (rowB
[k
] >> 5) & 0x1f;
416 const int rowAb0
= (rowA
[j
] >> 10) & 0x1f;
417 const int rowAb1
= (rowA
[k
] >> 10) & 0x1f;
418 const int rowBb0
= (rowB
[j
] >> 10) & 0x1f;
419 const int rowBb1
= (rowB
[k
] >> 10) & 0x1f;
420 const int rowAa0
= (rowA
[j
] >> 15) & 0x1;
421 const int rowAa1
= (rowA
[k
] >> 15) & 0x1;
422 const int rowBa0
= (rowB
[j
] >> 15) & 0x1;
423 const int rowBa1
= (rowB
[k
] >> 15) & 0x1;
424 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
425 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
426 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
427 const int alpha
= (rowAa0
+ rowAa1
+ rowBa0
+ rowBa1
) >> 2;
428 dst
[i
] = (alpha
<< 15) | (blue
<< 10) | (green
<< 5) | red
;
431 else if (datatype
== UBYTE_3_3_2
&& comps
== 3) {
433 const ubyte
*rowA
= (const ubyte
*) srcRowA
;
434 const ubyte
*rowB
= (const ubyte
*) srcRowB
;
435 ubyte
*dst
= (ubyte
*) dstRow
;
436 for (i
= j
= 0, k
= k0
; i
< (uint
) dstWidth
;
437 i
++, j
+= colStride
, k
+= colStride
) {
438 const int rowAr0
= rowA
[j
] & 0x3;
439 const int rowAr1
= rowA
[k
] & 0x3;
440 const int rowBr0
= rowB
[j
] & 0x3;
441 const int rowBr1
= rowB
[k
] & 0x3;
442 const int rowAg0
= (rowA
[j
] >> 2) & 0x7;
443 const int rowAg1
= (rowA
[k
] >> 2) & 0x7;
444 const int rowBg0
= (rowB
[j
] >> 2) & 0x7;
445 const int rowBg1
= (rowB
[k
] >> 2) & 0x7;
446 const int rowAb0
= (rowA
[j
] >> 5) & 0x7;
447 const int rowAb1
= (rowA
[k
] >> 5) & 0x7;
448 const int rowBb0
= (rowB
[j
] >> 5) & 0x7;
449 const int rowBb1
= (rowB
[k
] >> 5) & 0x7;
450 const int red
= (rowAr0
+ rowAr1
+ rowBr0
+ rowBr1
) >> 2;
451 const int green
= (rowAg0
+ rowAg1
+ rowBg0
+ rowBg1
) >> 2;
452 const int blue
= (rowAb0
+ rowAb1
+ rowBb0
+ rowBb1
) >> 2;
453 dst
[i
] = (blue
<< 5) | (green
<< 2) | red
;
457 debug_printf("bad format in do_row()");
463 format_to_type_comps(enum pipe_format pformat
,
464 enum dtype
*datatype
, uint
*comps
)
467 case PIPE_FORMAT_A8R8G8B8_UNORM
:
468 case PIPE_FORMAT_B8G8R8A8_UNORM
:
472 case PIPE_FORMAT_A1R5G5B5_UNORM
:
473 *datatype
= USHORT_1_5_5_5_REV
;
476 case PIPE_FORMAT_A4R4G4B4_UNORM
:
477 *datatype
= USHORT_4_4_4_4
;
480 case PIPE_FORMAT_R5G6B5_UNORM
:
481 *datatype
= USHORT_5_6_5
;
484 case PIPE_FORMAT_U_L8
:
485 case PIPE_FORMAT_U_A8
:
486 case PIPE_FORMAT_U_I8
:
490 case PIPE_FORMAT_U_A8_L8
:
501 reduce_1d(enum pipe_format pformat
,
502 int srcWidth
, const ubyte
*srcPtr
,
503 int dstWidth
, ubyte
*dstPtr
)
508 format_to_type_comps(pformat
, &datatype
, &comps
);
510 /* we just duplicate the input row, kind of hack, saves code */
511 do_row(datatype
, comps
,
512 srcWidth
, srcPtr
, srcPtr
,
518 * Strides are in bytes. If zero, it'll be computed as width * bpp.
521 reduce_2d(enum pipe_format pformat
,
522 int srcWidth
, int srcHeight
,
523 int srcRowStride
, const ubyte
*srcPtr
,
524 int dstWidth
, int dstHeight
,
525 int dstRowStride
, ubyte
*dstPtr
)
529 const int bpt
= pf_get_size(pformat
);
530 const ubyte
*srcA
, *srcB
;
534 format_to_type_comps(pformat
, &datatype
, &comps
);
537 srcRowStride
= bpt
* srcWidth
;
540 dstRowStride
= bpt
* dstWidth
;
542 /* Compute src and dst pointers */
545 srcB
= srcA
+ srcRowStride
;
550 for (row
= 0; row
< dstHeight
; row
++) {
551 do_row(datatype
, comps
,
552 srcWidth
, srcA
, srcB
,
554 srcA
+= 2 * srcRowStride
;
555 srcB
+= 2 * srcRowStride
;
562 make_1d_mipmap(struct gen_mipmap_state
*ctx
,
563 struct pipe_texture
*pt
,
564 uint face
, uint baseLevel
, uint lastLevel
)
566 struct pipe_context
*pipe
= ctx
->pipe
;
567 struct pipe_screen
*screen
= pipe
->screen
;
568 struct pipe_winsys
*winsys
= pipe
->winsys
;
569 const uint zslice
= 0;
572 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
573 const uint srcLevel
= dstLevel
- 1;
574 struct pipe_surface
*srcSurf
, *dstSurf
;
575 void *srcMap
, *dstMap
;
577 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
);
578 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
580 srcMap
= ((ubyte
*) winsys
->buffer_map(winsys
, srcSurf
->buffer
,
581 PIPE_BUFFER_USAGE_CPU_READ
)
583 dstMap
= ((ubyte
*) winsys
->buffer_map(winsys
, dstSurf
->buffer
,
584 PIPE_BUFFER_USAGE_CPU_WRITE
)
587 reduce_1d(pt
->format
,
588 srcSurf
->width
, srcMap
,
589 dstSurf
->width
, dstMap
);
591 winsys
->buffer_unmap(winsys
, srcSurf
->buffer
);
592 winsys
->buffer_unmap(winsys
, dstSurf
->buffer
);
594 pipe_surface_reference(&srcSurf
, NULL
);
595 pipe_surface_reference(&dstSurf
, NULL
);
601 make_2d_mipmap(struct gen_mipmap_state
*ctx
,
602 struct pipe_texture
*pt
,
603 uint face
, uint baseLevel
, uint lastLevel
)
605 struct pipe_context
*pipe
= ctx
->pipe
;
606 struct pipe_screen
*screen
= pipe
->screen
;
607 struct pipe_winsys
*winsys
= pipe
->winsys
;
608 const uint zslice
= 0;
610 const int bpt
= pf_get_size(pt
->format
);
612 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
613 const uint srcLevel
= dstLevel
- 1;
614 struct pipe_surface
*srcSurf
, *dstSurf
;
615 ubyte
*srcMap
, *dstMap
;
617 srcSurf
= screen
->get_tex_surface(screen
, pt
, face
, srcLevel
, zslice
);
618 dstSurf
= screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
620 srcMap
= ((ubyte
*) winsys
->buffer_map(winsys
, srcSurf
->buffer
,
621 PIPE_BUFFER_USAGE_CPU_READ
)
623 dstMap
= ((ubyte
*) winsys
->buffer_map(winsys
, dstSurf
->buffer
,
624 PIPE_BUFFER_USAGE_CPU_WRITE
)
627 reduce_2d(pt
->format
,
628 srcSurf
->width
, srcSurf
->height
,
629 srcSurf
->pitch
* bpt
, srcMap
,
630 dstSurf
->width
, dstSurf
->height
,
631 dstSurf
->pitch
* bpt
, dstMap
);
633 winsys
->buffer_unmap(winsys
, srcSurf
->buffer
);
634 winsys
->buffer_unmap(winsys
, dstSurf
->buffer
);
636 pipe_surface_reference(&srcSurf
, NULL
);
637 pipe_surface_reference(&dstSurf
, NULL
);
643 make_3d_mipmap(struct gen_mipmap_state
*ctx
,
644 struct pipe_texture
*pt
,
645 uint face
, uint baseLevel
, uint lastLevel
)
651 fallback_gen_mipmap(struct gen_mipmap_state
*ctx
,
652 struct pipe_texture
*pt
,
653 uint face
, uint baseLevel
, uint lastLevel
)
655 switch (pt
->target
) {
656 case PIPE_TEXTURE_1D
:
657 make_1d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
659 case PIPE_TEXTURE_2D
:
660 case PIPE_TEXTURE_CUBE
:
661 make_2d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
663 case PIPE_TEXTURE_3D
:
664 make_3d_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
673 * Create a mipmap generation context.
674 * The idea is to create one of these and re-use it each time we need to
677 struct gen_mipmap_state
*
678 util_create_gen_mipmap(struct pipe_context
*pipe
)
680 struct pipe_blend_state blend
;
681 struct pipe_depth_stencil_alpha_state depthstencil
;
682 struct pipe_rasterizer_state rasterizer
;
683 struct gen_mipmap_state
*ctx
;
685 ctx
= CALLOC_STRUCT(gen_mipmap_state
);
691 /* we don't use blending, but need to set valid values */
692 memset(&blend
, 0, sizeof(blend
));
693 blend
.rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
694 blend
.alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
695 blend
.rgb_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
696 blend
.alpha_dst_factor
= PIPE_BLENDFACTOR_ZERO
;
697 blend
.colormask
= PIPE_MASK_RGBA
;
698 ctx
->blend
= pipe
->create_blend_state(pipe
, &blend
);
700 /* depth/stencil/alpha */
701 memset(&depthstencil
, 0, sizeof(depthstencil
));
702 ctx
->depthstencil
= pipe
->create_depth_stencil_alpha_state(pipe
, &depthstencil
);
705 memset(&rasterizer
, 0, sizeof(rasterizer
));
706 rasterizer
.front_winding
= PIPE_WINDING_CW
;
707 rasterizer
.cull_mode
= PIPE_WINDING_NONE
;
708 rasterizer
.bypass_clipping
= 1; /* bypasses viewport too */
709 //rasterizer.bypass_vs = 1;
710 ctx
->rasterizer
= pipe
->create_rasterizer_state(pipe
, &rasterizer
);
714 ctx
->viewport
.scale
[0] = 1.0;
715 ctx
->viewport
.scale
[1] = 1.0;
716 ctx
->viewport
.scale
[2] = 1.0;
717 ctx
->viewport
.scale
[3] = 1.0;
718 ctx
->viewport
.translate
[0] = 0.0;
719 ctx
->viewport
.translate
[1] = 0.0;
720 ctx
->viewport
.translate
[2] = 0.0;
721 ctx
->viewport
.translate
[3] = 0.0;
726 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
727 TGSI_SEMANTIC_GENERIC
};
728 const uint semantic_indexes
[] = { 0, 0 };
729 ctx
->vs
= util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
733 /* fragment shader */
734 ctx
->fs
= util_make_fragment_tex_shader(pipe
);
741 * Destroy a mipmap generation context
744 util_destroy_gen_mipmap(struct gen_mipmap_state
*ctx
)
746 struct pipe_context
*pipe
= ctx
->pipe
;
748 pipe
->delete_blend_state(pipe
, ctx
->blend
);
749 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->depthstencil
);
750 pipe
->delete_rasterizer_state(pipe
, ctx
->rasterizer
);
751 pipe
->delete_vs_state(pipe
, ctx
->vs
);
752 pipe
->delete_fs_state(pipe
, ctx
->fs
);
760 simple_viewport(struct pipe_context
*pipe
, uint width
, uint height
)
762 struct pipe_viewport_state vp
;
764 vp
.scale
[0] = 0.5 * width
;
765 vp
.scale
[1] = -0.5 * height
;
768 vp
.translate
[0] = 0.5 * width
;
769 vp
.translate
[1] = 0.5 * height
;
770 vp
.translate
[2] = 0.0;
771 vp
.translate
[3] = 0.0;
773 pipe
->set_viewport_state(pipe
, &vp
);
779 * Generate mipmap images. It's assumed all needed texture memory is
782 * \param pt the texture to generate mipmap levels for
783 * \param face which cube face to generate mipmaps for (0 for non-cube maps)
784 * \param baseLevel the first mipmap level to use as a src
785 * \param lastLevel the last mipmap level to generate
788 util_gen_mipmap(struct gen_mipmap_state
*ctx
,
789 struct pipe_texture
*pt
,
790 uint face
, uint baseLevel
, uint lastLevel
)
792 struct pipe_context
*pipe
= ctx
->pipe
;
793 struct pipe_screen
*screen
= pipe
->screen
;
794 struct pipe_framebuffer_state fb
;
795 struct pipe_sampler_state sampler
;
800 /* check if we can render in the texture's format */
801 if (!screen
->is_format_supported(screen
, pt
->format
, PIPE_SURFACE
)) {
802 fallback_gen_mipmap(ctx
, pt
, face
, baseLevel
, lastLevel
);
806 /* init framebuffer state */
807 memset(&fb
, 0, sizeof(fb
));
811 memset(&sampler
, 0, sizeof(sampler
));
812 sampler
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
813 sampler
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
814 sampler
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
815 sampler
.min_mip_filter
= PIPE_TEX_MIPFILTER_NEAREST
;
816 sampler
.min_img_filter
= PIPE_TEX_FILTER_LINEAR
;
817 sampler
.mag_img_filter
= PIPE_TEX_FILTER_LINEAR
;
818 sampler
.normalized_coords
= 1;
821 pipe
->bind_blend_state(pipe
, ctx
->blend
);
822 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->depthstencil
);
823 pipe
->bind_rasterizer_state(pipe
, ctx
->rasterizer
);
824 pipe
->bind_vs_state(pipe
, ctx
->vs
);
825 pipe
->bind_fs_state(pipe
, ctx
->fs
);
827 pipe
->set_viewport_state(pipe
, &ctx
->viewport
);
831 * XXX for small mipmap levels, it may be faster to use the software
834 for (dstLevel
= baseLevel
+ 1; dstLevel
<= lastLevel
; dstLevel
++) {
835 const uint srcLevel
= dstLevel
- 1;
838 * Setup framebuffer / dest surface
840 fb
.cbufs
[0] = screen
->get_tex_surface(screen
, pt
, face
, dstLevel
, zslice
);
841 pipe
->set_framebuffer_state(pipe
, &fb
);
844 * Setup sampler state
845 * Note: we should only have to set the min/max LOD clamps to ensure
846 * we grab texels from the right mipmap level. But some hardware
847 * has trouble with min clamping so we also set the lod_bias to
848 * try to work around that.
850 sampler
.min_lod
= sampler
.max_lod
= (float) srcLevel
;
851 sampler
.lod_bias
= (float) srcLevel
;
852 sampler_cso
= pipe
->create_sampler_state(pipe
, &sampler
);
853 pipe
->bind_sampler_states(pipe
, 1, &sampler_cso
);
856 simple_viewport(pipe
, pt
->width
[dstLevel
], pt
->height
[dstLevel
]);
859 pipe
->set_sampler_textures(pipe
, 1, &pt
);
861 /* quad coords in window coords (bypassing clipping, viewport mapping) */
862 util_draw_texquad(pipe
,
863 0.0F
, 0.0F
, /* x0, y0 */
864 (float) pt
->width
[dstLevel
], /* x1 */
865 (float) pt
->height
[dstLevel
], /* y1 */
869 pipe
->flush(pipe
, PIPE_FLUSH_WAIT
);
871 /*pipe->texture_update(pipe, pt); not really needed */
873 pipe
->delete_sampler_state(pipe
, sampler_cso
);
876 /* Note: caller must restore pipe/gallium state at this time */