From 96106df17897b862b87937d6222a3e6483f45480 Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 13 Nov 2020 14:26:23 +0100
Subject: [PATCH 1/6] frontend/dri: copy image use in dup_image

Don't lose the use flags when dup'ing an image.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 src/gallium/frontends/dri/dri2.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c
index 0c0168497a2..1cd42cd8114 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -1308,6 +1308,7 @@ dri2_dup_image(__DRIimage *image, void *loaderPrivate)
    img->dri_format = image->dri_format;
    /* This should be 0 for sub images, but dup is also used for base images. */
    img->dri_components = image->dri_components;
+   img->use = image->use;
    img->loader_private = loaderPrivate;
 
    return img;
-- 
GitLab


From 00add4be8620175ccc69869e22479962dacdce9d Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 13 Nov 2020 14:38:41 +0100
Subject: [PATCH 2/6] dri: bring back use flags for createImageWithModifiers

createImageWithModifiers dropped the use flags that were present with
the createImage interface as it was believed at the time that all those
use flags could be expressed as a modifier. This turned out to be untrue,
as there are some use flags like SCANOUT and the BACKBUFFER hint that
won't ever get a eqivalent modifier expression.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 include/GL/internal/dri_interface.h      | 1 +
 src/egl/drivers/dri2/platform_wayland.c  | 4 ++--
 src/gallium/frontends/dri/dri2.c         | 5 ++---
 src/gbm/backends/dri/gbm_dri.c           | 2 +-
 src/loader/loader_dri3_helper.c          | 3 +++
 src/mesa/drivers/dri/i965/intel_screen.c | 2 +-
 6 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 39d5dd07533..222821428d0 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1678,6 +1678,7 @@ struct __DRIimageExtensionRec {
                                            int width, int height, int format,
                                            const uint64_t *modifiers,
                                            const unsigned int modifier_count,
+                                           unsigned int use,
                                            void *loaderPrivate);
 
    /*
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index c0b26c4b623..bb508cbe421 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -595,7 +595,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
                                                       dri2_surf->base.Height,
                                                       linear_dri_image_format,
                                                       &linear_mod,
-                                                      1,
+                                                      1, use_flags,
                                                       NULL);
       } else {
          dri2_surf->back->linear_copy =
@@ -624,7 +624,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
                                                      dri2_surf->base.Height,
                                                      dri_image_format,
                                                      modifiers,
-                                                     num_modifiers,
+                                                     num_modifiers, use_flags,
                                                      NULL);
       } else {
          dri2_surf->back->dri_image =
diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c
index 1cd42cd8114..1f1e7a9a65e 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -1074,12 +1074,11 @@ static __DRIimage *
 dri2_create_image_with_modifiers(__DRIscreen *dri_screen,
                                  int width, int height, int format,
                                  const uint64_t *modifiers,
-                                 const unsigned count,
+                                 const unsigned count, unsigned int use,
                                  void *loaderPrivate)
 {
    return dri2_create_image_common(dri_screen, width, height, format,
-                                   __DRI_IMAGE_USE_SHARE, modifiers, count,
-                                   loaderPrivate);
+                                   use, modifiers, count, loaderPrivate);
 }
 
 static bool
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index b5634741554..aff3a107e7d 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -1173,7 +1173,7 @@ gbm_dri_bo_create(struct gbm_device *gbm,
                                               width, height,
                                               dri_format,
                                               modifiers, count,
-                                              bo);
+                                              dri_use, bo);
 
       if (bo->image) {
          /* The client passed in a list of invalid modifiers */
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index ccf8d1795e7..6fc6a2b705a 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -1407,6 +1407,9 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
                                                                        format,
                                                                        modifiers,
                                                                        count,
+                                                                       __DRI_IMAGE_USE_SHARE |
+                                                                       __DRI_IMAGE_USE_SCANOUT |
+                                                                       __DRI_IMAGE_USE_BACKBUFFER,
                                                                        buffer);
          }
 
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index 4492d43c040..4511b962eef 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -893,7 +893,7 @@ static __DRIimage *
 intel_create_image_with_modifiers(__DRIscreen *dri_screen,
                                   int width, int height, int format,
                                   const uint64_t *modifiers,
-                                  const unsigned count,
+                                  const unsigned count, unsigned int use,
                                   void *loaderPrivate)
 {
    return intel_create_image_common(dri_screen, width, height, format, 0,
-- 
GitLab


From 587aac46dbadf2aca1489aadd4216e592e11e17b Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 13 Nov 2020 14:59:52 +0100
Subject: [PATCH 3/6] frontend/dri: add EXPLICIT_FLUSH hint in
 dri2_resource_get_param

dri2_resource_get_param() is called from two different places right now.
Only one of them adds the EXPLICIT_FLUSH hint to the handle usage, which
may disable the optimizations provided by this hint without a reason.

Make sure to always add this hint when appropriate.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 src/gallium/frontends/dri/dri2.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c
index 1f1e7a9a65e..7851ebceb3e 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -1198,6 +1198,9 @@ dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param,
    if (!pscreen->resource_get_param)
       return false;
 
+   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
+      handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
+
    return pscreen->resource_get_param(pscreen, NULL, image->texture,
                                       image->plane, 0, 0, param, handle_usage,
                                       value);
@@ -1242,9 +1245,6 @@ dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value)
 
    handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
 
-   if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
-      handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;
-
    if (!dri2_resource_get_param(image, param, handle_usage, &res_param))
       return false;
 
-- 
GitLab


From 59f74212bbb5e28badd0775929e42856c9a01d35 Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 13 Nov 2020 15:03:37 +0100
Subject: [PATCH 4/6] etnaviv: remove double assigment of surface->texture

surf->base.texture is already assigned earlier via a proper
pipe_resource_reference call. Remove the superfluous assignement.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
---
 src/gallium/drivers/etnaviv/etnaviv_surface.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_surface.c b/src/gallium/drivers/etnaviv/etnaviv_surface.c
index c78973bdb09..52a937652d2 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_surface.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_surface.c
@@ -112,7 +112,6 @@ etna_create_surface(struct pipe_context *pctx, struct pipe_resource *prsc,
       etna_screen_resource_alloc_ts(pctx->screen, rsc);
    }
 
-   surf->base.texture = &rsc->base;
    surf->base.format = templat->format;
    surf->base.width = rsc->levels[level].width;
    surf->base.height = rsc->levels[level].height;
-- 
GitLab


From 570908323e02c4558f5a9abc2d82621056cd65ab Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Tue, 17 Nov 2020 12:08:13 +0100
Subject: [PATCH 5/6] etnaviv: compact etna_state_updates

Just reclaim a bit of screen real estate, purely cosmetic change.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 src/gallium/drivers/etnaviv/etnaviv_state.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c
index 1b4a7040b50..84fea58ecb5 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_state.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_state.c
@@ -749,24 +749,18 @@ struct etna_state_updater {
 static const struct etna_state_updater etna_state_updates[] = {
    {
       etna_shader_update_vertex, ETNA_DIRTY_SHADER | ETNA_DIRTY_VERTEX_ELEMENTS,
-   },
-   {
+   }, {
       etna_shader_link, ETNA_DIRTY_SHADER,
-   },
-   {
+   }, {
       etna_update_blend, ETNA_DIRTY_BLEND | ETNA_DIRTY_FRAMEBUFFER
-   },
-   {
+   }, {
       etna_update_blend_color, ETNA_DIRTY_BLEND_COLOR | ETNA_DIRTY_FRAMEBUFFER,
-   },
-   {
+   }, {
       etna_update_ts_config, ETNA_DIRTY_DERIVE_TS,
-   },
-   {
+   }, {
       etna_update_clipping, ETNA_DIRTY_SCISSOR | ETNA_DIRTY_FRAMEBUFFER |
                             ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT,
-   },
-   {
+   }, {
       etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER,
    }
 };
-- 
GitLab


From 537c7a6ea3fd2e5a6433e52b406ba39b89f520d9 Mon Sep 17 00:00:00 2001
From: Lucas Stach <l.stach@pengutronix.de>
Date: Fri, 13 Nov 2020 15:05:55 +0100
Subject: [PATCH 6/6] etnaviv: flush used render buffers on context flush when
 neccessary

Some resources like backbuffers are explicitly flushed by the frontend
at the appropriate time, others however won't get flushed explicitly.
Remember those resources when they get emitted as a render buffer and
flush them on a context flush to make their content visible to other
entities sharing the buffer.

We still keep the optimized path for most resources where the frontend
promises to do the flushing for us and only enable implicit flushing
when a buffer handle is exported/imported without the
PIPE_HANDLE_USAGE_EXPLICIT_FLUSH flag set.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
 src/gallium/drivers/etnaviv/etnaviv_context.c  | 16 ++++++++++++++++
 src/gallium/drivers/etnaviv/etnaviv_context.h  |  3 +++
 src/gallium/drivers/etnaviv/etnaviv_resource.c |  7 +++++++
 src/gallium/drivers/etnaviv/etnaviv_resource.h |  2 ++
 src/gallium/drivers/etnaviv/etnaviv_state.c    | 17 +++++++++++++++++
 5 files changed, 45 insertions(+)

diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c
index 9c334a450c6..80c5d430419 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.c
@@ -128,6 +128,9 @@ etna_context_destroy(struct pipe_context *pctx)
       _mesa_set_destroy(ctx->used_resources_write, NULL);
 
    }
+   if (ctx->flush_resources)
+      _mesa_set_destroy(ctx->flush_resources, NULL);
+
    mtx_unlock(&ctx->lock);
 
    if (ctx->dummy_desc_bo)
@@ -475,6 +478,14 @@ etna_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence,
    list_for_each_entry(struct etna_acc_query, aq, &ctx->active_acc_queries, node)
       etna_acc_query_suspend(aq, ctx);
 
+   /* flush all resources that need an implicit flush */
+   set_foreach(ctx->flush_resources, entry) {
+      struct pipe_resource *prsc = (struct pipe_resource *)entry->key;
+
+      pctx->flush_resource(pctx, prsc);
+   }
+   _mesa_set_clear(ctx->flush_resources, NULL);
+
    etna_cmd_stream_flush(ctx->stream, ctx->in_fence_fd,
                           (flags & PIPE_FLUSH_FENCE_FD) ? &out_fence_fd : NULL);
 
@@ -581,6 +592,11 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
    if (!ctx->used_resources_write)
       goto fail;
 
+   ctx->flush_resources = _mesa_set_create(NULL, _mesa_hash_pointer,
+                                           _mesa_key_pointer_equal);
+   if (!ctx->flush_resources)
+      goto fail;
+
    mtx_init(&ctx->lock, mtx_recursive);
 
    /* context ctxate setup */
diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.h b/src/gallium/drivers/etnaviv/etnaviv_context.h
index dd6af3d93e6..112902aac8a 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_context.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_context.h
@@ -206,6 +206,9 @@ struct etna_context {
    struct set *used_resources_read;
    struct set *used_resources_write;
 
+   /* resources that must be flushed implicitly at the context flush time */
+   struct set *flush_resources;
+
    mtx_t lock;
 };
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
index ae4f24b9b44..0c8c28e66aa 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
@@ -265,6 +265,7 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
    rsc->base.nr_samples = nr_samples;
    rsc->layout = layout;
    rsc->halign = halign;
+   rsc->explicit_flush = true;
 
    pipe_reference_init(&rsc->base.reference, 1);
    util_range_init(&rsc->valid_buffer_range);
@@ -519,6 +520,9 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
    rsc->layout = modifier_to_layout(handle->modifier);
    rsc->halign = TEXTURE_HALIGN_FOUR;
 
+   if (usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH)
+      rsc->explicit_flush = true;
+
    level->width = tmpl->width0;
    level->height = tmpl->height0;
    level->depth = tmpl->depth0;
@@ -584,6 +588,9 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
    handle->offset = rsc->levels[0].offset;
    handle->modifier = layout_to_modifier(rsc->layout);
 
+   if (!(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH))
+      rsc->explicit_flush = false;
+
    if (handle->type == WINSYS_HANDLE_TYPE_SHARED) {
       return etna_bo_get_name(rsc->bo, &handle->handle) == 0;
    } else if (handle->type == WINSYS_HANDLE_TYPE_KMS) {
diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
index cb83e891d34..167cf4ed069 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
+++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
@@ -93,6 +93,8 @@ struct etna_resource {
    struct pipe_resource *texture;
    /* for when PE doesn't support the base layout */
    struct pipe_resource *render;
+   /* frontend flushes resource via an explicit call to flush_resource */
+   bool explicit_flush;
 
    enum etna_resource_status status;
 
diff --git a/src/gallium/drivers/etnaviv/etnaviv_state.c b/src/gallium/drivers/etnaviv/etnaviv_state.c
index 84fea58ecb5..5848735ab14 100644
--- a/src/gallium/drivers/etnaviv/etnaviv_state.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_state.c
@@ -741,6 +741,21 @@ etna_update_zsa(struct etna_context *ctx)
    return true;
 }
 
+static bool
+etna_record_flush_resources(struct etna_context *ctx)
+{
+   struct pipe_framebuffer_state *fb = &ctx->framebuffer_s;
+
+   if (fb->nr_cbufs > 0) {
+      struct etna_surface *surf = etna_surface(fb->cbufs[0]);
+
+      if (!etna_resource(surf->prsc)->explicit_flush)
+         _mesa_set_add(ctx->flush_resources, surf->prsc);
+   }
+
+   return true;
+}
+
 struct etna_state_updater {
    bool (*update)(struct etna_context *ctx);
    uint32_t dirty;
@@ -762,6 +777,8 @@ static const struct etna_state_updater etna_state_updates[] = {
                             ETNA_DIRTY_RASTERIZER | ETNA_DIRTY_VIEWPORT,
    }, {
       etna_update_zsa, ETNA_DIRTY_ZSA | ETNA_DIRTY_SHADER,
+   }, {
+      etna_record_flush_resources, ETNA_DIRTY_FRAMEBUFFER,
    }
 };
 
-- 
GitLab

