• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "pipe/p_defines.h"
27 #include "draw/draw_context.h"
28 #include "util/u_bitmask.h"
29 #include "util/u_inlines.h"
30 #include "util/u_math.h"
31 #include "util/u_memory.h"
32 
33 #include "svga_cmd.h"
34 #include "svga_context.h"
35 #include "svga_hw_reg.h"
36 #include "svga_screen.h"
37 
38 
39 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
40  */
41 static SVGA3dFace
svga_translate_cullmode(unsigned mode,unsigned front_ccw)42 svga_translate_cullmode(unsigned mode, unsigned front_ccw)
43 {
44    const int hw_front_ccw = 0;  /* hardware is always CW */
45    switch (mode) {
46    case PIPE_FACE_NONE:
47       return SVGA3D_FACE_NONE;
48    case PIPE_FACE_FRONT:
49       return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK;
50    case PIPE_FACE_BACK:
51       return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT;
52    case PIPE_FACE_FRONT_AND_BACK:
53       return SVGA3D_FACE_FRONT_BACK;
54    default:
55       assert(0);
56       return SVGA3D_FACE_NONE;
57    }
58 }
59 
60 static SVGA3dShadeMode
svga_translate_flatshade(unsigned mode)61 svga_translate_flatshade(unsigned mode)
62 {
63    return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
64 }
65 
66 
67 static unsigned
translate_fill_mode(unsigned fill)68 translate_fill_mode(unsigned fill)
69 {
70    switch (fill) {
71    case PIPE_POLYGON_MODE_POINT:
72       return SVGA3D_FILLMODE_POINT;
73    case PIPE_POLYGON_MODE_LINE:
74       return SVGA3D_FILLMODE_LINE;
75    case PIPE_POLYGON_MODE_FILL:
76       return SVGA3D_FILLMODE_FILL;
77    default:
78       assert(!"Bad fill mode");
79       return SVGA3D_FILLMODE_FILL;
80    }
81 }
82 
83 
84 static unsigned
translate_cull_mode(unsigned cull)85 translate_cull_mode(unsigned cull)
86 {
87    switch (cull) {
88    case PIPE_FACE_NONE:
89       return SVGA3D_CULL_NONE;
90    case PIPE_FACE_FRONT:
91       return SVGA3D_CULL_FRONT;
92    case PIPE_FACE_BACK:
93       return SVGA3D_CULL_BACK;
94    case PIPE_FACE_FRONT_AND_BACK:
95       /* NOTE: we simply no-op polygon drawing in svga_draw_vbo() */
96       return SVGA3D_CULL_NONE;
97    default:
98       assert(!"Bad cull mode");
99       return SVGA3D_CULL_NONE;
100    }
101 }
102 
103 
104 int
svga_define_rasterizer_object(struct svga_context * svga,struct svga_rasterizer_state * rast,unsigned samples)105 svga_define_rasterizer_object(struct svga_context *svga,
106                               struct svga_rasterizer_state *rast,
107                               unsigned samples)
108 {
109    struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
110    unsigned fill_mode = translate_fill_mode(rast->templ.fill_front);
111    const unsigned cull_mode = translate_cull_mode(rast->templ.cull_face);
112    const int depth_bias = rast->templ.offset_units;
113    const float slope_scaled_depth_bias = rast->templ.offset_scale;
114    /* PIPE_CAP_POLYGON_OFFSET_CLAMP not supported: */
115    const float depth_bias_clamp = 0.0;
116    const float line_width = rast->templ.line_width > 0.0f ?
117       rast->templ.line_width : 1.0f;
118    const uint8 line_factor = rast->templ.line_stipple_enable ?
119       rast->templ.line_stipple_factor : 0;
120    const uint16 line_pattern = rast->templ.line_stipple_enable ?
121       rast->templ.line_stipple_pattern : 0;
122    const uint8 pv_last = !rast->templ.flatshade_first &&
123       svgascreen->haveProvokingVertex;
124    int rastId;
125    enum pipe_error ret;
126 
127    rastId = util_bitmask_add(svga->rast_object_id_bm);
128 
129    if (rast->templ.fill_front != rast->templ.fill_back) {
130       /* The VGPU10 device can't handle different front/back fill modes.
131        * We'll handle that with a swtnl/draw fallback.  But we need to
132        * make sure we always fill triangles in that case.
133        */
134       fill_mode = SVGA3D_FILLMODE_FILL;
135    }
136 
137    if (samples > 1 && svga_have_gl43(svga) &&
138        svgascreen->sws->have_rasterizer_state_v2_cmd) {
139 
140       ret = SVGA3D_sm5_DefineRasterizerState_v2(svga->swc,
141                   rastId,
142                   fill_mode,
143                   cull_mode,
144                   rast->templ.front_ccw,
145                   depth_bias,
146                   depth_bias_clamp,
147                   slope_scaled_depth_bias,
148                   rast->templ.depth_clip_near,
149                   rast->templ.scissor,
150                   rast->templ.multisample,
151                   rast->templ.line_smooth,
152                   line_width,
153                   rast->templ.line_stipple_enable,
154                   line_factor,
155                   line_pattern,
156                   pv_last,
157                   samples);
158    } else {
159       ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
160                   rastId,
161                   fill_mode,
162                   cull_mode,
163                   rast->templ.front_ccw,
164                   depth_bias,
165                   depth_bias_clamp,
166                   slope_scaled_depth_bias,
167                   rast->templ.depth_clip_near,
168                   rast->templ.scissor,
169                   rast->templ.multisample,
170                   rast->templ.line_smooth,
171                   line_width,
172                   rast->templ.line_stipple_enable,
173                   line_factor,
174                   line_pattern,
175                   pv_last);
176    }
177 
178    if (ret != PIPE_OK) {
179       util_bitmask_clear(svga->rast_object_id_bm, rastId);
180       return SVGA3D_INVALID_ID;
181    }
182 
183    return rastId;
184 }
185 
186 
187 static void *
svga_create_rasterizer_state(struct pipe_context * pipe,const struct pipe_rasterizer_state * templ)188 svga_create_rasterizer_state(struct pipe_context *pipe,
189                              const struct pipe_rasterizer_state *templ)
190 {
191    struct svga_context *svga = svga_context(pipe);
192    struct svga_rasterizer_state *rast = CALLOC_STRUCT(svga_rasterizer_state);
193    struct svga_screen *screen = svga_screen(pipe->screen);
194 
195    if (!rast)
196       return NULL;
197 
198    /* need this for draw module. */
199    rast->templ = *templ;
200 
201    rast->shademode = svga_translate_flatshade(templ->flatshade);
202    rast->cullmode = svga_translate_cullmode(templ->cull_face, templ->front_ccw);
203    rast->scissortestenable = templ->scissor;
204    rast->multisampleantialias = templ->multisample;
205    rast->antialiasedlineenable = templ->line_smooth;
206    rast->lastpixel = templ->line_last_pixel;
207    rast->pointsprite = templ->point_quad_rasterization;
208 
209    if (rast->templ.multisample) {
210       /* The OpenGL 3.0 spec says points are always drawn as circles when
211        * MSAA is enabled.  Note that our implementation isn't 100% correct,
212        * though.  Our smooth point implementation involves drawing a square,
213        * computing fragment distance from point center, then attenuating
214        * the fragment alpha value.  We should not attenuate alpha if msaa
215        * is enabled.  We should discard fragments entirely outside the circle
216        * and let the GPU compute per-fragment coverage.
217        * But as-is, our implementation gives acceptable results and passes
218        * Piglit's MSAA point smooth test.
219        */
220       rast->templ.point_smooth = TRUE;
221    }
222 
223    if (rast->templ.point_smooth &&
224        rast->templ.point_size_per_vertex == 0 &&
225        rast->templ.point_size <= screen->pointSmoothThreshold) {
226       /* If the point size is less than the threshold, deactivate smoothing.
227        * Note that this only effects point rendering when we use the
228        * pipe_rasterizer_state::point_size value, not when the point size
229        * is set in the VS.
230        */
231       rast->templ.point_smooth = FALSE;
232    }
233 
234    if (rast->templ.point_smooth) {
235       /* For smooth points we need to generate fragments for at least
236        * a 2x2 region.  Otherwise the quad we draw may be too small and
237        * we may generate no fragments at all.
238        */
239       rast->pointsize = MAX2(2.0f, templ->point_size);
240    }
241    else {
242       rast->pointsize = templ->point_size;
243    }
244 
245    rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
246 
247    /* Use swtnl + decomposition implement these:
248     */
249 
250    if (templ->line_width <= screen->maxLineWidth) {
251       /* pass line width to device */
252       rast->linewidth = MAX2(1.0F, templ->line_width);
253    }
254    else if (svga->debug.no_line_width) {
255       /* nothing */
256    }
257    else {
258       /* use 'draw' pipeline for wide line */
259       rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
260       rast->need_pipeline_lines_str = "line width";
261    }
262 
263    if (templ->line_stipple_enable) {
264       if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) {
265          SVGA3dLinePattern lp;
266          lp.repeat = templ->line_stipple_factor + 1;
267          lp.pattern = templ->line_stipple_pattern;
268          rast->linepattern = lp.uintValue;
269       }
270       else {
271          /* use 'draw' module to decompose into short line segments */
272          rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
273          rast->need_pipeline_lines_str = "line stipple";
274       }
275    }
276 
277    if (!svga_have_vgpu10(svga) && rast->templ.point_smooth) {
278       rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
279       rast->need_pipeline_points_str = "smooth points";
280    }
281 
282    if (templ->line_smooth && !screen->haveLineSmooth) {
283       /*
284        * XXX: Enabling the pipeline slows down performance immensely, so ignore
285        * line smooth state, where there is very little visual improvement.
286        * Smooth lines will still be drawn for wide lines.
287        */
288 #if 0
289       rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
290       rast->need_pipeline_lines_str = "smooth lines";
291 #endif
292    }
293 
294    {
295       int fill_front = templ->fill_front;
296       int fill_back = templ->fill_back;
297       int fill = PIPE_POLYGON_MODE_FILL;
298       boolean offset_front = util_get_offset(templ, fill_front);
299       boolean offset_back = util_get_offset(templ, fill_back);
300       boolean offset = FALSE;
301 
302       switch (templ->cull_face) {
303       case PIPE_FACE_FRONT_AND_BACK:
304          offset = FALSE;
305          fill = PIPE_POLYGON_MODE_FILL;
306          break;
307 
308       case PIPE_FACE_FRONT:
309          offset = offset_back;
310          fill = fill_back;
311          break;
312 
313       case PIPE_FACE_BACK:
314          offset = offset_front;
315          fill = fill_front;
316          break;
317 
318       case PIPE_FACE_NONE:
319          if (fill_front != fill_back || offset_front != offset_back) {
320             /* Always need the draw module to work out different
321              * front/back fill modes:
322              */
323             rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
324             rast->need_pipeline_tris_str = "different front/back fillmodes";
325             fill = PIPE_POLYGON_MODE_FILL;
326          }
327          else {
328             offset = offset_front;
329             fill = fill_front;
330          }
331          break;
332 
333       default:
334          assert(0);
335          break;
336       }
337 
338       /* Unfilled primitive modes aren't implemented on all virtual
339        * hardware.  We can do some unfilled processing with index
340        * translation, but otherwise need the draw module:
341        */
342       if (fill != PIPE_POLYGON_MODE_FILL &&
343           (templ->flatshade ||
344            templ->light_twoside ||
345            offset)) {
346          fill = PIPE_POLYGON_MODE_FILL;
347          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
348          rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation";
349       }
350 
351       /* If we are decomposing to lines, and lines need the pipeline,
352        * then we also need the pipeline for tris.
353        */
354       if (fill == PIPE_POLYGON_MODE_LINE &&
355           (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) {
356          fill = PIPE_POLYGON_MODE_FILL;
357          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
358          rast->need_pipeline_tris_str = "decomposing lines";
359       }
360 
361       /* Similarly for points:
362        */
363       if (fill == PIPE_POLYGON_MODE_POINT &&
364           (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) {
365          fill = PIPE_POLYGON_MODE_FILL;
366          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
367          rast->need_pipeline_tris_str = "decomposing points";
368       }
369 
370       if (offset) {
371          rast->slopescaledepthbias = templ->offset_scale;
372          rast->depthbias = templ->offset_units;
373       }
374 
375       rast->hw_fillmode = fill;
376    }
377 
378    if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
379       /* Turn off stuff which will get done in the draw module:
380        */
381       rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
382       rast->slopescaledepthbias = 0;
383       rast->depthbias = 0;
384    }
385 
386    if (0 && rast->need_pipeline) {
387       debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline);
388       debug_printf(" pnts: %s \n", rast->need_pipeline_points_str);
389       debug_printf(" lins: %s \n", rast->need_pipeline_lines_str);
390       debug_printf(" tris: %s \n", rast->need_pipeline_tris_str);
391    }
392 
393    if (svga_have_vgpu10(svga)) {
394       rast->id = svga_define_rasterizer_object(svga, rast, 0);
395       if (rast->id == SVGA3D_INVALID_ID) {
396          svga_context_flush(svga, NULL);
397          rast->id = svga_define_rasterizer_object(svga, rast, 0);
398          assert(rast->id != SVGA3D_INVALID_ID);
399       }
400    }
401 
402    if (svga_have_gl43(svga)) {
403       /* initialize the alternate rasterizer state ids.
404        * For 0 and 1 sample count, we can use the same rasterizer object.
405        */
406       rast->altRastIds[0] = rast->altRastIds[1] = rast->id;
407 
408       for (unsigned i = 2; i < ARRAY_SIZE(rast->altRastIds); i++) {
409          rast->altRastIds[i] = SVGA3D_INVALID_ID;
410       }
411    }
412 
413    if (templ->poly_smooth) {
414       util_debug_message(&svga->debug.callback, CONFORMANCE,
415                          "GL_POLYGON_SMOOTH not supported");
416    }
417 
418    svga->hud.num_rasterizer_objects++;
419    SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
420                         SVGA_STATS_COUNT_RASTERIZERSTATE);
421 
422    return rast;
423 }
424 
425 
426 static void
svga_bind_rasterizer_state(struct pipe_context * pipe,void * state)427 svga_bind_rasterizer_state(struct pipe_context *pipe, void *state)
428 {
429    struct svga_context *svga = svga_context(pipe);
430    struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
431 
432    if (!raster || !svga->curr.rast) {
433       svga->dirty |= SVGA_NEW_STIPPLE | SVGA_NEW_DEPTH_STENCIL_ALPHA;
434    }
435    else {
436       if (raster->templ.poly_stipple_enable !=
437           svga->curr.rast->templ.poly_stipple_enable) {
438          svga->dirty |= SVGA_NEW_STIPPLE;
439       }
440       if (raster->templ.rasterizer_discard !=
441           svga->curr.rast->templ.rasterizer_discard) {
442          svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;
443       }
444    }
445 
446    svga->curr.rast = raster;
447 
448    svga->dirty |= SVGA_NEW_RAST;
449 }
450 
451 
452 static void
svga_delete_rasterizer_state(struct pipe_context * pipe,void * state)453 svga_delete_rasterizer_state(struct pipe_context *pipe, void *state)
454 {
455    struct svga_context *svga = svga_context(pipe);
456    struct svga_rasterizer_state *raster =
457       (struct svga_rasterizer_state *) state;
458 
459    /* free any alternate rasterizer state used for point sprite */
460    if (raster->no_cull_rasterizer)
461       svga_delete_rasterizer_state(pipe, (void *)(raster->no_cull_rasterizer));
462 
463    if (svga_have_vgpu10(svga)) {
464       SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRasterizerState(svga->swc,
465                                                             raster->id));
466 
467       if (raster->id == svga->state.hw_draw.rasterizer_id)
468          svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID;
469 
470       util_bitmask_clear(svga->rast_object_id_bm, raster->id);
471    }
472 
473    FREE(state);
474    svga->hud.num_rasterizer_objects--;
475 }
476 
477 
478 void
svga_init_rasterizer_functions(struct svga_context * svga)479 svga_init_rasterizer_functions(struct svga_context *svga)
480 {
481    svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
482    svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
483    svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
484 }
485