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
44static void
45print_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
76struct xorg_shaders {
77   struct xorg_renderer *r;
78
79   struct cso_hash *vs_hash;
80   struct cso_hash *fs_hash;
81};
82
83static INLINE void
84src_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
107static struct ureg_src
108vs_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
119static void
120linear_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
179static void
180radial_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
263static void *
264create_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
322static void *
323create_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
392static INLINE void
393xrender_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
454static void *
455create_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
609struct 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
620static void
621cache_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
638void 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
648static INLINE void *
649shader_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
670struct 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