mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
waylandsink: create and maintain the subsurface inside the sink
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.
This commit is contained in:
parent
b806313396
commit
07f671fcaf
5 changed files with 71 additions and 31 deletions
|
@ -100,13 +100,13 @@ static void gst_wayland_sink_videooverlay_init (GstVideoOverlayInterface *
|
|||
iface);
|
||||
static void gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay,
|
||||
guintptr handle);
|
||||
static void gst_wayland_sink_set_render_rectangle (GstVideoOverlay * overlay,
|
||||
gint x, gint y, gint w, gint h);
|
||||
static void gst_wayland_sink_expose (GstVideoOverlay * overlay);
|
||||
|
||||
/* WaylandVideo interface */
|
||||
static void gst_wayland_sink_waylandvideo_init (GstWaylandVideoInterface *
|
||||
iface);
|
||||
static void gst_wayland_sink_set_surface_size (GstWaylandVideo * video,
|
||||
gint w, gint h);
|
||||
static void gst_wayland_sink_pause_rendering (GstWaylandVideo * video);
|
||||
static void gst_wayland_sink_resume_rendering (GstWaylandVideo * video);
|
||||
|
||||
|
@ -616,12 +616,15 @@ render_last_buffer (GstWaylandSink * sink)
|
|||
src.h = sink->video_height;
|
||||
dst.w = sink->window->width;
|
||||
dst.h = sink->window->height;
|
||||
gst_video_sink_center_rect (src, dst, &res, FALSE);
|
||||
gst_video_sink_center_rect (src, dst, &res, TRUE);
|
||||
|
||||
if (sink->window->subsurface)
|
||||
wl_subsurface_set_position (sink->window->subsurface,
|
||||
sink->window->x + res.x, sink->window->y + res.y);
|
||||
wl_viewport_set_destination (sink->window->viewport, res.w, res.h);
|
||||
|
||||
wl_surface_attach (surface, meta->wbuffer, 0, 0);
|
||||
wl_surface_damage (surface, 0, 0, res.w, res.h);
|
||||
wl_surface_damage (surface, 0, 0, dst.w, dst.h);
|
||||
|
||||
wl_surface_commit (surface);
|
||||
wl_display_flush (sink->display->display);
|
||||
|
@ -732,6 +735,7 @@ static void
|
|||
gst_wayland_sink_videooverlay_init (GstVideoOverlayInterface * iface)
|
||||
{
|
||||
iface->set_window_handle = gst_wayland_sink_set_window_handle;
|
||||
iface->set_render_rectangle = gst_wayland_sink_set_render_rectangle;
|
||||
iface->expose = gst_wayland_sink_expose;
|
||||
}
|
||||
|
||||
|
@ -760,7 +764,7 @@ gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay, guintptr handle)
|
|||
"an externally-supplied display handle. Consider providing a "
|
||||
"display handle from your application with GstContext"));
|
||||
} else {
|
||||
sink->window = gst_wl_window_new_from_surface (sink->display, surface);
|
||||
sink->window = gst_wl_window_new_in_surface (sink->display, surface);
|
||||
}
|
||||
} else {
|
||||
GST_ERROR_OBJECT (sink, "Failed to find display handle, "
|
||||
|
@ -771,6 +775,28 @@ gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay, guintptr handle)
|
|||
GST_OBJECT_UNLOCK (sink);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wayland_sink_set_render_rectangle (GstVideoOverlay * overlay,
|
||||
gint x, gint y, gint w, gint h)
|
||||
{
|
||||
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
|
||||
|
||||
g_return_if_fail (sink != NULL);
|
||||
|
||||
GST_OBJECT_LOCK (sink);
|
||||
if (!sink->window) {
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
GST_WARNING_OBJECT (sink,
|
||||
"set_render_rectangle called without window, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "window geometry changed to (%d, %d) %d x %d",
|
||||
x, y, w, h);
|
||||
gst_wl_window_set_size (sink->window, x, y, w, h);
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wayland_sink_expose (GstVideoOverlay * overlay)
|
||||
{
|
||||
|
@ -791,32 +817,10 @@ gst_wayland_sink_expose (GstVideoOverlay * overlay)
|
|||
static void
|
||||
gst_wayland_sink_waylandvideo_init (GstWaylandVideoInterface * iface)
|
||||
{
|
||||
iface->set_surface_size = gst_wayland_sink_set_surface_size;
|
||||
iface->pause_rendering = gst_wayland_sink_pause_rendering;
|
||||
iface->resume_rendering = gst_wayland_sink_resume_rendering;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wayland_sink_set_surface_size (GstWaylandVideo * video, gint w, gint h)
|
||||
{
|
||||
GstWaylandSink *sink = GST_WAYLAND_SINK (video);
|
||||
|
||||
g_return_if_fail (sink != NULL);
|
||||
g_return_if_fail (sink->window != NULL);
|
||||
|
||||
GST_OBJECT_LOCK (sink);
|
||||
if (!sink->window) {
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
GST_WARNING_OBJECT (sink,
|
||||
"set_surface_size called without window, ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "changing window size to %d x %d", w, h);
|
||||
gst_wl_window_set_size (sink->window, w, h);
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_wayland_sink_pause_rendering (GstWaylandVideo * video)
|
||||
{
|
||||
|
|
|
@ -69,6 +69,9 @@ gst_wl_display_finalize (GObject * gobject)
|
|||
if (self->compositor)
|
||||
wl_compositor_destroy (self->compositor);
|
||||
|
||||
if (self->subcompositor)
|
||||
wl_subcompositor_destroy (self->subcompositor);
|
||||
|
||||
if (self->registry)
|
||||
wl_registry_destroy (self->registry);
|
||||
|
||||
|
@ -135,6 +138,9 @@ registry_handle_global (void *data, struct wl_registry *registry,
|
|||
if (g_strcmp0 (interface, "wl_compositor") == 0) {
|
||||
self->compositor = wl_registry_bind (registry, id, &wl_compositor_interface,
|
||||
MIN (version, 3));
|
||||
} else if (g_strcmp0 (interface, "wl_subcompositor") == 0) {
|
||||
self->subcompositor =
|
||||
wl_registry_bind (registry, id, &wl_subcompositor_interface, 1);
|
||||
} else if (g_strcmp0 (interface, "wl_shell") == 0) {
|
||||
self->shell = wl_registry_bind (registry, id, &wl_shell_interface, 1);
|
||||
} else if (g_strcmp0 (interface, "wl_shm") == 0) {
|
||||
|
|
|
@ -48,6 +48,7 @@ struct _GstWlDisplay
|
|||
/* globals */
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
struct wl_shell *shell;
|
||||
struct wl_shm *shm;
|
||||
struct wl_scaler *scaler;
|
||||
|
|
|
@ -84,6 +84,10 @@ gst_wl_window_finalize (GObject * gobject)
|
|||
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);
|
||||
|
@ -98,7 +102,7 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, gint width, gint height)
|
|||
wl_compositor_create_surface (display->compositor));
|
||||
window->own_surface = TRUE;
|
||||
|
||||
gst_wl_window_set_size (window, width, height);
|
||||
gst_wl_window_set_size (window, 0, 0, width, height);
|
||||
|
||||
window->shell_surface = wl_shell_get_shell_surface (display->shell,
|
||||
window->surface);
|
||||
|
@ -117,6 +121,23 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, gint width, gint height)
|
|||
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)
|
||||
|
@ -128,6 +149,8 @@ gst_wl_window_new_from_surface (GstWlDisplay * display,
|
|||
|
||||
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;
|
||||
|
||||
|
@ -172,10 +195,12 @@ gst_wl_window_is_toplevel (GstWlWindow * window)
|
|||
}
|
||||
|
||||
void
|
||||
gst_wl_window_set_size (GstWlWindow * window, gint w, gint h)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,10 @@ struct _GstWlWindow
|
|||
|
||||
GstWlDisplay *display;
|
||||
struct wl_surface *surface;
|
||||
struct wl_subsurface *subsurface;
|
||||
struct wl_viewport *viewport;
|
||||
struct wl_shell_surface *shell_surface;
|
||||
gint width, height;
|
||||
gint x, y, width, height;
|
||||
gboolean own_surface;
|
||||
};
|
||||
|
||||
|
@ -56,6 +57,8 @@ GType gst_wl_window_get_type (void);
|
|||
|
||||
GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display,
|
||||
gint width, gint height);
|
||||
GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display,
|
||||
struct wl_surface * parent);
|
||||
GstWlWindow *gst_wl_window_new_from_surface (GstWlDisplay * display,
|
||||
struct wl_surface * surface);
|
||||
|
||||
|
@ -63,7 +66,8 @@ GstWlDisplay *gst_wl_window_get_display (GstWlWindow * window);
|
|||
struct wl_surface *gst_wl_window_get_wl_surface (GstWlWindow * window);
|
||||
gboolean gst_wl_window_is_toplevel (GstWlWindow *window);
|
||||
|
||||
void gst_wl_window_set_size (GstWlWindow * window, gint w, gint h);
|
||||
void gst_wl_window_set_size (GstWlWindow * window, gint x, gint y, gint w,
|
||||
gint h);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
Loading…
Reference in a new issue