gallium: fix issues in recursive flushing
authorBrian Paul <brian.paul@tungstengraphics.com>
Thu, 24 Apr 2008 00:08:20 +0000 (18:08 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Thu, 24 Apr 2008 00:08:20 +0000 (18:08 -0600)
When flushing/rendering, some stages (like AA line/point) need to set
pipe/driver state.  Those driver functions often call draw_flush().
That leads to recursion.

Use new draw->suspend_flush flag to explicitly prevent that in the key places.
Remove the draw->vcache_flushing field.
Reuse draw->flushing as a debug/assertion var.

src/gallium/auxiliary/draw/draw_context.c
src/gallium/auxiliary/draw/draw_pipe_aaline.c
src/gallium/auxiliary/draw/draw_pipe_aapoint.c
src/gallium/auxiliary/draw/draw_pipe_pstipple.c
src/gallium/auxiliary/draw/draw_private.h
src/gallium/auxiliary/draw/draw_pt_vcache.c

index f901878..98e23fa 100644 (file)
@@ -367,8 +367,10 @@ draw_set_mapped_element_buffer( struct draw_context *draw,
  */
 void draw_do_flush( struct draw_context *draw, unsigned flags )
 {
-   if (!draw->flushing && !draw->vcache_flushing)
+   if (!draw->suspend_flushing)
    {
+      assert(!draw->flushing); /* catch inadvertant recursion */
+
       draw->flushing = TRUE;
 
       draw_pipeline_flush( draw, flags );
index 7e5f8bd..0545dbc 100644 (file)
@@ -485,11 +485,16 @@ aaline_create_sampler(struct aaline_stage *aaline)
 static boolean
 bind_aaline_fragment_shader(struct aaline_stage *aaline)
 {
+   struct draw_context *draw = aaline->stage.draw;
+
    if (!aaline->fs->aaline_fs && 
        !generate_aaline_fs(aaline))
       return FALSE;
 
+   draw->suspend_flushing = TRUE;
    aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs);
+   draw->suspend_flushing = FALSE;
+
    return TRUE;
 }
 
@@ -663,8 +668,10 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
    pipe_texture_reference(&aaline->state.texture[aaline->fs->sampler_unit],
                           aaline->texture);
 
+   draw->suspend_flushing = TRUE;
    aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
    aaline->driver_set_sampler_textures(pipe, num_samplers, aaline->state.texture);
+   draw->suspend_flushing = FALSE;
 
    /* now really draw first line */
    stage->line = aaline_line;
@@ -682,14 +689,14 @@ aaline_flush(struct draw_stage *stage, unsigned flags)
    stage->line = aaline_first_line;
    stage->next->flush( stage->next, flags );
 
-   /* restore original frag shader */
+   /* restore original frag shader, texture, sampler state */
+   draw->suspend_flushing = TRUE;
    aaline->driver_bind_fs_state(pipe, aaline->fs->driver_fs);
-
-   /* XXX restore original texture, sampler state */
    aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
                                       aaline->state.sampler);
    aaline->driver_set_sampler_textures(pipe, aaline->num_textures,
                                        aaline->state.texture);
+   draw->suspend_flushing = FALSE;
 
    draw->extra_vp_outputs.slot = 0;
 }
@@ -783,6 +790,7 @@ aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
 {
    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
    struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
+
    /* save current */
    aaline->fs = aafs;
    /* pass-through */
@@ -807,9 +815,12 @@ aaline_bind_sampler_states(struct pipe_context *pipe,
                            unsigned num, void **sampler)
 {
    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+   struct draw_context *draw = aaline->stage.draw;
+
    /* save current */
    memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
    aaline->num_samplers = num;
+
    /* pass-through */
    aaline->driver_bind_sampler_states(aaline->pipe, num, sampler);
 }
@@ -820,6 +831,7 @@ aaline_set_sampler_textures(struct pipe_context *pipe,
                             unsigned num, struct pipe_texture **texture)
 {
    struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
+   struct draw_context *draw = aaline->stage.draw;
    uint i;
 
    /* save current */
index 8c38c15..122a486 100644 (file)
@@ -537,11 +537,16 @@ generate_aapoint_fs(struct aapoint_stage *aapoint)
 static boolean
 bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
 {
+   struct draw_context *draw = aapoint->stage.draw;
+
    if (!aapoint->fs->aapoint_fs &&
        !generate_aapoint_fs(aapoint))
       return FALSE;
 
+   draw->suspend_flushing = TRUE;
    aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs);
+   draw->suspend_flushing = FALSE;
+
    return TRUE;
 }
 
@@ -714,7 +719,9 @@ aapoint_flush(struct draw_stage *stage, unsigned flags)
    stage->next->flush( stage->next, flags );
 
    /* restore original frag shader */
+   draw->suspend_flushing = TRUE;
    aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs);
+   draw->suspend_flushing = FALSE;
 
    draw->extra_vp_outputs.slot = 0;
 }
index 848d3be..f8156fe 100644 (file)
@@ -467,11 +467,14 @@ pstip_create_sampler(struct pstip_stage *pstip)
 static boolean
 bind_pstip_fragment_shader(struct pstip_stage *pstip)
 {
+   struct draw_context *draw = pstip->stage.draw;
    if (!pstip->fs->pstip_fs &&
        !generate_pstip_fs(pstip))
       return FALSE;
 
+   draw->suspend_flushing = TRUE;
    pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
+   draw->suspend_flushing = FALSE;
    return TRUE;
 }
 
@@ -488,6 +491,7 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
 {
    struct pstip_stage *pstip = pstip_stage(stage);
    struct pipe_context *pipe = pstip->pipe;
+   struct draw_context *draw = stage->draw;
    uint num_samplers;
 
    assert(stage->draw->rasterizer->poly_stipple_enable);
@@ -512,8 +516,10 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
 
    assert(num_samplers <= PIPE_MAX_SAMPLERS);
 
+   draw->suspend_flushing = TRUE;
    pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
    pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures);
+   draw->suspend_flushing = FALSE;
 
    /* now really draw first triangle */
    stage->tri = draw_pipe_passthrough_tri;
@@ -524,7 +530,7 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
 static void
 pstip_flush(struct draw_stage *stage, unsigned flags)
 {
-   /*struct draw_context *draw = stage->draw;*/
+   struct draw_context *draw = stage->draw;
    struct pstip_stage *pstip = pstip_stage(stage);
    struct pipe_context *pipe = pstip->pipe;
 
@@ -534,11 +540,13 @@ pstip_flush(struct draw_stage *stage, unsigned flags)
    /* restore original frag shader */
    pstip->driver_bind_fs_state(pipe, pstip->fs->driver_fs);
 
-   /* XXX restore original texture, sampler state */
+   /* restore original texture, sampler state */
+   draw->suspend_flushing = TRUE;
    pstip->driver_bind_sampler_states(pipe, pstip->num_samplers,
                                      pstip->state.samplers);
    pstip->driver_set_sampler_textures(pipe, pstip->num_textures,
                                       pstip->state.textures);
+   draw->suspend_flushing = FALSE;
 }
 
 
@@ -661,6 +669,7 @@ pstip_set_sampler_textures(struct pipe_context *pipe,
                            unsigned num, struct pipe_texture **texture)
 {
    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+   struct draw_context *draw = pstip->stage.draw;
    uint i;
 
    /* save current */
@@ -683,8 +692,11 @@ pstip_set_polygon_stipple(struct pipe_context *pipe,
                           const struct pipe_poly_stipple *stipple)
 {
    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
+   struct draw_context *draw = (struct draw_context *) pipe->draw;
+
    /* save current */
    pstip->state.stipple = stipple;
+
    /* pass-through */
    pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
 
index 39aa81b..ca5021c 100644 (file)
@@ -178,9 +178,9 @@ struct draw_context
       boolean bypass_clipping;
    } driver;
 
-   boolean flushing;
-   boolean vcache_flushing;
-   boolean bypass_clipping;     /* set if either api or driver bypass_clipping true */
+   boolean flushing;         /**< debugging/sanity */
+   boolean suspend_flushing; /**< internally set */
+   boolean bypass_clipping;  /**< set if either api or driver bypass_clipping true */
 
    /* pipe state that we need: */
    const struct pipe_rasterizer_state *rasterizer;
index afcff41..1530554 100644 (file)
@@ -63,7 +63,6 @@ struct vcache_frontend {
 
 static void vcache_flush( struct vcache_frontend *vcache )
 {
-   vcache->draw->vcache_flushing = TRUE;
    if (vcache->draw_count) {
       vcache->middle->run( vcache->middle,
                            vcache->fetch_elts,
@@ -75,7 +74,6 @@ static void vcache_flush( struct vcache_frontend *vcache )
    memset(vcache->in, ~0, sizeof(vcache->in));
    vcache->fetch_count = 0;
    vcache->draw_count = 0;
-   vcache->draw->vcache_flushing = FALSE;
 }
 
 static void vcache_check_flush( struct vcache_frontend *vcache )