1 #include "xorg_exa_tgsi.h"
2 
3 /*### stupidity defined in X11/extensions/XI.h */
4 #undef Absolute
5 
6 #include "pipe/p_format.h"
7 #include "pipe/p_context.h"
8 #include "pipe/p_state.h"
9 #include "pipe/p_shader_tokens.h"
10 
11 #include "util/u_memory.h"
12 
13 #include "tgsi/tgsi_ureg.h"
14 
15 #include "cso_cache/cso_context.h"
16 #include "cso_cache/cso_hash.h"
17 
18 /* Vertex shader:
19  * IN[0]    = vertex pos
20  * IN[1]    = src tex coord | solid fill color
21  * IN[2]    = mask tex coord
22  * IN[3]    = dst tex coord
23  * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
24  * CONST[1] = (-1, -1, 0, 0)
25  *
26  * OUT[0]   = vertex pos
27  * OUT[1]   = src tex coord | solid fill color
28  * OUT[2]   = mask tex coord
29  * OUT[3]   = dst tex coord
30  */
31 
32 /* Fragment shader:
33  * SAMP[0]  = src
34  * SAMP[1]  = mask
35  * SAMP[2]  = dst
36  * IN[0]    = pos src | solid fill color
37  * IN[1]    = pos mask
38  * IN[2]    = pos dst
39  * CONST[0] = (0, 0, 0, 1)
40  *
41  * OUT[0] = color
42  */
43 
44 static void
print_fs_traits(int fs_traits)45 print_fs_traits(int fs_traits)
46 {
47    const char *strings[] = {
48       "FS_COMPOSITE",       /* = 1 << 0, */
49       "FS_MASK",            /* = 1 << 1, */
50       "FS_SOLID_FILL",      /* = 1 << 2, */
51       "FS_LINGRAD_FILL",    /* = 1 << 3, */
52       "FS_RADGRAD_FILL",    /* = 1 << 4, */
53       "FS_CA_FULL",         /* = 1 << 5, */ /* src.rgba * mask.rgba */
54       "FS_CA_SRCALPHA",     /* = 1 << 6, */ /* src.aaaa * mask.rgba */
55       "FS_YUV",             /* = 1 << 7, */
56       "FS_SRC_REPEAT_NONE", /* = 1 << 8, */
57       "FS_MASK_REPEAT_NONE",/* = 1 << 9, */
58       "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */
59       "FS_MASK_SWIZZLE_RGB",/* = 1 << 11, */
60       "FS_SRC_SET_ALPHA",   /* = 1 << 12, */
61       "FS_MASK_SET_ALPHA",  /* = 1 << 13, */
62       "FS_SRC_LUMINANCE",   /* = 1 << 14, */
63       "FS_MASK_LUMINANCE",  /* = 1 << 15, */
64    };
65    int i, k;
66    debug_printf("%s: ", __func__);
67 
68    for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) {
69       if (fs_traits & k)
70          debug_printf("%s, ", strings[i]);
71    }
72 
73    debug_printf("\n");
74 }
75 
76 struct xorg_shaders {
77    struct xorg_renderer *r;
78 
79    struct cso_hash *vs_hash;
80    struct cso_hash *fs_hash;
81 };
82 
83 static INLINE void
src_in_mask(struct ureg_program * ureg,struct ureg_dst dst,struct ureg_src src,struct ureg_src mask,unsigned component_alpha,unsigned mask_luminance)84 src_in_mask(struct ureg_program *ureg,
85             struct ureg_dst dst,
86             struct ureg_src src,
87             struct ureg_src mask,
88             unsigned component_alpha,
89             unsigned mask_luminance)
90 {
91    if (component_alpha == FS_CA_FULL) {
92       ureg_MUL(ureg, dst, src, mask);
93    } else if (component_alpha == FS_CA_SRCALPHA) {
94       ureg_MUL(ureg, dst,
95                ureg_scalar(src, TGSI_SWIZZLE_W), mask);
96    }
97    else {
98       if (mask_luminance)
99          ureg_MUL(ureg, dst, src,
100                   ureg_scalar(mask, TGSI_SWIZZLE_X));
101       else
102          ureg_MUL(ureg, dst, src,
103                   ureg_scalar(mask, TGSI_SWIZZLE_W));
104    }
105 }
106 
107 static struct ureg_src
vs_normalize_coords(struct ureg_program * ureg,struct ureg_src coords,struct ureg_src const0,struct ureg_src const1)108 vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
109                     struct ureg_src const0, struct ureg_src const1)
110 {
111    struct ureg_dst tmp = ureg_DECL_temporary(ureg);
112    struct ureg_src ret;
113    ureg_MAD(ureg, tmp, coords, const0, const1);
114    ret = ureg_src(tmp);
115    ureg_release_temporary(ureg, tmp);
116    return ret;
117 }
118 
119 static void
linear_gradient(struct ureg_program * ureg,struct ureg_dst out,struct ureg_src pos,struct ureg_src sampler,struct ureg_src coords,struct ureg_src const0124,struct ureg_src matrow0,struct ureg_src matrow1,struct ureg_src matrow2)120 linear_gradient(struct ureg_program *ureg,
121                 struct ureg_dst out,
122                 struct ureg_src pos,
123                 struct ureg_src sampler,
124                 struct ureg_src coords,
125                 struct ureg_src const0124,
126                 struct ureg_src matrow0,
127                 struct ureg_src matrow1,
128                 struct ureg_src matrow2)
129 {
130    struct ureg_dst temp0 = ureg_DECL_temporary(ureg);
131    struct ureg_dst temp1 = ureg_DECL_temporary(ureg);
132    struct ureg_dst temp2 = ureg_DECL_temporary(ureg);
133    struct ureg_dst temp3 = ureg_DECL_temporary(ureg);
134    struct ureg_dst temp4 = ureg_DECL_temporary(ureg);
135    struct ureg_dst temp5 = ureg_DECL_temporary(ureg);
136 
137    ureg_MOV(ureg,
138             ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos);
139    ureg_MOV(ureg,
140             ureg_writemask(temp0, TGSI_WRITEMASK_Z),
141             ureg_scalar(const0124, TGSI_SWIZZLE_Y));
142 
143    ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
144    ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
145    ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
146    ureg_RCP(ureg, temp3, ureg_src(temp3));
147    ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
148    ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
149 
150    ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X),
151             ureg_src(temp1));
152    ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y),
153             ureg_src(temp2));
154 
155    ureg_MUL(ureg, temp0,
156             ureg_scalar(coords, TGSI_SWIZZLE_Y),
157             ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y));
158    ureg_MAD(ureg, temp1,
159             ureg_scalar(coords, TGSI_SWIZZLE_X),
160             ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X),
161             ureg_src(temp0));
162 
163    ureg_MUL(ureg, temp2,
164             ureg_src(temp1),
165             ureg_scalar(coords, TGSI_SWIZZLE_Z));
166 
167    ureg_TEX(ureg, out,
168             TGSI_TEXTURE_1D, ureg_src(temp2), sampler);
169 
170    ureg_release_temporary(ureg, temp0);
171    ureg_release_temporary(ureg, temp1);
172    ureg_release_temporary(ureg, temp2);
173    ureg_release_temporary(ureg, temp3);
174    ureg_release_temporary(ureg, temp4);
175    ureg_release_temporary(ureg, temp5);
176 }
177 
178 
179 static void
radial_gradient(struct ureg_program * ureg,struct ureg_dst out,struct ureg_src pos,struct ureg_src sampler,struct ureg_src coords,struct ureg_src const0124,struct ureg_src matrow0,struct ureg_src matrow1,struct ureg_src matrow2)180 radial_gradient(struct ureg_program *ureg,
181                 struct ureg_dst out,
182                 struct ureg_src pos,
183                 struct ureg_src sampler,
184                 struct ureg_src coords,
185                 struct ureg_src const0124,
186                 struct ureg_src matrow0,
187                 struct ureg_src matrow1,
188                 struct ureg_src matrow2)
189 {
190    struct ureg_dst temp0 = ureg_DECL_temporary(ureg);
191    struct ureg_dst temp1 = ureg_DECL_temporary(ureg);
192    struct ureg_dst temp2 = ureg_DECL_temporary(ureg);
193    struct ureg_dst temp3 = ureg_DECL_temporary(ureg);
194    struct ureg_dst temp4 = ureg_DECL_temporary(ureg);
195    struct ureg_dst temp5 = ureg_DECL_temporary(ureg);
196 
197    ureg_MOV(ureg,
198             ureg_writemask(temp0, TGSI_WRITEMASK_XY),
199             pos);
200    ureg_MOV(ureg,
201             ureg_writemask(temp0, TGSI_WRITEMASK_Z),
202             ureg_scalar(const0124, TGSI_SWIZZLE_Y));
203 
204    ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
205    ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
206    ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
207    ureg_RCP(ureg, temp3, ureg_src(temp3));
208    ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
209    ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
210 
211    ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X),
212             ureg_src(temp1));
213    ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y),
214             ureg_src(temp2));
215 
216    ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y),
217             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
218    ureg_MAD(ureg, temp1,
219             ureg_scalar(coords, TGSI_SWIZZLE_X),
220             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
221             ureg_src(temp0));
222    ureg_ADD(ureg, temp1,
223             ureg_src(temp1), ureg_src(temp1));
224    ureg_MUL(ureg, temp3,
225             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y),
226             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
227    ureg_MAD(ureg, temp4,
228             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
229             ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
230             ureg_src(temp3));
231    ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4)));
232    ureg_MUL(ureg, temp2,
233             ureg_scalar(coords, TGSI_SWIZZLE_Z),
234             ureg_src(temp4));
235    ureg_MUL(ureg, temp0,
236             ureg_scalar(const0124, TGSI_SWIZZLE_W),
237             ureg_src(temp2));
238    ureg_MUL(ureg, temp3,
239             ureg_src(temp1), ureg_src(temp1));
240    ureg_SUB(ureg, temp2,
241             ureg_src(temp3), ureg_src(temp0));
242    ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2)));
243    ureg_RCP(ureg, temp2, ureg_src(temp2));
244    ureg_SUB(ureg, temp1,
245             ureg_src(temp2), ureg_src(temp1));
246    ureg_ADD(ureg, temp0,
247             ureg_scalar(coords, TGSI_SWIZZLE_Z),
248             ureg_scalar(coords, TGSI_SWIZZLE_Z));
249    ureg_RCP(ureg, temp0, ureg_src(temp0));
250    ureg_MUL(ureg, temp2,
251             ureg_src(temp1), ureg_src(temp0));
252    ureg_TEX(ureg, out, TGSI_TEXTURE_1D,
253             ureg_src(temp2), sampler);
254 
255    ureg_release_temporary(ureg, temp0);
256    ureg_release_temporary(ureg, temp1);
257    ureg_release_temporary(ureg, temp2);
258    ureg_release_temporary(ureg, temp3);
259    ureg_release_temporary(ureg, temp4);
260    ureg_release_temporary(ureg, temp5);
261 }
262 
263 static void *
create_vs(struct pipe_context * pipe,unsigned vs_traits)264 create_vs(struct pipe_context *pipe,
265           unsigned vs_traits)
266 {
267    struct ureg_program *ureg;
268    struct ureg_src src;
269    struct ureg_dst dst;
270    struct ureg_src const0, const1;
271    boolean is_fill = (vs_traits & VS_FILL) != 0;
272    boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;
273    boolean has_mask = (vs_traits & VS_MASK) != 0;
274    boolean is_yuv = (vs_traits & VS_YUV) != 0;
275    unsigned input_slot = 0;
276 
277    ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
278    if (ureg == NULL)
279       return 0;
280 
281    const0 = ureg_DECL_constant(ureg, 0);
282    const1 = ureg_DECL_constant(ureg, 1);
283 
284    /* it has to be either a fill or a composite op */
285    debug_assert((is_fill ^ is_composite) ^ is_yuv);
286 
287    src = ureg_DECL_vs_input(ureg, input_slot++);
288    dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
289    src = vs_normalize_coords(ureg, src,
290                              const0, const1);
291    ureg_MOV(ureg, dst, src);
292 
293    if (is_yuv) {
294       src = ureg_DECL_vs_input(ureg, input_slot++);
295       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
296       ureg_MOV(ureg, dst, src);
297    }
298 
299    if (is_composite) {
300       src = ureg_DECL_vs_input(ureg, input_slot++);
301       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
302       ureg_MOV(ureg, dst, src);
303    }
304 
305    if (is_fill) {
306       src = ureg_DECL_vs_input(ureg, input_slot++);
307       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
308       ureg_MOV(ureg, dst, src);
309    }
310 
311    if (has_mask) {
312       src = ureg_DECL_vs_input(ureg, input_slot++);
313       dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
314       ureg_MOV(ureg, dst, src);
315    }
316 
317    ureg_END(ureg);
318 
319    return ureg_create_shader_and_destroy(ureg, pipe);
320 }
321 
322 static void *
create_yuv_shader(struct pipe_context * pipe,struct ureg_program * ureg)323 create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg)
324 {
325    struct ureg_src y_sampler, u_sampler, v_sampler;
326    struct ureg_src pos;
327    struct ureg_src matrow0, matrow1, matrow2;
328    struct ureg_dst y, u, v, rgb;
329    struct ureg_dst out = ureg_DECL_output(ureg,
330                                           TGSI_SEMANTIC_COLOR,
331                                           0);
332 
333    pos = ureg_DECL_fs_input(ureg,
334                             TGSI_SEMANTIC_GENERIC,
335                             0,
336                             TGSI_INTERPOLATE_PERSPECTIVE);
337 
338    rgb = ureg_DECL_temporary(ureg);
339    y = ureg_DECL_temporary(ureg);
340    u = ureg_DECL_temporary(ureg);
341    v = ureg_DECL_temporary(ureg);
342 
343    y_sampler = ureg_DECL_sampler(ureg, 0);
344    u_sampler = ureg_DECL_sampler(ureg, 1);
345    v_sampler = ureg_DECL_sampler(ureg, 2);
346 
347    matrow0 = ureg_DECL_constant(ureg, 0);
348    matrow1 = ureg_DECL_constant(ureg, 1);
349    matrow2 = ureg_DECL_constant(ureg, 2);
350 
351    ureg_TEX(ureg, y,
352             TGSI_TEXTURE_2D, pos, y_sampler);
353    ureg_TEX(ureg, u,
354             TGSI_TEXTURE_2D, pos, u_sampler);
355    ureg_TEX(ureg, v,
356             TGSI_TEXTURE_2D, pos, v_sampler);
357 
358    ureg_SUB(ureg, u, ureg_src(u),
359             ureg_scalar(matrow0, TGSI_SWIZZLE_W));
360    ureg_SUB(ureg, v, ureg_src(v),
361             ureg_scalar(matrow0, TGSI_SWIZZLE_W));
362 
363    ureg_MUL(ureg, rgb,
364             ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X),
365             matrow0);
366    ureg_MAD(ureg, rgb,
367             ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X),
368             matrow1,
369             ureg_src(rgb));
370    ureg_MAD(ureg, rgb,
371             ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X),
372             matrow2,
373             ureg_src(rgb));
374 
375    /* rgb.a = 1; */
376    ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W),
377             ureg_scalar(matrow0, TGSI_SWIZZLE_X));
378 
379    ureg_MOV(ureg, out, ureg_src(rgb));
380 
381    ureg_release_temporary(ureg, rgb);
382    ureg_release_temporary(ureg, y);
383    ureg_release_temporary(ureg, u);
384    ureg_release_temporary(ureg, v);
385 
386    ureg_END(ureg);
387 
388    return ureg_create_shader_and_destroy(ureg, pipe);
389 }
390 
391 
392 static INLINE void
xrender_tex(struct ureg_program * ureg,struct ureg_dst dst,struct ureg_src coords,struct ureg_src sampler,struct ureg_src imm0,boolean repeat_none,boolean swizzle,boolean set_alpha)393 xrender_tex(struct ureg_program *ureg,
394             struct ureg_dst dst,
395             struct ureg_src coords,
396             struct ureg_src sampler,
397             struct ureg_src imm0,
398             boolean repeat_none,
399             boolean swizzle,
400             boolean set_alpha)
401 {
402    if (repeat_none) {
403       struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
404       struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
405       ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
406                                         TGSI_SWIZZLE_X,
407                                         TGSI_SWIZZLE_Y,
408                                         TGSI_SWIZZLE_X,
409                                         TGSI_SWIZZLE_Y),
410                ureg_scalar(imm0, TGSI_SWIZZLE_X));
411       ureg_SLT(ureg, tmp0, ureg_swizzle(coords,
412                                         TGSI_SWIZZLE_X,
413                                         TGSI_SWIZZLE_Y,
414                                         TGSI_SWIZZLE_X,
415                                         TGSI_SWIZZLE_Y),
416                ureg_scalar(imm0, TGSI_SWIZZLE_W));
417       ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));
418       ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
419                ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
420       ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
421       if (swizzle)
422          ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
423                                            TGSI_SWIZZLE_Z,
424                                            TGSI_SWIZZLE_Y,
425                                            TGSI_SWIZZLE_X,
426                                            TGSI_SWIZZLE_W));
427       if (set_alpha)
428          ureg_MOV(ureg,
429                   ureg_writemask(tmp1, TGSI_WRITEMASK_W),
430                   ureg_scalar(imm0, TGSI_SWIZZLE_W));
431       ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
432       ureg_release_temporary(ureg, tmp0);
433       ureg_release_temporary(ureg, tmp1);
434    } else {
435       if (swizzle) {
436          struct ureg_dst tmp = ureg_DECL_temporary(ureg);
437          ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
438          ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
439                                           TGSI_SWIZZLE_Z,
440                                           TGSI_SWIZZLE_Y,
441                                           TGSI_SWIZZLE_X,
442                                           TGSI_SWIZZLE_W));
443          ureg_release_temporary(ureg, tmp);
444       } else {
445          ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
446       }
447       if (set_alpha)
448          ureg_MOV(ureg,
449                   ureg_writemask(dst, TGSI_WRITEMASK_W),
450                   ureg_scalar(imm0, TGSI_SWIZZLE_W));
451    }
452 }
453 
454 static void *
create_fs(struct pipe_context * pipe,unsigned fs_traits)455 create_fs(struct pipe_context *pipe,
456           unsigned fs_traits)
457 {
458    struct ureg_program *ureg;
459    struct ureg_src /*dst_sampler,*/ src_sampler, mask_sampler;
460    struct ureg_src /*dst_pos,*/ src_input, mask_pos;
461    struct ureg_dst src, mask;
462    struct ureg_dst out;
463    struct ureg_src imm0 = { 0 };
464    unsigned has_mask = (fs_traits & FS_MASK) != 0;
465    unsigned is_fill = (fs_traits & FS_FILL) != 0;
466    unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
467    unsigned is_solid   = (fs_traits & FS_SOLID_FILL) != 0;
468    unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0;
469    unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0;
470    unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA;
471    unsigned is_yuv = (fs_traits & FS_YUV) != 0;
472    unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
473    unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
474    unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
475    unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
476    unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
477    unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
478    unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
479    unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
480 
481 #if 0
482    print_fs_traits(fs_traits);
483 #else
484    (void)print_fs_traits;
485 #endif
486 
487    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
488    if (ureg == NULL)
489       return 0;
490 
491    /* it has to be either a fill, a composite op or a yuv conversion */
492    debug_assert((is_fill ^ is_composite) ^ is_yuv);
493    (void) is_yuv;
494 
495    out = ureg_DECL_output(ureg,
496                           TGSI_SEMANTIC_COLOR,
497                           0);
498 
499    if (src_repeat_none || mask_repeat_none ||
500        src_set_alpha || mask_set_alpha ||
501        src_luminance) {
502       imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
503    }
504    if (is_composite) {
505       src_sampler = ureg_DECL_sampler(ureg, 0);
506       src_input = ureg_DECL_fs_input(ureg,
507                                      TGSI_SEMANTIC_GENERIC,
508                                      0,
509                                      TGSI_INTERPOLATE_PERSPECTIVE);
510    } else if (is_fill) {
511       if (is_solid)
512          src_input = ureg_DECL_fs_input(ureg,
513                                         TGSI_SEMANTIC_COLOR,
514                                         0,
515                                         TGSI_INTERPOLATE_PERSPECTIVE);
516       else
517          src_input = ureg_DECL_fs_input(ureg,
518                                         TGSI_SEMANTIC_POSITION,
519                                         0,
520                                         TGSI_INTERPOLATE_PERSPECTIVE);
521    } else {
522       debug_assert(is_yuv);
523       return create_yuv_shader(pipe, ureg);
524    }
525 
526    if (has_mask) {
527       mask_sampler = ureg_DECL_sampler(ureg, 1);
528       mask_pos = ureg_DECL_fs_input(ureg,
529                                     TGSI_SEMANTIC_GENERIC,
530                                     1,
531                                     TGSI_INTERPOLATE_PERSPECTIVE);
532    }
533 
534 #if 0  /* unused right now */
535    dst_sampler = ureg_DECL_sampler(ureg, 2);
536    dst_pos = ureg_DECL_fs_input(ureg,
537                                 TGSI_SEMANTIC_POSITION,
538                                 2,
539                                 TGSI_INTERPOLATE_PERSPECTIVE);
540 #endif
541 
542 
543    if (is_composite) {
544       if (has_mask || src_luminance)
545          src = ureg_DECL_temporary(ureg);
546       else
547          src = out;
548       xrender_tex(ureg, src, src_input, src_sampler, imm0,
549                   src_repeat_none, src_swizzle, src_set_alpha);
550    } else if (is_fill) {
551       if (is_solid) {
552          if (has_mask || src_luminance)
553             src = ureg_dst(src_input);
554          else
555             ureg_MOV(ureg, out, src_input);
556       } else if (is_lingrad || is_radgrad) {
557          struct ureg_src coords, const0124,
558             matrow0, matrow1, matrow2;
559 
560          if (has_mask || src_luminance)
561             src = ureg_DECL_temporary(ureg);
562          else
563             src = out;
564 
565          coords = ureg_DECL_constant(ureg, 0);
566          const0124 = ureg_DECL_constant(ureg, 1);
567          matrow0 = ureg_DECL_constant(ureg, 2);
568          matrow1 = ureg_DECL_constant(ureg, 3);
569          matrow2 = ureg_DECL_constant(ureg, 4);
570 
571          if (is_lingrad) {
572             linear_gradient(ureg, src,
573                             src_input, src_sampler,
574                             coords, const0124,
575                             matrow0, matrow1, matrow2);
576          } else if (is_radgrad) {
577             radial_gradient(ureg, src,
578                             src_input, src_sampler,
579                             coords, const0124,
580                             matrow0, matrow1, matrow2);
581          }
582       } else
583          debug_assert(!"Unknown fill type!");
584    }
585    if (src_luminance) {
586       ureg_MOV(ureg, src,
587                ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
588       ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
589                ureg_scalar(imm0, TGSI_SWIZZLE_X));
590       if (!has_mask)
591          ureg_MOV(ureg, out, ureg_src(src));
592    }
593 
594    if (has_mask) {
595       mask = ureg_DECL_temporary(ureg);
596       xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
597                   mask_repeat_none, mask_swizzle, mask_set_alpha);
598       /* src IN mask */
599       src_in_mask(ureg, out, ureg_src(src), ureg_src(mask),
600                   comp_alpha_mask, mask_luminance);
601       ureg_release_temporary(ureg, mask);
602    }
603 
604    ureg_END(ureg);
605 
606    return ureg_create_shader_and_destroy(ureg, pipe);
607 }
608 
xorg_shaders_create(struct xorg_renderer * r)609 struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r)
610 {
611    struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
612 
613    sc->r = r;
614    sc->vs_hash = cso_hash_create();
615    sc->fs_hash = cso_hash_create();
616 
617    return sc;
618 }
619 
620 static void
cache_destroy(struct cso_context * cso,struct cso_hash * hash,unsigned processor)621 cache_destroy(struct cso_context *cso,
622               struct cso_hash *hash,
623               unsigned processor)
624 {
625    struct cso_hash_iter iter = cso_hash_first_node(hash);
626    while (!cso_hash_iter_is_null(iter)) {
627       void *shader = (void *)cso_hash_iter_data(iter);
628       if (processor == PIPE_SHADER_FRAGMENT) {
629          cso_delete_fragment_shader(cso, shader);
630       } else if (processor == PIPE_SHADER_VERTEX) {
631          cso_delete_vertex_shader(cso, shader);
632       }
633       iter = cso_hash_erase(hash, iter);
634    }
635    cso_hash_delete(hash);
636 }
637 
xorg_shaders_destroy(struct xorg_shaders * sc)638 void xorg_shaders_destroy(struct xorg_shaders *sc)
639 {
640    cache_destroy(sc->r->cso, sc->vs_hash,
641                  PIPE_SHADER_VERTEX);
642    cache_destroy(sc->r->cso, sc->fs_hash,
643                  PIPE_SHADER_FRAGMENT);
644 
645    FREE(sc);
646 }
647 
648 static INLINE void *
shader_from_cache(struct pipe_context * pipe,unsigned type,struct cso_hash * hash,unsigned key)649 shader_from_cache(struct pipe_context *pipe,
650                   unsigned type,
651                   struct cso_hash *hash,
652                   unsigned key)
653 {
654    void *shader = 0;
655 
656    struct cso_hash_iter iter = cso_hash_find(hash, key);
657 
658    if (cso_hash_iter_is_null(iter)) {
659       if (type == PIPE_SHADER_VERTEX)
660          shader = create_vs(pipe, key);
661       else
662          shader = create_fs(pipe, key);
663       cso_hash_insert(hash, key, shader);
664    } else
665       shader = (void *)cso_hash_iter_data(iter);
666 
667    return shader;
668 }
669 
xorg_shaders_get(struct xorg_shaders * sc,unsigned vs_traits,unsigned fs_traits)670 struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
671                                     unsigned vs_traits,
672                                     unsigned fs_traits)
673 {
674    struct xorg_shader shader = { NULL, NULL };
675    void *vs, *fs;
676 
677    vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
678                           sc->vs_hash, vs_traits);
679    fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
680                           sc->fs_hash, fs_traits);
681 
682    debug_assert(vs && fs);
683    if (!vs || !fs)
684       return shader;
685 
686    shader.vs = vs;
687    shader.fs = fs;
688 
689    return shader;
690 }
691