1 /*
2 * GStreamer
3 * Copyright (C) 2010 Intel Corporation.
4 * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Authors:
22 * Matthew Allum
23 * Robert Bragg
24 * Kristian Høgsberg
25 */
26
27 /* code originally from clutter's wayland backend found here
28 * http://git.gnome.org/browse/clutter/tree/clutter/wayland/clutter-event-wayland.c
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <wayland-client.h>
38 #include <gst/gst.h>
39
40 #include "wayland_event_source.h"
41
42 #define GST_CAT_DEFAULT gst_gl_wayland_event_source_debug
43 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
44
45 static void
init_debug(void)46 init_debug (void)
47 {
48 static gsize _debug;
49
50 if (g_once_init_enter (&_debug)) {
51 GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "glwaylandeventsource", 0,
52 "OpenGL Wayland event source");
53 g_once_init_leave (&_debug, 1);
54 }
55 }
56
57 typedef struct _WaylandEventSource
58 {
59 GSource source;
60 GPollFD pfd;
61 uint32_t mask;
62 struct wl_display *display;
63 struct wl_event_queue *queue;
64 gboolean reading;
65 } WaylandEventSource;
66
67 static gboolean
wayland_event_source_prepare(GSource * base,gint * timeout)68 wayland_event_source_prepare (GSource * base, gint * timeout)
69 {
70 WaylandEventSource *source = (WaylandEventSource *) base;
71
72 *timeout = -1;
73
74 /* we may be called multiple times for prepare */
75 if (source->reading)
76 wl_display_cancel_read (source->display);
77
78 if (source->queue) {
79 if (wl_display_prepare_read_queue (source->display, source->queue) != 0)
80 return TRUE;
81 } else {
82 if (wl_display_prepare_read (source->display) != 0)
83 return TRUE;
84 }
85
86 source->reading = TRUE;
87
88 /* FIXME: this may return EAGAIN if the fd is full */
89 if (wl_display_flush (source->display) < 0)
90 g_critical ("Failed to flush Wayland connection\n");
91
92 return FALSE;
93 }
94
95 static gboolean
wayland_event_source_check(GSource * base)96 wayland_event_source_check (GSource * base)
97 {
98 WaylandEventSource *source = (WaylandEventSource *) base;
99
100 source->reading = FALSE;
101
102 if (source->pfd.revents & G_IO_IN) {
103 if (wl_display_read_events (source->display) == 0)
104 return TRUE;
105 } else {
106 wl_display_cancel_read (source->display);
107 }
108
109 return FALSE;
110 }
111
112 static gboolean
wayland_event_source_dispatch(GSource * base,GSourceFunc callback,gpointer data)113 wayland_event_source_dispatch (GSource * base,
114 GSourceFunc callback, gpointer data)
115 {
116 WaylandEventSource *source = (WaylandEventSource *) base;
117
118 if (source->queue) {
119 wl_display_dispatch_queue_pending (source->display, source->queue);
120 } else {
121 wl_display_dispatch_pending (source->display);
122 }
123 source->pfd.revents = 0;
124
125 if (callback)
126 callback (data);
127
128 return TRUE;
129 }
130
131 static void
wayland_event_source_finalize(GSource * base)132 wayland_event_source_finalize (GSource * base)
133 {
134 WaylandEventSource *source = (WaylandEventSource *) base;
135
136 if (source->reading) {
137 wl_display_cancel_read (source->display);
138 }
139 source->reading = FALSE;
140 }
141
142 static GSourceFuncs wayland_event_source_funcs = {
143 wayland_event_source_prepare,
144 wayland_event_source_check,
145 wayland_event_source_dispatch,
146 wayland_event_source_finalize
147 };
148
149 GSource *
wayland_event_source_new(struct wl_display * display,struct wl_event_queue * queue)150 wayland_event_source_new (struct wl_display *display,
151 struct wl_event_queue *queue)
152 {
153 WaylandEventSource *source;
154
155 init_debug ();
156
157 source = (WaylandEventSource *)
158 g_source_new (&wayland_event_source_funcs, sizeof (WaylandEventSource));
159 source->display = display;
160 source->queue = queue;
161 source->pfd.fd = wl_display_get_fd (display);
162 source->pfd.events = G_IO_IN | G_IO_ERR;
163 g_source_add_poll (&source->source, &source->pfd);
164
165 return &source->source;
166 }
167