1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
24 **********************************************************/
26 #include "pipe/p_inlines.h"
27 #include "pipe/p_defines.h"
28 #include "util/u_math.h"
30 #include "svga_context.h"
31 #include "svga_state.h"
33 #include "svga_tgsi.h"
35 #include "svga_hw_reg.h"
39 static INLINE
int compare_fs_keys( const struct svga_fs_compile_key
*a
,
40 const struct svga_fs_compile_key
*b
)
42 unsigned keysize
= svga_fs_key_size( a
);
43 return memcmp( a
, b
, keysize
);
47 static struct svga_shader_result
*search_fs_key( struct svga_fragment_shader
*fs
,
48 const struct svga_fs_compile_key
*key
)
50 struct svga_shader_result
*result
= fs
->base
.results
;
54 for ( ; result
; result
= result
->next
) {
55 if (compare_fs_keys( key
, &result
->key
.fkey
) == 0)
63 static enum pipe_error
compile_fs( struct svga_context
*svga
,
64 struct svga_fragment_shader
*fs
,
65 const struct svga_fs_compile_key
*key
,
66 struct svga_shader_result
**out_result
)
68 struct svga_shader_result
*result
;
71 result
= svga_translate_fragment_program( fs
, key
);
73 ret
= PIPE_ERROR_OUT_OF_MEMORY
;
78 ret
= SVGA3D_DefineShader(svga
->swc
,
79 svga
->state
.next_fs_id
,
82 result
->nr_tokens
* sizeof result
->tokens
[0]);
87 result
->id
= svga
->state
.next_fs_id
++;
88 result
->next
= fs
->base
.results
;
89 fs
->base
.results
= result
;
94 svga_destroy_shader_result( result
);
98 /* The blend workaround for simulating logicop xor behaviour requires
99 * that the incoming fragment color be white. This change achieves
100 * that by hooking up a hard-wired fragment shader that just emits
103 * This is a slightly incomplete solution as it assumes that the
104 * actual bound shader has no other effects beyond generating a
105 * fragment color. In particular shaders containing TEXKIL and/or
106 * depth-write will not have the correct behaviour, nor will those
107 * expecting to use alphatest.
109 * These are avoidable issues, but they are not much worse than the
110 * unavoidable ones associated with this technique, so it's not clear
111 * how much effort should be expended trying to resolve them - the
112 * ultimate result will still not be correct in most cases.
114 * Shader below was generated with:
115 * SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt
117 static int emit_white_fs( struct svga_context
*svga
)
122 * def c0, 1.000000, 0.000000, 0.000000, 1.000000
126 static const unsigned white_tokens
[] = {
140 ret
= SVGA3D_DefineShader(svga
->swc
,
141 svga
->state
.next_fs_id
,
142 SVGA3D_SHADERTYPE_PS
,
144 sizeof(white_tokens
));
148 svga
->state
.white_fs_id
= svga
->state
.next_fs_id
++;
153 /* SVGA_NEW_TEXTURE_BINDING
155 * SVGA_NEW_NEED_SWTNL
158 static int make_fs_key( const struct svga_context
*svga
,
159 struct svga_fs_compile_key
*key
)
164 memset(key
, 0, sizeof *key
);
166 /* Only need fragment shader fixup for twoside lighting if doing
167 * hwtnl. Otherwise the draw module does the whole job for us.
171 if (!svga
->state
.sw
.need_swtnl
) {
174 key
->light_twoside
= svga
->curr
.rast
->templ
.light_twoside
;
175 key
->front_cw
= (svga
->curr
.rast
->templ
.front_winding
==
180 /* XXX: want to limit this to the textures that the shader actually
183 * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
185 for (i
= 0; i
< svga
->curr
.num_textures
; i
++) {
186 if (svga
->curr
.texture
[i
]) {
187 assert(svga
->curr
.sampler
[i
]);
188 key
->tex
[i
].texture_target
= svga
->curr
.texture
[i
]->target
;
189 if (!svga
->curr
.sampler
[i
]->normalized_coords
) {
190 key
->tex
[i
].width_height_idx
= idx
++;
191 key
->tex
[i
].unnormalized
= TRUE
;
192 ++key
->num_unnormalized_coords
;
196 key
->num_textures
= svga
->curr
.num_textures
;
199 for (i
= 0; i
< svga
->curr
.num_samplers
; ++i
) {
200 if (svga
->curr
.sampler
[i
]) {
201 key
->tex
[i
].compare_mode
= svga
->curr
.sampler
[i
]->compare_mode
;
202 key
->tex
[i
].compare_func
= svga
->curr
.sampler
[i
]->compare_func
;
211 static int emit_hw_fs( struct svga_context
*svga
,
214 struct svga_shader_result
*result
= NULL
;
215 unsigned id
= SVGA3D_INVALID_ID
;
220 if (svga
->curr
.blend
->need_white_fragments
) {
221 if (svga
->state
.white_fs_id
== SVGA3D_INVALID_ID
) {
222 ret
= emit_white_fs( svga
);
226 id
= svga
->state
.white_fs_id
;
229 struct svga_fragment_shader
*fs
= svga
->curr
.fs
;
230 struct svga_fs_compile_key key
;
232 /* SVGA_NEW_TEXTURE_BINDING
234 * SVGA_NEW_NEED_SWTNL
237 ret
= make_fs_key( svga
, &key
);
241 result
= search_fs_key( fs
, &key
);
243 ret
= compile_fs( svga
, fs
, &key
, &result
);
252 assert(id
!= SVGA3D_INVALID_ID
);
254 if (id
!= svga
->state
.hw_draw
.shader_id
[PIPE_SHADER_FRAGMENT
]) {
255 ret
= SVGA3D_SetShader(svga
->swc
,
256 SVGA3D_SHADERTYPE_PS
,
261 svga
->dirty
|= SVGA_NEW_FS_RESULT
;
262 svga
->state
.hw_draw
.shader_id
[PIPE_SHADER_FRAGMENT
] = id
;
263 svga
->state
.hw_draw
.fs
= result
;
269 struct svga_tracked_state svga_hw_fs
=
271 "fragment shader (hwtnl)",
273 SVGA_NEW_TEXTURE_BINDING
|
274 SVGA_NEW_NEED_SWTNL
|