waylandsink: Use wl_scaler/wl_viewport to scale the surface in the compositor/hardware
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Tue, 11 Mar 2014 11:14:00 +0000 (13:14 +0200)
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>
Tue, 17 Jun 2014 11:51:25 +0000 (13:51 +0200)
ext/wayland/gstwaylandsink.c
ext/wayland/gstwaylandsink.h
ext/wayland/wldisplay.c
ext/wayland/wldisplay.h
ext/wayland/wlwindow.c
ext/wayland/wlwindow.h

index 06e6fd9..2400e6f 100644 (file)
@@ -275,23 +275,11 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
 {
   GstWaylandSink *sink;
   GstCaps *caps;
-  gint width, height;
 
   sink = GST_WAYLAND_SINK (bsink);
 
   caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
 
-  /* If we don't have a window yet, it will
-   * be created using the upstream size.
-   * Otherwise, we should tell upstream exactly
-   * what size we want. We don't resize ourselves. */
-  if (sink->window) {
-    caps = gst_caps_make_writable (caps);
-    gst_wl_window_get_size (sink->window, &width, &height);
-    gst_caps_set_simple (caps, "width", G_TYPE_INT, width,
-        "height", G_TYPE_INT, height, NULL);
-  }
-
   if (filter) {
     GstCaps *intersection;
 
@@ -334,16 +322,13 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
   sink->video_height = info.height;
 
   /* create the output window if needed */
-  if (!sink->window || sink->video_width != sink->window->width ||
-      sink->video_height != sink->window->height) {
-
+  if (!sink->window) {
     if (!sink->display)
       sink->display = gst_wl_display_new (sink->display_name, &error);
 
     if (sink->display == NULL)
       goto display_failed;
 
-    g_clear_object (&sink->window);
     sink->window = gst_wl_window_new_toplevel (sink->display, sink->video_width,
         sink->video_height);
   }
@@ -372,7 +357,6 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
   gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
   gst_object_unref (newpool);
 
-  sink->negotiated = TRUE;
   GST_OBJECT_UNLOCK (sink);
   return TRUE;
 
@@ -527,7 +511,7 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
   GST_LOG_OBJECT (sink, "render buffer %p", buffer);
 
   /* surface is resizing - drop buffers until finished */
-  if (sink->drawing_frozen || !sink->negotiated)
+  if (sink->drawing_frozen)
     goto done;
 
   /* drop buffers until we get a frame callback */
@@ -579,6 +563,11 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
 
   wl_surface_attach (surface, meta->wbuffer, 0, 0);
   wl_surface_damage (surface, 0, 0, res.w, res.h);
+
+  wl_viewport_set (sink->window->viewport, wl_fixed_from_int (0),
+      wl_fixed_from_int (0), wl_fixed_from_int (src.w),
+      wl_fixed_from_int (src.h), res.w, res.h);
+
   callback = wl_surface_frame (surface);
   wl_callback_add_listener (callback, &frame_callback_listener, sink);
   wl_surface_commit (surface);
@@ -690,7 +679,6 @@ static void
 gst_wayland_sink_set_surface_size (GstWaylandVideo * video, gint w, gint h)
 {
   GstWaylandSink *sink = GST_WAYLAND_SINK (video);
-  GstPad *peer;
 
   g_return_if_fail (sink != NULL);
   g_return_if_fail (sink->window != NULL);
@@ -704,18 +692,7 @@ gst_wayland_sink_set_surface_size (GstWaylandVideo * video, gint w, gint h)
   }
 
   gst_wl_window_set_size (sink->window, w, h);
-  sink->negotiated = FALSE;
   GST_OBJECT_UNLOCK (sink);
-
-  /* upstream must change video size because we can't resize ourselves.
-   * This can be removed when we move to wl_viewport */
-  if (GST_STATE (sink) > GST_STATE_READY) {
-    peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink));
-    if (peer) {
-      gst_pad_send_event (peer, gst_event_new_reconfigure ());
-      gst_object_unref (peer);
-    }
-  }
 }
 
 static void
index 06c2b2c..929dfbb 100644 (file)
@@ -63,7 +63,6 @@ struct _GstWaylandSink
 
   gboolean redraw_pending;
   gboolean drawing_frozen;
-  gboolean negotiated;
   GCond render_cond;
 };
 
index 590fc98..8973f79 100644 (file)
@@ -140,6 +140,8 @@ registry_handle_global (void *data, struct wl_registry *registry,
   } else if (g_strcmp0 (interface, "wl_shm") == 0) {
     self->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1);
     wl_shm_add_listener (self->shm, &shm_listener, self);
+  } else if (g_strcmp0 (interface, "wl_scaler") == 0) {
+    self->scaler = wl_registry_bind (registry, id, &wl_scaler_interface, 1);
   }
 }
 
index dbe49d9..2a90a40 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <gst/gst.h>
 #include <wayland-client.h>
+#include "scaler-client-protocol.h"
 
 #define GST_TYPE_WL_DISPLAY                  (gst_wl_display_get_type ())
 #define GST_WL_DISPLAY(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplay))
@@ -47,6 +48,7 @@ struct _GstWlDisplay
   struct wl_compositor *compositor;
   struct wl_shell *shell;
   struct wl_shm *shm;
+  struct wl_scaler *scaler;
   GArray *formats;
 
   /* private */
index f1d103a..11fe0bc 100644 (file)
@@ -74,6 +74,8 @@ 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);
   }
@@ -100,6 +102,8 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, gint width, gint height)
   window->surface = wl_compositor_create_surface (display->compositor);
   window->own_surface = TRUE;
 
+  window->viewport = wl_scaler_get_viewport (display->scaler, window->surface);
+
   window->shell_surface = wl_shell_get_shell_surface (display->shell,
       window->surface);
 
@@ -133,6 +137,8 @@ gst_wl_window_new_from_surface (GstWlDisplay * display,
   window->surface = surface;
   window->own_surface = FALSE;
 
+  window->viewport = wl_scaler_get_viewport (display->scaler, window->surface);
+
   return window;
 }
 
index ebdd000..51461e4 100644 (file)
@@ -39,6 +39,7 @@ struct _GstWlWindow
 
   GstWlDisplay *display;
   struct wl_surface *surface;
+  struct wl_viewport *viewport;
   struct wl_shell_surface *shell_surface;
   gint width, height;
   gboolean own_surface;