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. Signed-off-by: Dave Airlie <[email protected]> --- src/intel.h | 1 + src/intel_display.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/intel_driver.c | 16 ++++++-- 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/src/intel.h b/src/intel.h index 20d8282..caf07bb 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 6f3f7e6..c777435 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,110 @@ Bool intel_crtc_on(xf86CrtcPtr crtc) return ret; } + +static PixmapPtr +intel_create_pixmap_for_fbcon(ScrnInfoPtr scrn, int fbcon_id) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + ScreenPtr pScreen = xf86ScrnToScreen(scrn); + intel_screen_private *intel = intel_get_screen_private(scrn); + struct intel_mode *intel_mode = intel->modes; + drmModeFBPtr fbcon; + struct drm_gem_flink flink; + drm_intel_bo *bo; + PixmapPtr pixmap = NULL; + int i; + + fbcon = drmModeGetFB(intel_mode->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(intel_mode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't flink fbcon handle\n"); + return NULL; + } + + 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"); + return NULL; + } + + pixmap = GetScratchPixmapHeader(pScreen, + fbcon->width, fbcon->height, + fbcon->depth, fbcon->bpp, + fbcon->pitch, NULL); + if (pixmap == NULL) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't allocate pixmap fbcon contents\n"); + return NULL; + } + + intel_set_pixmap_bo(pixmap, bo); + 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; + int 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) + goto fallback; + + src = intel_create_pixmap_for_fbcon(scrn, fbcon_id); + if (src == NULL) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "Couldn't create pixmap for fbcon\n"); + return; + } + + /* We dont have a screen Pixmap yet */ + dst = GetScratchPixmapHeader(pScreen, + scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + pitch, + NULL); + intel_set_pixmap_bo(dst, intel->front_buffer); + + intel->uxa_driver->prepare_copy(src, dst, -1, -1, GXcopy, FB_ALLONES); + + intel->uxa_driver->copy(dst, 0, 0, 0, 0, + scrn->virtualX, scrn->virtualY); + + intel->uxa_driver->done_copy(dst); + + /* I830EmitFlush(scrn); */ + intel_batch_submit(scrn); + + (*pScreen->DestroyPixmap)(src); + (*pScreen->DestroyPixmap)(dst); + + pScreen->canDoBGNoneRoot = TRUE; + return; +fallback: + return; +} diff --git a/src/intel_driver.c b/src/intel_driver.c index 67cec48..703c3a3 100644 --- a/src/intel_driver.c +++ b/src/intel_driver.c @@ -83,6 +83,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL); static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL); static Bool I830EnterVT(VT_FUNC_ARGS_DECL); +static Bool I830EnterVT_copy(ScrnInfoPtr pScrn, Bool copy_fb); /* temporary */ extern void xf86SetCursor(ScreenPtr screen, CursorPtr pCurs, int x, int y); @@ -167,6 +168,7 @@ static Bool i830CreateScreenResources(ScreenPtr screen) if (!(*screen->CreateScreenResources) (screen)) return FALSE; + intel_copy_fb(scrn); return intel_uxa_create_screen_resources(screen); } @@ -1007,7 +1009,7 @@ I830ScreenInit(SCREEN_INIT_ARGS_DECL) * later memory should be bound when allocating, e.g rotate_mem */ scrn->vtSema = TRUE; - return I830EnterVT(VT_FUNC_ARGS(0)); + return I830EnterVT_copy(scrn, FALSE); } static void i830AdjustFrame(ADJUST_FRAME_ARGS_DECL) @@ -1048,9 +1050,8 @@ static void I830LeaveVT(VT_FUNC_ARGS_DECL) /* * This gets called when gaining control of the VT, and from ScreenInit(). */ -static Bool I830EnterVT(VT_FUNC_ARGS_DECL) +static Bool I830EnterVT_copy(ScrnInfoPtr scrn, Bool copy_fb) { - SCRN_INFO_PTR(arg); intel_screen_private *intel = intel_get_screen_private(scrn); int ret; @@ -1061,12 +1062,21 @@ static Bool I830EnterVT(VT_FUNC_ARGS_DECL) strerror(errno)); } + if (copy_fb) + intel_copy_fb(scrn); + if (!xf86SetDesiredModes(scrn)) return FALSE; return TRUE; } +static Bool I830EnterVT(VT_FUNC_ARGS_DECL) +{ + SCRN_INFO_PTR(arg); + return I830EnterVT_copy(scrn, TRUE); +} + static Bool I830SwitchMode(SWITCH_MODE_ARGS_DECL) { SCRN_INFO_PTR(arg); -- 1.7.10.2 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
