[PATCH xf86-video-amdgpu 3/4] glamor: Avoid generating GEM flink names for BOs shared via DRI3 (v2)

Michel Dänzer michel at daenzer.net
Thu Feb 25 07:20:39 UTC 2016


From: Michel Dänzer <michel.daenzer at amd.com>

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 <michel.daenzer at amd.com>
---
 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



More information about the xorg-driver-ati mailing list