svga: expose HW smooth/stipple/wide lines
authorBrian Paul <brianp@vmware.com>
Mon, 9 Dec 2013 18:46:56 +0000 (10:46 -0800)
committerBrian Paul <brianp@vmware.com>
Thu, 12 Dec 2013 01:19:44 +0000 (17:19 -0800)
Newer virtual HW versions support smooth/stipple/wide lines.
Use that instead of 'draw' fallbacks when possible.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
src/gallium/drivers/svga/include/svga3d_reg.h
src/gallium/drivers/svga/svga_context.h
src/gallium/drivers/svga/svga_pipe_rasterizer.c
src/gallium/drivers/svga/svga_screen.c
src/gallium/drivers/svga/svga_screen.h
src/gallium/drivers/svga/svga_state_rss.c
src/gallium/drivers/svga/svga_swtnl_draw.c

index 05b83c69c6cad8582bd5f6f6c326fb031999359e..464d3267451ea8ea8c93692b1ebbc8cd825457b9 100644 (file)
@@ -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
index 284ee2db4a5d57c6beb277d646b023b6f7b1c919..dee0cec6460e93f577beb77ff07498214bf1ff48 100644 (file)
@@ -160,6 +160,7 @@ struct svga_rasterizer_state {
    float slopescaledepthbias;
    float depthbias;
    float pointsize;
+   float linewidth;
    
    unsigned hw_unfilled:16;         /* PIPE_POLYGON_MODE_x */
 
index 61e13fae9d9e9d5f5542a0c8f6ffb0dd48e352f2..356898a86e7ef2bb484539def9f611897c20e34c 100644 (file)
@@ -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;
 }
 
index 6c2533800d612522822a572bb1fdace7e54750d8..330ffdf0e2de3af1949806d04d5a715015663b74 100644 (file)
@@ -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 {
index 517a3fa844a6bf3e57514cf8bf84f4b2387d597f..b85191c4b2638012924c1f5e4acaf16b1825ad86 100644 (file)
@@ -47,6 +47,9 @@ struct svga_screen
 
    SVGA3dHardwareVersion hw_version;
 
+   /** Device caps */
+   boolean haveLineStipple, haveLineSmooth;
+   float maxLineWidth, maxLineWidthAA;
    float maxPointSize;
    unsigned max_color_buffers;
 
index 51d36b751b82c01622333e990c02e95d1492e657..fb56b3d36baf29718170638fbfca91f502a625af 100644 (file)
@@ -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))
index 0a049569ff7c6160032da2b8305552a24e48132e..66e4adfdcbe46cb3c3c4fb27a8d5df9eb084bedc 100644 (file)
@@ -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);