1 #include "xorg_exa_tgsi.h"
3 /*### stupidity defined in X11/extensions/XI.h */
6 #include "pipe/p_format.h"
7 #include "pipe/p_context.h"
8 #include "pipe/p_state.h"
9 #include "pipe/p_inlines.h"
10 #include "pipe/p_shader_tokens.h"
12 #include "util/u_memory.h"
13 #include "util/u_simple_shaders.h"
15 #include "tgsi/tgsi_ureg.h"
17 #include "cso_cache/cso_context.h"
18 #include "cso_cache/cso_hash.h"
22 * IN[1] = src tex coord | solid fill color
23 * IN[2] = mask tex coord
24 * IN[3] = dst tex coord
25 * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
26 * CONST[1] = (-1, -1, 0, 0)
29 * OUT[1] = src tex coord | solid fill color
30 * OUT[2] = mask tex coord
31 * OUT[3] = dst tex coord
38 * IN[0] = pos src | solid fill color
41 * CONST[0] = (0, 0, 0, 1)
47 struct xorg_renderer
*r
;
49 struct cso_hash
*vs_hash
;
50 struct cso_hash
*fs_hash
;
54 src_in_mask(struct ureg_program
*ureg
,
60 if (component_alpha
== FS_CA_FULL
) {
61 ureg_MUL(ureg
, dst
, src
, mask
);
62 } else if (component_alpha
== FS_CA_SRCALPHA
) {
64 ureg_scalar(src
, TGSI_SWIZZLE_W
), mask
);
67 ureg_MUL(ureg
, dst
, src
,
68 ureg_scalar(mask
, TGSI_SWIZZLE_X
));
72 static struct ureg_src
73 vs_normalize_coords(struct ureg_program
*ureg
, struct ureg_src coords
,
74 struct ureg_src const0
, struct ureg_src const1
)
76 struct ureg_dst tmp
= ureg_DECL_temporary(ureg
);
78 ureg_MAD(ureg
, tmp
, coords
, const0
, const1
);
80 ureg_release_temporary(ureg
, tmp
);
85 linear_gradient(struct ureg_program
*ureg
,
88 struct ureg_src sampler
,
89 struct ureg_src coords
,
90 struct ureg_src const0124
,
91 struct ureg_src matrow0
,
92 struct ureg_src matrow1
,
93 struct ureg_src matrow2
)
95 struct ureg_dst temp0
= ureg_DECL_temporary(ureg
);
96 struct ureg_dst temp1
= ureg_DECL_temporary(ureg
);
97 struct ureg_dst temp2
= ureg_DECL_temporary(ureg
);
98 struct ureg_dst temp3
= ureg_DECL_temporary(ureg
);
99 struct ureg_dst temp4
= ureg_DECL_temporary(ureg
);
100 struct ureg_dst temp5
= ureg_DECL_temporary(ureg
);
103 ureg_writemask(temp0
, TGSI_WRITEMASK_XY
), pos
);
105 ureg_writemask(temp0
, TGSI_WRITEMASK_Z
),
106 ureg_scalar(const0124
, TGSI_SWIZZLE_Y
));
108 ureg_DP3(ureg
, temp1
, matrow0
, ureg_src(temp0
));
109 ureg_DP3(ureg
, temp2
, matrow1
, ureg_src(temp0
));
110 ureg_DP3(ureg
, temp3
, matrow2
, ureg_src(temp0
));
111 ureg_RCP(ureg
, temp3
, ureg_src(temp3
));
112 ureg_MUL(ureg
, temp1
, ureg_src(temp1
), ureg_src(temp3
));
113 ureg_MUL(ureg
, temp2
, ureg_src(temp2
), ureg_src(temp3
));
115 ureg_MOV(ureg
, ureg_writemask(temp4
, TGSI_WRITEMASK_X
),
117 ureg_MOV(ureg
, ureg_writemask(temp4
, TGSI_WRITEMASK_Y
),
120 ureg_MUL(ureg
, temp0
,
121 ureg_scalar(coords
, TGSI_SWIZZLE_Y
),
122 ureg_scalar(ureg_src(temp4
), TGSI_SWIZZLE_Y
));
123 ureg_MAD(ureg
, temp1
,
124 ureg_scalar(coords
, TGSI_SWIZZLE_X
),
125 ureg_scalar(ureg_src(temp4
), TGSI_SWIZZLE_X
),
128 ureg_MUL(ureg
, temp2
,
130 ureg_scalar(coords
, TGSI_SWIZZLE_Z
));
133 TGSI_TEXTURE_1D
, ureg_src(temp2
), sampler
);
135 ureg_release_temporary(ureg
, temp0
);
136 ureg_release_temporary(ureg
, temp1
);
137 ureg_release_temporary(ureg
, temp2
);
138 ureg_release_temporary(ureg
, temp3
);
139 ureg_release_temporary(ureg
, temp4
);
140 ureg_release_temporary(ureg
, temp5
);
145 radial_gradient(struct ureg_program
*ureg
,
148 struct ureg_src sampler
,
149 struct ureg_src coords
,
150 struct ureg_src const0124
,
151 struct ureg_src matrow0
,
152 struct ureg_src matrow1
,
153 struct ureg_src matrow2
)
155 struct ureg_dst temp0
= ureg_DECL_temporary(ureg
);
156 struct ureg_dst temp1
= ureg_DECL_temporary(ureg
);
157 struct ureg_dst temp2
= ureg_DECL_temporary(ureg
);
158 struct ureg_dst temp3
= ureg_DECL_temporary(ureg
);
159 struct ureg_dst temp4
= ureg_DECL_temporary(ureg
);
160 struct ureg_dst temp5
= ureg_DECL_temporary(ureg
);
163 ureg_writemask(temp0
, TGSI_WRITEMASK_XY
),
166 ureg_writemask(temp0
, TGSI_WRITEMASK_Z
),
167 ureg_scalar(const0124
, TGSI_SWIZZLE_Y
));
169 ureg_DP3(ureg
, temp1
, matrow0
, ureg_src(temp0
));
170 ureg_DP3(ureg
, temp2
, matrow1
, ureg_src(temp0
));
171 ureg_DP3(ureg
, temp3
, matrow2
, ureg_src(temp0
));
172 ureg_RCP(ureg
, temp3
, ureg_src(temp3
));
173 ureg_MUL(ureg
, temp1
, ureg_src(temp1
), ureg_src(temp3
));
174 ureg_MUL(ureg
, temp2
, ureg_src(temp2
), ureg_src(temp3
));
176 ureg_MOV(ureg
, ureg_writemask(temp5
, TGSI_WRITEMASK_X
),
178 ureg_MOV(ureg
, ureg_writemask(temp5
, TGSI_WRITEMASK_Y
),
181 ureg_MUL(ureg
, temp0
, ureg_scalar(coords
, TGSI_SWIZZLE_Y
),
182 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_Y
));
183 ureg_MAD(ureg
, temp1
,
184 ureg_scalar(coords
, TGSI_SWIZZLE_X
),
185 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_X
),
187 ureg_ADD(ureg
, temp1
,
188 ureg_src(temp1
), ureg_src(temp1
));
189 ureg_MUL(ureg
, temp3
,
190 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_Y
),
191 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_Y
));
192 ureg_MAD(ureg
, temp4
,
193 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_X
),
194 ureg_scalar(ureg_src(temp5
), TGSI_SWIZZLE_X
),
196 ureg_MOV(ureg
, temp4
, ureg_negate(ureg_src(temp4
)));
197 ureg_MUL(ureg
, temp2
,
198 ureg_scalar(coords
, TGSI_SWIZZLE_Z
),
200 ureg_MUL(ureg
, temp0
,
201 ureg_scalar(const0124
, TGSI_SWIZZLE_W
),
203 ureg_MUL(ureg
, temp3
,
204 ureg_src(temp1
), ureg_src(temp1
));
205 ureg_SUB(ureg
, temp2
,
206 ureg_src(temp3
), ureg_src(temp0
));
207 ureg_RSQ(ureg
, temp2
, ureg_abs(ureg_src(temp2
)));
208 ureg_RCP(ureg
, temp2
, ureg_src(temp2
));
209 ureg_SUB(ureg
, temp1
,
210 ureg_src(temp2
), ureg_src(temp1
));
211 ureg_ADD(ureg
, temp0
,
212 ureg_scalar(coords
, TGSI_SWIZZLE_Z
),
213 ureg_scalar(coords
, TGSI_SWIZZLE_Z
));
214 ureg_RCP(ureg
, temp0
, ureg_src(temp0
));
215 ureg_MUL(ureg
, temp2
,
216 ureg_src(temp1
), ureg_src(temp0
));
217 ureg_TEX(ureg
, out
, TGSI_TEXTURE_1D
,
218 ureg_src(temp2
), sampler
);
220 ureg_release_temporary(ureg
, temp0
);
221 ureg_release_temporary(ureg
, temp1
);
222 ureg_release_temporary(ureg
, temp2
);
223 ureg_release_temporary(ureg
, temp3
);
224 ureg_release_temporary(ureg
, temp4
);
225 ureg_release_temporary(ureg
, temp5
);
229 create_vs(struct pipe_context
*pipe
,
232 struct ureg_program
*ureg
;
235 struct ureg_src const0
, const1
;
236 boolean is_fill
= (vs_traits
& VS_FILL
) != 0;
237 boolean is_composite
= (vs_traits
& VS_COMPOSITE
) != 0;
238 boolean has_mask
= (vs_traits
& VS_MASK
) != 0;
239 boolean is_yuv
= (vs_traits
& VS_YUV
) != 0;
240 unsigned input_slot
= 0;
242 ureg
= ureg_create(TGSI_PROCESSOR_VERTEX
);
246 const0
= ureg_DECL_constant(ureg
, 0);
247 const1
= ureg_DECL_constant(ureg
, 1);
249 /* it has to be either a fill or a composite op */
250 debug_assert((is_fill
^ is_composite
) ^ is_yuv
);
252 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
253 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
254 src
= vs_normalize_coords(ureg
, src
,
256 ureg_MOV(ureg
, dst
, src
);
259 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
260 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 0);
261 ureg_MOV(ureg
, dst
, src
);
265 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
266 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 0);
267 ureg_MOV(ureg
, dst
, src
);
271 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
272 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
273 ureg_MOV(ureg
, dst
, src
);
277 src
= ureg_DECL_vs_input(ureg
, input_slot
++);
278 dst
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_GENERIC
, 1);
279 ureg_MOV(ureg
, dst
, src
);
284 return ureg_create_shader_and_destroy(ureg
, pipe
);
288 create_yuv_shader(struct pipe_context
*pipe
, struct ureg_program
*ureg
)
290 struct ureg_src y_sampler
, u_sampler
, v_sampler
;
292 struct ureg_src matrow0
, matrow1
, matrow2
;
293 struct ureg_dst y
, u
, v
, rgb
;
294 struct ureg_dst out
= ureg_DECL_output(ureg
,
298 pos
= ureg_DECL_fs_input(ureg
,
299 TGSI_SEMANTIC_GENERIC
,
301 TGSI_INTERPOLATE_PERSPECTIVE
);
303 rgb
= ureg_DECL_temporary(ureg
);
304 y
= ureg_DECL_temporary(ureg
);
305 u
= ureg_DECL_temporary(ureg
);
306 v
= ureg_DECL_temporary(ureg
);
308 y_sampler
= ureg_DECL_sampler(ureg
, 0);
309 u_sampler
= ureg_DECL_sampler(ureg
, 1);
310 v_sampler
= ureg_DECL_sampler(ureg
, 2);
312 matrow0
= ureg_DECL_constant(ureg
, 0);
313 matrow1
= ureg_DECL_constant(ureg
, 1);
314 matrow2
= ureg_DECL_constant(ureg
, 2);
317 TGSI_TEXTURE_2D
, pos
, y_sampler
);
319 TGSI_TEXTURE_2D
, pos
, u_sampler
);
321 TGSI_TEXTURE_2D
, pos
, v_sampler
);
323 ureg_SUB(ureg
, u
, ureg_src(u
),
324 ureg_scalar(matrow0
, TGSI_SWIZZLE_W
));
325 ureg_SUB(ureg
, v
, ureg_src(v
),
326 ureg_scalar(matrow0
, TGSI_SWIZZLE_W
));
329 ureg_scalar(ureg_src(y
), TGSI_SWIZZLE_X
),
332 ureg_scalar(ureg_src(u
), TGSI_SWIZZLE_X
),
336 ureg_scalar(ureg_src(v
), TGSI_SWIZZLE_X
),
341 ureg_MOV(ureg
, ureg_writemask(rgb
, TGSI_WRITEMASK_W
),
342 ureg_scalar(matrow0
, TGSI_SWIZZLE_X
));
344 ureg_MOV(ureg
, out
, ureg_src(rgb
));
346 ureg_release_temporary(ureg
, rgb
);
347 ureg_release_temporary(ureg
, y
);
348 ureg_release_temporary(ureg
, u
);
349 ureg_release_temporary(ureg
, v
);
353 return ureg_create_shader_and_destroy(ureg
, pipe
);
358 xrender_tex(struct ureg_program
*ureg
,
360 struct ureg_src coords
,
361 struct ureg_src sampler
,
365 struct ureg_dst tmp0
= ureg_DECL_temporary(ureg
);
366 struct ureg_dst tmp1
= ureg_DECL_temporary(ureg
);
367 struct ureg_src const0
= ureg_DECL_constant(ureg
, 0);
368 ureg_SGT(ureg
, tmp1
, ureg_swizzle(coords
,
373 ureg_scalar(const0
, TGSI_SWIZZLE_X
));
374 ureg_SLT(ureg
, tmp0
, ureg_swizzle(coords
,
379 ureg_scalar(const0
, TGSI_SWIZZLE_W
));
380 ureg_MIN(ureg
, tmp0
, ureg_src(tmp0
), ureg_src(tmp1
));
381 ureg_MIN(ureg
, tmp0
, ureg_scalar(ureg_src(tmp0
), TGSI_SWIZZLE_X
),
382 ureg_scalar(ureg_src(tmp0
), TGSI_SWIZZLE_Y
));
383 ureg_TEX(ureg
, tmp1
, TGSI_TEXTURE_2D
, coords
, sampler
);
384 ureg_MUL(ureg
, dst
, ureg_src(tmp1
), ureg_src(tmp0
));
385 ureg_release_temporary(ureg
, tmp0
);
386 ureg_release_temporary(ureg
, tmp1
);
388 ureg_TEX(ureg
, dst
, TGSI_TEXTURE_2D
, coords
, sampler
);
392 create_fs(struct pipe_context
*pipe
,
395 struct ureg_program
*ureg
;
396 struct ureg_src
/*dst_sampler,*/ src_sampler
, mask_sampler
;
397 struct ureg_src
/*dst_pos,*/ src_input
, mask_pos
;
398 struct ureg_dst src
, mask
;
400 unsigned has_mask
= (fs_traits
& FS_MASK
) != 0;
401 unsigned is_fill
= (fs_traits
& FS_FILL
) != 0;
402 unsigned is_composite
= (fs_traits
& FS_COMPOSITE
) != 0;
403 unsigned is_solid
= (fs_traits
& FS_SOLID_FILL
) != 0;
404 unsigned is_lingrad
= (fs_traits
& FS_LINGRAD_FILL
) != 0;
405 unsigned is_radgrad
= (fs_traits
& FS_RADGRAD_FILL
) != 0;
406 unsigned comp_alpha
= (fs_traits
& FS_COMPONENT_ALPHA
) != 0;
407 unsigned is_yuv
= (fs_traits
& FS_YUV
) != 0;
408 unsigned src_repeat_none
= (fs_traits
& FS_SRC_REPEAT_NONE
) != 0;
409 unsigned mask_repeat_none
= (fs_traits
& FS_MASK_REPEAT_NONE
) != 0;
411 ureg
= ureg_create(TGSI_PROCESSOR_FRAGMENT
);
415 /* it has to be either a fill, a composite op or a yuv conversion */
416 debug_assert((is_fill
^ is_composite
) ^ is_yuv
);
418 out
= ureg_DECL_output(ureg
,
423 src_sampler
= ureg_DECL_sampler(ureg
, 0);
424 src_input
= ureg_DECL_fs_input(ureg
,
425 TGSI_SEMANTIC_GENERIC
,
427 TGSI_INTERPOLATE_PERSPECTIVE
);
428 } else if (is_fill
) {
430 src_input
= ureg_DECL_fs_input(ureg
,
433 TGSI_INTERPOLATE_PERSPECTIVE
);
435 src_input
= ureg_DECL_fs_input(ureg
,
436 TGSI_SEMANTIC_POSITION
,
438 TGSI_INTERPOLATE_PERSPECTIVE
);
440 debug_assert(is_yuv
);
441 return create_yuv_shader(pipe
, ureg
);
445 mask_sampler
= ureg_DECL_sampler(ureg
, 1);
446 mask_pos
= ureg_DECL_fs_input(ureg
,
447 TGSI_SEMANTIC_GENERIC
,
449 TGSI_INTERPOLATE_PERSPECTIVE
);
452 #if 0 /* unused right now */
453 dst_sampler
= ureg_DECL_sampler(ureg
, 2);
454 dst_pos
= ureg_DECL_fs_input(ureg
,
455 TGSI_SEMANTIC_POSITION
,
457 TGSI_INTERPOLATE_PERSPECTIVE
);
462 src
= ureg_DECL_temporary(ureg
);
465 xrender_tex(ureg
, src
, src_input
, src_sampler
,
467 } else if (is_fill
) {
470 src
= ureg_dst(src_input
);
472 ureg_MOV(ureg
, out
, src_input
);
473 } else if (is_lingrad
|| is_radgrad
) {
474 struct ureg_src coords
, const0124
,
475 matrow0
, matrow1
, matrow2
;
478 src
= ureg_DECL_temporary(ureg
);
482 coords
= ureg_DECL_constant(ureg
, 0);
483 const0124
= ureg_DECL_constant(ureg
, 1);
484 matrow0
= ureg_DECL_constant(ureg
, 2);
485 matrow1
= ureg_DECL_constant(ureg
, 3);
486 matrow2
= ureg_DECL_constant(ureg
, 4);
489 linear_gradient(ureg
, src
,
490 src_input
, src_sampler
,
492 matrow0
, matrow1
, matrow2
);
493 } else if (is_radgrad
) {
494 radial_gradient(ureg
, src
,
495 src_input
, src_sampler
,
497 matrow0
, matrow1
, matrow2
);
500 debug_assert(!"Unknown fill type!");
504 mask
= ureg_DECL_temporary(ureg
);
505 xrender_tex(ureg
, mask
, mask_pos
, mask_sampler
,
508 src_in_mask(ureg
, out
, ureg_src(src
), ureg_src(mask
), comp_alpha
);
509 ureg_release_temporary(ureg
, mask
);
514 return ureg_create_shader_and_destroy(ureg
, pipe
);
517 struct xorg_shaders
* xorg_shaders_create(struct xorg_renderer
*r
)
519 struct xorg_shaders
*sc
= CALLOC_STRUCT(xorg_shaders
);
522 sc
->vs_hash
= cso_hash_create();
523 sc
->fs_hash
= cso_hash_create();
529 cache_destroy(struct cso_context
*cso
,
530 struct cso_hash
*hash
,
533 struct cso_hash_iter iter
= cso_hash_first_node(hash
);
534 while (!cso_hash_iter_is_null(iter
)) {
535 void *shader
= (void *)cso_hash_iter_data(iter
);
536 if (processor
== PIPE_SHADER_FRAGMENT
) {
537 cso_delete_fragment_shader(cso
, shader
);
538 } else if (processor
== PIPE_SHADER_VERTEX
) {
539 cso_delete_vertex_shader(cso
, shader
);
541 iter
= cso_hash_erase(hash
, iter
);
543 cso_hash_delete(hash
);
546 void xorg_shaders_destroy(struct xorg_shaders
*sc
)
548 cache_destroy(sc
->r
->cso
, sc
->vs_hash
,
550 cache_destroy(sc
->r
->cso
, sc
->fs_hash
,
551 PIPE_SHADER_FRAGMENT
);
557 shader_from_cache(struct pipe_context
*pipe
,
559 struct cso_hash
*hash
,
564 struct cso_hash_iter iter
= cso_hash_find(hash
, key
);
566 if (cso_hash_iter_is_null(iter
)) {
567 if (type
== PIPE_SHADER_VERTEX
)
568 shader
= create_vs(pipe
, key
);
570 shader
= create_fs(pipe
, key
);
571 cso_hash_insert(hash
, key
, shader
);
573 shader
= (void *)cso_hash_iter_data(iter
);
578 struct xorg_shader
xorg_shaders_get(struct xorg_shaders
*sc
,
582 struct xorg_shader shader
= { NULL
, NULL
};
585 vs
= shader_from_cache(sc
->r
->pipe
, PIPE_SHADER_VERTEX
,
586 sc
->vs_hash
, vs_traits
);
587 fs
= shader_from_cache(sc
->r
->pipe
, PIPE_SHADER_FRAGMENT
,
588 sc
->fs_hash
, fs_traits
);
590 debug_assert(vs
&& fs
);