summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2012-06-12 10:26:34 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-06-12 15:09:05 +0100
commit3b9b64c7c9b5b0bfaafb97c9a9fe5849bbb412da (patch)
tree30249dd20eeefba76f7e42b4ab1d3933c1877621
parentb6525702b9ffd21beb8ea6bb10a8ad5ce7f9de14 (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.h1
-rw-r--r--src/intel_display.c129
-rw-r--r--src/intel_driver.c6
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)