Hi,

Because some hardware under some circumstances (e.g. disabled tiling)
may not be able to use a hardware-specific clear path, it would be
nice to let a state tracker do the clearing by drawing a
screen-aligned quad. I am proposing to change the pipe_context->clear
function to return TRUE if buffers were cleared by the driver, and
FALSE if the state tracker should do the clearing by taking a generic
path.

As an example, r300g can use the fast clearing only if colorbuffers
and zbuffers are micro-tiled, otherwise it must draw a screen-aligned
quad and doing it in the driver is really messy.

The attached patch implements this interface change and adapts all
state trackers and drivers.

I noticed that a lot of drivers still use slow util_clear, so they
will greatly benefit from this patch. It's up to their maintainers
whether they enable it, I suspect some unstable drivers may not be
able to draw a quad without visual errors.

Please review.

Best regards
Marek Olšák
From a6d16e7bce330900d496593054ec6aeb3ed51a2f Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Marek=20Ol=C5=A1=C3=A1k?= <mar...@gmail.com>
Date: Mon, 7 Dec 2009 00:33:17 +0100
Subject: [PATCH] gallium: let drivers fallback on framebuffer clearing

A driver can either clear a framebuffer by itself or can tell the state tracker
to draw a screen-aligned quad if a hardware-specific clear path is not
available.
---
 src/gallium/drivers/cell/ppu/cell_clear.c    |    4 +++-
 src/gallium/drivers/cell/ppu/cell_clear.h    |    3 ++-
 src/gallium/drivers/i915/i915_clear.c        |    3 ++-
 src/gallium/drivers/i915/i915_context.h      |    4 ++--
 src/gallium/drivers/identity/id_context.c    |   12 ++++++------
 src/gallium/drivers/llvmpipe/lp_clear.c      |    4 +++-
 src/gallium/drivers/llvmpipe/lp_clear.h      |    2 +-
 src/gallium/drivers/nv04/nv04_clear.c        |   10 ++++++----
 src/gallium/drivers/nv04/nv04_context.h      |    4 ++--
 src/gallium/drivers/nv10/nv10_clear.c        |    3 ++-
 src/gallium/drivers/nv10/nv10_context.h      |    2 +-
 src/gallium/drivers/nv20/nv20_clear.c        |    3 ++-
 src/gallium/drivers/nv20/nv20_context.h      |    2 +-
 src/gallium/drivers/nv30/nv30_clear.c        |    3 ++-
 src/gallium/drivers/nv30/nv30_context.h      |    2 +-
 src/gallium/drivers/nv40/nv40_clear.c        |    3 ++-
 src/gallium/drivers/nv40/nv40_context.h      |    2 +-
 src/gallium/drivers/nv50/nv50_clear.c        |    4 +++-
 src/gallium/drivers/nv50/nv50_context.h      |    2 +-
 src/gallium/drivers/r300/r300_clear.c        |   11 ++++++-----
 src/gallium/drivers/r300/r300_clear.h        |   12 +++++++-----
 src/gallium/drivers/softpipe/sp_clear.c      |    5 +++--
 src/gallium/drivers/softpipe/sp_clear.h      |    2 +-
 src/gallium/drivers/svga/svga_context.h      |   10 +++++-----
 src/gallium/drivers/svga/svga_pipe_clear.c   |    3 ++-
 src/gallium/drivers/trace/tr_context.c       |    7 +++++--
 src/gallium/include/pipe/p_context.h         |    4 +++-
 src/gallium/state_trackers/vega/api_masks.c  |   11 +++++++----
 src/gallium/state_trackers/vega/vg_context.c |    6 +++++-
 src/gallium/state_trackers/vega/vg_tracker.c |    8 ++++++--
 src/gallium/state_trackers/xorg/xorg_exa.c   |    7 +++++--
 src/mesa/state_tracker/st_cb_clear.c         |   12 +++++++++---
 32 files changed, 107 insertions(+), 63 deletions(-)

diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c
index 79ad687..553d924 100644
--- a/src/gallium/drivers/cell/ppu/cell_clear.c
+++ b/src/gallium/drivers/cell/ppu/cell_clear.c
@@ -48,7 +48,7 @@
 /**
  * Called via pipe->clear()
  */
-void
+boolean
 cell_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
            double depth, unsigned stencil)
 {
@@ -89,4 +89,6 @@ cell_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
       clr->surface = surfIndex;
       clr->value = clearValue;
    }
+
+   return TRUE;
 }
diff --git a/src/gallium/drivers/cell/ppu/cell_clear.h b/src/gallium/drivers/cell/ppu/cell_clear.h
index 08e091a..9fc3a01 100644
--- a/src/gallium/drivers/cell/ppu/cell_clear.h
+++ b/src/gallium/drivers/cell/ppu/cell_clear.h
@@ -29,11 +29,12 @@
 #ifndef CELL_CLEAR_H
 #define CELL_CLEAR_H
 
+#include "pipe/p_compiler.h"
 
 struct pipe_context;
 
 
-extern void
+extern boolean
 cell_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
            double depth, unsigned stencil);
 
diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c
index 90530f2..21528e5 100644
--- a/src/gallium/drivers/i915/i915_clear.c
+++ b/src/gallium/drivers/i915/i915_clear.c
@@ -39,10 +39,11 @@
  * Clear the given buffers to the specified values.
  * No masking, no scissor (clear entire buffer).
  */
-void
+boolean
 i915_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
 	   double depth, unsigned stencil)
 {
    util_clear(pipe, &i915_context(pipe)->framebuffer, buffers, rgba, depth,
               stencil);
+   return TRUE;
 }
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index 234b441..5925a18 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -319,8 +319,8 @@ void i915_emit_hardware_state(struct i915_context *i915 );
 /***********************************************************************
  * i915_clear.c: 
  */
-void i915_clear( struct pipe_context *pipe, unsigned buffers, const float *rgba,
-                 double depth, unsigned stencil);
+boolean i915_clear( struct pipe_context *pipe, unsigned buffers, const float *rgba,
+                    double depth, unsigned stencil);
 
 
 /***********************************************************************
diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c
index 4509c7b..26152ab 100644
--- a/src/gallium/drivers/identity/id_context.c
+++ b/src/gallium/drivers/identity/id_context.c
@@ -630,7 +630,7 @@ identity_surface_fill(struct pipe_context *_pipe,
                       value);
 }
 
-static void
+static boolean
 identity_clear(struct pipe_context *_pipe,
                unsigned buffers,
                const float *rgba,
@@ -640,11 +640,11 @@ identity_clear(struct pipe_context *_pipe,
    struct identity_context *id_pipe = identity_context(_pipe);
    struct pipe_context *pipe = id_pipe->pipe;
 
-   pipe->clear(pipe,
-               buffers,
-               rgba,
-               depth,
-               stencil);
+   return pipe->clear(pipe,
+                      buffers,
+                      rgba,
+                      depth,
+                      stencil);
 }
 
 static void
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.c b/src/gallium/drivers/llvmpipe/lp_clear.c
index bdcff94..807f8d2 100644
--- a/src/gallium/drivers/llvmpipe/lp_clear.c
+++ b/src/gallium/drivers/llvmpipe/lp_clear.c
@@ -45,7 +45,7 @@
  * Clear the given buffers to the specified values.
  * No masking, no scissor (clear entire buffer).
  */
-void
+boolean
 llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
                double depth, unsigned stencil)
 {
@@ -78,4 +78,6 @@ llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
       /* non-cached surface */
       pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
    }
+
+   return TRUE;
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.h b/src/gallium/drivers/llvmpipe/lp_clear.h
index 6d4ffcc..8a827f2 100644
--- a/src/gallium/drivers/llvmpipe/lp_clear.h
+++ b/src/gallium/drivers/llvmpipe/lp_clear.h
@@ -35,7 +35,7 @@
 #include "pipe/p_state.h"
 struct pipe_context;
 
-extern void
+extern boolean
 llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
                double depth, unsigned stencil);
 
diff --git a/src/gallium/drivers/nv04/nv04_clear.c b/src/gallium/drivers/nv04/nv04_clear.c
index 01cacd3..ba16aee 100644
--- a/src/gallium/drivers/nv04/nv04_clear.c
+++ b/src/gallium/drivers/nv04/nv04_clear.c
@@ -1,12 +1,14 @@
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
+#include "util/u_clear.h"
 
 #include "nv04_context.h"
 
-void
-nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
-	   unsigned clearValue)
+boolean
+nv04_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
+	   double depth, unsigned stencil)
 {
-	pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue);
+	util_clear(pipe, nv04_context(pipe)->framebuffer, buffers, rgba, depth, stencil);
+	return TRUE;
 }
diff --git a/src/gallium/drivers/nv04/nv04_context.h b/src/gallium/drivers/nv04/nv04_context.h
index 55326c7..a0acea1 100644
--- a/src/gallium/drivers/nv04/nv04_context.h
+++ b/src/gallium/drivers/nv04/nv04_context.h
@@ -118,8 +118,8 @@ extern void nv04_init_surface_functions(struct nv04_context *nv04);
 extern void nv04_screen_init_miptree_functions(struct pipe_screen *screen);
 
 /* nv04_clear.c */
-extern void nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps,
-		       unsigned clearValue);
+extern boolean nv04_clear(struct pipe_context *pipe, unsigned buffers,
+		       const float *rgba, double depth, unsigned stencil);
 
 /* nv04_draw.c */
 extern struct draw_stage *nv04_draw_render_stage(struct nv04_context *nv04);
diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c
index a39a2b5..f8c6a04 100644
--- a/src/gallium/drivers/nv10/nv10_clear.c
+++ b/src/gallium/drivers/nv10/nv10_clear.c
@@ -5,10 +5,11 @@
 
 #include "nv10_context.h"
 
-void
+boolean
 nv10_clear(struct pipe_context *pipe, unsigned buffers,
            const float *rgba, double depth, unsigned stencil)
 {
 	util_clear(pipe, nv10_context(pipe)->framebuffer, buffers, rgba, depth,
 		   stencil);
+	return TRUE;
 }
diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h
index 36a6aa7..3716f17 100644
--- a/src/gallium/drivers/nv10/nv10_context.h
+++ b/src/gallium/drivers/nv10/nv10_context.h
@@ -119,7 +119,7 @@ extern void nv10_init_surface_functions(struct nv10_context *nv10);
 extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen);
 
 /* nv10_clear.c */
-extern void nv10_clear(struct pipe_context *pipe, unsigned buffers,
+extern boolean nv10_clear(struct pipe_context *pipe, unsigned buffers,
 		       const float *rgba, double depth, unsigned stencil);
 
 
diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c
index 2b4490f..2d77360 100644
--- a/src/gallium/drivers/nv20/nv20_clear.c
+++ b/src/gallium/drivers/nv20/nv20_clear.c
@@ -5,10 +5,11 @@
 
 #include "nv20_context.h"
 
-void
+boolean
 nv20_clear(struct pipe_context *pipe, unsigned buffers,
            const float *rgba, double depth, unsigned stencil)
 {
 	util_clear(pipe, nv20_context(pipe)->framebuffer, buffers, rgba, depth,
 		   stencil);
+	return TRUE;
 }
diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h
index a4eaa95..03e4288 100644
--- a/src/gallium/drivers/nv20/nv20_context.h
+++ b/src/gallium/drivers/nv20/nv20_context.h
@@ -119,7 +119,7 @@ extern void nv20_init_surface_functions(struct nv20_context *nv20);
 extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen);
 
 /* nv20_clear.c */
-extern void nv20_clear(struct pipe_context *pipe, unsigned buffers,
+extern boolean nv20_clear(struct pipe_context *pipe, unsigned buffers,
 		       const float *rgba, double depth, unsigned stencil);
 
 /* nv20_draw.c */
diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c
index c4ba926..8519f79 100644
--- a/src/gallium/drivers/nv30/nv30_clear.c
+++ b/src/gallium/drivers/nv30/nv30_clear.c
@@ -5,10 +5,11 @@
 
 #include "nv30_context.h"
 
-void
+boolean
 nv30_clear(struct pipe_context *pipe, unsigned buffers,
            const float *rgba, double depth, unsigned stencil)
 {
 	util_clear(pipe, &nv30_context(pipe)->framebuffer, buffers, rgba, depth,
 		   stencil);
+	return TRUE;
 }
diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h
index 8d49366..806a4e5 100644
--- a/src/gallium/drivers/nv30/nv30_context.h
+++ b/src/gallium/drivers/nv30/nv30_context.h
@@ -207,7 +207,7 @@ extern boolean nv30_draw_elements(struct pipe_context *pipe,
 				  unsigned count);
 
 /* nv30_clear.c */
-extern void nv30_clear(struct pipe_context *pipe, unsigned buffers,
+extern boolean nv30_clear(struct pipe_context *pipe, unsigned buffers,
 		       const float *rgba, double depth, unsigned stencil);
 
 #endif
diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nv40/nv40_clear.c
index ddf13ad..109c3fe 100644
--- a/src/gallium/drivers/nv40/nv40_clear.c
+++ b/src/gallium/drivers/nv40/nv40_clear.c
@@ -5,10 +5,11 @@
 
 #include "nv40_context.h"
 
-void
+boolean
 nv40_clear(struct pipe_context *pipe, unsigned buffers,
            const float *rgba, double depth, unsigned stencil)
 {
 	util_clear(pipe, &nv40_context(pipe)->framebuffer, buffers, rgba, depth,
 		   stencil);
+	return TRUE;
 }
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index a3d5941..d2cf3f1 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -228,7 +228,7 @@ extern boolean nv40_draw_elements(struct pipe_context *pipe,
 				  unsigned count);
 
 /* nv40_clear.c */
-extern void nv40_clear(struct pipe_context *pipe, unsigned buffers,
+extern boolean nv40_clear(struct pipe_context *pipe, unsigned buffers,
 		       const float *rgba, double depth, unsigned stencil);
 
 #endif
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
index e0b2d28..aac3a93 100644
--- a/src/gallium/drivers/nv50/nv50_clear.c
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -26,7 +26,7 @@
 
 #include "nv50_context.h"
 
-void
+boolean
 nv50_clear(struct pipe_context *pipe, unsigned buffers,
 	   const float *rgba, double depth, unsigned stencil)
 {
@@ -64,5 +64,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,
 		BEGIN_RING(chan, tesla, NV50TCL_CLEAR_BUFFERS, 1);
 		OUT_RING  (chan, (i << 6) | 0x3c);
 	}
+
+	return TRUE;
 }
 
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 4b0f062..f08d46b 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -201,7 +201,7 @@ extern boolean nv50_draw_elements(struct pipe_context *pipe,
 extern void nv50_vbo_validate(struct nv50_context *nv50);
 
 /* nv50_clear.c */
-extern void nv50_clear(struct pipe_context *pipe, unsigned buffers,
+extern boolean nv50_clear(struct pipe_context *pipe, unsigned buffers,
 		       const float *rgba, double depth, unsigned stencil);
 
 /* nv50_program.c */
diff --git a/src/gallium/drivers/r300/r300_clear.c b/src/gallium/drivers/r300/r300_clear.c
index 02d6d50..f67afb9 100644
--- a/src/gallium/drivers/r300/r300_clear.c
+++ b/src/gallium/drivers/r300/r300_clear.c
@@ -26,13 +26,14 @@
 #include "util/u_clear.h"
 
 /* Clears currently bound buffers. */
-void r300_clear(struct pipe_context* pipe,
-                unsigned buffers,
-                const float* rgba,
-                double depth,
-                unsigned stencil)
+boolean r300_clear(struct pipe_context* pipe,
+                   unsigned buffers,
+                   const float* rgba,
+                   double depth,
+                   unsigned stencil)
 {
     /* XXX we can and should do one clear if both color and zs are set */
     util_clear(pipe, &r300_context(pipe)->framebuffer_state,
             buffers, rgba, depth, stencil);
+    return TRUE;
 }
diff --git a/src/gallium/drivers/r300/r300_clear.h b/src/gallium/drivers/r300/r300_clear.h
index b8fcdf2..c25638c 100644
--- a/src/gallium/drivers/r300/r300_clear.h
+++ b/src/gallium/drivers/r300/r300_clear.h
@@ -23,12 +23,14 @@
 #ifndef R300_CLEAR_H
 #define R300_CLEAR_H
 
+#include "pipe/p_compiler.h"
+
 struct pipe_context;
 
-void r300_clear(struct pipe_context* pipe,
-                unsigned buffers,
-                const float* rgba,
-                double depth,
-                unsigned stencil);
+boolean r300_clear(struct pipe_context* pipe,
+                   unsigned buffers,
+                   const float* rgba,
+                   double depth,
+                   unsigned stencil);
 
 #endif /* R300_CLEAR_H */
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c
index 8fac8e6..1d49aa2 100644
--- a/src/gallium/drivers/softpipe/sp_clear.c
+++ b/src/gallium/drivers/softpipe/sp_clear.c
@@ -43,7 +43,7 @@
  * Clear the given buffers to the specified values.
  * No masking, no scissor (clear entire buffer).
  */
-void
+boolean
 softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
                double depth, unsigned stencil)
 {
@@ -52,7 +52,7 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
    uint i;
 
    if (softpipe->no_rast)
-      return;
+      return TRUE;
 
 #if 0
    softpipe_update_derived(softpipe); /* not needed?? */
@@ -86,4 +86,5 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
    }
 
    softpipe->dirty_render_cache = TRUE;
+   return TRUE;
 }
diff --git a/src/gallium/drivers/softpipe/sp_clear.h b/src/gallium/drivers/softpipe/sp_clear.h
index 9be3b86..1b7cb27 100644
--- a/src/gallium/drivers/softpipe/sp_clear.h
+++ b/src/gallium/drivers/softpipe/sp_clear.h
@@ -34,7 +34,7 @@
 
 struct pipe_context;
 
-extern void
+extern boolean
 softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
                double depth, unsigned stencil);
 
diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h
index e650a25..09ca770 100644
--- a/src/gallium/drivers/svga/svga_context.h
+++ b/src/gallium/drivers/svga/svga_context.h
@@ -391,11 +391,11 @@ struct svga_context
 /***********************************************************************
  * svga_clear.c: 
  */
-void svga_clear(struct pipe_context *pipe, 
-                unsigned buffers,
-                const float *rgba,
-                double depth,
-                unsigned stencil);
+boolean svga_clear(struct pipe_context *pipe,
+                   unsigned buffers,
+                   const float *rgba,
+                   double depth,
+                   unsigned stencil);
 
 
 /***********************************************************************
diff --git a/src/gallium/drivers/svga/svga_pipe_clear.c b/src/gallium/drivers/svga/svga_pipe_clear.c
index 6195c38..8e7694f 100644
--- a/src/gallium/drivers/svga/svga_pipe_clear.c
+++ b/src/gallium/drivers/svga/svga_pipe_clear.c
@@ -94,7 +94,7 @@ try_clear(struct svga_context *svga,
  * Clear the given surface to the specified value.
  * No masking, no scissor (clear entire buffer).
  */
-void
+boolean
 svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
 	   double depth, unsigned stencil)
 {
@@ -122,4 +122,5 @@ svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
    svga_mark_surfaces_dirty(svga);
 
    assert (ret == PIPE_OK);
+   return TRUE;
 }
diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c
index 2f0f063..dee0dcf 100644
--- a/src/gallium/drivers/trace/tr_context.c
+++ b/src/gallium/drivers/trace/tr_context.c
@@ -1149,7 +1149,7 @@ trace_context_surface_fill(struct pipe_context *_pipe,
 }
 
 
-static INLINE void
+static INLINE boolean
 trace_context_clear(struct pipe_context *_pipe,
                     unsigned buffers,
                     const float *rgba,
@@ -1158,6 +1158,7 @@ trace_context_clear(struct pipe_context *_pipe,
 {
    struct trace_context *tr_ctx = trace_context(_pipe);
    struct pipe_context *pipe = tr_ctx->pipe;
+   boolean result;
 
    trace_dump_call_begin("pipe_context", "clear");
 
@@ -1167,9 +1168,11 @@ trace_context_clear(struct pipe_context *_pipe,
    trace_dump_arg(float, depth);
    trace_dump_arg(uint, stencil);
 
-   pipe->clear(pipe, buffers, rgba, depth, stencil);
+   result = pipe->clear(pipe, buffers, rgba, depth, stencil);
 
+   trace_dump_ret(bool, result);
    trace_dump_call_end();
+   return result;
 }
 
 
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index f896001..c994ae6 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -233,8 +233,10 @@ struct pipe_context {
     * \param rgba  pointer to an array of one float for each of r, g, b, a.
     * \param depth  depth clear value in [0,1].
     * \param stencil  stencil clear value
+    * \return FALSE if the pipe driver wants the state tracker to clear buffers
+    *         with a quad
     */
-   void (*clear)(struct pipe_context *pipe,
+   boolean (*clear)(struct pipe_context *pipe,
                  unsigned buffers,
 		 const float *rgba,
                  double depth,
diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c
index 4f9f3da..92105d5 100644
--- a/src/gallium/state_trackers/vega/api_masks.c
+++ b/src/gallium/state_trackers/vega/api_masks.c
@@ -219,11 +219,14 @@ void vgClear(VGint x, VGint y,
    /* check for a whole surface clear */
    if (!ctx->state.vg.scissoring &&
        (x == 0 && y == 0 && width == fb->width && height == fb->height)) {
-      ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
-                       ctx->state.vg.clear_color, 1., 0);
-   } else {
-      clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color);
+      if (ctx->pipe->clear(ctx->pipe,
+                           PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+                           ctx->state.vg.clear_color, 1., 0)) {
+         return;
+      }
    }
+
+   clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color);
 }
 
 
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
index 00d23f5..19e0163 100644
--- a/src/gallium/state_trackers/vega/vg_context.c
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -39,6 +39,7 @@
 
 #include "cso_cache/cso_context.h"
 
+#include "util/u_clear.h"
 #include "util/u_simple_shaders.h"
 #include "util/u_memory.h"
 #include "util/u_blit.h"
@@ -249,7 +250,10 @@ static void update_clip_state(struct vg_context *ctx)
                                      ctx->pass_through_depth_fs->driver);
       cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
 
-      ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
+      if (!ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0)) {
+         /* XXX optimize */
+         util_clear(ctx->pipe, fb, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
+      }
 
       /* disable color writes */
       blend->colormask = 0; /*disable colorwrites*/
diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c
index 5a286b1..610657e 100644
--- a/src/gallium/state_trackers/vega/vg_tracker.c
+++ b/src/gallium/state_trackers/vega/vg_tracker.c
@@ -31,6 +31,7 @@
 #include "pipe/p_context.h"
 #include "pipe/p_inlines.h"
 #include "pipe/p_screen.h"
+#include "util/u_clear.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
 #include "util/u_rect.h"
@@ -312,8 +313,11 @@ void st_resize_framebuffer(struct st_framebuffer *stfb,
    ctx->state.dirty |= VIEWPORT_DIRTY;
    ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
 
-   ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
-                    NULL, 0.0, 0);
+   if (!ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL,
+                         NULL, 0.0, 0)) {
+      /* XXX optimize */
+      util_clear(ctx->pipe, state, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
+   }
 
    /* we need all the other state already set */
 
diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c
index 55b87ae..3c51759 100644
--- a/src/gallium/state_trackers/xorg/xorg_exa.c
+++ b/src/gallium/state_trackers/xorg/xorg_exa.c
@@ -43,6 +43,7 @@
 #include "pipe/p_state.h"
 #include "pipe/p_inlines.h"
 
+#include "util/u_clear.h"
 #include "util/u_rect.h"
 #include "util/u_math.h"
 #include "util/u_debug.h"
@@ -378,8 +379,10 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1)
 
     if (x0 == 0 && y0 == 0 &&
         x1 == pPixmap->drawable.width && y1 == pPixmap->drawable.height) {
-       exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, exa->solid_color, 0.0, 0);
-       return;
+        if (exa->pipe->clear(exa->pipe, PIPE_CLEAR_COLOR, exa->solid_color,
+                             0.0, 0)) {
+            return;
+        }
     }
 
     xorg_solid(exa, priv, x0, y0, x1, y1) ;
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index e83b6c9..222300d 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -493,15 +493,21 @@ static void st_clear(GLcontext *ctx, GLbitfield mask)
     * If we're going to use clear_with_quad() for any reason, use it for
     * everything possible.
     */
+   if (!quad_buffers && clear_buffers)
+      if (!ctx->st->pipe->clear(ctx->st->pipe, clear_buffers,
+                                ctx->Color.ClearColor,
+                                ctx->Depth.Clear, ctx->Stencil.Clear)) {
+         /* the pipe driver wants to clear the framebuffer with a quad */
+         quad_buffers = clear_buffers;
+      }
+
    if (quad_buffers) {
       quad_buffers |= clear_buffers;
       clear_with_quad(ctx,
                       quad_buffers & PIPE_CLEAR_COLOR,
                       mask & BUFFER_BIT_DEPTH,
                       mask & BUFFER_BIT_STENCIL);
-   } else if (clear_buffers)
-      ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor,
-                           ctx->Depth.Clear, ctx->Stencil.Clear);
+   }
 
    if (mask & BUFFER_BIT_ACCUM)
       st_clear_accum_buffer(ctx,
-- 
1.6.3.3

------------------------------------------------------------------------------
Join us December 9, 2009 for the Red Hat Virtual Experience,
a free event focused on virtualization and cloud computing. 
Attend in-depth sessions from your desk. Your couch. Anywhere.
http://p.sf.net/sfu/redhat-sfdev2dev
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to