• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GStreamer
3  * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdint.h>
26 #include <stdlib.h>
27 
28 #include <gst/vulkan/gstvkapi.h>
29 
30 #include <gst/vulkan/xcb/gstvkdisplay_xcb.h>
31 #include "gstvkwindow_xcb.h"
32 
33 #include "xcb_event_source.h"
34 
35 static gint
_compare_xcb_window(GstVulkanWindowXCB * window_xcb,xcb_window_t * window_id)36 _compare_xcb_window (GstVulkanWindowXCB * window_xcb, xcb_window_t * window_id)
37 {
38   gint ret;
39 
40   g_return_val_if_fail (GST_IS_VULKAN_WINDOW_XCB (window_xcb), -1);
41   g_return_val_if_fail (window_id != 0, -1);
42 
43   ret = window_xcb->win_id - *window_id;
44 
45   return ret;
46 }
47 
48 static GstVulkanWindowXCB *
_find_window_from_xcb_window(GstVulkanDisplayXCB * display_xcb,xcb_window_t window_id)49 _find_window_from_xcb_window (GstVulkanDisplayXCB * display_xcb,
50     xcb_window_t window_id)
51 {
52   GstVulkanDisplay *display = GST_VULKAN_DISPLAY (display_xcb);
53 
54   if (!window_id)
55     return NULL;
56 
57   return (GstVulkanWindowXCB *) gst_vulkan_display_find_window (display,
58       &window_id, (GCompareFunc) _compare_xcb_window);
59 }
60 
61 static GstVulkanWindowXCB *
_window_from_event(GstVulkanDisplayXCB * display_xcb,xcb_generic_event_t * event)62 _window_from_event (GstVulkanDisplayXCB * display_xcb,
63     xcb_generic_event_t * event)
64 {
65   uint8_t event_code = event->response_type & 0x7f;
66 
67   switch (event_code) {
68 /* *INDENT-OFF* */
69 #define WIN_FROM_EVENT(case_val,event_type,window_field) \
70     case case_val:{ \
71       event_type * real_event = (event_type *) event; \
72       return _find_window_from_xcb_window (display_xcb, real_event->window_field); \
73     }
74     WIN_FROM_EVENT (XCB_CLIENT_MESSAGE, xcb_client_message_event_t, window)
75     WIN_FROM_EVENT (XCB_CONFIGURE_NOTIFY, xcb_configure_notify_event_t, window)
76     WIN_FROM_EVENT (XCB_EXPOSE, xcb_expose_event_t, window)
77     WIN_FROM_EVENT (XCB_KEY_PRESS, xcb_key_press_event_t, event)
78     WIN_FROM_EVENT (XCB_KEY_RELEASE, xcb_key_release_event_t, event)
79     WIN_FROM_EVENT (XCB_BUTTON_PRESS, xcb_button_press_event_t, event)
80     WIN_FROM_EVENT (XCB_BUTTON_RELEASE, xcb_button_release_event_t, event)
81     WIN_FROM_EVENT (XCB_MOTION_NOTIFY, xcb_motion_notify_event_t, event)
82 #undef WIN_FROM_EVENT
83 /* *INDENT-ON* */
84     default:
85       return NULL;
86   }
87 }
88 
89 G_GNUC_INTERNAL
90     extern gboolean
91 gst_vulkan_window_xcb_handle_event (GstVulkanWindowXCB * window_xcb,
92     xcb_generic_event_t * event);
93 
94 static gboolean
_xcb_handle_event(GstVulkanDisplayXCB * display_xcb)95 _xcb_handle_event (GstVulkanDisplayXCB * display_xcb)
96 {
97   xcb_connection_t *connection =
98       GST_VULKAN_DISPLAY_XCB_CONNECTION (display_xcb);
99   xcb_generic_event_t *event;
100   gboolean ret = TRUE;
101 
102   while (ret && (event = xcb_poll_for_event (connection))) {
103     GstVulkanWindowXCB *window_xcb;
104 
105     window_xcb = _window_from_event (display_xcb, event);
106     if (window_xcb) {
107       ret = gst_vulkan_window_xcb_handle_event (window_xcb, event);
108       gst_object_unref (window_xcb);
109     }
110 
111     g_free (event);
112   }
113 
114   return ret;
115 }
116 
117 typedef struct _XCBEventSource
118 {
119   GSource source;
120   GPollFD pfd;
121   uint32_t mask;
122   GstVulkanDisplayXCB *display_xcb;
123 } XCBEventSource;
124 
125 static gboolean
xcb_event_source_prepare(GSource * base,gint * timeout)126 xcb_event_source_prepare (GSource * base, gint * timeout)
127 {
128   *timeout = -1;
129   return FALSE;
130 }
131 
132 static gboolean
xcb_event_source_check(GSource * base)133 xcb_event_source_check (GSource * base)
134 {
135   XCBEventSource *source = (XCBEventSource *) base;
136   gboolean retval;
137 
138   retval = source->pfd.revents;
139 
140   return retval;
141 }
142 
143 static gboolean
xcb_event_source_dispatch(GSource * base,GSourceFunc callback,gpointer data)144 xcb_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
145 {
146   XCBEventSource *source = (XCBEventSource *) base;
147 
148   gboolean ret = _xcb_handle_event (source->display_xcb);
149 
150   if (callback)
151     callback (data);
152 
153   return ret;
154 }
155 
156 static GSourceFuncs xcb_event_source_funcs = {
157   xcb_event_source_prepare,
158   xcb_event_source_check,
159   xcb_event_source_dispatch,
160   NULL
161 };
162 
163 GSource *
xcb_event_source_new(GstVulkanDisplayXCB * display_xcb)164 xcb_event_source_new (GstVulkanDisplayXCB * display_xcb)
165 {
166   xcb_connection_t *connection;
167   XCBEventSource *source;
168 
169   connection = GST_VULKAN_DISPLAY_XCB_CONNECTION (display_xcb);
170   g_return_val_if_fail (connection != NULL, NULL);
171 
172   source = (XCBEventSource *)
173       g_source_new (&xcb_event_source_funcs, sizeof (XCBEventSource));
174   source->display_xcb = display_xcb;
175   source->pfd.fd = xcb_get_file_descriptor (connection);
176   source->pfd.events = G_IO_IN | G_IO_ERR;
177   g_source_add_poll (&source->source, &source->pfd);
178 
179   return &source->source;
180 }
181