[PATCH] xorg/driver/x86-video-intel: Avoid flicker on transition from the fb console to X

James Bottomley James.Bottomley at HansenPartnership.com
Mon Apr 11 13:03:44 PDT 2011


This patch avoids flicker as the Linux boot fbcon gives way to X by
taking an exact pixmap represenation of the fb console and rendering it
to the X display before transitioning.

---

The original patch seems to have been by Kristian Høgsberg, but every
distro has a slight variation in their build package for the intel
driver.  It's time to get it upstream to avoid us all forward porting
copies (and possibly getting it wrong).

James

Index: xf86-video-intel-2.14.903/src/intel.h
===================================================================
--- xf86-video-intel-2.14.903.orig/src/intel.h
+++ xf86-video-intel-2.14.903/src/intel.h
@@ -462,6 +462,7 @@ extern void intel_mode_fini(intel_screen
 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 pScrn);
 
 enum DRI2FrameEventType {
 	DRI2_SWAP,
Index: xf86-video-intel-2.14.903/src/intel_display.c
===================================================================
--- xf86-video-intel-2.14.903.orig/src/intel_display.c
+++ xf86-video-intel-2.14.903/src/intel_display.c
@@ -30,6 +30,7 @@
 #endif
 
 #include <sys/types.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
@@ -1426,6 +1427,108 @@ fail:
 	return FALSE;
 }
 
+static PixmapPtr
+intel_create_pixmap_for_fbcon(ScrnInfoPtr pScrn)
+{
+  xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+  ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+  drmModeFBPtr fbcon = NULL;
+  PixmapPtr pixmap = NULL;
+  struct drm_gem_flink flink;
+  drm_intel_bo *bo;
+
+  struct intel_crtc *intel_crtc = xf86_config->crtc[0]->driver_private;
+  struct intel_mode *intel_mode = intel_crtc->mode;
+  intel_screen_private *intel = intel_get_screen_private(pScrn);
+  int i;
+
+  for (i = 0; i < intel_mode->mode_res->count_crtcs; i++) {
+       intel_crtc = xf86_config->crtc[i]->driver_private;
+
+       fbcon = drmModeGetFB(intel_mode->fd, intel_crtc->mode_crtc->buffer_id);
+       if (fbcon != NULL) break;
+  }
+  if (fbcon == NULL) {
+   xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+	      "Couldn't find an fbcon\n.");
+   return NULL;
+ }
+  flink.handle = fbcon->handle;
+  if (ioctl(intel_mode->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(intel->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;
+  }
+
+  intel_set_pixmap_bo(pixmap, bo);
+  drm_intel_bo_unreference(bo);
+  drmModeFreeFB(fbcon);
+
+  return pixmap;
+}
+
+void intel_copy_fb(ScrnInfoPtr pScrn)
+{
+  ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
+  intel_screen_private *intel = intel_get_screen_private(pScrn);
+  PixmapPtr src, dst;
+  unsigned int pitch = pScrn->displayWidth * intel->cpp;
+  int savePMSize;
+  int pixmap_size;
+
+  /* Ugly: this runs before CreateScratchPixmap() which normally calculates
+     this number :( 
+  */
+  pixmap_size = sizeof(PixmapRec) + dixPrivatesSize(PRIVATE_PIXMAP);
+  savePMSize = pScreen->totalPixmapSize;
+  pScreen->totalPixmapSize = BitmapBytePad(pixmap_size * 8);
+
+  src = intel_create_pixmap_for_fbcon(pScrn);
+  if (src == NULL) {
+    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                          "Couldn't create pixmap for fbcon\n");
+    pScreen->totalPixmapSize = savePMSize; 
+    return;
+  }
+
+  /* We dont have a screen Pixmap yet */
+  dst = GetScratchPixmapHeader(pScreen,
+			       pScrn->virtualX, pScrn->virtualY,
+			       pScrn->depth, pScrn->bitsPerPixel,
+			       pitch,
+			       NULL);
+  pScreen->totalPixmapSize = savePMSize; 
+  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,
+			  pScrn->virtualX, pScrn->virtualY);
+  intel->uxa_driver->done_copy(dst);
+
+  intel_batch_submit(pScrn);
+
+  (*pScreen->DestroyPixmap)(src);
+  (*pScreen->DestroyPixmap)(dst);
+}
+
 Bool
 intel_do_pageflip(intel_screen_private *intel,
 		  dri_bo *new_front,
@@ -1573,6 +1676,8 @@ Bool intel_mode_pre_init(ScrnInfoPtr scr
 	unsigned int i;
 	int has_flipping;
 
+	scrn->canDoBGNoneRoot = TRUE;
+
 	mode = calloc(1, sizeof *mode);
 	if (!mode)
 		return FALSE;
Index: xf86-video-intel-2.14.903/src/intel_driver.c
===================================================================
--- xf86-video-intel-2.14.903.orig/src/intel_driver.c
+++ xf86-video-intel-2.14.903/src/intel_driver.c
@@ -1123,6 +1123,8 @@ static Bool I830EnterVT(int scrnIndex, i
 
 	intel_set_gem_max_sizes(scrn);
 
+	intel_copy_fb(scrn);
+
 	if (!xf86SetDesiredModes(scrn))
 		return FALSE;
 





More information about the xorg mailing list