src/video/mir/SDL_mirwindow.c
author Brandon Schaefer <brandon.schaefer@canonical.com>
Wed, 08 Jun 2016 08:01:21 -0700
changeset 10181 b82c0f22d22a
parent 10095 0897c3accd52
child 10299 5a45e29a6ea7
permissions -rw-r--r--
MIR: Add better error handling for a failed connection
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2016 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_egl_c.h"
    31 #include "../SDL_sysvideo.h"
    32 
    33 #include "SDL_mirevents.h"
    34 #include "SDL_mirwindow.h"
    35 
    36 #include "SDL_mirdyn.h"
    37 
    38 int
    39 IsSurfaceValid(MIR_Window* mir_window)
    40 {
    41     if (!MIR_mir_surface_is_valid(mir_window->surface)) {
    42         const char* error = MIR_mir_surface_get_error_message(mir_window->surface);
    43         return SDL_SetError("Failed to created a mir surface: %s", error);
    44     }
    45 
    46     return 0;
    47 }
    48 
    49 MirPixelFormat
    50 FindValidPixelFormat(MIR_Data* mir_data)
    51 {
    52     unsigned int pf_size = 32;
    53     unsigned int valid_formats;
    54     unsigned int f;
    55 
    56     MirPixelFormat formats[pf_size];
    57     MIR_mir_connection_get_available_surface_formats(mir_data->connection, formats,
    58                                                      pf_size, &valid_formats);
    59 
    60     for (f = 0; f < valid_formats; f++) {
    61         MirPixelFormat cur_pf = formats[f];
    62 
    63         if (cur_pf == mir_pixel_format_abgr_8888 ||
    64             cur_pf == mir_pixel_format_xbgr_8888 ||
    65             cur_pf == mir_pixel_format_argb_8888 ||
    66             cur_pf == mir_pixel_format_xrgb_8888) {
    67 
    68             return cur_pf;
    69         }
    70     }
    71 
    72     return mir_pixel_format_invalid;
    73 }
    74 
    75 int
    76 MIR_CreateWindow(_THIS, SDL_Window* window)
    77 {
    78     MIR_Window* mir_window;
    79     MIR_Data* mir_data;
    80     MirPixelFormat pixel_format;
    81     MirBufferUsage buffer_usage;
    82 
    83     MirSurfaceSpec* spec;
    84 
    85     mir_window = SDL_calloc(1, sizeof(MIR_Window));
    86     if (!mir_window)
    87         return SDL_OutOfMemory();
    88 
    89     mir_data = _this->driverdata;
    90     window->driverdata = mir_window;
    91 
    92     if (window->x == SDL_WINDOWPOS_UNDEFINED)
    93         window->x = 0;
    94 
    95     if (window->y == SDL_WINDOWPOS_UNDEFINED)
    96         window->y = 0;
    97 
    98     mir_window->mir_data = mir_data;
    99     mir_window->sdl_window = window;
   100 
   101     if (window->flags & SDL_WINDOW_OPENGL) {
   102         pixel_format = MIR_mir_connection_get_egl_pixel_format(mir_data->connection,
   103                                                                _this->egl_data->egl_display,
   104                                                                _this->egl_data->egl_config);
   105     }
   106     else {
   107         pixel_format = FindValidPixelFormat(mir_data);
   108     }
   109 
   110     mir_data->pixel_format = pixel_format;
   111     if (pixel_format == mir_pixel_format_invalid) {
   112         return SDL_SetError("Failed to find a valid pixel format.");
   113     }
   114 
   115     buffer_usage = mir_buffer_usage_hardware;
   116     if (mir_data->software)
   117         buffer_usage = mir_buffer_usage_software;
   118 
   119     spec = MIR_mir_connection_create_spec_for_normal_surface(mir_data->connection,
   120                                                              window->w,
   121                                                              window->h,
   122                                                              pixel_format);
   123 
   124     MIR_mir_surface_spec_set_buffer_usage(spec, buffer_usage);
   125     MIR_mir_surface_spec_set_name(spec, "Mir surface");
   126 
   127     mir_window->surface = MIR_mir_surface_create_sync(spec);
   128     MIR_mir_surface_set_event_handler(mir_window->surface, MIR_HandleEvent, window);
   129 
   130     MIR_mir_surface_spec_release(spec);
   131 
   132     if (!MIR_mir_surface_is_valid(mir_window->surface)) {
   133         return SDL_SetError("Failed to created a mir surface: %s",
   134             MIR_mir_surface_get_error_message(mir_window->surface));
   135     }
   136 
   137     if (window->flags & SDL_WINDOW_OPENGL) {
   138         EGLNativeWindowType egl_native_window =
   139                         (EGLNativeWindowType)MIR_mir_buffer_stream_get_egl_native_window(
   140                                                        MIR_mir_surface_get_buffer_stream(mir_window->surface));
   141 
   142         mir_window->egl_surface = SDL_EGL_CreateSurface(_this, egl_native_window);
   143 
   144         if (mir_window->egl_surface == EGL_NO_SURFACE) {
   145             return SDL_SetError("Failed to created a window surface %p",
   146                                 _this->egl_data->egl_display);
   147         }
   148     }
   149     else {
   150         mir_window->egl_surface = EGL_NO_SURFACE;
   151     }
   152 
   153     mir_data->current_window = mir_window;
   154 
   155     return 0;
   156 }
   157 
   158 void
   159 MIR_DestroyWindow(_THIS, SDL_Window* window)
   160 {
   161     MIR_Data* mir_data     = _this->driverdata;
   162     MIR_Window* mir_window = window->driverdata;
   163 
   164     if (mir_data) {
   165         SDL_EGL_DestroySurface(_this, mir_window->egl_surface);
   166         MIR_mir_surface_release_sync(mir_window->surface);
   167 
   168         mir_data->current_window = NULL;
   169 
   170         SDL_free(mir_window);
   171     }
   172     window->driverdata = NULL;
   173 }
   174 
   175 SDL_bool
   176 MIR_GetWindowWMInfo(_THIS, SDL_Window* window, SDL_SysWMinfo* info)
   177 {
   178     if (info->version.major == SDL_MAJOR_VERSION &&
   179         info->version.minor == SDL_MINOR_VERSION) {
   180         MIR_Window* mir_window = window->driverdata;
   181 
   182         info->subsystem = SDL_SYSWM_MIR;
   183         info->info.mir.connection = mir_window->mir_data->connection;
   184         info->info.mir.surface = mir_window->surface;
   185 
   186         return SDL_TRUE;
   187     }
   188 
   189     return SDL_FALSE;
   190 }
   191 
   192 void
   193 MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
   194                         SDL_VideoDisplay* display,
   195                         SDL_bool fullscreen)
   196 {
   197     MIR_Data*   mir_data   = _this->driverdata;
   198     MIR_Window* mir_window = window->driverdata;
   199     MirSurfaceSpec* spec;
   200     MirSurfaceState state;
   201 
   202     if (IsSurfaceValid(mir_window) < 0)
   203         return;
   204 
   205     if (fullscreen) {
   206         state = mir_surface_state_fullscreen;
   207     } else {
   208         state = mir_surface_state_restored;
   209     }
   210 
   211     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   212     MIR_mir_surface_spec_set_state(spec, state);
   213 
   214     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   215     MIR_mir_surface_spec_release(spec);
   216 }
   217 
   218 void
   219 MIR_MaximizeWindow(_THIS, SDL_Window* window)
   220 {
   221     MIR_Data*   mir_data   = _this->driverdata;
   222     MIR_Window* mir_window = window->driverdata;
   223     MirSurfaceSpec* spec;
   224 
   225     if (IsSurfaceValid(mir_window) < 0)
   226         return;
   227 
   228     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   229     MIR_mir_surface_spec_set_state(spec, mir_surface_state_maximized);
   230 
   231     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   232     MIR_mir_surface_spec_release(spec);
   233 }
   234 
   235 void
   236 MIR_MinimizeWindow(_THIS, SDL_Window* window)
   237 {
   238     MIR_Data*   mir_data   = _this->driverdata;
   239     MIR_Window* mir_window = window->driverdata;
   240     MirSurfaceSpec* spec;
   241 
   242     if (IsSurfaceValid(mir_window) < 0)
   243         return;
   244 
   245     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   246     MIR_mir_surface_spec_set_state(spec, mir_surface_state_minimized);
   247 
   248     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   249     MIR_mir_surface_spec_release(spec);
   250 }
   251 
   252 void
   253 MIR_RestoreWindow(_THIS, SDL_Window * window)
   254 {
   255     MIR_Data*   mir_data   = _this->driverdata;
   256     MIR_Window* mir_window = window->driverdata;
   257     MirSurfaceSpec* spec;
   258 
   259     if (IsSurfaceValid(mir_window) < 0)
   260         return;
   261 
   262     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   263     MIR_mir_surface_spec_set_state(spec, mir_surface_state_restored);
   264 
   265     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   266     MIR_mir_surface_spec_release(spec);
   267 }
   268 
   269 void
   270 MIR_HideWindow(_THIS, SDL_Window* window)
   271 {
   272     MIR_Data*   mir_data   = _this->driverdata;
   273     MIR_Window* mir_window = window->driverdata;
   274     MirSurfaceSpec* spec;
   275 
   276     if (IsSurfaceValid(mir_window) < 0)
   277         return;
   278 
   279     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   280     MIR_mir_surface_spec_set_state(spec, mir_surface_state_hidden);
   281 
   282     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   283     MIR_mir_surface_spec_release(spec);
   284 }
   285 
   286 void
   287 MIR_SetWindowSize(_THIS, SDL_Window* window)
   288 {
   289     MIR_Data*   mir_data   = _this->driverdata;
   290     MIR_Window* mir_window = window->driverdata;
   291     MirSurfaceSpec* spec;
   292 
   293     if (IsSurfaceValid(mir_window) < 0)
   294         return;
   295 
   296     /* You cannot set the x/y of a mir window! So only update w/h */
   297     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   298     MIR_mir_surface_spec_set_width (spec, window->w);
   299     MIR_mir_surface_spec_set_height(spec, window->h);
   300 
   301     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   302     MIR_mir_surface_spec_release(spec);
   303 }
   304 
   305 void
   306 MIR_SetWindowMinimumSize(_THIS, SDL_Window* window)
   307 {
   308     MIR_Data*   mir_data   = _this->driverdata;
   309     MIR_Window* mir_window = window->driverdata;
   310     MirSurfaceSpec* spec;
   311 
   312     if (IsSurfaceValid(mir_window) < 0)
   313         return;
   314 
   315     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   316     MIR_mir_surface_spec_set_min_width (spec, window->min_w);
   317     MIR_mir_surface_spec_set_min_height(spec, window->min_h);
   318 
   319     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   320     MIR_mir_surface_spec_release(spec);
   321 }
   322 
   323 void
   324 MIR_SetWindowMaximumSize(_THIS, SDL_Window* window)
   325 {
   326     MIR_Data*   mir_data   = _this->driverdata;
   327     MIR_Window* mir_window = window->driverdata;
   328     MirSurfaceSpec* spec;
   329 
   330     if (IsSurfaceValid(mir_window) < 0)
   331         return;
   332 
   333     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   334     MIR_mir_surface_spec_set_max_width (spec, window->max_w);
   335     MIR_mir_surface_spec_set_max_height(spec, window->max_h);
   336 
   337     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   338     MIR_mir_surface_spec_release(spec);
   339 }
   340 
   341 void
   342 MIR_SetWindowTitle(_THIS, SDL_Window* window)
   343 {
   344     MIR_Data*   mir_data   = _this->driverdata;
   345     MIR_Window* mir_window = window->driverdata;
   346     char const* title = window->title ? window->title : "";
   347     MirSurfaceSpec* spec;
   348 
   349     if (IsSurfaceValid(mir_window) < 0)
   350         return;
   351 
   352     spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
   353     MIR_mir_surface_spec_set_name(spec, title);
   354 
   355     MIR_mir_surface_apply_spec(mir_window->surface, spec);
   356     MIR_mir_surface_spec_release(spec);
   357 }
   358 
   359 #endif /* SDL_VIDEO_DRIVER_MIR */
   360 
   361 /* vi: set ts=4 sw=4 expandtab: */