[Tizen] add vulkan local header
[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_SetError("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     SDL_Log("%s with angle %d",__FUNCTION__, _this->rotation);
135     switch (_this->rotation) {
136          case 90:
137             rot = TIZEN_ROTATION_270;
138             break;
139          case 180:
140             rot = TIZEN_ROTATION_180;
141             break;
142          case 270:
143             rot = TIZEN_ROTATION_90;
144             break;
145          case 0:
146             rot = TIZEN_ROTATION_0;
147             break;
148          default:
149             rot = TIZEN_ROTATION_0;
150             break;
151       }
152
153       SDL_SetError("call wl_egl_win_set_rotation with rot %d",rot);
154       _this->tizen_pre_rotation_data->wl_egl_window_set_rotation(_this->egl_window, rot);
155 }
156
157 void
158 _tizen_window_orientaiton_hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue)
159 {
160     char *p_str = NULL;
161     char orientation_type[4][20] = {"Portrait","LandscapeLeft","PortraitUpsideDown","LandscapeRight"};
162     int checked[4] = {0,};
163     int i;
164     unsigned int j = 0;
165     SDL_WindowData *wind = (SDL_WindowData*)userdata;
166     Ecore_Wl_Window *window = wind->window;
167
168     if (wind->rotation_supported == 0) {
169         return;
170     }
171
172     SDL_assert(SDL_strncmp(name, SDL_HINT_ORIENTATIONS, SDL_strlen(SDL_HINT_ORIENTATIONS)) == 0);
173
174     if ((oldValue == NULL) && (newValue == NULL)) {
175         return;
176     }
177
178     for (i=0;i<4;i++) {
179         p_str = SDL_strstr(newValue, orientation_type[i]);
180         if (p_str) {
181             if (p_str == newValue) {
182                 int rot = 0;
183                 if (i == 0) rot = 0;
184                 else if (i == 1) rot = 90;
185                 else if (i == 2) rot = 180;
186                 else if (i == 3) rot = 270;
187                 wind->rotation = rot;
188             }
189
190             if (i == 0) {
191                 checked[j] = 0;
192                 SDL_Log("SDL  %s: avaiable rotation: 0", __FUNCTION__);
193             }
194             else if (i == 1) {
195                 checked[j] = 90;
196                 SDL_Log("SDL %s: avaiable rotation: 90", __FUNCTION__);
197             }
198             else if (i == 2) {
199                 checked[j] = 180;
200                 SDL_Log("SDL %s: avaiable rotation: 180", __FUNCTION__);
201             }
202             else if (i == 3) {
203                 checked[j] = 270;
204                 SDL_Log("SDL %s: avaiable rotation: 270", __FUNCTION__);
205             }
206             j++;
207         }
208     }
209
210     if (j > 0) {
211         if (j == 1) {
212             ecore_wl_window_rotation_preferred_rotation_set(window,wind->rotation);
213             SDL_Log("SDL %s: support pre_rotation %d", __FUNCTION__,wind->support_pre_rotation);
214             if (wind->support_pre_rotation) {
215                 SDL_Log("SDL %s: set pre rotation %d", __FUNCTION__,wind->rotation);
216                 _tizen_pre_rotation_set(wind);
217             }
218         }
219         ecore_wl_window_rotation_available_rotations_set(window, (const int*)checked, j);
220     }
221 }
222
223 void
224 _tizen_window_orientation_add_hint(void *data)
225 {
226     SDL_WindowData *wind = (SDL_WindowData*)data;
227     if (wind->rotation_supported == 0) {
228         return;
229     }
230
231     SDL_AddHintCallback(SDL_HINT_ORIENTATIONS, _tizen_window_orientaiton_hint_callback, data);
232 }
233
234 int
235 Tizen_CreateWindow(_THIS, SDL_Window *window)
236 {
237     SDL_VideoData *data = _this->driverdata;
238     SDL_WindowData *wind;
239     Ecore_Wl_Global *global;
240     Eina_Inlist *globals;
241
242     wind = calloc(1, sizeof * wind);
243     if (!wind) {
244         return SDL_OutOfMemory();
245     }
246
247     window->driverdata = wind;
248     window->flags |= SDL_WINDOW_INPUT_FOCUS;    /* always has input focus */
249
250 #if SDL_VIDEO_OPENGL_EGL
251     if (window->flags & SDL_WINDOW_OPENGL) {
252         SDL_GL_LoadLibrary(NULL);
253     }
254 #endif
255
256 #if SDL_VIDEO_VULKAN
257     if (window->flags & SDL_WINDOW_VULKAN) {
258         if (!_this->vulkan_GetInstanceExtensions) {
259             SDL_SetError("No Vulkan support in video driver");
260         }
261
262         if (_this->vulkan_LoadLibrary(_this, NULL) < 0) {
263             SDL_SetError("Fail to load Vulkan Library");
264         }
265     }
266 #endif
267
268     if (window->x == SDL_WINDOWPOS_UNDEFINED) {
269         window->x = 0;
270     }
271     if (window->y == SDL_WINDOWPOS_UNDEFINED) {
272         window->y = 0;
273     }
274
275     if (!(globals = ecore_wl_globals_get()))
276       {
277          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to get wayland globals");
278          return -1;
279       }
280
281     wind->window = ecore_wl_window_new(NULL,
282                                        window->x, window->y, window->w, window->h,
283                                        ECORE_WL_WINDOW_BUFFER_TYPE_SHM);
284     wind->surface = ecore_wl_window_surface_create(wind->window);
285     wind->rotation = 0;
286     wind->rotation_supported = 0;
287     wind->received_rotation = 0;
288     ecore_wl_window_opaque_region_set(wind->window, window->x, window->y, window->w, window->h);
289
290 #if SDL_VIDEO_OPENGL_EGL
291     if (window->flags & SDL_WINDOW_OPENGL) {
292         wind->egl_window = wl_egl_window_create(ecore_wl_window_surface_get(wind->window), window->w, window->h);
293
294         /* Create the GLES window surface */
295         wind->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) wind->egl_window);
296         if (wind->egl_surface == EGL_NO_SURFACE) {
297             SDL_SetError("failed to create a window surface");
298             return -1;
299         }
300
301         //Support PreRotation
302         wind->support_pre_rotation = 0;
303         if (_tizen_PreRotatotion_LoadLibrary(wind, "libwayland-egl.so")) {
304             if (wind->tizen_pre_rotation_data->wl_egl_window_get_capabilities(wind->egl_window) == TIZEN_WL_EGL_WINDOW_CAPABILITY_ROTATION_SUPPORTED ) {
305                 wind->support_pre_rotation = 1;
306                 SDL_Log("Can support PreRotation");
307             }
308             else {
309                 SDL_Log("can not support PreRotation !!");
310             }
311         }
312         else {
313             SDL_Log("can not support PreRotation !!");
314         }
315     }
316 #endif
317
318     wind->id = ecore_wl_window_id_get(wind->window);
319     eina_hash_add(data->windows, &wind->id, window);
320
321     Tizen_InitKeyboard(_this);
322     SDL_SetMouseFocus(window);
323
324     if (window->flags & 0x00008000) {
325         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
326         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[SDL] touch bypass setting is done!\n");
327         SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "---------------------------------------");
328         ecore_wl_window_input_region_set(wind->window, -1, -1, 1, 1);
329         ecore_wl_window_focus_skip_set(wind->window, EINA_TRUE);
330     }
331
332     EINA_INLIST_FOREACH(globals, global) {
333          if (!strcmp(global->interface, "tizen_policy_ext")) {
334               wind->rotation_supported = 1;
335               SDL_Log("SDL can support rotation in this device!!!!!!!!!!!");
336               break;
337            }
338       }
339     // Add orientaiton hint cb
340     _tizen_window_orientation_add_hint((void*)wind);
341     return 0;
342 }
343
344 void
345 _tizen_egl_window_resize(SDL_Window *window)
346 {
347     SDL_WindowData *wind = window->driverdata;
348     if (!wind->egl_window) {
349         return;
350     }
351
352     // TODO : consider to rotation status.
353 #if SDL_VIDEO_OPENGL_EGL
354     if (window->flags & SDL_WINDOW_OPENGL) {
355         // TODO : if window size is not FULL, we need the code about Non FullSize Window.
356         int aw, ah;
357         wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
358         wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
359     }
360 #endif
361
362 }
363
364 void
365 _tizen_setwindowsize(SDL_Window *window)
366 {
367     SDL_WindowData *wind = window->driverdata;
368     if (!wind->window) {
369         return;
370     }
371     ecore_wl_window_update_size(wind->window, window->w, window->h);
372 }
373
374 void
375 Tizen_SetWindowSize(_THIS, SDL_Window *window)
376 {
377    SDL_Log("[SDL_Size] Tizen_SetWindowSize");
378 //    _tizen_setwindowsize(window);
379 //    _tizen_egl_window_resize(window);
380 }
381
382 void
383 Tizen_GetWindowSize(_THIS, SDL_Window *window, int *w, int *h)
384 {
385     SDL_WindowData *wind = window->driverdata;
386     if (!wind->window) {
387         return;
388     }
389
390     if (w) *w = window->w;
391     if (h) *h = window->h;
392 }
393
394 void
395 Tizen_SetWindowPosition(_THIS, SDL_Window * window)
396 {
397     SDL_WindowData *wind = window->driverdata;
398     if (!wind->window) {
399         return;
400     }
401
402     // TODO : consider to rotation status.
403    ecore_wl_window_position_set(wind->window, window->x, window->y);
404 }
405
406 void
407 Tizen_DestroyWindow(_THIS, SDL_Window *window)
408 {
409     SDL_VideoData *data = _this->driverdata;
410     SDL_WindowData *wind = window->driverdata;
411
412     if (data) {
413         eina_hash_del(data->windows, &wind->id, window);
414 #if SDL_VIDEO_OPENGL_EGL
415     if (window->flags & SDL_WINDOW_OPENGL) {
416         SDL_EGL_DestroySurface(_this, wind->egl_surface);
417         wl_egl_window_destroy(wind->egl_window);
418     }
419 #endif
420         ecore_wl_window_free(wind->window);
421         SDL_free(wind);
422     }
423
424     window->driverdata = NULL;
425 }
426
427 SDL_Window*
428 Tizen_FindWindow(_THIS, Ecore_Wl_Window *ewin)
429 {
430     SDL_VideoData *data = _this->driverdata;
431     int id;
432
433     id = ecore_wl_window_id_get(ewin);
434     return (SDL_Window*)eina_hash_find(data->windows, &id);
435 }
436
437 Eina_Bool
438 _tizen_cb_event_window_visibility_change(void *data, int type, void *event)
439 {
440     _THIS = data;
441     Ecore_Wl_Event_Window_Visibility_Change *ev;
442     Ecore_Wl_Window *ew;
443     SDL_Window *window;
444
445     ev = event;
446     ew = ecore_wl_window_find(ev->win);
447     window = Tizen_FindWindow(_this, ew);
448
449     SDL_Log( "visibility window: %p, ecore_wl_window: %p\n", window, ew);
450
451     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
452     SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
453     return ECORE_CALLBACK_PASS_ON;
454 }
455
456 Eina_Bool
457 _tizen_cb_window_configure(void *data, int type EINA_UNUSED, void *event)
458 {
459    _THIS = data;
460    Ecore_Wl_Window *ew;
461    SDL_Window *window;
462    SDL_WindowData *wind;
463    Ecore_Wl_Event_Window_Configure *ev;
464    ev = event;
465    ew = ecore_wl_window_find(ev->win);
466    window = Tizen_FindWindow(_this, ew);
467    wind = window->driverdata;
468
469    if (wind->rotation_supported == 0){
470       return ECORE_CALLBACK_PASS_ON;
471    }
472 /*
473    int nx = 0, ny = 0, nw = 0, nh = 0;
474   SDL_Log( "configure notify window: %p, ecore_wl_window: %p\n", window, ew);
475
476    ecore_wl_window_geometry_get(ew, &nx, &ny, &nw, &nh);
477    if (nw < 1) nw = 1;
478    if (nh < 1) nh = 1;
479    
480    SDL_Log("[SDL_Size] * _tizen_cb_window_configure :: w->w:%d, w->h:%d, nw:%d, nh:%d", window->w, window->h, nw, nh);
481    if ((window->x != nx) || (window->y != ny))
482      ecore_wl_window_position_set(ew, nx, ny);
483
484    if ((window->w != nw) || (window->h != nh)) {
485      _tizen_setwindowsize(window);
486    }
487    */
488    return ECORE_CALLBACK_PASS_ON;
489 }
490
491
492 void
493 _tizen_send_rotation_event(SDL_Window *window, unsigned int angle)
494 {
495     SDL_Event event;
496     SDL_WindowData *wind;
497     wind = window->driverdata;
498
499     SDL_memset(&event, 0, sizeof(event));
500     event.type = SDL_ROTATEEVENT;
501     event.user.code = 0;
502     if (wind->support_pre_rotation)
503         event.user.data1 = (void*)0;
504     else
505         event.user.data1 = (void*)angle;
506     event.user.data2 = (void*)-1;
507
508     SDL_PushEvent(&event);
509     return;
510 }
511
512 Eina_Bool
513 _tizen_cb_event_window_rotate(void *data, int type EINA_UNUSED, void *event)
514 {
515     _THIS = data;
516     Ecore_Wl_Event_Window_Rotate *ev;
517     Ecore_Wl_Window *ew;
518     SDL_Window *window;
519     SDL_WindowData *wind;
520
521     ev = event;
522     if (!ev) {
523         return ECORE_CALLBACK_PASS_ON;
524     }
525
526     ew = ecore_wl_window_find(ev->win);
527     window = Tizen_FindWindow(_this, ew);
528     wind = window->driverdata;
529
530     if (wind->rotation != ev->angle) {
531         /* set ecore_wayland window rotation */
532         wind->rotation = ev->angle;
533         ecore_wl_window_rotation_set(ew, ev->angle);
534
535         if(wind->support_pre_rotation) {
536             _tizen_pre_rotation_set(wind);
537
538             int aw, ah;
539             wl_egl_window_get_attached_size(wind->egl_window, &aw, &ah);
540             wl_egl_window_resize(wind->egl_window, aw, ah, 0, 0);
541
542             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", aw, ah);
543
544             if(wind->rotation == 90 || wind->rotation == 270) {
545                 SDL_SetWindowSize(window, ah, aw);
546                 window->w = ah;//for Fullscreen
547                 window->h = aw;
548             } else {
549                 SDL_SetWindowSize(window, aw, ah);//->call wl_egl_window_resize()
550                 window->w = aw;//for Fullscreen
551                 window->h = ah;
552             }
553             SDL_Log("[SDL_Size] * _tizen_cb_event_window_rotate aw ah : %d, %d", window->w, window->h);
554     }
555
556         // Send Rotation Event
557         _tizen_send_rotation_event(window, ev->angle);
558         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);
559     }
560
561     wind->received_rotation = 1;
562     const char* hint = SDL_GetHint(SDL_HINT_ORIENTATIONS);
563     if(hint && *hint != '\0')
564         Tizen_IndicatorProcessEvent(_this->current_glwin, wind->rotation);
565
566     return ECORE_CALLBACK_PASS_ON;
567 }
568
569 int
570 Tizen_InitWindow(_THIS)
571 {
572     SDL_VideoData *data = _this->driverdata;
573
574     data->windows = eina_hash_int32_new(NULL);
575
576     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_VISIBILITY_CHANGE,
577                         _tizen_cb_event_window_visibility_change,_this);
578     ecore_event_handler_add(ECORE_EVENT_KEY_UP,
579                         _tizen_cb_event_keyup_change,_this);
580     ecore_event_handler_add(ECORE_EVENT_KEY_DOWN,
581                         _tizen_cb_event_keydown_change,_this);
582     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN,
583                         _tizen_cb_event_mousedown_change,_this);
584     ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
585                         _tizen_cb_event_mouseup_change,_this);
586     ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE,
587                         _tizen_cb_event_mousemove_change,_this);
588     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_ROTATE,
589                         _tizen_cb_event_window_rotate,_this);
590     ecore_event_handler_add(ECORE_WL_EVENT_WINDOW_CONFIGURE,
591                         _tizen_cb_window_configure,_this);
592     ecore_event_handler_add(ECORE_EVENT_JOYSTICK,
593                         _tizen_cb_event_joystick_change,_this);
594     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_IN,
595                         _tizen_cb_event_focus_in,_this);
596     ecore_event_handler_add(ECORE_WL_EVENT_FOCUS_OUT,
597                         _tizen_cb_event_focus_out,_this);
598     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_IN,
599                         _tizen_cb_event_mouse_in,_this);
600     ecore_event_handler_add(ECORE_WL_EVENT_MOUSE_OUT,
601                         _tizen_cb_event_mouse_out,_this);
602
603     data->current_thread = SDL_GetThreadID(0);
604
605     return 0;
606 }
607
608 void
609 Tizen_DeinitWindow(_THIS)
610 {
611     SDL_VideoData *data = _this->driverdata;
612
613     eina_hash_free(data->windows);
614 }
615 #endif /* SDL_VIDEO_DRIVER_TIZEN */
616
617 /* vi: set ts=4 sw=4 expandtab: */