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