From ccd6bf8272cba7c57e4ae09ab8a03db63472648e Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Mon, 9 Dec 2013 10:46:56 -0800 Subject: [PATCH] svga: expose HW smooth/stipple/wide lines MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Newer virtual HW versions support smooth/stipple/wide lines. Use that instead of 'draw' fallbacks when possible. Reviewed-by: José Fonseca --- src/gallium/drivers/svga/include/svga3d_reg.h | 12 +++++-- src/gallium/drivers/svga/svga_context.h | 1 + .../drivers/svga/svga_pipe_rasterizer.c | 35 +++++++++++++++---- src/gallium/drivers/svga/svga_screen.c | 32 +++++++++++++++-- src/gallium/drivers/svga/svga_screen.h | 3 ++ src/gallium/drivers/svga/svga_state_rss.c | 9 ++++- src/gallium/drivers/svga/svga_swtnl_draw.c | 21 +++++++++-- 7 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/svga/include/svga3d_reg.h b/src/gallium/drivers/svga/include/svga3d_reg.h index 05b83c69c6c..464d3267451 100644 --- a/src/gallium/drivers/svga/include/svga3d_reg.h +++ b/src/gallium/drivers/svga/include/svga3d_reg.h @@ -432,8 +432,7 @@ typedef enum { SVGA3D_RS_DSTBLENDALPHA = 95, /* SVGA3dBlendOp */ SVGA3D_RS_BLENDEQUATIONALPHA = 96, /* SVGA3dBlendEquation */ SVGA3D_RS_TRANSPARENCYANTIALIAS = 97, /* SVGA3dTransparencyAntialiasType */ - SVGA3D_RS_LINEAA = 98, /* SVGA3dBool */ - SVGA3D_RS_LINEWIDTH = 99, /* float */ + SVGA3D_RS_LINEWIDTH = 98, /* float */ SVGA3D_RS_MAX } SVGA3dRenderStateName; @@ -1879,6 +1878,15 @@ typedef enum { SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = 82, SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = 83, + SVGA3D_DEVCAP_DEAD1 = 84, + SVGA3D_DEVCAP_85 = 85, + SVGA3D_DEVCAP_86 = 86, + + SVGA3D_DEVCAP_LINE_AA = 87, /* boolean */ + SVGA3D_DEVCAP_LINE_STIPPLE = 88, /* boolean */ + SVGA3D_DEVCAP_MAX_LINE_WIDTH = 89, /* float */ + SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH = 90, /* float */ + /* * Don't add new caps into the previous section; the values in this * enumeration must not change. You can put new values right before diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 284ee2db4a5..dee0cec6460 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -160,6 +160,7 @@ struct svga_rasterizer_state { float slopescaledepthbias; float depthbias; float pointsize; + float linewidth; unsigned hw_unfilled:16; /* PIPE_POLYGON_MODE_x */ diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 61e13fae9d9..356898a86e7 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -30,6 +30,7 @@ #include "util/u_memory.h" #include "svga_context.h" +#include "svga_screen.h" #include "svga_hw_reg.h" @@ -66,6 +67,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe, { struct svga_context *svga = svga_context(pipe); struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state ); + struct svga_screen *screen = svga_screen(pipe->screen); /* need this for draw module. */ rast->templ = *templ; @@ -100,23 +102,28 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->need_pipeline_tris_str = "poly stipple"; } - if (templ->line_width >= 1.5f && - !svga->debug.no_line_width) { + if (screen->maxLineWidth > 1.0F) { + /* 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"; } @@ -127,9 +134,16 @@ svga_create_rasterizer_state(struct pipe_context *pipe, rast->need_pipeline_points_str = "smooth points"; } - if (templ->line_smooth) { + 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 } { @@ -228,6 +242,13 @@ svga_create_rasterizer_state(struct pipe_context *pipe, 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); + } + return rast; } diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 6c2533800d6..330ffdf0e2d 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -103,9 +103,9 @@ svga_get_paramf(struct pipe_screen *screen, enum pipe_capf param) switch (param) { case PIPE_CAPF_MAX_LINE_WIDTH: - /* fall-through */ + return svgascreen->maxLineWidth; case PIPE_CAPF_MAX_LINE_WIDTH_AA: - return 7.0; + return svgascreen->maxLineWidthAA; case PIPE_CAPF_MAX_POINT_WIDTH: /* fall-through */ @@ -660,6 +660,34 @@ svga_screen_create(struct svga_winsys_screen *sws) } } + /* Query device caps + */ + if (!sws->get_cap(sws, SVGA3D_DEVCAP_LINE_STIPPLE, &result)) + svgascreen->haveLineStipple = FALSE; + else + svgascreen->haveLineStipple = result.u; + + if (!sws->get_cap(sws, SVGA3D_DEVCAP_LINE_AA, &result)) + svgascreen->haveLineSmooth = FALSE; + else + svgascreen->haveLineSmooth = result.u; + + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_LINE_WIDTH, &result)) + svgascreen->maxLineWidth = 1.0F; + else + svgascreen->maxLineWidth = result.f; + + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH, &result)) + svgascreen->maxLineWidthAA = 1.0F; + else + svgascreen->maxLineWidthAA = result.f; + + if (0) + debug_printf("svga: haveLineStip %u " + "haveLineSmooth %u maxLineWidth %f\n", + svgascreen->haveLineStipple, svgascreen->haveLineSmooth, + svgascreen->maxLineWidth); + if (!sws->get_cap(sws, SVGA3D_DEVCAP_MAX_POINT_SIZE, &result)) { svgascreen->maxPointSize = 1.0F; } else { diff --git a/src/gallium/drivers/svga/svga_screen.h b/src/gallium/drivers/svga/svga_screen.h index 517a3fa844a..b85191c4b26 100644 --- a/src/gallium/drivers/svga/svga_screen.h +++ b/src/gallium/drivers/svga/svga_screen.h @@ -47,6 +47,9 @@ struct svga_screen SVGA3dHardwareVersion hw_version; + /** Device caps */ + boolean haveLineStipple, haveLineSmooth; + float maxLineWidth, maxLineWidthAA; float maxPointSize; unsigned max_color_buffers; diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index 51d36b751b8..fb56b3d36ba 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -221,11 +221,18 @@ emit_rss(struct svga_context *svga, unsigned dirty) EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail ); EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail ); EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail ); - EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail ); EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail ); EMIT_RS_FLOAT( svga, point_size_min, POINTSIZEMIN, fail ); EMIT_RS_FLOAT( svga, screen->maxPointSize, POINTSIZEMAX, fail ); EMIT_RS( svga, curr->pointsprite, POINTSPRITEENABLE, fail); + + /* Emit line state, when the device understands it */ + if (screen->haveLineStipple) + EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail ); + if (screen->haveLineSmooth) + EMIT_RS( svga, curr->antialiasedlineenable, ANTIALIASEDLINEENABLE, fail ); + if (screen->maxLineWidth > 1.0F) + EMIT_RS_FLOAT( svga, curr->linewidth, LINEWIDTH, fail ); } if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE)) diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 0a049569ff7..66e4adfdcbe 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -29,6 +29,7 @@ #include "pipe/p_state.h" #include "svga_context.h" +#include "svga_screen.h" #include "svga_swtnl.h" #include "svga_state.h" #include "svga_swtnl_private.h" @@ -137,6 +138,8 @@ svga_swtnl_draw_vbo(struct svga_context *svga, boolean svga_init_swtnl( struct svga_context *svga ) { + struct svga_screen *screen = svga_screen(svga->pipe.screen); + svga->swtnl.backend = svga_vbuf_render_create(svga); if(!svga->swtnl.backend) goto fail; @@ -161,10 +164,24 @@ boolean svga_init_swtnl( struct svga_context *svga ) /* must be done before installing Draw stages */ util_blitter_cache_all_shaders(svga->blitter); - draw_install_aaline_stage(svga->swtnl.draw, &svga->pipe); - draw_install_aapoint_stage(svga->swtnl.draw, &svga->pipe); + if (!screen->haveLineSmooth) + draw_install_aaline_stage(svga->swtnl.draw, &svga->pipe); + + /* always install polygon stipple stage */ draw_install_pstipple_stage(svga->swtnl.draw, &svga->pipe); + /* enable/disable line stipple stage depending on device caps */ + draw_enable_line_stipple(svga->swtnl.draw, !screen->haveLineStipple); + + /* always install AA point stage */ + draw_install_aapoint_stage(svga->swtnl.draw, &svga->pipe); + + /* Set wide line threshold above device limit (so we'll never really use it) + */ + draw_wide_line_threshold(svga->swtnl.draw, + MAX2(screen->maxLineWidth, + screen->maxLineWidthAA)); + if (debug_get_bool_option("SVGA_SWTNL_FSE", FALSE)) draw_set_driver_clipping(svga->swtnl.draw, TRUE, TRUE, TRUE); -- 2.30.2