Merge branch 'width0'
[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 "pipe/p_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_state.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_winding )
41 {
42 switch (mode) {
43 case PIPE_WINDING_NONE:
44 return SVGA3D_FACE_NONE;
45 case PIPE_WINDING_CCW:
46 return SVGA3D_FACE_BACK;
47 case PIPE_WINDING_CW:
48 return SVGA3D_FACE_FRONT;
49 case PIPE_WINDING_BOTH:
50 return SVGA3D_FACE_FRONT_BACK;
51 default:
52 assert(0);
53 return SVGA3D_FACE_NONE;
54 }
55 }
56
57 static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
58 {
59 return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
60 }
61
62
63 static void *
64 svga_create_rasterizer_state(struct pipe_context *pipe,
65 const struct pipe_rasterizer_state *templ)
66 {
67 struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state );
68 /* need this for draw module. */
69 rast->templ = *templ;
70
71 /* light_twoside - XXX: need fragment shader varient */
72 /* poly_smooth - XXX: no fallback available */
73 /* poly_stipple_enable - draw module */
74 /* point_sprite - ? */
75 /* point_size_per_vertex - ? */
76 /* sprite_coord_mode - ??? */
77 /* bypass_vs_viewport_and_clip - handled by viewport setup */
78 /* flatshade_first - handled by index translation */
79 /* gl_rasterization_rules - XXX - viewport code */
80 /* line_width - draw module */
81 /* fill_cw, fill_ccw - draw module or index translation */
82
83 rast->shademode = svga_translate_flatshade( templ->flatshade );
84 rast->cullmode = svga_translate_cullmode( templ->cull_mode,
85 templ->front_winding );
86 rast->scissortestenable = templ->scissor;
87 rast->multisampleantialias = templ->multisample;
88 rast->antialiasedlineenable = templ->line_smooth;
89 rast->lastpixel = templ->line_last_pixel;
90 rast->pointsize = templ->point_size;
91 rast->pointsize_min = templ->point_size_min;
92 rast->pointsize_max = templ->point_size_max;
93 rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
94
95 /* Use swtnl + decomposition implement these:
96 */
97 if (templ->poly_stipple_enable)
98 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
99
100 if (templ->line_width != 1.0 &&
101 templ->line_width != 0.0)
102 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
103
104 if (templ->line_stipple_enable) {
105 /* LinePattern not implemented on all backends.
106 */
107 if (0) {
108 SVGA3dLinePattern lp;
109 lp.repeat = templ->line_stipple_factor + 1;
110 lp.pattern = templ->line_stipple_pattern;
111 rast->linepattern = lp.uintValue;
112 }
113 else {
114 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
115 }
116 }
117
118 if (templ->point_smooth)
119 rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
120
121 {
122 boolean offset_cw = templ->offset_cw;
123 boolean offset_ccw = templ->offset_ccw;
124 boolean offset = 0;
125 int fill_cw = templ->fill_cw;
126 int fill_ccw = templ->fill_ccw;
127 int fill = PIPE_POLYGON_MODE_FILL;
128
129 switch (templ->cull_mode) {
130 case PIPE_WINDING_BOTH:
131 offset = 0;
132 fill = PIPE_POLYGON_MODE_FILL;
133 break;
134
135 case PIPE_WINDING_CW:
136 offset = offset_ccw;
137 fill = fill_ccw;
138 break;
139
140 case PIPE_WINDING_CCW:
141 offset = offset_cw;
142 fill = fill_cw;
143 break;
144
145 case PIPE_WINDING_NONE:
146 if (fill_cw != fill_ccw || offset_cw != offset_ccw)
147 {
148 /* Always need the draw module to work out different
149 * front/back fill modes:
150 */
151 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
152 }
153 else {
154 offset = offset_ccw;
155 fill = fill_ccw;
156 }
157 break;
158
159 default:
160 assert(0);
161 break;
162 }
163
164 /* Unfilled primitive modes aren't implemented on all virtual
165 * hardware. We can do some unfilled processing with index
166 * translation, but otherwise need the draw module:
167 */
168 if (fill != PIPE_POLYGON_MODE_FILL &&
169 (templ->flatshade ||
170 templ->light_twoside ||
171 offset ||
172 templ->cull_mode != PIPE_WINDING_NONE))
173 {
174 fill = PIPE_POLYGON_MODE_FILL;
175 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
176 }
177
178 /* If we are decomposing to lines, and lines need the pipeline,
179 * then we also need the pipeline for tris.
180 */
181 if (fill == PIPE_POLYGON_MODE_LINE &&
182 (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES))
183 {
184 fill = PIPE_POLYGON_MODE_FILL;
185 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
186 }
187
188 /* Similarly for points:
189 */
190 if (fill == PIPE_POLYGON_MODE_POINT &&
191 (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS))
192 {
193 fill = PIPE_POLYGON_MODE_FILL;
194 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
195 }
196
197 if (offset) {
198 rast->slopescaledepthbias = templ->offset_scale;
199 rast->depthbias = templ->offset_units;
200 }
201
202 rast->hw_unfilled = fill;
203 }
204
205
206
207
208 if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
209 /* Turn off stuff which will get done in the draw module:
210 */
211 rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
212 rast->slopescaledepthbias = 0;
213 rast->depthbias = 0;
214 }
215
216 return rast;
217 }
218
219 static void svga_bind_rasterizer_state( struct pipe_context *pipe,
220 void *state )
221 {
222 struct svga_context *svga = svga_context(pipe);
223 struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
224
225 svga->curr.rast = raster;
226
227 draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL);
228
229 svga->dirty |= SVGA_NEW_RAST;
230 }
231
232 static void svga_delete_rasterizer_state(struct pipe_context *pipe,
233 void *raster)
234 {
235 FREE(raster);
236 }
237
238
239 void svga_init_rasterizer_functions( struct svga_context *svga )
240 {
241 svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
242 svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
243 svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
244 }
245
246
247 /***********************************************************************
248 * Hardware state update
249 */
250