[PATCH] intel/uxa: do copy fb at startup.

Dave Airlie airlied at gmail.com
Tue Jun 12 02:26:34 PDT 2012


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 <airlied at redhat.com>
---
 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



More information about the xorg-devel mailing list