st/xorg: lots of render fixes
[mesa.git] / src / gallium / state_trackers / xorg / xorg_exa_tgsi.c
1 #include "xorg_exa_tgsi.h"
2
3 /*### stupidity defined in X11/extensions/XI.h */
4 #undef Absolute
5
6 #include "pipe/p_format.h"
7 #include "pipe/p_context.h"
8 #include "pipe/p_state.h"
9 #include "pipe/p_inlines.h"
10 #include "pipe/p_shader_tokens.h"
11
12 #include "util/u_memory.h"
13 #include "util/u_simple_shaders.h"
14
15 #include "tgsi/tgsi_ureg.h"
16
17 #include "cso_cache/cso_context.h"
18 #include "cso_cache/cso_hash.h"
19
20 /* Vertex shader:
21 * IN[0] = vertex pos
22 * IN[1] = src tex coord | solid fill color
23 * IN[2] = mask tex coord
24 * IN[3] = dst tex coord
25 * CONST[0] = (2/dst_width, 2/dst_height, 1, 1)
26 * CONST[1] = (-1, -1, 0, 0)
27 *
28 * OUT[0] = vertex pos
29 * OUT[1] = src tex coord | solid fill color
30 * OUT[2] = mask tex coord
31 * OUT[3] = dst tex coord
32 */
33
34 /* Fragment shader:
35 * SAMP[0] = src
36 * SAMP[1] = mask
37 * SAMP[2] = dst
38 * IN[0] = pos src | solid fill color
39 * IN[1] = pos mask
40 * IN[2] = pos dst
41 * CONST[0] = (0, 0, 0, 1)
42 *
43 * OUT[0] = color
44 */
45
46 struct xorg_shaders {
47 struct xorg_renderer *r;
48
49 struct cso_hash *vs_hash;
50 struct cso_hash *fs_hash;
51 };
52
53 static INLINE void
54 src_in_mask(struct ureg_program *ureg,
55 struct ureg_dst dst,
56 struct ureg_src src,
57 struct ureg_src mask,
58 boolean component_alpha)
59 {
60 if (component_alpha) {
61 ureg_MUL(ureg, dst, src, mask);
62 }
63 else {
64 ureg_MUL(ureg, dst, src,
65 ureg_scalar(mask, TGSI_SWIZZLE_W));
66 }
67 }
68
69 static struct ureg_src
70 vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
71 struct ureg_src const0, struct ureg_src const1)
72 {
73 struct ureg_dst tmp = ureg_DECL_temporary(ureg);
74 struct ureg_src ret;
75 ureg_MAD(ureg, tmp, coords, const0, const1);
76 ret = ureg_src(tmp);
77 ureg_release_temporary(ureg, tmp);
78 return ret;
79 }
80
81 static void
82 linear_gradient(struct ureg_program *ureg,
83 struct ureg_dst out,
84 struct ureg_src pos,
85 struct ureg_src sampler,
86 struct ureg_src coords,
87 struct ureg_src const0124,
88 struct ureg_src matrow0,
89 struct ureg_src matrow1,
90 struct ureg_src matrow2)
91 {
92 struct ureg_dst temp0 = ureg_DECL_temporary(ureg);
93 struct ureg_dst temp1 = ureg_DECL_temporary(ureg);
94 struct ureg_dst temp2 = ureg_DECL_temporary(ureg);
95 struct ureg_dst temp3 = ureg_DECL_temporary(ureg);
96 struct ureg_dst temp4 = ureg_DECL_temporary(ureg);
97 struct ureg_dst temp5 = ureg_DECL_temporary(ureg);
98
99 ureg_MOV(ureg,
100 ureg_writemask(temp0, TGSI_WRITEMASK_XY), pos);
101 ureg_MOV(ureg,
102 ureg_writemask(temp0, TGSI_WRITEMASK_Z),
103 ureg_scalar(const0124, TGSI_SWIZZLE_Y));
104
105 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
106 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
107 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
108 ureg_RCP(ureg, temp3, ureg_src(temp3));
109 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
110 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
111
112 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_X),
113 ureg_src(temp1));
114 ureg_MOV(ureg, ureg_writemask(temp4, TGSI_WRITEMASK_Y),
115 ureg_src(temp2));
116
117 ureg_MUL(ureg, temp0,
118 ureg_scalar(coords, TGSI_SWIZZLE_Y),
119 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_Y));
120 ureg_MAD(ureg, temp1,
121 ureg_scalar(coords, TGSI_SWIZZLE_X),
122 ureg_scalar(ureg_src(temp4), TGSI_SWIZZLE_X),
123 ureg_src(temp0));
124
125 ureg_MUL(ureg, temp2,
126 ureg_src(temp1),
127 ureg_scalar(coords, TGSI_SWIZZLE_Z));
128
129 ureg_TEX(ureg, out,
130 TGSI_TEXTURE_1D, ureg_src(temp2), sampler);
131
132 ureg_release_temporary(ureg, temp0);
133 ureg_release_temporary(ureg, temp1);
134 ureg_release_temporary(ureg, temp2);
135 ureg_release_temporary(ureg, temp3);
136 ureg_release_temporary(ureg, temp4);
137 ureg_release_temporary(ureg, temp5);
138 }
139
140
141 static void
142 radial_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,
150 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,
160 ureg_writemask(temp0, TGSI_WRITEMASK_XY),
161 pos);
162 ureg_MOV(ureg,
163 ureg_writemask(temp0, TGSI_WRITEMASK_Z),
164 ureg_scalar(const0124, TGSI_SWIZZLE_Y));
165
166 ureg_DP3(ureg, temp1, matrow0, ureg_src(temp0));
167 ureg_DP3(ureg, temp2, matrow1, ureg_src(temp0));
168 ureg_DP3(ureg, temp3, matrow2, ureg_src(temp0));
169 ureg_RCP(ureg, temp3, ureg_src(temp3));
170 ureg_MUL(ureg, temp1, ureg_src(temp1), ureg_src(temp3));
171 ureg_MUL(ureg, temp2, ureg_src(temp2), ureg_src(temp3));
172
173 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_X),
174 ureg_src(temp1));
175 ureg_MOV(ureg, ureg_writemask(temp5, TGSI_WRITEMASK_Y),
176 ureg_src(temp2));
177
178 ureg_MUL(ureg, temp0, ureg_scalar(coords, TGSI_SWIZZLE_Y),
179 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
180 ureg_MAD(ureg, temp1,
181 ureg_scalar(coords, TGSI_SWIZZLE_X),
182 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
183 ureg_src(temp0));
184 ureg_ADD(ureg, temp1,
185 ureg_src(temp1), ureg_src(temp1));
186 ureg_MUL(ureg, temp3,
187 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y),
188 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_Y));
189 ureg_MAD(ureg, temp4,
190 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
191 ureg_scalar(ureg_src(temp5), TGSI_SWIZZLE_X),
192 ureg_src(temp3));
193 ureg_MOV(ureg, temp4, ureg_negate(ureg_src(temp4)));
194 ureg_MUL(ureg, temp2,
195 ureg_scalar(coords, TGSI_SWIZZLE_Z),
196 ureg_src(temp4));
197 ureg_MUL(ureg, temp0,
198 ureg_scalar(const0124, TGSI_SWIZZLE_W),
199 ureg_src(temp2));
200 ureg_MUL(ureg, temp3,
201 ureg_src(temp1), ureg_src(temp1));
202 ureg_SUB(ureg, temp2,
203 ureg_src(temp3), ureg_src(temp0));
204 ureg_RSQ(ureg, temp2, ureg_abs(ureg_src(temp2)));
205 ureg_RCP(ureg, temp2, ureg_src(temp2));
206 ureg_SUB(ureg, temp1,
207 ureg_src(temp2), ureg_src(temp1));
208 ureg_ADD(ureg, temp0,
209 ureg_scalar(coords, TGSI_SWIZZLE_Z),
210 ureg_scalar(coords, TGSI_SWIZZLE_Z));
211 ureg_RCP(ureg, temp0, ureg_src(temp0));
212 ureg_MUL(ureg, temp2,
213 ureg_src(temp1), ureg_src(temp0));
214 ureg_TEX(ureg, out, TGSI_TEXTURE_1D,
215 ureg_src(temp2), sampler);
216
217 ureg_release_temporary(ureg, temp0);
218 ureg_release_temporary(ureg, temp1);
219 ureg_release_temporary(ureg, temp2);
220 ureg_release_temporary(ureg, temp3);
221 ureg_release_temporary(ureg, temp4);
222 ureg_release_temporary(ureg, temp5);
223 }
224
225 static void *
226 create_vs(struct pipe_context *pipe,
227 unsigned vs_traits)
228 {
229 struct ureg_program *ureg;
230 struct ureg_src src;
231 struct ureg_dst dst;
232 struct ureg_src const0, const1;
233 boolean is_fill = vs_traits & VS_FILL;
234 boolean is_composite = vs_traits & VS_COMPOSITE;
235 boolean has_mask = vs_traits & VS_MASK;
236 unsigned input_slot = 0;
237
238 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
239 if (ureg == NULL)
240 return 0;
241
242 const0 = ureg_DECL_constant(ureg, 0);
243 const1 = ureg_DECL_constant(ureg, 1);
244
245 /* it has to be either a fill or a composite op */
246 debug_assert(is_fill ^ is_composite);
247
248 src = ureg_DECL_vs_input(ureg, input_slot++);
249 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
250 src = vs_normalize_coords(ureg, src,
251 const0, const1);
252 ureg_MOV(ureg, dst, src);
253
254 if (is_composite) {
255 src = ureg_DECL_vs_input(ureg, input_slot++);
256 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);
257 ureg_MOV(ureg, dst, src);
258 }
259
260 if (is_fill) {
261 src = ureg_DECL_vs_input(ureg, input_slot++);
262 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
263 ureg_MOV(ureg, dst, src);
264 }
265
266 if (has_mask) {
267 src = ureg_DECL_vs_input(ureg, input_slot++);
268 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
269 ureg_MOV(ureg, dst, src);
270 }
271
272 ureg_END(ureg);
273
274 return ureg_create_shader_and_destroy(ureg, pipe);
275 }
276
277 static void *
278 create_fs(struct pipe_context *pipe,
279 unsigned fs_traits)
280 {
281 struct ureg_program *ureg;
282 struct ureg_src /*dst_sampler,*/ src_sampler, mask_sampler;
283 struct ureg_src /*dst_pos,*/ src_input, mask_pos;
284 struct ureg_dst src, mask;
285 struct ureg_dst out;
286 boolean has_mask = fs_traits & FS_MASK;
287 boolean is_fill = fs_traits & FS_FILL;
288 boolean is_composite = fs_traits & FS_COMPOSITE;
289 boolean is_solid = fs_traits & FS_SOLID_FILL;
290 boolean is_lingrad = fs_traits & FS_LINGRAD_FILL;
291 boolean is_radgrad = fs_traits & FS_RADGRAD_FILL;
292 boolean is_comp_alpha = fs_traits & FS_COMPONENT_ALPHA;
293
294 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
295 if (ureg == NULL)
296 return 0;
297
298 /* it has to be either a fill or a composite op */
299 debug_assert(is_fill ^ is_composite);
300
301 out = ureg_DECL_output(ureg,
302 TGSI_SEMANTIC_COLOR,
303 0);
304
305 if (is_composite) {
306 src_sampler = ureg_DECL_sampler(ureg, 0);
307 src_input = ureg_DECL_fs_input(ureg,
308 TGSI_SEMANTIC_GENERIC,
309 0,
310 TGSI_INTERPOLATE_PERSPECTIVE);
311 } else {
312 debug_assert(is_fill);
313 if (is_solid)
314 src_input = ureg_DECL_fs_input(ureg,
315 TGSI_SEMANTIC_COLOR,
316 0,
317 TGSI_INTERPOLATE_PERSPECTIVE);
318 else
319 src_input = ureg_DECL_fs_input(ureg,
320 TGSI_SEMANTIC_POSITION,
321 0,
322 TGSI_INTERPOLATE_PERSPECTIVE);
323 }
324
325 if (has_mask) {
326 mask_sampler = ureg_DECL_sampler(ureg, 1);
327 mask_pos = ureg_DECL_fs_input(ureg,
328 TGSI_SEMANTIC_GENERIC,
329 1,
330 TGSI_INTERPOLATE_PERSPECTIVE);
331 }
332
333 #if 0 /* unused right now */
334 dst_sampler = ureg_DECL_sampler(ureg, 2);
335 dst_pos = ureg_DECL_fs_input(ureg,
336 TGSI_SEMANTIC_POSITION,
337 2,
338 TGSI_INTERPOLATE_PERSPECTIVE);
339 #endif
340
341 if (is_composite) {
342 if (has_mask)
343 src = ureg_DECL_temporary(ureg);
344 else
345 src = out;
346 ureg_TEX(ureg, src,
347 TGSI_TEXTURE_2D, src_input, src_sampler);
348 } else if (is_fill) {
349 if (is_solid) {
350 if (has_mask)
351 src = ureg_dst(src_input);
352 else
353 ureg_MOV(ureg, out, src_input);
354 } else if (is_lingrad || is_radgrad) {
355 struct ureg_src coords, const0124,
356 matrow0, matrow1, matrow2;
357
358 if (has_mask)
359 src = ureg_DECL_temporary(ureg);
360 else
361 src = out;
362
363 coords = ureg_DECL_constant(ureg, 0);
364 const0124 = ureg_DECL_constant(ureg, 1);
365 matrow0 = ureg_DECL_constant(ureg, 2);
366 matrow1 = ureg_DECL_constant(ureg, 3);
367 matrow2 = ureg_DECL_constant(ureg, 4);
368
369 if (is_lingrad) {
370 linear_gradient(ureg, src,
371 src_input, src_sampler,
372 coords, const0124,
373 matrow0, matrow1, matrow2);
374 } else if (is_radgrad) {
375 radial_gradient(ureg, src,
376 src_input, src_sampler,
377 coords, const0124,
378 matrow0, matrow1, matrow2);
379 }
380 } else
381 debug_assert(!"Unknown fill type!");
382 }
383
384 if (has_mask) {
385 mask = ureg_DECL_temporary(ureg);
386 ureg_TEX(ureg, mask,
387 TGSI_TEXTURE_2D, mask_pos, mask_sampler);
388 /* src IN mask */
389 src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), is_comp_alpha);
390 ureg_release_temporary(ureg, mask);
391 }
392
393 ureg_END(ureg);
394
395 return ureg_create_shader_and_destroy(ureg, pipe);
396 }
397
398 struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r)
399 {
400 struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
401
402 sc->r = r;
403 sc->vs_hash = cso_hash_create();
404 sc->fs_hash = cso_hash_create();
405
406 return sc;
407 }
408
409 static void
410 cache_destroy(struct cso_context *cso,
411 struct cso_hash *hash,
412 unsigned processor)
413 {
414 struct cso_hash_iter iter = cso_hash_first_node(hash);
415 while (!cso_hash_iter_is_null(iter)) {
416 void *shader = (void *)cso_hash_iter_data(iter);
417 if (processor == PIPE_SHADER_FRAGMENT) {
418 cso_delete_fragment_shader(cso, shader);
419 } else if (processor == PIPE_SHADER_VERTEX) {
420 cso_delete_vertex_shader(cso, shader);
421 }
422 iter = cso_hash_erase(hash, iter);
423 }
424 cso_hash_delete(hash);
425 }
426
427 void xorg_shaders_destroy(struct xorg_shaders *sc)
428 {
429 cache_destroy(sc->r->cso, sc->vs_hash,
430 PIPE_SHADER_VERTEX);
431 cache_destroy(sc->r->cso, sc->fs_hash,
432 PIPE_SHADER_FRAGMENT);
433
434 free(sc);
435 }
436
437 static INLINE void *
438 shader_from_cache(struct pipe_context *pipe,
439 unsigned type,
440 struct cso_hash *hash,
441 unsigned key)
442 {
443 void *shader = 0;
444
445 struct cso_hash_iter iter = cso_hash_find(hash, key);
446
447 if (cso_hash_iter_is_null(iter)) {
448 if (type == PIPE_SHADER_VERTEX)
449 shader = create_vs(pipe, key);
450 else
451 shader = create_fs(pipe, key);
452 cso_hash_insert(hash, key, shader);
453 } else
454 shader = (void *)cso_hash_iter_data(iter);
455
456 return shader;
457 }
458
459 struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
460 unsigned vs_traits,
461 unsigned fs_traits)
462 {
463 struct xorg_shader shader = { NULL, NULL };
464 void *vs, *fs;
465
466 vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,
467 sc->vs_hash, vs_traits);
468 fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,
469 sc->fs_hash, fs_traits);
470
471 debug_assert(vs && fs);
472 if (!vs || !fs)
473 return shader;
474
475 shader.vs = vs;
476 shader.fs = fs;
477
478 return shader;
479 }