Index: /trunk/src/VBox/Additions/x11/vboxvideo/undefined
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/undefined	(revision 49627)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/undefined	(revision 49628)
@@ -30,4 +30,5 @@
 drmFreeVersion
 drmGetVersion
+drmIoctl
 fbPictureInit
 fbScreenInit
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 49627)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.c	(revision 49628)
@@ -76,4 +76,5 @@
 
 #include "vboxvideo.h"
+#include <VBox/VBoxGuest.h>
 #include "version-generated.h"
 #include "product-generated.h"
@@ -101,4 +102,8 @@
 # include "xf86Modes.h"
 # include <X11/Xatom.h>
+#endif
+
+#ifdef VBOX_DRI
+# include "xf86drm.h"
 #endif
 
@@ -1014,4 +1019,9 @@
 #ifdef VBOX_DRI
     pVBox->useDRI = VBOXDRIScreenInit(pScrn, pScreen, pVBox);
+# ifndef VBOX_DRI_OLD  /* DRI2 */
+    if (pVBox->drmFD >= 0)
+        /* Tell the kernel driver, if present, that we are taking over. */
+        drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_DISABLE_HGSMI, NULL);
+# endif
 #endif
 
@@ -1179,10 +1189,14 @@
     TRACE_ENTRY();
     vboxClearVRAM(pScrn, 0, 0);
-    if (pVBox->fHaveHGSMI)
-        vboxEnableVbva(pScrn);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         DRIUnlock(xf86ScrnToScreen(pScrn));
-#endif
+#elif defined(VBOX_DRI)  /* DRI2 */
+    if (pVBox->drmFD >= 0)
+        /* Tell the kernel driver, if present, that we are taking over. */
+        drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_DISABLE_HGSMI, NULL);
+#endif
+    if (pVBox->fHaveHGSMI)
+        vboxEnableVbva(pScrn);
     /* Re-assert this in case we had a change request while switched out. */
     if (pVBox->FBSize.cx && pVBox->FBSize.cy)
@@ -1208,10 +1222,16 @@
         vboxDisableVbva(pScrn);
     vboxClearVRAM(pScrn, 0, 0);
-    VBOXRestoreMode(pScrn);
     vboxDisableGraphicsCap(pVBox);
 #ifdef VBOX_DRI_OLD
     if (pVBox->useDRI)
         DRILock(xf86ScrnToScreen(pScrn), 0);
-#endif
+#elif defined(VBOX_DRI)  /* DRI2 */
+    if (pVBox->drmFD >= 0)
+        /* Tell the kernel driver, if present, that it can use the framebuffer
+         * driver again. */
+        drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_ENABLE_HGSMI, NULL);
+    else
+#endif
+        VBOXRestoreMode(pScrn);
     TRACE_EXIT();
 }
@@ -1231,4 +1251,9 @@
     }
 #ifdef VBOX_DRI
+# ifndef VBOX_DRI_OLD  /* DRI2 */
+    if (pVBox->drmFD >= 0)
+        /* Tell the kernel driver, if present, that we are going away. */
+        drmIoctl(pVBox->drmFD, VBOXVIDEO_IOCTL_ENABLE_HGSMI, NULL);
+# endif
     if (pVBox->useDRI)
         VBOXDRICloseScreen(pScreen, pVBox);
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 49627)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo.h	(revision 49628)
@@ -57,4 +57,6 @@
 
 #ifdef DEBUG
+
+#include <xf86.h>
 
 #define TRACE_ENTRY() \
@@ -196,6 +198,6 @@
     __GLXvisualConfig *pVisualConfigs;
     DRIInfoRec *pDRIInfo;
+# endif
     int drmFD;
-# endif
 #endif
 } VBOXRec, *VBOXPtr;
Index: /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c
===================================================================
--- /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c	(revision 49627)
+++ /trunk/src/VBox/Additions/x11/vboxvideo/vboxvideo_dri2.c	(revision 49628)
@@ -17,6 +17,9 @@
 
 #include "vboxvideo.h"
+#include <xf86drm.h>
 #include <drm.h>
 #include <dri2.h>
+#include <fcntl.h>
+#include <unistd.h>
 
 static void VBOXDRICopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
@@ -37,4 +40,17 @@
 }
 
+/* We need to pass a constant path string to the screen initialisation function.
+ * The format is hard-coded in "drmOpen" in libdrm, and libdrm contains a
+ * comment to say that open should be done manually in future and not using
+ * "drmOpen", so we will do it manually but also hard-coding the format.  The
+ * maximum minor number (15) is also hard-coded. */
+#define PATH(minor) "/dev/dri/card" #minor
+const char *devicePaths[] =
+{
+    PATH(0), PATH(1), PATH(2), PATH(3), PATH(4), PATH(5), PATH(6), PATH(7),
+    PATH(8), PATH(9), PATH(10), PATH(11), PATH(12), PATH(13), PATH(14), PATH(15)
+};
+#undef PATH
+
 /** As long as we are using our fake DRI driver inside of Mesa, we only want
  *  to implement the minimum here to make Mesa load it.  Notably we just set
@@ -43,10 +59,33 @@
 {
     DRI2InfoRec DRI2Info;
+    unsigned i;
 
     memset(&DRI2Info, 0, sizeof(DRI2Info));
+    for (i = 0; i < RT_ELEMENTS(devicePaths); ++i)
+    {
+        int fd = open(devicePaths[i], O_RDWR);
+        if (fd >= 0)
+        {
+            drmVersionPtr pVersion = drmGetVersion(fd);
+            if (   pVersion
+                && pVersion->name_len
+                && !strcmp(pVersion->name, VBOX_DRM_DRIVER_NAME))
+            {
+                TRACE_LOG("Opened drm device %s\n", devicePaths[i]);
+                DRI2Info.deviceName = devicePaths[i];
+                /* Keep the driver open and hope that the path won't change. */
+                pVBox->drmFD = fd;
+                drmFreeVersion(pVersion);
+                break;
+            }
+            close(fd);
+            drmFreeVersion(pVersion);
+        }
+    }
+    if (!DRI2Info.deviceName)
+        return FALSE;
     DRI2Info.version = 3;
     DRI2Info.fd = -1;
     DRI2Info.driverName = VBOX_DRI_DRIVER_NAME;
-    DRI2Info.deviceName = "/dev/dri/card0";  /** @todo: do this right. */
     DRI2Info.CopyRegion = VBOXDRICopyRegion;
     DRI2Info.Wait = NULL;
@@ -56,7 +95,8 @@
 }
 
-void
-VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox)
+void VBOXDRICloseScreen(ScreenPtr pScreen, VBOXPtr pVBox)
 {
     DRI2CloseScreen(pScreen);
+    if (pVBox->drmFD)
+        close(pVBox->drmFD);
 }
