diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 1e39005fd..a99ccd8e7 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -416,7 +416,8 @@ cogl_sources_c += \
 endif
 if SUPPORT_EGL_PLATFORM_KMS
 cogl_experimental_h += \
-	$(srcdir)/cogl-kms-renderer.h
+	$(srcdir)/cogl-kms-renderer.h \
+	$(srcdir)/cogl-kms-display.h
 cogl_sources_c += \
 	$(srcdir)/winsys/cogl-winsys-egl-kms.c \
 	$(srcdir)/winsys/cogl-winsys-egl-kms-private.h
diff --git a/cogl/cogl-kms-display.h b/cogl/cogl-kms-display.h
new file mode 100644
index 000000000..012f871d0
--- /dev/null
+++ b/cogl/cogl-kms-display.h
@@ -0,0 +1,58 @@
+
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2012 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef __COGL_KMS_DISPLAY_H__
+#define __COGL_KMS_DISPLAY_H__
+
+#include <cogl/cogl-types.h>
+#include <cogl/cogl-display.h>
+
+G_BEGIN_DECLS
+
+/**
+ * cogl_kms_display_queue_modes_reset:
+ * @display: A #CoglDisplay
+ *
+ * Asks Cogl to explicitly reset the crtc output modes at the next
+ * #CoglOnscreen swap_buffers request. For applications that support
+ * VT switching they may want to re-assert the output modes when
+ * switching back to the applications VT since the modes are often not
+ * correctly restored automatically.
+ *
+ * <note>The @display must have been either explicitly setup via
+ * cogl_display_setup() or implicitily setup by having created a
+ * context using the @display</note>
+ *
+ * Since: 2.0
+ * Stability: unstable
+ */
+void
+cogl_kms_display_queue_modes_reset (CoglDisplay *display);
+
+G_END_DECLS
+#endif /* __COGL_KMS_DISPLAY_H__ */
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 8663f9557..3f1eb5303 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -105,6 +105,7 @@
 #include <cogl/cogl-poll.h>
 #if defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
 #include <cogl/cogl-kms-renderer.h>
+#include <cogl/cogl-kms-display.h>
 #endif
 #if COGL_HAS_WIN32_SUPPORT
 #include <cogl/cogl-win32-renderer.h>
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 2fd391040..f5d1e28a6 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -50,6 +50,7 @@
 #include "cogl-framebuffer-private.h"
 #include "cogl-onscreen-private.h"
 #include "cogl-kms-renderer.h"
+#include "cogl-kms-display.h"
 
 static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
 
@@ -76,6 +77,7 @@ typedef struct _CoglDisplayKMS
 {
   GList *outputs;
   int width, height;
+  gboolean pending_set_crtc;
   gboolean pending_swap_notify;
 } CoglDisplayKMS;
 
@@ -356,23 +358,26 @@ find_output (int _index,
   return output;
 }
 
-static gboolean
-set_crtc (int fd, uint32_t fb_id, CoglOutputKMS *output, GError **error)
+static void
+setup_crtc_modes (CoglDisplay *display, int fb_id)
 {
-  int ret = drmModeSetCrtc (fd,
-                            output->encoder->crtc_id,
-                            fb_id, 0, 0,
-                            &output->connector->connector_id, 1,
-                            &output->mode);
-  if (ret)
-    {
-      g_set_error (error, COGL_WINSYS_ERROR,
-                   COGL_WINSYS_ERROR_INIT,
-                   "Failed to set mode %s: %m", output->mode.name);
-      return FALSE;
-    }
+  CoglDisplayEGL *egl_display = display->winsys;
+  CoglDisplayKMS *kms_display = egl_display->platform;
+  CoglRendererEGL *egl_renderer = display->renderer->winsys;
+  CoglRendererKMS *kms_renderer = egl_renderer->platform;
+  GList *l;
 
-  return TRUE;
+  for (l = kms_display->outputs; l; l = l->next)
+    {
+      CoglOutputKMS *output = l->data;
+      int ret = drmModeSetCrtc (kms_renderer->fd,
+                                output->encoder->crtc_id,
+                                fb_id, 0, 0,
+                                &output->connector->connector_id, 1,
+                                &output->mode);
+      if (ret)
+        g_warning ("Failed to set crtc mode %s: %m", output->mode.name);
+    }
 }
 
 static gboolean
@@ -388,10 +393,6 @@ _cogl_winsys_egl_display_setup (CoglDisplay *display,
   drmModeRes *resources;
   CoglOutputKMS *output0, *output1;
   gboolean mirror;
-  struct gbm_bo *bo;
-  uint32_t handle, pitch, fb_id;
-  int width;
-  int height;
 
   kms_display = g_slice_new0 (CoglDisplayKMS);
   egl_display->platform = kms_display;
@@ -475,37 +476,12 @@ _cogl_winsys_egl_display_setup (CoglDisplay *display,
   else
     output0->mode = output0->modes[0];
 
-  width = output0->mode.hdisplay;
-  height = output0->mode.vdisplay;
+  kms_display->width = output0->mode.hdisplay;
+  kms_display->height = output0->mode.vdisplay;
 
-  bo = gbm_bo_create (kms_renderer->gbm,
-                      width, height, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT);
-  pitch = gbm_bo_get_pitch (bo);
-  handle = gbm_bo_get_handle (bo).u32;
-  if (drmModeAddFB (kms_renderer->fd,
-                    width,
-                    height,
-                    24, /* depth */
-                    32, /* bpp */
-                    pitch,
-                    handle,
-                    &fb_id) != 0)
-    {
-      g_set_error (error, COGL_WINSYS_ERROR,
-                   COGL_WINSYS_ERROR_INIT,
-                   "Failed to create initial framebuffer");
-      return FALSE;
-    }
-
-  if (!set_crtc (kms_renderer->fd, fb_id, output0, error))
-    return FALSE;
-
-  if (mirror)
-    if (!set_crtc (kms_renderer->fd, fb_id, output1, error))
-      return FALSE;
-
-  kms_display->width = width;
-  kms_display->height = height;
+  /* We defer setting the crtc modes until the first swap_buffers request of a
+   * CoglOnscreen framebuffer. */
+  kms_display->pending_set_crtc = TRUE;
 
   return TRUE;
 }
@@ -705,6 +681,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
       return;
     }
 
+  /* If this is the first framebuffer to be presented then we now setup the
+   * crtc modes... */
+  if (kms_display->pending_set_crtc)
+    {
+      setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
+      kms_display->pending_set_crtc = FALSE;
+    }
+
   flip = g_slice_new0 (CoglFlipKMS);
   flip->onscreen = onscreen;
 
@@ -985,3 +969,14 @@ cogl_kms_renderer_get_kms_fd (CoglRenderer *renderer)
   else
     return -1;
 }
+
+void
+cogl_kms_display_queue_modes_reset (CoglDisplay *display)
+{
+  if (display->setup)
+    {
+      CoglDisplayEGL *egl_display = display->winsys;
+      CoglDisplayKMS *kms_display = egl_display->platform;
+      kms_display->pending_set_crtc = TRUE;
+    }
+}