[PATCH xf86-video-amdgpu 5/6] Make drmmode_copy_fb() work with glamor

Michel Dänzer michel at daenzer.net
Thu Aug 6 02:59:35 PDT 2015


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

Needed for Xorg -background none.

(Ported from radeon commit 3999bf88cdb192fe2f30b03bd2ed6f6a3f9f9057)

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/amdgpu_drv.h      |   1 +
 src/amdgpu_kms.c      |   7 +++-
 src/drmmode_display.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 113 insertions(+), 8 deletions(-)

diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index c7bc4f3..7194a48 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -202,6 +202,7 @@ typedef struct {
 	struct amdgpu_dri2 dri2;
 
 	/* accel */
+	PixmapPtr fbcon_pixmap;
 	uint_fast32_t gpu_flushed;
 	uint_fast32_t gpu_synced;
 	Bool use_glamor;
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index cc88e2c..1cc945e 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -112,6 +112,9 @@ static void AMDGPUFreeRec(ScrnInfoPtr pScrn)
 
 	info = AMDGPUPTR(pScrn);
 
+	if (info->fbcon_pixmap)
+		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+
 	if (info->dri2.drm_fd > 0) {
 		DevUnion *pPriv;
 		AMDGPUEntPtr pAMDGPUEnt;
@@ -1193,7 +1196,7 @@ Bool AMDGPUScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
 	pScrn->pScreen = pScreen;
 
 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
-	if (bgNoneRoot) {
+	if (bgNoneRoot && info->use_glamor) {
 		info->CreateWindow = pScreen->CreateWindow;
 		pScreen->CreateWindow = AMDGPUCreateWindow;
 	}
@@ -1256,7 +1259,7 @@ Bool AMDGPUEnterVT_KMS(VT_FUNC_ARGS_DECL)
 	pScrn->vtSema = TRUE;
 
 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
-	if (bgNoneRoot)
+	if (bgNoneRoot && info->use_glamor)
 		drmmode_copy_fb(pScrn, &info->drmmode);
 #endif
 
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3c8e231..161c2ca 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -314,16 +314,117 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
 
 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
 
-/* TODO: currently this function only clear the front buffer to zero */
-/* Moving forward, we might to look into making the copy with glamor instead */
+static PixmapPtr
+create_pixmap_for_fbcon(drmmode_ptr drmmode,
+			ScrnInfoPtr pScrn, int fbcon_id)
+{
+	AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
+	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
+	PixmapPtr pixmap = info->fbcon_pixmap;
+	struct amdgpu_buffer *bo;
+	drmModeFBPtr fbcon;
+	struct drm_gem_flink flink;
+	struct amdgpu_bo_import_result import = {0};
+
+	if (pixmap)
+		return pixmap;
+
+	fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
+	if (fbcon == NULL)
+		return NULL;
+
+	if (fbcon->depth != pScrn->depth ||
+	    fbcon->width != pScrn->virtualX ||
+	    fbcon->height != pScrn->virtualY)
+		goto out_free_fb;
+
+	flink.handle = fbcon->handle;
+	if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't flink fbcon handle\n");
+		goto out_free_fb;
+	}
+
+	bo = calloc(1, sizeof(struct amdgpu_buffer));
+	if (bo == NULL) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate bo for fbcon handle\n");
+		goto out_free_fb;
+	}
+	bo->ref_count = 1;
+
+	if (amdgpu_bo_import(pAMDGPUEnt->pDev,
+			     amdgpu_bo_handle_type_gem_flink_name, flink.name,
+			     &import) != 0) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't import BO for fbcon handle\n");
+		goto out_free_bo;
+	}
+	bo->bo.amdgpu = import.buf_handle;
+
+	pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
+					  fbcon->depth, fbcon->bpp,
+					  fbcon->pitch, bo);
+	info->fbcon_pixmap = pixmap;
+out_free_bo:
+	amdgpu_bo_unref(&bo);
+out_free_fb:
+	drmModeFreeFB(fbcon);
+	return pixmap;
+}
+
 void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
 {
+	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
-	uint32_t size = pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY;
+	PixmapPtr src, dst;
+	ScreenPtr pScreen = pScrn->pScreen;
+	int fbcon_id = 0;
+	GCPtr gc;
+	int i;
+
+	for (i = 0; i < xf86_config->num_crtc; i++) {
+		drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
+
+		if (drmmode_crtc->mode_crtc->buffer_id)
+			fbcon_id = drmmode_crtc->mode_crtc->buffer_id;
+	}
+
+	if (!fbcon_id)
+		return;
+
+	if (fbcon_id == drmmode->fb_id) {
+		/* in some rare case there might be no fbcon and we might already
+		 * be the one with the current fb to avoid a false deadlck in
+		 * kernel ttm code just do nothing as anyway there is nothing
+		 * to do
+		 */
+		return;
+	}
+
+	src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
+	if (!src)
+		return;
+
+	dst = pScreen->GetScreenPixmap(pScreen);
+
+	gc = GetScratchGC(pScrn->depth, pScreen);
+	ValidateGC(&dst->drawable, gc);
+
+	(*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
+			     pScrn->virtualX, pScrn->virtualY, 0, 0);
+
+	FreeScratchGC(gc);
+
+	amdgpu_glamor_flush(pScrn);
+
+	pScreen->canDoBGNoneRoot = TRUE;
+
+	if (info->fbcon_pixmap)
+		pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+	info->fbcon_pixmap = NULL;
 
-	/* memset the bo */
-	amdgpu_bo_map(pScrn, info->front_buffer);
-	memset(info->front_buffer->cpu_ptr, 0x00, size);
+	return;
 }
 
 #endif /* GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 */
-- 
2.5.0



More information about the xorg-driver-ati mailing list