Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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