Add display size accessors.
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapidisplay_x11.c
1 /*
2  *  gstvaapidisplay_x11.c - VA/X11 display abstraction
3  *
4  *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
5  *
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.
10  *
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.
15  *
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
19  */
20
21 /**
22  * SECTION:gst-vaapi-display-x11
23  * @short_description:
24  */
25
26 #include "config.h"
27 #include "gstvaapiutils.h"
28 #include "gstvaapidisplay_x11.h"
29
30 #define DEBUG 1
31 #include "gstvaapidebug.h"
32
33 G_DEFINE_TYPE(GstVaapiDisplayX11,
34               gst_vaapi_display_x11,
35               GST_VAAPI_TYPE_DISPLAY);
36
37 #define GST_VAAPI_DISPLAY_X11_GET_PRIVATE(obj)                  \
38     (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
39                                  GST_VAAPI_TYPE_DISPLAY_X11,    \
40                                  GstVaapiDisplayX11Private))
41
42 struct _GstVaapiDisplayX11Private {
43     gboolean    create_display;
44     gchar      *display_name;
45     Display    *x11_display;
46     int         x11_screen;
47     VADisplay  *va_display;
48 };
49
50 enum {
51     PROP_0,
52
53     PROP_DISPLAY_NAME,
54     PROP_X11_DISPLAY
55 };
56
57 static void
58 gst_vaapi_display_x11_finalize(GObject *object)
59 {
60     G_OBJECT_CLASS(gst_vaapi_display_x11_parent_class)->finalize(object);
61 }
62
63 static void
64 set_display_name(GstVaapiDisplayX11 *display, const gchar *display_name)
65 {
66     GstVaapiDisplayX11Private * const priv = display->priv;
67
68     g_free(priv->display_name);
69
70     if (display_name)
71         priv->display_name = g_strdup(display_name);
72     else
73         priv->display_name = NULL;
74 }
75
76 static void
77 gst_vaapi_display_x11_set_property(
78     GObject      *object,
79     guint         prop_id,
80     const GValue *value,
81     GParamSpec   *pspec
82 )
83 {
84     GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
85
86     switch (prop_id) {
87     case PROP_DISPLAY_NAME:
88         set_display_name(display, g_value_get_string(value));
89         break;
90     case PROP_X11_DISPLAY:
91         display->priv->x11_display = g_value_get_pointer(value);
92         break;
93     default:
94         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
95         break;
96     }
97 }
98
99 static void
100 gst_vaapi_display_x11_get_property(
101     GObject    *object,
102     guint       prop_id,
103     GValue     *value,
104     GParamSpec *pspec
105 )
106 {
107     GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
108
109     switch (prop_id) {
110     case PROP_DISPLAY_NAME:
111         g_value_set_string(value, display->priv->display_name);
112         break;
113     case PROP_X11_DISPLAY:
114         g_value_set_pointer(value, gst_vaapi_display_x11_get_display(display));
115         break;
116     default:
117         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
118         break;
119     }
120 }
121
122 static void
123 gst_vaapi_display_x11_constructed(GObject *object)
124 {
125     GstVaapiDisplayX11 * const display = GST_VAAPI_DISPLAY_X11(object);
126     GObjectClass *parent_class;
127
128     display->priv->create_display = display->priv->x11_display == NULL;
129
130     /* Reset display-name if the user provided his own X11 display */
131     if (!display->priv->create_display)
132         set_display_name(display, XDisplayString(display->priv->x11_display));
133
134     parent_class = G_OBJECT_CLASS(gst_vaapi_display_x11_parent_class);
135     if (parent_class->constructed)
136         parent_class->constructed(object);
137 }
138
139 static gboolean
140 gst_vaapi_display_x11_open_display(GstVaapiDisplay *display)
141 {
142     GstVaapiDisplayX11Private * const priv =
143         GST_VAAPI_DISPLAY_X11(display)->priv;
144
145     /* XXX: maintain an X11 display cache */
146     if (!priv->x11_display && priv->create_display)
147         priv->x11_display = XOpenDisplay(priv->display_name);
148     if (!priv->x11_display)
149         return FALSE;
150
151     priv->x11_screen = DefaultScreen(priv->x11_display);
152     priv->va_display = vaGetDisplay(priv->x11_display);
153     return priv->va_display != NULL;
154 }
155
156 static void
157 gst_vaapi_display_x11_close_display(GstVaapiDisplay *display)
158 {
159     GstVaapiDisplayX11Private * const priv =
160         GST_VAAPI_DISPLAY_X11(display)->priv;
161
162     if (priv->x11_display) {
163         if (priv->create_display)
164             XCloseDisplay(priv->x11_display);
165         priv->x11_display = NULL;
166     }
167
168     if (priv->display_name) {
169         g_free(priv->display_name);
170         priv->display_name = NULL;
171     }
172
173     priv->va_display = NULL;
174 }
175
176 static VADisplay
177 gst_vaapi_display_x11_get_va_display(GstVaapiDisplay *display)
178 {
179     return GST_VAAPI_DISPLAY_X11(display)->priv->va_display;
180 }
181
182 static void
183 gst_vaapi_display_x11_get_size(
184     GstVaapiDisplay *display,
185     guint           *pwidth,
186     guint           *pheight
187 )
188 {
189     GstVaapiDisplayX11Private * const priv = GST_VAAPI_DISPLAY_X11(display)->priv;
190
191     if (!priv->x11_display)
192         return;
193
194     if (pwidth)
195         *pwidth = DisplayWidth(priv->x11_display, priv->x11_screen);
196
197     if (pheight)
198         *pheight = DisplayHeight(priv->x11_display, priv->x11_screen);
199 }
200
201 static void
202 gst_vaapi_display_x11_class_init(GstVaapiDisplayX11Class *klass)
203 {
204     GObjectClass * const object_class = G_OBJECT_CLASS(klass);
205     GstVaapiDisplayClass * const dpy_class = GST_VAAPI_DISPLAY_CLASS(klass);
206
207     g_type_class_add_private(klass, sizeof(GstVaapiDisplayX11Private));
208
209     object_class->finalize      = gst_vaapi_display_x11_finalize;
210     object_class->set_property  = gst_vaapi_display_x11_set_property;
211     object_class->get_property  = gst_vaapi_display_x11_get_property;
212     object_class->constructed   = gst_vaapi_display_x11_constructed;
213
214     dpy_class->open_display     = gst_vaapi_display_x11_open_display;
215     dpy_class->close_display    = gst_vaapi_display_x11_close_display;
216     dpy_class->get_display      = gst_vaapi_display_x11_get_va_display;
217     dpy_class->get_size         = gst_vaapi_display_x11_get_size;
218
219     /**
220      * GstVaapiDisplayX11:x11-display:
221      *
222      * The X11 #Display that was created by gst_vaapi_display_x11_new()
223      * or that was bound from gst_vaapi_display_x11_new_with_display().
224      */
225     g_object_class_install_property
226         (object_class,
227          PROP_X11_DISPLAY,
228          g_param_spec_pointer("x11-display",
229                               "X11 display",
230                               "X11 display",
231                               G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
232
233     /**
234      * GstVaapiDisplayX11:display-name:
235      *
236      * The X11 display name.
237      */
238     g_object_class_install_property
239         (object_class,
240          PROP_DISPLAY_NAME,
241          g_param_spec_string("display-name",
242                              "X11 display name",
243                              "X11 display name",
244                              NULL,
245                              G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
246 }
247
248 static void
249 gst_vaapi_display_x11_init(GstVaapiDisplayX11 *display)
250 {
251     GstVaapiDisplayX11Private *priv = GST_VAAPI_DISPLAY_X11_GET_PRIVATE(display);
252
253     display->priv        = priv;
254     priv->create_display = TRUE;
255     priv->x11_display    = NULL;
256     priv->x11_screen     = 0;
257     priv->display_name   = NULL;
258 }
259
260 /**
261  * gst_vaapi_display_x11_new:
262  * @display_name: the X11 display name
263  *
264  * Opens an X11 #Display using @display_name and returns a newly
265  * allocated #GstVaapiDisplay object. The X11 display will be cloed
266  * when the reference count of the object reaches zero.
267  *
268  * Return value: a newly allocated #GstVaapiDisplay object
269  */
270 GstVaapiDisplay *
271 gst_vaapi_display_x11_new(const gchar *display_name)
272 {
273     return g_object_new(GST_VAAPI_TYPE_DISPLAY_X11,
274                         "display-name", display_name,
275                         NULL);
276 }
277
278 /**
279  * gst_vaapi_display_x11_new_with_display:
280  * @x11_display: an X11 #Display
281  *
282  * Creates a #GstVaapiDisplay based on the X11 @x11_display
283  * display. The caller still owns the display and must call
284  * XCloseDisplay() when all #GstVaapiDisplay references are
285  * released. Doing so too early can yield undefined behaviour.
286  *
287  * Return value: a newly allocated #GstVaapiDisplay object
288  */
289 GstVaapiDisplay *
290 gst_vaapi_display_x11_new_with_display(Display *x11_display)
291 {
292     return g_object_new(GST_VAAPI_TYPE_DISPLAY_X11,
293                         "x11-display", x11_display,
294                         NULL);
295 }
296
297 /**
298  * gst_vaapi_display_x11_get_display:
299  * @display: a #GstVaapiDisplayX11
300  *
301  * Returns the underlying X11 #Display that was created by
302  * gst_vaapi_display_x11_new() or that was bound from
303  * gst_vaapi_display_x11_new_with_display().
304  *
305  * Return value: the X11 #Display attached to @display
306  */
307 Display *
308 gst_vaapi_display_x11_get_display(GstVaapiDisplayX11 *display)
309 {
310     g_return_val_if_fail(GST_VAAPI_IS_DISPLAY_X11(display), NULL);
311
312     return display->priv->x11_display;
313 }