Blob Blame History Raw
From e65e1eeb74775ab98b9e8912e35fc7ad1af1ffb2 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Kristian=20H=C3=B8gsberg?= <krh@redhat.com>
Date: Tue, 24 Feb 2009 10:49:45 -0500
Subject: [PATCH 2/2] Copy initial framebuffer contents when starting with -br.

---
 src/drmmode_display.c |   87 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/i830.h            |    1 +
 src/i830_driver.c     |    2 +
 3 files changed, 89 insertions(+), 1 deletions(-)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 5b48bda..527b293 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -29,6 +29,8 @@
 #include "config.h"
 #endif
 
+#include <sys/ioctl.h>
+
 #include "xorgVersion.h"
 
 #ifdef XF86DRM_MODE
@@ -145,7 +147,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	unsigned int pitch = pScrn->displayWidth * pI830->cpp;
 
 	if (drmmode->fb_id == 0) {
-		ret = drmModeAddFB(drmmode->fd,
+ 		ret = drmModeAddFB(drmmode->fd,
 				   pScrn->virtualX, pScrn->virtualY,
 				   pScrn->depth, pScrn->bitsPerPixel,
 				   pitch, pI830->front_buffer->bo->handle,
@@ -733,6 +735,8 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp)
 
 	xf86InitialConfiguration(pScrn, pI830->can_resize);
 
+	pScrn->canDoBGNoneRoot = TRUE;
+
 	return TRUE;
 }
 
@@ -760,4 +764,85 @@ Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo)
 #endif
 }
 
+static PixmapPtr
+drmmode_create_pixmap_for_fbcon(ScrnInfoPtr pScrn)
+{
+	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+	drmmode_crtc_private_ptr
+		/* FIXME: Find currently active crtc */
+		drmmode_crtc = xf86_config->crtc[1]->driver_private;
+	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	drmmode_ptr drmmode = drmmode_crtc->drmmode;
+	I830Ptr pI830 = I830PTR(pScrn);
+	drmModeFBPtr fbcon;
+	struct drm_gem_flink flink;
+	drm_intel_bo *bo;
+	PixmapPtr pixmap = NULL;
+
+	fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
+	if (fbcon == NULL)
+		return NULL;
+
+	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");
+		return NULL;
+	}
+
+	bo = drm_intel_bo_gem_create_from_name(pI830->bufmgr,
+					       "fbcon", flink.name);
+	if (bo == NULL) {
+		xf86DrvMsg(pScrn->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(pScrn->scrnIndex, X_ERROR,
+			   "Couldn't allocate pixmap fbcon contents\n");
+		return NULL;
+	}
+
+	i830_set_pixmap_bo(pixmap, bo);
+	drm_intel_bo_unreference(bo);
+	drmModeFreeFB(fbcon);
+
+	return pixmap;
+}
+void drmmode_copy_fb(ScrnInfoPtr pScrn)
+{
+	ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+	I830Ptr pI830 = I830PTR(pScrn);
+	PixmapPtr src, dst;
+	unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+
+	src = drmmode_create_pixmap_for_fbcon(pScrn);
+
+	/* We dont have a screen Pixmap yet */
+	dst = GetScratchPixmapHeader(pScreen,
+				     pScrn->virtualX, pScrn->virtualY,
+				     pScrn->depth, pScrn->bitsPerPixel,
+				     pitch,
+				     NULL);
+	i830_set_pixmap_bo(dst, pI830->front_buffer->bo);
+
+	pI830->uxa_driver->prepare_copy(src, dst, -1, -1, GXcopy, FB_ALLONES);
+
+	pI830->uxa_driver->copy(dst, 0, 0, 0, 0,
+				pScrn->virtualX, pScrn->virtualY);
+
+	pI830->uxa_driver->done_copy(dst);
+
+	I830EmitFlush(pScrn);
+	intel_batch_flush(pScrn, TRUE);
+
+	(*pScreen->DestroyPixmap)(src);
+	(*pScreen->DestroyPixmap)(dst);
+}
+
 #endif
diff --git a/src/i830.h b/src/i830.h
index 7904b9f..74b04e9 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -832,6 +832,7 @@ void I830DRI2CloseScreen(ScreenPtr pScreen);
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, int fd, int cpp);
 extern Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData,
 				     dri_bo **bo);
+extern void drmmode_copy_fb(ScrnInfoPtr pScrn);
 #endif
 
 extern Bool I830AccelInit(ScreenPtr pScreen);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 0a8a9c6..8aa33b6 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3690,6 +3690,8 @@ I830EnterVT(int scrnIndex, int flags)
        /* Clear the framebuffer */
        memset(pI830->FbBase + pScrn->fbOffset, 0,
 	      pScrn->virtualY * pScrn->displayWidth * pI830->cpp);
+   } else {
+	drmmode_copy_fb(pScrn);
    }
 
    if (!xf86SetDesiredModes (pScrn))
-- 
1.6.1.3