[Mesa-dev] [PATCH v2 01/10] renderonly/etnaviv: stop importing resource from renderonly

Christian Gmeiner christian.gmeiner at gmail.com
Wed Jul 19 08:57:57 UTC 2017


2017-07-04 17:45 GMT+02:00 Lucas Stach <l.stach at pengutronix.de>:
> The current way of importing the resource from renderonly after allocation
> is opaque and is taking away control from the driver, which it needs in
> order to implement more advanced scenarios, than the simple linear
> scanout with matching stride alignments.
>
> Signed-off-by: Lucas Stach <l.stach at pengutronix.de>

Looks good ti me (but I did not test this series on real hw).

Reviewed-by: Christian Gmeiner <christian.gmeiner at gmail.com>

> ---
>  src/gallium/auxiliary/renderonly/renderonly.c    | 52 +++++++-----------------
>  src/gallium/auxiliary/renderonly/renderonly.h    | 20 ++++-----
>  src/gallium/drivers/etnaviv/etnaviv_clear_blit.c |  8 ++--
>  src/gallium/drivers/etnaviv/etnaviv_resource.c   | 34 ++++++++++++----
>  src/gallium/drivers/etnaviv/etnaviv_resource.h   |  5 +++
>  src/gallium/drivers/vc4/vc4_resource.c           |  5 ++-
>  6 files changed, 62 insertions(+), 62 deletions(-)
>
> diff --git a/src/gallium/auxiliary/renderonly/renderonly.c b/src/gallium/auxiliary/renderonly/renderonly.c
> index d3ed214f4e43..da91f12b2ea1 100644
> --- a/src/gallium/auxiliary/renderonly/renderonly.c
> +++ b/src/gallium/auxiliary/renderonly/renderonly.c
> @@ -50,27 +50,12 @@ renderonly_dup(const struct renderonly *ro)
>     return copy;
>  }
>
> -struct renderonly_scanout *
> -renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro)
> -{
> -   struct renderonly_scanout *scanout;
> -
> -   scanout = CALLOC_STRUCT(renderonly_scanout);
> -   if (!scanout)
> -      return NULL;
> -
> -   scanout->prime = rsc;
> -
> -   return scanout;
> -}
> -
>  void
>  renderonly_scanout_destroy(struct renderonly_scanout *scanout,
>                            struct renderonly *ro)
>  {
>     struct drm_mode_destroy_dumb destroy_dumb = { };
>
> -   pipe_resource_reference(&scanout->prime, NULL);
>     if (ro->kms_fd != -1) {
>        destroy_dumb.handle = scanout->handle;
>        drmIoctl(ro->kms_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
> @@ -80,12 +65,11 @@ renderonly_scanout_destroy(struct renderonly_scanout *scanout,
>
>  struct renderonly_scanout *
>  renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
> -                                               struct renderonly *ro)
> +                                               struct renderonly *ro,
> +                                               struct winsys_handle *out_handle)
>  {
> -   struct pipe_screen *screen = rsc->screen;
>     struct renderonly_scanout *scanout;
> -   struct winsys_handle handle;
> -   int prime_fd, err;
> +   int err;
>     struct drm_mode_create_dumb create_dumb = {
>        .width = rsc->width0,
>        .height = rsc->height0,
> @@ -108,30 +92,21 @@ renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
>     scanout->handle = create_dumb.handle;
>     scanout->stride = create_dumb.pitch;
>
> -   /* export dumb buffer */
> +   if (!out_handle)
> +      return scanout;
> +
> +   /* fill in winsys handle */
> +   memset(out_handle, 0, sizeof(*out_handle));
> +   out_handle->type = DRM_API_HANDLE_TYPE_FD;
> +   out_handle->stride = create_dumb.pitch;
> +
>     err = drmPrimeHandleToFD(ro->kms_fd, create_dumb.handle, O_CLOEXEC,
> -         &prime_fd);
> +         (int *)&out_handle->handle);
>     if (err < 0) {
>        fprintf(stderr, "failed to export dumb buffer: %s\n", strerror(errno));
>        goto free_dumb;
>     }
>
> -   /* import dumb buffer */
> -   memset(&handle, 0, sizeof(handle));
> -   handle.type = DRM_API_HANDLE_TYPE_FD;
> -   handle.handle = prime_fd;
> -   handle.stride = create_dumb.pitch;
> -
> -   scanout->prime = screen->resource_from_handle(screen, rsc,
> -         &handle, PIPE_HANDLE_USAGE_READ_WRITE);
> -
> -   close(prime_fd);
> -
> -   if (!scanout->prime) {
> -      fprintf(stderr, "failed to create resource_from_handle: %s\n", strerror(errno));
> -      goto free_dumb;
> -   }
> -
>     return scanout;
>
>  free_dumb:
> @@ -146,7 +121,8 @@ free_scanout:
>
>  struct renderonly_scanout *
>  renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
> -                                          struct renderonly *ro)
> +                                          struct renderonly *ro,
> +                                          struct winsys_handle *out_handle)
>  {
>     struct pipe_screen *screen = rsc->screen;
>     struct renderonly_scanout *scanout;
> diff --git a/src/gallium/auxiliary/renderonly/renderonly.h b/src/gallium/auxiliary/renderonly/renderonly.h
> index 70641c45878a..6a89c29e2ef6 100644
> --- a/src/gallium/auxiliary/renderonly/renderonly.h
> +++ b/src/gallium/auxiliary/renderonly/renderonly.h
> @@ -34,8 +34,6 @@
>  struct renderonly_scanout {
>     uint32_t handle;
>     uint32_t stride;
> -
> -   struct pipe_resource *prime;
>  };
>
>  struct renderonly {
> @@ -59,7 +57,8 @@ struct renderonly {
>      *   to be done in flush_resource(..) like a resolve to linear.
>      */
>     struct renderonly_scanout *(*create_for_resource)(struct pipe_resource *rsc,
> -                                                     struct renderonly *ro);
> +                                                     struct renderonly *ro,
> +                                                     struct winsys_handle *out_handle);
>     int kms_fd;
>     int gpu_fd;
>  };
> @@ -68,14 +67,13 @@ struct renderonly *
>  renderonly_dup(const struct renderonly *ro);
>
>  static inline struct renderonly_scanout *
> -renderonly_scanout_for_resource(struct pipe_resource *rsc, struct renderonly *ro)
> +renderonly_scanout_for_resource(struct pipe_resource *rsc,
> +                                struct renderonly *ro,
> +                                struct winsys_handle *out_handle)
>  {
> -   return ro->create_for_resource(rsc, ro);
> +   return ro->create_for_resource(rsc, ro, out_handle);
>  }
>
> -struct renderonly_scanout *
> -renderonly_scanout_for_prime(struct pipe_resource *rsc, struct renderonly *ro);
> -
>  void
>  renderonly_scanout_destroy(struct renderonly_scanout *scanout,
>                            struct renderonly *ro);
> @@ -99,13 +97,15 @@ renderonly_get_handle(struct renderonly_scanout *scanout,
>   */
>  struct renderonly_scanout *
>  renderonly_create_kms_dumb_buffer_for_resource(struct pipe_resource *rsc,
> -                                               struct renderonly *ro);
> +                                               struct renderonly *ro,
> +                                               struct winsys_handle *out_handle);
>
>  /**
>   * Import GPU resource into scanout hw.
>   */
>  struct renderonly_scanout *
>  renderonly_create_gpu_import_for_resource(struct pipe_resource *rsc,
> -                                          struct renderonly *ro);
> +                                          struct renderonly *ro,
> +                                          struct winsys_handle *out_handle);
>
>  #endif /* RENDERONLY_H_ */
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> index 80967be3f93d..83acfe21d033 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
> @@ -602,10 +602,10 @@ etna_flush_resource(struct pipe_context *pctx, struct pipe_resource *prsc)
>  {
>     struct etna_resource *rsc = etna_resource(prsc);
>
> -   if (rsc->scanout) {
> -      if (etna_resource_older(etna_resource(rsc->scanout->prime), rsc)) {
> -         etna_copy_resource(pctx, rsc->scanout->prime, prsc, 0, 0);
> -         etna_resource(rsc->scanout->prime)->seqno = rsc->seqno;
> +   if (rsc->external) {
> +      if (etna_resource_older(etna_resource(rsc->external), rsc)) {
> +         etna_copy_resource(pctx, rsc->external, prsc, 0, 0);
> +         etna_resource(rsc->external)->seqno = rsc->seqno;
>        }
>     } else if (etna_resource_needs_flush(rsc)) {
>        etna_copy_resource(pctx, prsc, prsc, 0, 0);
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.c b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> index 97e0a15597fa..a62c22d0f338 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.c
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.c
> @@ -214,8 +214,20 @@ etna_resource_alloc(struct pipe_screen *pscreen, unsigned layout,
>     rsc->bo = bo;
>     rsc->ts_bo = 0; /* TS is only created when first bound to surface */
>
> -   if (templat->bind & PIPE_BIND_SCANOUT)
> -      rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro);
> +   if (templat->bind & PIPE_BIND_SCANOUT) {
> +      struct winsys_handle handle;
> +      rsc->scanout = renderonly_scanout_for_resource(&rsc->base, screen->ro,
> +                                                     &handle);
> +      if (!rsc->scanout)
> +         goto free_rsc;
> +
> +      rsc->external = pscreen->resource_from_handle(pscreen, &rsc->base,
> +                                                    &handle,
> +                                                    PIPE_HANDLE_USAGE_WRITE);
> +      close(handle.handle);
> +      if (!rsc->external)
> +         goto free_rsc;
> +   }
>
>     if (DBG_ENABLED(ETNA_DBG_ZERO)) {
>        void *map = etna_bo_map(bo);
> @@ -310,6 +322,7 @@ etna_resource_destroy(struct pipe_screen *pscreen, struct pipe_resource *prsc)
>     list_delinit(&rsc->list);
>
>     pipe_resource_reference(&rsc->texture, NULL);
> +   pipe_resource_reference(&rsc->external, NULL);
>
>     FREE(rsc);
>  }
> @@ -375,16 +388,12 @@ etna_resource_from_handle(struct pipe_screen *pscreen,
>        /* Render targets are linear in Xorg but must be tiled
>        * here. It would be nice if dri_drawable_get_format()
>        * set scanout for these buffers too. */
> -      struct etna_resource *tiled;
>
>        ptiled = etna_resource_create(pscreen, tmpl);
>        if (!ptiled)
>           goto fail;
>
> -      tiled = etna_resource(ptiled);
> -      tiled->scanout = renderonly_scanout_for_prime(prsc, screen->ro);
> -      if (!tiled->scanout)
> -         goto fail;
> +      etna_resource(ptiled)->external = prsc;
>
>        return ptiled;
>     }
> @@ -406,9 +415,18 @@ etna_resource_get_handle(struct pipe_screen *pscreen,
>                           struct winsys_handle *handle, unsigned usage)
>  {
>     struct etna_resource *rsc = etna_resource(prsc);
> +   /* Scanout is always attached to the base resource */
> +   struct renderonly_scanout *scanout = rsc->scanout;
> +
> +   /*
> +    * External resources are preferred, so a import->export chain of
> +    * render/sampler incompatible buffers yield the same handle.
> +    * */

nitpick: remove one *

> +   if (rsc->external)
> +      rsc = etna_resource(rsc->external);
>
>     if (handle->type == DRM_API_HANDLE_TYPE_KMS &&
> -       renderonly_get_handle(rsc->scanout, handle))
> +       renderonly_get_handle(scanout, handle))
>        return TRUE;
>
>     return etna_screen_bo_get_handle(pscreen, rsc->bo, rsc->levels[0].stride,
> diff --git a/src/gallium/drivers/etnaviv/etnaviv_resource.h b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> index 3507e5ccecbc..5f563c06adcf 100644
> --- a/src/gallium/drivers/etnaviv/etnaviv_resource.h
> +++ b/src/gallium/drivers/etnaviv/etnaviv_resource.h
> @@ -75,6 +75,11 @@ struct etna_resource {
>
>     /* When we are rendering to a texture, we need a differently tiled resource */
>     struct pipe_resource *texture;
> +   /*
> +    * If imported resources have an render/sampler incompatible tiling, we keep
> +    * them as an external resource, which is blitted as needed.
> +    */
> +   struct pipe_resource *external;
>
>     enum etna_resource_status status;
>
> diff --git a/src/gallium/drivers/vc4/vc4_resource.c b/src/gallium/drivers/vc4/vc4_resource.c
> index 5aaa31d6e67d..480ef6860ef9 100644
> --- a/src/gallium/drivers/vc4/vc4_resource.c
> +++ b/src/gallium/drivers/vc4/vc4_resource.c
> @@ -598,7 +598,7 @@ vc4_resource_create(struct pipe_screen *pscreen,
>
>          if (screen->ro && tmpl->bind & PIPE_BIND_SCANOUT) {
>                  rsc->scanout =
> -                        renderonly_scanout_for_resource(prsc, screen->ro);
> +                        renderonly_scanout_for_resource(prsc, screen->ro, NULL);
>                  if (!rsc->scanout)
>                          goto fail;
>          }
> @@ -679,7 +679,8 @@ vc4_resource_from_handle(struct pipe_screen *pscreen,
>                   */
>                  rsc->scanout =
>                          renderonly_create_gpu_import_for_resource(prsc,
> -                                                                  screen->ro);
> +                                                                  screen->ro,
> +                                                                  NULL);
>                  if (!rsc->scanout)
>                          goto fail;
>          }
> --
> 2.11.0
>

greets
--
Christian Gmeiner, MSc

https://christian-gmeiner.info


More information about the mesa-dev mailing list