diff mbox

[RFC,2/2] sna: Support running nested in Mir

Message ID 1374475480-7255-2-git-send-email-christopher.halse.rogers@canonical.com (mailing list archive)
State New, archived
Headers show

Commit Message

Christopher James Halse Rogers July 22, 2013, 6:44 a.m. UTC
From: Christopher James Halse Rogers <raof@ubuntu.com>

This is pretty much functional for both SNA and UXA, but can't reasonably
be applied until the Xserver patch has landed, and that needs more work.

This demonstrates the approach, however.

There's probably some code to be shared with XWayland support, around the
output handling (or lack thereof) and possibly integration with the underlying
compositor for SwapBuffers etc.

---
 src/intel.h          |   7 ++
 src/intel_display.c  |  18 +++++
 src/intel_dri.c      |  23 +++++++
 src/intel_driver.c   | 191 ++++++++++++++++++++++++++++++++++++++++++++-------
 src/intel_module.c   |  30 +++++++-
 src/sna/sna.h        |  12 ++++
 src/sna/sna_accel.c  |  28 ++++++++
 src/sna/sna_dri.c    |   5 ++
 src/sna/sna_driver.c | 140 +++++++++++++++++++++++++++++++------
 9 files changed, 406 insertions(+), 48 deletions(-)

Comments

Chris Wilson July 22, 2013, 7:53 a.m. UTC | #1
With xorgMir this is not going to fly. Make sure the compatibility
cruft, first of all, exists and is out of line in a header. And expose
the driving heartbeat of when to refresh the screen pixmap from Xmir.
-Chris
Christopher James Halse Rogers July 22, 2013, 8:10 a.m. UTC | #2
On Mon, 22 Jul, 2013 at 5:53 PM, Chris Wilson 
<chris@chris-wilson.co.uk> wrote:
> With xorgMir this is not going to fly. Make sure the compatibility
> cruft, first of all, exists and is out of line in a header.
> 

Do you mean remove the various #ifdef XMIR bits, or *all* the bits 
gated on xorgMir? Some of that's not going to be trivial to hide away 
in a header.

>  And expose the driving heartbeat of when to refresh the screen 
> pixmap from Xmir.
> 
I'm not sure what you mean here - Xmir exposes the on-buffer-available 
callback, which gets triggered when swap_buffers has returned the next 
buffer to render to. This is what I'd think of as the refresh 
heartbeat. Is this not what you mean?

If you're rendering as fast as possible, this will be a 
once-per-compositor-vblank event.
Chris Wilson July 22, 2013, 8:33 a.m. UTC | #3
On Mon, Jul 22, 2013 at 08:20:49AM +0010, Christopher James Halse Rogers wrote:
> On Mon, 22 Jul, 2013 at 5:53 PM, Chris Wilson
> <chris@chris-wilson.co.uk> wrote:
> >With xorgMir this is not going to fly. Make sure the compatibility
> >cruft, first of all, exists and is out of line in a header.
> >
> 
> Do you mean remove the various #ifdef XMIR bits, or *all* the bits
> gated on xorgMir? Some of that's not going to be trivial to hide
> away in a header.

It looked like it could be done quite simply. The most important part is
to avoid the extern xorgMir - as that will be a major nuisance.

> > And expose the driving heartbeat of when to refresh the screen
> >pixmap from Xmir.
> >
> I'm not sure what you mean here - Xmir exposes the
> on-buffer-available callback, which gets triggered when swap_buffers
> has returned the next buffer to render to. This is what I'd think of
> as the refresh heartbeat. Is this not what you mean?

Yes, that's what it looked like. But I didn't see how that was being
coupled into how fast we updated.
 
> If you're rendering as fast as possible, this will be a
> once-per-compositor-vblank event.

That's what I would expect, so I am just missing the logic between that
and us sending updates.
-Chris
Chris Wilson July 22, 2013, 8:41 a.m. UTC | #4
On Mon, Jul 22, 2013 at 04:44:40PM +1000, christopher.halse.rogers@canonical.com wrote:
> From: Christopher James Halse Rogers <raof@ubuntu.com>
> 
> This is pretty much functional for both SNA and UXA, but can't reasonably
> be applied until the Xserver patch has landed, and that needs more work.
> 
> This demonstrates the approach, however.
> 
> There's probably some code to be shared with XWayland support, around the
> output handling (or lack thereof) and possibly integration with the underlying
> compositor for SwapBuffers etc.

git-am doesn't like the base sha1, can you point me to a branch?
-Chris
Christopher James Halse Rogers July 22, 2013, 9:27 a.m. UTC | #5
On Mon, 22 Jul, 2013 at 6:41 PM, Chris Wilson 
<chris@chris-wilson.co.uk> wrote:
> On Mon, Jul 22, 2013 at 04:44:40PM +1000, 
> christopher.halse.rogers@canonical.com wrote:
>>  From: Christopher James Halse Rogers <raof@ubuntu.com>
>>  
>>  This is pretty much functional for both SNA and UXA, but can't 
>> reasonably
>>  be applied until the Xserver patch has landed, and that needs more 
>> work.
>>  
>>  This demonstrates the approach, however.
>>  
>>  There's probably some code to be shared with XWayland support, 
>> around the
>>  output handling (or lack thereof) and possibly integration with the 
>> underlying
>>  compositor for SwapBuffers etc.
>> 
> git-am doesn't like the base sha1, can you point me to a branch?
> 
Oh.

Well, doesn't that make me look rather stupid. It's based on sha 
2770655371, ie: 2.21.9, because that's what my master branch was up to, 
and I didn't notice that it wasn't set to track origin/master. Git fail!
diff mbox

Patch

diff --git a/src/intel.h b/src/intel.h
index d4c9aff..01011f5 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -76,6 +76,12 @@  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <libudev.h>
 #endif
 
+#if XMIR
+#include "xmir.h"
+#else
+typedef struct xmir_screen xmir_screen;
+#endif
+
 /* remain compatible to xorg-server 1.6 */
 #ifndef MONITOR_EDID_COMPLETE_RAWDATA
 #define MONITOR_EDID_COMPLETE_RAWDATA EDID_COMPLETE_RAWDATA
@@ -350,6 +356,7 @@  typedef struct intel_screen_private {
 	InputHandlerProc uevent_handler;
 #endif
 	Bool has_prime_vmap_flush;
+	xmir_screen *xmir;
 } intel_screen_private;
 
 #ifndef I915_PARAM_HAS_PRIME_VMAP_FLUSH
diff --git a/src/intel_display.c b/src/intel_display.c
index 17168e5..d84a367 100644
--- a/src/intel_display.c
+++ b/src/intel_display.c
@@ -1872,6 +1872,17 @@  intel_mode_init(struct intel_screen_private *intel)
 {
 	struct intel_mode *mode = intel->modes;
 
+	if (intel->modes == NULL) {
+		mode = calloc (sizeof *mode, 1);
+		mode->fd = intel->drmSubFD;
+
+		mode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
+		mode->event_context.vblank_handler = intel_vblank_handler;
+		mode->event_context.page_flip_handler = intel_page_flip_handler;
+
+		intel->modes = mode;
+	}
+
 	/* We need to re-register the mode->fd for the synchronisation
 	 * feedback on every server generation, so perform the
 	 * registration within ScreenInit and not PreInit.
@@ -1967,6 +1978,13 @@  Bool intel_crtc_on(xf86CrtcPtr crtc)
 	Bool ret;
 	int i;
 
+	/* We're not in control of this crtc, probably because we're running nested.
+	 * We can't say anything useful about whether the CRTC's on or not, so say
+	 * off.
+	 */
+	if (!intel_crtc)
+		return FALSE;
+
 	if (!crtc->enabled)
 		return FALSE;
 
diff --git a/src/intel_dri.c b/src/intel_dri.c
index 0370034..e382e5e 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -68,6 +68,11 @@  USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "intel_glamor.h"
 #include "uxa.h"
 
+#ifdef XMIR
+#include "xmir.h"
+#include "xf86Priv.h"
+#endif
+
 typedef struct {
 	int refcnt;
 	PixmapPtr pixmap;
@@ -1545,6 +1550,19 @@  static const char *dri_driver_name(intel_screen_private *intel)
 	return s;
 }
 
+#if DRI2INFOREC_VERSION >= 8 && defined(XMIR)
+static int I830DRI2AuthMagic(ScreenPtr screen, uint32_t magic)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+
+	if (xorgMir)
+		return xmir_auth_drm_magic(intel->xmir, magic);
+	else
+		return drmAuthMagic(intel->drmSubFD, magic);
+}
+#endif
+
 Bool I830DRI2ScreenInit(ScreenPtr screen)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -1625,6 +1643,11 @@  Bool I830DRI2ScreenInit(ScreenPtr screen)
 	driverNames[0] = info.driverName;
 #endif
 
+#if DRI2INFOREC_VERSION >= 8 && XMIR
+	info.version = 8;
+	info.AuthMagic2 = I830DRI2AuthMagic;
+#endif
+
 	return DRI2ScreenInit(screen, &info);
 }
 
diff --git a/src/intel_driver.c b/src/intel_driver.c
index ae2e31e..e960d89 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -64,6 +64,12 @@  USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "intel.h"
 #include "intel_video.h"
 
+#ifdef XMIR
+#include "xmir.h"
+#include "dix.h"
+#include "xf86Priv.h"
+#endif
+
 #ifdef INTEL_XVMC
 #define _INTEL_XVMC_SERVER_
 #include "intel_hwmc.h"
@@ -169,7 +175,8 @@  static Bool i830CreateScreenResources(ScreenPtr screen)
 	if (!intel_uxa_create_screen_resources(screen))
 		return FALSE;
 
-	intel_copy_fb(scrn);
+	if (!xorgMir)
+		intel_copy_fb(scrn);
 	return TRUE;
 }
 
@@ -246,41 +253,51 @@  static void intel_check_dri_option(ScrnInfoPtr scrn)
 
 static Bool intel_open_drm_master(ScrnInfoPtr scrn)
 {
-	intel_screen_private *intel = intel_get_screen_private(scrn);
-	struct pci_device *dev = intel->PciInfo;
-	drmSetVersion sv;
 	struct drm_i915_getparam gp;
 	int err, has_gem;
-	char busid[20];
+	intel_screen_private *intel = intel_get_screen_private(scrn);
 
-	snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
-		 dev->domain, dev->bus, dev->dev, dev->func);
+        struct pci_device *dev = intel->PciInfo;
+        drmSetVersion sv;
+        char busid[20];
 
-	intel->drmSubFD = drmOpen(NULL, busid);
-	if (intel->drmSubFD == -1) {
+        snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%d",
+                 dev->domain, dev->bus, dev->dev, dev->func);
+
+	if (xorgMir) {
+	    intel->drmSubFD = xmir_get_drm_fd(busid);
+            if (intel->drmSubFD < 0) {
+		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+			   "[drm] Failed to retrieve DRM device %s from Mir\n",
+			   busid);
+		return FALSE;
+            }
+	} else {
+	    intel->drmSubFD = drmOpen(NULL, busid);
+	    if (intel->drmSubFD == -1) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "[drm] Failed to open DRM device for %s: %s\n",
 			   busid, strerror(errno));
 		return FALSE;
-	}
-
-	/* Check that what we opened was a master or a master-capable FD,
-	 * by setting the version of the interface we'll use to talk to it.
-	 * (see DRIOpenDRMMaster() in DRI1)
-	 */
-	sv.drm_di_major = 1;
-	sv.drm_di_minor = 1;
-	sv.drm_dd_major = -1;
-	sv.drm_dd_minor = -1;
-	err = drmSetInterfaceVersion(intel->drmSubFD, &sv);
-	if (err != 0) {
+	    }
+
+	    /* Check that what we opened was a master or a master-capable FD,
+	     * by setting the version of the interface we'll use to talk to it.
+	     * (see DRIOpenDRMMaster() in DRI1)
+	     */
+	    sv.drm_di_major = 1;
+	    sv.drm_di_minor = 1;
+	    sv.drm_dd_major = -1;
+	    sv.drm_dd_minor = -1;
+	    err = drmSetInterfaceVersion(intel->drmSubFD, &sv);
+	    if (err != 0) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "[drm] failed to set drm interface version.\n");
 		drmClose(intel->drmSubFD);
 		intel->drmSubFD = -1;
 		return FALSE;
+	    }
 	}
-
 	has_gem = FALSE;
 	gp.param = I915_PARAM_HAS_GEM;
 	gp.value = &has_gem;
@@ -299,7 +316,7 @@  static Bool intel_open_drm_master(ScrnInfoPtr scrn)
 
 static void intel_close_drm_master(intel_screen_private *intel)
 {
-	if (intel && intel->drmSubFD > 0) {
+	if (intel && intel->drmSubFD > 0 && !xorgMir) {
 		drmClose(intel->drmSubFD);
 		intel->drmSubFD = -1;
 	}
@@ -462,6 +479,101 @@  static void intel_setup_capabilities(ScrnInfoPtr scrn)
 #endif
 }
 
+#ifdef XMIR
+
+static void
+intel_xmir_copy_pixmap_to_mir(PixmapPtr src,
+                              int dst_fd)
+{
+	ScreenPtr pScreen = src->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+        dri_bo *bo;
+	PixmapPtr dst;
+	unsigned int pitch = scrn->displayWidth * intel->cpp;
+
+	/* TODO: This is open-coded create_pixmap_for_bo
+	 * We actually want to keep a stable pixmap, and just intel_set_pixmap_bo each time.
+	 */
+
+	dst = pScreen->CreatePixmap(pScreen, 0, 0, scrn->depth, 0);
+
+	if (dst == NullPixmap)
+		return;
+
+	if (!pScreen->ModifyPixmapHeader(dst,
+					 scrn->virtualX, scrn->virtualY,
+					 scrn->depth, scrn->bitsPerPixel,
+					 pitch, NULL))
+		goto cleanup_dst;
+
+
+        bo = drm_intel_bo_gem_create_from_prime(intel->bufmgr, dst_fd, 0);
+        if (!bo)
+            goto cleanup_dst;
+        intel_set_pixmap_bo(dst, bo);
+
+	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);
+
+        /* Ensure we submit the right buffer */
+        intel_batch_submit(scrn);
+cleanup_dst:
+	(*pScreen->DestroyPixmap)(dst);
+}
+
+static void
+intel_xmir_buffer_available(WindowPtr win)
+{
+	int window_fd;
+	PixmapPtr window_pixmap;
+
+	if(!xmir_window_is_dirty(win))
+		return;
+
+	window_fd = xmir_prime_fd_for_window(win);
+
+	window_pixmap = (*win->drawable.pScreen->GetWindowPixmap)(win);
+	intel_xmir_copy_pixmap_to_mir(window_pixmap, window_fd);
+
+	xmir_submit_rendering_for_window(win, NULL);
+}
+
+static void
+intel_submit_dirty_window(WindowPtr win, DamagePtr damage)
+{
+	int window_fd;
+	PixmapPtr window_pixmap;
+
+	if(!xmir_window_has_free_buffer(win))
+		return;
+
+	window_fd = xmir_prime_fd_for_window(win);
+
+	window_pixmap = (*win->drawable.pScreen->GetWindowPixmap)(win);
+	intel_xmir_copy_pixmap_to_mir(window_pixmap, window_fd);
+
+	xmir_submit_rendering_for_window(win, DamageRegion(damage));
+
+	DamageEmpty(damage);
+}
+
+static xmir_driver driver = {
+	XMIR_DRIVER_VERSION,
+	intel_xmir_buffer_available
+};
+
+#endif /* XMIR */
+
 /**
  * This is called before ScreenInit to do any require probing of screen
  * configuration.
@@ -516,6 +628,12 @@  static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
 
 	intel->PciInfo = xf86GetPciInfoForEntity(intel->pEnt->index);
 
+	if (xorgMir) {
+		intel->xmir = xmir_screen_create(scrn);
+		if (!intel->xmir)
+			return FALSE;
+	}
+
 	if (!intel_open_drm_master(scrn)) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "Failed to become DRM master.\n");
@@ -560,6 +678,9 @@  static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
 	intel_check_chipset_option(scrn);
 	intel_check_dri_option(scrn);
 
+        if (intel->xmir && !xmir_screen_pre_init(scrn, intel->xmir, &driver))
+            return FALSE;
+
 	if (!intel_init_bufmgr(intel)) {
 		PreInitCleanup(scrn);
 		return FALSE;
@@ -622,7 +743,10 @@  static Bool I830PreInit(ScrnInfoPtr scrn, int flags)
 
 	I830XvInit(scrn);
 
-	if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
+	if (xorgMir) {
+		xf86ProviderSetup(scrn, NULL, "Intel");
+	}
+	else if (!intel_mode_pre_init(scrn, intel->drmSubFD, intel->cpp)) {
 		PreInitCleanup(scrn);
 		return FALSE;
 	}
@@ -759,6 +883,10 @@  I830BlockHandler(BLOCKHANDLER_ARGS_DECL)
 #ifdef INTEL_PIXMAP_SHARING
 	intel_dirty_update(screen);
 #endif
+#ifdef XMIR
+	if (xorgMir)
+		xmir_screen_for_each_damaged_window(intel->xmir, intel_submit_dirty_window);
+#endif
 }
 
 static Bool
@@ -974,6 +1102,9 @@  I830ScreenInit(SCREEN_INIT_ARGS_DECL)
 
 	fbPictureInit(screen, NULL, 0);
 
+	if(intel->xmir)
+		xmir_screen_init(screen, intel->xmir);
+
 	xf86SetBlackWhitePixels(screen);
 
 	if (!intel_uxa_init(screen)) {
@@ -987,7 +1118,7 @@  I830ScreenInit(SCREEN_INIT_ARGS_DECL)
 	miDCInitialize(screen, xf86GetPointerScreenFuncs());
 
 	xf86DrvMsg(scrn->scrnIndex, X_INFO, "Initializing HW Cursor\n");
-	if (!xf86_cursors_init(screen, 64, 64,
+	if (!xorgMir && !xf86_cursors_init(screen, 64, 64,
 			       (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
 				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
 				HARDWARE_CURSOR_INVERT_MASK |
@@ -1109,6 +1240,9 @@  static void I830LeaveVT(VT_FUNC_ARGS_DECL)
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	int ret;
 
+	if (xorgMir)
+		return;
+
 	xf86RotateFreeShadow(scrn);
 
 	xf86_hide_cursors(scrn);
@@ -1128,6 +1262,10 @@  static Bool I830EnterVT(VT_FUNC_ARGS_DECL)
 	intel_screen_private *intel = intel_get_screen_private(scrn);
 	int ret;
 
+	if (xorgMir) {
+		return xf86SetDesiredModes(scrn);
+	}
+
 	ret = drmSetMaster(intel->drmSubFD);
 	if (ret) {
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1184,7 +1322,8 @@  static Bool I830CloseScreen(CLOSE_SCREEN_ARGS_DECL)
 	}
 
 	if (intel->front_buffer) {
-		intel_mode_remove_fb(intel);
+		if (!xorgMir)
+			intel_mode_remove_fb(intel);
 		drm_intel_bo_unreference(intel->front_buffer);
 		intel->front_buffer = NULL;
 	}
diff --git a/src/intel_module.c b/src/intel_module.c
index c1d0e09..602b889 100644
--- a/src/intel_module.c
+++ b/src/intel_module.c
@@ -51,6 +51,11 @@ 
 #include <xf86platformBus.h>
 #endif
 
+#ifdef XMIR
+#include <xf86Priv.h>
+#include <xmir.h>
+#endif
+
 static const struct intel_device_info intel_generic_info = {
 	.gen = -1,
 };
@@ -428,6 +433,11 @@  static Bool intel_driver_func(ScrnInfoPtr pScrn,
 #else
 		(*flag) = HW_IO | HW_MMIO;
 #endif
+
+#ifdef XMIR
+		if (xorgMir)
+			(*flag) = HW_SKIP_CONSOLE;
+#endif
 		return TRUE;
 	default:
 		/* Unknown or deprecated function */
@@ -483,6 +493,21 @@  static Bool has_kernel_mode_setting(const struct pci_device *dev)
 	return ret;
 }
 
+static Bool has_mir_support(const struct pci_device *dev)
+{
+	char id[20];
+
+	snprintf(id, sizeof(id),
+		 "pci:%04x:%02x:%02x.%d",
+		 dev->domain, dev->bus, dev->dev, dev->func);
+
+        if (xmir_get_drm_fd(id) < 0)
+            return FALSE;
+
+        return TRUE;
+}
+
+
 #if !UMS_ONLY
 extern XF86ConfigPtr xf86configptr;
 
@@ -578,7 +603,7 @@  static Bool intel_pci_probe(DriverPtr		driver,
 			    struct pci_device	*device,
 			    intptr_t		match_data)
 {
-	if (!has_kernel_mode_setting(device)) {
+	if (!has_kernel_mode_setting(device) && !xorgMir) {
 #if KMS_ONLY
 		return FALSE;
 #else
@@ -609,6 +634,9 @@  intel_platform_probe(DriverPtr driver,
 	if (!dev->pdev)
 		return FALSE;
 
+        if (xorgMir && !has_mir_support(dev->pdev))
+		return FALSE;
+
 	if (!has_kernel_mode_setting(dev->pdev))
 		return FALSE;
 
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 79ac1ad..9853ce8 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -75,6 +75,14 @@  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <libudev.h>
 #endif
 
+#if XMIR
+#include <xf86Priv.h>
+#include "xmir.h"
+#else
+typedef struct xmir_screen xmir_screen;
+#define xorgMir 0
+#endif
+
 #if HAS_DEBUG_FULL
 #define DBG(x) ErrorF x
 #else
@@ -306,6 +314,7 @@  struct sna {
 #endif
 
 	struct sna_render render;
+	xmir_screen *xmir;
 
 #if DEBUG_MEMORY
 	struct {
@@ -725,6 +734,9 @@  void sna_accel_watch_flush(struct sna *sna, int enable);
 void sna_accel_close(struct sna *sna);
 void sna_accel_free(struct sna *sna);
 
+void sna_xmir_copy_pixmap_to_mir(PixmapPtr src, int dst_fd);
+int sna_dri_auth_magic2(ScreenPtr screen, uint32_t magic);
+
 void sna_copy_fbcon(struct sna *sna);
 
 bool sna_composite_create(struct sna *sna);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 7e0ca6d..f6ebf1e 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -14770,6 +14770,34 @@  void sna_accel_close(struct sna *sna)
 	kgem_cleanup_cache(&sna->kgem);
 }
 
+#ifdef XMIR
+void
+sna_xmir_copy_pixmap_to_mir(PixmapPtr src, int dst_fd)
+{
+	ScreenPtr pScreen = src->drawable.pScreen;
+	ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
+	struct sna *sna = to_sna_from_pixmap(src);
+	struct sna_pixmap *priv = sna_pixmap(src);
+	struct kgem_bo *bo;
+	unsigned int pitch = priv->gpu_bo->pitch;
+	BoxRec box;
+
+	bo = kgem_create_for_prime(&sna->kgem, dst_fd, pitch * src->drawable.height);
+	if (!bo)
+		return;
+	bo->pitch = pitch;
+
+	box.x1 = box.y1 = 0;
+	box.x2 = scrn->virtualX;
+	box.y2 = scrn->virtualY;
+
+	sna->render.copy_boxes(sna, GXcopy, src, sna_pixmap(src)->gpu_bo, 0, 0,
+			       src, bo, 0, 0, &box, 1, 0);
+	kgem_submit(&sna->kgem);
+	kgem_bo_destroy(&sna->kgem, bo);
+}
+#endif
+
 void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
 {
 	if (sna->kgem.need_retire)
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 9c1bda0..ec3a1eb 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -2469,6 +2469,11 @@  bool sna_dri_open(struct sna *sna, ScreenPtr screen)
 	info.ReuseBufferNotify = NULL;
 #endif
 
+#if DRI2INFOREC_VERSION >= 8 && XMIR
+	info.version = 8;
+	info.AuthMagic2 = sna_dri_auth_magic2;
+#endif
+
 #if USE_ASYNC_SWAP
 	info.version = 10;
 	info.AsyncSwap = sna_dri_async_swap;
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index de1384d..5bd380c 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -242,7 +242,8 @@  static Bool sna_create_screen_resources(ScreenPtr screen)
 					  screen->width,
 					  screen->height,
 					  screen->rootDepth,
-					  SNA_CREATE_FB);
+					  xorgMir ? CREATE_PIXMAP_USAGE_SHARED
+						  : SNA_CREATE_FB);
 	if (!sna->front) {
 		xf86DrvMsg(screen->myNum, X_ERROR,
 			   "[intel] Unable to create front buffer %dx%d at depth %d\n",
@@ -253,7 +254,8 @@  static Bool sna_create_screen_resources(ScreenPtr screen)
 		return FALSE;
 	}
 
-	if (!sna_pixmap_force_to_gpu(sna->front, MOVE_WRITE)) {
+	if (!sna_pixmap_force_to_gpu(sna->front, xorgMir ? MOVE_READ | MOVE_WRITE
+							 : MOVE_WRITE)) {
 		xf86DrvMsg(screen->myNum, X_ERROR,
 			   "[intel] Failed to allocate video resources for front buffer %dx%d at depth %d\n",
 			   screen->width,
@@ -264,6 +266,9 @@  static Bool sna_create_screen_resources(ScreenPtr screen)
 
 	screen->SetScreenPixmap(sna->front);
 
+	if (xorgMir)
+		return TRUE;
+
 	sna_copy_fbcon(sna);
 
 	if (!sna_become_master(sna)) {
@@ -314,7 +319,6 @@  static int sna_open_drm_master(ScrnInfoPtr scrn)
 	struct sna_device *dev;
 	struct sna *sna = to_sna(scrn);
 	struct pci_device *pci = sna->PciInfo;
-	drmSetVersion sv;
 	int err;
 	char busid[20];
 	int fd;
@@ -333,11 +337,16 @@  static int sna_open_drm_master(ScrnInfoPtr scrn)
 		 pci->domain, pci->bus, pci->dev, pci->func);
 
 	DBG(("%s: opening device '%s'\n",  __FUNCTION__, busid));
-	fd = drmOpen(NULL, busid);
+
+	if (!xorgMir)
+		fd = drmOpen(NULL, busid);
+	else
+		fd = xmir_get_drm_fd(busid);
+
 	if (fd == -1) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-			   "[drm] Failed to open DRM device for %s: %s\n",
-			   busid, strerror(errno));
+			   "[drm] Failed to open DRM device for %s%s: %s\n",
+			   busid, xorgMir ? " from Mir" : "", strerror(errno));
 		return -1;
 	}
 
@@ -345,17 +354,21 @@  static int sna_open_drm_master(ScrnInfoPtr scrn)
 	 * by setting the version of the interface we'll use to talk to it.
 	 * (see DRIOpenDRMMaster() in DRI1)
 	 */
-	sv.drm_di_major = 1;
-	sv.drm_di_minor = 1;
-	sv.drm_dd_major = -1;
-	sv.drm_dd_minor = -1;
-	err = drmSetInterfaceVersion(fd, &sv);
-	if (err != 0) {
-		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
-			   "[drm] failed to set drm interface version: %s [%d].\n",
-			   strerror(-err), -err);
-		drmClose(fd);
-		return -1;
+	if (!xorgMir) {
+		drmSetVersion sv;
+
+		sv.drm_di_major = 1;
+		sv.drm_di_minor = 1;
+		sv.drm_dd_major = -1;
+		sv.drm_dd_minor = -1;
+		err = drmSetInterfaceVersion(fd, &sv);
+		if (err != 0) {
+			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+				"[drm] failed to set drm interface version: %s [%d].\n",
+				strerror(-err), -err);
+			drmClose(fd);
+			return -1;
+		}
 	}
 
 	dev = malloc(sizeof(*dev));
@@ -386,7 +399,8 @@  static void sna_close_drm_master(ScrnInfoPtr scrn)
 	if (--dev->open_count)
 		return;
 
-	drmClose(dev->fd);
+	if (!xorgMir)
+		drmClose(dev->fd);
 	sna_set_device(scrn, NULL);
 	free(dev);
 }
@@ -469,6 +483,51 @@  static Bool fb_supports_depth(int fd, int depth)
 	return ret;
 }
 
+#ifdef XMIR
+
+static void
+sna_xmir_buffer_available(WindowPtr win)
+{
+	int window_fd;
+	PixmapPtr window_pixmap;
+
+	if(!xmir_window_is_dirty(win))
+		return;
+
+	window_fd = xmir_prime_fd_for_window(win);
+
+	window_pixmap = (*win->drawable.pScreen->GetWindowPixmap)(win);
+	sna_xmir_copy_pixmap_to_mir(window_pixmap, window_fd);
+
+	xmir_submit_rendering_for_window(win, NULL);
+}
+
+static void
+sna_xmir_submit_dirty_window(WindowPtr win, DamagePtr damage)
+{
+	int window_fd;
+	PixmapPtr window_pixmap;
+
+	if(!xmir_window_has_free_buffer(win))
+		return;
+
+	window_fd = xmir_prime_fd_for_window(win);
+
+	window_pixmap = (*win->drawable.pScreen->GetWindowPixmap)(win);
+	sna_xmir_copy_pixmap_to_mir(window_pixmap, window_fd);
+
+	xmir_submit_rendering_for_window(win, DamageRegion(damage));
+
+	DamageEmpty(damage);
+}
+
+static xmir_driver sna_xmir_driver = {
+	XMIR_DRIVER_VERSION,
+	sna_xmir_buffer_available
+};
+
+#endif /* XMIR */
+
 /**
  * This is called before ScreenInit to do any require probing of screen
  * configuration.
@@ -536,6 +595,12 @@  static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
 	scrn->progClock = TRUE;
 	scrn->rgbBits = 8;
 
+	if (xorgMir) {
+		sna->xmir = xmir_screen_create(scrn);
+		if (!sna->xmir)
+			return FALSE;
+	}
+
 	fd = sna_open_drm_master(scrn);
 	if (fd == -1) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
@@ -581,6 +646,9 @@  static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
 
 	intel_detect_chipset(scrn, sna->pEnt, sna->PciInfo);
 
+	if (sna->xmir && !xmir_screen_pre_init(scrn, sna->xmir, &sna_xmir_driver))
+		return FALSE;
+
 	kgem_init(&sna->kgem, fd, sna->PciInfo, sna->info->gen);
 	if (xf86ReturnOptValBool(sna->Options, OPTION_ACCEL_DISABLE, FALSE) ||
 	    !sna_option_cast_to_bool(sna, OPTION_ACCEL_METHOD, TRUE)) {
@@ -635,7 +703,9 @@  static Bool sna_pre_init(ScrnInfoPtr scrn, int flags)
 		xf86DrvMsg(scrn->scrnIndex, X_WARNING,
 			   "Tiling disabled, expect poor performance and increased power consumption.\n");
 
-	if (!sna_mode_pre_init(scrn, sna)) {
+	if (xorgMir)
+		xf86ProviderSetup(scrn, NULL, "Intel");
+	else if (!sna_mode_pre_init(scrn, sna)) {
 		xf86DrvMsg(scrn->scrnIndex, X_ERROR,
 			   "No outputs and no modes.\n");
 		PreInitCleanup(scrn);
@@ -670,6 +740,10 @@  sna_block_handler(BLOCKHANDLER_ARGS_DECL)
 
 	if (*tv == NULL || ((*tv)->tv_usec | (*tv)->tv_sec))
 		sna_accel_block_handler(sna, tv);
+#ifdef XMIR
+	if (xorgMir)
+		xmir_screen_for_each_damaged_window(sna->xmir, sna_xmir_submit_dirty_window);
+#endif
 }
 
 static void
@@ -829,6 +903,9 @@  static void sna_leave_vt(VT_FUNC_ARGS_DECL)
 
 	DBG(("%s\n", __FUNCTION__));
 
+	if (xorgMir)
+		return;
+
 	xf86_hide_cursors(scrn);
 
 	if (drmDropMaster(sna->kgem.fd))
@@ -846,7 +923,8 @@  static Bool sna_early_close_screen(CLOSE_SCREEN_ARGS_DECL)
 	xf86_hide_cursors(scrn);
 	sna_uevent_fini(scrn);
 
-	sna_mode_close(sna);
+	if (!xorgMir)
+		sna_mode_close(sna);
 
 	if (sna->dri_open) {
 		sna_dri_close(sna, screen);
@@ -886,6 +964,19 @@  static Bool sna_late_close_screen(CLOSE_SCREEN_ARGS_DECL)
 	return TRUE;
 }
 
+#if DRI2INFOREC_VERSION >= 8 && defined(XMIR)
+int sna_dri_auth_magic2(ScreenPtr screen, uint32_t magic)
+{
+	ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+	struct sna *sna = to_sna(scrn);
+
+	if (xorgMir)
+		return xmir_auth_drm_magic(sna->xmir, magic);
+	else
+		return drmAuthMagic(sna_device(scrn)->fd, magic);
+}
+#endif
+
 static void sna_mode_set(ScrnInfoPtr scrn)
 {
 	struct sna *sna = to_sna(scrn);
@@ -1007,6 +1098,9 @@  sna_screen_init(SCREEN_INIT_ARGS_DECL)
 		return FALSE;
 	}
 
+	if (sna->xmir)
+		xmir_screen_init(screen, sna->xmir);
+
 	xf86SetBlackWhitePixels(screen);
 
 	xf86SetBackingStore(screen);
@@ -1014,7 +1108,7 @@  sna_screen_init(SCREEN_INIT_ARGS_DECL)
 	if (!miDCInitialize(screen, xf86GetPointerScreenFuncs()))
 		return FALSE;
 
-	if (xf86_cursors_init(screen, SNA_CURSOR_X, SNA_CURSOR_Y,
+	if (!xorgMir && xf86_cursors_init(screen, SNA_CURSOR_X, SNA_CURSOR_Y,
 			       HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
 			       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
 			       HARDWARE_CURSOR_INVERT_MASK |
@@ -1109,6 +1203,10 @@  static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
 	struct sna *sna = to_sna(scrn);
 
 	DBG(("%s\n", __FUNCTION__));
+
+	if (xorgMir)
+		return xf86SetDesiredModes(scrn);
+
 	if (!sna_become_master(sna))
 		return FALSE;