From: Michel Dänzer <[email protected]>

We can't create our own struct amdgpu_buffer representation in this case
because destroying that would make the GEM handle inaccessible to glamor
as well. So just get the handle directly via dma-buf.

(ported from radeon commit 391900a670addec39515f924265bfa9f8bfa9ec0,
 extended to cache BO handles in the private for non-DRI3 pixmaps as
 well)

v2: Swap whole pixmap privates instead of just BOs in
    amdgpu_dri2_exchange_buffers to avoid invalidating cached BO handles

Signed-off-by: Michel Dänzer <[email protected]>
---
 src/amdgpu_bo_helper.c | 40 +++++++++++++++++++++++++++++++++++++---
 src/amdgpu_dri2.c      | 25 ++++++++++++++-----------
 src/amdgpu_dri3.c      | 10 ++++++++++
 src/amdgpu_pixmap.h    |  5 +++++
 4 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/src/amdgpu_bo_helper.c b/src/amdgpu_bo_helper.c
index ad56197..01b0d87 100644
--- a/src/amdgpu_bo_helper.c
+++ b/src/amdgpu_bo_helper.c
@@ -133,12 +133,46 @@ Bool amdgpu_bo_get_handle(struct amdgpu_buffer *bo, 
uint32_t *handle)
 
 Bool amdgpu_pixmap_get_handle(PixmapPtr pixmap, uint32_t *handle)
 {
-       struct amdgpu_buffer *bo = amdgpu_get_pixmap_bo(pixmap);
+#ifdef USE_GLAMOR
+       ScreenPtr screen = pixmap->drawable.pScreen;
+       ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
+#endif
+       struct amdgpu_pixmap *priv = amdgpu_get_pixmap_private(pixmap);
+
+       if (!priv) {
+               priv = calloc(1, sizeof(*priv));
+               amdgpu_set_pixmap_private(pixmap, priv);
+       }
 
-       if (!bo)
+       if (priv->handle_valid)
+               goto success;
+       
+#ifdef USE_GLAMOR
+       if (info->use_glamor) {
+               AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+               CARD16 stride;
+               CARD32 size;
+               int fd, r;
+
+               fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
+               if (fd < 0)
+                       return FALSE;
+
+               r = drmPrimeFDToHandle(pAMDGPUEnt->fd, fd, &priv->handle);
+               close(fd);
+               if (r == 0)
+                       goto success;
+       }
+#endif
+
+       if (!priv->bo || !amdgpu_bo_get_handle(priv->bo, &priv->handle))
                return FALSE;
 
-       return amdgpu_bo_get_handle(bo, handle);
+ success:
+       priv->handle_valid = TRUE;
+       *handle = priv->handle;
+       return TRUE;
 }
 
 int amdgpu_bo_map(ScrnInfoPtr pScrn, struct amdgpu_buffer *bo)
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index d974cb8..18eb876 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -719,8 +719,8 @@ amdgpu_dri2_exchange_buffers(DrawablePtr draw, 
DRI2BufferPtr front,
 {
        struct dri2_buffer_priv *front_priv = front->driverPrivate;
        struct dri2_buffer_priv *back_priv = back->driverPrivate;
-       struct amdgpu_buffer *front_bo = NULL;
-       struct amdgpu_buffer *back_bo = NULL;
+       struct amdgpu_pixmap *front_pix;
+       struct amdgpu_pixmap *back_pix;
        ScreenPtr screen;
        AMDGPUInfoPtr info;
        RegionRec region;
@@ -737,20 +737,23 @@ amdgpu_dri2_exchange_buffers(DrawablePtr draw, 
DRI2BufferPtr front,
        front->name = back->name;
        back->name = tmp;
 
-       /* Swap pixmap bos */
-       front_bo = amdgpu_get_pixmap_bo(front_priv->pixmap);
-       back_bo = amdgpu_get_pixmap_bo(back_priv->pixmap);
-       amdgpu_set_pixmap_bo(front_priv->pixmap, back_bo);
-       amdgpu_set_pixmap_bo(back_priv->pixmap, front_bo);
+       /* Swap pixmap privates */
+       front_pix = amdgpu_get_pixmap_private(front_priv->pixmap);
+       back_pix = amdgpu_get_pixmap_private(back_priv->pixmap);
+       amdgpu_set_pixmap_private(front_priv->pixmap, back_pix);
+       amdgpu_set_pixmap_private(back_priv->pixmap, front_pix);
 
        /* Do we need to update the Screen? */
        screen = draw->pScreen;
        info = AMDGPUPTR(xf86ScreenToScrn(screen));
-       if (front_bo == info->front_buffer) {
-               amdgpu_bo_ref(back_bo);
+       if (front_pix->bo == info->front_buffer) {
+               struct amdgpu_pixmap *screen_priv =
+                       
amdgpu_get_pixmap_private(screen->GetScreenPixmap(screen));
+
+               amdgpu_bo_ref(back_pix->bo);
                amdgpu_bo_unref(&info->front_buffer);
-               info->front_buffer = back_bo;
-               amdgpu_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo);
+               info->front_buffer = back_pix->bo;
+               *screen_priv = *back_pix;
        }
 
        amdgpu_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
diff --git a/src/amdgpu_dri3.c b/src/amdgpu_dri3.c
index c4b40d0..65d4899 100644
--- a/src/amdgpu_dri3.c
+++ b/src/amdgpu_dri3.c
@@ -125,6 +125,16 @@ static PixmapPtr amdgpu_dri3_pixmap_from_fd(ScreenPtr 
screen,
 {
        PixmapPtr pixmap;
 
+#ifdef USE_GLAMOR
+       /* Avoid generating a GEM flink name if possible */
+       if (AMDGPUPTR(xf86ScreenToScrn(screen))->use_glamor) {
+               pixmap = glamor_pixmap_from_fd(screen, fd, width, height,
+                                              stride, depth, bpp);
+               if (pixmap)
+                       return pixmap;
+       }
+#endif
+
        if (depth < 8)
                return NULL;
 
diff --git a/src/amdgpu_pixmap.h b/src/amdgpu_pixmap.h
index 7e0e449..6fd5ef1 100644
--- a/src/amdgpu_pixmap.h
+++ b/src/amdgpu_pixmap.h
@@ -33,6 +33,10 @@ struct amdgpu_pixmap {
        uint_fast32_t gpu_write;
 
        struct amdgpu_buffer *bo;
+
+       /* GEM handle for pixmaps shared via DRI3 */
+       Bool handle_valid;
+       uint32_t handle;
 };
 
 #if HAS_DEVPRIVATEKEYREC
@@ -70,6 +74,7 @@ static inline void amdgpu_set_pixmap_bo(PixmapPtr pPix, 
struct amdgpu_buffer *bo
 
                if (priv->bo) {
                        amdgpu_bo_unref(&priv->bo);
+                       priv->handle_valid = FALSE;
                }
 
                if (!bo) {
-- 
2.7.0

_______________________________________________
xorg-driver-ati mailing list
[email protected]
https://lists.x.org/mailman/listinfo/xorg-driver-ati

Reply via email to