Home | History | Annotate | Download | only in xa
      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_ADD(ureg, temp2, ureg_src(temp3), ureg_negate(ureg_src(temp0)));
    243     ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2)));
    244     ureg_RCP(ureg, temp2, ureg_src(temp2));
    245     ureg_ADD(ureg, temp1, ureg_src(temp2), ureg_negate(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(PIPE_SHADER_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     ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D,
    343                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    344                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    345     ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D,
    346                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    347                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    348     ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D,
    349                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    350                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    351 
    352     matrow0 = ureg_DECL_constant(ureg, 0);
    353     matrow1 = ureg_DECL_constant(ureg, 1);
    354     matrow2 = ureg_DECL_constant(ureg, 2);
    355     matrow3 = ureg_DECL_constant(ureg, 3);
    356 
    357     ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler);
    358     ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler);
    359     ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler);
    360 
    361     ureg_MOV(ureg, rgb, matrow3);
    362     ureg_MAD(ureg, rgb,
    363 	     ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb));
    364     ureg_MAD(ureg, rgb,
    365 	     ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb));
    366     ureg_MAD(ureg, rgb,
    367 	     ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb));
    368 
    369     ureg_MOV(ureg, out, ureg_src(rgb));
    370 
    371     ureg_release_temporary(ureg, rgb);
    372     ureg_release_temporary(ureg, y);
    373     ureg_release_temporary(ureg, u);
    374     ureg_release_temporary(ureg, v);
    375 
    376     ureg_END(ureg);
    377 
    378     return ureg_create_shader_and_destroy(ureg, pipe);
    379 }
    380 
    381 static inline void
    382 xrender_tex(struct ureg_program *ureg,
    383 	    struct ureg_dst dst,
    384 	    struct ureg_src coords,
    385 	    struct ureg_src sampler,
    386 	    struct ureg_src imm0,
    387 	    boolean repeat_none, boolean swizzle, boolean set_alpha)
    388 {
    389     if (repeat_none) {
    390 	struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);
    391 	struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);
    392 
    393 	ureg_SGT(ureg, tmp1, ureg_swizzle(coords,
    394 					  TGSI_SWIZZLE_X,
    395 					  TGSI_SWIZZLE_Y,
    396 					  TGSI_SWIZZLE_X,
    397 					  TGSI_SWIZZLE_Y), ureg_scalar(imm0,
    398 								       TGSI_SWIZZLE_X));
    399 	ureg_SLT(ureg, tmp0,
    400 		 ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,
    401 			      TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(imm0,
    402 									   TGSI_SWIZZLE_W));
    403 	ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));
    404 	ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),
    405 		 ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));
    406 	ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);
    407 	if (swizzle)
    408 	    ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),
    409 					      TGSI_SWIZZLE_Z,
    410 					      TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
    411 					      TGSI_SWIZZLE_W));
    412 	if (set_alpha)
    413 	    ureg_MOV(ureg,
    414 		     ureg_writemask(tmp1, TGSI_WRITEMASK_W),
    415 		     ureg_scalar(imm0, TGSI_SWIZZLE_W));
    416 	ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));
    417 	ureg_release_temporary(ureg, tmp0);
    418 	ureg_release_temporary(ureg, tmp1);
    419     } else {
    420 	if (swizzle) {
    421 	    struct ureg_dst tmp = ureg_DECL_temporary(ureg);
    422 
    423 	    ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);
    424 	    ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),
    425 					     TGSI_SWIZZLE_Z,
    426 					     TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,
    427 					     TGSI_SWIZZLE_W));
    428 	    ureg_release_temporary(ureg, tmp);
    429 	} else {
    430 	    ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);
    431 	}
    432 	if (set_alpha)
    433 	    ureg_MOV(ureg,
    434 		     ureg_writemask(dst, TGSI_WRITEMASK_W),
    435 		     ureg_scalar(imm0, TGSI_SWIZZLE_W));
    436     }
    437 }
    438 
    439 static void *
    440 create_fs(struct pipe_context *pipe, unsigned fs_traits)
    441 {
    442     struct ureg_program *ureg;
    443     struct ureg_src /*dst_sampler, */ src_sampler, mask_sampler;
    444     struct ureg_src /*dst_pos, */ src_input, mask_pos;
    445     struct ureg_dst src, mask;
    446     struct ureg_dst out;
    447     struct ureg_src imm0 = { 0 };
    448     unsigned has_mask = (fs_traits & FS_MASK) != 0;
    449     unsigned is_fill = (fs_traits & FS_FILL) != 0;
    450     unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0;
    451     unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0;
    452     unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0;
    453     unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0;
    454     unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA;
    455     unsigned is_yuv = (fs_traits & FS_YUV) != 0;
    456     unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;
    457     unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;
    458     unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;
    459     unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;
    460     unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;
    461     unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;
    462     unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;
    463     unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;
    464     unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;
    465 
    466 #if 0
    467     print_fs_traits(fs_traits);
    468 #else
    469     (void)print_fs_traits;
    470 #endif
    471 
    472     ureg = ureg_create(PIPE_SHADER_FRAGMENT);
    473     if (ureg == NULL)
    474 	return 0;
    475 
    476     /* it has to be either a fill, a composite op or a yuv conversion */
    477     debug_assert((is_fill ^ is_composite) ^ is_yuv);
    478     (void)is_yuv;
    479 
    480     out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
    481 
    482     if (src_repeat_none || mask_repeat_none ||
    483 	src_set_alpha || mask_set_alpha || src_luminance) {
    484 	imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);
    485     }
    486     if (is_composite) {
    487 	src_sampler = ureg_DECL_sampler(ureg, 0);
    488         ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D,
    489                                TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    490                                TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    491 	src_input = ureg_DECL_fs_input(ureg,
    492 				       TGSI_SEMANTIC_GENERIC, 0,
    493 				       TGSI_INTERPOLATE_PERSPECTIVE);
    494     } else if (is_fill) {
    495 	if (is_solid)
    496 	    src_input = ureg_DECL_fs_input(ureg,
    497 					   TGSI_SEMANTIC_COLOR, 0,
    498 					   TGSI_INTERPOLATE_PERSPECTIVE);
    499 	else
    500 	    src_input = ureg_DECL_fs_input(ureg,
    501 					   TGSI_SEMANTIC_POSITION, 0,
    502 					   TGSI_INTERPOLATE_PERSPECTIVE);
    503     } else {
    504 	debug_assert(is_yuv);
    505 	return create_yuv_shader(pipe, ureg);
    506     }
    507 
    508     if (has_mask) {
    509 	mask_sampler = ureg_DECL_sampler(ureg, 1);
    510         ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D,
    511                                TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    512                                TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    513 	mask_pos = ureg_DECL_fs_input(ureg,
    514 				      TGSI_SEMANTIC_GENERIC, 1,
    515 				      TGSI_INTERPOLATE_PERSPECTIVE);
    516     }
    517 #if 0				/* unused right now */
    518     dst_sampler = ureg_DECL_sampler(ureg, 2);
    519     ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D,
    520                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,
    521                            TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);
    522     dst_pos = ureg_DECL_fs_input(ureg,
    523 				 TGSI_SEMANTIC_POSITION, 2,
    524 				 TGSI_INTERPOLATE_PERSPECTIVE);
    525 #endif
    526 
    527     if (is_composite) {
    528 	if (has_mask || src_luminance || dst_luminance)
    529 	    src = ureg_DECL_temporary(ureg);
    530 	else
    531 	    src = out;
    532 	xrender_tex(ureg, src, src_input, src_sampler, imm0,
    533 		    src_repeat_none, src_swizzle, src_set_alpha);
    534     } else if (is_fill) {
    535 	if (is_solid) {
    536 	    if (has_mask || src_luminance || dst_luminance)
    537 		src = ureg_dst(src_input);
    538 	    else
    539 		ureg_MOV(ureg, out, src_input);
    540 	} else if (is_lingrad || is_radgrad) {
    541 	    struct ureg_src coords, const0124, matrow0, matrow1, matrow2;
    542 
    543 	    if (has_mask || src_luminance || dst_luminance)
    544 		src = ureg_DECL_temporary(ureg);
    545 	    else
    546 		src = out;
    547 
    548 	    coords = ureg_DECL_constant(ureg, 0);
    549 	    const0124 = ureg_DECL_constant(ureg, 1);
    550 	    matrow0 = ureg_DECL_constant(ureg, 2);
    551 	    matrow1 = ureg_DECL_constant(ureg, 3);
    552 	    matrow2 = ureg_DECL_constant(ureg, 4);
    553 
    554 	    if (is_lingrad) {
    555 		linear_gradient(ureg, src,
    556 				src_input, src_sampler,
    557 				coords, const0124, matrow0, matrow1, matrow2);
    558 	    } else if (is_radgrad) {
    559 		radial_gradient(ureg, src,
    560 				src_input, src_sampler,
    561 				coords, const0124, matrow0, matrow1, matrow2);
    562 	    }
    563 	} else
    564 	    debug_assert(!"Unknown fill type!");
    565     }
    566     if (src_luminance) {
    567 	ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));
    568 	ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),
    569 		 ureg_scalar(imm0, TGSI_SWIZZLE_X));
    570 	if (!has_mask && !dst_luminance)
    571 	    ureg_MOV(ureg, out, ureg_src(src));
    572     }
    573 
    574     if (has_mask) {
    575 	mask = ureg_DECL_temporary(ureg);
    576 	xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0,
    577 		    mask_repeat_none, mask_swizzle, mask_set_alpha);
    578 	/* src IN mask */
    579 
    580 	src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),
    581 		    ureg_src(mask),
    582 		    comp_alpha_mask, mask_luminance);
    583 
    584 	ureg_release_temporary(ureg, mask);
    585     }
    586 
    587     if (dst_luminance) {
    588 	/*
    589 	 * Make sure the alpha channel goes into the output L8 surface.
    590 	 */
    591 	ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));
    592     }
    593 
    594     ureg_END(ureg);
    595 
    596     return ureg_create_shader_and_destroy(ureg, pipe);
    597 }
    598 
    599 struct xa_shaders *
    600 xa_shaders_create(struct xa_context *r)
    601 {
    602     struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders);
    603 
    604     sc->r = r;
    605     sc->vs_hash = cso_hash_create();
    606     sc->fs_hash = cso_hash_create();
    607 
    608     return sc;
    609 }
    610 
    611 static void
    612 cache_destroy(struct cso_context *cso,
    613 	      struct cso_hash *hash, unsigned processor)
    614 {
    615     struct cso_hash_iter iter = cso_hash_first_node(hash);
    616 
    617     while (!cso_hash_iter_is_null(iter)) {
    618 	void *shader = (void *)cso_hash_iter_data(iter);
    619 
    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 
    630 void
    631 xa_shaders_destroy(struct xa_shaders *sc)
    632 {
    633     cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX);
    634     cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT);
    635 
    636     FREE(sc);
    637 }
    638 
    639 static inline void *
    640 shader_from_cache(struct pipe_context *pipe,
    641 		  unsigned type, struct cso_hash *hash, unsigned key)
    642 {
    643     void *shader = 0;
    644 
    645     struct cso_hash_iter iter = cso_hash_find(hash, key);
    646 
    647     if (cso_hash_iter_is_null(iter)) {
    648 	if (type == PIPE_SHADER_VERTEX)
    649 	    shader = create_vs(pipe, key);
    650 	else
    651 	    shader = create_fs(pipe, key);
    652 	cso_hash_insert(hash, key, shader);
    653     } else
    654 	shader = (void *)cso_hash_iter_data(iter);
    655 
    656     return shader;
    657 }
    658 
    659 struct xa_shader
    660 xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits)
    661 {
    662     struct xa_shader shader = { NULL, NULL };
    663     void *vs, *fs;
    664 
    665     vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
    666 			   sc->vs_hash, vs_traits);
    667     fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
    668 			   sc->fs_hash, fs_traits);
    669 
    670     debug_assert(vs && fs);
    671     if (!vs || !fs)
    672 	return shader;
    673 
    674     shader.vs = vs;
    675     shader.fs = fs;
    676 
    677     return shader;
    678 }
    679