700ea6ebb3be8f6a63ec954b0d7464ce2a94b36e
[platform/upstream/gstreamer-vaapi.git] / gst-libs / gst / vaapi / gstvaapiwindow.c
1 /*
2  *  gstvaapiwindow.c - VA window abstraction
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2011-2013 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24
25 /**
26  * SECTION:gstvaapiwindow
27  * @short_description: VA window abstraction
28  */
29
30 #include "sysdeps.h"
31 #include "gstvaapiwindow.h"
32 #include "gstvaapiwindow_priv.h"
33 #include "gstvaapisurface_priv.h"
34
35 #define DEBUG 1
36 #include "gstvaapidebug.h"
37
38 /* Ensure those symbols are actually defined in the resulting libraries */
39 #undef gst_vaapi_window_ref
40 #undef gst_vaapi_window_unref
41 #undef gst_vaapi_window_replace
42
43 static void
44 gst_vaapi_window_ensure_size(GstVaapiWindow *window)
45 {
46     const GstVaapiWindowClass * const klass =
47         GST_VAAPI_WINDOW_GET_CLASS(window);
48
49     if (!window->check_geometry)
50         return;
51
52     if (klass->get_geometry)
53         klass->get_geometry(window, NULL, NULL,
54             &window->width, &window->height);
55
56     window->check_geometry = FALSE;
57     window->is_fullscreen  = (window->width  == window->display_width &&
58                               window->height == window->display_height);
59 }
60
61 static gboolean
62 gst_vaapi_window_create(GstVaapiWindow *window, guint width, guint height)
63 {
64     gst_vaapi_display_get_size(
65         GST_VAAPI_OBJECT_DISPLAY(window),
66         &window->display_width,
67         &window->display_height
68     );
69
70     if (!GST_VAAPI_WINDOW_GET_CLASS(window)->create(window, &width, &height))
71         return FALSE;
72
73     if (width != window->width || height != window->height) {
74         GST_DEBUG("backend resized window to %ux%u", width, height);
75         window->width  = width;
76         window->height = height;
77     }
78     return TRUE;
79 }
80
81 GstVaapiWindow *
82 gst_vaapi_window_new(const GstVaapiWindowClass *window_class,
83     GstVaapiDisplay *display, guint width, guint height)
84 {
85     GstVaapiWindow *window;
86
87     g_return_val_if_fail(width  > 0, NULL);
88     g_return_val_if_fail(height > 0, NULL);
89
90     window = gst_vaapi_object_new(GST_VAAPI_OBJECT_CLASS(window_class),
91         display);
92     if (!window)
93         return NULL;
94
95     GST_VAAPI_OBJECT_ID(window) = 0;
96     if (!gst_vaapi_window_create(window, width, height))
97         goto error;
98     return window;
99
100 error:
101     gst_vaapi_window_unref_internal(window);
102     return NULL;
103 }
104
105 GstVaapiWindow *
106 gst_vaapi_window_new_from_native(const GstVaapiWindowClass *window_class,
107     GstVaapiDisplay *display, gpointer native_window)
108 {
109     GstVaapiWindow *window;
110
111     window = gst_vaapi_object_new(GST_VAAPI_OBJECT_CLASS(window_class),
112         display);
113     if (!window)
114         return NULL;
115
116     GST_VAAPI_OBJECT_ID(window) = GPOINTER_TO_SIZE(native_window);
117     window->use_foreign_window = TRUE;
118     if (!gst_vaapi_window_create(window, 0, 0))
119         goto error;
120     return window;
121
122 error:
123     gst_vaapi_window_unref_internal(window);
124     return NULL;
125 }
126
127 /**
128  * gst_vaapi_window_ref:
129  * @window: a #GstVaapiWindow
130  *
131  * Atomically increases the reference count of the given @window by one.
132  *
133  * Returns: The same @window argument
134  */
135 GstVaapiWindow *
136 gst_vaapi_window_ref(GstVaapiWindow *window)
137 {
138     return gst_vaapi_window_ref_internal(window);
139 }
140
141 /**
142  * gst_vaapi_window_unref:
143  * @window: a #GstVaapiWindow
144  *
145  * Atomically decreases the reference count of the @window by one. If
146  * the reference count reaches zero, the window will be free'd.
147  */
148 void
149 gst_vaapi_window_unref(GstVaapiWindow *window)
150 {
151     gst_vaapi_window_unref_internal(window);
152 }
153
154 /**
155  * gst_vaapi_window_replace:
156  * @old_window_ptr: a pointer to a #GstVaapiWindow
157  * @new_window: a #GstVaapiWindow
158  *
159  * Atomically replaces the window window held in @old_window_ptr with
160  * @new_window. This means that @old_window_ptr shall reference a
161  * valid window. However, @new_window can be NULL.
162  */
163 void
164 gst_vaapi_window_replace(GstVaapiWindow **old_window_ptr,
165     GstVaapiWindow *new_window)
166 {
167     gst_vaapi_window_replace_internal(old_window_ptr, new_window);
168 }
169
170 /**
171  * gst_vaapi_window_get_display:
172  * @window: a #GstVaapiWindow
173  *
174  * Returns the #GstVaapiDisplay this @window is bound to.
175  *
176  * Return value: the parent #GstVaapiDisplay object
177  */
178 GstVaapiDisplay *
179 gst_vaapi_window_get_display(GstVaapiWindow *window)
180 {
181     g_return_val_if_fail(window != NULL, NULL);
182
183     return GST_VAAPI_OBJECT_DISPLAY(window);
184 }
185
186 /**
187  * gst_vaapi_window_show:
188  * @window: a #GstVaapiWindow
189  *
190  * Flags a window to be displayed. Any window that is not shown will
191  * not appear on the screen.
192  */
193 void
194 gst_vaapi_window_show(GstVaapiWindow *window)
195 {
196     g_return_if_fail(window != NULL);
197
198     GST_VAAPI_WINDOW_GET_CLASS(window)->show(window);
199     window->check_geometry = TRUE;
200 }
201
202 /**
203  * gst_vaapi_window_hide:
204  * @window: a #GstVaapiWindow
205  *
206  * Reverses the effects of gst_vaapi_window_show(), causing the window
207  * to be hidden (invisible to the user).
208  */
209 void
210 gst_vaapi_window_hide(GstVaapiWindow *window)
211 {
212     g_return_if_fail(window != NULL);
213
214     GST_VAAPI_WINDOW_GET_CLASS(window)->hide(window);
215 }
216
217 /**
218  * gst_vaapi_window_get_fullscreen:
219  * @window: a #GstVaapiWindow
220  *
221  * Retrieves whether the @window is fullscreen or not
222  *
223  * Return value: %TRUE if the window is fullscreen
224  */
225 gboolean
226 gst_vaapi_window_get_fullscreen(GstVaapiWindow *window)
227 {
228     g_return_val_if_fail(window != NULL, FALSE);
229
230     gst_vaapi_window_ensure_size(window);
231
232     return window->is_fullscreen;
233 }
234
235 /**
236  * gst_vaapi_window_set_fullscreen:
237  * @window: a #GstVaapiWindow
238  * @fullscreen: %TRUE to request window to get fullscreen
239  *
240  * Requests to place the @window in fullscreen or unfullscreen states.
241  */
242 void
243 gst_vaapi_window_set_fullscreen(GstVaapiWindow *window, gboolean fullscreen)
244 {
245     const GstVaapiWindowClass *klass;
246
247     g_return_if_fail(window != NULL);
248
249     klass = GST_VAAPI_WINDOW_GET_CLASS(window);
250
251     if (window->is_fullscreen != fullscreen &&
252         klass->set_fullscreen && klass->set_fullscreen(window, fullscreen)) {
253         window->is_fullscreen  = fullscreen;
254         window->check_geometry = TRUE;
255     }
256 }
257
258 /**
259  * gst_vaapi_window_get_width:
260  * @window: a #GstVaapiWindow
261  *
262  * Retrieves the width of a #GstVaapiWindow.
263  *
264  * Return value: the width of the @window, in pixels
265  */
266 guint
267 gst_vaapi_window_get_width(GstVaapiWindow *window)
268 {
269     g_return_val_if_fail(window != NULL, 0);
270
271     gst_vaapi_window_ensure_size(window);
272
273     return window->width;
274 }
275
276 /**
277  * gst_vaapi_window_get_height:
278  * @window: a #GstVaapiWindow
279  *
280  * Retrieves the height of a #GstVaapiWindow
281  *
282  * Return value: the height of the @window, in pixels
283  */
284 guint
285 gst_vaapi_window_get_height(GstVaapiWindow *window)
286 {
287     g_return_val_if_fail(window != NULL, 0);
288
289     gst_vaapi_window_ensure_size(window);
290
291     return window->height;
292 }
293
294 /**
295  * gst_vaapi_window_get_size:
296  * @window: a #GstVaapiWindow
297  * @pwidth: return location for the width, or %NULL
298  * @pheight: return location for the height, or %NULL
299  *
300  * Retrieves the dimensions of a #GstVaapiWindow.
301  */
302 void
303 gst_vaapi_window_get_size(GstVaapiWindow *window, guint *pwidth, guint *pheight)
304 {
305     g_return_if_fail(window != NULL);
306
307     gst_vaapi_window_ensure_size(window);
308
309     if (pwidth)
310         *pwidth = window->width;
311
312     if (pheight)
313         *pheight = window->height;
314 }
315
316 /**
317  * gst_vaapi_window_set_width:
318  * @window: a #GstVaapiWindow
319  * @width: requested new width for the window, in pixels
320  *
321  * Resizes the @window to match the specified @width.
322  */
323 void
324 gst_vaapi_window_set_width(GstVaapiWindow *window, guint width)
325 {
326     g_return_if_fail(window != NULL);
327
328     gst_vaapi_window_set_size(window, width, window->height);
329 }
330
331 /**
332  * gst_vaapi_window_set_height:
333  * @window: a #GstVaapiWindow
334  * @height: requested new height for the window, in pixels
335  *
336  * Resizes the @window to match the specified @height.
337  */
338 void
339 gst_vaapi_window_set_height(GstVaapiWindow *window, guint height)
340 {
341     g_return_if_fail(window != NULL);
342
343     gst_vaapi_window_set_size(window, window->width, height);
344 }
345
346 /**
347  * gst_vaapi_window_set_size:
348  * @window: a #GstVaapiWindow
349  * @width: requested new width for the window, in pixels
350  * @height: requested new height for the window, in pixels
351  *
352  * Resizes the @window to match the specified @width and @height.
353  */
354 void
355 gst_vaapi_window_set_size(GstVaapiWindow *window, guint width, guint height)
356 {
357     g_return_if_fail(window != NULL);
358
359     if (width == window->width && height == window->height)
360         return;
361
362     if (!GST_VAAPI_WINDOW_GET_CLASS(window)->resize(window, width, height))
363         return;
364
365     window->width  = width;
366     window->height = height;
367 }
368
369 static inline void
370 get_surface_rect(GstVaapiSurface *surface, GstVaapiRectangle *rect)
371 {
372     rect->x      = 0;
373     rect->y      = 0;
374     rect->width  = GST_VAAPI_SURFACE_WIDTH(surface);
375     rect->height = GST_VAAPI_SURFACE_HEIGHT(surface);
376 }
377
378 static inline void
379 get_window_rect(GstVaapiWindow *window, GstVaapiRectangle *rect)
380 {
381     guint width, height;
382
383     gst_vaapi_window_get_size(window, &width, &height);
384     rect->x      = 0;
385     rect->y      = 0;
386     rect->width  = width;
387     rect->height = height;
388 }
389
390 /**
391  * gst_vaapi_window_put_surface:
392  * @window: a #GstVaapiWindow
393  * @surface: a #GstVaapiSurface
394  * @src_rect: the sub-rectangle of the source surface to
395  *   extract and process. If %NULL, the entire surface will be used.
396  * @dst_rect: the sub-rectangle of the destination
397  *   window into which the surface is rendered. If %NULL, the entire
398  *   window will be used.
399  * @flags: postprocessing flags. See #GstVaapiSurfaceRenderFlags
400  *
401  * Renders the @surface region specified by @src_rect into the @window
402  * region specified by @dst_rect. The @flags specify how de-interlacing
403  * (if needed), color space conversion, scaling and other postprocessing
404  * transformations are performed.
405  *
406  * Return value: %TRUE on success
407  */
408 gboolean
409 gst_vaapi_window_put_surface(
410     GstVaapiWindow          *window,
411     GstVaapiSurface         *surface,
412     const GstVaapiRectangle *src_rect,
413     const GstVaapiRectangle *dst_rect,
414     guint                    flags
415 )
416 {
417     const GstVaapiWindowClass *klass;
418     GstVaapiRectangle src_rect_default, dst_rect_default;
419
420     g_return_val_if_fail(window != NULL, FALSE);
421     g_return_val_if_fail(surface != NULL, FALSE);
422
423     klass = GST_VAAPI_WINDOW_GET_CLASS(window);
424     if (!klass->render)
425         return FALSE;
426
427     if (!src_rect) {
428         src_rect = &src_rect_default;
429         get_surface_rect(surface, &src_rect_default);
430     }
431
432     if (!dst_rect) {
433         dst_rect = &dst_rect_default;
434         get_window_rect(window, &dst_rect_default);
435     }
436
437     return klass->render(window, surface, src_rect, dst_rect, flags);
438 }
439
440 static inline void
441 get_pixmap_rect(GstVaapiPixmap *pixmap, GstVaapiRectangle *rect)
442 {
443     guint width, height;
444
445     gst_vaapi_pixmap_get_size(pixmap, &width, &height);
446     rect->x      = 0;
447     rect->y      = 0;
448     rect->width  = width;
449     rect->height = height;
450 }
451
452 /**
453  * gst_vaapi_window_put_pixmap:
454  * @window: a #GstVaapiWindow
455  * @pixmap: a #GstVaapiPixmap
456  * @src_rect: the sub-rectangle of the source pixmap to
457  *   extract and process. If %NULL, the entire pixmap will be used.
458  * @dst_rect: the sub-rectangle of the destination
459  *   window into which the pixmap is rendered. If %NULL, the entire
460  *   window will be used.
461  *
462  * Renders the @pixmap region specified by @src_rect into the @window
463  * region specified by @dst_rect.
464  *
465  * Return value: %TRUE on success
466  */
467 gboolean
468 gst_vaapi_window_put_pixmap(
469     GstVaapiWindow          *window,
470     GstVaapiPixmap          *pixmap,
471     const GstVaapiRectangle *src_rect,
472     const GstVaapiRectangle *dst_rect
473 )
474 {
475     const GstVaapiWindowClass *klass;
476     GstVaapiRectangle src_rect_default, dst_rect_default;
477
478     g_return_val_if_fail(window != NULL, FALSE);
479     g_return_val_if_fail(pixmap != NULL, FALSE);
480
481     klass = GST_VAAPI_WINDOW_GET_CLASS(window);
482     if (!klass->render_pixmap)
483         return FALSE;
484
485     if (!src_rect) {
486         src_rect = &src_rect_default;
487         get_pixmap_rect(pixmap, &src_rect_default);
488     }
489
490     if (!dst_rect) {
491         dst_rect = &dst_rect_default;
492         get_window_rect(window, &dst_rect_default);
493     }
494     return klass->render_pixmap(window, pixmap, src_rect, dst_rect);
495 }