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