• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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