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