Jelajahi Sumber

Added Mir video target (thanks, Brandon!).

Ryan C. Gordon 11 tahun lalu
induk
melakukan
19f8c6224f

+ 2 - 0
CMakeLists.txt

@@ -231,6 +231,7 @@ set_option(SNDIO               "Support the sndio audio API" ${UNIX_SYS})
 set_option(RPATH               "Use an rpath when linking SDL" ${UNIX_SYS})
 set_option(CLOCK_GETTIME       "Use clock_gettime() instead of gettimeofday()" OFF)
 set_option(INPUT_TSLIB         "Use the Touchscreen library for input" ${UNIX_SYS})
+set_option(VIDEO_MIR           "Use Mir video driver" ${UNIX_SYS})
 set_option(VIDEO_X11           "Use X11 video driver" ${UNIX_SYS})
 set_option(VIDEO_WAYLAND       "Use Wayland video driver" ${UNIX_SYS})
 dep_option(X11_SHARED          "Dynamically load X11 support" ON "VIDEO_X11" OFF)
@@ -654,6 +655,7 @@ if(UNIX AND NOT APPLE)
 
   if(SDL_VIDEO)
     CheckX11()
+    CheckMir()
     CheckDirectFB()
     CheckOpenGLX11()
     CheckOpenGLESX11()

+ 21 - 0
cmake/sdlchecks.cmake

@@ -505,6 +505,27 @@ macro(CheckX11)
   endif(VIDEO_X11)
 endmacro(CheckX11)
 
+macro(CheckMir)
+    if(VIDEO_MIR)
+        find_library(MIR_LIB mirclient mircommon egl)
+        pkg_check_modules(MIR_TOOLKIT mirclient mircommon)
+        pkg_check_modules(EGL egl)
+        pkg_check_modules(XKB xkbcommon)
+
+        if (MIR_LIB AND MIR_TOOLKIT_FOUND AND EGL_FOUND AND XKB_FOUND)
+            set(HAVE_VIDEO_MIR TRUE)
+            set(HAVE_SDL_VIDEO TRUE)
+
+            file(GLOB MIR_SOURCES ${SDL2_SOURCE_DIR}/src/video/mir/*.c)
+            set(SOURCE_FILES ${SOURCE_FILES} ${MIR_SOURCES})
+            set(SDL_VIDEO_DRIVER_MIR 1)
+
+            list(APPEND EXTRA_CFLAGS ${MIR_TOOLKIT_CFLAGS} ${EGL_CLFAGS} ${XKB_CLFLAGS})
+            list(APPEND EXTRA_LDFLAGS ${MIR_TOOLKIT_LDFLAGS} ${EGL_LDLAGS} ${XKB_LDLAGS})
+        endif (MIR_LIB AND MIR_TOOLKIT_FOUND AND EGL_FOUND AND XKB_FOUND)
+    endif(VIDEO_MIR)
+endmacro(CheckMir)
+
 # Requires:
 # - EGL
 macro(CheckWayland)

+ 100 - 0
configure

@@ -817,6 +817,7 @@ enable_sndio
 enable_sndio_shared
 enable_diskaudio
 enable_dummyaudio
+enable_video_mir
 enable_video_wayland
 enable_video_wayland_qt_touch
 enable_wayland_shared
@@ -1534,6 +1535,7 @@ Optional Features:
   --enable-sndio-shared   dynamically load sndio audio support [[default=yes]]
   --enable-diskaudio      support the disk writer audio driver [[default=yes]]
   --enable-dummyaudio     support the dummy audio driver [[default=yes]]
+  --enable-video-mir      use Mir video driver [[default=yes]]
   --enable-video-wayland  use Wayland video driver [[default=yes]]
   --enable-video-wayland-qt-touch
                           QtWayland server support for Wayland video driver
@@ -18627,6 +18629,103 @@ $as_echo "$have_gcc_preferred_stack_boundary" >&6; }
     fi
 }
 
+CheckMir()
+{
+    # Check whether --enable-video-mir was given.
+if test "${enable_video_mir+set}" = set; then :
+  enableval=$enable_video_mir;
+else
+  enable_video_mir=yes
+fi
+
+
+    if test x$enable_video = xyes -a x$enable_video_mir = xyes; then
+        # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+        if test x$PKG_CONFIG != xno; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mir support" >&5
+$as_echo_n "checking for Mir support... " >&6; }
+            video_mir=no
+            tmp_CFLAGS="$CFLAGS"
+            CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags egl mirclient xkbcommon`"
+
+            cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <EGL/egl.h>
+             #include <xkbcommon/xkbcommon.h>
+             #include <mir_toolkit/mir_client_library.h>
+
+int
+main ()
+{
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+            video_mir=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+            CFLAGS="$tmp_CFLAGS"
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: $video_mir" >&5
+$as_echo "$video_mir" >&6; }
+
+            if test x$video_mir = xyes; then
+                  $as_echo "#define SDL_VIDEO_DRIVER_MIR 1" >>confdefs.h
+
+                  SOURCES="$SOURCES $srcdir/src/video/mir/*.c"
+                  EXTRA_CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags egl mirclient xkbcommon`"
+                  EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$PKG_CONFIG --libs egl mirclient xkbcommon`"
+                  have_video=yes
+            fi
+        fi
+    fi
+}
 
 CheckWarnAll()
 {
@@ -22451,6 +22550,7 @@ case "$host" in
         CheckSNDIO
         CheckX11
         CheckWayland
+        CheckMir
         CheckDirectFB
         CheckFusionSound
         CheckOpenGLX11

+ 37 - 0
configure.in

@@ -1124,6 +1124,42 @@ CheckStackBoundary()
     fi
 }
 
+CheckMir()
+{
+    AC_ARG_ENABLE(video-mir,
+    AC_HELP_STRING([--enable-video-mir], [use Mir video driver [[default=yes]]]),
+                   , enable_video_mir=yes)
+
+    if test x$enable_video = xyes -a x$enable_video_mir = xyes; then
+        AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+
+        if test x$PKG_CONFIG != xno; then
+            AC_MSG_CHECKING(for Mir support)
+            video_mir=no
+            tmp_CFLAGS="$CFLAGS"
+            CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags egl mirclient xkbcommon`"
+
+            AC_TRY_COMPILE([
+             #include <EGL/egl.h>
+             #include <xkbcommon/xkbcommon.h>
+             #include <mir_toolkit/mir_client_library.h>
+            ],[
+            ],[
+            video_mir=yes
+            ])
+            CFLAGS="$tmp_CFLAGS"
+            AC_MSG_RESULT($video_mir)
+
+            if test x$video_mir = xyes; then
+                  AC_DEFINE(SDL_VIDEO_DRIVER_MIR)
+                  SOURCES="$SOURCES $srcdir/src/video/mir/*.c"
+                  EXTRA_CFLAGS="$EXTRA_CFLAGS `$PKG_CONFIG --cflags egl mirclient xkbcommon`"
+                  EXTRA_LDFLAGS="$EXTRA_LDFLAGS `$PKG_CONFIG --libs egl mirclient xkbcommon`"
+                  have_video=yes
+            fi
+        fi
+    fi
+}
 
 dnl See if GCC's -Wall is supported.
 CheckWarnAll()
@@ -2612,6 +2648,7 @@ case "$host" in
         CheckSNDIO
         CheckX11
         CheckWayland
+        CheckMir
         CheckDirectFB
         CheckFusionSound
         CheckOpenGLX11

+ 1 - 0
include/SDL_config.h.cmake

@@ -259,6 +259,7 @@
 #cmakedefine SDL_VIDEO_DRIVER_DUMMY @SDL_VIDEO_DRIVER_DUMMY@
 #cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@
 #cmakedefine SDL_VIDEO_DRIVER_WAYLAND @SDL_VIDEO_DRIVER_WAYLAND@
+#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
 #cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@
 #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
 #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT @SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT@

+ 1 - 0
include/SDL_config.h.in

@@ -267,6 +267,7 @@
 #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
 #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
 #undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
+#undef SDL_VIDEO_DRIVER_MIR
 #undef SDL_VIDEO_DRIVER_X11
 #undef SDL_VIDEO_DRIVER_RPI
 #undef SDL_VIDEO_DRIVER_X11_DYNAMIC

+ 1 - 0
include/SDL_syswm.h

@@ -105,6 +105,7 @@ typedef enum
     SDL_SYSWM_COCOA,
     SDL_SYSWM_UIKIT,
     SDL_SYSWM_WAYLAND,
+    SDL_SYSWM_MIR,
 } SDL_SYSWM_TYPE;
 
 /**

+ 3 - 0
src/video/SDL_sysvideo.h

@@ -345,6 +345,9 @@ extern VideoBootStrap COCOA_bootstrap;
 #if SDL_VIDEO_DRIVER_X11
 extern VideoBootStrap X11_bootstrap;
 #endif
+#if SDL_VIDEO_DRIVER_MIR
+extern VideoBootStrap MIR_bootstrap;
+#endif
 #if SDL_VIDEO_DRIVER_DIRECTFB
 extern VideoBootStrap DirectFB_bootstrap;
 #endif

+ 3 - 0
src/video/SDL_video.c

@@ -59,6 +59,9 @@ static VideoBootStrap *bootstrap[] = {
 #if SDL_VIDEO_DRIVER_X11
     &X11_bootstrap,
 #endif
+#if SDL_VIDEO_DRIVER_MIR
+    &MIR_bootstrap,
+#endif
 #if SDL_VIDEO_DRIVER_DIRECTFB
     &DirectFB_bootstrap,
 #endif

+ 246 - 0
src/video/mir/SDL_mirevents.c

@@ -0,0 +1,246 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/SDL_touch_c.h"
+#include "../../events/scancodes_xfree86.h"
+
+#include "SDL_mirevents.h"
+#include "SDL_mirwindow.h"
+
+#include <xkbcommon/xkbcommon.h>
+
+static void
+HandleKeyText(int32_t key_code)
+{
+    char text[8];
+    int size = 0;
+
+    size = xkb_keysym_to_utf8(key_code, text, sizeof text);
+
+    if (size > 0) {
+        text[size] = '\0';
+        SDL_SendKeyboardText(text);
+    }
+}
+
+static void
+CheckKeyboardFocus(SDL_Window* sdl_window)
+{
+    SDL_Window* keyboard_window = SDL_GetKeyboardFocus();
+
+    if (keyboard_window != sdl_window)
+        SDL_SetKeyboardFocus(sdl_window);
+}
+
+
+/* FIXME
+   Mir still needs to implement its IM API, for now we assume
+   a single key press produces a character.
+*/
+static void
+HandleKeyEvent(MirKeyEvent const ev, SDL_Window* window)
+{
+    uint32_t scancode = SDL_SCANCODE_UNKNOWN;
+    Uint8 key_state = ev.action == mir_key_action_up ? SDL_RELEASED : SDL_PRESSED;
+
+    CheckKeyboardFocus(window);
+
+    if (ev.scan_code < SDL_arraysize(xfree86_scancode_table2))
+        scancode = xfree86_scancode_table2[ev.scan_code];
+
+    if (scancode != SDL_SCANCODE_UNKNOWN)
+        SDL_SendKeyboardKey(key_state, scancode);
+
+    if (key_state == SDL_PRESSED)
+        HandleKeyText(ev.key_code);
+}
+
+static void
+HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirMotionButton button_state)
+{
+    static uint32_t last_sdl_button;
+    uint32_t sdl_button;
+
+    switch (button_state) {
+        case mir_motion_button_primary:
+            sdl_button = SDL_BUTTON_LEFT;
+            break;
+        case mir_motion_button_secondary:
+            sdl_button = SDL_BUTTON_RIGHT;
+            break;
+        case mir_motion_button_tertiary:
+            sdl_button = SDL_BUTTON_MIDDLE;
+            break;
+        case mir_motion_button_forward:
+            sdl_button = SDL_BUTTON_X1;
+            break;
+        case mir_motion_button_back:
+            sdl_button = SDL_BUTTON_X2;
+            break;
+        default:
+            sdl_button = last_sdl_button;
+            break;
+    }
+
+    last_sdl_button = sdl_button;
+    SDL_SendMouseButton(sdl_window, 0, state, sdl_button);
+}
+
+static void
+HandleTouchPress(int device_id, int source_id, SDL_bool down, float x, float y, float pressure)
+{
+    SDL_SendTouch(device_id, source_id, down, x, y, pressure);
+}
+
+static void
+HandleTouchMotion(int device_id, int source_id, float x, float y, float pressure)
+{
+    SDL_SendTouchMotion(device_id, source_id, x, y, pressure);
+}
+
+static void
+HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
+{
+    SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
+}
+
+static void
+HandleMouseScroll(SDL_Window* sdl_window, int hscroll, int vscroll)
+{
+    SDL_SendMouseWheel(sdl_window, 0, hscroll, vscroll);
+}
+
+static void
+AddTouchDevice(int device_id)
+{
+    if (SDL_AddTouch(device_id, "") < 0)
+        SDL_SetError("Error: can't add touch %s, %d", __FILE__, __LINE__);
+}
+
+static void
+HandleTouchEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
+{
+    int device_id = motion.device_id;
+    int id = motion.pointer_coordinates[cord_index].id;
+
+    int width  = sdl_window->w;
+    int height = sdl_window->h;
+    float x   = motion.pointer_coordinates[cord_index].x;
+    float y   = motion.pointer_coordinates[cord_index].y;
+
+    float n_x = x / width;
+    float n_y = y / height;
+    float pressure = motion.pointer_coordinates[cord_index].pressure;
+
+    AddTouchDevice(motion.device_id);
+
+    switch (motion.action) {
+        case mir_motion_action_down:
+        case mir_motion_action_pointer_down:
+            HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure);
+            break;
+        case mir_motion_action_up:
+        case mir_motion_action_pointer_up:
+            HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure);
+            break;
+        case mir_motion_action_hover_move:
+        case mir_motion_action_move:
+            HandleTouchMotion(device_id, id, n_x, n_y, pressure);
+            break;
+        default:
+            break;
+    }
+}
+
+static void
+HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
+{
+    SDL_SetMouseFocus(sdl_window);
+
+    switch (motion.action) {
+        case mir_motion_action_down:
+        case mir_motion_action_pointer_down:
+            HandleMouseButton(sdl_window, SDL_PRESSED, motion.button_state);
+            break;
+        case mir_motion_action_up:
+        case mir_motion_action_pointer_up:
+            HandleMouseButton(sdl_window, SDL_RELEASED, motion.button_state);
+            break;
+        case mir_motion_action_hover_move:
+        case mir_motion_action_move:
+            HandleMouseMotion(sdl_window,
+                              motion.pointer_coordinates[cord_index].x,
+                              motion.pointer_coordinates[cord_index].y);
+            break;
+        case mir_motion_action_outside:
+            SDL_SetMouseFocus(NULL);
+            break;
+        case mir_motion_action_scroll:
+            HandleMouseScroll(sdl_window,
+                              motion.pointer_coordinates[cord_index].hscroll,
+                              motion.pointer_coordinates[cord_index].vscroll);
+            break;
+        case mir_motion_action_cancel:
+        case mir_motion_action_hover_enter:
+        case mir_motion_action_hover_exit:
+            break;
+        default:
+            break;
+    }
+}
+
+static void
+HandleMotionEvent(MirMotionEvent const motion, SDL_Window* sdl_window)
+{
+    int cord_index;
+    for (cord_index = 0; cord_index < motion.pointer_count; cord_index++) {
+        if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_mouse) {
+            HandleMouseEvent(motion, cord_index, sdl_window);
+        }
+        else if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_finger) {
+            HandleTouchEvent(motion, cord_index, sdl_window);
+        }
+    }
+}
+
+void
+MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context)
+{
+    SDL_Window* window = (SDL_Window*)context;
+    switch (ev->type) {
+        case (mir_event_type_key):
+            HandleKeyEvent(ev->key, window);
+            break;
+        case (mir_event_type_motion):
+            HandleMotionEvent(ev->motion, window);
+            break;
+        default:
+            break;
+    }
+}

+ 36 - 0
src/video/mir/SDL_mirevents.h

@@ -0,0 +1,36 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_mirevents_h
+#define _SDL_mirevents_h
+
+#include <mir_toolkit/mir_client_library.h>
+
+extern void
+MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context);
+
+#endif /* _SDL_mirevents_h */

+ 146 - 0
src/video/mir/SDL_mirframebuffer.c

@@ -0,0 +1,146 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+#include "SDL_mirevents.h"
+#include "SDL_mirframebuffer.h"
+#include "SDL_mirwindow.h"
+
+static const Uint32 mir_pixel_format_to_sdl_format[] = {
+    SDL_PIXELFORMAT_UNKNOWN,  /* mir_pixel_format_invalid   */
+    SDL_PIXELFORMAT_ABGR8888, /* mir_pixel_format_abgr_8888 */
+    SDL_PIXELFORMAT_BGR888,   /* mir_pixel_format_xbgr_8888 */
+    SDL_PIXELFORMAT_ARGB8888, /* mir_pixel_format_argb_8888 */
+    SDL_PIXELFORMAT_RGB888,   /* mir_pixel_format_xrgb_8888 */
+    SDL_PIXELFORMAT_BGR24     /* mir_pixel_format_bgr_888   */
+};
+
+Uint32
+MIR_GetSDLPixelFormat(MirPixelFormat format)
+{
+    return mir_pixel_format_to_sdl_format[format];
+}
+
+int
+MIR_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
+                            void** pixels, int* pitch)
+{
+    MIR_Data* mir_data = _this->driverdata;
+    MIR_Window* mir_window;
+    MirSurfaceParameters surfaceparm;
+
+    if (MIR_CreateWindow(_this, window) < 0)
+        return SDL_SetError("Failed to created a mir window.");
+
+    mir_window = window->driverdata;
+
+    mir_surface_get_parameters(mir_window->surface, &surfaceparm);
+
+    *format = MIR_GetSDLPixelFormat(surfaceparm.pixel_format);
+    if (*format == SDL_PIXELFORMAT_UNKNOWN)
+        return SDL_SetError("Unknown pixel format");
+
+    *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+
+    *pixels = SDL_malloc(window->h*(*pitch));
+    if (*pixels == NULL)
+        return SDL_OutOfMemory();
+
+    mir_window->surface = mir_connection_create_surface_sync(mir_data->connection, &surfaceparm);
+    if (!mir_surface_is_valid(mir_window->surface)) {
+        const char* error = mir_surface_get_error_message(mir_window->surface);
+        return SDL_SetError("Failed to created a mir surface: %s", error);
+    }
+
+    return 0;
+}
+
+int
+MIR_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
+                            const SDL_Rect* rects, int numrects)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    MirGraphicsRegion region;
+    int i, j, x, y, w, h, start;
+    int bytes_per_pixel, bytes_per_row, s_stride, d_stride;
+
+    mir_surface_get_graphics_region(mir_window->surface, &region);
+
+    char* s_dest = region.vaddr;
+    char* pixels = (char*)window->surface->pixels;
+
+    s_stride = window->surface->pitch;
+    d_stride = region.stride;
+    bytes_per_pixel = window->surface->format->BytesPerPixel;
+
+    for (i = 0; i < numrects; i++) {
+        s_dest = region.vaddr;
+        pixels = (char*)window->surface->pixels;
+
+        x = rects[i].x;
+        y = rects[i].y;
+        w = rects[i].w;
+        h = rects[i].h;
+
+        if (w <= 0 || h <= 0 || (x + w) <= 0 || (y + h) <= 0)
+            continue;
+
+        if (x < 0) {
+            x += w;
+            w += rects[i].x;
+        }
+
+        if (y < 0) {
+            y += h;
+            h += rects[i].y;
+        }
+
+        if (x + w > window->w)
+            w = window->w - x;
+        if (y + h > window->h)
+            h = window->h - y;
+
+        start = y * s_stride + x;
+        pixels += start;
+        s_dest += start;
+
+        bytes_per_row =  bytes_per_pixel * w;
+        for (j = 0; j < h; j++) {
+            memcpy(s_dest, pixels, bytes_per_row);
+            pixels += s_stride;
+            s_dest += d_stride;
+        }
+    }
+
+    mir_surface_swap_buffers_sync(mir_window->surface);
+
+    return 0;
+}
+
+void
+MIR_DestroyWindowFramebuffer(_THIS, SDL_Window* window)
+{
+}

+ 46 - 0
src/video/mir/SDL_mirframebuffer.h

@@ -0,0 +1,46 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_mirframebuffer_h
+#define _SDL_mirframebuffer_h
+
+#include "../SDL_sysvideo.h"
+
+#include "SDL_mirvideo.h"
+
+extern int
+MIR_CreateWindowFramebuffer(_THIS, SDL_Window* sdl_window, Uint32* format,
+                            void** pixels, int* pitch);
+
+extern int
+MIR_UpdateWindowFramebuffer(_THIS, SDL_Window* sdl_window,
+                            const SDL_Rect* rects, int numrects);
+
+extern void
+MIR_DestroyWindowFramebuffer(_THIS, SDL_Window* sdl_window);
+
+#endif /* _SDL_mirframebuffer_h */

+ 145 - 0
src/video/mir/SDL_mirmouse.c

@@ -0,0 +1,145 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#include "SDL_mirmouse.h"
+
+#include "../../events/SDL_mouse_c.h"
+#include "SDL_assert.h"
+
+static SDL_Cursor*
+MIR_CreateDefaultCursor()
+{
+    SDL_Cursor* cursor;
+
+    cursor = SDL_calloc(1, sizeof(SDL_Cursor));
+    if (cursor) {
+    }
+    else {
+        SDL_OutOfMemory();
+    }
+
+    return cursor;
+}
+
+static SDL_Cursor*
+MIR_CreateCursor(SDL_Surface* sruface, int hot_x, int hot_y)
+{
+    return MIR_CreateDefaultCursor();
+}
+
+static SDL_Cursor*
+MIR_CreateSystemCursor(SDL_SystemCursor id)
+{
+    switch(id) {
+        case SDL_SYSTEM_CURSOR_ARROW:
+            break;
+        case SDL_SYSTEM_CURSOR_IBEAM:
+            break;
+        case SDL_SYSTEM_CURSOR_WAIT:
+            break;
+        case SDL_SYSTEM_CURSOR_CROSSHAIR:
+            break;
+        case SDL_SYSTEM_CURSOR_WAITARROW:
+            break;
+        case SDL_SYSTEM_CURSOR_SIZENWSE:
+            break;
+        case SDL_SYSTEM_CURSOR_SIZENESW:
+            break;
+        case SDL_SYSTEM_CURSOR_SIZEWE:
+            break;
+        case SDL_SYSTEM_CURSOR_SIZENS:
+            break;
+        case SDL_SYSTEM_CURSOR_SIZEALL:
+            break;
+        case SDL_SYSTEM_CURSOR_NO:
+            break;
+        case SDL_SYSTEM_CURSOR_HAND:
+            break;
+        default:
+            SDL_assert(0);
+            return NULL;
+    }
+
+    return MIR_CreateDefaultCursor();
+}
+
+static void
+MIR_FreeCursor(SDL_Cursor* cursor)
+{
+    if (cursor)
+      SDL_free(cursor);
+}
+
+static int
+MIR_ShowCursor(SDL_Cursor* cursor)
+{
+    return 0;
+}
+
+static void
+MIR_WarpMouse(SDL_Window* window, int x, int y)
+{
+    SDL_Unsupported();
+}
+
+static int
+MIR_SetRelativeMouseMode(SDL_bool enabled)
+{
+    return SDL_Unsupported();
+}
+
+/* TODO Actually implement the cursor, need to wait for mir support */
+void
+MIR_InitMouse()
+{
+    SDL_Mouse* mouse = SDL_GetMouse();
+
+    mouse->CreateCursor         = MIR_CreateCursor;
+    mouse->ShowCursor           = MIR_ShowCursor;
+    mouse->FreeCursor           = MIR_FreeCursor;
+    mouse->WarpMouse            = MIR_WarpMouse;
+    mouse->CreateSystemCursor   = MIR_CreateSystemCursor;
+    mouse->SetRelativeMouseMode = MIR_SetRelativeMouseMode;
+
+    SDL_SetDefaultCursor(MIR_CreateDefaultCursor());
+}
+
+void
+MIR_FiniMouse()
+{
+    SDL_Mouse* mouse = SDL_GetMouse();
+
+    MIR_FreeCursor(mouse->def_cursor);
+    mouse->def_cursor = NULL;
+
+    mouse->CreateCursor         = NULL;
+    mouse->ShowCursor           = NULL;
+    mouse->FreeCursor           = NULL;
+    mouse->WarpMouse            = NULL;
+    mouse->CreateSystemCursor   = NULL;
+    mouse->SetRelativeMouseMode = NULL;
+}

+ 37 - 0
src/video/mir/SDL_mirmouse.h

@@ -0,0 +1,37 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_mirmouse_h
+#define _SDL_mirmouse_h
+
+extern void
+MIR_InitMouse();
+
+extern void
+MIR_FiniMouse();
+
+#endif /* _SDL_mirmouse_h */

+ 122 - 0
src/video/mir/SDL_miropengl.c

@@ -0,0 +1,122 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+#include "SDL_miropengl.h"
+
+#include <dlfcn.h>
+
+#define DEFAULT_OGL_ES2 "libGLESv2.so"
+
+void* MIR_GLHandle = NULL;
+
+void
+MIR_GL_SwapWindow(_THIS, SDL_Window* window)
+{
+    MIR_Window* mir_wind = window->driverdata;
+
+    SDL_EGL_SwapBuffers(_this, mir_wind->egl_surface);
+}
+
+int
+MIR_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context)
+{
+  if (window) {
+      EGLSurface egl_surface = ((MIR_Window*)window->driverdata)->egl_surface;
+      return SDL_EGL_MakeCurrent(_this, egl_surface, context);
+  }
+
+  return SDL_EGL_MakeCurrent(_this, NULL, NULL);
+}
+
+SDL_GLContext
+MIR_GL_CreateContext(_THIS, SDL_Window* window)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    SDL_GLContext context;
+    context = SDL_EGL_CreateContext(_this, mir_window->egl_surface);
+
+    return context;
+}
+
+int
+MIR_GL_LoadLibrary(_THIS, const char* path)
+{
+    MIR_Data* mir_data = _this->driverdata;
+
+    SDL_EGL_LoadLibrary(_this, path,
+                        mir_connection_get_egl_native_display(mir_data->connection));
+
+    SDL_EGL_ChooseConfig(_this);
+
+    return 0;
+}
+
+void
+MIR_GL_UnloadLibrary(_THIS)
+{
+    SDL_EGL_UnloadLibrary(_this);
+
+    if (MIR_GLHandle) {
+        dlclose(MIR_GLHandle);
+        MIR_GLHandle = NULL;
+    }
+}
+
+void
+Ensure_GL_HandleOpen()
+{
+    if (!MIR_GLHandle) {
+        MIR_GLHandle = dlopen(DEFAULT_OGL_ES2, RTLD_GLOBAL);
+        if (!MIR_GLHandle) {
+            SDL_SetError("Failed to dlopen library.");
+        }
+    }
+}
+
+void*
+MIR_GL_GetProcAddress(_THIS, const char* proc)
+{
+    void* proc_addr = eglGetProcAddress(proc);
+
+    /* FIXME when on the phone/tablet eglGetProcAddress returns NULL through libhybris,
+       seems to be a problem in android. Also looks like a problem in the android video driver:
+       src/video/android/SDL_androidgl.c
+
+       Workaround, to just get the address ourself
+    */
+
+    if (!proc_addr) {
+        Ensure_GL_HandleOpen();
+        proc_addr = dlsym(MIR_GLHandle, proc);
+    }
+
+    if (!proc_addr) {
+        SDL_SetError("Failed to find proc address!");
+    }
+
+    return proc_addr;
+}

+ 57 - 0
src/video/mir/SDL_miropengl.h

@@ -0,0 +1,57 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_miropengl_h
+#define _SDL_miropengl_h
+
+#include "SDL_mirwindow.h"
+
+#include "../SDL_egl_c.h"
+
+#define MIR_GL_DeleteContext   SDL_EGL_DeleteContext
+#define MIR_GL_GetSwapInterval SDL_EGL_GetSwapInterval
+#define MIR_GL_SetSwapInterval SDL_EGL_SetSwapInterval
+
+extern void
+MIR_GL_SwapWindow(_THIS, SDL_Window* window);
+
+extern int
+MIR_GL_MakeCurrent(_THIS, SDL_Window* window, SDL_GLContext context);
+
+extern SDL_GLContext
+MIR_GL_CreateContext(_THIS, SDL_Window* window);
+
+extern int
+MIR_GL_LoadLibrary(_THIS, const char* path);
+
+extern void
+MIR_GL_UnloadLibrary(_THIS);
+
+extern void*
+MIR_GL_GetProcAddress(_THIS, const char* proc);
+
+#endif /* _SDL_miropengl_h */

+ 319 - 0
src/video/mir/SDL_mirvideo.c

@@ -0,0 +1,319 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+#include "SDL_video.h"
+
+#include "SDL_mirframebuffer.h"
+#include "SDL_mirmouse.h"
+#include "SDL_miropengl.h"
+#include "SDL_mirvideo.h"
+#include "SDL_mirwindow.h"
+
+#define MIR_DRIVER_NAME "mir"
+
+static int
+MIR_VideoInit(_THIS);
+
+static void
+MIR_VideoQuit(_THIS);
+
+static int
+MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect);
+
+static void
+MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* sdl_display);
+
+static int
+MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* sdl_display, SDL_DisplayMode* mode);
+
+static SDL_WindowShaper*
+MIR_CreateShaper(SDL_Window* window)
+{
+    /* FIXME Im not sure if mir support this atm, will have to come back to this */
+    return NULL;
+}
+
+static int
+MIR_SetWindowShape(SDL_WindowShaper* shaper, SDL_Surface* shape, SDL_WindowShapeMode* shape_mode)
+{
+    return SDL_Unsupported();
+}
+
+static int
+MIR_ResizeWindowShape(SDL_Window* window)
+{
+    return SDL_Unsupported();
+}
+
+static int
+MIR_Available()
+{
+    return 1;
+}
+
+static void
+MIR_DeleteDevice(SDL_VideoDevice* device)
+{
+    SDL_free(device);
+}
+
+void
+MIR_PumpEvents(_THIS)
+{
+}
+
+static SDL_VideoDevice*
+MIR_CreateDevice(int device_index)
+{
+    MIR_Data* mir_data;
+    SDL_VideoDevice* device = SDL_calloc(1, sizeof(SDL_VideoDevice));
+    if (!device) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    mir_data = SDL_calloc(1, sizeof(MIR_Data));
+    if (!mir_data) {
+        SDL_OutOfMemory();
+        SDL_free(device);
+        return NULL;
+    }
+
+    device->driverdata = mir_data;
+
+    /* mirvideo */
+    device->VideoInit        = MIR_VideoInit;
+    device->VideoQuit        = MIR_VideoQuit;
+    device->GetDisplayBounds = MIR_GetDisplayBounds;
+    device->GetDisplayModes  = MIR_GetDisplayModes;
+    device->SetDisplayMode   = MIR_SetDisplayMode;
+    device->free             = MIR_DeleteDevice;
+
+    /* miropengles */
+    device->GL_SwapWindow      = MIR_GL_SwapWindow;
+    device->GL_MakeCurrent     = MIR_GL_MakeCurrent;
+    device->GL_CreateContext   = MIR_GL_CreateContext;
+    device->GL_DeleteContext   = MIR_GL_DeleteContext;
+    device->GL_LoadLibrary     = MIR_GL_LoadLibrary;
+    device->GL_UnloadLibrary   = MIR_GL_UnloadLibrary;
+    device->GL_GetSwapInterval = MIR_GL_GetSwapInterval;
+    device->GL_SetSwapInterval = MIR_GL_SetSwapInterval;
+    device->GL_GetProcAddress  = MIR_GL_GetProcAddress;
+
+    /* mirwindow */
+    device->CreateWindow        = MIR_CreateWindow;
+    device->DestroyWindow       = MIR_DestroyWindow;
+    device->GetWindowWMInfo     = MIR_GetWindowWMInfo;
+    device->SetWindowFullscreen = MIR_SetWindowFullscreen;
+    device->MaximizeWindow      = MIR_MaximizeWindow;
+    device->MinimizeWindow      = MIR_MinimizeWindow;
+    device->RestoreWindow       = MIR_RestoreWindow;
+
+    device->CreateWindowFrom     = NULL;
+    device->SetWindowTitle       = NULL;
+    device->SetWindowIcon        = NULL;
+    device->SetWindowPosition    = NULL;
+    device->SetWindowSize        = NULL;
+    device->SetWindowMinimumSize = NULL;
+    device->SetWindowMaximumSize = NULL;
+    device->ShowWindow           = NULL;
+    device->HideWindow           = NULL;
+    device->RaiseWindow          = NULL;
+    device->SetWindowBordered    = NULL;
+    device->SetWindowGammaRamp   = NULL;
+    device->GetWindowGammaRamp   = NULL;
+    device->SetWindowGrab        = NULL;
+    device->OnWindowEnter        = NULL;
+
+    /* mirframebuffer */
+    device->CreateWindowFramebuffer  = MIR_CreateWindowFramebuffer;
+    device->UpdateWindowFramebuffer  = MIR_UpdateWindowFramebuffer;
+    device->DestroyWindowFramebuffer = MIR_DestroyWindowFramebuffer;
+
+    device->shape_driver.CreateShaper      = MIR_CreateShaper;
+    device->shape_driver.SetWindowShape    = MIR_SetWindowShape;
+    device->shape_driver.ResizeWindowShape = MIR_ResizeWindowShape;
+
+    device->PumpEvents = MIR_PumpEvents;
+
+    device->SuspendScreenSaver = NULL;
+
+    device->StartTextInput   = NULL;
+    device->StopTextInput    = NULL;
+    device->SetTextInputRect = NULL;
+
+    device->HasScreenKeyboardSupport = NULL;
+    device->ShowScreenKeyboard       = NULL;
+    device->HideScreenKeyboard       = NULL;
+    device->IsScreenKeyboardShown    = NULL;
+
+    device->SetClipboardText = NULL;
+    device->GetClipboardText = NULL;
+    device->HasClipboardText = NULL;
+
+    device->ShowMessageBox = NULL;
+
+    return device;
+}
+
+VideoBootStrap MIR_bootstrap = {
+    MIR_DRIVER_NAME, "SDL Mir video driver",
+    MIR_Available, MIR_CreateDevice
+};
+
+static void
+MIR_SetCurrentDisplayMode(MirDisplayOutput const* out, SDL_VideoDisplay* display)
+{
+    SDL_DisplayMode mode = {
+        .format = SDL_PIXELFORMAT_RGB888,
+        .w = out->modes[out->current_mode].horizontal_resolution,
+        .h = out->modes[out->current_mode].vertical_resolution,
+        .refresh_rate = out->modes[out->current_mode].refresh_rate,
+        .driverdata = NULL
+    };
+
+    display->desktop_mode = mode;
+    display->current_mode = mode;
+}
+
+static void
+MIR_AddAllModesFromDisplay(MirDisplayOutput const* out, SDL_VideoDisplay* display)
+{
+    int n_mode;
+    for (n_mode = 0; n_mode < out->num_modes; ++n_mode) {
+        SDL_DisplayMode mode = {
+            .format = SDL_PIXELFORMAT_RGB888,
+            .w = out->modes[n_mode].horizontal_resolution,
+            .h = out->modes[n_mode].vertical_resolution,
+            .refresh_rate = out->modes[n_mode].refresh_rate,
+            .driverdata = NULL
+        };
+
+        SDL_AddDisplayMode(display, &mode);
+    }
+}
+
+static void
+MIR_InitDisplays(_THIS)
+{
+    MIR_Data* mir_data = _this->driverdata;
+    int d;
+
+    MirDisplayConfiguration* display_config =
+            mir_connection_create_display_config(mir_data->connection);
+
+    for (d = 0; d < display_config->num_outputs; d++) {
+        MirDisplayOutput const* out = display_config->outputs + d;
+
+        SDL_VideoDisplay display;
+        SDL_zero(display);
+
+        if (out->used &&
+            out->connected &&
+            out->num_modes &&
+            out->current_mode < out->num_modes) {
+
+            MIR_SetCurrentDisplayMode(out, &display);
+            MIR_AddAllModesFromDisplay(out, &display);
+
+            SDL_AddVideoDisplay(&display);
+        }
+    }
+
+    mir_display_config_destroy(display_config);
+}
+
+int
+MIR_VideoInit(_THIS)
+{
+    MIR_Data* mir_data = _this->driverdata;
+
+    mir_data->connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
+
+    if (!mir_connection_is_valid(mir_data->connection))
+        return SDL_SetError("Failed to connect to the Mir Server");
+
+    MIR_InitDisplays(_this);
+    MIR_InitMouse();
+
+    return 0;
+}
+
+void
+MIR_VideoQuit(_THIS)
+{
+    MIR_Data* mir_data = _this->driverdata;
+
+    MIR_FiniMouse();
+
+    MIR_GL_DeleteContext(_this, NULL);
+    MIR_GL_UnloadLibrary(_this);
+
+    mir_connection_release(mir_data->connection);
+
+    SDL_free(mir_data);
+    _this->driverdata = NULL;
+}
+
+static int
+MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect)
+{
+    MIR_Data* mir_data = _this->driverdata;
+    int d;
+
+    MirDisplayConfiguration* display_config =
+            mir_connection_create_display_config(mir_data->connection);
+
+    for (d = 0; d < display_config->num_outputs; d++) {
+        MirDisplayOutput const* out = display_config->outputs + d;
+
+        if (out->used &&
+            out->connected &&
+            out->num_modes &&
+            out->current_mode < out->num_modes) {
+
+            rect->x = out->position_x;
+            rect->y = out->position_y;
+            rect->w = out->modes->horizontal_resolution;
+            rect->h = out->modes->vertical_resolution;
+        }
+    }
+
+    mir_display_config_destroy(display_config);
+
+    return 0;
+}
+
+static void
+MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* sdl_display)
+{
+}
+
+static int
+MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* sdl_display, SDL_DisplayMode* mode)
+{
+    return 0;
+}

+ 40 - 0
src/video/mir/SDL_mirvideo.h

@@ -0,0 +1,40 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_mirvideo_h_
+#define _SDL_mirvideo_h_
+
+#include <EGL/egl.h>
+#include <mir_toolkit/mir_client_library.h>
+
+typedef struct
+{
+    MirConnection* connection;
+
+} MIR_Data;
+
+#endif /* _SDL_mirvideo_h_ */

+ 216 - 0
src/video/mir/SDL_mirwindow.c

@@ -0,0 +1,216 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#include "../SDL_egl_c.h"
+#include "../SDL_sysvideo.h"
+
+#include "SDL_mirevents.h"
+#include "SDL_mirwindow.h"
+
+int
+IsSurfaceValid(MIR_Window* mir_window)
+{
+    if (!mir_surface_is_valid(mir_window->surface)) {
+        const char* error = mir_surface_get_error_message(mir_window->surface);
+        return SDL_SetError("Failed to created a mir surface: %s", error);
+    }
+
+    return 0;
+}
+
+MirPixelFormat
+FindValidPixelFormat(MIR_Data* mir_data)
+{
+    unsigned int pf_size = 32;
+    unsigned int valid_formats;
+    unsigned int f;
+
+    MirPixelFormat formats[pf_size];
+    mir_connection_get_available_surface_formats(mir_data->connection, formats,
+                                                 pf_size, &valid_formats);
+
+    for (f = 0; f < valid_formats; f++) {
+        MirPixelFormat cur_pf = formats[f];
+
+        if (cur_pf == mir_pixel_format_abgr_8888 ||
+            cur_pf == mir_pixel_format_xbgr_8888 ||
+            cur_pf == mir_pixel_format_argb_8888 ||
+            cur_pf == mir_pixel_format_xrgb_8888) {
+
+            return cur_pf;
+        }
+    }
+
+    return mir_pixel_format_invalid;
+}
+
+int
+MIR_CreateWindow(_THIS, SDL_Window* window)
+{
+    MIR_Window* mir_window;
+    MIR_Data* mir_data;
+
+    MirSurfaceParameters surfaceparm =
+    {
+        .name = "MirSurface",
+        .width = window->w,
+        .height = window->h,
+        .pixel_format = mir_pixel_format_invalid,
+        .buffer_usage = mir_buffer_usage_hardware
+    };
+
+    MirEventDelegate delegate = {
+        MIR_HandleInput,
+        window
+    };
+
+    mir_window = SDL_calloc(1, sizeof(MIR_Window));
+    if (!mir_window)
+        return SDL_OutOfMemory();
+
+    mir_data = _this->driverdata;
+    window->driverdata = mir_window;
+
+    if (window->x == SDL_WINDOWPOS_UNDEFINED)
+        window->x = 0;
+
+    if (window->y == SDL_WINDOWPOS_UNDEFINED)
+        window->y = 0;
+
+    mir_window->mir_data = mir_data;
+    mir_window->sdl_window = window;
+
+    surfaceparm.pixel_format = FindValidPixelFormat(mir_data);
+    if (surfaceparm.pixel_format == mir_pixel_format_invalid) {
+        return SDL_SetError("Failed to find a valid pixel format.");
+    }
+
+    mir_window->surface = mir_connection_create_surface_sync(mir_data->connection, &surfaceparm);
+    if (!mir_surface_is_valid(mir_window->surface)) {
+        const char* error = mir_surface_get_error_message(mir_window->surface);
+        return SDL_SetError("Failed to created a mir surface: %s", error);
+    }
+
+    if (window->flags & SDL_WINDOW_OPENGL) {
+        EGLNativeWindowType egl_native_window =
+                        (EGLNativeWindowType)mir_surface_get_egl_native_window(mir_window->surface);
+
+        mir_window->egl_surface = SDL_EGL_CreateSurface(_this, egl_native_window);
+
+        if (mir_window->egl_surface == EGL_NO_SURFACE) {
+            return SDL_SetError("Failed to created a window surface %p",
+                                _this->egl_data->egl_display);
+        }
+    }
+    else {
+        mir_window->egl_surface = EGL_NO_SURFACE;
+    }
+
+    mir_surface_set_event_handler(mir_window->surface, &delegate);
+
+    return 0;
+}
+
+void
+MIR_DestroyWindow(_THIS, SDL_Window* window)
+{
+    MIR_Data* mir_data = _this->driverdata;
+    MIR_Window* mir_window = window->driverdata;
+
+    window->driverdata = NULL;
+
+    if (mir_data) {
+        SDL_EGL_DestroySurface(_this, mir_window->egl_surface);
+        mir_surface_release_sync(mir_window->surface);
+
+        SDL_free(mir_window);
+    }
+}
+
+SDL_bool
+MIR_GetWindowWMInfo(_THIS, SDL_Window* window, SDL_SysWMinfo* info)
+{
+    if (info->version.major == SDL_MAJOR_VERSION &&
+        info->version.minor == SDL_MINOR_VERSION) {
+
+        info->subsystem = SDL_SYSWM_MIR;
+        return SDL_TRUE;
+    }
+
+    return SDL_FALSE;
+}
+
+void
+MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
+                        SDL_VideoDisplay* display,
+                        SDL_bool fullscreen)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    if (IsSurfaceValid(mir_window) < 0)
+        return;
+
+    if (fullscreen) {
+        mir_surface_set_type(mir_window->surface, mir_surface_state_fullscreen);
+    }
+    else {
+        mir_surface_set_type(mir_window->surface, mir_surface_state_restored);
+    }
+}
+
+void
+MIR_MaximizeWindow(_THIS, SDL_Window* window)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    if (IsSurfaceValid(mir_window) < 0)
+        return;
+
+    mir_surface_set_type(mir_window->surface, mir_surface_state_maximized);
+}
+
+void
+MIR_MinimizeWindow(_THIS, SDL_Window* window)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    if (IsSurfaceValid(mir_window) < 0)
+        return;
+
+    mir_surface_set_type(mir_window->surface, mir_surface_state_minimized);
+}
+
+void
+MIR_RestoreWindow(_THIS, SDL_Window * window)
+{
+    MIR_Window* mir_window = window->driverdata;
+
+    if (IsSurfaceValid(mir_window) < 0)
+        return;
+
+    mir_surface_set_type(mir_window->surface, mir_surface_state_restored);
+}

+ 69 - 0
src/video/mir/SDL_mirwindow.h

@@ -0,0 +1,69 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+  Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_mirwindow_h
+#define _SDL_mirwindow_h
+
+#include "../SDL_sysvideo.h"
+#include "SDL_syswm.h"
+
+#include "SDL_mirvideo.h"
+
+typedef struct {
+    SDL_Window* sdl_window;
+    MIR_Data* mir_data;
+
+    MirSurface* surface;
+    EGLSurface egl_surface;
+
+} MIR_Window;
+
+
+extern int
+MIR_CreateWindow(_THIS, SDL_Window* window);
+
+extern void
+MIR_DestroyWindow(_THIS, SDL_Window* window);
+
+extern void
+MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
+                        SDL_VideoDisplay* display,
+                        SDL_bool fullscreen);
+
+extern void
+MIR_MaximizeWindow(_THIS, SDL_Window* window);
+
+extern void
+MIR_MinimizeWindow(_THIS, SDL_Window* window);
+
+extern void
+MIR_RestoreWindow(_THIS, SDL_Window* window);
+
+extern SDL_bool
+MIR_GetWindowWMInfo(_THIS, SDL_Window* window, SDL_SysWMinfo* info);
+
+#endif /* _SDL_mirwindow */