This means that the given surface in set_window_handle can now be the window's top-level surface on top of which waylandsink creates its own subsurface for rendering the video. This has many advantages: * We can maintain aspect ratio by overlaying the subsurface in the center of the given area and fill the parent surface's area black in case we need to draw borders (instead of adding another subsurface inside the subsurface given from the application, so, less subsurfaces) * We can more easily support toolkits without subsurfaces (see gtk) * We can get properly use gst_video_overlay_set_render_rectangle as our api to set the video area size from the application and therefore remove gst_wayland_video_set_surface_size.
207 lines
5.0 KiB
C
207 lines
5.0 KiB
C
/* GStreamer Wayland video sink
|
|
*
|
|
* Copyright (C) 2011 Intel Corporation
|
|
* Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
|
|
* Copyright (C) 2014 Collabora Ltd.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "wlwindow.h"
|
|
|
|
GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
|
|
#define GST_CAT_DEFAULT gstwayland_debug
|
|
|
|
G_DEFINE_TYPE (GstWlWindow, gst_wl_window, G_TYPE_OBJECT);
|
|
|
|
static void gst_wl_window_finalize (GObject * gobject);
|
|
|
|
static void
|
|
handle_ping (void *data, struct wl_shell_surface *shell_surface,
|
|
uint32_t serial)
|
|
{
|
|
wl_shell_surface_pong (shell_surface, serial);
|
|
}
|
|
|
|
static void
|
|
handle_configure (void *data, struct wl_shell_surface *shell_surface,
|
|
uint32_t edges, int32_t width, int32_t height)
|
|
{
|
|
}
|
|
|
|
static void
|
|
handle_popup_done (void *data, struct wl_shell_surface *shell_surface)
|
|
{
|
|
}
|
|
|
|
static const struct wl_shell_surface_listener shell_surface_listener = {
|
|
handle_ping,
|
|
handle_configure,
|
|
handle_popup_done
|
|
};
|
|
|
|
static void
|
|
gst_wl_window_class_init (GstWlWindowClass * klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
gobject_class->finalize = gst_wl_window_finalize;
|
|
}
|
|
|
|
static void
|
|
gst_wl_window_init (GstWlWindow * self)
|
|
{
|
|
}
|
|
|
|
static void
|
|
gst_wl_window_finalize (GObject * gobject)
|
|
{
|
|
GstWlWindow *self = GST_WL_WINDOW (gobject);
|
|
|
|
wl_viewport_destroy (self->viewport);
|
|
|
|
if (self->shell_surface) {
|
|
wl_shell_surface_destroy (self->shell_surface);
|
|
}
|
|
|
|
if (self->own_surface) {
|
|
wl_surface_destroy (self->surface);
|
|
}
|
|
|
|
if (self->subsurface) {
|
|
wl_subsurface_destroy (self->subsurface);
|
|
}
|
|
|
|
g_clear_object (&self->display);
|
|
|
|
G_OBJECT_CLASS (gst_wl_window_parent_class)->finalize (gobject);
|
|
}
|
|
|
|
GstWlWindow *
|
|
gst_wl_window_new_toplevel (GstWlDisplay * display, gint width, gint height)
|
|
{
|
|
GstWlWindow *window;
|
|
|
|
window = gst_wl_window_new_from_surface (display,
|
|
wl_compositor_create_surface (display->compositor));
|
|
window->own_surface = TRUE;
|
|
|
|
gst_wl_window_set_size (window, 0, 0, width, height);
|
|
|
|
window->shell_surface = wl_shell_get_shell_surface (display->shell,
|
|
window->surface);
|
|
|
|
if (window->shell_surface) {
|
|
wl_shell_surface_add_listener (window->shell_surface,
|
|
&shell_surface_listener, window);
|
|
wl_shell_surface_set_toplevel (window->shell_surface);
|
|
} else {
|
|
GST_ERROR ("Unable to get wl_shell_surface");
|
|
|
|
g_object_unref (window);
|
|
return NULL;
|
|
}
|
|
|
|
return window;
|
|
}
|
|
|
|
GstWlWindow *
|
|
gst_wl_window_new_in_surface (GstWlDisplay * display,
|
|
struct wl_surface * parent)
|
|
{
|
|
GstWlWindow *window;
|
|
|
|
window = gst_wl_window_new_from_surface (display,
|
|
wl_compositor_create_surface (display->compositor));
|
|
window->own_surface = TRUE;
|
|
|
|
window->subsurface = wl_subcompositor_get_subsurface (display->subcompositor,
|
|
window->surface, parent);
|
|
wl_subsurface_set_desync (window->subsurface);
|
|
|
|
return window;
|
|
}
|
|
|
|
GstWlWindow *
|
|
gst_wl_window_new_from_surface (GstWlDisplay * display,
|
|
struct wl_surface * surface)
|
|
{
|
|
GstWlWindow *window;
|
|
struct wl_region *region;
|
|
|
|
g_return_val_if_fail (surface != NULL, NULL);
|
|
|
|
window = g_object_new (GST_TYPE_WL_WINDOW, NULL);
|
|
window->display = g_object_ref (display);
|
|
window->x = 0;
|
|
window->y = 0;
|
|
window->width = 0;
|
|
window->height = 0;
|
|
|
|
window->surface = surface;
|
|
window->own_surface = FALSE;
|
|
|
|
/* make sure the surface runs on our local queue */
|
|
wl_proxy_set_queue ((struct wl_proxy *) surface, display->queue);
|
|
|
|
window->viewport = wl_scaler_get_viewport (display->scaler, window->surface);
|
|
|
|
/* do not accept input */
|
|
region = wl_compositor_create_region (display->compositor);
|
|
wl_surface_set_input_region (surface, region);
|
|
wl_region_destroy (region);
|
|
|
|
return window;
|
|
}
|
|
|
|
GstWlDisplay *
|
|
gst_wl_window_get_display (GstWlWindow * window)
|
|
{
|
|
g_return_val_if_fail (window != NULL, NULL);
|
|
|
|
return g_object_ref (window->display);
|
|
}
|
|
|
|
struct wl_surface *
|
|
gst_wl_window_get_wl_surface (GstWlWindow * window)
|
|
{
|
|
g_return_val_if_fail (window != NULL, NULL);
|
|
|
|
return window->surface;
|
|
}
|
|
|
|
gboolean
|
|
gst_wl_window_is_toplevel (GstWlWindow * window)
|
|
{
|
|
g_return_val_if_fail (window != NULL, FALSE);
|
|
|
|
return (window->shell_surface != NULL);
|
|
}
|
|
|
|
void
|
|
gst_wl_window_set_size (GstWlWindow * window, gint x, gint y, gint w, gint h)
|
|
{
|
|
g_return_if_fail (window != NULL);
|
|
|
|
window->x = x;
|
|
window->y = y;
|
|
window->width = w;
|
|
window->height = h;
|
|
}
|