Mesa (master): svga: expose HW smooth/stipple/wide lines

Brian Paul brianp at kemper.freedesktop.org
Thu Dec 12 01:22:50 UTC 2013


Module: Mesa
Branch: master
Commit: ccd6bf8272cba7c57e4ae09ab8a03db63472648e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ccd6bf8272cba7c57e4ae09ab8a03db63472648e

Author: Brian Paul <brianp at vmware.com>
Date:   Mon Dec  9 10:46:56 2013 -0800

svga: expose HW smooth/stipple/wide lines

Newer virtual HW versions support smooth/stipple/wide lines.
Use that instead of 'draw' fallbacks when possible.

Reviewed-by: José Fonseca <jfonseca at vmware.com>

---

 src/gallium/drivers/svga/include/svga3d_reg.h   |   12 ++++++-
 src/gallium/drivers/svga/svga_context.h         |    1 +
 src/gallium/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 05b83c6..464d326 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 284ee2d..dee0cec 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 61e13fa..356898a 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 6c25338..330ffdf 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 517a3fa..b85191c 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 51d36b7..fb56b3d 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 0a04956..66e4adf 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);
 




More information about the mesa-commit mailing list