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"
29 #include "util/u_bitmask.h"
31 #include "svga_context.h"
32 #include "svga_state.h"
34 #include "svga_tgsi.h"
36 #include "svga_hw_reg.h"
40 static INLINE
int compare_fs_keys( const struct svga_fs_compile_key
*a
,
41 const struct svga_fs_compile_key
*b
)
43 unsigned keysize
= svga_fs_key_size( a
);
44 return memcmp( a
, b
, keysize
);
48 static struct svga_shader_result
*search_fs_key( struct svga_fragment_shader
*fs
,
49 const struct svga_fs_compile_key
*key
)
51 struct svga_shader_result
*result
= fs
->base
.results
;
55 for ( ; result
; result
= result
->next
) {
56 if (compare_fs_keys( key
, &result
->key
.fkey
) == 0)
64 static enum pipe_error
compile_fs( struct svga_context
*svga
,
65 struct svga_fragment_shader
*fs
,
66 const struct svga_fs_compile_key
*key
,
67 struct svga_shader_result
**out_result
)
69 struct svga_shader_result
*result
;
72 result
= svga_translate_fragment_program( fs
, key
);
74 ret
= PIPE_ERROR_OUT_OF_MEMORY
;
78 result
->id
= util_bitmask_add(svga
->fs_bm
);
79 if(result
->id
== UTIL_BITMASK_INVALID_INDEX
)
82 ret
= SVGA3D_DefineShader(svga
->swc
,
86 result
->nr_tokens
* sizeof result
->tokens
[0]);
91 result
->next
= fs
->base
.results
;
92 fs
->base
.results
= result
;
97 if (result
->id
!= UTIL_BITMASK_INVALID_INDEX
)
98 util_bitmask_clear( svga
->fs_bm
, result
->id
);
99 svga_destroy_shader_result( result
);
104 /* The blend workaround for simulating logicop xor behaviour requires
105 * that the incoming fragment color be white. This change achieves
106 * that by hooking up a hard-wired fragment shader that just emits
109 * This is a slightly incomplete solution as it assumes that the
110 * actual bound shader has no other effects beyond generating a
111 * fragment color. In particular shaders containing TEXKIL and/or
112 * depth-write will not have the correct behaviour, nor will those
113 * expecting to use alphatest.
115 * These are avoidable issues, but they are not much worse than the
116 * unavoidable ones associated with this technique, so it's not clear
117 * how much effort should be expended trying to resolve them - the
118 * ultimate result will still not be correct in most cases.
120 * Shader below was generated with:
121 * SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt
123 static int emit_white_fs( struct svga_context
*svga
)
125 int ret
= PIPE_ERROR
;
128 * def c0, 1.000000, 0.000000, 0.000000, 1.000000
132 static const unsigned white_tokens
[] = {
146 assert(SVGA3D_INVALID_ID
== UTIL_BITMASK_INVALID_INDEX
);
147 svga
->state
.white_fs_id
= util_bitmask_add(svga
->fs_bm
);
148 if(svga
->state
.white_fs_id
== SVGA3D_INVALID_ID
)
151 ret
= SVGA3D_DefineShader(svga
->swc
,
152 svga
->state
.white_fs_id
,
153 SVGA3D_SHADERTYPE_PS
,
155 sizeof(white_tokens
));
162 util_bitmask_clear(svga
->fs_bm
, svga
->state
.white_fs_id
);
163 svga
->state
.white_fs_id
= SVGA3D_INVALID_ID
;
169 /* SVGA_NEW_TEXTURE_BINDING
171 * SVGA_NEW_NEED_SWTNL
174 static int make_fs_key( const struct svga_context
*svga
,
175 struct svga_fs_compile_key
*key
)
180 memset(key
, 0, sizeof *key
);
182 /* Only need fragment shader fixup for twoside lighting if doing
183 * hwtnl. Otherwise the draw module does the whole job for us.
187 if (!svga
->state
.sw
.need_swtnl
) {
190 key
->light_twoside
= svga
->curr
.rast
->templ
.light_twoside
;
191 key
->front_cw
= (svga
->curr
.rast
->templ
.front_winding
==
196 /* XXX: want to limit this to the textures that the shader actually
199 * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
201 for (i
= 0; i
< svga
->curr
.num_textures
; i
++) {
202 if (svga
->curr
.texture
[i
]) {
203 assert(svga
->curr
.sampler
[i
]);
204 key
->tex
[i
].texture_target
= svga
->curr
.texture
[i
]->target
;
205 if (!svga
->curr
.sampler
[i
]->normalized_coords
) {
206 key
->tex
[i
].width_height_idx
= idx
++;
207 key
->tex
[i
].unnormalized
= TRUE
;
208 ++key
->num_unnormalized_coords
;
212 key
->num_textures
= svga
->curr
.num_textures
;
215 for (i
= 0; i
< svga
->curr
.num_samplers
; ++i
) {
216 if (svga
->curr
.sampler
[i
]) {
217 key
->tex
[i
].compare_mode
= svga
->curr
.sampler
[i
]->compare_mode
;
218 key
->tex
[i
].compare_func
= svga
->curr
.sampler
[i
]->compare_func
;
227 static int emit_hw_fs( struct svga_context
*svga
,
230 struct svga_shader_result
*result
= NULL
;
231 unsigned id
= SVGA3D_INVALID_ID
;
236 if (svga
->curr
.blend
->need_white_fragments
) {
237 if (svga
->state
.white_fs_id
== SVGA3D_INVALID_ID
) {
238 ret
= emit_white_fs( svga
);
242 id
= svga
->state
.white_fs_id
;
245 struct svga_fragment_shader
*fs
= svga
->curr
.fs
;
246 struct svga_fs_compile_key key
;
248 /* SVGA_NEW_TEXTURE_BINDING
250 * SVGA_NEW_NEED_SWTNL
253 ret
= make_fs_key( svga
, &key
);
257 result
= search_fs_key( fs
, &key
);
259 ret
= compile_fs( svga
, fs
, &key
, &result
);
268 assert(id
!= SVGA3D_INVALID_ID
);
270 if (result
!= svga
->state
.hw_draw
.fs
) {
271 ret
= SVGA3D_SetShader(svga
->swc
,
272 SVGA3D_SHADERTYPE_PS
,
277 svga
->dirty
|= SVGA_NEW_FS_RESULT
;
278 svga
->state
.hw_draw
.fs
= result
;
284 struct svga_tracked_state svga_hw_fs
=
286 "fragment shader (hwtnl)",
288 SVGA_NEW_TEXTURE_BINDING
|
289 SVGA_NEW_NEED_SWTNL
|