renderonly/etnaviv: stop importing resource from renderonly
authorLucas Stach <l.stach@pengutronix.de>
Fri, 9 Jun 2017 16:23:16 +0000 (18:23 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Wed, 19 Jul 2017 14:26:49 +0000 (16:26 +0200)
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@pengutronix.de>
Reviewed-by: Christian Gmeiner <christian.gmeiner@gmail.com>
Acked-by: Daniel Stone <daniels@collabora.com>
src/gallium/auxiliary/renderonly/renderonly.c
src/gallium/auxiliary/renderonly/renderonly.h
src/gallium/drivers/etnaviv/etnaviv_clear_blit.c
src/gallium/drivers/etnaviv/etnaviv_resource.c
src/gallium/drivers/etnaviv/etnaviv_resource.h
src/gallium/drivers/vc4/vc4_resource.c

index d3ed214f4e43debd7db58992eaeef551625421af..da91f12b2ea160394c0b4d55f4b5cf8c947a1498 100644 (file)
@@ -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;
index 70641c45878a11e654bb0ca95b579087c218c5c6..6a89c29e2ef6b0f9bccc77687c02fe79e9626d47 100644 (file)
@@ -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_ */
index d9ff9624fa4c4e0cc1e2665e662efcd6b78ae10a..b832dd8f2634ffae0fa173191088a9a4f66a4397 100644 (file)
@@ -610,10 +610,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);
index a709482c1b6b3b9c755bc3b197d44dbf8f8fd4fd..8d96baf2a04087838dda9f1e2231c7bf9a4821ca 100644 (file)
@@ -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);
 }
@@ -379,16 +392,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;
    }
@@ -410,9 +419,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.
+    */
+   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,
index 3507e5ccecbc8a6d94322c8318228a5cf24770b1..5f563c06adcfcc7bef7e86797990d311e856bf5a 100644 (file)
@@ -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;
 
index 94301bd41149525fefe61e72e40a1c9aed33550b..2018dc36d93bf109b2ab4e7f712822d2d93c08cb 100644 (file)
@@ -671,7 +671,7 @@ vc4_resource_create_with_modifiers(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;
         }
@@ -769,7 +769,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;
         }