Mesa (staging/20.1): gallium: add pipe cap for scissored clears and pass scissor state to clear() hook

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Apr 29 21:20:09 UTC 2020


Module: Mesa
Branch: staging/20.1
Commit: 1c8bcad81a7ce106b37f1ee4a75b817651d6545e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1c8bcad81a7ce106b37f1ee4a75b817651d6545e

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Tue Mar 24 12:02:51 2020 -0400

gallium: add pipe cap for scissored clears and pass scissor state to clear() hook

this adds a new pipe cap that drivers can support which enables passing buffer
clears with scissor test enabled through to be handled by the driver instead
of having mesa draw a quad

also adjust all existing clear() hooks to have the new parameter

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Reviewed-by: Vasily Khoruzhick <anarsoul at gmail.com>
Reviewed-by: Kristian H. Kristensen <hoegsberg at google.com>
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4310>

---

 src/gallium/auxiliary/driver_ddebug/dd_draw.c    |  9 ++++++--
 src/gallium/auxiliary/driver_ddebug/dd_pipe.h    |  1 +
 src/gallium/auxiliary/driver_noop/noop_pipe.c    |  2 +-
 src/gallium/auxiliary/driver_rbug/rbug_context.c |  2 ++
 src/gallium/auxiliary/driver_trace/tr_context.c  |  6 ++++-
 src/gallium/auxiliary/postprocess/pp_mlaa.c      |  2 +-
 src/gallium/auxiliary/postprocess/pp_run.c       |  2 +-
 src/gallium/auxiliary/util/u_screen.c            |  1 +
 src/gallium/auxiliary/util/u_tests.c             |  2 +-
 src/gallium/auxiliary/util/u_threaded_context.c  |  9 ++++++--
 src/gallium/docs/source/screen.rst               |  2 ++
 src/gallium/drivers/etnaviv/etnaviv_blt.c        |  2 +-
 src/gallium/drivers/etnaviv/etnaviv_rs.c         |  2 +-
 src/gallium/drivers/freedreno/freedreno_draw.c   |  2 +-
 src/gallium/drivers/i915/i915_clear.c            |  2 ++
 src/gallium/drivers/i915/i915_context.h          |  2 ++
 src/gallium/drivers/iris/iris_clear.c            |  1 +
 src/gallium/drivers/lima/lima_draw.c             |  2 +-
 src/gallium/drivers/llvmpipe/lp_clear.c          |  1 +
 src/gallium/drivers/llvmpipe/lp_clear.h          |  1 +
 src/gallium/drivers/nouveau/nv30/nv30_clear.c    |  2 +-
 src/gallium/drivers/nouveau/nv50/nv50_context.h  |  1 +
 src/gallium/drivers/nouveau/nv50/nv50_surface.c  |  2 +-
 src/gallium/drivers/nouveau/nvc0/nvc0_context.h  |  1 +
 src/gallium/drivers/nouveau/nvc0/nvc0_surface.c  |  1 +
 src/gallium/drivers/panfrost/pan_context.c       |  1 +
 src/gallium/drivers/r300/r300_blit.c             |  1 +
 src/gallium/drivers/r600/r600_blit.c             |  1 +
 src/gallium/drivers/radeonsi/si_clear.c          |  1 +
 src/gallium/drivers/softpipe/sp_clear.c          |  1 +
 src/gallium/drivers/softpipe/sp_clear.h          |  1 +
 src/gallium/drivers/svga/svga_pipe_clear.c       |  2 +-
 src/gallium/drivers/swr/swr_clear.cpp            |  1 +
 src/gallium/drivers/tegra/tegra_context.c        |  4 ++--
 src/gallium/drivers/v3d/v3dx_draw.c              |  2 +-
 src/gallium/drivers/vc4/vc4_draw.c               |  2 +-
 src/gallium/drivers/virgl/virgl_context.c        |  1 +
 src/gallium/drivers/zink/zink_context.c          |  1 +
 src/gallium/include/pipe/p_context.h             |  2 ++
 src/gallium/include/pipe/p_defines.h             |  1 +
 src/gallium/state_trackers/nine/nine_state.c     |  2 +-
 src/gallium/tests/graw/clear.c                   |  2 +-
 src/gallium/tests/graw/fs-fragcoord.c            |  1 +
 src/gallium/tests/graw/fs-frontface.c            |  1 +
 src/gallium/tests/graw/fs-test.c                 |  2 +-
 src/gallium/tests/graw/fs-write-z.c              |  1 +
 src/gallium/tests/graw/gs-test.c                 |  2 +-
 src/gallium/tests/graw/occlusion-query.c         |  1 +
 src/gallium/tests/graw/quad-sample.c             |  2 +-
 src/gallium/tests/graw/quad-tex.c                |  2 +-
 src/gallium/tests/graw/shader-leak.c             |  2 +-
 src/gallium/tests/graw/tex-srgb.c                |  2 +-
 src/gallium/tests/graw/tex-swizzle.c             |  2 +-
 src/gallium/tests/graw/tri-gs.c                  |  2 +-
 src/gallium/tests/graw/tri-instanced.c           |  2 +-
 src/gallium/tests/graw/tri-large.c               |  2 +-
 src/gallium/tests/graw/tri.c                     |  2 +-
 src/gallium/tests/graw/vs-test.c                 |  2 +-
 src/gallium/tests/trivial/quad-tex.c             |  2 +-
 src/gallium/tests/trivial/tri.c                  |  2 +-
 src/mesa/state_tracker/st_cb_clear.c             | 28 ++++++++++++++++++++++--
 src/mesa/state_tracker/st_context.h              |  4 ++++
 src/mesa/state_tracker/st_manager.c              |  2 ++
 63 files changed, 114 insertions(+), 38 deletions(-)

diff --git a/src/gallium/auxiliary/driver_ddebug/dd_draw.c b/src/gallium/auxiliary/driver_ddebug/dd_draw.c
index a0414a6cd5e..b93890f4f99 100644
--- a/src/gallium/auxiliary/driver_ddebug/dd_draw.c
+++ b/src/gallium/auxiliary/driver_ddebug/dd_draw.c
@@ -515,6 +515,9 @@ dd_dump_clear(struct dd_draw_state *dstate, struct call_clear *info, FILE *f)
 {
    fprintf(f, "%s:\n", __func__+8);
    DUMP_M(uint, info, buffers);
+   fprintf(f, "  scissor_state: %d,%d %d,%d\n",
+              info->scissor_state.minx, info->scissor_state.miny,
+              info->scissor_state.maxx, info->scissor_state.maxy);
    DUMP_M_ADDR(color_union, info, color);
    DUMP_M(double, info, depth);
    DUMP_M(hex, info, stencil);
@@ -1478,7 +1481,7 @@ dd_context_flush_resource(struct pipe_context *_pipe,
 }
 
 static void
-dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
+dd_context_clear(struct pipe_context *_pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
                  const union pipe_color_union *color, double depth,
                  unsigned stencil)
 {
@@ -1488,12 +1491,14 @@ dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
 
    record->call.type = CALL_CLEAR;
    record->call.info.clear.buffers = buffers;
+   if (scissor_state)
+      record->call.info.clear.scissor_state = *scissor_state;
    record->call.info.clear.color = *color;
    record->call.info.clear.depth = depth;
    record->call.info.clear.stencil = stencil;
 
    dd_before_draw(dctx, record);
-   pipe->clear(pipe, buffers, color, depth, stencil);
+   pipe->clear(pipe, buffers, scissor_state, color, depth, stencil);
    dd_after_draw(dctx, record);
 }
 
diff --git a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h
index 1c3487c2011..cf5d879c2d8 100644
--- a/src/gallium/auxiliary/driver_ddebug/dd_pipe.h
+++ b/src/gallium/auxiliary/driver_ddebug/dd_pipe.h
@@ -93,6 +93,7 @@ struct call_resource_copy_region
 struct call_clear
 {
    unsigned buffers;
+   struct pipe_scissor_state scissor_state;
    union pipe_color_union color;
    double depth;
    unsigned stencil;
diff --git a/src/gallium/auxiliary/driver_noop/noop_pipe.c b/src/gallium/auxiliary/driver_noop/noop_pipe.c
index 4ffff6c1db4..dc6454c9165 100644
--- a/src/gallium/auxiliary/driver_noop/noop_pipe.c
+++ b/src/gallium/auxiliary/driver_noop/noop_pipe.c
@@ -253,7 +253,7 @@ static void noop_texture_subdata(struct pipe_context *pipe,
 /*
  * clear/copy
  */
-static void noop_clear(struct pipe_context *ctx, unsigned buffers,
+static void noop_clear(struct pipe_context *ctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
                        const union pipe_color_union *color, double depth, unsigned stencil)
 {
 }
diff --git a/src/gallium/auxiliary/driver_rbug/rbug_context.c b/src/gallium/auxiliary/driver_rbug/rbug_context.c
index 7c5a2929d89..a36f3377e8c 100644
--- a/src/gallium/auxiliary/driver_rbug/rbug_context.c
+++ b/src/gallium/auxiliary/driver_rbug/rbug_context.c
@@ -921,6 +921,7 @@ rbug_flush_resource(struct pipe_context *_pipe,
 static void
 rbug_clear(struct pipe_context *_pipe,
            unsigned buffers,
+           const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color,
            double depth,
            unsigned stencil)
@@ -931,6 +932,7 @@ rbug_clear(struct pipe_context *_pipe,
    mtx_lock(&rb_pipe->call_mutex);
    pipe->clear(pipe,
                buffers,
+               scissor_state,
                color,
                depth,
                stencil);
diff --git a/src/gallium/auxiliary/driver_trace/tr_context.c b/src/gallium/auxiliary/driver_trace/tr_context.c
index 083458dc147..4b19b6c31fa 100644
--- a/src/gallium/auxiliary/driver_trace/tr_context.c
+++ b/src/gallium/auxiliary/driver_trace/tr_context.c
@@ -1175,6 +1175,7 @@ trace_context_flush_resource(struct pipe_context *_pipe,
 static void
 trace_context_clear(struct pipe_context *_pipe,
                     unsigned buffers,
+                    const struct pipe_scissor_state *scissor_state,
                     const union pipe_color_union *color,
                     double depth,
                     unsigned stencil)
@@ -1186,6 +1187,9 @@ trace_context_clear(struct pipe_context *_pipe,
 
    trace_dump_arg(ptr, pipe);
    trace_dump_arg(uint, buffers);
+   trace_dump_arg_begin("scissor_state");
+   trace_dump_scissor_state(scissor_state);
+   trace_dump_arg_end();
    trace_dump_arg_begin("color");
    if (color)
       trace_dump_array(float, color->f, 4);
@@ -1195,7 +1199,7 @@ trace_context_clear(struct pipe_context *_pipe,
    trace_dump_arg(float, depth);
    trace_dump_arg(uint, stencil);
 
-   pipe->clear(pipe, buffers, color, depth, stencil);
+   pipe->clear(pipe, buffers, scissor_state, color, depth, stencil);
 
    trace_dump_call_end();
 }
diff --git a/src/gallium/auxiliary/postprocess/pp_mlaa.c b/src/gallium/auxiliary/postprocess/pp_mlaa.c
index e3ce5eaf015..51e3e0260fa 100644
--- a/src/gallium/auxiliary/postprocess/pp_mlaa.c
+++ b/src/gallium/auxiliary/postprocess/pp_mlaa.c
@@ -122,7 +122,7 @@ pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
    pp_filter_set_fb(p);
    pp_filter_misc_state(p);
    cso_set_depth_stencil_alpha(p->cso, &mstencil);
-   p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR0,
+   p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR0, NULL,
                   &p->clear_color, 0, 0);
 
    {
diff --git a/src/gallium/auxiliary/postprocess/pp_run.c b/src/gallium/auxiliary/postprocess/pp_run.c
index 813225332fc..c6987153f73 100644
--- a/src/gallium/auxiliary/postprocess/pp_run.c
+++ b/src/gallium/auxiliary/postprocess/pp_run.c
@@ -300,5 +300,5 @@ void
 pp_filter_set_clear_fb(struct pp_program *p)
 {
    cso_set_framebuffer(p->cso, &p->framebuffer);
-   p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR0, &p->clear_color, 0, 0);
+   p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR0, NULL, &p->clear_color, 0, 0);
 }
diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c
index 54ebe77420d..ae024f0e650 100644
--- a/src/gallium/auxiliary/util/u_screen.c
+++ b/src/gallium/auxiliary/util/u_screen.c
@@ -223,6 +223,7 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen,
    case PIPE_CAP_SHAREABLE_SHADERS:
    case PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS:
    case PIPE_CAP_CLEAR_TEXTURE:
+   case PIPE_CAP_CLEAR_SCISSORED:
    case PIPE_CAP_DRAW_PARAMETERS:
    case PIPE_CAP_TGSI_PACK_HALF_FLOAT:
    case PIPE_CAP_MULTI_DRAW_INDIRECT:
diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
index 8ff22bccd4e..00f75906173 100644
--- a/src/gallium/auxiliary/util/u_tests.c
+++ b/src/gallium/auxiliary/util/u_tests.c
@@ -177,7 +177,7 @@ util_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *c
    util_set_rasterizer_normal(cso);
    util_set_max_viewport(cso, cb);
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR0, NULL, (void*)clear_color, 0, 0);
 }
 
 static void
diff --git a/src/gallium/auxiliary/util/u_threaded_context.c b/src/gallium/auxiliary/util/u_threaded_context.c
index cfe88d310e8..d8536af77be 100644
--- a/src/gallium/auxiliary/util/u_threaded_context.c
+++ b/src/gallium/auxiliary/util/u_threaded_context.c
@@ -2343,20 +2343,22 @@ tc_invalidate_resource(struct pipe_context *_pipe,
 
 struct tc_clear {
    unsigned buffers;
+   struct pipe_scissor_state scissor_state;
    union pipe_color_union color;
    double depth;
    unsigned stencil;
+   bool scissor_state_set;
 };
 
 static void
 tc_call_clear(struct pipe_context *pipe, union tc_payload *payload)
 {
    struct tc_clear *p = (struct tc_clear *)payload;
-   pipe->clear(pipe, p->buffers, &p->color, p->depth, p->stencil);
+   pipe->clear(pipe, p->buffers, p->scissor_state_set ? &p->scissor_state : NULL, &p->color, p->depth, p->stencil);
 }
 
 static void
-tc_clear(struct pipe_context *_pipe, unsigned buffers,
+tc_clear(struct pipe_context *_pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
          const union pipe_color_union *color, double depth,
          unsigned stencil)
 {
@@ -2364,6 +2366,9 @@ tc_clear(struct pipe_context *_pipe, unsigned buffers,
    struct tc_clear *p = tc_add_struct_typed_call(tc, TC_CALL_clear, tc_clear);
 
    p->buffers = buffers;
+   if (scissor_state)
+      p->scissor_state = *scissor_state;
+   p->scissor_state_set = !!scissor_state;
    p->color = *color;
    p->depth = depth;
    p->stencil = stencil;
diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst
index a40461fed70..e006ef19568 100644
--- a/src/gallium/docs/source/screen.rst
+++ b/src/gallium/docs/source/screen.rst
@@ -303,6 +303,8 @@ The integer capabilities:
   a compressed block is copied to/from a plain pixel of the same size.
 * ``PIPE_CAP_CLEAR_TEXTURE``: Whether `clear_texture` will be
   available in contexts.
+* ``PIPE_CAP_CLEAR_SCISSORED``: Whether `clear` can accept a scissored
+  bounding box.
 * ``PIPE_CAP_DRAW_PARAMETERS``: Whether ``TGSI_SEMANTIC_BASEVERTEX``,
   ``TGSI_SEMANTIC_BASEINSTANCE``, and ``TGSI_SEMANTIC_DRAWID`` are
   supported in vertex shaders.
diff --git a/src/gallium/drivers/etnaviv/etnaviv_blt.c b/src/gallium/drivers/etnaviv/etnaviv_blt.c
index 225d2a7c243..63fcb8c649b 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_blt.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_blt.c
@@ -339,7 +339,7 @@ etna_blit_clear_zs_blt(struct pipe_context *pctx, struct pipe_surface *dst,
 }
 
 static void
-etna_clear_blt(struct pipe_context *pctx, unsigned buffers,
+etna_clear_blt(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct etna_context *ctx = etna_context(pctx);
diff --git a/src/gallium/drivers/etnaviv/etnaviv_rs.c b/src/gallium/drivers/etnaviv/etnaviv_rs.c
index 47ba585e304..bcd11e05a78 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_rs.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_rs.c
@@ -407,7 +407,7 @@ etna_blit_clear_zs_rs(struct pipe_context *pctx, struct pipe_surface *dst,
 }
 
 static void
-etna_clear_rs(struct pipe_context *pctx, unsigned buffers,
+etna_clear_rs(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct etna_context *ctx = etna_context(pctx);
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c
index 8be7135eb93..0ba2106c0cc 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -308,7 +308,7 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 }
 
 static void
-fd_clear(struct pipe_context *pctx, unsigned buffers,
+fd_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
 		const union pipe_color_union *color, double depth, unsigned stencil)
 {
 	struct fd_context *ctx = fd_context(pctx);
diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c
index a1c3314f4e2..56281c23f66 100644
--- a/src/gallium/drivers/i915/i915_clear.c
+++ b/src/gallium/drivers/i915/i915_clear.c
@@ -217,6 +217,7 @@ i915_clear_emit(struct pipe_context *pipe, unsigned buffers,
  */
 void
 i915_clear_blitter(struct pipe_context *pipe, unsigned buffers,
+                   const struct pipe_scissor_state *scissor_state,
                    const union pipe_color_union *color,
                    double depth, unsigned stencil)
 {
@@ -245,6 +246,7 @@ i915_clear_blitter(struct pipe_context *pipe, unsigned buffers,
 
 void
 i915_clear_render(struct pipe_context *pipe, unsigned buffers,
+                  const struct pipe_scissor_state *scissor_state,
                   const union pipe_color_union *color,
                   double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h
index 626a17f5606..1e273260936 100644
--- a/src/gallium/drivers/i915/i915_context.h
+++ b/src/gallium/drivers/i915/i915_context.h
@@ -376,9 +376,11 @@ void i915_emit_hardware_state(struct i915_context *i915 );
  * i915_clear.c: 
  */
 void i915_clear_blitter(struct pipe_context *pipe, unsigned buffers,
+                        const struct pipe_scissor_state *scissor_state,
                         const union pipe_color_union *color,
                         double depth, unsigned stencil);
 void i915_clear_render(struct pipe_context *pipe, unsigned buffers,
+                       const struct pipe_scissor_state *scissor_state,
                        const union pipe_color_union *color,
                        double depth, unsigned stencil);
 void i915_clear_emit(struct pipe_context *pipe, unsigned buffers,
diff --git a/src/gallium/drivers/iris/iris_clear.c b/src/gallium/drivers/iris/iris_clear.c
index 163783a8504..4c3adfdc39f 100644
--- a/src/gallium/drivers/iris/iris_clear.c
+++ b/src/gallium/drivers/iris/iris_clear.c
@@ -636,6 +636,7 @@ clear_depth_stencil(struct iris_context *ice,
 static void
 iris_clear(struct pipe_context *ctx,
            unsigned buffers,
+           const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *p_color,
            double depth,
            unsigned stencil)
diff --git a/src/gallium/drivers/lima/lima_draw.c b/src/gallium/drivers/lima/lima_draw.c
index 294210709f7..15474a08f9f 100644
--- a/src/gallium/drivers/lima/lima_draw.c
+++ b/src/gallium/drivers/lima/lima_draw.c
@@ -131,7 +131,7 @@ lima_damage_rect_union(struct pipe_scissor_state *rect,
 }
 
 static void
-lima_clear(struct pipe_context *pctx, unsigned buffers,
+lima_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct lima_context *ctx = lima_context(pctx);
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.c b/src/gallium/drivers/llvmpipe/lp_clear.c
index 064206fc238..3fd67b79dac 100644
--- a/src/gallium/drivers/llvmpipe/lp_clear.c
+++ b/src/gallium/drivers/llvmpipe/lp_clear.c
@@ -47,6 +47,7 @@
 void
 llvmpipe_clear(struct pipe_context *pipe, 
                unsigned buffers,
+               const struct pipe_scissor_state *scissor_state,
                const union pipe_color_union *color,
                double depth,
                unsigned stencil)
diff --git a/src/gallium/drivers/llvmpipe/lp_clear.h b/src/gallium/drivers/llvmpipe/lp_clear.h
index 7249929cbc7..9d28d2559a3 100644
--- a/src/gallium/drivers/llvmpipe/lp_clear.h
+++ b/src/gallium/drivers/llvmpipe/lp_clear.h
@@ -37,6 +37,7 @@ struct pipe_context;
 
 extern void
 llvmpipe_clear(struct pipe_context *pipe, unsigned buffers,
+               const struct pipe_scissor_state *scissor_state,
                const union pipe_color_union *color,
                double depth, unsigned stencil);
 
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_clear.c b/src/gallium/drivers/nouveau/nv30/nv30_clear.c
index 4e6df1eff60..b307b679564 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_clear.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_clear.c
@@ -50,7 +50,7 @@ pack_zeta(enum pipe_format format, double depth, unsigned stencil)
 }
 
 static void
-nv30_clear(struct pipe_context *pipe, unsigned buffers,
+nv30_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct nv30_context *nv30 = nv30_context(pipe);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h
index b9da8b50565..9894e9d613f 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h
@@ -248,6 +248,7 @@ bool nv50_state_validate_3d(struct nv50_context *, uint32_t);
 
 /* nv50_surface.c */
 extern void nv50_clear(struct pipe_context *, unsigned buffers,
+                       const struct pipe_scissor_state *scissor_state,
                        const union pipe_color_union *color,
                        double depth, unsigned stencil);
 extern void nv50_init_surface_functions(struct nv50_context *);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_surface.c b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
index 34c2633916b..2b39c2592e0 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_surface.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_surface.c
@@ -524,7 +524,7 @@ nv50_clear_texture(struct pipe_context *pipe,
 }
 
 void
-nv50_clear(struct pipe_context *pipe, unsigned buffers,
+nv50_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color,
            double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
index 4cfd207d4c0..dacb48411ba 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.h
@@ -356,6 +356,7 @@ bool nvc0_state_validate_3d(struct nvc0_context *, uint32_t);
 
 /* nvc0_surface.c */
 extern void nvc0_clear(struct pipe_context *, unsigned buffers,
+                       const struct pipe_scissor_state *scissor_state,
                        const union pipe_color_union *color,
                        double depth, unsigned stencil);
 extern void nvc0_init_surface_functions(struct nvc0_context *);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
index 2b38fe6e7f5..538effdb531 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_surface.c
@@ -682,6 +682,7 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe,
 
 void
 nvc0_clear(struct pipe_context *pipe, unsigned buffers,
+           const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color,
            double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/panfrost/pan_context.c b/src/gallium/drivers/panfrost/pan_context.c
index 33fad6208b6..7ff551d093b 100644
--- a/src/gallium/drivers/panfrost/pan_context.c
+++ b/src/gallium/drivers/panfrost/pan_context.c
@@ -125,6 +125,7 @@ static void
 panfrost_clear(
         struct pipe_context *pipe,
         unsigned buffers,
+        const struct pipe_scissor_state *scissor_state,
         const union pipe_color_union *color,
         double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 33344982c1e..b627e013898 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -202,6 +202,7 @@ DEBUG_GET_ONCE_BOOL_OPTION(hyperz, "RADEON_HYPERZ", FALSE)
 /* Clear currently bound buffers. */
 static void r300_clear(struct pipe_context* pipe,
                        unsigned buffers,
+                       const struct pipe_scissor_state *scissor_state,
                        const union pipe_color_union *color,
                        double depth,
                        unsigned stencil)
diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c
index 606b3892e3b..32154b11b7c 100644
--- a/src/gallium/drivers/r600/r600_blit.c
+++ b/src/gallium/drivers/r600/r600_blit.c
@@ -463,6 +463,7 @@ static bool r600_decompress_subresource(struct pipe_context *ctx,
 }
 
 static void r600_clear(struct pipe_context *ctx, unsigned buffers,
+		       const struct pipe_scissor_state *scissor_state,
 		       const union pipe_color_union *color,
 		       double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/radeonsi/si_clear.c b/src/gallium/drivers/radeonsi/si_clear.c
index 8c89c9be199..12512e7df73 100644
--- a/src/gallium/drivers/radeonsi/si_clear.c
+++ b/src/gallium/drivers/radeonsi/si_clear.c
@@ -540,6 +540,7 @@ static void si_do_fast_color_clear(struct si_context *sctx, unsigned *buffers,
 }
 
 static void si_clear(struct pipe_context *ctx, unsigned buffers,
+                     const struct pipe_scissor_state *scissor_state,
                      const union pipe_color_union *color, double depth, unsigned stencil)
 {
    struct si_context *sctx = (struct si_context *)ctx;
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c
index d2626a24333..300cbd077d9 100644
--- a/src/gallium/drivers/softpipe/sp_clear.c
+++ b/src/gallium/drivers/softpipe/sp_clear.c
@@ -47,6 +47,7 @@
  */
 void
 softpipe_clear(struct pipe_context *pipe, unsigned buffers,
+               const struct pipe_scissor_state *scissor_state,
                const union pipe_color_union *color,
                double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/softpipe/sp_clear.h b/src/gallium/drivers/softpipe/sp_clear.h
index 0398e5badbb..b9a489a633c 100644
--- a/src/gallium/drivers/softpipe/sp_clear.h
+++ b/src/gallium/drivers/softpipe/sp_clear.h
@@ -36,6 +36,7 @@ struct pipe_context;
 
 extern void
 softpipe_clear(struct pipe_context *pipe, unsigned buffers,
+               const struct pipe_scissor_state *scissor_state,
                const union pipe_color_union *color,
                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 75507fc1752..89a9b533f91 100644
--- a/src/gallium/drivers/svga/svga_pipe_clear.c
+++ b/src/gallium/drivers/svga/svga_pipe_clear.c
@@ -230,7 +230,7 @@ try_clear(struct svga_context *svga,
  * No masking, no scissor (clear entire buffer).
  */
 static void
-svga_clear(struct pipe_context *pipe, unsigned buffers,
+svga_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *color,
 	   double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/swr/swr_clear.cpp b/src/gallium/drivers/swr/swr_clear.cpp
index 4473f76a0a2..d579cbdde9f 100644
--- a/src/gallium/drivers/swr/swr_clear.cpp
+++ b/src/gallium/drivers/swr/swr_clear.cpp
@@ -27,6 +27,7 @@
 static void
 swr_clear(struct pipe_context *pipe,
           unsigned buffers,
+          const struct pipe_scissor_state *scissor_state,
           const union pipe_color_union *color,
           double depth,
           unsigned stencil)
diff --git a/src/gallium/drivers/tegra/tegra_context.c b/src/gallium/drivers/tegra/tegra_context.c
index e91baf0be34..c3ae90e4d6d 100644
--- a/src/gallium/drivers/tegra/tegra_context.c
+++ b/src/gallium/drivers/tegra/tegra_context.c
@@ -700,13 +700,13 @@ tegra_blit(struct pipe_context *pcontext, const struct pipe_blit_info *pinfo)
 }
 
 static void
-tegra_clear(struct pipe_context *pcontext, unsigned buffers,
+tegra_clear(struct pipe_context *pcontext, unsigned buffers, const struct pipe_scissor_state *scissor_state,
             const union pipe_color_union *color, double depth,
             unsigned stencil)
 {
    struct tegra_context *context = to_tegra_context(pcontext);
 
-   context->gpu->clear(context->gpu, buffers, color, depth, stencil);
+   context->gpu->clear(context->gpu, buffers, NULL, color, depth, stencil);
 }
 
 static void
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index 9bbfe4537e7..f4377e79d4a 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -1744,7 +1744,7 @@ v3d_tlb_clear(struct v3d_job *job, unsigned buffers,
 }
 
 static void
-v3d_clear(struct pipe_context *pctx, unsigned buffers,
+v3d_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
           const union pipe_color_union *color, double depth, unsigned stencil)
 {
         struct v3d_context *v3d = v3d_context(pctx);
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c
index 3da60ff64a8..b4523bb1250 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -517,7 +517,7 @@ pack_rgba(enum pipe_format format, const float *rgba)
 }
 
 static void
-vc4_clear(struct pipe_context *pctx, unsigned buffers,
+vc4_clear(struct pipe_context *pctx, unsigned buffers, const struct pipe_scissor_state *scissor_state,
           const union pipe_color_union *color, double depth, unsigned stencil)
 {
         struct vc4_context *vc4 = vc4_context(pctx);
diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c
index d83bd7a40b7..381a9c023a8 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -816,6 +816,7 @@ static void virgl_bind_fs_state(struct pipe_context *ctx,
 
 static void virgl_clear(struct pipe_context *ctx,
                                 unsigned buffers,
+                                const struct pipe_scissor_state *scissor_state,
                                 const union pipe_color_union *color,
                                 double depth, unsigned stencil)
 {
diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 4c2fe44da53..323f87e27ac 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -812,6 +812,7 @@ zink_resource_barrier(VkCommandBuffer cmdbuf, struct zink_resource *res,
 static void
 zink_clear(struct pipe_context *pctx,
            unsigned buffers,
+           const struct pipe_scissor_state *scissor_state,
            const union pipe_color_union *pcolor,
            double depth, unsigned stencil)
 {
diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h
index 3a8b9eba462..37957466ded 100644
--- a/src/gallium/include/pipe/p_context.h
+++ b/src/gallium/include/pipe/p_context.h
@@ -512,12 +512,14 @@ struct pipe_context {
     * The entire buffers are cleared (no scissor, no colormask, etc).
     *
     * \param buffers  bitfield of PIPE_CLEAR_* values.
+    * \param scissor_state  the scissored region to clear
     * \param color  pointer to a union of fiu array for each of r, g, b, a.
     * \param depth  depth clear value in [0,1].
     * \param stencil  stencil clear value
     */
    void (*clear)(struct pipe_context *pipe,
                  unsigned buffers,
+                 const struct pipe_scissor_state *scissor_state,
                  const union pipe_color_union *color,
                  double depth,
                  unsigned stencil);
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 13e124bf728..dd0c7331b69 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -817,6 +817,7 @@ enum pipe_cap
    PIPE_CAP_SHAREABLE_SHADERS,
    PIPE_CAP_COPY_BETWEEN_COMPRESSED_AND_PLAIN_FORMATS,
    PIPE_CAP_CLEAR_TEXTURE,
+   PIPE_CAP_CLEAR_SCISSORED,
    PIPE_CAP_DRAW_PARAMETERS,
    PIPE_CAP_TGSI_PACK_HALF_FLOAT,
    PIPE_CAP_MULTI_DRAW_INDIRECT,
diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c
index 227e9539592..8724ec87c81 100644
--- a/src/gallium/state_trackers/nine/nine_state.c
+++ b/src/gallium/state_trackers/nine/nine_state.c
@@ -2238,7 +2238,7 @@ CSMT_ITEM_NO_WAIT(nine_context_clear_fb,
          rect.x2 >= zsbuf_surf->desc.Width &&
          rect.y2 >= zsbuf_surf->desc.Height))) {
         DBG("Clear fast path\n");
-        pipe->clear(pipe, bufs, &rgba, Z, Stencil);
+        pipe->clear(pipe, bufs, NULL, &rgba, Z, Stencil);
         return;
     }
 
diff --git a/src/gallium/tests/graw/clear.c b/src/gallium/tests/graw/clear.c
index 2a08ae15485..522799c1e1a 100644
--- a/src/gallium/tests/graw/clear.c
+++ b/src/gallium/tests/graw/clear.c
@@ -28,7 +28,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {1, 0, 1, 1} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    ctx->flush(ctx, NULL, 0);
 
    graw_save_surface_to_file(ctx, surf, NULL);
diff --git a/src/gallium/tests/graw/fs-fragcoord.c b/src/gallium/tests/graw/fs-fragcoord.c
index 9afea0caa0b..016bbaa0410 100644
--- a/src/gallium/tests/graw/fs-fragcoord.c
+++ b/src/gallium/tests/graw/fs-fragcoord.c
@@ -185,6 +185,7 @@ draw(void)
 
    info.ctx->clear(info.ctx,
               PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+              NULL,
               &clear_color, 1.0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
    info.ctx->flush(info.ctx, NULL, 0);
diff --git a/src/gallium/tests/graw/fs-frontface.c b/src/gallium/tests/graw/fs-frontface.c
index 3ad89f6b646..956c7fee3a0 100644
--- a/src/gallium/tests/graw/fs-frontface.c
+++ b/src/gallium/tests/graw/fs-frontface.c
@@ -159,6 +159,7 @@ draw(void)
 
    info.ctx->clear(info.ctx,
               PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+              NULL,
               &clear_color, 1.0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
    info.ctx->flush(info.ctx, NULL, 0);
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index a4182be55bd..346bbedd61a 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -232,7 +232,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {.1,.3,.5,0} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    ctx->flush(ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/fs-write-z.c b/src/gallium/tests/graw/fs-write-z.c
index 196c67bc368..4002dce15f1 100644
--- a/src/gallium/tests/graw/fs-write-z.c
+++ b/src/gallium/tests/graw/fs-write-z.c
@@ -164,6 +164,7 @@ draw(void)
 
    info.ctx->clear(info.ctx,
               PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+              NULL,
               &clear_color, 1.0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, NUM_VERTS);
    info.ctx->flush(info.ctx, NULL, 0);
diff --git a/src/gallium/tests/graw/gs-test.c b/src/gallium/tests/graw/gs-test.c
index a984e0acfb0..5d3739c7281 100644
--- a/src/gallium/tests/graw/gs-test.c
+++ b/src/gallium/tests/graw/gs-test.c
@@ -318,7 +318,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {.1,.3,.5,0} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    if (draw_strip)
       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
    else
diff --git a/src/gallium/tests/graw/occlusion-query.c b/src/gallium/tests/graw/occlusion-query.c
index 1232c5bb401..b639a9bb9a1 100644
--- a/src/gallium/tests/graw/occlusion-query.c
+++ b/src/gallium/tests/graw/occlusion-query.c
@@ -168,6 +168,7 @@ draw(void)
 
    info.ctx->clear(info.ctx,
                    PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
+                   NULL,
                    &clear_color, 1.0, 0);
 
    q1 = info.ctx->create_query(info.ctx, PIPE_QUERY_OCCLUSION_COUNTER, 0);
diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c
index a5029484b3b..043abdf5044 100644
--- a/src/gallium/tests/graw/quad-sample.c
+++ b/src/gallium/tests/graw/quad-sample.c
@@ -148,7 +148,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {.5,.5,.5,1} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4);
    ctx->flush(ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/quad-tex.c b/src/gallium/tests/graw/quad-tex.c
index 35ba4fa3469..40caad4ae90 100644
--- a/src/gallium/tests/graw/quad-tex.c
+++ b/src/gallium/tests/graw/quad-tex.c
@@ -106,7 +106,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {.5,.5,.5,1} };
 
-   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
    info.ctx->flush(info.ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
index 8fa1a727f54..90d674745fd 100644
--- a/src/gallium/tests/graw/shader-leak.c
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -148,7 +148,7 @@ static void draw( void )
 
       ctx->bind_fs_state(ctx, fs);
 
-      ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+      ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
       util_draw_arrays(ctx, PIPE_PRIM_POINTS, 0, 1);
       ctx->flush(ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/tex-srgb.c b/src/gallium/tests/graw/tex-srgb.c
index 503350a68d8..964b4188b51 100644
--- a/src/gallium/tests/graw/tex-srgb.c
+++ b/src/gallium/tests/graw/tex-srgb.c
@@ -127,7 +127,7 @@ static void draw( void )
    clear_color.f[2] = 0.5;
    clear_color.f[3] = 1.0;
 
-   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
 
    info.ctx->set_sampler_views(info.ctx, PIPE_SHADER_FRAGMENT, 0, 1, &linear_sv);
    set_vertices(vertices1, 4);
diff --git a/src/gallium/tests/graw/tex-swizzle.c b/src/gallium/tests/graw/tex-swizzle.c
index 787f324fc35..538e12e7477 100644
--- a/src/gallium/tests/graw/tex-swizzle.c
+++ b/src/gallium/tests/graw/tex-swizzle.c
@@ -107,7 +107,7 @@ static void draw(void)
    clear_color.f[2] = 0.5;
    clear_color.f[3] = 1.0;
 
-   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_QUADS, 0, 4);
    info.ctx->flush(info.ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index ed721f378b1..6820bc530ea 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -162,7 +162,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {1,0,1,1} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    ctx->flush(ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index 297377b894e..72dce01980c 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -188,7 +188,7 @@ static void draw( void )
    union pipe_color_union clear_color = { {1,0,1,1} };
    struct pipe_draw_info info;
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
 
 
    util_draw_init_info(&info);
diff --git a/src/gallium/tests/graw/tri-large.c b/src/gallium/tests/graw/tri-large.c
index 78a2ddbda44..e1b0888bf04 100644
--- a/src/gallium/tests/graw/tri-large.c
+++ b/src/gallium/tests/graw/tri-large.c
@@ -106,7 +106,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {1,0,1,1} };
 
-   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    info.ctx->flush(info.ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/tri.c b/src/gallium/tests/graw/tri.c
index 2267d98a8fe..9882384a2f6 100644
--- a/src/gallium/tests/graw/tri.c
+++ b/src/gallium/tests/graw/tri.c
@@ -103,7 +103,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {1,0,1,1} };
 
-   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   info.ctx->clear(info.ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(info.ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    info.ctx->flush(info.ctx, NULL, 0);
 
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index b3714543b3a..1b96914ad2a 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -220,7 +220,7 @@ static void draw( void )
 {
    union pipe_color_union clear_color = { {.1,.3,.5,0} };
 
-   ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
+   ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
    util_draw_arrays(ctx, PIPE_PRIM_POINTS, 0, ARRAY_SIZE(vertices));
    ctx->flush(ctx, NULL, 0);
 
diff --git a/src/gallium/tests/trivial/quad-tex.c b/src/gallium/tests/trivial/quad-tex.c
index 271dee648d6..a30cfb9b9f7 100644
--- a/src/gallium/tests/trivial/quad-tex.c
+++ b/src/gallium/tests/trivial/quad-tex.c
@@ -309,7 +309,7 @@ static void draw(struct program *p)
 	cso_set_framebuffer(p->cso, &p->framebuffer);
 
 	/* clear the render target */
-	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);
+	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, NULL, &p->clear_color, 0, 0);
 
 	/* set misc state we care about */
 	cso_set_blend(p->cso, &p->blend);
diff --git a/src/gallium/tests/trivial/tri.c b/src/gallium/tests/trivial/tri.c
index 1e773cb28f9..79bb5d95086 100644
--- a/src/gallium/tests/trivial/tri.c
+++ b/src/gallium/tests/trivial/tri.c
@@ -246,7 +246,7 @@ static void draw(struct program *p)
 	cso_set_framebuffer(p->cso, &p->framebuffer);
 
 	/* clear the render target */
-	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, &p->clear_color, 0, 0);
+	p->pipe->clear(p->pipe, PIPE_CLEAR_COLOR, NULL, &p->clear_color, 0, 0);
 
 	/* set misc state we care about */
 	cso_set_blend(p->cso, &p->blend);
diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c
index b7d44d2c1b5..e38f44ed78b 100644
--- a/src/mesa/state_tracker/st_cb_clear.c
+++ b/src/mesa/state_tracker/st_cb_clear.c
@@ -432,6 +432,7 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
       = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
    GLbitfield quad_buffers = 0x0;
    GLbitfield clear_buffers = 0x0;
+   bool have_scissor_buffers = false;
    GLuint i;
 
    st_flush_bitmap_cache(st);
@@ -462,12 +463,14 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
             unsigned surf_colormask =
                util_format_colormask(util_format_description(strb->surface->format));
 
-            if (is_scissor_enabled(ctx, rb) ||
+            bool scissor = is_scissor_enabled(ctx, rb);
+            if ((scissor && !st->can_scissor_clear) ||
                 is_window_rectangle_enabled(ctx) ||
                 ((colormask & surf_colormask) != surf_colormask))
                quad_buffers |= PIPE_CLEAR_COLOR0 << i;
             else
                clear_buffers |= PIPE_CLEAR_COLOR0 << i;
+            have_scissor_buffers |= scissor && st->can_scissor_clear;
          }
       }
    }
@@ -510,10 +513,31 @@ st_Clear(struct gl_context *ctx, GLbitfield mask)
     * renderbuffers, because it's likely to be faster.
     */
    if (clear_buffers) {
+      const struct gl_scissor_rect *scissor = &ctx->Scissor.ScissorArray[0];
+      struct pipe_scissor_state scissor_state = {
+         .minx = MAX2(scissor->X, 0),
+         .miny = MAX2(scissor->Y, 0),
+         .maxx = MAX2(scissor->X + scissor->Width, 0),
+         .maxy = MAX2(scissor->Y + scissor->Height, 0),
+
+      };
+
+      /* Now invert Y if needed.
+       * Gallium drivers use the convention Y=0=top for surfaces.
+       */
+      if (st->state.fb_orientation == Y_0_TOP) {
+         const struct gl_framebuffer *fb = ctx->DrawBuffer;
+         /* use intermediate variables to avoid uint underflow */
+         GLint miny, maxy;
+         miny = fb->Height - scissor_state.maxy;
+         maxy = fb->Height - scissor_state.miny;
+         scissor_state.miny = MAX2(miny, 0);
+         scissor_state.maxy = MAX2(maxy, 0);
+      }
       /* We can't translate the clear color to the colorbuffer format,
        * because different colorbuffers may have different formats.
        */
-      st->pipe->clear(st->pipe, clear_buffers,
+      st->pipe->clear(st->pipe, clear_buffers, have_scissor_buffers ? &scissor_state : NULL,
                       (union pipe_color_union*)&ctx->Color.ClearColor,
                       ctx->Depth.Clear, ctx->Stencil.Clear);
    }
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h
index 267aa32ad78..a4a1ce5d4ad 100644
--- a/src/mesa/state_tracker/st_context.h
+++ b/src/mesa/state_tracker/st_context.h
@@ -182,6 +182,10 @@ struct st_context
    boolean draw_needs_minmax_index;
    boolean has_hw_atomics;
 
+
+   /* driver supports scissored clears */
+   boolean can_scissor_clear;
+
    /* Some state is contained in constant objects.
     * Other state is just parameter values.
     */
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index ae600737cc6..cc1572bcc31 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -984,6 +984,8 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
       }
    }
 
+   st->can_scissor_clear = !!st->pipe->screen->get_param(st->pipe->screen, PIPE_CAP_CLEAR_SCISSORED);
+
    st->invalidate_on_gl_viewport =
       smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
 



More information about the mesa-commit mailing list