src/video/mir/SDL_mirvideo.c
changeset 12391 ca6e41ade79a
parent 12390 60f322c5984f
child 12392 046dcbdbaa74
equal deleted inserted replaced
12390:60f322c5984f 12391:ca6e41ade79a
     1 /*
       
     2   Simple DirectMedia Layer
       
     3   Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
       
     4 
       
     5   This software is provided 'as-is', without any express or implied
       
     6   warranty.  In no event will the authors be held liable for any damages
       
     7   arising from the use of this software.
       
     8 
       
     9   Permission is granted to anyone to use this software for any purpose,
       
    10   including commercial applications, and to alter it and redistribute it
       
    11   freely, subject to the following restrictions:
       
    12 
       
    13   1. The origin of this software must not be misrepresented; you must not
       
    14      claim that you wrote the original software. If you use this software
       
    15      in a product, an acknowledgment in the product documentation would be
       
    16      appreciated but is not required.
       
    17   2. Altered source versions must be plainly marked as such, and must not be
       
    18      misrepresented as being the original software.
       
    19   3. This notice may not be removed or altered from any source distribution.
       
    20 */
       
    21 
       
    22 /*
       
    23   Contributed by Brandon Schaefer, <brandon.schaefer@canonical.com>
       
    24 */
       
    25 
       
    26 #include "../../SDL_internal.h"
       
    27 
       
    28 #if SDL_VIDEO_DRIVER_MIR
       
    29 
       
    30 #include "SDL_assert.h"
       
    31 #include "SDL_log.h"
       
    32 
       
    33 #include "SDL_mirwindow.h"
       
    34 #include "SDL_video.h"
       
    35 
       
    36 #include "SDL_mirframebuffer.h"
       
    37 #include "SDL_mirmouse.h"
       
    38 #include "SDL_miropengl.h"
       
    39 #include "SDL_mirvideo.h"
       
    40 #include "SDL_mirvulkan.h"
       
    41 
       
    42 #include "SDL_mirdyn.h"
       
    43 
       
    44 #define MIR_DRIVER_NAME "mir"
       
    45 
       
    46 static const Uint32 mir_pixel_format_to_sdl_format[] = {
       
    47     SDL_PIXELFORMAT_UNKNOWN,  /* mir_pixel_format_invalid   */
       
    48     SDL_PIXELFORMAT_ABGR8888, /* mir_pixel_format_abgr_8888 */
       
    49     SDL_PIXELFORMAT_BGR888,   /* mir_pixel_format_xbgr_8888 */
       
    50     SDL_PIXELFORMAT_ARGB8888, /* mir_pixel_format_argb_8888 */
       
    51     SDL_PIXELFORMAT_RGB888,   /* mir_pixel_format_xrgb_8888 */
       
    52     SDL_PIXELFORMAT_BGR24,    /* mir_pixel_format_bgr_888   */
       
    53     SDL_PIXELFORMAT_RGB24,    /* mir_pixel_format_rgb_888   */
       
    54     SDL_PIXELFORMAT_RGB565,   /* mir_pixel_format_rgb_565   */
       
    55     SDL_PIXELFORMAT_RGBA5551, /* mir_pixel_format_rgba_5551 */
       
    56     SDL_PIXELFORMAT_RGBA4444  /* mir_pixel_format_rgba_4444 */
       
    57 };
       
    58 
       
    59 Uint32
       
    60 MIR_GetSDLPixelFormat(MirPixelFormat format)
       
    61 {
       
    62     return mir_pixel_format_to_sdl_format[format];
       
    63 }
       
    64 
       
    65 static int
       
    66 MIR_VideoInit(_THIS);
       
    67 
       
    68 static void
       
    69 MIR_VideoQuit(_THIS);
       
    70 
       
    71 static int
       
    72 MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect);
       
    73 
       
    74 static void
       
    75 MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* sdl_display);
       
    76 
       
    77 static int
       
    78 MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* sdl_display, SDL_DisplayMode* mode);
       
    79 
       
    80 static SDL_WindowShaper*
       
    81 MIR_CreateShaper(SDL_Window* window)
       
    82 {
       
    83     /* FIXME Im not sure if mir support this atm, will have to come back to this */
       
    84     return NULL;
       
    85 }
       
    86 
       
    87 static int
       
    88 MIR_SetWindowShape(SDL_WindowShaper* shaper, SDL_Surface* shape, SDL_WindowShapeMode* shape_mode)
       
    89 {
       
    90     return SDL_Unsupported();
       
    91 }
       
    92 
       
    93 static int
       
    94 MIR_ResizeWindowShape(SDL_Window* window)
       
    95 {
       
    96     return SDL_Unsupported();
       
    97 }
       
    98 
       
    99 static int
       
   100 MIR_Available()
       
   101 {
       
   102     int available = 0;
       
   103 
       
   104     if (SDL_MIR_LoadSymbols()) {
       
   105 
       
   106         /* Lets ensure we can connect to the mir server */
       
   107         MirConnection* connection = MIR_mir_connect_sync(NULL, SDL_FUNCTION);
       
   108 
       
   109         if (!MIR_mir_connection_is_valid(connection)) {
       
   110             SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Unable to connect to the mir server %s",
       
   111                 MIR_mir_connection_get_error_message(connection));
       
   112 
       
   113             return available;
       
   114         }
       
   115 
       
   116         MIR_mir_connection_release(connection);
       
   117 
       
   118         available = 1;
       
   119         SDL_MIR_UnloadSymbols();
       
   120     }
       
   121 
       
   122     return available;
       
   123 }
       
   124 
       
   125 static void
       
   126 MIR_DeleteDevice(SDL_VideoDevice* device)
       
   127 {
       
   128     SDL_free(device);
       
   129     SDL_MIR_UnloadSymbols();
       
   130 }
       
   131 
       
   132 static void
       
   133 MIR_PumpEvents(_THIS)
       
   134 {
       
   135 }
       
   136 
       
   137 static SDL_VideoDevice*
       
   138 MIR_CreateDevice(int device_index)
       
   139 {
       
   140     MIR_Data* mir_data;
       
   141     SDL_VideoDevice* device = NULL;
       
   142 
       
   143     if (!SDL_MIR_LoadSymbols()) {
       
   144         return NULL;
       
   145     }
       
   146 
       
   147     device = SDL_calloc(1, sizeof(SDL_VideoDevice));
       
   148     if (!device) {
       
   149         SDL_MIR_UnloadSymbols();
       
   150         SDL_OutOfMemory();
       
   151         return NULL;
       
   152     }
       
   153 
       
   154     mir_data = SDL_calloc(1, sizeof(MIR_Data));
       
   155     if (!mir_data) {
       
   156         SDL_free(device);
       
   157         SDL_MIR_UnloadSymbols();
       
   158         SDL_OutOfMemory();
       
   159         return NULL;
       
   160     }
       
   161 
       
   162     device->driverdata = mir_data;
       
   163 
       
   164     /* mirvideo */
       
   165     device->VideoInit        = MIR_VideoInit;
       
   166     device->VideoQuit        = MIR_VideoQuit;
       
   167     device->GetDisplayBounds = MIR_GetDisplayBounds;
       
   168     device->GetDisplayModes  = MIR_GetDisplayModes;
       
   169     device->SetDisplayMode   = MIR_SetDisplayMode;
       
   170     device->free             = MIR_DeleteDevice;
       
   171 
       
   172     /* miropengles */
       
   173     device->GL_SwapWindow      = MIR_GL_SwapWindow;
       
   174     device->GL_MakeCurrent     = MIR_GL_MakeCurrent;
       
   175     device->GL_CreateContext   = MIR_GL_CreateContext;
       
   176     device->GL_DeleteContext   = MIR_GL_DeleteContext;
       
   177     device->GL_LoadLibrary     = MIR_GL_LoadLibrary;
       
   178     device->GL_UnloadLibrary   = MIR_GL_UnloadLibrary;
       
   179     device->GL_GetSwapInterval = MIR_GL_GetSwapInterval;
       
   180     device->GL_SetSwapInterval = MIR_GL_SetSwapInterval;
       
   181     device->GL_GetProcAddress  = MIR_GL_GetProcAddress;
       
   182 
       
   183     /* mirwindow */
       
   184     device->CreateSDLWindow         = MIR_CreateWindow;
       
   185     device->DestroyWindow        = MIR_DestroyWindow;
       
   186     device->GetWindowWMInfo      = MIR_GetWindowWMInfo;
       
   187     device->SetWindowFullscreen  = MIR_SetWindowFullscreen;
       
   188     device->MaximizeWindow       = MIR_MaximizeWindow;
       
   189     device->MinimizeWindow       = MIR_MinimizeWindow;
       
   190     device->RestoreWindow        = MIR_RestoreWindow;
       
   191     device->ShowWindow           = MIR_RestoreWindow;
       
   192     device->HideWindow           = MIR_HideWindow;
       
   193     device->SetWindowSize        = MIR_SetWindowSize;
       
   194     device->SetWindowMinimumSize = MIR_SetWindowMinimumSize;
       
   195     device->SetWindowMaximumSize = MIR_SetWindowMaximumSize;
       
   196     device->SetWindowTitle       = MIR_SetWindowTitle;
       
   197     device->SetWindowGrab        = MIR_SetWindowGrab;
       
   198     device->SetWindowGammaRamp   = MIR_SetWindowGammaRamp;
       
   199     device->GetWindowGammaRamp   = MIR_GetWindowGammaRamp;
       
   200 
       
   201     device->CreateSDLWindowFrom     = NULL;
       
   202     device->SetWindowIcon        = NULL;
       
   203     device->RaiseWindow          = NULL;
       
   204     device->SetWindowBordered    = NULL;
       
   205     device->SetWindowResizable   = NULL;
       
   206     device->OnWindowEnter        = NULL;
       
   207     device->SetWindowPosition    = NULL;
       
   208 
       
   209     /* mirframebuffer */
       
   210     device->CreateWindowFramebuffer  = MIR_CreateWindowFramebuffer;
       
   211     device->UpdateWindowFramebuffer  = MIR_UpdateWindowFramebuffer;
       
   212     device->DestroyWindowFramebuffer = MIR_DestroyWindowFramebuffer;
       
   213 
       
   214     device->shape_driver.CreateShaper      = MIR_CreateShaper;
       
   215     device->shape_driver.SetWindowShape    = MIR_SetWindowShape;
       
   216     device->shape_driver.ResizeWindowShape = MIR_ResizeWindowShape;
       
   217 
       
   218     device->PumpEvents = MIR_PumpEvents;
       
   219 
       
   220     device->SuspendScreenSaver = NULL;
       
   221 
       
   222     device->StartTextInput   = NULL;
       
   223     device->StopTextInput    = NULL;
       
   224     device->SetTextInputRect = NULL;
       
   225 
       
   226     device->HasScreenKeyboardSupport = NULL;
       
   227     device->ShowScreenKeyboard       = NULL;
       
   228     device->HideScreenKeyboard       = NULL;
       
   229     device->IsScreenKeyboardShown    = NULL;
       
   230 
       
   231     device->SetClipboardText = NULL;
       
   232     device->GetClipboardText = NULL;
       
   233     device->HasClipboardText = NULL;
       
   234 
       
   235     device->ShowMessageBox = NULL;
       
   236 
       
   237 #if SDL_VIDEO_VULKAN
       
   238     device->Vulkan_LoadLibrary = MIR_Vulkan_LoadLibrary;
       
   239     device->Vulkan_UnloadLibrary = MIR_Vulkan_UnloadLibrary;
       
   240     device->Vulkan_GetInstanceExtensions = MIR_Vulkan_GetInstanceExtensions;
       
   241     device->Vulkan_CreateSurface = MIR_Vulkan_CreateSurface;
       
   242 #endif
       
   243 
       
   244     return device;
       
   245 }
       
   246 
       
   247 VideoBootStrap MIR_bootstrap = {
       
   248     MIR_DRIVER_NAME, "SDL Mir video driver",
       
   249     MIR_Available, MIR_CreateDevice
       
   250 };
       
   251 
       
   252 static SDL_DisplayMode
       
   253 MIR_ConvertModeToSDLMode(MirOutputMode const* mode, MirPixelFormat format)
       
   254 {
       
   255     SDL_DisplayMode sdl_mode  = {
       
   256         .format = MIR_GetSDLPixelFormat(format),
       
   257         .w      = MIR_mir_output_mode_get_width(mode),
       
   258         .h      = MIR_mir_output_mode_get_height(mode),
       
   259         .refresh_rate = MIR_mir_output_mode_get_refresh_rate(mode),
       
   260         .driverdata   = NULL
       
   261     };
       
   262 
       
   263     return sdl_mode;
       
   264 }
       
   265 
       
   266 static void
       
   267 MIR_AddModeToDisplay(SDL_VideoDisplay* display, MirOutputMode const* mode, MirPixelFormat format)
       
   268 {
       
   269     SDL_DisplayMode sdl_mode = MIR_ConvertModeToSDLMode(mode, format);
       
   270     SDL_AddDisplayMode(display, &sdl_mode);
       
   271 }
       
   272 
       
   273 static void
       
   274 MIR_InitDisplayFromOutput(_THIS, MirOutput* output)
       
   275 {
       
   276     SDL_VideoDisplay display;
       
   277     int m;
       
   278 
       
   279     MirPixelFormat format = MIR_mir_output_get_current_pixel_format(output);
       
   280     int num_modes         = MIR_mir_output_get_num_modes(output);
       
   281     SDL_DisplayMode current_mode = MIR_ConvertModeToSDLMode(MIR_mir_output_get_current_mode(output), format);
       
   282 
       
   283     SDL_zero(display);
       
   284 
       
   285     // Unfortunate cast, but SDL_AddVideoDisplay will strdup this pointer so its read-only in this case.
       
   286     display.name = (char*)MIR_mir_output_type_name(MIR_mir_output_get_type(output));
       
   287 
       
   288     for (m = 0; m < num_modes; m++) {
       
   289         MirOutputMode const* mode = MIR_mir_output_get_mode(output, m);
       
   290         MIR_AddModeToDisplay(&display, mode, format);
       
   291     }
       
   292 
       
   293     display.desktop_mode = current_mode;
       
   294     display.current_mode = current_mode;
       
   295 
       
   296     display.driverdata = output;
       
   297     SDL_AddVideoDisplay(&display);
       
   298 }
       
   299 
       
   300 static void
       
   301 MIR_InitDisplays(_THIS)
       
   302 {
       
   303     MIR_Data* mir_data = _this->driverdata;
       
   304     int num_outputs    = MIR_mir_display_config_get_num_outputs(mir_data->display_config);
       
   305     int d;
       
   306 
       
   307     for (d = 0; d < num_outputs; d++) {
       
   308         MirOutput* output = MIR_mir_display_config_get_mutable_output(mir_data->display_config, d);
       
   309         SDL_bool enabled  = MIR_mir_output_is_enabled(output);
       
   310         MirOutputConnectionState state = MIR_mir_output_get_connection_state(output);
       
   311 
       
   312         if (enabled && state == mir_output_connection_state_connected) {
       
   313             MIR_InitDisplayFromOutput(_this, output);
       
   314         }
       
   315     }
       
   316 }
       
   317 
       
   318 static int
       
   319 MIR_VideoInit(_THIS)
       
   320 {
       
   321     MIR_Data* mir_data = _this->driverdata;
       
   322 
       
   323     mir_data->connection     = MIR_mir_connect_sync(NULL, SDL_FUNCTION);
       
   324     mir_data->current_window = NULL;
       
   325     mir_data->software       = SDL_FALSE;
       
   326     mir_data->pixel_format   = mir_pixel_format_invalid;
       
   327 
       
   328     if (!MIR_mir_connection_is_valid(mir_data->connection)) {
       
   329         return SDL_SetError("Failed to connect to the mir server: %s",
       
   330             MIR_mir_connection_get_error_message(mir_data->connection));
       
   331     }
       
   332 
       
   333     mir_data->display_config = MIR_mir_connection_create_display_configuration(mir_data->connection);
       
   334 
       
   335     MIR_InitDisplays(_this);
       
   336     MIR_InitMouse();
       
   337 
       
   338     return 0;
       
   339 }
       
   340 
       
   341 static void
       
   342 MIR_CleanUpDisplayConfig(_THIS)
       
   343 {
       
   344     MIR_Data* mir_data = _this->driverdata;
       
   345     int i;
       
   346 
       
   347     // SDL_VideoQuit frees the display driverdata, we own it not them
       
   348     for (i = 0; i < _this->num_displays; ++i) {
       
   349         _this->displays[i].driverdata = NULL;
       
   350     }
       
   351 
       
   352     MIR_mir_display_config_release(mir_data->display_config);
       
   353 }
       
   354 
       
   355 static void
       
   356 MIR_VideoQuit(_THIS)
       
   357 {
       
   358     MIR_Data* mir_data = _this->driverdata;
       
   359 
       
   360     MIR_CleanUpDisplayConfig(_this);
       
   361 
       
   362     MIR_FiniMouse();
       
   363 
       
   364     MIR_GL_DeleteContext(_this, NULL);
       
   365     MIR_GL_UnloadLibrary(_this);
       
   366 
       
   367     MIR_mir_connection_release(mir_data->connection);
       
   368 
       
   369     SDL_free(mir_data);
       
   370     _this->driverdata = NULL;
       
   371 }
       
   372 
       
   373 static int
       
   374 MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect)
       
   375 {
       
   376     MirOutput const* output = display->driverdata;
       
   377 
       
   378     rect->x = MIR_mir_output_get_position_x(output);
       
   379     rect->y = MIR_mir_output_get_position_y(output);
       
   380     rect->w = display->current_mode.w;
       
   381     rect->h = display->current_mode.h;
       
   382 
       
   383     return 0;
       
   384 }
       
   385 
       
   386 static void
       
   387 MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* display)
       
   388 {
       
   389 }
       
   390 
       
   391 static int
       
   392 MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* display, SDL_DisplayMode* mode)
       
   393 {
       
   394     int m;
       
   395     MirOutput* output = display->driverdata;
       
   396     int num_modes     = MIR_mir_output_get_num_modes(output);
       
   397     Uint32 sdl_format = MIR_GetSDLPixelFormat(
       
   398                             MIR_mir_output_get_current_pixel_format(output));
       
   399 
       
   400     for (m = 0; m < num_modes; m++) {
       
   401         MirOutputMode const* mir_mode = MIR_mir_output_get_mode(output, m);
       
   402         int width  = MIR_mir_output_mode_get_width(mir_mode);
       
   403         int height = MIR_mir_output_mode_get_height(mir_mode);
       
   404         double refresh_rate = MIR_mir_output_mode_get_refresh_rate(mir_mode);
       
   405 
       
   406         if (mode->format == sdl_format &&
       
   407             mode->w      == width &&
       
   408             mode->h      == height &&
       
   409             mode->refresh_rate == refresh_rate) {
       
   410 
       
   411             // FIXME Currently wont actually *set* anything. Need to wait for applying display changes
       
   412             MIR_mir_output_set_current_mode(output, mir_mode);
       
   413             return 0;
       
   414         }
       
   415     }
       
   416 
       
   417     return -1;
       
   418 }
       
   419 
       
   420 #endif /* SDL_VIDEO_DRIVER_MIR */
       
   421 
       
   422 /* vi: set ts=4 sw=4 expandtab: */
       
   423