~registry/dolphin-emu/triforce

« back to all changes in this revision

Viewing changes to Source/Core/DolphinWX/Src/GLInterface/Wayland_Util.cpp

  • Committer: Sérgio Benjamim
  • Date: 2015-02-13 05:54:40 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20150213055440-ey2rt3sjpy27km78
Dolphin Triforce branch from code.google, commit b957980 (4.0-315).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2013 Scott Moreau <oreaus@gmail.com>
 
2
 
 
3
// This program is free software: you can redistribute it and/or modify
 
4
// it under the terms of the GNU General Public License as published by
 
5
// the Free Software Foundation, version 2.0.
 
6
 
 
7
// This program is distributed in the hope that it will be useful,
 
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
// GNU General Public License 2.0 for more details.
 
11
 
 
12
// A copy of the GPL 2.0 should have been included with the program.
 
13
// If not, see http://www.gnu.org/licenses/
 
14
 
 
15
// Official SVN repository and contact information can be found at
 
16
// http://code.google.com/p/dolphin-emu/
 
17
 
 
18
#include "Core.h"
 
19
#include "State.h"
 
20
#include "../GLInterface.h"
 
21
#include <linux/input.h>
 
22
#include <sys/mman.h>
 
23
 
 
24
 
 
25
static void
 
26
redraw(void *data, struct wl_callback *callback, uint32_t time);
 
27
 
 
28
static const struct wl_callback_listener frame_listener = {
 
29
        redraw
 
30
};
 
31
 
 
32
static void
 
33
redraw(void *data, struct wl_callback *callback, uint32_t time)
 
34
{
 
35
        if (GLWin.wl_callback != callback) {
 
36
                printf("Got wrong callback from wayland server\n");
 
37
                exit(-1);
 
38
        }
 
39
 
 
40
        GLWin.wl_callback = NULL;
 
41
 
 
42
        if (callback)
 
43
                wl_callback_destroy(callback);
 
44
 
 
45
        if (!GLWin.configured)
 
46
                return;
 
47
 
 
48
        // Reset the frame callback
 
49
        GLWin.wl_callback = wl_surface_frame(GLWin.wl_surface);
 
50
        wl_callback_add_listener(GLWin.wl_callback, &frame_listener, 0);
 
51
 
 
52
        // Present rendered buffer on screen
 
53
        //eglSwapBuffers(GLWin.egl_dpy, GLWin.egl_surf);
 
54
}
 
55
 
 
56
static void
 
57
hide_cursor(void)
 
58
{
 
59
        if (!GLWin.pointer.wl_pointer)
 
60
                return;
 
61
 
 
62
        wl_pointer_set_cursor(GLWin.pointer.wl_pointer,
 
63
                              GLWin.pointer.serial, NULL, 0, 0);
 
64
}
 
65
 
 
66
static void
 
67
configure_callback(void *data, struct wl_callback *callback, uint32_t  time)
 
68
{
 
69
        wl_callback_destroy(callback);
 
70
 
 
71
        GLWin.configured = true;
 
72
 
 
73
        if (GLWin.wl_callback == NULL)
 
74
                redraw(data, NULL, time);
 
75
}
 
76
 
 
77
static struct wl_callback_listener configure_callback_listener = {
 
78
        configure_callback,
 
79
};
 
80
 
 
81
static void
 
82
handle_ping(void *data, struct wl_shell_surface *wl_shell_surface,
 
83
            uint32_t serial)
 
84
{
 
85
        wl_shell_surface_pong(wl_shell_surface, serial);
 
86
}
 
87
 
 
88
static void
 
89
handle_configure(void *data, struct wl_shell_surface *wl_shell_surface,
 
90
                 uint32_t edges, int32_t width, int32_t height)
 
91
{
 
92
 
 
93
        if (GLWin.wl_egl_native)
 
94
                wl_egl_window_resize(GLWin.wl_egl_native, width, height, 0, 0);
 
95
 
 
96
        GLWin.geometry.width = width;
 
97
        GLWin.geometry.height = height;
 
98
 
 
99
        GLInterface->SetBackBufferDimensions(width, height);
 
100
 
 
101
        if (!GLWin.fullscreen)
 
102
                GLWin.window_size = GLWin.geometry;
 
103
}
 
104
 
 
105
static void
 
106
handle_popup_done(void *data, struct wl_shell_surface *wl_shell_surface)
 
107
{
 
108
}
 
109
 
 
110
static const struct wl_shell_surface_listener shell_surface_listener = {
 
111
        handle_ping,
 
112
        handle_configure,
 
113
        handle_popup_done
 
114
};
 
115
 
 
116
static void
 
117
pointer_handle_enter(void *data, struct wl_pointer *pointer,
 
118
                     uint32_t serial, struct wl_surface *surface,
 
119
                     wl_fixed_t sx, wl_fixed_t sy)
 
120
{
 
121
        GLWin.pointer.serial = serial;
 
122
 
 
123
        if (GLWin.fullscreen)
 
124
                hide_cursor();
 
125
}
 
126
 
 
127
static void
 
128
pointer_handle_leave(void *data, struct wl_pointer *pointer,
 
129
                     uint32_t serial, struct wl_surface *surface)
 
130
{
 
131
}
 
132
 
 
133
static void
 
134
pointer_handle_motion(void *data, struct wl_pointer *pointer,
 
135
                      uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
 
136
{
 
137
}
 
138
 
 
139
static void
 
140
pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
 
141
                      uint32_t serial, uint32_t time, uint32_t button,
 
142
                      uint32_t state)
 
143
{
 
144
}
 
145
 
 
146
static void
 
147
pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
 
148
                    uint32_t time, uint32_t axis, wl_fixed_t value)
 
149
{
 
150
}
 
151
 
 
152
static const struct wl_pointer_listener pointer_listener = {
 
153
        pointer_handle_enter,
 
154
        pointer_handle_leave,
 
155
        pointer_handle_motion,
 
156
        pointer_handle_button,
 
157
        pointer_handle_axis,
 
158
};
 
159
 
 
160
void setup_callback_listener()
 
161
{
 
162
        struct wl_callback *callback;
 
163
 
 
164
        callback = wl_display_sync(GLWin.wl_display);
 
165
        wl_callback_add_listener(callback, &configure_callback_listener, 0);
 
166
}
 
167
 
 
168
static void
 
169
toggle_fullscreen(bool fullscreen)
 
170
{
 
171
        GLWin.fullscreen = fullscreen;
 
172
        GLWin.configured = false;
 
173
 
 
174
        if (fullscreen) {
 
175
                wl_shell_surface_set_fullscreen(GLWin.wl_shell_surface,
 
176
                                                WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
 
177
                                                0, NULL);
 
178
        } else {
 
179
                wl_shell_surface_set_toplevel(GLWin.wl_shell_surface);
 
180
                handle_configure(NULL, GLWin.wl_shell_surface, 0,
 
181
                                 GLWin.window_size.width,
 
182
                                 GLWin.window_size.height);
 
183
        }
 
184
 
 
185
        setup_callback_listener();
 
186
}
 
187
 
 
188
static void
 
189
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
 
190
                       uint32_t format, int fd, uint32_t size)
 
191
{
 
192
        char *map_str;
 
193
 
 
194
        if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
 
195
                close(fd);
 
196
                return;
 
197
        }
 
198
 
 
199
        map_str = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
 
200
        if (map_str == MAP_FAILED) {
 
201
                close(fd);
 
202
                return;
 
203
        }
 
204
 
 
205
        GLWin.keyboard.xkb.keymap = xkb_map_new_from_string(GLWin.keyboard.xkb.context,
 
206
                                                    map_str,
 
207
                                                    XKB_KEYMAP_FORMAT_TEXT_V1,
 
208
                                                    (xkb_keymap_compile_flags) 0);
 
209
        munmap(map_str, size);
 
210
        close(fd);
 
211
 
 
212
        if (!GLWin.keyboard.xkb.keymap) {
 
213
                fprintf(stderr, "failed to compile keymap\n");
 
214
                return;
 
215
        }
 
216
 
 
217
        GLWin.keyboard.xkb.state = xkb_state_new(GLWin.keyboard.xkb.keymap);
 
218
        if (!GLWin.keyboard.xkb.state) {
 
219
                fprintf(stderr, "failed to create XKB state\n");
 
220
                xkb_map_unref(GLWin.keyboard.xkb.keymap);
 
221
                GLWin.keyboard.xkb.keymap = NULL;
 
222
                return;
 
223
        }
 
224
 
 
225
        GLWin.keyboard.xkb.control_mask =
 
226
                1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Control");
 
227
        GLWin.keyboard.xkb.alt_mask =
 
228
                1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Mod1");
 
229
        GLWin.keyboard.xkb.shift_mask =
 
230
                1 << xkb_map_mod_get_index(GLWin.keyboard.xkb.keymap, "Shift");
 
231
}
 
232
 
 
233
static void
 
234
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
 
235
                      uint32_t serial, struct wl_surface *surface,
 
236
                      struct wl_array *keys)
 
237
{
 
238
}
 
239
 
 
240
static void
 
241
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
 
242
                      uint32_t serial, struct wl_surface *surface)
 
243
{
 
244
}
 
245
 
 
246
static void
 
247
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
 
248
                    uint32_t serial, uint32_t time, uint32_t key,
 
249
                    uint32_t state)
 
250
{
 
251
        if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
 
252
                return;
 
253
 
 
254
        if (key == KEY_ESC)
 
255
                GLWin.running = false;
 
256
        else if ((key == KEY_P) ||
 
257
                ((key == KEY_ENTER) && (GLWin.keyboard.modifiers == 0)))
 
258
                Core::SetState((Core::GetState() == Core::CORE_RUN) ?
 
259
                                Core::CORE_PAUSE : Core::CORE_RUN);
 
260
        else if (key == KEY_F)
 
261
                toggle_fullscreen(!GLWin.fullscreen);
 
262
        else if ((key == KEY_ENTER) && (GLWin.keyboard.modifiers == MOD_ALT_MASK))
 
263
                toggle_fullscreen(!GLWin.fullscreen);
 
264
        else if (key >= KEY_F1 && key <= KEY_F8) {
 
265
                int slot_number = key - KEY_F1 + 1;
 
266
                if (GLWin.keyboard.modifiers == MOD_SHIFT_MASK)
 
267
                        State::Save(slot_number);
 
268
                else
 
269
                        State::Load(slot_number);
 
270
        }
 
271
        else if (key == KEY_F9)
 
272
                Core::SaveScreenShot();
 
273
        else if (key == KEY_F11)
 
274
                State::LoadLastSaved();
 
275
        else if (key == KEY_F12) {
 
276
                if (GLWin.keyboard.modifiers == MOD_SHIFT_MASK)
 
277
                        State::UndoLoadState();
 
278
                else
 
279
                        State::UndoSaveState();
 
280
        }
 
281
}
 
282
 
 
283
static void
 
284
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
 
285
                          uint32_t serial, uint32_t mods_depressed,
 
286
                          uint32_t mods_latched, uint32_t mods_locked,
 
287
                          uint32_t group)
 
288
{
 
289
        xkb_mod_mask_t mask;
 
290
 
 
291
        xkb_state_update_mask(GLWin.keyboard.xkb.state, mods_depressed, mods_latched,
 
292
                              mods_locked, 0, 0, group);
 
293
        mask = xkb_state_serialize_mods(GLWin.keyboard.xkb.state,
 
294
                                        (xkb_state_component)
 
295
                                        (XKB_STATE_DEPRESSED |
 
296
                                         XKB_STATE_LATCHED));
 
297
        GLWin.keyboard.modifiers = 0;
 
298
        if (mask & GLWin.keyboard.xkb.control_mask)
 
299
                GLWin.keyboard.modifiers |= MOD_CONTROL_MASK;
 
300
        if (mask & GLWin.keyboard.xkb.alt_mask)
 
301
                GLWin.keyboard.modifiers |= MOD_ALT_MASK;
 
302
        if (mask & GLWin.keyboard.xkb.shift_mask)
 
303
                GLWin.keyboard.modifiers |= MOD_SHIFT_MASK;
 
304
}
 
305
 
 
306
static const struct wl_keyboard_listener keyboard_listener = {
 
307
        keyboard_handle_keymap,
 
308
        keyboard_handle_enter,
 
309
        keyboard_handle_leave,
 
310
        keyboard_handle_key,
 
311
        keyboard_handle_modifiers,
 
312
};
 
313
 
 
314
static void
 
315
seat_handle_capabilities(void *data, struct wl_seat *seat,
 
316
                         uint32_t caps)
 
317
{
 
318
        struct wl_pointer *wl_pointer = NULL;
 
319
        struct wl_keyboard *wl_keyboard = NULL;
 
320
 
 
321
        if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl_pointer) {
 
322
                wl_pointer = wl_seat_get_pointer(seat);
 
323
                wl_pointer_add_listener(wl_pointer, &pointer_listener, 0);
 
324
        } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl_pointer) {
 
325
                wl_pointer_destroy(wl_pointer);
 
326
                wl_pointer = NULL;
 
327
        }
 
328
 
 
329
        GLWin.pointer.wl_pointer = wl_pointer;
 
330
 
 
331
        if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !wl_keyboard) {
 
332
                wl_keyboard = wl_seat_get_keyboard(seat);
 
333
                wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, 0);
 
334
        } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && wl_keyboard) {
 
335
                wl_keyboard_destroy(wl_keyboard);
 
336
                wl_keyboard = NULL;
 
337
        }
 
338
 
 
339
        GLWin.keyboard.wl_keyboard = wl_keyboard;
 
340
}
 
341
 
 
342
static const struct wl_seat_listener seat_listener = {
 
343
        seat_handle_capabilities,
 
344
};
 
345
 
 
346
static void
 
347
registry_handle_global(void *data, struct wl_registry *registry,
 
348
                       uint32_t name, const char *interface, uint32_t version)
 
349
{
 
350
        if (strcmp(interface, "wl_compositor") == 0) {
 
351
                GLWin.wl_compositor = (wl_compositor *)
 
352
                        wl_registry_bind(registry, name,
 
353
                                         &wl_compositor_interface, 1);
 
354
        } else if (strcmp(interface, "wl_shell") == 0) {
 
355
                GLWin.wl_shell = (wl_shell *) wl_registry_bind(registry, name,
 
356
                                            &wl_shell_interface, 1);
 
357
        } else if (strcmp(interface, "wl_seat") == 0) {
 
358
                GLWin.wl_seat = (wl_seat *) wl_registry_bind(registry, name,
 
359
                                           &wl_seat_interface, 1);
 
360
                wl_seat_add_listener(GLWin.wl_seat, &seat_listener, 0);
 
361
        } else if (strcmp(interface, "wl_shm") == 0) {
 
362
                GLWin.wl_shm = (wl_shm *) wl_registry_bind(registry, name,
 
363
                                          &wl_shm_interface, 1);
 
364
                GLWin.wl_cursor_theme = (wl_cursor_theme *) wl_cursor_theme_load(NULL, 32, GLWin.wl_shm);
 
365
                GLWin.wl_cursor = (wl_cursor *)
 
366
                        wl_cursor_theme_get_cursor(GLWin.wl_cursor_theme, "left_ptr");
 
367
        }
 
368
}
 
369
 
 
370
static void
 
371
registry_handle_global_remove(void *data, struct wl_registry *registry,
 
372
                              uint32_t name)
 
373
{
 
374
}
 
375
 
 
376
static const struct wl_registry_listener registry_listener = {
 
377
        registry_handle_global,
 
378
        registry_handle_global_remove
 
379
};
 
380
 
 
381
bool cWaylandInterface::ServerConnect(void)
 
382
{
 
383
        GLWin.wl_display = wl_display_connect(NULL);
 
384
 
 
385
        if (!GLWin.wl_display)
 
386
                return false;
 
387
 
 
388
        return true;
 
389
}
 
390
 
 
391
bool cWaylandInterface::Initialize(void *config)
 
392
{
 
393
        if (!GLWin.wl_display) {
 
394
                printf("Error: couldn't open wayland display\n");
 
395
                return false;
 
396
        }
 
397
 
 
398
        GLWin.pointer.wl_pointer = NULL;
 
399
        GLWin.keyboard.wl_keyboard = NULL;
 
400
 
 
401
        GLWin.keyboard.xkb.context = xkb_context_new((xkb_context_flags) 0);
 
402
        if (GLWin.keyboard.xkb.context == NULL) {
 
403
                fprintf(stderr, "Failed to create XKB context\n");
 
404
                return NULL;
 
405
        }
 
406
 
 
407
        GLWin.wl_registry = wl_display_get_registry(GLWin.wl_display);
 
408
        wl_registry_add_listener(GLWin.wl_registry,
 
409
                                 &registry_listener, NULL);
 
410
 
 
411
        wl_display_dispatch(GLWin.wl_display);
 
412
 
 
413
        GLWin.wl_cursor_surface =
 
414
                wl_compositor_create_surface(GLWin.wl_compositor);
 
415
 
 
416
        return true;
 
417
}
 
418
 
 
419
void *cWaylandInterface::EGLGetDisplay(void)
 
420
{
 
421
#if HAVE_X11
 
422
        return eglGetDisplay((_XDisplay *) GLWin.wl_display);
 
423
#else
 
424
        return eglGetDisplay(GLWin.wl_display);
 
425
#endif
 
426
}
 
427
 
 
428
void *cWaylandInterface::CreateWindow(void)
 
429
{
 
430
        GLWin.window_size.width = 640;
 
431
        GLWin.window_size.height = 480;
 
432
        GLWin.fullscreen = true;
 
433
        GLWin.frame_drawn = false;
 
434
        GLWin.swap_complete = false;
 
435
 
 
436
        GLWin.wl_surface = wl_compositor_create_surface(GLWin.wl_compositor);
 
437
        GLWin.wl_shell_surface = wl_shell_get_shell_surface(GLWin.wl_shell,
 
438
                                                           GLWin.wl_surface);
 
439
 
 
440
        wl_shell_surface_add_listener(GLWin.wl_shell_surface,
 
441
                                      &shell_surface_listener, 0);
 
442
 
 
443
        GLWin.wl_egl_native = wl_egl_window_create(GLWin.wl_surface,
 
444
                                                   GLWin.window_size.width,
 
445
                                                   GLWin.window_size.height);
 
446
#if HAVE_X11
 
447
        return GLWin.wl_egl_native;
 
448
#else
 
449
        return GLWin.wl_egl_native;
 
450
#endif
 
451
}
 
452
 
 
453
void cWaylandInterface::DestroyWindow(void)
 
454
{
 
455
        wl_egl_window_destroy(GLWin.wl_egl_native);
 
456
 
 
457
        wl_shell_surface_destroy(GLWin.wl_shell_surface);
 
458
        wl_surface_destroy(GLWin.wl_surface);
 
459
 
 
460
        if (GLWin.wl_callback)
 
461
                wl_callback_destroy(GLWin.wl_callback);
 
462
}
 
463
 
 
464
void cWaylandInterface::UpdateFPSDisplay(const char *text)
 
465
{
 
466
        wl_shell_surface_set_title(GLWin.wl_shell_surface, text);
 
467
}
 
468
 
 
469
void cWaylandInterface::ToggleFullscreen(bool fullscreen)
 
470
{
 
471
        toggle_fullscreen(GLWin.fullscreen);
 
472
}