diff options
author | Rob Clark <robdclark@gmail.com> | 2014-04-24 14:26:21 -0400 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2014-04-25 15:06:00 -0400 |
commit | c95db2e9975c4e33f4ff28ce69a7f51512b61171 (patch) | |
tree | 97115417d67aec006e2dcd5b46bac5aa19b6dbcd | |
parent | 076cad8098a5df07e38123c69e853510c8a0d83e (diff) |
kms: copy old fb to new fb on modeset
Based on what is done in the other big desktop DDX's.. before the splash
screen drops master, copy out it's contents. This enables a seemless
transition from splash screen to greeter.
Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r-- | src/drmmode_display.c | 103 |
1 files changed, 101 insertions, 2 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index aa67a3e..fa5db68 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -224,6 +224,101 @@ drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode) } +static void +drmmode_fbcon_copy(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); + MSMPtr pMsm = MSMPTR(pScrn); + ExaDriverPtr exa = pMsm->pExa; + drmmode_ptr drmmode = NULL; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + drmModeFBPtr fb; + unsigned w = pScrn->virtualX, h = pScrn->virtualY, bpp = pScrn->bitsPerPixel; + uint32_t fbcon_id = 0; + struct fd_bo *fbcon_bo; + PixmapPtr fbcon_pix, scanout_pix; + void *ptr; + int i; + + for (i = 0; i < config->num_crtc; i++) { + drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private; + if (crtc->mode_crtc->buffer_id) { + fbcon_id = crtc->mode_crtc->buffer_id; + drmmode = crtc->drmmode; + } + } + + if (!fbcon_id) + goto fallback; + + fb = drmModeGetFB(drmmode->fd, fbcon_id); + if (!fb) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to retrieve fbcon fb: id %d\n", fbcon_id); + goto fallback; + } + + if (fb->depth != pScrn->depth || fb->width != w || fb->height != h) { + drmModeFreeFB(fb); + goto fallback; + } + + fbcon_bo = fd_bo_from_handle(pMsm->dev, fb->handle, + fb->height * fb->pitch); + if (!fbcon_bo) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to retrieve fbcon buffer: handle=0x%08x\n", + fb->handle); + drmModeFreeFB(fb); + goto fallback; + } + + fbcon_pix = drmmode_pixmap_wrap(pScreen, fb->width, fb->height, + fb->depth, fb->bpp, fb->pitch, fbcon_bo, NULL); + drmModeFreeFB(fb); + if (!fbcon_pix) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to create pixmap for fbcon contents\n"); + goto fallback; + } + + scanout_pix = drmmode_pixmap_wrap(pScreen, w, h, pScrn->depth, + bpp, pScrn->displayWidth * bpp / 8, pMsm->scanout, NULL); + if (!scanout_pix) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to init scanout pixmap for fbcon mirror\n"); + pScreen->DestroyPixmap(fbcon_pix); + goto fallback; + } + + exa->PrepareCopy(fbcon_pix, scanout_pix, 0, 0, GXcopy, ~0); + exa->Copy(scanout_pix, 0, 0, 0, 0, w, h); + exa->DoneCopy(scanout_pix); + + /* shouldn't really be needed, the PrepareAccess below will do this, + * but for good measure: + */ + MSMFlushAccel(pScreen); + + /* wait for completion before continuing, avoids seeing a momentary + * flash of "corruption" on occasion + */ + exa->PrepareAccess(scanout_pix, EXA_PREPARE_SRC); + exa->FinishAccess(scanout_pix, EXA_PREPARE_SRC); + + pScreen->DestroyPixmap(scanout_pix); + pScreen->DestroyPixmap(fbcon_pix); + pScreen->canDoBGNoneRoot = TRUE; + + return; + +fallback: + ptr = fd_bo_map(pMsm->scanout); + if (!ptr) + return; + memset(ptr, 0x00, fd_bo_size(pMsm->scanout)); +} + static Bool drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, int x, int y) @@ -1009,6 +1104,12 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) goto fail; } + if (!old_bo) { + drmmode_fbcon_copy(screen); + } else { + memset(ptr, 0x00, fd_bo_size(pMsm->scanout)); + } + /* NOTE do everything that could fail before this point, * otherwise you could end up w/ screen pixmap pointing * at the wrong scanout bo @@ -1022,8 +1123,6 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height) #endif } - memset(ptr, 0x00, fd_bo_size(pMsm->scanout)); - for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; |