From: Michel Dänzer <[email protected]> Needed for Xorg -background none.
(Ported from radeon commit 3999bf88cdb192fe2f30b03bd2ed6f6a3f9f9057) Signed-off-by: Michel Dänzer <[email protected]> --- 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 _______________________________________________ xorg-driver-ati mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-driver-ati
