| /* |
| Simple DirectMedia Layer |
| Copyright (C) 1997-2016 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_internal.h" |
| |
| #if SDL_VIDEO_DRIVER_MIR |
| |
| #include "SDL_mirwindow.h" |
| #include "SDL_video.h" |
| |
| #include "SDL_mirframebuffer.h" |
| #include "SDL_mirmouse.h" |
| #include "SDL_miropengl.h" |
| #include "SDL_mirvideo.h" |
| |
| #include "SDL_mirdyn.h" |
| |
| #define MIR_DRIVER_NAME "mir" |
| |
| 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 */ |
| SDL_PIXELFORMAT_RGB24, /* mir_pixel_format_rgb_888 */ |
| SDL_PIXELFORMAT_RGB565, /* mir_pixel_format_rgb_565 */ |
| SDL_PIXELFORMAT_RGBA5551, /* mir_pixel_format_rgba_5551 */ |
| SDL_PIXELFORMAT_RGBA4444 /* mir_pixel_format_rgba_4444 */ |
| }; |
| |
| Uint32 |
| MIR_GetSDLPixelFormat(MirPixelFormat format) |
| { |
| return mir_pixel_format_to_sdl_format[format]; |
| } |
| |
| 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() |
| { |
| int available = 0; |
| |
| if (SDL_MIR_LoadSymbols()) { |
| /* !!! FIXME: try to make a MirConnection here. */ |
| available = 1; |
| SDL_MIR_UnloadSymbols(); |
| } |
| |
| return available; |
| } |
| |
| static void |
| MIR_DeleteDevice(SDL_VideoDevice* device) |
| { |
| SDL_free(device); |
| SDL_MIR_UnloadSymbols(); |
| } |
| |
| static void |
| MIR_PumpEvents(_THIS) |
| { |
| } |
| |
| static SDL_VideoDevice* |
| MIR_CreateDevice(int device_index) |
| { |
| MIR_Data* mir_data; |
| SDL_VideoDevice* device = NULL; |
| |
| if (!SDL_MIR_LoadSymbols()) { |
| return NULL; |
| } |
| |
| device = SDL_calloc(1, sizeof(SDL_VideoDevice)); |
| if (!device) { |
| SDL_MIR_UnloadSymbols(); |
| SDL_OutOfMemory(); |
| return NULL; |
| } |
| |
| mir_data = SDL_calloc(1, sizeof(MIR_Data)); |
| if (!mir_data) { |
| SDL_free(device); |
| SDL_MIR_UnloadSymbols(); |
| SDL_OutOfMemory(); |
| 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->ShowWindow = MIR_RestoreWindow; |
| device->HideWindow = MIR_HideWindow; |
| device->SetWindowSize = MIR_SetWindowSize; |
| device->SetWindowMinimumSize = MIR_SetWindowMinimumSize; |
| device->SetWindowMaximumSize = MIR_SetWindowMaximumSize; |
| device->SetWindowTitle = MIR_SetWindowTitle; |
| device->SetWindowGrab = MIR_SetWindowGrab; |
| device->SetWindowGammaRamp = MIR_SetWindowGammaRamp; |
| device->GetWindowGammaRamp = MIR_GetWindowGammaRamp; |
| |
| device->CreateWindowFrom = NULL; |
| device->SetWindowIcon = NULL; |
| device->RaiseWindow = NULL; |
| device->SetWindowBordered = NULL; |
| device->SetWindowResizable = NULL; |
| device->OnWindowEnter = NULL; |
| device->SetWindowPosition = 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 SDL_DisplayMode |
| MIR_ConvertModeToSDLMode(MirOutputMode const* mode, MirPixelFormat format) |
| { |
| SDL_DisplayMode sdl_mode = { |
| .format = MIR_GetSDLPixelFormat(format), |
| .w = MIR_mir_output_mode_get_width(mode), |
| .h = MIR_mir_output_mode_get_height(mode), |
| .refresh_rate = MIR_mir_output_mode_get_refresh_rate(mode), |
| .driverdata = NULL |
| }; |
| |
| return sdl_mode; |
| } |
| |
| static void |
| MIR_AddModeToDisplay(SDL_VideoDisplay* display, MirOutputMode const* mode, MirPixelFormat format) |
| { |
| SDL_DisplayMode sdl_mode = MIR_ConvertModeToSDLMode(mode, format); |
| SDL_AddDisplayMode(display, &sdl_mode); |
| } |
| |
| static void |
| MIR_InitDisplayFromOutput(_THIS, MirOutput* output) |
| { |
| SDL_VideoDisplay display; |
| int m; |
| |
| MirPixelFormat format = MIR_mir_output_get_current_pixel_format(output); |
| int num_modes = MIR_mir_output_get_num_modes(output); |
| SDL_DisplayMode current_mode = MIR_ConvertModeToSDLMode(mir_output_get_current_mode(output), format); |
| |
| SDL_zero(display); |
| |
| // Unfortunate cast, but SDL_AddVideoDisplay will strdup this pointer so its read-only in this case. |
| display.name = (char*)MIR_mir_output_type_name(MIR_mir_output_get_type(output)); |
| |
| for (m = 0; m < num_modes; m++) { |
| MirOutputMode const* mode = MIR_mir_output_get_mode(output, m); |
| MIR_AddModeToDisplay(&display, mode, format); |
| } |
| |
| display.desktop_mode = current_mode; |
| display.current_mode = current_mode; |
| |
| display.driverdata = output; |
| SDL_AddVideoDisplay(&display); |
| } |
| |
| static void |
| MIR_InitDisplays(_THIS) |
| { |
| MIR_Data* mir_data = _this->driverdata; |
| int num_outputs = MIR_mir_display_config_get_num_outputs(mir_data->display_config); |
| int d; |
| |
| for (d = 0; d < num_outputs; d++) { |
| MirOutput* output = MIR_mir_display_config_get_mutable_output(mir_data->display_config, d); |
| SDL_bool enabled = MIR_mir_output_is_enabled(output); |
| MirOutputConnectionState state = MIR_mir_output_get_connection_state(output); |
| |
| if (enabled && state == mir_output_connection_state_connected) { |
| MIR_InitDisplayFromOutput(_this, output); |
| } |
| } |
| } |
| |
| static int |
| MIR_VideoInit(_THIS) |
| { |
| MIR_Data* mir_data = _this->driverdata; |
| |
| mir_data->connection = MIR_mir_connect_sync(NULL, __PRETTY_FUNCTION__); |
| mir_data->current_window = NULL; |
| mir_data->software = SDL_FALSE; |
| mir_data->pixel_format = mir_pixel_format_invalid; |
| |
| if (!MIR_mir_connection_is_valid(mir_data->connection)) { |
| return SDL_SetError("Failed to connect to the mir server: %s", |
| MIR_mir_connection_get_error_message(mir_data->connection)); |
| } |
| |
| mir_data->display_config = MIR_mir_connection_create_display_configuration(mir_data->connection); |
| |
| MIR_InitDisplays(_this); |
| MIR_InitMouse(); |
| |
| return 0; |
| } |
| |
| static void |
| MIR_CleanUpDisplayConfig(_THIS) |
| { |
| MIR_Data* mir_data = _this->driverdata; |
| int i; |
| |
| // SDL_VideoQuit frees the display driverdata, we own it not them |
| for (i = 0; i < _this->num_displays; ++i) { |
| _this->displays[i].driverdata = NULL; |
| } |
| |
| MIR_mir_display_config_release(mir_data->display_config); |
| } |
| |
| static void |
| MIR_VideoQuit(_THIS) |
| { |
| MIR_Data* mir_data = _this->driverdata; |
| |
| MIR_CleanUpDisplayConfig(_this); |
| |
| MIR_FiniMouse(); |
| |
| MIR_GL_DeleteContext(_this, NULL); |
| MIR_GL_UnloadLibrary(_this); |
| |
| MIR_mir_connection_release(mir_data->connection); |
| |
| SDL_free(mir_data); |
| _this->driverdata = NULL; |
| } |
| |
| static int |
| MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect) |
| { |
| MirOutput const* output = display->driverdata; |
| |
| rect->x = MIR_mir_output_get_position_x(output); |
| rect->y = MIR_mir_output_get_position_y(output); |
| rect->w = display->current_mode.w; |
| rect->h = display->current_mode.h; |
| |
| return 0; |
| } |
| |
| static void |
| MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* display) |
| { |
| } |
| |
| static int |
| MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* display, SDL_DisplayMode* mode) |
| { |
| int m; |
| MirOutput* output = display->driverdata; |
| int num_modes = MIR_mir_output_get_num_modes(output); |
| Uint32 sdl_format = MIR_GetSDLPixelFormat( |
| MIR_mir_output_get_current_pixel_format(output)); |
| |
| for (m = 0; m < num_modes; m++) { |
| MirOutputMode const* mir_mode = MIR_mir_output_get_mode(output, m); |
| int width = MIR_mir_output_mode_get_width(mir_mode); |
| int height = MIR_mir_output_mode_get_height(mir_mode); |
| double refresh_rate = MIR_mir_output_mode_get_refresh_rate(mir_mode); |
| |
| if (mode->format == sdl_format && |
| mode->w == width && |
| mode->h == height && |
| mode->refresh_rate == refresh_rate) { |
| |
| // FIXME Currently wont actually *set* anything. Need to wait for applying display changes |
| MIR_mir_output_set_current_mode(output, mir_mode); |
| return 0; |
| } |
| } |
| |
| return -1; |
| } |
| |
| #endif /* SDL_VIDEO_DRIVER_MIR */ |
| |
| /* vi: set ts=4 sw=4 expandtab: */ |
| |