Signed-off-by: Rob Clark <robdcl...@gmail.com>
---
 src/gallium/drivers/freedreno/a6xx/fd6_gmem.c |  3 +-
 .../drivers/freedreno/freedreno_batch.c       |  1 +
 .../drivers/freedreno/freedreno_batch.h       |  8 +-
 .../drivers/freedreno/freedreno_draw.c        | 99 ++++++++++++-------
 .../drivers/freedreno/freedreno_resource.c    | 33 +++++++
 .../drivers/freedreno/freedreno_state.h       | 10 ++
 .../drivers/freedreno/freedreno_surface.h     | 18 ++++
 7 files changed, 137 insertions(+), 35 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c 
b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index 8cda7d6ddae..0a82f69fc62 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -36,6 +36,7 @@
 #include "freedreno_draw.h"
 #include "freedreno_state.h"
 #include "freedreno_resource.h"
+#include "freedreno_surface.h"
 
 #include "fd6_gmem.h"
 #include "fd6_context.h"
@@ -901,7 +902,7 @@ emit_resolve_blit(struct fd_batch *batch,
 {
        uint32_t info = 0;
 
-       if (!rsc->valid)
+       if (!fd_surface_valid(psurf))
                return;
 
        switch (buffer) {
diff --git a/src/gallium/drivers/freedreno/freedreno_batch.c 
b/src/gallium/drivers/freedreno/freedreno_batch.c
index eae2f68ce11..280a412222a 100644
--- a/src/gallium/drivers/freedreno/freedreno_batch.c
+++ b/src/gallium/drivers/freedreno/freedreno_batch.c
@@ -78,6 +78,7 @@ batch_init(struct fd_batch *batch)
        batch->cleared = 0;
        batch->fast_cleared = 0;
        batch->invalidated = 0;
+       batch->partial_invalidated = 0;
        batch->restore = batch->resolve = 0;
        batch->needs_flush = false;
        batch->flushed = false;
diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h 
b/src/gallium/drivers/freedreno/freedreno_batch.h
index a40d36094cd..9846ceea6ff 100644
--- a/src/gallium/drivers/freedreno/freedreno_batch.h
+++ b/src/gallium/drivers/freedreno/freedreno_batch.h
@@ -95,7 +95,13 @@ struct fd_batch {
                FD_BUFFER_DEPTH   = PIPE_CLEAR_DEPTH,
                FD_BUFFER_STENCIL = PIPE_CLEAR_STENCIL,
                FD_BUFFER_ALL     = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | 
FD_BUFFER_STENCIL,
-       } invalidated, cleared, fast_cleared, restore, resolve;
+       } invalidated, partial_invalidated, cleared, fast_cleared, restore, 
resolve;
+
+       /* for partially invalidated fb surfaces, track the invalidated rect: */
+       struct {
+               struct pipe_box zsbuf;
+               struct pipe_box cbuf[8];
+       } invalid;
 
        /* is this a non-draw batch (ie compute/blit which has no pfb state)? */
        bool nondraw : 1;
diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c 
b/src/gallium/drivers/freedreno/freedreno_draw.c
index f17cb563063..5b4b728b6d3 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -36,6 +36,7 @@
 #include "freedreno_context.h"
 #include "freedreno_fence.h"
 #include "freedreno_state.h"
+#include "freedreno_surface.h"
 #include "freedreno_resource.h"
 #include "freedreno_query_acc.h"
 #include "freedreno_query_hw.h"
@@ -57,6 +58,14 @@ resource_written(struct fd_batch *batch, struct 
pipe_resource *prsc)
        fd_batch_resource_used(batch, fd_resource(prsc), true);
 }
 
+static void
+surface_valid(struct pipe_surface *psurf)
+{
+       struct fd_surface *surf = fd_surface(psurf);
+       surf->invalid = false;
+       surf->partial_invalid = false;
+}
+
 static void
 fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
 {
@@ -138,59 +147,78 @@ fd_draw_vbo(struct pipe_context *pctx, const struct 
pipe_draw_info *info)
        mtx_lock(&ctx->screen->lock);
 
        if (ctx->dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_ZSA)) {
+               unsigned b = 0;
                if (fd_depth_enabled(ctx)) {
-                       if (fd_resource(pfb->zsbuf->texture)->valid) {
-                               restore_buffers |= FD_BUFFER_DEPTH;
-                       } else {
-                               batch->invalidated |= FD_BUFFER_DEPTH;
-                       }
-                       buffers |= FD_BUFFER_DEPTH;
-                       resource_written(batch, pfb->zsbuf->texture);
+                       b |= FD_BUFFER_DEPTH;
                        batch->gmem_reason |= FD_GMEM_DEPTH_ENABLED;
                }
 
                if (fd_stencil_enabled(ctx)) {
-                       if (fd_resource(pfb->zsbuf->texture)->valid) {
-                               restore_buffers |= FD_BUFFER_STENCIL;
+                       b |= FD_BUFFER_STENCIL;
+                       batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
+               }
+
+               if (b) {
+                       if (fd_surface_valid(pfb->zsbuf)) {
+                               restore_buffers |= b;
+                       } else if (fd_surface_partially_valid(pfb->zsbuf)) {
+                               restore_buffers |= b;
+                               batch->partial_invalidated |= b;
+                               batch->invalid.zsbuf = 
fd_surface(pfb->zsbuf)->invalid_region;
                        } else {
-                               batch->invalidated |= FD_BUFFER_STENCIL;
+                               batch->invalidated |= b;
+                       }
+                       buffers |= b;
+
+                       if (fd_depth_write_enabled(ctx) ||
+                                       fd_stencil_write_enabled(ctx)) {
+                               resource_written(batch, pfb->zsbuf->texture);
+                       } else {
+                               resource_read(batch, pfb->zsbuf->texture);
                        }
-                       buffers |= FD_BUFFER_STENCIL;
-                       resource_written(batch, pfb->zsbuf->texture);
-                       batch->gmem_reason |= FD_GMEM_STENCIL_ENABLED;
                }
        }
 
        if (ctx->dirty & FD_DIRTY_FRAMEBUFFER) {
                for (i = 0; i < pfb->nr_cbufs; i++) {
-                       if (!pfb->cbufs[i])
+                       struct pipe_surface *psurf = pfb->cbufs[i];
+
+                       if (!psurf)
                                continue;
 
+                       if (fd_surface_valid(psurf)) {
+                               restore_buffers |= PIPE_CLEAR_COLOR0 << i;
+                       } else if (fd_surface_partially_valid(psurf)) {
+                               restore_buffers |= PIPE_CLEAR_COLOR0 << i;
+                               batch->partial_invalidated |= PIPE_CLEAR_COLOR0 
<< i;
+                               batch->invalid.cbuf[i] = 
fd_surface(psurf)->invalid_region;
+                       } else {
+                               batch->invalidated |= PIPE_CLEAR_COLOR0 << i;
+                       }
+
+                       buffers |= PIPE_CLEAR_COLOR0 << i;
+
                        resource_written(batch, pfb->cbufs[i]->texture);
                }
        }
 
-       if (fd_logicop_enabled(ctx))
-               batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
+       if (pfb->zsbuf)
+               surface_valid(pfb->zsbuf);
 
-       for (i = 0; i < pfb->nr_cbufs; i++) {
-               struct pipe_resource *surf;
+       for (i = 0; i < pfb->nr_cbufs; i++)
+               surface_valid(pfb->cbufs[i]);
 
-               if (!pfb->cbufs[i])
-                       continue;
+       if (fd_logicop_enabled(ctx))
+               batch->gmem_reason |= FD_GMEM_LOGICOP_ENABLED;
 
-               surf = pfb->cbufs[i]->texture;
+       if (ctx->dirty & FD_DIRTY_BLEND) {
+               for (i = 0; i < pfb->nr_cbufs; i++) {
+                       if (!pfb->cbufs[i])
+                               continue;
 
-               if (fd_resource(surf)->valid) {
-                       restore_buffers |= PIPE_CLEAR_COLOR0 << i;
-               } else {
-                       batch->invalidated |= PIPE_CLEAR_COLOR0 << i;
+                       if (fd_blend_enabled(ctx, i))
+                               batch->gmem_reason |= FD_GMEM_BLEND_ENABLED;
                }
-
-               buffers |= PIPE_CLEAR_COLOR0 << i;
-
-               if (fd_blend_enabled(ctx, i))
-                       batch->gmem_reason |= FD_GMEM_BLEND_ENABLED;
        }
 
        /* Mark SSBOs as being written.. we don't actually know which ones are
@@ -420,13 +448,18 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
 
        mtx_lock(&ctx->screen->lock);
 
-       if (buffers & PIPE_CLEAR_COLOR)
-               for (i = 0; i < pfb->nr_cbufs; i++)
-                       if (buffers & (PIPE_CLEAR_COLOR0 << i))
+       if (buffers & PIPE_CLEAR_COLOR) {
+               for (i = 0; i < pfb->nr_cbufs; i++) {
+                       if (buffers & (PIPE_CLEAR_COLOR0 << i)) {
                                resource_written(batch, pfb->cbufs[i]->texture);
+                               surface_valid(pfb->cbufs[i]);
+                       }
+               }
+       }
 
        if (buffers & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) {
                resource_written(batch, pfb->zsbuf->texture);
+               surface_valid(pfb->zsbuf);
                batch->gmem_reason |= FD_GMEM_CLEARS_DEPTH_STENCIL;
        }
 
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c 
b/src/gallium/drivers/freedreno/freedreno_resource.c
index 85bbbe271f9..68a5cf24505 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -1124,6 +1124,17 @@ fd_blitter_pipe_end(struct fd_context *ctx)
        ctx->in_blit = false;
 }
 
+/**
+ * Invalidate the contents of the resource. This is used to
+ *
+ * (1) implement EGL's semantic of undefined depth/stencil
+ * contents after a swapbuffers.  This allows a tiled renderer (for
+ * example) to not store the depth buffer.
+ *
+ * (2) implement GL's InvalidateBufferData. For backwards compatibility,
+ * you must only rely on the usability for this purpose when
+ * PIPE_CAP_INVALIDATE_BUFFER is enabled.
+ */
 static void
 fd_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
 {
@@ -1152,6 +1163,27 @@ fd_invalidate_resource(struct pipe_context *pctx, struct 
pipe_resource *prsc)
        rsc->valid = false;
 }
 
+/**
+ * Like ->invalidate_surface, but can invalidate a specific layer and level
+ * of a resource.  If the backing surf->texture has just a single layer and
+ * level (like window system buffers) it is equiv to ->invalidate_resource
+ */
+static void
+fd_invalidate_surface(struct pipe_context *pctx, struct pipe_surface *psurf,
+               struct pipe_box *region)
+{
+       struct fd_surface *surf = fd_surface(psurf);
+
+       if (region) {
+               /* partial invalidate: */
+               surf->partial_invalid = true;
+               surf->invalid_region = *region;
+       } else {
+               /* full invalidate: */
+               surf->invalid = true;
+       }
+}
+
 static enum pipe_format
 fd_resource_get_internal_format(struct pipe_resource *prsc)
 {
@@ -1261,5 +1293,6 @@ fd_resource_context_init(struct pipe_context *pctx)
        pctx->blit = fd_blit;
        pctx->flush_resource = fd_flush_resource;
        pctx->invalidate_resource = fd_invalidate_resource;
+       pctx->invalidate_surface = fd_invalidate_surface;
        pctx->get_sample_position = fd_get_sample_position;
 }
diff --git a/src/gallium/drivers/freedreno/freedreno_state.h 
b/src/gallium/drivers/freedreno/freedreno_state.h
index 35584e41e3a..18e90dc0056 100644
--- a/src/gallium/drivers/freedreno/freedreno_state.h
+++ b/src/gallium/drivers/freedreno/freedreno_state.h
@@ -35,11 +35,21 @@ static inline bool fd_depth_enabled(struct fd_context *ctx)
        return ctx->zsa && ctx->zsa->depth.enabled;
 }
 
+static inline bool fd_depth_write_enabled(struct fd_context *ctx)
+{
+       return ctx->zsa && ctx->zsa->depth.writemask;
+}
+
 static inline bool fd_stencil_enabled(struct fd_context *ctx)
 {
        return ctx->zsa && ctx->zsa->stencil[0].enabled;
 }
 
+static inline bool fd_stencil_write_enabled(struct fd_context *ctx)
+{
+       return ctx->zsa && ctx->zsa->stencil[0].writemask;
+}
+
 static inline bool fd_logicop_enabled(struct fd_context *ctx)
 {
        return ctx->blend && ctx->blend->logicop_enable;
diff --git a/src/gallium/drivers/freedreno/freedreno_surface.h 
b/src/gallium/drivers/freedreno/freedreno_surface.h
index 8898f890eda..ce6ac142472 100644
--- a/src/gallium/drivers/freedreno/freedreno_surface.h
+++ b/src/gallium/drivers/freedreno/freedreno_surface.h
@@ -29,8 +29,13 @@
 
 #include "pipe/p_state.h"
 
+#include "freedreno_resource.h"
+
 struct fd_surface {
        struct pipe_surface base;
+       bool invalid;
+       bool partial_invalid;
+       struct pipe_box invalid_region;
 };
 
 static inline struct fd_surface *
@@ -39,6 +44,19 @@ fd_surface(struct pipe_surface *psurf)
        return (struct fd_surface *)psurf;
 }
 
+static inline bool
+fd_surface_valid(struct pipe_surface *psurf)
+{
+       return fd_resource(psurf->texture)->valid &&
+                       !fd_surface(psurf)->invalid;
+}
+
+static inline bool
+fd_surface_partially_valid(struct pipe_surface *psurf)
+{
+       return fd_surface(psurf)->partial_invalid;
+}
+
 struct pipe_surface* fd_create_surface(struct pipe_context *pctx,
                struct pipe_resource *ptex,
                const struct pipe_surface *surf_tmpl);
-- 
2.19.2

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to