2 * gstvaapiwindow_x11.c - VA/X11 window abstraction
4 * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 * SECTION:gst-vaapi-window-x11
27 #include "gstvaapiwindow_x11.h"
28 #include "gstvaapidisplay_x11.h"
29 #include "gstvaapiutils_x11.h"
32 #include "gstvaapidebug.h"
34 G_DEFINE_TYPE(GstVaapiWindowX11, gst_vaapi_window_x11, GST_VAAPI_TYPE_WINDOW);
36 #define GST_VAAPI_WINDOW_X11_GET_PRIVATE(obj) \
37 (G_TYPE_INSTANCE_GET_PRIVATE((obj), \
38 GST_VAAPI_TYPE_WINDOW_X11, \
39 GstVaapiWindowX11Private))
41 struct _GstVaapiWindowX11Private {
42 GstVaapiDisplay *display;
44 guint create_window : 1;
56 gst_vaapi_window_x11_show(GstVaapiWindow *window)
58 GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
59 Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
65 GST_VAAPI_DISPLAY_LOCK(priv->display);
67 XMapWindow(dpy, priv->xid);
68 if (priv->create_window)
69 x11_wait_event(dpy, priv->xid, MapNotify);
70 has_errors = x11_untrap_errors() != 0;
71 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
75 priv->is_visible = TRUE;
80 gst_vaapi_window_x11_hide(GstVaapiWindow *window)
82 GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
83 Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
86 if (!priv->is_visible)
89 GST_VAAPI_DISPLAY_LOCK(priv->display);
91 XUnmapWindow(dpy, priv->xid);
92 if (priv->create_window)
93 x11_wait_event(dpy, priv->xid, UnmapNotify);
94 has_errors = x11_untrap_errors() != 0;
95 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
99 priv->is_visible = FALSE;
104 gst_vaapi_window_x11_create(GstVaapiWindow *window, guint *width, guint *height)
106 GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
107 Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
110 if (!priv->create_window && priv->xid) {
111 GST_VAAPI_DISPLAY_LOCK(priv->display);
112 ok = x11_get_geometry(dpy, priv->xid, NULL, NULL, width, height);
113 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
117 GST_VAAPI_DISPLAY_LOCK(priv->display);
118 priv->xid = x11_create_window(dpy, *width, *height);
120 XRaiseWindow(dpy, priv->xid);
121 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
122 return priv->xid != None;
126 gst_vaapi_window_x11_destroy(GstVaapiWindow *window)
128 GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
129 Display * const dpy = GST_VAAPI_DISPLAY_XDISPLAY(priv->display);
132 if (priv->create_window) {
133 GST_VAAPI_DISPLAY_LOCK(priv->display);
134 XDestroyWindow(dpy, priv->xid);
135 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
141 g_object_unref(priv->display);
142 priv->display = NULL;
147 gst_vaapi_window_x11_resize(GstVaapiWindow *window, guint width, guint height)
149 GstVaapiWindowX11Private * const priv = GST_VAAPI_WINDOW_X11(window)->priv;
155 GST_VAAPI_DISPLAY_LOCK(priv->display);
158 GST_VAAPI_DISPLAY_XDISPLAY(priv->display),
163 has_errors = x11_untrap_errors() != 0;
164 GST_VAAPI_DISPLAY_UNLOCK(priv->display);
169 gst_vaapi_window_x11_render(
170 GstVaapiWindow *window,
171 GstVaapiSurface *surface,
172 const GstVideoRectangle *src_rect,
173 const GstVideoRectangle *dst_rect,
177 GstVaapiDisplay *display;
178 VASurfaceID surface_id;
181 display = gst_vaapi_surface_get_display(surface);
185 surface_id = gst_vaapi_surface_get_id(surface);
186 if (surface_id == VA_INVALID_ID)
189 GST_VAAPI_DISPLAY_LOCK(display);
190 status = vaPutSurface(
191 GST_VAAPI_DISPLAY_VADISPLAY(display),
193 GST_VAAPI_WINDOW_X11(window)->priv->xid,
203 get_PutSurface_flags_from_GstVaapiSurfaceRenderFlags(flags)
205 GST_VAAPI_DISPLAY_UNLOCK(display);
206 if (!vaapi_check_status(status, "vaPutSurface()"))
213 gst_vaapi_window_x11_finalize(GObject *object)
215 G_OBJECT_CLASS(gst_vaapi_window_x11_parent_class)->finalize(object);
219 gst_vaapi_window_x11_set_property(
226 GstVaapiWindowX11 * const window = GST_VAAPI_WINDOW_X11(object);
230 window->priv->display = g_object_ref(g_value_get_object(value));
233 window->priv->xid = g_value_get_uint(value);
236 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
242 gst_vaapi_window_x11_get_property(
249 GstVaapiWindowX11 * const window = GST_VAAPI_WINDOW_X11(object);
253 g_value_set_object(value, window->priv->display);
256 g_value_set_uint(value, gst_vaapi_window_x11_get_xid(window));
259 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
265 gst_vaapi_window_x11_constructed(GObject *object)
267 GstVaapiWindowX11 * const window = GST_VAAPI_WINDOW_X11(object);
268 GObjectClass *parent_class;
270 window->priv->create_window = window->priv->xid == None;
272 parent_class = G_OBJECT_CLASS(gst_vaapi_window_x11_parent_class);
273 if (parent_class->constructed)
274 parent_class->constructed(object);
278 gst_vaapi_window_x11_class_init(GstVaapiWindowX11Class *klass)
280 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
281 GstVaapiWindowClass * const window_class = GST_VAAPI_WINDOW_CLASS(klass);
283 g_type_class_add_private(klass, sizeof(GstVaapiWindowX11Private));
285 object_class->finalize = gst_vaapi_window_x11_finalize;
286 object_class->set_property = gst_vaapi_window_x11_set_property;
287 object_class->get_property = gst_vaapi_window_x11_get_property;
288 object_class->constructed = gst_vaapi_window_x11_constructed;
290 window_class->create = gst_vaapi_window_x11_create;
291 window_class->destroy = gst_vaapi_window_x11_destroy;
292 window_class->show = gst_vaapi_window_x11_show;
293 window_class->hide = gst_vaapi_window_x11_hide;
294 window_class->resize = gst_vaapi_window_x11_resize;
295 window_class->render = gst_vaapi_window_x11_render;
298 * GstVaapiWindowX11:display:
300 * The #GstVaapiDisplay this window is bound to
302 g_object_class_install_property
305 g_param_spec_object("display",
307 "The GstVaapiDisplay this window is bound to",
308 GST_VAAPI_TYPE_DISPLAY,
309 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
312 * GstVaapiWindowX11:xid:
314 * The underlying X11 #Window XID.
316 g_object_class_install_property
319 g_param_spec_uint("xid",
321 "The underlying X11 window id",
323 G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
327 gst_vaapi_window_x11_init(GstVaapiWindowX11 *window)
329 GstVaapiWindowX11Private *priv = GST_VAAPI_WINDOW_X11_GET_PRIVATE(window);
332 priv->display = NULL;
334 priv->create_window = TRUE;
335 priv->is_visible = FALSE;
339 * gst_vaapi_window_x11_new:
340 * @display: a #GstVaapiDisplay
341 * @width: the requested window width, in pixels
342 * @height: the requested windo height, in pixels
344 * Creates a window with the specified @width and @height. The window
345 * will be attached to the @display and remains invisible to the user
346 * until gst_vaapi_window_show() is called.
348 * Return value: the newly allocated #GstVaapiWindow object
351 gst_vaapi_window_x11_new(GstVaapiDisplay *display, guint width, guint height)
353 GST_DEBUG("new window, size %ux%u", width, height);
355 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
356 g_return_val_if_fail(width > 0, NULL);
357 g_return_val_if_fail(height > 0, NULL);
359 return g_object_new(GST_VAAPI_TYPE_WINDOW_X11,
367 * gst_vaapi_window_x11_new_with_xid:
368 * @display: a #GstVaapiDisplay
369 * @xid: an X11 #Window id
371 * Creates a #GstVaapiWindow using the X11 #Window @xid. The caller
372 * still owns the window and must call XDestroyWindow() when all
373 * #GstVaapiWindow references are released. Doing so too early can
374 * yield undefined behaviour.
376 * Return value: the newly allocated #GstVaapiWindow object
379 gst_vaapi_window_x11_new_with_xid(GstVaapiDisplay *display, Window xid)
381 GST_DEBUG("new window from xid 0x%08x", xid);
383 g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
384 g_return_val_if_fail(xid != None, NULL);
386 return g_object_new(GST_VAAPI_TYPE_WINDOW_X11,
393 * gst_vaapi_window_x11_get_xid:
394 * @window: a #GstVaapiWindowX11
396 * Returns the underlying X11 #Window that was created by
397 * gst_vaapi_window_x11_new() or that was bound with
398 * gst_vaapi_window_x11_new_with_xid().
400 * Return value: the underlying X11 #Window bound to @window.
403 gst_vaapi_window_x11_get_xid(GstVaapiWindowX11 *window)
405 g_return_val_if_fail(GST_VAAPI_WINDOW_X11(window), None);
407 return window->priv->xid;