Home | History | Annotate | Download | only in xorg
      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
     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
     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
    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
    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
    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 *
    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 *
    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
    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 *
    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 
    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
    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 
    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 *
    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 
    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