• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_mirwindow.h"
31 #include "SDL_video.h"
32 
33 #include "SDL_mirframebuffer.h"
34 #include "SDL_mirmouse.h"
35 #include "SDL_miropengl.h"
36 #include "SDL_mirvideo.h"
37 
38 #include "SDL_mirdyn.h"
39 
40 #define MIR_DRIVER_NAME "mir"
41 
42 static const Uint32 mir_pixel_format_to_sdl_format[] = {
43     SDL_PIXELFORMAT_UNKNOWN,  /* mir_pixel_format_invalid   */
44     SDL_PIXELFORMAT_ABGR8888, /* mir_pixel_format_abgr_8888 */
45     SDL_PIXELFORMAT_BGR888,   /* mir_pixel_format_xbgr_8888 */
46     SDL_PIXELFORMAT_ARGB8888, /* mir_pixel_format_argb_8888 */
47     SDL_PIXELFORMAT_RGB888,   /* mir_pixel_format_xrgb_8888 */
48     SDL_PIXELFORMAT_BGR24,    /* mir_pixel_format_bgr_888   */
49     SDL_PIXELFORMAT_RGB24,    /* mir_pixel_format_rgb_888   */
50     SDL_PIXELFORMAT_RGB565,   /* mir_pixel_format_rgb_565   */
51     SDL_PIXELFORMAT_RGBA5551, /* mir_pixel_format_rgba_5551 */
52     SDL_PIXELFORMAT_RGBA4444  /* mir_pixel_format_rgba_4444 */
53 };
54 
55 Uint32
MIR_GetSDLPixelFormat(MirPixelFormat format)56 MIR_GetSDLPixelFormat(MirPixelFormat format)
57 {
58     return mir_pixel_format_to_sdl_format[format];
59 }
60 
61 static int
62 MIR_VideoInit(_THIS);
63 
64 static void
65 MIR_VideoQuit(_THIS);
66 
67 static int
68 MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect);
69 
70 static void
71 MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* sdl_display);
72 
73 static int
74 MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* sdl_display, SDL_DisplayMode* mode);
75 
76 static SDL_WindowShaper*
MIR_CreateShaper(SDL_Window * window)77 MIR_CreateShaper(SDL_Window* window)
78 {
79     /* FIXME Im not sure if mir support this atm, will have to come back to this */
80     return NULL;
81 }
82 
83 static int
MIR_SetWindowShape(SDL_WindowShaper * shaper,SDL_Surface * shape,SDL_WindowShapeMode * shape_mode)84 MIR_SetWindowShape(SDL_WindowShaper* shaper, SDL_Surface* shape, SDL_WindowShapeMode* shape_mode)
85 {
86     return SDL_Unsupported();
87 }
88 
89 static int
MIR_ResizeWindowShape(SDL_Window * window)90 MIR_ResizeWindowShape(SDL_Window* window)
91 {
92     return SDL_Unsupported();
93 }
94 
95 static int
MIR_Available()96 MIR_Available()
97 {
98     int available = 0;
99 
100     if (SDL_MIR_LoadSymbols()) {
101         /* !!! FIXME: try to make a MirConnection here. */
102         available = 1;
103         SDL_MIR_UnloadSymbols();
104     }
105 
106     return available;
107 }
108 
109 static void
MIR_DeleteDevice(SDL_VideoDevice * device)110 MIR_DeleteDevice(SDL_VideoDevice* device)
111 {
112     SDL_free(device);
113     SDL_MIR_UnloadSymbols();
114 }
115 
116 static void
MIR_PumpEvents(_THIS)117 MIR_PumpEvents(_THIS)
118 {
119 }
120 
121 static SDL_VideoDevice*
MIR_CreateDevice(int device_index)122 MIR_CreateDevice(int device_index)
123 {
124     MIR_Data* mir_data;
125     SDL_VideoDevice* device = NULL;
126 
127     if (!SDL_MIR_LoadSymbols()) {
128         return NULL;
129     }
130 
131     device = SDL_calloc(1, sizeof(SDL_VideoDevice));
132     if (!device) {
133         SDL_MIR_UnloadSymbols();
134         SDL_OutOfMemory();
135         return NULL;
136     }
137 
138     mir_data = SDL_calloc(1, sizeof(MIR_Data));
139     if (!mir_data) {
140         SDL_free(device);
141         SDL_MIR_UnloadSymbols();
142         SDL_OutOfMemory();
143         return NULL;
144     }
145 
146     device->driverdata = mir_data;
147 
148     /* mirvideo */
149     device->VideoInit        = MIR_VideoInit;
150     device->VideoQuit        = MIR_VideoQuit;
151     device->GetDisplayBounds = MIR_GetDisplayBounds;
152     device->GetDisplayModes  = MIR_GetDisplayModes;
153     device->SetDisplayMode   = MIR_SetDisplayMode;
154     device->free             = MIR_DeleteDevice;
155 
156     /* miropengles */
157     device->GL_SwapWindow      = MIR_GL_SwapWindow;
158     device->GL_MakeCurrent     = MIR_GL_MakeCurrent;
159     device->GL_CreateContext   = MIR_GL_CreateContext;
160     device->GL_DeleteContext   = MIR_GL_DeleteContext;
161     device->GL_LoadLibrary     = MIR_GL_LoadLibrary;
162     device->GL_UnloadLibrary   = MIR_GL_UnloadLibrary;
163     device->GL_GetSwapInterval = MIR_GL_GetSwapInterval;
164     device->GL_SetSwapInterval = MIR_GL_SetSwapInterval;
165     device->GL_GetProcAddress  = MIR_GL_GetProcAddress;
166 
167     /* mirwindow */
168     device->CreateWindow         = MIR_CreateWindow;
169     device->DestroyWindow        = MIR_DestroyWindow;
170     device->GetWindowWMInfo      = MIR_GetWindowWMInfo;
171     device->SetWindowFullscreen  = MIR_SetWindowFullscreen;
172     device->MaximizeWindow       = MIR_MaximizeWindow;
173     device->MinimizeWindow       = MIR_MinimizeWindow;
174     device->RestoreWindow        = MIR_RestoreWindow;
175     device->ShowWindow           = MIR_RestoreWindow;
176     device->HideWindow           = MIR_HideWindow;
177     device->SetWindowSize        = MIR_SetWindowSize;
178     device->SetWindowMinimumSize = MIR_SetWindowMinimumSize;
179     device->SetWindowMaximumSize = MIR_SetWindowMaximumSize;
180     device->SetWindowTitle       = MIR_SetWindowTitle;
181     device->SetWindowGrab        = MIR_SetWindowGrab;
182     device->SetWindowGammaRamp   = MIR_SetWindowGammaRamp;
183     device->GetWindowGammaRamp   = MIR_GetWindowGammaRamp;
184 
185     device->CreateWindowFrom     = NULL;
186     device->SetWindowIcon        = NULL;
187     device->RaiseWindow          = NULL;
188     device->SetWindowBordered    = NULL;
189     device->SetWindowResizable   = NULL;
190     device->OnWindowEnter        = NULL;
191     device->SetWindowPosition    = NULL;
192 
193     /* mirframebuffer */
194     device->CreateWindowFramebuffer  = MIR_CreateWindowFramebuffer;
195     device->UpdateWindowFramebuffer  = MIR_UpdateWindowFramebuffer;
196     device->DestroyWindowFramebuffer = MIR_DestroyWindowFramebuffer;
197 
198     device->shape_driver.CreateShaper      = MIR_CreateShaper;
199     device->shape_driver.SetWindowShape    = MIR_SetWindowShape;
200     device->shape_driver.ResizeWindowShape = MIR_ResizeWindowShape;
201 
202     device->PumpEvents = MIR_PumpEvents;
203 
204     device->SuspendScreenSaver = NULL;
205 
206     device->StartTextInput   = NULL;
207     device->StopTextInput    = NULL;
208     device->SetTextInputRect = NULL;
209 
210     device->HasScreenKeyboardSupport = NULL;
211     device->ShowScreenKeyboard       = NULL;
212     device->HideScreenKeyboard       = NULL;
213     device->IsScreenKeyboardShown    = NULL;
214 
215     device->SetClipboardText = NULL;
216     device->GetClipboardText = NULL;
217     device->HasClipboardText = NULL;
218 
219     device->ShowMessageBox = NULL;
220 
221     return device;
222 }
223 
224 VideoBootStrap MIR_bootstrap = {
225     MIR_DRIVER_NAME, "SDL Mir video driver",
226     MIR_Available, MIR_CreateDevice
227 };
228 
229 static SDL_DisplayMode
MIR_ConvertModeToSDLMode(MirOutputMode const * mode,MirPixelFormat format)230 MIR_ConvertModeToSDLMode(MirOutputMode const* mode, MirPixelFormat format)
231 {
232     SDL_DisplayMode sdl_mode  = {
233         .format = MIR_GetSDLPixelFormat(format),
234         .w      = MIR_mir_output_mode_get_width(mode),
235         .h      = MIR_mir_output_mode_get_height(mode),
236         .refresh_rate = MIR_mir_output_mode_get_refresh_rate(mode),
237         .driverdata   = NULL
238     };
239 
240     return sdl_mode;
241 }
242 
243 static void
MIR_AddModeToDisplay(SDL_VideoDisplay * display,MirOutputMode const * mode,MirPixelFormat format)244 MIR_AddModeToDisplay(SDL_VideoDisplay* display, MirOutputMode const* mode, MirPixelFormat format)
245 {
246     SDL_DisplayMode sdl_mode = MIR_ConvertModeToSDLMode(mode, format);
247     SDL_AddDisplayMode(display, &sdl_mode);
248 }
249 
250 static void
MIR_InitDisplayFromOutput(_THIS,MirOutput * output)251 MIR_InitDisplayFromOutput(_THIS, MirOutput* output)
252 {
253     SDL_VideoDisplay display;
254     int m;
255 
256     MirPixelFormat format = MIR_mir_output_get_current_pixel_format(output);
257     int num_modes         = MIR_mir_output_get_num_modes(output);
258     SDL_DisplayMode current_mode = MIR_ConvertModeToSDLMode(mir_output_get_current_mode(output), format);
259 
260     SDL_zero(display);
261 
262     // Unfortunate cast, but SDL_AddVideoDisplay will strdup this pointer so its read-only in this case.
263     display.name = (char*)MIR_mir_output_type_name(MIR_mir_output_get_type(output));
264 
265     for (m = 0; m < num_modes; m++) {
266         MirOutputMode const* mode = MIR_mir_output_get_mode(output, m);
267         MIR_AddModeToDisplay(&display, mode, format);
268     }
269 
270     display.desktop_mode = current_mode;
271     display.current_mode = current_mode;
272 
273     display.driverdata = output;
274     SDL_AddVideoDisplay(&display);
275 }
276 
277 static void
MIR_InitDisplays(_THIS)278 MIR_InitDisplays(_THIS)
279 {
280     MIR_Data* mir_data = _this->driverdata;
281     int num_outputs    = MIR_mir_display_config_get_num_outputs(mir_data->display_config);
282     int d;
283 
284     for (d = 0; d < num_outputs; d++) {
285         MirOutput* output = MIR_mir_display_config_get_mutable_output(mir_data->display_config, d);
286         SDL_bool enabled  = MIR_mir_output_is_enabled(output);
287         MirOutputConnectionState state = MIR_mir_output_get_connection_state(output);
288 
289         if (enabled && state == mir_output_connection_state_connected) {
290             MIR_InitDisplayFromOutput(_this, output);
291         }
292     }
293 }
294 
295 static int
MIR_VideoInit(_THIS)296 MIR_VideoInit(_THIS)
297 {
298     MIR_Data* mir_data = _this->driverdata;
299 
300     mir_data->connection     = MIR_mir_connect_sync(NULL, __PRETTY_FUNCTION__);
301     mir_data->current_window = NULL;
302     mir_data->software       = SDL_FALSE;
303     mir_data->pixel_format   = mir_pixel_format_invalid;
304 
305     if (!MIR_mir_connection_is_valid(mir_data->connection)) {
306         return SDL_SetError("Failed to connect to the mir server: %s",
307             MIR_mir_connection_get_error_message(mir_data->connection));
308     }
309 
310     mir_data->display_config = MIR_mir_connection_create_display_configuration(mir_data->connection);
311 
312     MIR_InitDisplays(_this);
313     MIR_InitMouse();
314 
315     return 0;
316 }
317 
318 static void
MIR_CleanUpDisplayConfig(_THIS)319 MIR_CleanUpDisplayConfig(_THIS)
320 {
321     MIR_Data* mir_data = _this->driverdata;
322     int i;
323 
324     // SDL_VideoQuit frees the display driverdata, we own it not them
325     for (i = 0; i < _this->num_displays; ++i) {
326         _this->displays[i].driverdata = NULL;
327     }
328 
329     MIR_mir_display_config_release(mir_data->display_config);
330 }
331 
332 static void
MIR_VideoQuit(_THIS)333 MIR_VideoQuit(_THIS)
334 {
335     MIR_Data* mir_data = _this->driverdata;
336 
337     MIR_CleanUpDisplayConfig(_this);
338 
339     MIR_FiniMouse();
340 
341     MIR_GL_DeleteContext(_this, NULL);
342     MIR_GL_UnloadLibrary(_this);
343 
344     MIR_mir_connection_release(mir_data->connection);
345 
346     SDL_free(mir_data);
347     _this->driverdata = NULL;
348 }
349 
350 static int
MIR_GetDisplayBounds(_THIS,SDL_VideoDisplay * display,SDL_Rect * rect)351 MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect)
352 {
353     MirOutput const* output = display->driverdata;
354 
355     rect->x = MIR_mir_output_get_position_x(output);
356     rect->y = MIR_mir_output_get_position_y(output);
357     rect->w = display->current_mode.w;
358     rect->h = display->current_mode.h;
359 
360     return 0;
361 }
362 
363 static void
MIR_GetDisplayModes(_THIS,SDL_VideoDisplay * display)364 MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* display)
365 {
366 }
367 
368 static int
MIR_SetDisplayMode(_THIS,SDL_VideoDisplay * display,SDL_DisplayMode * mode)369 MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* display, SDL_DisplayMode* mode)
370 {
371     int m;
372     MirOutput* output = display->driverdata;
373     int num_modes     = MIR_mir_output_get_num_modes(output);
374     Uint32 sdl_format = MIR_GetSDLPixelFormat(
375                             MIR_mir_output_get_current_pixel_format(output));
376 
377     for (m = 0; m < num_modes; m++) {
378         MirOutputMode const* mir_mode = MIR_mir_output_get_mode(output, m);
379         int width  = MIR_mir_output_mode_get_width(mir_mode);
380         int height = MIR_mir_output_mode_get_height(mir_mode);
381         double refresh_rate = MIR_mir_output_mode_get_refresh_rate(mir_mode);
382 
383         if (mode->format == sdl_format &&
384             mode->w      == width &&
385             mode->h      == height &&
386             mode->refresh_rate == refresh_rate) {
387 
388             // FIXME Currently wont actually *set* anything. Need to wait for applying display changes
389             MIR_mir_output_set_current_mode(output, mir_mode);
390             return 0;
391         }
392     }
393 
394     return -1;
395 }
396 
397 #endif /* SDL_VIDEO_DRIVER_MIR */
398 
399 /* vi: set ts=4 sw=4 expandtab: */
400 
401