svga: add work-around for Sauerbraten Z fighting issue
[mesa.git] / src / gallium / drivers / svga / svga_pipe_rasterizer.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 "draw/draw_context.h"
27 #include "util/u_inlines.h"
28 #include "pipe/p_defines.h"
29 #include "util/u_math.h"
30 #include "util/u_memory.h"
31
32 #include "svga_context.h"
33 #include "svga_screen.h"
34
35 #include "svga_hw_reg.h"
36
37 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
38 */
39 static SVGA3dFace svga_translate_cullmode( unsigned mode,
40 unsigned front_ccw )
41 {
42 const int hw_front_ccw = 0; /* hardware is always CW */
43 switch (mode) {
44 case PIPE_FACE_NONE:
45 return SVGA3D_FACE_NONE;
46 case PIPE_FACE_FRONT:
47 return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK;
48 case PIPE_FACE_BACK:
49 return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT;
50 case PIPE_FACE_FRONT_AND_BACK:
51 return SVGA3D_FACE_FRONT_BACK;
52 default:
53 assert(0);
54 return SVGA3D_FACE_NONE;
55 }
56 }
57
58 static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
59 {
60 return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
61 }
62
63
64 static void *
65 svga_create_rasterizer_state(struct pipe_context *pipe,
66 const struct pipe_rasterizer_state *templ)
67 {
68 struct svga_context *svga = svga_context(pipe);
69 struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state );
70 struct svga_screen *screen = svga_screen(pipe->screen);
71
72 /* need this for draw module. */
73 rast->templ = *templ;
74
75 /* light_twoside - XXX: need fragment shader variant */
76 /* poly_smooth - XXX: no fallback available */
77 /* poly_stipple_enable - draw module */
78 /* sprite_coord_enable - ? */
79 /* point_quad_rasterization - ? */
80 /* point_size_per_vertex - ? */
81 /* sprite_coord_mode - ??? */
82 /* flatshade_first - handled by index translation */
83 /* half_pixel_center - XXX - viewport code */
84 /* line_width - draw module */
85 /* fill_cw, fill_ccw - draw module or index translation */
86
87 rast->shademode = svga_translate_flatshade( templ->flatshade );
88 rast->cullmode = svga_translate_cullmode( templ->cull_face,
89 templ->front_ccw );
90 rast->scissortestenable = templ->scissor;
91 rast->multisampleantialias = templ->multisample;
92 rast->antialiasedlineenable = templ->line_smooth;
93 rast->lastpixel = templ->line_last_pixel;
94 rast->pointsprite = templ->sprite_coord_enable != 0x0;
95 rast->pointsize = templ->point_size;
96 rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
97
98 /* Use swtnl + decomposition implement these:
99 */
100 if (templ->poly_stipple_enable) {
101 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
102 rast->need_pipeline_tris_str = "poly stipple";
103 }
104
105 if (screen->maxLineWidth > 1.0F) {
106 /* pass line width to device */
107 rast->linewidth = MAX2(1.0F, templ->line_width);
108 }
109 else if (svga->debug.no_line_width) {
110 /* nothing */
111 }
112 else {
113 /* use 'draw' pipeline for wide line */
114 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
115 rast->need_pipeline_lines_str = "line width";
116 }
117
118 if (templ->line_stipple_enable) {
119 if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) {
120 SVGA3dLinePattern lp;
121 lp.repeat = templ->line_stipple_factor + 1;
122 lp.pattern = templ->line_stipple_pattern;
123 rast->linepattern = lp.uintValue;
124 }
125 else {
126 /* use 'draw' module to decompose into short line segments */
127 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
128 rast->need_pipeline_lines_str = "line stipple";
129 }
130 }
131
132 if (templ->point_smooth) {
133 rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
134 rast->need_pipeline_points_str = "smooth points";
135 }
136
137 if (templ->line_smooth && !screen->haveLineSmooth) {
138 /*
139 * XXX: Enabling the pipeline slows down performance immensely, so ignore
140 * line smooth state, where there is very little visual improvement.
141 * Smooth lines will still be drawn for wide lines.
142 */
143 #if 0
144 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
145 rast->need_pipeline_lines_str = "smooth lines";
146 #endif
147 }
148
149 {
150 int fill_front = templ->fill_front;
151 int fill_back = templ->fill_back;
152 int fill = PIPE_POLYGON_MODE_FILL;
153 boolean offset_front = util_get_offset(templ, fill_front);
154 boolean offset_back = util_get_offset(templ, fill_back);
155 boolean offset = FALSE;
156
157 switch (templ->cull_face) {
158 case PIPE_FACE_FRONT_AND_BACK:
159 offset = FALSE;
160 fill = PIPE_POLYGON_MODE_FILL;
161 break;
162
163 case PIPE_FACE_FRONT:
164 offset = offset_front;
165 fill = fill_front;
166 break;
167
168 case PIPE_FACE_BACK:
169 offset = offset_back;
170 fill = fill_back;
171 break;
172
173 case PIPE_FACE_NONE:
174 if (fill_front != fill_back || offset_front != offset_back)
175 {
176 /* Always need the draw module to work out different
177 * front/back fill modes:
178 */
179 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
180 rast->need_pipeline_tris_str = "different front/back fillmodes";
181 }
182 else {
183 offset = offset_front;
184 fill = fill_front;
185 }
186 break;
187
188 default:
189 assert(0);
190 break;
191 }
192
193 /* Unfilled primitive modes aren't implemented on all virtual
194 * hardware. We can do some unfilled processing with index
195 * translation, but otherwise need the draw module:
196 */
197 if (fill != PIPE_POLYGON_MODE_FILL &&
198 (templ->flatshade ||
199 templ->light_twoside ||
200 offset ||
201 templ->cull_face != PIPE_FACE_NONE))
202 {
203 fill = PIPE_POLYGON_MODE_FILL;
204 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
205 rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation";
206 }
207
208 /* If we are decomposing to lines, and lines need the pipeline,
209 * then we also need the pipeline for tris.
210 */
211 if (fill == PIPE_POLYGON_MODE_LINE &&
212 (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES))
213 {
214 fill = PIPE_POLYGON_MODE_FILL;
215 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
216 rast->need_pipeline_tris_str = "decomposing lines";
217 }
218
219 /* Similarly for points:
220 */
221 if (fill == PIPE_POLYGON_MODE_POINT &&
222 (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS))
223 {
224 fill = PIPE_POLYGON_MODE_FILL;
225 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
226 rast->need_pipeline_tris_str = "decomposing points";
227 }
228
229 if (offset) {
230 rast->slopescaledepthbias = templ->offset_scale;
231 rast->depthbias = templ->offset_units;
232 }
233
234 rast->hw_unfilled = fill;
235 }
236
237 if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
238 /* Turn off stuff which will get done in the draw module:
239 */
240 rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
241 rast->slopescaledepthbias = 0;
242 rast->depthbias = 0;
243 }
244
245 if (0 && rast->need_pipeline) {
246 debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline);
247 debug_printf(" pnts: %s \n", rast->need_pipeline_points_str);
248 debug_printf(" lins: %s \n", rast->need_pipeline_lines_str);
249 debug_printf(" tris: %s \n", rast->need_pipeline_tris_str);
250 }
251
252 return rast;
253 }
254
255 static void svga_bind_rasterizer_state( struct pipe_context *pipe,
256 void *state )
257 {
258 struct svga_context *svga = svga_context(pipe);
259 struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
260
261
262 draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL,
263 state);
264 svga->curr.rast = raster;
265
266 svga->dirty |= SVGA_NEW_RAST;
267 }
268
269 static void svga_delete_rasterizer_state(struct pipe_context *pipe,
270 void *raster)
271 {
272 FREE(raster);
273 }
274
275
276 void svga_init_rasterizer_functions( struct svga_context *svga )
277 {
278 svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
279 svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
280 svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
281 }
282
283
284 /***********************************************************************
285 * Hardware state update
286 */
287