X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fsvga%2Fsvga_pipe_rasterizer.c;h=1b823d64ec040013f7c6e96bd49c458c54204f2e;hb=39d00722b22a0059bbc58f0158a22f384519cd39;hp=d391fde7b2f7e9dc3f209c4e5f4e81b24ac2d2be;hpb=f0ca9f71341f494be961aacc08bddd9cea28fca2;p=mesa.git diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index d391fde7b2f..1b823d64ec0 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -23,20 +23,23 @@ * **********************************************************/ +#include "pipe/p_defines.h" #include "draw/draw_context.h" +#include "util/u_bitmask.h" #include "util/u_inlines.h" -#include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "svga_cmd.h" #include "svga_context.h" - #include "svga_hw_reg.h" +#include "svga_screen.h" + /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW. */ -static SVGA3dFace svga_translate_cullmode( unsigned mode, - unsigned front_ccw ) +static SVGA3dFace +svga_translate_cullmode(unsigned mode, unsigned front_ccw) { const int hw_front_ccw = 0; /* hardware is always CW */ switch (mode) { @@ -54,112 +57,240 @@ static SVGA3dFace svga_translate_cullmode( unsigned mode, } } -static SVGA3dShadeMode svga_translate_flatshade( unsigned mode ) +static SVGA3dShadeMode +svga_translate_flatshade(unsigned mode) { return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH; } +static unsigned +translate_fill_mode(unsigned fill) +{ + switch (fill) { + case PIPE_POLYGON_MODE_POINT: + return SVGA3D_FILLMODE_POINT; + case PIPE_POLYGON_MODE_LINE: + return SVGA3D_FILLMODE_LINE; + case PIPE_POLYGON_MODE_FILL: + return SVGA3D_FILLMODE_FILL; + default: + assert(!"Bad fill mode"); + return SVGA3D_FILLMODE_FILL; + } +} + + +static unsigned +translate_cull_mode(unsigned cull) +{ + switch (cull) { + case PIPE_FACE_NONE: + return SVGA3D_CULL_NONE; + case PIPE_FACE_FRONT: + return SVGA3D_CULL_FRONT; + case PIPE_FACE_BACK: + return SVGA3D_CULL_BACK; + case PIPE_FACE_FRONT_AND_BACK: + /* NOTE: we simply no-op polygon drawing in svga_draw_vbo() */ + return SVGA3D_CULL_NONE; + default: + assert(!"Bad cull mode"); + return SVGA3D_CULL_NONE; + } +} + + +static void +define_rasterizer_object(struct svga_context *svga, + struct svga_rasterizer_state *rast) +{ + struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); + unsigned fill_mode = translate_fill_mode(rast->templ.fill_front); + const unsigned cull_mode = translate_cull_mode(rast->templ.cull_face); + const int depth_bias = rast->templ.offset_units; + const float slope_scaled_depth_bias = rast->templ.offset_scale; + /* PIPE_CAP_POLYGON_OFFSET_CLAMP not supported: */ + const float depth_bias_clamp = 0.0; + const float line_width = rast->templ.line_width > 0.0f ? + rast->templ.line_width : 1.0f; + const uint8 line_factor = rast->templ.line_stipple_enable ? + rast->templ.line_stipple_factor : 0; + const uint16 line_pattern = rast->templ.line_stipple_enable ? + rast->templ.line_stipple_pattern : 0; + const uint8 pv_last = !rast->templ.flatshade_first && + svgascreen->haveProvokingVertex; + + rast->id = util_bitmask_add(svga->rast_object_id_bm); + + if (rast->templ.fill_front != rast->templ.fill_back) { + /* The VGPU10 device can't handle different front/back fill modes. + * We'll handle that with a swtnl/draw fallback. But we need to + * make sure we always fill triangles in that case. + */ + fill_mode = SVGA3D_FILLMODE_FILL; + } + + SVGA_RETRY(svga, SVGA3D_vgpu10_DefineRasterizerState + (svga->swc, + rast->id, + fill_mode, + cull_mode, + rast->templ.front_ccw, + depth_bias, + depth_bias_clamp, + slope_scaled_depth_bias, + rast->templ.depth_clip_near, + rast->templ.scissor, + rast->templ.multisample, + rast->templ.line_smooth, + line_width, + rast->templ.line_stipple_enable, + line_factor, + line_pattern, + pv_last)); +} + + static void * svga_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *templ) { struct svga_context *svga = svga_context(pipe); - struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state ); + struct svga_rasterizer_state *rast = CALLOC_STRUCT(svga_rasterizer_state); + struct svga_screen *screen = svga_screen(pipe->screen); + + if (!rast) + return NULL; /* need this for draw module. */ rast->templ = *templ; - /* light_twoside - XXX: need fragment shader variant */ - /* poly_smooth - XXX: no fallback available */ - /* poly_stipple_enable - draw module */ - /* sprite_coord_enable - ? */ - /* point_quad_rasterization - ? */ - /* point_size_per_vertex - ? */ - /* sprite_coord_mode - ??? */ - /* bypass_vs_viewport_and_clip - handled by viewport setup */ - /* flatshade_first - handled by index translation */ - /* gl_rasterization_rules - XXX - viewport code */ - /* line_width - draw module */ - /* fill_cw, fill_ccw - draw module or index translation */ - - rast->shademode = svga_translate_flatshade( templ->flatshade ); - rast->cullmode = svga_translate_cullmode( templ->cull_face, - templ->front_ccw ); + rast->shademode = svga_translate_flatshade(templ->flatshade); + rast->cullmode = svga_translate_cullmode(templ->cull_face, templ->front_ccw); rast->scissortestenable = templ->scissor; rast->multisampleantialias = templ->multisample; rast->antialiasedlineenable = templ->line_smooth; rast->lastpixel = templ->line_last_pixel; - rast->pointsize = templ->point_size; - rast->hw_unfilled = PIPE_POLYGON_MODE_FILL; + rast->pointsprite = templ->point_quad_rasterization; + + if (rast->templ.multisample) { + /* The OpenGL 3.0 spec says points are always drawn as circles when + * MSAA is enabled. Note that our implementation isn't 100% correct, + * though. Our smooth point implementation involves drawing a square, + * computing fragment distance from point center, then attenuating + * the fragment alpha value. We should not attenuate alpha if msaa + * is enabled. We should kill fragments entirely outside the circle + * and let the GPU compute per-fragment coverage. + * But as-is, our implementation gives acceptable results and passes + * Piglit's MSAA point smooth test. + */ + rast->templ.point_smooth = TRUE; + } + + if (rast->templ.point_smooth && + rast->templ.point_size_per_vertex == 0 && + rast->templ.point_size <= screen->pointSmoothThreshold) { + /* If the point size is less than the threshold, disable smoothing. + * Note that this only effects point rendering when we use the + * pipe_rasterizer_state::point_size value, not when the point size + * is set in the VS. + */ + rast->templ.point_smooth = FALSE; + } + + if (rast->templ.point_smooth) { + /* For smooth points we need to generate fragments for at least + * a 2x2 region. Otherwise the quad we draw may be too small and + * we may generate no fragments at all. + */ + rast->pointsize = MAX2(2.0f, templ->point_size); + } + else { + rast->pointsize = templ->point_size; + } + + rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; /* Use swtnl + decomposition implement these: */ - if (templ->poly_stipple_enable) { - rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; - rast->need_pipeline_tris_str = "poly stipple"; - } - if (templ->line_width != 1.0 && - templ->line_width != 0.0 && - !svga->debug.no_line_width) { + if (templ->line_width <= screen->maxLineWidth) { + /* pass line width to device */ + rast->linewidth = MAX2(1.0F, templ->line_width); + } + else if (svga->debug.no_line_width) { + /* nothing */ + } + else { + /* use 'draw' pipeline for wide line */ rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; rast->need_pipeline_lines_str = "line width"; } if (templ->line_stipple_enable) { - /* XXX: LinePattern not implemented on all backends, and there is no - * mechanism to query it. - */ - if (!svga->debug.force_hw_line_stipple) { + if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) { SVGA3dLinePattern lp; lp.repeat = templ->line_stipple_factor + 1; lp.pattern = templ->line_stipple_pattern; rast->linepattern = lp.uintValue; } else { + /* use 'draw' module to decompose into short line segments */ rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; rast->need_pipeline_lines_str = "line stipple"; } - } + } - if (templ->point_smooth) { + if (!svga_have_vgpu10(svga) && rast->templ.point_smooth) { rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; rast->need_pipeline_points_str = "smooth points"; } + if (templ->line_smooth && !screen->haveLineSmooth) { + /* + * XXX: Enabling the pipeline slows down performance immensely, so ignore + * line smooth state, where there is very little visual improvement. + * Smooth lines will still be drawn for wide lines. + */ +#if 0 + rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; + rast->need_pipeline_lines_str = "smooth lines"; +#endif + } + { int fill_front = templ->fill_front; int fill_back = templ->fill_back; int fill = PIPE_POLYGON_MODE_FILL; boolean offset_front = util_get_offset(templ, fill_front); boolean offset_back = util_get_offset(templ, fill_back); - boolean offset = 0; + boolean offset = FALSE; switch (templ->cull_face) { case PIPE_FACE_FRONT_AND_BACK: - offset = 0; + offset = FALSE; fill = PIPE_POLYGON_MODE_FILL; break; case PIPE_FACE_FRONT: - offset = offset_front; - fill = fill_front; + offset = offset_back; + fill = fill_back; break; case PIPE_FACE_BACK: - offset = offset_back; - fill = fill_back; + offset = offset_front; + fill = fill_front; break; case PIPE_FACE_NONE: - if (fill_front != fill_back || offset_front != offset_back) - { + if (fill_front != fill_back || offset_front != offset_back) { /* Always need the draw module to work out different * front/back fill modes: */ rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; rast->need_pipeline_tris_str = "different front/back fillmodes"; + fill = PIPE_POLYGON_MODE_FILL; } else { offset = offset_front; @@ -179,9 +310,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, if (fill != PIPE_POLYGON_MODE_FILL && (templ->flatshade || templ->light_twoside || - offset || - templ->cull_face != PIPE_FACE_NONE)) - { + offset)) { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation"; @@ -191,8 +320,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, * then we also need the pipeline for tris. */ if (fill == PIPE_POLYGON_MODE_LINE && - (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) - { + (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; rast->need_pipeline_tris_str = "decomposing lines"; @@ -201,8 +329,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, /* Similarly for points: */ if (fill == PIPE_POLYGON_MODE_POINT && - (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) - { + (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) { fill = PIPE_POLYGON_MODE_FILL; rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; rast->need_pipeline_tris_str = "decomposing points"; @@ -213,53 +340,93 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->depthbias = templ->offset_units; } - rast->hw_unfilled = fill; + rast->hw_fillmode = fill; } - - - if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) { /* Turn off stuff which will get done in the draw module: */ - rast->hw_unfilled = PIPE_POLYGON_MODE_FILL; + rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; rast->slopescaledepthbias = 0; rast->depthbias = 0; } + if (0 && rast->need_pipeline) { + debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline); + debug_printf(" pnts: %s \n", rast->need_pipeline_points_str); + debug_printf(" lins: %s \n", rast->need_pipeline_lines_str); + debug_printf(" tris: %s \n", rast->need_pipeline_tris_str); + } + + if (svga_have_vgpu10(svga)) { + define_rasterizer_object(svga, rast); + } + + if (templ->poly_smooth) { + pipe_debug_message(&svga->debug.callback, CONFORMANCE, + "GL_POLYGON_SMOOTH not supported"); + } + + svga->hud.num_rasterizer_objects++; + SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, + SVGA_STATS_COUNT_RASTERIZERSTATE); + return rast; } -static void svga_bind_rasterizer_state( struct pipe_context *pipe, - void *state ) + +static void +svga_bind_rasterizer_state(struct pipe_context *pipe, void *state) { struct svga_context *svga = svga_context(pipe); struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state; + if (!raster || !svga->curr.rast) { + svga->dirty |= SVGA_NEW_STIPPLE | SVGA_NEW_DEPTH_STENCIL_ALPHA; + } + else { + if (raster->templ.poly_stipple_enable != + svga->curr.rast->templ.poly_stipple_enable) { + svga->dirty |= SVGA_NEW_STIPPLE; + } + if (raster->templ.rasterizer_discard != + svga->curr.rast->templ.rasterizer_discard) { + svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA; + } + } + svga->curr.rast = raster; - draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL, - state); - svga->dirty |= SVGA_NEW_RAST; } -static void svga_delete_rasterizer_state(struct pipe_context *pipe, - void *raster) + +static void +svga_delete_rasterizer_state(struct pipe_context *pipe, void *state) { - FREE(raster); + struct svga_context *svga = svga_context(pipe); + struct svga_rasterizer_state *raster = + (struct svga_rasterizer_state *) state; + + if (svga_have_vgpu10(svga)) { + SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, + raster->id)); + + if (raster->id == svga->state.hw_draw.rasterizer_id) + svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID; + + util_bitmask_clear(svga->rast_object_id_bm, raster->id); + } + + FREE(state); + svga->hud.num_rasterizer_objects--; } -void svga_init_rasterizer_functions( struct svga_context *svga ) +void +svga_init_rasterizer_functions(struct svga_context *svga) { svga->pipe.create_rasterizer_state = svga_create_rasterizer_state; svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state; svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state; } - - -/*********************************************************************** - * Hardware state update - */ -