diff options
author | Dave Airlie <airlied@gmail.com> | 2012-06-12 10:26:34 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-12 15:09:05 +0100 |
commit | 3b9b64c7c9b5b0bfaafb97c9a9fe5849bbb412da (patch) | |
tree | 30249dd20eeefba76f7e42b4ab1d3933c1877621 | |
parent | b6525702b9ffd21beb8ea6bb10a8ad5ce7f9de14 (diff) |
uxa: do copy fb at startup.
Copy the current framebuffer for smooth wayland->gdm handoff.
This has been hanging around in Fedora for too long now, and we've
dropped the feature a few times, and yes I know the Simpsons did it^W^W^W
SNA does it.
I've updated the code to have some of the better fixes from nouveau.
I've no idea who wrote this code either, krh or ajax. [ickle: The
earliest version I've found had krh's fingerprints on it, though it may
still have been a joint effort.]
Signed-off-by: Dave Airlie <airlied@redhat.com>
[ickle: improve error handling, only copy the fb during initial takeover]
-rw-r--r-- | src/intel.h | 1 | ||||
-rw-r--r-- | src/intel_display.c | 129 | ||||
-rw-r--r-- | src/intel_driver.c | 6 |
3 files changed, 135 insertions, 1 deletions
diff --git a/src/intel.h b/src/intel.h index 20d82826..caf07bb0 100644 --- a/src/intel.h +++ b/src/intel.h @@ -368,6 +368,7 @@ extern void intel_mode_fini(intel_screen_private *intel); extern int intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, xf86CrtcPtr crtc); extern int intel_crtc_id(xf86CrtcPtr crtc); extern int intel_output_dpms_status(xf86OutputPtr output); +extern void intel_copy_fb(ScrnInfoPtr scrn); enum DRI2FrameEventType { DRI2_SWAP, diff --git a/src/intel_display.c b/src/intel_display.c index 6f3f7e64..8de63449 100644 --- a/src/intel_display.c +++ b/src/intel_display.c @@ -35,6 +35,7 @@ #include <unistd.h> #include <errno.h> #include <poll.h> +#include <sys/ioctl.h> #include "xorgVersion.h" @@ -45,6 +46,8 @@ #include "X11/Xatom.h" #include "X11/extensions/dpmsconst.h" #include "xf86DDC.h" +#include "fb.h" +#include "uxa.h" #include "intel_glamor.h" @@ -1748,3 +1751,129 @@ Bool intel_crtc_on(xf86CrtcPtr crtc) return ret; } + +static PixmapPtr +intel_create_pixmap_for_bo(ScreenPtr pScreen, dri_bo *bo, + int width, int height, + int depth, int bpp, + int pitch) +{ + PixmapPtr pixmap; + + pixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, 0); + if (pixmap == NullPixmap) + return pixmap; + + if (!pScreen->ModifyPixmapHeader(pixmap, + width, height, + depth, bpp, + pitch, NULL)) { + pScreen->DestroyPixmap(pixmap); + return NullPixmap; + } + + intel_set_pixmap_bo(pixmap, bo); + return pixmap; +} + +static PixmapPtr +intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id) +{ + ScreenPtr pScreen = xf86ScrnToScreen(scrn); + intel_screen_private *intel = intel_get_screen_private(scrn); + struct intel_mode *mode = intel->modes; + int fd = mode->fd; + drmModeFBPtr fbcon; + struct drm_gem_flink flink; + drm_intel_bo *bo; + PixmapPtr pixmap = NullPixmap; + + fbcon = drmModeGetFB(fd, fbcon_id); + if (fbcon == NULL) + return NULL; + + if (fbcon->depth != scrn->depth || + fbcon->width != scrn->virtualX || + fbcon->height != scrn->virtualY) + goto out_free_fb; + + flink.handle = fbcon->handle; + if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink fbcon handle\n"); + goto out_free_fb; + } + + bo = drm_intel_bo_gem_create_from_name(intel->bufmgr, + "fbcon", flink.name); + if (bo == NULL) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't allocate bo for fbcon handle\n"); + goto out_free_fb; + } + + pixmap = intel_create_pixmap_for_bo(pScreen, bo, + fbcon->width, fbcon->height, + fbcon->depth, fbcon->bpp, + fbcon->pitch); + if (pixmap == NullPixmap) + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't allocate pixmap fbcon contents\n"); + drm_intel_bo_unreference(bo); +out_free_fb: + drmModeFreeFB(fbcon); + + return pixmap; +} + +void intel_copy_fb(ScrnInfoPtr scrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + ScreenPtr pScreen = xf86ScrnToScreen(scrn); + intel_screen_private *intel = intel_get_screen_private(scrn); + PixmapPtr src, dst; + unsigned int pitch = scrn->displayWidth * intel->cpp; + struct intel_crtc *intel_crtc; + int i, fbcon_id; + + if (intel->force_fallback) + return; + + fbcon_id = 0; + for (i = 0; i < xf86_config->num_crtc; i++) { + intel_crtc = xf86_config->crtc[i]->driver_private; + if (intel_crtc->mode_crtc->buffer_id) + fbcon_id = intel_crtc->mode_crtc->buffer_id; + } + if (!fbcon_id) + return; + + src = intel_create_pixmap_for_fbcon(scrn, fbcon_id); + if (src == NULL) + return; + + /* We dont have a screen Pixmap yet */ + dst = intel_create_pixmap_for_bo(pScreen, intel->front_buffer, + scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + pitch); + if (dst == NullPixmap) + goto cleanup_src; + + if (!intel->uxa_driver->prepare_copy(src, dst, + -1, -1, + GXcopy, FB_ALLONES)) + goto cleanup_dst; + + intel->uxa_driver->copy(dst, + 0, 0, + 0, 0, + scrn->virtualX, scrn->virtualY); + intel->uxa_driver->done_copy(dst); + pScreen->canDoBGNoneRoot = TRUE; + +cleanup_dst: + (*pScreen->DestroyPixmap)(dst); +cleanup_src: + (*pScreen->DestroyPixmap)(src); +} diff --git a/src/intel_driver.c b/src/intel_driver.c index 67cec488..8962a112 100644 --- a/src/intel_driver.c +++ b/src/intel_driver.c @@ -167,7 +167,11 @@ static Bool i830CreateScreenResources(ScreenPtr screen) if (!(*screen->CreateScreenResources) (screen)) return FALSE; - return intel_uxa_create_screen_resources(screen); + if (!intel_uxa_create_screen_resources(screen)) + return FALSE; + + intel_copy_fb(scrn); + return TRUE; } static void PreInitCleanup(ScrnInfoPtr scrn) |