softpipe: use the polygon stipple utility module
authorBrian Paul <brianp@vmware.com>
Thu, 21 Jul 2011 15:55:22 +0000 (09:55 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 21 Jul 2011 16:32:15 +0000 (10:32 -0600)
This is an alternative to the draw module's polygon stipple stage.
The softpipe implementation here is just a test.  The advantange of
using the new polygon stipple utility module (with other drivers)
is we can avoid software vertex processing in the draw module and
get much better performance.
Polygon stipple doesn't require special vertex processing like
the other draw module stage.

src/gallium/drivers/softpipe/sp_clear.c
src/gallium/drivers/softpipe/sp_context.c
src/gallium/drivers/softpipe/sp_context.h
src/gallium/drivers/softpipe/sp_draw_arrays.c
src/gallium/drivers/softpipe/sp_quad_pipe.c
src/gallium/drivers/softpipe/sp_setup.c
src/gallium/drivers/softpipe/sp_state.h
src/gallium/drivers/softpipe/sp_state_derived.c
src/gallium/drivers/softpipe/sp_state_shader.c

index ae3f00f33874e5c5ab29c79836f53e9072d88389..22e8a2e58170dbc641158ca62c652606d93fb7b2 100644 (file)
@@ -60,7 +60,7 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
       return;
 
 #if 0
-   softpipe_update_derived(softpipe); /* not needed?? */
+   softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
 #endif
 
    if (buffers & PIPE_CLEAR_COLOR) {
index ce22f6462289bf8011ddf9fd98d0cfb368812031..eabf2dae3fc74dd9f0034bbfef63839fdfe7f782 100644 (file)
@@ -35,6 +35,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_pstipple.h"
 #include "util/u_inlines.h"
 #include "tgsi/tgsi_exec.h"
 #include "sp_clear.h"
@@ -88,6 +89,14 @@ softpipe_destroy( struct pipe_context *pipe )
    struct softpipe_context *softpipe = softpipe_context( pipe );
    uint i;
 
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+   if (softpipe->pstipple.sampler)
+      pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
+
+   pipe_resource_reference(&softpipe->pstipple.texture, NULL);
+   pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
+#endif
+
    if (softpipe->draw)
       draw_destroy( softpipe->draw );
 
@@ -341,6 +350,11 @@ softpipe_create_context( struct pipe_screen *screen,
 
    sp_init_surface_functions(softpipe);
 
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+   /* create the polgon stipple sampler */
+   softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
+#endif
+
    return &softpipe->pipe;
 
  fail:
index 79291abca978517a8457bd0bb0728eaf1fd3cc57..410b0a65792734cbb0f2be91fb6a5150f6498e11 100644 (file)
 #include "sp_quad_pipe.h"
 
 
-/** Do polygon stipple in the driver here, or in the draw module? */
-#define DO_PSTIPPLE_IN_DRAW_MODULE 1
+/** Do polygon stipple in the draw module? */
+#define DO_PSTIPPLE_IN_DRAW_MODULE 0
+
+/** Do polygon stipple with the util module? */
+#define DO_PSTIPPLE_IN_HELPER_MODULE 1
 
 
 struct softpipe_vbuf_render;
@@ -144,6 +147,13 @@ struct softpipe_context {
    struct pipe_query *render_cond_query;
    uint render_cond_mode;
 
+   /** Polygon stipple items */
+   struct {
+      struct pipe_resource *texture;
+      struct pipe_sampler_state *sampler;
+      struct pipe_sampler_view *sampler_view;
+   } pstipple;
+
    /** Software quad rendering pipeline */
    struct {
       struct quad_stage *shade;
index 01b4ca985d0ea8cbdb212cc2619df3c060f32654..69b5b96b4fd0b6268292ad23c094349cc36218b5 100644 (file)
@@ -64,7 +64,7 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode)
    sp->reduced_api_prim = u_reduced_prim(mode);
 
    if (sp->dirty) {
-      softpipe_update_derived(sp);
+      softpipe_update_derived(sp, sp->reduced_api_prim);
    }
 
    softpipe_map_transfers(sp);
@@ -122,7 +122,7 @@ softpipe_draw_vbo(struct pipe_context *pipe,
    sp->reduced_api_prim = u_reduced_prim(info->mode);
 
    if (sp->dirty) {
-      softpipe_update_derived(sp);
+      softpipe_update_derived(sp, sp->reduced_api_prim);
    }
 
    softpipe_map_transfers(sp);
index a98f8b7bde5f99bcff9dd7862325d4b86e03fe83..0c4506ae8f4b3c3690b819c9f1cb8595d1bbec22 100644 (file)
@@ -61,7 +61,7 @@ sp_build_quad_pipeline(struct softpipe_context *sp)
       insert_stage_at_head( sp, sp->quad.shade );
    }
 
-#if !DO_PSTIPPLE_IN_DRAW_MODULE
+#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
    if (sp->rasterizer->poly_stipple_enable)
       insert_stage_at_head( sp, sp->quad.pstipple );
 #endif
index b82594ca2a5433482255e7ffa1e8530433777dae..656d001809fa2789dbb9957b77f1b6b0f3c63037 100644 (file)
@@ -1397,7 +1397,7 @@ sp_setup_prepare(struct setup_context *setup)
    struct softpipe_context *sp = setup->softpipe;
 
    if (sp->dirty) {
-      softpipe_update_derived(sp);
+      softpipe_update_derived(sp, sp->reduced_api_prim);
    }
 
    /* Note: nr_attrs is only used for debugging (vertex printing) */
index 243f7aab8ba29ffbfde32482e3297e4c84f38439..ec4c8cf5e4dd530bd4167f0e66c26789f6191d53 100644 (file)
@@ -62,7 +62,7 @@ struct vertex_info;
 
 struct sp_fragment_shader_variant_key
 {
-   int foo;  /* XXX temporary */
+   boolean polygon_stipple;
 };
 
 
@@ -72,6 +72,8 @@ struct sp_fragment_shader_variant
    struct sp_fragment_shader_variant_key key;
    struct tgsi_shader_info info;
 
+   unsigned stipple_sampler_unit;
+
    /* See comments about this elsewhere */
 #if 0
    struct draw_fragment_shader *draw_shader;
@@ -150,7 +152,7 @@ softpipe_set_framebuffer_state(struct pipe_context *,
                                const struct pipe_framebuffer_state *);
 
 void
-softpipe_update_derived(struct softpipe_context *softpipe);
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim);
 
 void
 softpipe_draw_vbo(struct pipe_context *pipe,
@@ -179,6 +181,12 @@ struct vertex_info *
 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
 
 
+struct sp_fragment_shader_variant *
+softpipe_find_fs_variant(struct softpipe_context *softpipe,
+                         struct sp_fragment_shader *fs,
+                         const struct sp_fragment_shader_variant_key *key);
+
+
 struct sp_fragment_shader_variant *
 softpipe_find_fs_variant(struct softpipe_context *softpipe,
                          struct sp_fragment_shader *fs,
index 583d0bd9f7bce438e27f3044ced59ef2d795629c..fd688089a3e6a2bd317a5ff8abd035538ef6c949 100644 (file)
  * 
  **************************************************************************/
 
+#include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_pstipple.h"
 #include "pipe/p_shader_tokens.h"
 #include "draw/draw_context.h"
 #include "draw/draw_vertex.h"
@@ -242,12 +244,15 @@ update_tgsi_samplers( struct softpipe_context *softpipe )
 
 
 static void
-update_fragment_shader(struct softpipe_context *softpipe)
+update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
 {
    struct sp_fragment_shader_variant_key key;
 
    memset(&key, 0, sizeof(key));
 
+   if (prim == PIPE_PRIM_TRIANGLES)
+      key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
+
    if (softpipe->fs) {
       softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
                                                       softpipe->fs, &key);
@@ -276,11 +281,63 @@ update_fragment_shader(struct softpipe_context *softpipe)
 }
 
 
+/**
+ * This should be called when the polygon stipple pattern changes.
+ * We create a new texture from the stipple pattern and create a new
+ * sampler view.
+ */
+static void
+update_polygon_stipple_pattern(struct softpipe_context *softpipe)
+{
+   struct pipe_resource *tex;
+   struct pipe_sampler_view *view;
+
+   tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
+                                              softpipe->poly_stipple.stipple);
+   pipe_resource_reference(&softpipe->pstipple.texture, tex);
+
+   view = util_pstipple_create_sampler_view(&softpipe->pipe, tex);
+   pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
+}
+
+
+/**
+ * Should be called when polygon stipple is enabled/disabled or when
+ * the fragment shader changes.
+ * We add/update the fragment sampler and sampler views to sample from
+ * the polygon stipple texture.  The texture unit that we use depends on
+ * the fragment shader (we need to use a unit not otherwise used by the
+ * shader).
+ */
+static void
+update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
+{
+   if (prim == PIPE_PRIM_TRIANGLES &&
+       softpipe->fs_variant->key.polygon_stipple) {
+      const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
+
+      assert(unit >= softpipe->num_fragment_samplers);
+
+      /* sampler state */
+      softpipe->fragment_samplers[unit] = softpipe->pstipple.sampler;
+
+      /* sampler view */
+      pipe_sampler_view_reference(&softpipe->fragment_sampler_views[unit],
+                                  softpipe->pstipple.sampler_view);
+
+      sp_tex_tile_cache_set_sampler_view(softpipe->fragment_tex_cache[unit],
+                                         softpipe->pstipple.sampler_view);
+
+      softpipe->dirty |= SP_NEW_SAMPLER;
+   }
+}
+
+
 /* Hopefully this will remain quite simple, otherwise need to pull in
  * something like the state tracker mechanism.
  */
 void
-softpipe_update_derived(struct softpipe_context *softpipe)
+softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
 {
    struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
 
@@ -290,10 +347,23 @@ softpipe_update_derived(struct softpipe_context *softpipe)
       softpipe->tex_timestamp = sp_screen->timestamp;
       softpipe->dirty |= SP_NEW_TEXTURE;
    }
-      
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+   if (softpipe->dirty & SP_NEW_STIPPLE)
+      /* before updating samplers! */
+      update_polygon_stipple_pattern(softpipe);
+#endif
+
    if (softpipe->dirty & (SP_NEW_RASTERIZER |
                           SP_NEW_FS))
-      update_fragment_shader(softpipe);
+      update_fragment_shader(softpipe, prim);
+
+#if DO_PSTIPPLE_IN_HELPER_MODULE
+   if (softpipe->dirty & (SP_NEW_RASTERIZER |
+                          SP_NEW_STIPPLE |
+                          SP_NEW_FS))
+      update_polygon_stipple_enable(softpipe, prim);
+#endif
 
    if (softpipe->dirty & (SP_NEW_SAMPLER |
                           SP_NEW_TEXTURE |
index ddb9a98b45f02f555c50cbc031299024c161ecd0..da895270aa97b398b1ad248b455a9e71d0b8fa30 100644 (file)
@@ -33,6 +33,7 @@
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
 #include "util/u_inlines.h"
+#include "util/u_pstipple.h"
 #include "draw/draw_context.h"
 #include "draw/draw_vs.h"
 #include "draw/draw_gs.h"
@@ -51,7 +52,15 @@ create_fs_variant(struct softpipe_context *softpipe,
                   const struct sp_fragment_shader_variant_key *key)
 {
    struct sp_fragment_shader_variant *var;
-   struct pipe_shader_state *curfs = &fs->shader;
+   struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
+   unsigned unit = 0;
+
+   if (key->polygon_stipple) {
+      /* get new shader that implements polygon stippling */
+      stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
+                                                        curfs, &unit);
+      curfs = stipple_fs;
+   }
 
    /* codegen, create variant object */
    var = softpipe_create_fs_variant_sse(softpipe, curfs);
@@ -62,6 +71,7 @@ create_fs_variant(struct softpipe_context *softpipe,
    if (var) {
       var->key = *key;
       var->tokens = tgsi_dup_tokens(curfs->tokens);
+      var->stipple_sampler_unit = unit;
 
       tgsi_scan_shader(var->tokens, &var->info);
 
@@ -82,6 +92,11 @@ create_fs_variant(struct softpipe_context *softpipe,
       fs->variants = var;
    }
 
+   if (stipple_fs) {
+      free((void *) stipple_fs->tokens);
+      free(stipple_fs);
+   }
+
    return var;
 }