OSDN Git Service

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