Merge "[Tizen] add vulkan local header" into tizen
[platform/upstream/SDL.git] / src / video / tizen / SDL_tizenwindow.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4   Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
5
6   This software is provided 'as-is', without any express or implied
7   warranty.  In no event will the authors be held liable for any damages
8   arising from the use of this software.
9
10   Permission is granted to anyone to use this software for any purpose,
11   including commercial applications, and to alter it and redistribute it
12   freely, subject to the following restrictions:
13
14   1. The origin of this software must not be misrepresented; you must not
15      claim that you wrote the original software. If you use this software
16      in a product, an acknowledgment in the product documentation would be
17      appreciated but is not required.
18   2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20   3. This notice may not be removed or altered from any source distribution.
21 */
22
23 #include "../../SDL_internal.h"
24
25 #if SDL_VIDEO_DRIVER_TIZEN
26
27 #include "SDL_log.h"
28 #include "SDL_hints.h"
29 #include "SDL_loadso.h"
30
31 #include "SDL_tizenindicator.h"
32
33 #include "SDL_tizenvideo.h"
34 #include "SDL_tizentouch.h"
35 #include "SDL_tizenkeyboard.h"
36 #include "SDL_tizenmouse.h"
37 #include "SDL_tizenevents_c.h"
38
39 #include "SDL_tizenwindow.h"
40
41 #include "../../events/SDL_mouse_c.h"
42 #include "../../joystick/tizen/SDL_sysjoystick_c.h"
43
44 #include "../SDL_egl_c.h"
45 #include "../SDL_vulkan_c.h"
46 #include "../SDL_sysvideo.h"
47 #include "../../events/SDL_windowevents_c.h"
48
49 #define LOAD_FUNC(NAME) \
50 _this->tizen_pre_rotation_data->NAME = SDL_LoadFunction(_this->tizen_pre_rotation_data->prerotation_dll_handle, #NAME); \
51 if (!_this->tizen_pre_rotation_data->NAME) \
52 { \
53     SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Could not retrieve pre-rotation function " #NAME); \
54     return SDL_FALSE; \
55 }
56
57 int
58 _tizen_PreRotatotion_LoadLibrary(SDL_WindowData *_this, const char *lib_path)
59 {
60     void *lib_dll_handle = NULL;
61     char *path = NULL;
62
63     if (_this->isLoaded_pre_rotation)
64         return SDL_TRUE;
65
66     _this->tizen_pre_rotation_data = (Tizen_Prerotation_Data *) SDL_calloc(1, sizeof(Tizen_Prerotation_Data));
67     if (!_this->tizen_pre_rotation_data) {
68         return SDL_OutOfMemory();
69     }
70
71     if (!lib_path)
72         lib_dll_handle = SDL_LoadObject(lib_path);
73
74     if (!lib_dll_handle) {
75         path = "libwayland-egl.so";
76         lib_dll_handle = SDL_LoadObject(path);
77     }
78
79     _this->tizen_pre_rotation_data->prerotation_dll_handle = lib_dll_handle;
80
81     if (lib_dll_handle == NULL)
82         return SDL_FALSE;
83
84     LOAD_FUNC(wl_egl_window_set_rotation);
85     LOAD_FUNC(wl_egl_window_get_capabilities);
86     _this->isLoaded_pre_rotation = 1;
87
88     return SDL_TRUE;
89 }
90
91 SDL_bool
92 Tizen_GetWindowWMInfo(_THIS, SDL_Window *window, SDL_SysWMinfo *info)
93 {
94     SDL_WindowData *wmdata = (SDL_WindowData *)window->driverdata;
95     info->info.tizen.egl_display = NULL;
96     info->info.tizen.egl_surface = NULL;
97 #if SDL_VIDEO_OPENGL_EGL
98     if (_this->egl_data)
99     {
100        info->info.tizen.egl_display = (void*)_this->egl_data->egl_display;
101     }
102     info->info.tizen.egl_surface = (void*)wmdata->egl_surface;
103 #endif
104     info->subsystem = SDL_SYSWM_TIZEN;
105     return SDL_TRUE;
106 }
107
108 int
109 Tizen_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
110 {
111     return 0;  /* just succeed, the real work is done elsewhere. */
112 }
113
114 void
115 Tizen_ShowWindow(_THIS, SDL_Window *window)
116 {
117     SDL_WindowData *wind = window->driverdata;
118     ecore_wl_window_show(wind->window);
119 }
120
121 void
122 Tizen_SetWindowFullscreen(_THIS, SDL_Window *window,
123                           SDL_VideoDisplay *_display, SDL_bool fullscreen)
124 {
125     /*DO NOTHING*/
126 }
127
128 void
129 _tizen_pre_rotation_set(SDL_WindowData *_this)
130 {
131     tizen_wl_egl_window_rotation rot;
132     if (!_this->egl_window) return;
133
134     switch (_this->rotation) {
135          case 90:
136             rot = TIZEN_ROTATION_270;
137             break;
138          case 180:
139             rot = TIZEN_ROTATION_180;
140             break;
141          case 270:
142             rot = TIZEN_ROTATION_90;
143             break;
144          case 0:
145             rot = TIZEN_ROTATION_0;
146             break;
147          default:
148             rot = TIZEN_ROTATION_0;
149             break;
150       }
151
152       _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
153 }
154
155 void
156 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
157 {
158     char *p_str = NULL;
159     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
160     int checked[4] = {0,};
161     int i;
162     unsigned int j = 0;
163     SDL_WindowData *wind = (SDL_WindowData*)userdata;
164     Ecore_Wl_Window *window = wind->window;
165
166     if (wind->rotation_supported == 0) {
167         return;
168     }
169
170     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
171
172     if ((oldValue == NULL) && (newValue == NULL)) {
173         return;
174     }
175
176     for (i=0;i<4;i++) {
177         p_str = SDL_strstr(newValue, orientation_type[i]);
178         if (p_str) {
179             if (p_str == newValue) {
180                 int rot = 0;
181                 if (i == 0) rot = 0;
182                 else if (i == 1) rot = 90;
183                 else if (i == 2) rot = 180;
184                 else if (i == 3) rot = 270;
185                 wind->rotation = rot;
186             }
187
188             if (i == 0) {
189                 checked[j] = 0;
190             }
191             else if (i == 1) {
192                 checked[j] = 90;
193             }
194             else if (i == 2) {
195                 checked[j] = 180;
196             }
197             else if (i == 3) {
198                 checked[j] = 270;
199             }
200             j++;
201         }
202     }
203
204     if (j > 0) {
205         if (j == 1) {
206             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
207             if (wind->support_pre_rotation) {
208                 _tizen_pre_rotation_set(wind);
209             }
210         }
211         ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
212     }
213 }
214
215 void
216 _tizen_window_orientation_add_hint(void *data)
217 {
218     SDL_WindowData *wind = (SDL_WindowData*)data;
219     if (wind->rotation_supported == 0) {
220         return;
221     }
222
223     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
224 }
225
226 int
227 Tizen_CreateWindow(_THIS, SDL_Window *window)
228 {
229     SDL_VideoData *data = _this->driverdata;
230     SDL_WindowData *wind;
231     Ecore_Wl_Global *global;
232     Eina_Inlist *globals;
233
234     wind = calloc(1, sizeof * wind);
235     if (!wind) {
236         return SDL_OutOfMemory();
237     }
238
239     window->driverdata = wind;
240     window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
241
242 #if SDL_VIDEO_OPENGL_EGL
243     if (window->flags & SDL_WINDOW_OPENGL) {
244         SDL_GL_LoadLibrary(NULL);
245     }
246 #endif
247
248 #if SDL_VIDEO_VULKAN
249     if (window->flags & SDL_WINDOW_VULKAN) {
250         if (!_this->vulkan_GetInstanceExtensions) {
251             SDL_SetError("No Vulkan support in video driver");
252         }
253
254         if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
255             SDL_SetError("Fail to load Vulkan Library");
256         }
257     }
258 #endif
259
260     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
261         window->x = 0;
262     }
263     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
264         window->y = 0;
265     }
266
267     if (!(globals = ecore_wl_globals_get()))
268       {
269          SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "Failed to get wayland globals");
270          return -1;
271       }
272
273     wind->window = ecore_wl_window_new(NULL,
274                                        window->x, window->y, window->w, window->h,
275                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
276     wind->surface = ecore_wl_window_surface_create(wind->window);
277     wind->rotation = 0;
278     wind->rotation_supported = 0;
279     wind->received_rotation = 0;
280     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
281
282 #if SDL_VIDEO_OPENGL_EGL
283     if (window->flags & SDL_WINDOW_OPENGL) {
284         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
285
286         /* Create the GLES window surface */
287         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
288         if (wind->egl_surface == EGL_NO_SURFACE) {
289             SDL_LogError(SDL_LOG_CATEGORY_ASSERT, "failed to create a window surface");
290             return -1;
291         }
292
293         //Support PreRotation
294         wind->support_pre_rotation = 0;
295         if (_tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
296             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
297                 wind->support_pre_rotation = 1;
298             }
299         }
300     }
301 #endif
302
303     wind->id = ecore_wl_window_id_get(wind->window);
304     eina_hash_add(data->windows, &wind->id, window);
305
306     Tizen_InitKeyboard(_this);
307     SDL_SetMouseFocus(window);
308
309     if (window->flags & 0x00008000) {
310         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
311         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
312     }
313
314     EINA_INLIST_FOREACH(globals, global) {
315          if (!strcmp(global->interface, "tizen_policy_ext")) {
316               wind->rotation_supported = 1;
317               break;
318            }
319       }
320     // Add orientaiton hint cb
321     _tizen_window_orientation_add_hint((void*)wind);
322
323     return 0;
324 }
325
326 void
327 _tizen_egl_window_resize(SDL_Window *window)
328 {
329     SDL_WindowData *wind = window->driverdata;
330     if (!wind->egl_window) {
331         return;
332     }
333
334     // TODO : consider to rotation status.
335 #if SDL_VIDEO_OPENGL_EGL
336     if (window->flags & SDL_WINDOW_OPENGL) {
337         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
338         int aw, ah;
339         wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
340         wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
341     }
342 #endif
343
344 }
345
346 void
347 _tizen_setwindowsize(SDL_Window *window)
348 {
349     SDL_WindowData *wind = window->driverdata;
350     if (!wind->window) {
351         return;
352     }
353     ecore_wl_window_update_size(wind->window, window->w, window->h);
354 }
355
356 void
357 Tizen_SetWindowSize(_THIS, SDL_Window *window)
358 {
359 //    _tizen_setwindowsize(window);
360 //    _tizen_egl_window_resize(window);
361 }
362
363 void
364 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
365 {
366     SDL_WindowData *wind = window->driverdata;
367     if (!wind->window) {
368         return;
369     }
370
371     if (w) *w = window->w;
372     if (h) *h = window->h;
373 }
374
375 void
376 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
377 {
378     SDL_WindowData *wind = window->driverdata;
379     if (!wind->window) {
380         return;
381     }
382
383     // TODO : consider to rotation status.
384    ecore_wl_window_position_set(wind->window, window->x, window->y);
385 }
386
387 void
388 Tizen_DestroyWindow(_THIS, SDL_Window *window)
389 {
390     SDL_VideoData *data = _this->driverdata;
391     SDL_WindowData *wind = window->driverdata;
392
393     if (data) {
394         eina_hash_del(data->windows, &wind->id, window);
395 #if SDL_VIDEO_OPENGL_EGL
396     if (window->flags & SDL_WINDOW_OPENGL) {
397         SDL_EGL_DestroySurface(_this, wind->egl_surface);
398         wl_egl_window_destroy(wind->egl_window);
399     }
400 #endif
401         ecore_wl_window_free(wind->window);
402         SDL_free(wind);
403     }
404
405     window->driverdata = NULL;
406 }
407
408 SDL_Window*
409 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
410 {
411     SDL_VideoData *data = _this->driverdata;
412     int id;
413
414     id = ecore_wl_window_id_get(ewin);
415     return (SDL_Window*)eina_hash_find(data->windows, &id);
416 }
417
418 Eina_Bool
419 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
420 {
421     _THIS = data;
422     Ecore_Wl_Event_Window_Visibility_Change *ev;
423     Ecore_Wl_Window *ew;
424     SDL_Window *window;
425
426     ev = event;
427     ew = ecore_wl_window_find(ev->win);
428     window = Tizen_FindWindow(_this, ew);
429
430     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
431     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
432     return ECORE_CALLBACK_PASS_ON;
433 }
434
435 Eina_Bool
436 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
437 {
438    _THIS = data;
439    Ecore_Wl_Window *ew;
440    SDL_Window *window;
441    SDL_WindowData *wind;
442    Ecore_Wl_Event_Window_Configure *ev;
443    ev = event;
444    ew = ecore_wl_window_find(ev->win);
445    window = Tizen_FindWindow(_this, ew);
446    wind = window->driverdata;
447
448    if (wind->rotation_supported == 0){
449       return ECORE_CALLBACK_PASS_ON;
450    }
451 /*
452    int nx = 0, ny = 0, nw = 0, nh = 0;
453   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
454
455    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
456    if (nw < 1) nw = 1;
457    if (nh < 1) nh = 1;
458    
459    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
460    if ((window->x != nx) || (window->y != ny))
461      ecore_wl_window_position_set(ew, nx, ny);
462
463    if ((window->w != nw) || (window->h != nh)) {
464      _tizen_setwindowsize(window);
465    }
466    */
467    return ECORE_CALLBACK_PASS_ON;
468 }
469
470
471 void
472 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
473 {
474     SDL_Event event;
475     SDL_WindowData *wind;
476     wind = window->driverdata;
477
478     SDL_memset(&event, 0, sizeof(event));
479     event.type = SDL_ROTATEEVENT;
480     event.user.code = 0;
481     if (wind->support_pre_rotation)
482         event.user.data1 = (void*)0;
483     else
484         event.user.data1 = (void*)angle;
485     event.user.data2 = (void*)-1;
486
487     SDL_PushEvent(&event);
488     return;
489 }
490
491 Eina_Bool
492 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
493 {
494     _THIS = data;
495     Ecore_Wl_Event_Window_Rotate *ev;
496     Ecore_Wl_Window *ew;
497     SDL_Window *window;
498     SDL_WindowData *wind;
499
500     ev = event;
501     if (!ev) {
502         return ECORE_CALLBACK_PASS_ON;
503     }
504
505     ew = ecore_wl_window_find(ev->win);
506     window = Tizen_FindWindow(_this, ew);
507     wind = window->driverdata;
508
509     if (wind->rotation != ev->angle) {
510         /* set ecore_wayland window rotation */
511         wind->rotation = ev->angle;
512         ecore_wl_window_rotation_set(ew, ev->angle);
513
514         if(wind->support_pre_rotation) {
515             _tizen_pre_rotation_set(wind);
516
517             int aw, ah;
518             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
519             wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
520
521             if(wind->rotation == 90 || wind->rotation == 270) {
522                 SDL_SetWindowSize(window, ah, aw);
523                 window->w = ah;//for Fullscreen
524                 window->h = aw;
525             } else {
526                 SDL_SetWindowSize(window, aw, ah);//->call wl_egl_window_resize()
527                 window->w = aw;//for Fullscreen
528                 window->h = ah;
529             }
530     }
531
532         // Send Rotation Event
533         _tizen_send_rotation_event(window, ev->angle);
534         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
535     }
536
537     wind->received_rotation = 1;
538     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
539     if(hint && *hint != '\0')
540         Tizen_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
541
542     return ECORE_CALLBACK_PASS_ON;
543 }
544
545 int
546 Tizen_InitWindow(_THIS)
547 {
548     SDL_VideoData *data = _this->driverdata;
549
550     data->windows = eina_hash_int32_new(NULL);
551
552     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
553                         _tizen_cb_event_window_visibility_change,_this);
554     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
555                         _tizen_cb_event_keyup_change,_this);
556     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
557                         _tizen_cb_event_keydown_change,_this);
558     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
559                         _tizen_cb_event_mousedown_change,_this);
560     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
561                         _tizen_cb_event_mouseup_change,_this);
562     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
563                         _tizen_cb_event_mousemove_change,_this);
564     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
565                         _tizen_cb_event_window_rotate,_this);
566     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
567                         _tizen_cb_window_configure,_this);
568     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
569                         _tizen_cb_event_joystick_change,_this);
570     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
571                         _tizen_cb_event_focus_in,_this);
572     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
573                         _tizen_cb_event_focus_out,_this);
574     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
575                         _tizen_cb_event_mouse_in,_this);
576     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
577                         _tizen_cb_event_mouse_out,_this);
578
579     data->current_thread = SDL_GetThreadID(0);
580
581     return 0;
582 }
583
584 void
585 Tizen_DeinitWindow(_THIS)
586 {
587     SDL_VideoData *data = _this->driverdata;
588
589     eina_hash_free(data->windows);
590 }
591 #endif /* SDL_VIDEO_DRIVER_TIZEN */
592
593 /* vi: set ts=4 sw=4 expandtab: */