From 19f8c6224fd126d25c58a3088a9c65c3467ca0d0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 2 Feb 2014 23:41:46 -0500 Subject: [PATCH] Added Mir video target (thanks, Brandon!). --- CMakeLists.txt | 2 + cmake/sdlchecks.cmake | 21 ++ configure | 100 +++++++++ configure.in | 37 ++++ include/SDL_config.h.cmake | 1 + include/SDL_config.h.in | 1 + include/SDL_syswm.h | 1 + src/video/SDL_sysvideo.h | 3 + src/video/SDL_video.c | 3 + src/video/mir/SDL_mirevents.c | 246 ++++++++++++++++++++++ src/video/mir/SDL_mirevents.h | 36 ++++ src/video/mir/SDL_mirframebuffer.c | 146 +++++++++++++ src/video/mir/SDL_mirframebuffer.h | 46 +++++ src/video/mir/SDL_mirmouse.c | 145 +++++++++++++ src/video/mir/SDL_mirmouse.h | 37 ++++ src/video/mir/SDL_miropengl.c | 122 +++++++++++ src/video/mir/SDL_miropengl.h | 57 ++++++ src/video/mir/SDL_mirvideo.c | 319 +++++++++++++++++++++++++++++ src/video/mir/SDL_mirvideo.h | 40 ++++ src/video/mir/SDL_mirwindow.c | 216 +++++++++++++++++++ src/video/mir/SDL_mirwindow.h | 69 +++++++ 21 files changed, 1648 insertions(+) create mode 100644 src/video/mir/SDL_mirevents.c create mode 100644 src/video/mir/SDL_mirevents.h create mode 100644 src/video/mir/SDL_mirframebuffer.c create mode 100644 src/video/mir/SDL_mirframebuffer.h create mode 100644 src/video/mir/SDL_mirmouse.c create mode 100644 src/video/mir/SDL_mirmouse.h create mode 100644 src/video/mir/SDL_miropengl.c create mode 100644 src/video/mir/SDL_miropengl.h create mode 100644 src/video/mir/SDL_mirvideo.c create mode 100644 src/video/mir/SDL_mirvideo.h create mode 100644 src/video/mir/SDL_mirwindow.c create mode 100644 src/video/mir/SDL_mirwindow.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f206fb5821487..8aa8fd7eaf702 100644 --- a/CMakeLists.txt +++ b/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() diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index 0dc549eae2c6a..2e48d27bb733d 100644 --- a/cmake/sdlchecks.cmake +++ b/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) diff --git a/configure b/configure index a2e554f03772f..ff1802ead60df 100755 --- a/configure +++ b/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 + #include + #include + +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 diff --git a/configure.in b/configure.in index 69f650aa664f1..d1e9e6632f2a2 100644 --- a/configure.in +++ b/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 + #include + #include + ],[ + ],[ + 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 diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index e21afbde21065..ca731f3f96718 100644 --- a/include/SDL_config.h.cmake +++ b/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@ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 5cfeb75df0252..eb9d805c36a84 100644 --- a/include/SDL_config.h.in +++ b/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 diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index ff4d47e8536e8..c26f141faac45 100644 --- a/include/SDL_syswm.h +++ b/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; /** diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 47240dbea9018..3ff352a1a998a 100644 --- a/src/video/SDL_sysvideo.h +++ b/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 diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 65df4bc997165..338a4cc96da17 100644 --- a/src/video/SDL_video.c +++ b/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 diff --git a/src/video/mir/SDL_mirevents.c b/src/video/mir/SDL_mirevents.c new file mode 100644 index 0000000000000..4ac377a60eddf --- /dev/null +++ b/src/video/mir/SDL_mirevents.c @@ -0,0 +1,246 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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 + +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; + } +} diff --git a/src/video/mir/SDL_mirevents.h b/src/video/mir/SDL_mirevents.h new file mode 100644 index 0000000000000..1be183aa3c9d3 --- /dev/null +++ b/src/video/mir/SDL_mirevents.h @@ -0,0 +1,36 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#include "SDL_config.h" + +#ifndef _SDL_mirevents_h +#define _SDL_mirevents_h + +#include + +extern void +MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context); + +#endif /* _SDL_mirevents_h */ diff --git a/src/video/mir/SDL_mirframebuffer.c b/src/video/mir/SDL_mirframebuffer.c new file mode 100644 index 0000000000000..b0b77df391ff6 --- /dev/null +++ b/src/video/mir/SDL_mirframebuffer.c @@ -0,0 +1,146 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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, ®ion); + + 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) +{ +} diff --git a/src/video/mir/SDL_mirframebuffer.h b/src/video/mir/SDL_mirframebuffer.h new file mode 100644 index 0000000000000..704e4aa2e3f53 --- /dev/null +++ b/src/video/mir/SDL_mirframebuffer.h @@ -0,0 +1,46 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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 */ diff --git a/src/video/mir/SDL_mirmouse.c b/src/video/mir/SDL_mirmouse.c new file mode 100644 index 0000000000000..010e292fde9fc --- /dev/null +++ b/src/video/mir/SDL_mirmouse.c @@ -0,0 +1,145 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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; +} diff --git a/src/video/mir/SDL_mirmouse.h b/src/video/mir/SDL_mirmouse.h new file mode 100644 index 0000000000000..0832f0f051967 --- /dev/null +++ b/src/video/mir/SDL_mirmouse.h @@ -0,0 +1,37 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#include "SDL_config.h" + +#ifndef _SDL_mirmouse_h +#define _SDL_mirmouse_h + +extern void +MIR_InitMouse(); + +extern void +MIR_FiniMouse(); + +#endif /* _SDL_mirmouse_h */ diff --git a/src/video/mir/SDL_miropengl.c b/src/video/mir/SDL_miropengl.c new file mode 100644 index 0000000000000..fcd6568a9a967 --- /dev/null +++ b/src/video/mir/SDL_miropengl.c @@ -0,0 +1,122 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#include "SDL_config.h" +#include "SDL_miropengl.h" + +#include + +#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; +} diff --git a/src/video/mir/SDL_miropengl.h b/src/video/mir/SDL_miropengl.h new file mode 100644 index 0000000000000..dda1d0088a635 --- /dev/null +++ b/src/video/mir/SDL_miropengl.h @@ -0,0 +1,57 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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 */ diff --git a/src/video/mir/SDL_mirvideo.c b/src/video/mir/SDL_mirvideo.c new file mode 100644 index 0000000000000..174d9af13f458 --- /dev/null +++ b/src/video/mir/SDL_mirvideo.c @@ -0,0 +1,319 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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; +} diff --git a/src/video/mir/SDL_mirvideo.h b/src/video/mir/SDL_mirvideo.h new file mode 100644 index 0000000000000..baa0ef0bec674 --- /dev/null +++ b/src/video/mir/SDL_mirvideo.h @@ -0,0 +1,40 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#include "SDL_config.h" + +#ifndef _SDL_mirvideo_h_ +#define _SDL_mirvideo_h_ + +#include +#include + +typedef struct +{ + MirConnection* connection; + +} MIR_Data; + +#endif /* _SDL_mirvideo_h_ */ diff --git a/src/video/mir/SDL_mirwindow.c b/src/video/mir/SDL_mirwindow.c new file mode 100644 index 0000000000000..53f3d8f73b0d5 --- /dev/null +++ b/src/video/mir/SDL_mirwindow.c @@ -0,0 +1,216 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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); +} diff --git a/src/video/mir/SDL_mirwindow.h b/src/video/mir/SDL_mirwindow.h new file mode 100644 index 0000000000000..9377fa045b6a1 --- /dev/null +++ b/src/video/mir/SDL_mirwindow.h @@ -0,0 +1,69 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + 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, +*/ + +#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 */