1 /**********************************************************
2 * Copyright 2009-2011 VMware, Inc. All rights reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 *********************************************************
26 * Zack Rusin <zackr-at-vmware-dot-com>
30 #include "pipe/p_format.h"
31 #include "pipe/p_context.h"
32 #include "pipe/p_state.h"
33 #include "pipe/p_shader_tokens.h"
35 #include "util/u_memory.h"
37 #include "tgsi/tgsi_ureg.h"
39 #include "cso_cache/cso_context.h"
40 #include "cso_cache/cso_hash.h"
44 * IN[1] = src tex coord | solid fill color
45 * IN[2] = mask tex coord
46 * IN[3] = dst tex coord
47 * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
48 * CONST[1] = (-1, -1, 0, 0)
51 * OUT[1] = src tex coord
52 * OUT[2] = mask tex coord
53 * OUT[3] = dst tex coord
56 /* Fragment shader. Samplers are allocated when needed.
57 * SAMP[0] = sampler for first texture (src or mask if src is solid)
58 * SAMP[1] = sampler for second texture (mask or none)
59 * IN[0] = first texture coordinates if present
60 * IN[1] = second texture coordinates if present
61 * CONST[0] = Solid color (src if src solid or mask if mask solid
62 * or src in mask if both solid).
68 print_fs_traits(int fs_traits
)
70 const char *strings
[] = {
71 "FS_COMPOSITE", /* = 1 << 0, */
72 "FS_MASK", /* = 1 << 1, */
73 "FS_SRC_SRC", /* = 1 << 2, */
74 "FS_MASK_SRC", /* = 1 << 3, */
75 "FS_YUV", /* = 1 << 4, */
76 "FS_SRC_REPEAT_NONE", /* = 1 << 5, */
77 "FS_MASK_REPEAT_NONE", /* = 1 << 6, */
78 "FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */
79 "FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */
80 "FS_SRC_SET_ALPHA", /* = 1 << 9, */
81 "FS_MASK_SET_ALPHA", /* = 1 << 10, */
82 "FS_SRC_LUMINANCE", /* = 1 << 11, */
83 "FS_MASK_LUMINANCE", /* = 1 << 12, */
84 "FS_DST_LUMINANCE", /* = 1 << 13, */
85 "FS_CA", /* = 1 << 14, */
89 debug_printf("%s: ", __func__
);
91 for (i
= 0, k
= 1; k
< (1 << 16); i
++, k
<<= 1) {
93 debug_printf("%s, ", strings
[i
]);
100 struct xa_context
*r
;
102 struct cso_hash vs_hash
;
103 struct cso_hash fs_hash
;
107 src_in_mask(struct ureg_program
*ureg
,
110 struct ureg_src mask
,
111 unsigned mask_luminance
, boolean component_alpha
)
114 if (component_alpha
) {
115 ureg_MOV(ureg
, dst
, src
);
116 ureg_MUL(ureg
, ureg_writemask(dst
, TGSI_WRITEMASK_W
),
117 src
, ureg_scalar(mask
, TGSI_SWIZZLE_X
));
119 ureg_MUL(ureg
, dst
, src
, ureg_scalar(mask
, TGSI_SWIZZLE_X
));
121 else if (!component_alpha
)
122 ureg_MUL(ureg
, dst
, src
, ureg_scalar(mask
, TGSI_SWIZZLE_W
));
124 ureg_MUL(ureg
, dst
, src
, mask
);
127 static struct ureg_src
128 vs_normalize_coords(struct ureg_program
*ureg
,
129 struct ureg_src coords
,
130 struct ureg_src const0
, struct ureg_src const1
)
132 struct ureg_dst tmp
= ureg_DECL_temporary(ureg
);
135 ureg_MAD(ureg
, tmp
, coords
, const0
, const1
);
137 ureg_release_temporary(ureg
, tmp
);
142 create_vs(struct pipe_context
*pipe
, unsigned vs_traits
)
144 struct ureg_program
*ureg
;
147 struct ureg_src const0
, const1
;
148 boolean is_composite
= (vs_traits
& VS_COMPOSITE
) != 0;
149 boolean has_mask
= (vs_traits
& VS_MASK
) != 0;
150 boolean is_yuv
= (vs_traits
& VS_YUV
) != 0;
151 boolean is_src_src
= (vs_traits
& VS_SRC_SRC
) != 0;
152 boolean is_mask_src
= (vs_traits
& VS_MASK_SRC
) != 0;
153 unsigned input_slot
= 0;
155 ureg
= ureg_create(PIPE_SHADER_VERTEX
);
159 const0
= ureg_DECL_constant(ureg
, 0);
160 const1
= ureg_DECL_constant(ureg
, 1);
162 /* it has to be either a fill or a composite op */
163 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
164 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
165 src
= vs_normalize_coords(ureg
, src
, const0
, const1
);
166 ureg_MOV(ureg
, dst
, src
);
169 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
170 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 0);
171 ureg_MOV(ureg
, dst
, src
);
175 if (!is_src_src
|| (has_mask
&& !is_mask_src
)) {
176 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
177 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 0);
178 ureg_MOV(ureg
, dst
, src
);
181 if (!is_src_src
&& (has_mask
&& !is_mask_src
)) {
182 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
183 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 1);
184 ureg_MOV(ureg
, dst
, src
);
190 return ureg_create_shader_and_destroy(ureg
, pipe
);
194 create_yuv_shader(struct pipe_context
*pipe
, struct ureg_program
*ureg
)
196 struct ureg_src y_sampler
, u_sampler
, v_sampler
;
198 struct ureg_src matrow0
, matrow1
, matrow2
, matrow3
;
199 struct ureg_dst y
, u
, v
, rgb
;
200 struct ureg_dst out
= ureg_DECL_output(ureg
,
204 pos
= ureg_DECL_fs_input(ureg
,
205 TGSI_SEMANTIC_GENERIC
, 0,
206 TGSI_INTERPOLATE_PERSPECTIVE
);
208 rgb
= ureg_DECL_temporary(ureg
);
209 y
= ureg_DECL_temporary(ureg
);
210 u
= ureg_DECL_temporary(ureg
);
211 v
= ureg_DECL_temporary(ureg
);
213 y_sampler
= ureg_DECL_sampler(ureg
, 0);
214 u_sampler
= ureg_DECL_sampler(ureg
, 1);
215 v_sampler
= ureg_DECL_sampler(ureg
, 2);
217 ureg_DECL_sampler_view(ureg
, 0, TGSI_TEXTURE_2D
,
218 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
,
219 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
);
220 ureg_DECL_sampler_view(ureg
, 1, TGSI_TEXTURE_2D
,
221 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
,
222 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
);
223 ureg_DECL_sampler_view(ureg
, 2, TGSI_TEXTURE_2D
,
224 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
,
225 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
);
227 matrow0
= ureg_DECL_constant(ureg
, 0);
228 matrow1
= ureg_DECL_constant(ureg
, 1);
229 matrow2
= ureg_DECL_constant(ureg
, 2);
230 matrow3
= ureg_DECL_constant(ureg
, 3);
232 ureg_TEX(ureg
, y
, TGSI_TEXTURE_2D
, pos
, y_sampler
);
233 ureg_TEX(ureg
, u
, TGSI_TEXTURE_2D
, pos
, u_sampler
);
234 ureg_TEX(ureg
, v
, TGSI_TEXTURE_2D
, pos
, v_sampler
);
236 ureg_MOV(ureg
, rgb
, matrow3
);
238 ureg_scalar(ureg_src(y
), TGSI_SWIZZLE_X
), matrow0
, ureg_src(rgb
));
240 ureg_scalar(ureg_src(u
), TGSI_SWIZZLE_X
), matrow1
, ureg_src(rgb
));
242 ureg_scalar(ureg_src(v
), TGSI_SWIZZLE_X
), matrow2
, ureg_src(rgb
));
244 ureg_MOV(ureg
, out
, ureg_src(rgb
));
246 ureg_release_temporary(ureg
, rgb
);
247 ureg_release_temporary(ureg
, y
);
248 ureg_release_temporary(ureg
, u
);
249 ureg_release_temporary(ureg
, v
);
253 return ureg_create_shader_and_destroy(ureg
, pipe
);
257 xrender_tex(struct ureg_program
*ureg
,
259 struct ureg_src coords
,
260 struct ureg_src sampler
,
261 const struct ureg_src
*imm0
,
262 boolean repeat_none
, boolean swizzle
, boolean set_alpha
)
265 struct ureg_dst tmp0
= ureg_DECL_temporary(ureg
);
266 struct ureg_dst tmp1
= ureg_DECL_temporary(ureg
);
268 ureg_SGT(ureg
, tmp1
, ureg_swizzle(coords
,
272 TGSI_SWIZZLE_Y
), ureg_scalar(*imm0
,
275 ureg_swizzle(coords
, TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
,
276 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
), ureg_scalar(*imm0
,
278 ureg_MIN(ureg
, tmp0
, ureg_src(tmp0
), ureg_src(tmp1
));
279 ureg_MIN(ureg
, tmp0
, ureg_scalar(ureg_src(tmp0
), TGSI_SWIZZLE_X
),
280 ureg_scalar(ureg_src(tmp0
), TGSI_SWIZZLE_Y
));
281 ureg_TEX(ureg
, tmp1
, TGSI_TEXTURE_2D
, coords
, sampler
);
283 ureg_MOV(ureg
, tmp1
, ureg_swizzle(ureg_src(tmp1
),
285 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_X
,
289 ureg_writemask(tmp1
, TGSI_WRITEMASK_W
),
290 ureg_scalar(*imm0
, TGSI_SWIZZLE_W
));
291 ureg_MUL(ureg
, dst
, ureg_src(tmp1
), ureg_src(tmp0
));
292 ureg_release_temporary(ureg
, tmp0
);
293 ureg_release_temporary(ureg
, tmp1
);
296 struct ureg_dst tmp
= ureg_DECL_temporary(ureg
);
298 ureg_TEX(ureg
, tmp
, TGSI_TEXTURE_2D
, coords
, sampler
);
299 ureg_MOV(ureg
, dst
, ureg_swizzle(ureg_src(tmp
),
301 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_X
,
303 ureg_release_temporary(ureg
, tmp
);
305 ureg_TEX(ureg
, dst
, TGSI_TEXTURE_2D
, coords
, sampler
);
309 ureg_writemask(dst
, TGSI_WRITEMASK_W
),
310 ureg_scalar(*imm0
, TGSI_SWIZZLE_W
));
315 read_input(struct ureg_program
*ureg
,
317 const struct ureg_src
*imm0
,
318 boolean repeat_none
, boolean swizzle
, boolean set_alpha
,
319 boolean is_src
, unsigned *cur_constant
, unsigned *cur_sampler
)
321 struct ureg_src input
, sampler
;
324 input
= ureg_DECL_constant(ureg
, (*cur_constant
)++);
325 ureg_MOV(ureg
, dst
, input
);
327 sampler
= ureg_DECL_sampler(ureg
, *cur_sampler
);
328 ureg_DECL_sampler_view(ureg
, *cur_sampler
, TGSI_TEXTURE_2D
,
329 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
,
330 TGSI_RETURN_TYPE_FLOAT
, TGSI_RETURN_TYPE_FLOAT
);
331 input
= ureg_DECL_fs_input(ureg
,
332 TGSI_SEMANTIC_GENERIC
, (*cur_sampler
)++,
333 TGSI_INTERPOLATE_PERSPECTIVE
);
334 xrender_tex(ureg
, dst
, input
, sampler
, imm0
,
335 repeat_none
, swizzle
, set_alpha
);
340 create_fs(struct pipe_context
*pipe
, unsigned fs_traits
)
342 struct ureg_program
*ureg
;
343 struct ureg_dst src
, mask
;
345 struct ureg_src imm0
= { 0 };
346 unsigned has_mask
= (fs_traits
& FS_MASK
) != 0;
347 unsigned is_yuv
= (fs_traits
& FS_YUV
) != 0;
348 unsigned src_repeat_none
= (fs_traits
& FS_SRC_REPEAT_NONE
) != 0;
349 unsigned mask_repeat_none
= (fs_traits
& FS_MASK_REPEAT_NONE
) != 0;
350 unsigned src_swizzle
= (fs_traits
& FS_SRC_SWIZZLE_RGB
) != 0;
351 unsigned mask_swizzle
= (fs_traits
& FS_MASK_SWIZZLE_RGB
) != 0;
352 unsigned src_set_alpha
= (fs_traits
& FS_SRC_SET_ALPHA
) != 0;
353 unsigned mask_set_alpha
= (fs_traits
& FS_MASK_SET_ALPHA
) != 0;
354 unsigned src_luminance
= (fs_traits
& FS_SRC_LUMINANCE
) != 0;
355 unsigned mask_luminance
= (fs_traits
& FS_MASK_LUMINANCE
) != 0;
356 unsigned dst_luminance
= (fs_traits
& FS_DST_LUMINANCE
) != 0;
357 unsigned is_src_src
= (fs_traits
& FS_SRC_SRC
) != 0;
358 unsigned is_mask_src
= (fs_traits
& FS_MASK_SRC
) != 0;
359 boolean component_alpha
= (fs_traits
& FS_CA
) != 0;
360 unsigned cur_sampler
= 0;
361 unsigned cur_constant
= 0;
364 print_fs_traits(fs_traits
);
366 (void)print_fs_traits
;
369 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
374 return create_yuv_shader(pipe
, ureg
);
376 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
378 if (src_repeat_none
|| mask_repeat_none
||
379 src_set_alpha
|| mask_set_alpha
|| src_luminance
) {
380 imm0
= ureg_imm4f(ureg
, 0, 0, 0, 1);
383 src
= (has_mask
|| src_luminance
|| dst_luminance
) ?
384 ureg_DECL_temporary(ureg
) : out
;
386 read_input(ureg
, src
, &imm0
, src_repeat_none
, src_swizzle
,
387 src_set_alpha
, is_src_src
, &cur_constant
, &cur_sampler
);
390 ureg_MOV(ureg
, src
, ureg_scalar(ureg_src(src
), TGSI_SWIZZLE_X
));
391 ureg_MOV(ureg
, ureg_writemask(src
, TGSI_WRITEMASK_XYZ
),
392 ureg_scalar(imm0
, TGSI_SWIZZLE_X
));
393 if (!has_mask
&& !dst_luminance
)
394 ureg_MOV(ureg
, out
, ureg_src(src
));
398 mask
= ureg_DECL_temporary(ureg
);
399 read_input(ureg
, mask
, &imm0
, mask_repeat_none
,
400 mask_swizzle
, mask_set_alpha
, is_mask_src
, &cur_constant
,
403 src_in_mask(ureg
, (dst_luminance
) ? src
: out
, ureg_src(src
),
404 ureg_src(mask
), mask_luminance
, component_alpha
);
406 ureg_release_temporary(ureg
, mask
);
411 * Make sure the alpha channel goes into the output L8 surface.
413 ureg_MOV(ureg
, out
, ureg_scalar(ureg_src(src
), TGSI_SWIZZLE_W
));
418 return ureg_create_shader_and_destroy(ureg
, pipe
);
422 xa_shaders_create(struct xa_context
*r
)
424 struct xa_shaders
*sc
= CALLOC_STRUCT(xa_shaders
);
427 cso_hash_init(&sc
->vs_hash
);
428 cso_hash_init(&sc
->fs_hash
);
434 cache_destroy(struct pipe_context
*pipe
,
435 struct cso_hash
*hash
, unsigned processor
)
437 struct cso_hash_iter iter
= cso_hash_first_node(hash
);
439 while (!cso_hash_iter_is_null(iter
)) {
440 void *shader
= (void *)cso_hash_iter_data(iter
);
442 if (processor
== PIPE_SHADER_FRAGMENT
) {
443 pipe
->delete_fs_state(pipe
, shader
);
444 } else if (processor
== PIPE_SHADER_VERTEX
) {
445 pipe
->delete_vs_state(pipe
, shader
);
447 iter
= cso_hash_erase(hash
, iter
);
449 cso_hash_deinit(hash
);
453 xa_shaders_destroy(struct xa_shaders
*sc
)
455 cache_destroy(sc
->r
->pipe
, &sc
->vs_hash
, PIPE_SHADER_VERTEX
);
456 cache_destroy(sc
->r
->pipe
, &sc
->fs_hash
, PIPE_SHADER_FRAGMENT
);
462 shader_from_cache(struct pipe_context
*pipe
,
463 unsigned type
, struct cso_hash
*hash
, unsigned key
)
467 struct cso_hash_iter iter
= cso_hash_find(hash
, key
);
469 if (cso_hash_iter_is_null(iter
)) {
470 if (type
== PIPE_SHADER_VERTEX
)
471 shader
= create_vs(pipe
, key
);
473 shader
= create_fs(pipe
, key
);
474 cso_hash_insert(hash
, key
, shader
);
476 shader
= (void *)cso_hash_iter_data(iter
);
482 xa_shaders_get(struct xa_shaders
*sc
, unsigned vs_traits
, unsigned fs_traits
)
484 struct xa_shader shader
= { NULL
, NULL
};
487 vs
= shader_from_cache(sc
->r
->pipe
, PIPE_SHADER_VERTEX
,
488 &sc
->vs_hash
, vs_traits
);
489 fs
= shader_from_cache(sc
->r
->pipe
, PIPE_SHADER_FRAGMENT
,
490 &sc
->fs_hash
, fs_traits
);
492 debug_assert(vs
&& fs
);