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