diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index 1a37d6d0be..9730ccc113 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -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) { diff --git a/ext/wayland/wldisplay.c b/ext/wayland/wldisplay.c index 07ce07b82f..0e2e91e7d8 100644 --- a/ext/wayland/wldisplay.c +++ b/ext/wayland/wldisplay.c @@ -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) { diff --git a/ext/wayland/wldisplay.h b/ext/wayland/wldisplay.h index 95c11cb252..0224406672 100644 --- a/ext/wayland/wldisplay.h +++ b/ext/wayland/wldisplay.h @@ -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; diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c index 41ee5710b6..c3e513adda 100644 --- a/ext/wayland/wlwindow.c +++ b/ext/wayland/wlwindow.c @@ -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; } diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h index cfeb5c417d..ca30fdad63 100644 --- a/ext/wayland/wlwindow.h +++ b/ext/wayland/wlwindow.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