• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
print_fs_traits(int fs_traits)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
src_in_mask(struct ureg_program * ureg,struct ureg_dst dst,struct ureg_src src,struct ureg_src mask,unsigned component_alpha,unsigned mask_luminance)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
vs_normalize_coords(struct ureg_program * ureg,struct ureg_src coords,struct ureg_src const0,struct ureg_src const1)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
linear_gradient(struct ureg_program * ureg,struct ureg_dst out,struct ureg_src pos,struct ureg_src sampler,struct ureg_src coords,struct ureg_src const0124,struct ureg_src matrow0,struct ureg_src matrow1,struct ureg_src matrow2)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
radial_gradient(struct ureg_program * ureg,struct ureg_dst out,struct ureg_src pos,struct ureg_src sampler,struct ureg_src coords,struct ureg_src const0124,struct ureg_src matrow0,struct ureg_src matrow1,struct ureg_src matrow2)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 *
create_vs(struct pipe_context * pipe,unsigned vs_traits)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 *
create_yuv_shader(struct pipe_context * pipe,struct ureg_program * ureg)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
xrender_tex(struct ureg_program * ureg,struct ureg_dst dst,struct ureg_src coords,struct ureg_src sampler,struct ureg_src imm0,boolean repeat_none,boolean swizzle,boolean set_alpha)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 *
create_fs(struct pipe_context * pipe,unsigned fs_traits)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 *
xa_shaders_create(struct xa_context * r)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
cache_destroy(struct cso_context * cso,struct cso_hash * hash,unsigned processor)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
xa_shaders_destroy(struct xa_shaders * sc)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 *
shader_from_cache(struct pipe_context * pipe,unsigned type,struct cso_hash * hash,unsigned key)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
xa_shaders_get(struct xa_shaders * sc,unsigned vs_traits,unsigned fs_traits)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