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