Merge branch 'mesa_7_5_branch'
[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 struct xorg_shaders {
21 struct exa_context *exa;
22
23 struct cso_hash *vs_hash;
24 struct cso_hash *fs_hash;
25 };
26
27 /* SAMP[0] = dst
28 * SAMP[1] = src
29 * SAMP[2] = mask
30 * IN[0] = pos dst
31 * IN[1] = pos src
32 * IN[2] = pos mask
33 * CONST[0] = (0, 0, 0, 1)
34 */
35
36 static const char over_op[] =
37 "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
38 "MUL TEMP[3], TEMP[0], TEMP[3]\n"
39 "ADD TEMP[0], TEMP[3], TEMP[0]\n";
40
41
42 static INLINE void
43 create_preamble(struct ureg_program *ureg)
44 {
45 }
46
47
48 static INLINE void
49 src_in_mask(struct ureg_program *ureg,
50 struct ureg_dst dst,
51 struct ureg_src src,
52 struct ureg_src mask)
53 {
54 /* MUL dst, src, mask.wwww */
55 ureg_MUL(ureg, dst, src,
56 ureg_scalar(mask, TGSI_SWIZZLE_W));
57 }
58
59 static void *
60 create_vs(struct pipe_context *pipe,
61 unsigned vs_traits)
62 {
63 struct ureg_program *ureg;
64 struct ureg_src src;
65 struct ureg_dst dst;
66
67 ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
68 if (ureg == NULL)
69 return 0;
70
71 if ((vs_traits & VS_COMPOSITE)) {
72 src = ureg_DECL_vs_input(ureg,
73 TGSI_SEMANTIC_POSITION, 1);
74 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 1);
75 ureg_MOV(ureg, dst, src);
76 }
77 if ((vs_traits & VS_MASK)) {
78 src = ureg_DECL_vs_input(ureg,
79 TGSI_SEMANTIC_POSITION, 2);
80 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
81 ureg_MOV(ureg, dst, src);
82 }
83
84 ureg_END(ureg);
85
86 return ureg_create_shader_and_destroy(ureg, pipe);
87 }
88
89 static void *
90 create_fs(struct pipe_context *pipe,
91 unsigned fs_traits)
92 {
93 struct ureg_program *ureg;
94 struct ureg_src dst_sampler, src_sampler, mask_sampler;
95 struct ureg_src dst_pos, src_pos, mask_pos;
96 struct ureg_src src, mask;
97 struct ureg_dst out;
98
99 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
100 if (ureg == NULL)
101 return 0;
102
103 #if 0 /* unused right now */
104 dst_sampler = ureg_DECL_sampler(ureg);
105 dst_pos = ureg_DECL_fs_input(ureg,
106 TGSI_SEMANTIC_POSITION,
107 0,
108 TGSI_INTERPOLATE_PERSPECTIVE);
109 #endif
110
111 src_sampler = ureg_DECL_sampler(ureg);
112 src_pos = ureg_DECL_fs_input(ureg,
113 TGSI_SEMANTIC_POSITION,
114 1,
115 TGSI_INTERPOLATE_PERSPECTIVE);
116
117 out = ureg_DECL_output(ureg,
118 TGSI_SEMANTIC_COLOR,
119 0);
120
121 if ((fs_traits & FS_MASK)) {
122 mask_sampler = ureg_DECL_sampler(ureg);
123 mask_pos = ureg_DECL_fs_input(ureg,
124 TGSI_SEMANTIC_POSITION,
125 2,
126 TGSI_INTERPOLATE_PERSPECTIVE);
127 }
128
129 if ((fs_traits & FS_MASK)) {
130 ureg_TEX(ureg, ureg_dst(mask),
131 TGSI_TEXTURE_2D, mask_pos, mask_sampler);
132 /* src IN mask */
133 src_in_mask(ureg, out, src, mask);
134 } else {
135 ureg_TEX(ureg, out,
136 TGSI_TEXTURE_2D, src_pos, src_sampler);
137 }
138
139 ureg_END(ureg);
140
141 return ureg_create_shader_and_destroy(ureg, pipe);
142 }
143
144 struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
145 {
146 struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
147
148 sc->exa = exa;
149 sc->vs_hash = cso_hash_create();
150 sc->fs_hash = cso_hash_create();
151
152 return sc;
153 }
154
155 static void
156 cache_destroy(struct cso_context *cso,
157 struct cso_hash *hash,
158 unsigned processor)
159 {
160 struct cso_hash_iter iter = cso_hash_first_node(hash);
161 while (!cso_hash_iter_is_null(iter)) {
162 void *shader = (void *)cso_hash_iter_data(iter);
163 if (processor == PIPE_SHADER_FRAGMENT) {
164 cso_delete_fragment_shader(cso, shader);
165 } else if (processor == PIPE_SHADER_VERTEX) {
166 cso_delete_vertex_shader(cso, shader);
167 }
168 iter = cso_hash_erase(hash, iter);
169 }
170 cso_hash_delete(hash);
171 }
172
173 void xorg_shaders_destroy(struct xorg_shaders *sc)
174 {
175 cache_destroy(sc->exa->cso, sc->vs_hash,
176 PIPE_SHADER_VERTEX);
177 cache_destroy(sc->exa->cso, sc->fs_hash,
178 PIPE_SHADER_FRAGMENT);
179
180 free(sc);
181 }
182
183 static INLINE void *
184 shader_from_cache(struct pipe_context *pipe,
185 unsigned type,
186 struct cso_hash *hash,
187 unsigned key)
188 {
189 void *shader = 0;
190
191 struct cso_hash_iter iter = cso_hash_find(hash, key);
192
193 if (cso_hash_iter_is_null(iter)) {
194 if (type == PIPE_SHADER_VERTEX)
195 shader = create_vs(pipe, key);
196 else
197 shader = create_fs(pipe, key);
198 cso_hash_insert(hash, key, shader);
199 } else
200 shader = (void *)cso_hash_iter_data(iter);
201
202 return shader;
203 }
204
205 struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
206 unsigned vs_traits,
207 unsigned fs_traits)
208 {
209 struct xorg_shader shader = {0};
210 void *vs, *fs;
211
212 vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
213 sc->vs_hash, vs_traits);
214 fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
215 sc->fs_hash, fs_traits);
216
217 debug_assert(vs && fs);
218 if (!vs || !fs)
219 return shader;
220
221 shader.vs = vs;
222 shader.fs = fs;
223
224 return shader;
225 }