1 /*
2 * GStreamer
3 * Copyright (C) 2013 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 /**
22 * SECTION:gstgldisplay_wayland
23 * @short_description: Wayland display connection
24 * @title: GstGLDisplayWayland
25 * @see_also: #GstGLDisplay
26 *
27 * #GstGLDisplayWayland represents a connection to a Wayland `wl_display` handle
28 * created internally (gst_gl_display_wayland_new()) or wrapped by the application
29 * (gst_gl_display_wayland_new_with_display())
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "gstgldisplay_wayland.h"
37
38 GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
39 #define GST_CAT_DEFAULT gst_gl_display_debug
40
41 /* We can't define these in the public struct, or we'd break ABI */
42 typedef struct _GstGLDisplayWaylandPrivate
43 {
44 gint dummy;
45 } GstGLDisplayWaylandPrivate;
46
47 G_DEFINE_TYPE_WITH_PRIVATE (GstGLDisplayWayland, gst_gl_display_wayland,
48 GST_TYPE_GL_DISPLAY);
49
50 static void gst_gl_display_wayland_finalize (GObject * object);
51 static guintptr gst_gl_display_wayland_get_handle (GstGLDisplay * display);
52
53 static void
gst_gl_display_wayland_class_init(GstGLDisplayWaylandClass * klass)54 gst_gl_display_wayland_class_init (GstGLDisplayWaylandClass * klass)
55 {
56 GST_GL_DISPLAY_CLASS (klass)->get_handle =
57 GST_DEBUG_FUNCPTR (gst_gl_display_wayland_get_handle);
58
59 G_OBJECT_CLASS (klass)->finalize = gst_gl_display_wayland_finalize;
60 }
61
62 static void
gst_gl_display_wayland_init(GstGLDisplayWayland * display_wayland)63 gst_gl_display_wayland_init (GstGLDisplayWayland * display_wayland)
64 {
65 GstGLDisplay *display = (GstGLDisplay *) display_wayland;
66
67 display->type = GST_GL_DISPLAY_TYPE_WAYLAND;
68 display_wayland->foreign_display = FALSE;
69 }
70
71 static void
gst_gl_display_wayland_finalize(GObject * object)72 gst_gl_display_wayland_finalize (GObject * object)
73 {
74 GstGLDisplayWayland *display_wayland = GST_GL_DISPLAY_WAYLAND (object);
75
76 /* Cause eglTerminate() to occur before wl_display_disconnect()
77 * https://bugzilla.gnome.org/show_bug.cgi?id=787293 */
78 g_object_set_data (object, "gst.gl.display.egl", NULL);
79
80 if (!display_wayland->foreign_display && display_wayland->display) {
81 wl_display_flush (display_wayland->display);
82 wl_display_disconnect (display_wayland->display);
83 }
84
85 G_OBJECT_CLASS (gst_gl_display_wayland_parent_class)->finalize (object);
86 }
87
88 /**
89 * gst_gl_display_wayland_new:
90 * @name: (allow-none): a display name
91 *
92 * Create a new #GstGLDisplayWayland from the wayland display name. See `wl_display_connect`()
93 * for details on what is a valid name.
94 *
95 * Returns: (transfer full): a new #GstGLDisplayWayland or %NULL
96 */
97 GstGLDisplayWayland *
gst_gl_display_wayland_new(const gchar * name)98 gst_gl_display_wayland_new (const gchar * name)
99 {
100 GstGLDisplayWayland *ret;
101
102 GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
103
104 ret = g_object_new (GST_TYPE_GL_DISPLAY_WAYLAND, NULL);
105 gst_object_ref_sink (ret);
106 ret->display = wl_display_connect (name);
107
108 if (!ret->display) {
109 if (name != NULL) {
110 GST_ERROR ("Failed to open Wayland display connection with name \'%s\'",
111 name);
112 } else {
113 GST_INFO ("Failed to open Wayland display connection.");
114 }
115 gst_object_unref (ret);
116 return NULL;
117 }
118
119 return ret;
120 }
121
122 /**
123 * gst_gl_display_wayland_new_with_display:
124 * @display: an existing, wayland display
125 *
126 * Creates a new display connection from a wl_display Display.
127 *
128 * Returns: (transfer full): a new #GstGLDisplayWayland
129 */
130 GstGLDisplayWayland *
gst_gl_display_wayland_new_with_display(struct wl_display * display)131 gst_gl_display_wayland_new_with_display (struct wl_display * display)
132 {
133 GstGLDisplayWayland *ret;
134
135 g_return_val_if_fail (display != NULL, NULL);
136
137 GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay");
138
139 ret = g_object_new (GST_TYPE_GL_DISPLAY_WAYLAND, NULL);
140 gst_object_ref_sink (ret);
141
142 ret->display = display;
143 ret->foreign_display = TRUE;
144
145 return ret;
146 }
147
148 static guintptr
gst_gl_display_wayland_get_handle(GstGLDisplay * display)149 gst_gl_display_wayland_get_handle (GstGLDisplay * display)
150 {
151 return (guintptr) GST_GL_DISPLAY_WAYLAND (display)->display;
152 }
153