llvmpipe: turn off draw offset/twoside when we can handle it
authorKeith Whitwell <keithw@vmware.com>
Fri, 22 Oct 2010 17:58:36 +0000 (18:58 +0100)
committerKeith Whitwell <keithw@vmware.com>
Fri, 22 Oct 2010 17:58:36 +0000 (18:58 +0100)
src/gallium/drivers/llvmpipe/lp_state_rasterizer.c

index dbd73812e458ce4541c9e5493c385d9ab21ccb9a..574f9e940efe7eaa4564a385597c5680ada5992c 100644 (file)
 #include "lp_setup.h"
 #include "draw/draw_context.h"
 
+struct lp_rast_state {
+   struct pipe_rasterizer_state lp_state;
+   struct pipe_rasterizer_state draw_state;
+};
+
+/* State which might be handled in either the draw module or locally.
+ * This function is used to turn that state off in one of the two
+ * places.
+ */
+static void
+clear_flags(struct pipe_rasterizer_state *rast)
+{
+   rast->light_twoside = 0;
+   rast->offset_tri = 0;
+}
+
 
 
 static void *
 llvmpipe_create_rasterizer_state(struct pipe_context *pipe,
                                  const struct pipe_rasterizer_state *rast)
 {
-   /* We do nothing special with rasterizer state.
-    * The CSO handle is just a pointer to a pipe_rasterizer_state object.
+   boolean need_pipeline;
+
+   /* Partition rasterizer state into what we want the draw module to
+    * handle, and what we'll look after ourselves.
+    */
+   struct lp_rast_state *state = MALLOC_STRUCT(lp_rast_state);
+   if (state == NULL)
+      return NULL;
+
+   memcpy(&state->draw_state, rast, sizeof *rast);
+   memcpy(&state->lp_state, rast, sizeof *rast);
+
+   /* We rely on draw module to do unfilled polyons, AA lines and
+    * points and stipple.
+    * 
+    * Over time, reduce this list of conditions, and expand the list
+    * of flags which get cleared in clear_flags().
     */
-   return mem_dup(rast, sizeof(*rast));
+   need_pipeline = (rast->fill_front != PIPE_POLYGON_MODE_FILL ||
+                   rast->fill_back != PIPE_POLYGON_MODE_FILL ||
+                   rast->point_smooth ||
+                   rast->line_smooth ||
+                   rast->line_stipple_enable ||
+                   rast->poly_stipple_enable);
+
+   /* If not using the pipeline, clear out the flags which we can
+    * handle ourselves.  If we *are* using the pipeline, do everything
+    * on the pipeline and clear those flags on our internal copy of
+    * the state.
+    */
+   if (need_pipeline)
+      clear_flags(&state->lp_state);
+   else
+      clear_flags(&state->draw_state);
+
+   return state;
 }
 
 
@@ -50,36 +98,33 @@ static void
 llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle)
 {
    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
-   const struct pipe_rasterizer_state *rasterizer =
-      (const struct pipe_rasterizer_state *) handle;
-
-   if (llvmpipe->rasterizer == rasterizer)
-      return;
+   const struct lp_rast_state *state =
+      (const struct lp_rast_state *) handle;
 
-   /* pass-through to draw module */
-   draw_set_rasterizer_state(llvmpipe->draw, rasterizer, handle);
+   if (state) {
+      llvmpipe->rasterizer = &state->lp_state;
+      draw_set_rasterizer_state(llvmpipe->draw, &state->draw_state, handle);
 
-   llvmpipe->rasterizer = rasterizer;
-
-   /* Note: we can immediately set the triangle state here and
-    * not worry about binning because we handle culling during
-    * triangle setup, not when rasterizing the bins.
-    */
-   if (llvmpipe->rasterizer) {
+      /* XXX: just pass lp_state directly to setup.
+       */
       lp_setup_set_triangle_state( llvmpipe->setup,
-                   llvmpipe->rasterizer->cull_face,
-                   llvmpipe->rasterizer->front_ccw,
-                   llvmpipe->rasterizer->scissor,
-                   llvmpipe->rasterizer->gl_rasterization_rules);
+                                  state->lp_state.cull_face,
+                                  state->lp_state.front_ccw,
+                                  state->lp_state.scissor,
+                                  state->lp_state.gl_rasterization_rules);
       lp_setup_set_flatshade_first( llvmpipe->setup,
-                   llvmpipe->rasterizer->flatshade_first);
+                                   state->lp_state.flatshade_first);
       lp_setup_set_line_state( llvmpipe->setup,
-                   llvmpipe->rasterizer->line_width);
+                              state->lp_state.line_width);
       lp_setup_set_point_state( llvmpipe->setup,
-                   llvmpipe->rasterizer->point_size,
-                   llvmpipe->rasterizer->point_size_per_vertex,
-                   llvmpipe->rasterizer->sprite_coord_enable,
-                   llvmpipe->rasterizer->sprite_coord_mode);
+                               state->lp_state.point_size,
+                               state->lp_state.point_size_per_vertex,
+                               state->lp_state.sprite_coord_enable,
+                               state->lp_state.sprite_coord_mode);
+   }
+   else {
+      llvmpipe->rasterizer = NULL;
+      draw_set_rasterizer_state(llvmpipe->draw, NULL, handle);      
    }
 
    llvmpipe->dirty |= LP_NEW_RASTERIZER;