svga: rename shader_result -> variant
[mesa.git] / src / gallium / drivers / svga / svga_state_fs.c
1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 #include "util/u_inlines.h"
27 #include "pipe/p_defines.h"
28 #include "util/u_math.h"
29 #include "util/u_memory.h"
30 #include "util/u_bitmask.h"
31 #include "tgsi/tgsi_ureg.h"
32
33 #include "svga_context.h"
34 #include "svga_state.h"
35 #include "svga_cmd.h"
36 #include "svga_resource_texture.h"
37 #include "svga_tgsi.h"
38
39 #include "svga_hw_reg.h"
40
41
42
43 static INLINE int
44 compare_fs_keys(const struct svga_fs_compile_key *a,
45 const struct svga_fs_compile_key *b)
46 {
47 unsigned keysize_a = svga_fs_key_size( a );
48 unsigned keysize_b = svga_fs_key_size( b );
49
50 if (keysize_a != keysize_b) {
51 return (int)(keysize_a - keysize_b);
52 }
53 return memcmp( a, b, keysize_a );
54 }
55
56
57 /** Search for a fragment shader variant */
58 static struct svga_shader_variant *
59 search_fs_key(const struct svga_fragment_shader *fs,
60 const struct svga_fs_compile_key *key)
61 {
62 struct svga_shader_variant *variant = fs->base.variants;
63
64 assert(key);
65
66 for ( ; variant; variant = variant->next) {
67 if (compare_fs_keys( key, &variant->key.fkey ) == 0)
68 return variant;
69 }
70
71 return NULL;
72 }
73
74
75 /**
76 * If we fail to compile a fragment shader (because it uses too many
77 * registers, for example) we'll use a dummy/fallback shader that
78 * simply emits a constant color.
79 */
80 static const struct tgsi_token *
81 get_dummy_fragment_shader(void)
82 {
83 static const float red[4] = { 1.0, 0.0, 0.0, 0.0 };
84 struct ureg_program *ureg;
85 const struct tgsi_token *tokens;
86 struct ureg_src src;
87 struct ureg_dst dst;
88 unsigned num_tokens;
89
90 ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
91 if (!ureg)
92 return NULL;
93
94 dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
95 src = ureg_DECL_immediate(ureg, red, 4);
96 ureg_MOV(ureg, dst, src);
97 ureg_END(ureg);
98
99 tokens = ureg_get_tokens(ureg, &num_tokens);
100
101 ureg_destroy(ureg);
102
103 return tokens;
104 }
105
106
107 /**
108 * Translate TGSI shader into an svga shader variant.
109 */
110 static enum pipe_error
111 compile_fs(struct svga_context *svga,
112 struct svga_fragment_shader *fs,
113 const struct svga_fs_compile_key *key,
114 struct svga_shader_variant **out_variant)
115 {
116 struct svga_shader_variant *variant;
117 enum pipe_error ret = PIPE_ERROR;
118
119 variant = svga_translate_fragment_program( fs, key );
120 if (variant == NULL) {
121 /* some problem during translation, try the dummy shader */
122 const struct tgsi_token *dummy = get_dummy_fragment_shader();
123 if (!dummy) {
124 ret = PIPE_ERROR_OUT_OF_MEMORY;
125 goto fail;
126 }
127 debug_printf("Failed to compile fragment shader, using dummy shader instead.\n");
128 FREE((void *) fs->base.tokens);
129 fs->base.tokens = dummy;
130 variant = svga_translate_fragment_program(fs, key);
131 if (variant == NULL) {
132 ret = PIPE_ERROR;
133 goto fail;
134 }
135 }
136
137 variant->id = util_bitmask_add(svga->fs_bm);
138 if(variant->id == UTIL_BITMASK_INVALID_INDEX) {
139 ret = PIPE_ERROR_OUT_OF_MEMORY;
140 goto fail;
141 }
142
143 ret = SVGA3D_DefineShader(svga->swc,
144 variant->id,
145 SVGA3D_SHADERTYPE_PS,
146 variant->tokens,
147 variant->nr_tokens * sizeof variant->tokens[0]);
148 if (ret != PIPE_OK)
149 goto fail;
150
151 *out_variant = variant;
152 variant->next = fs->base.variants;
153 fs->base.variants = variant;
154 return PIPE_OK;
155
156 fail:
157 if (variant) {
158 if (variant->id != UTIL_BITMASK_INVALID_INDEX)
159 util_bitmask_clear( svga->fs_bm, variant->id );
160 svga_destroy_shader_variant( variant );
161 }
162 return ret;
163 }
164
165
166 /* SVGA_NEW_TEXTURE_BINDING
167 * SVGA_NEW_RAST
168 * SVGA_NEW_NEED_SWTNL
169 * SVGA_NEW_SAMPLER
170 */
171 static enum pipe_error
172 make_fs_key(const struct svga_context *svga,
173 struct svga_fragment_shader *fs,
174 struct svga_fs_compile_key *key)
175 {
176 unsigned i;
177 int idx = 0;
178
179 memset(key, 0, sizeof *key);
180
181 /* Only need fragment shader fixup for twoside lighting if doing
182 * hwtnl. Otherwise the draw module does the whole job for us.
183 *
184 * SVGA_NEW_SWTNL
185 */
186 if (!svga->state.sw.need_swtnl) {
187 /* SVGA_NEW_RAST
188 */
189 key->light_twoside = svga->curr.rast->templ.light_twoside;
190 key->front_ccw = svga->curr.rast->templ.front_ccw;
191 }
192
193 /* The blend workaround for simulating logicop xor behaviour
194 * requires that the incoming fragment color be white. This change
195 * achieves that by creating a variant of the current fragment
196 * shader that overrides all output colors with 1,1,1,1
197 *
198 * This will work for most shaders, including those containing
199 * TEXKIL and/or depth-write. However, it will break on the
200 * combination of xor-logicop plus alphatest.
201 *
202 * Ultimately, we could implement alphatest in the shader using
203 * texkil prior to overriding the outgoing fragment color.
204 *
205 * SVGA_NEW_BLEND
206 */
207 if (svga->curr.blend->need_white_fragments) {
208 key->white_fragments = 1;
209 }
210
211 /* XXX: want to limit this to the textures that the shader actually
212 * refers to.
213 *
214 * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
215 */
216 for (i = 0; i < svga->curr.num_sampler_views; i++) {
217 if (svga->curr.sampler_views[i]) {
218 assert(svga->curr.sampler[i]);
219 assert(svga->curr.sampler_views[i]->texture);
220 key->tex[i].texture_target = svga->curr.sampler_views[i]->texture->target;
221 if (!svga->curr.sampler[i]->normalized_coords) {
222 key->tex[i].width_height_idx = idx++;
223 key->tex[i].unnormalized = TRUE;
224 ++key->num_unnormalized_coords;
225 }
226
227 key->tex[i].swizzle_r = svga->curr.sampler_views[i]->swizzle_r;
228 key->tex[i].swizzle_g = svga->curr.sampler_views[i]->swizzle_g;
229 key->tex[i].swizzle_b = svga->curr.sampler_views[i]->swizzle_b;
230 key->tex[i].swizzle_a = svga->curr.sampler_views[i]->swizzle_a;
231 }
232 }
233 key->num_textures = svga->curr.num_sampler_views;
234
235 idx = 0;
236 for (i = 0; i < svga->curr.num_samplers; ++i) {
237 if (svga->curr.sampler_views[i]) {
238 struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
239 struct svga_texture *stex = svga_texture(tex);
240 SVGA3dSurfaceFormat format = stex->key.format;
241
242 if (format == SVGA3D_Z_D16 ||
243 format == SVGA3D_Z_D24X8 ||
244 format == SVGA3D_Z_D24S8) {
245 /* If we're sampling from a SVGA3D_Z_D16, SVGA3D_Z_D24X8,
246 * or SVGA3D_Z_D24S8 surface, we'll automatically get
247 * shadow comparison. But we only get LEQUAL mode.
248 * Set TEX_COMPARE_NONE here so we don't emit the extra FS
249 * code for shadow comparison.
250 */
251 key->tex[i].compare_mode = PIPE_TEX_COMPARE_NONE;
252 key->tex[i].compare_func = PIPE_FUNC_NEVER;
253 /* These depth formats _only_ support comparison mode and
254 * not ordinary sampling so warn if the later is expected.
255 */
256 if (svga->curr.sampler[i]->compare_mode !=
257 PIPE_TEX_COMPARE_R_TO_TEXTURE) {
258 debug_warn_once("Unsupported shadow compare mode");
259 }
260 /* The only supported comparison mode is LEQUAL */
261 if (svga->curr.sampler[i]->compare_func != PIPE_FUNC_LEQUAL) {
262 debug_warn_once("Unsupported shadow compare function");
263 }
264 }
265 else {
266 /* For other texture formats, just use the compare func/mode
267 * as-is. Should be no-ops for color textures. For depth
268 * textures, we do not get automatic depth compare. We have
269 * to do it ourselves in the shader. And we don't get PCF.
270 */
271 key->tex[i].compare_mode = svga->curr.sampler[i]->compare_mode;
272 key->tex[i].compare_func = svga->curr.sampler[i]->compare_func;
273 }
274 }
275 }
276
277 /* sprite coord gen state */
278 for (i = 0; i < svga->curr.num_samplers; ++i) {
279 key->tex[i].sprite_texgen =
280 svga->curr.rast->templ.sprite_coord_enable & (1 << i);
281 }
282
283 key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
284 == PIPE_SPRITE_COORD_LOWER_LEFT);
285
286 /* SVGA_NEW_FRAME_BUFFER */
287 if (fs->base.info.color0_writes_all_cbufs) {
288 /* Replicate color0 output to N colorbuffers */
289 key->write_color0_to_n_cbufs = svga->curr.framebuffer.nr_cbufs;
290 }
291
292 return PIPE_OK;
293 }
294
295
296
297 static enum pipe_error
298 emit_hw_fs(struct svga_context *svga, unsigned dirty)
299 {
300 struct svga_shader_variant *variant = NULL;
301 unsigned id = SVGA3D_INVALID_ID;
302 enum pipe_error ret = PIPE_OK;
303
304 struct svga_fragment_shader *fs = svga->curr.fs;
305 struct svga_fs_compile_key key;
306
307 /* SVGA_NEW_BLEND
308 * SVGA_NEW_TEXTURE_BINDING
309 * SVGA_NEW_RAST
310 * SVGA_NEW_NEED_SWTNL
311 * SVGA_NEW_SAMPLER
312 * SVGA_NEW_FRAME_BUFFER
313 */
314 ret = make_fs_key( svga, fs, &key );
315 if (ret != PIPE_OK)
316 return ret;
317
318 variant = search_fs_key( fs, &key );
319 if (!variant) {
320 ret = compile_fs( svga, fs, &key, &variant );
321 if (ret != PIPE_OK)
322 return ret;
323 }
324
325 assert (variant);
326 id = variant->id;
327
328 assert(id != SVGA3D_INVALID_ID);
329
330 if (variant != svga->state.hw_draw.fs) {
331 ret = SVGA3D_SetShader(svga->swc,
332 SVGA3D_SHADERTYPE_PS,
333 id );
334 if (ret != PIPE_OK)
335 return ret;
336
337 svga->dirty |= SVGA_NEW_FS_VARIANT;
338 svga->state.hw_draw.fs = variant;
339 }
340
341 return PIPE_OK;
342 }
343
344 struct svga_tracked_state svga_hw_fs =
345 {
346 "fragment shader (hwtnl)",
347 (SVGA_NEW_FS |
348 SVGA_NEW_TEXTURE_BINDING |
349 SVGA_NEW_NEED_SWTNL |
350 SVGA_NEW_RAST |
351 SVGA_NEW_SAMPLER |
352 SVGA_NEW_FRAME_BUFFER |
353 SVGA_NEW_BLEND),
354 emit_hw_fs
355 };
356
357
358