xorg_exa_tgsi.c revision d918896a754460bfcc5a9ba1e2844255f21ecab7
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
46struct xorg_shaders {
47   struct exa_context *exa;
48
49   struct cso_hash *vs_hash;
50   struct cso_hash *fs_hash;
51};
52
53static const char over_op[] =
54   "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n"
55   "MUL TEMP[3], TEMP[0], TEMP[3]\n"
56   "ADD TEMP[0], TEMP[3], TEMP[0]\n";
57
58
59static INLINE void
60create_preamble(struct ureg_program *ureg)
61{
62}
63
64
65static INLINE void
66src_in_mask(struct ureg_program *ureg,
67            struct ureg_dst dst,
68            struct ureg_src src,
69            struct ureg_src mask)
70{
71   /* MUL dst, src, mask.wwww */
72   ureg_MUL(ureg, dst, src,
73            ureg_scalar(mask, TGSI_SWIZZLE_W));
74}
75
76static struct ureg_src
77vs_normalize_coords(struct ureg_program *ureg, struct ureg_src coords,
78                    struct ureg_src const0, struct ureg_src const1)
79{
80   struct ureg_dst tmp = ureg_DECL_temporary(ureg);
81   struct ureg_src ret;
82   ureg_MUL(ureg, tmp, coords, const0);
83   ureg_ADD(ureg, tmp, ureg_src(tmp), const1);
84   ret = ureg_src(tmp);
85   ureg_release_temporary(ureg, tmp);
86   return ret;
87}
88
89static void *
90create_vs(struct pipe_context *pipe,
91          unsigned vs_traits)
92{
93   struct ureg_program *ureg;
94   struct ureg_src src;
95   struct ureg_dst dst;
96   struct ureg_src const0, const1;
97   boolean is_fill = vs_traits & VS_FILL;
98   boolean is_composite = vs_traits & VS_COMPOSITE;
99   boolean has_mask = vs_traits & VS_MASK;
100
101   ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
102   if (ureg == NULL)
103      return 0;
104
105   const0 = ureg_DECL_constant(ureg);
106   const1 = ureg_DECL_constant(ureg);
107
108   /* it has to be either a fill or a composite op */
109   debug_assert(is_fill ^ is_composite);
110
111   src = ureg_DECL_vs_input(ureg,
112                            TGSI_SEMANTIC_POSITION, 0);
113   dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
114   src = vs_normalize_coords(ureg, src,
115                             const0, const1);
116   ureg_MOV(ureg, dst, src);
117
118
119   if (is_composite) {
120      src = ureg_DECL_vs_input(ureg,
121                               TGSI_SEMANTIC_GENERIC, 1);
122      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);
123      ureg_MOV(ureg, dst, src);
124   }
125   if (is_fill) {
126      src = ureg_DECL_vs_input(ureg,
127                               TGSI_SEMANTIC_COLOR, 1);
128      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 1);
129      ureg_MOV(ureg, dst, src);
130   }
131
132   if (has_mask) {
133      src = ureg_DECL_vs_input(ureg,
134                               TGSI_SEMANTIC_GENERIC, 2);
135      dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 2);
136      ureg_MOV(ureg, dst, src);
137   }
138
139   ureg_END(ureg);
140
141   return ureg_create_shader_and_destroy(ureg, pipe);
142}
143
144static void *
145create_fs(struct pipe_context *pipe,
146          unsigned fs_traits)
147{
148   struct ureg_program *ureg;
149   struct ureg_src dst_sampler, src_sampler, mask_sampler;
150   struct ureg_src dst_pos, src_pos, mask_pos;
151   struct ureg_src src, mask;
152   struct ureg_dst out;
153   boolean is_fill = fs_traits & VS_FILL;
154   boolean is_composite = fs_traits & VS_COMPOSITE;
155   boolean has_mask = fs_traits & VS_MASK;
156
157   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
158   if (ureg == NULL)
159      return 0;
160
161   /* it has to be either a fill or a composite op */
162   debug_assert(is_fill ^ is_composite);
163
164   out = ureg_DECL_output(ureg,
165                          TGSI_SEMANTIC_COLOR,
166                          0);
167
168   src_sampler = ureg_DECL_sampler(ureg);
169   if (is_composite) {
170      src_pos = ureg_DECL_fs_input(ureg,
171                                   TGSI_SEMANTIC_POSITION,
172                                   0,
173                                   TGSI_INTERPOLATE_PERSPECTIVE);
174   }
175   if (is_fill) {
176      src_pos = ureg_DECL_fs_input(ureg,
177                                   TGSI_SEMANTIC_COLOR,
178                                   0,
179                                   TGSI_INTERPOLATE_PERSPECTIVE);
180   }
181
182   if ((fs_traits & FS_MASK)) {
183      mask_sampler = ureg_DECL_sampler(ureg);
184      mask_pos = ureg_DECL_fs_input(ureg,
185                                    TGSI_SEMANTIC_POSITION,
186                                    1,
187                                    TGSI_INTERPOLATE_PERSPECTIVE);
188   }
189
190#if 0  /* unused right now */
191   dst_sampler = ureg_DECL_sampler(ureg);
192   dst_pos = ureg_DECL_fs_input(ureg,
193                                TGSI_SEMANTIC_POSITION,
194                                2,
195                                TGSI_INTERPOLATE_PERSPECTIVE);
196#endif
197
198   if ((fs_traits & FS_MASK)) {
199      ureg_TEX(ureg, ureg_dst(mask),
200               TGSI_TEXTURE_2D, mask_pos, mask_sampler);
201      /* src IN mask */
202      src_in_mask(ureg, out, src, mask);
203   } else {
204      ureg_TEX(ureg, out,
205               TGSI_TEXTURE_2D, src_pos, src_sampler);
206   }
207
208   ureg_END(ureg);
209
210   return ureg_create_shader_and_destroy(ureg, pipe);
211}
212
213struct xorg_shaders * xorg_shaders_create(struct exa_context *exa)
214{
215   struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders);
216
217   sc->exa = exa;
218   sc->vs_hash = cso_hash_create();
219   sc->fs_hash = cso_hash_create();
220
221   return sc;
222}
223
224static void
225cache_destroy(struct cso_context *cso,
226              struct cso_hash *hash,
227              unsigned processor)
228{
229   struct cso_hash_iter iter = cso_hash_first_node(hash);
230   while (!cso_hash_iter_is_null(iter)) {
231      void *shader = (void *)cso_hash_iter_data(iter);
232      if (processor == PIPE_SHADER_FRAGMENT) {
233         cso_delete_fragment_shader(cso, shader);
234      } else if (processor == PIPE_SHADER_VERTEX) {
235         cso_delete_vertex_shader(cso, shader);
236      }
237      iter = cso_hash_erase(hash, iter);
238   }
239   cso_hash_delete(hash);
240}
241
242void xorg_shaders_destroy(struct xorg_shaders *sc)
243{
244   cache_destroy(sc->exa->cso, sc->vs_hash,
245                 PIPE_SHADER_VERTEX);
246   cache_destroy(sc->exa->cso, sc->fs_hash,
247                 PIPE_SHADER_FRAGMENT);
248
249   free(sc);
250}
251
252static INLINE void *
253shader_from_cache(struct pipe_context *pipe,
254                  unsigned type,
255                  struct cso_hash *hash,
256                  unsigned key)
257{
258   void *shader = 0;
259
260   struct cso_hash_iter iter = cso_hash_find(hash, key);
261
262   if (cso_hash_iter_is_null(iter)) {
263      if (type == PIPE_SHADER_VERTEX)
264         shader = create_vs(pipe, key);
265      else
266         shader = create_fs(pipe, key);
267      cso_hash_insert(hash, key, shader);
268   } else
269      shader = (void *)cso_hash_iter_data(iter);
270
271   return shader;
272}
273
274struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc,
275                                    unsigned vs_traits,
276                                    unsigned fs_traits)
277{
278   struct xorg_shader shader = {0};
279   void *vs, *fs;
280
281   vs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_VERTEX,
282                          sc->vs_hash, vs_traits);
283   fs = shader_from_cache(sc->exa->ctx, PIPE_SHADER_FRAGMENT,
284                          sc->fs_hash, fs_traits);
285
286   debug_assert(vs && fs);
287   if (!vs || !fs)
288      return shader;
289
290   shader.vs = vs;
291   shader.fs = fs;
292
293   return shader;
294}
295