You have been requested to review the proposed merge of 
~vanvugt/ubuntu/+source/mutter:fix-lp1763892-cosmic into 
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/cosmic.

For more details, see:
https://code.launchpad.net/~vanvugt/ubuntu/+source/mutter/+git/mutter/+merge/363599

 

-- 
Your team Ubuntu Desktop is requested to review the proposed merge of 
~vanvugt/ubuntu/+source/mutter:fix-lp1763892-cosmic into 
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/cosmic.
diff --git a/debian/changelog b/debian/changelog
index 564d95f..c3875a2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+mutter (3.30.2-1~ubuntu18.10.4) UNRELEASED; urgency=medium
+
+  * Add support for high frame rate displays (LP: #1763892):
+    - Introduce lp1763892-add-hardware-vsync-support.patch
+    - Drop erroneous clutter-Smooth-out-master-clock-to-smooth-visuals.patch
+
+ -- Daniel van Vugt <[email protected]>  Fri, 22 Feb 2019 17:42:49 +0800
+
 mutter (3.30.2-1~ubuntu18.10.3) cosmic; urgency=medium
 
   * d/p/clutter-Avoid-rounding-compensation-when-invalidating-2D-.patch,
diff --git a/debian/libmutter-3-0.symbols b/debian/libmutter-3-0.symbols
index 81ebd76..eb66e84 100644
--- a/debian/libmutter-3-0.symbols
+++ b/debian/libmutter-3-0.symbols
@@ -699,6 +699,7 @@ libmutter-3.so.0 libmutter-3-0 #MINVER#
  (arch=linux-any)meta_gpu_kms_can_have_outputs@Base 3.29.92
  (arch=linux-any)meta_gpu_kms_flip_closure_container_free@Base 3.29.4
  (arch=linux-any)meta_gpu_kms_flip_crtc@Base 3.28.2
+ (arch=linux-any)meta_gpu_kms_get_current_time_ns@Base 3.30.2
  (arch=linux-any)meta_gpu_kms_get_fd@Base 3.28.2
  (arch=linux-any)meta_gpu_kms_get_file_path@Base 3.28.2
  (arch=linux-any)meta_gpu_kms_get_max_buffer_size@Base 3.28.2
diff --git a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch b/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
deleted file mode 100644
index 2239837..0000000
--- a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From: Daniel van Vugt <[email protected]>
-Date: Fri, 16 Feb 2018 02:50:59 -0600
-Subject: clutter: Smooth out master clock to smooth visuals
-
-Clutter's master clock was jittery because it included errors in cur_tick
-such as dispatch delays due to other sources. Dispatch could also occur up
-to 1ms early since GSource can only be timed to the millisecond. All of this
-could impact the visual smoothness of animations as they are displayed on
-the steady interval of the monitor, but spacially moving in less regular
-steps derived from the dispatch times.
-
-The simple fix is to ignore any jitter in dispatch timing. Try a little
-bit harder to use a precise interval that will better match the display
-hardware, and smoother visuals will follow.
-
-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/25
-Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/70
----
- clutter/clutter/clutter-master-clock-default.c | 134 +++++++++++++++++--------
- 1 file changed, 93 insertions(+), 41 deletions(-)
-
-diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c
-index 7b2df0d..97b6d13 100644
---- a/clutter/clutter/clutter-master-clock-default.c
-+++ b/clutter/clutter/clutter-master-clock-default.c
-@@ -69,8 +69,10 @@ struct _ClutterMasterClockDefault
-   /* the previous state of the clock, in usecs, used to compute the delta */
-   gint64 prev_tick;
- 
-+  /* the ideal frame interval in usecs (inverse of your max refresh rate) */
-+  gint64 frame_interval;
-+
- #ifdef CLUTTER_ENABLE_DEBUG
--  gint64 frame_budget;
-   gint64 remaining_budget;
- #endif
- 
-@@ -264,6 +266,41 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
-     }
- }
- 
-+static gint64
-+estimate_next_presentation_time (ClutterMasterClockDefault *master_clock)
-+{
-+  gint64 frame_phase, now, now_phase, undershoot;
-+
-+  /* In future if this was updated from the backend's (maximum) refresh rate
-+   * then that would fix: https://bugzilla.gnome.org/show_bug.cgi?id=781296
-+   */
-+  master_clock->frame_interval = G_USEC_PER_SEC /
-+                                 clutter_get_default_frame_rate ();
-+
-+  now = g_source_get_time (master_clock->source);
-+  now_phase = now % master_clock->frame_interval;
-+
-+  /* To be precise we would like to use:
-+   *   frame_phase = a_recent_hardware_presentation_time % frame_interval;
-+   * where hardware_presentation_time must be using the same clock as
-+   * g_source_get_time. Unfortunately they're different clocks right now
-+   * so we can't.
-+   *   Alternatively, we could replace g_source_get_time in future with the
-+   * current time in the clutter/cogl presentation clock, but that function
-+   * also doesn't exist yet.
-+   *   Until we can get either of those, zero is fine. It just means latency
-+   * will be suboptimal by half a frame on average. We still get maximum
-+   * smoothness this way...
-+   */
-+  frame_phase = 0;
-+
-+  undershoot = frame_phase - now_phase;
-+  if (undershoot < 0)
-+    undershoot += master_clock->frame_interval;
-+
-+  return now + undershoot;
-+}
-+
- /*
-  * master_clock_next_frame_delay:
-  * @master_clock: a #ClutterMasterClock
-@@ -276,7 +313,8 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
- static gint
- master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
- {
--  gint64 now, next;
-+  gint64 now, target_presentation_time, ideal_render_start;  /* timestamps */
-+  gint64 ideal_prerender_time, lateness;  /* deltas */
-   gint swap_delay;
- 
-   if (!master_clock_is_running (master_clock))
-@@ -307,46 +345,45 @@ master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
-       return 0;
-     }
- 
--  if (master_clock->prev_tick == 0)
--    {
--      /* If we weren't previously running, then draw the next frame
--       * immediately
--       */
--      CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
--      return 0;
--    }
--
--  /* Otherwise, wait at least 1/frame_rate seconds since we last
--   * started a frame
--   */
-   now = g_source_get_time (master_clock->source);
- 
--  next = master_clock->prev_tick;
--
--  /* If time has gone backwards then there's no way of knowing how
--     long we should wait so let's just dispatch immediately */
--  if (now <= next)
-+  /* As first preference, try to carry on smoothly from the previous frame,
-+   * even if that means we start rendering frame 2 before frame 1 has been
-+   * presented. This is why we ignore estimate_next_presentation_time here...
-+   */
-+  target_presentation_time = master_clock->prev_tick +
-+                             master_clock->frame_interval;
-+  ideal_prerender_time = master_clock->frame_interval;
-+  ideal_render_start = target_presentation_time - ideal_prerender_time;
-+  lateness = now - ideal_render_start;
-+
-+  /* If we just woke from idle then try to improve the smoothness of the first
-+   * two frames some more. Otherwise the first frame would appear too old
-+   * relative to the second frame.
-+   */
-+  if (lateness >= master_clock->frame_interval)
-     {
--      CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
--
--      return 0;
-+      target_presentation_time = estimate_next_presentation_time (master_clock);
-+      ideal_render_start = target_presentation_time - ideal_prerender_time;
-+      lateness = now - ideal_render_start;
-     }
- 
--  next += (1000000L / clutter_get_default_frame_rate ());
--
--  if (next <= now)
-+  if (lateness > 0)
-     {
--      CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
--                    1000000L / (gulong) clutter_get_default_frame_rate ());
--
-+      CLUTTER_NOTE (SCHEDULER, "No wait required. We're already late.");
-       return 0;
-     }
-   else
-     {
--      CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
--                   (next - now) / 1000);
--
--      return (next - now) / 1000;
-+      /* We +1 here to avoid premature dispatches that would otherwise occur
-+       * repeatedly during the 1ms before 'ideal_render_start'. We don't care
-+       * if this makes the final dispatch 1ms late because the smoothing
-+       * algorithm corrects that, and it's much better than attempting to
-+       * render more frames than the hardware can physically display...
-+       */
-+      gint millisec_delay = -lateness / 1000 + 1;
-+      CLUTTER_NOTE (SCHEDULER, "Waiting %dms", millisec_delay);
-+      return millisec_delay;
-     }
- }
- 
-@@ -532,16 +569,34 @@ clutter_clock_dispatch (GSource     *source,
-   ClutterMasterClockDefault *master_clock = clock_source->master_clock;
-   gboolean stages_updated = FALSE;
-   GSList *stages;
--
--  CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
-+  gint64 smooth_tick;
- 
-   _clutter_threads_acquire_lock ();
- 
-   /* Get the time to use for this frame */
--  master_clock->cur_tick = g_source_get_time (source);
-+  smooth_tick = estimate_next_presentation_time (master_clock);
-+  if (smooth_tick <= master_clock->prev_tick)
-+    {
-+      /* Ordinarily this will never happen. But after we fix bug 781296, it
-+       * could happen in the rare case when the ideal frame_interval changes,
-+       * such as video mode switching or hotplugging monitors. As such it is
-+       * not considered a bug (unless it's happening without mode switching
-+       * or hotplugging).
-+       */
-+      CLUTTER_NOTE (SCHEDULER, "Master clock [tick] was premature (skipped)");
-+      _clutter_threads_release_lock ();
-+      return G_SOURCE_CONTINUE;
-+    }
-+
-+  master_clock->cur_tick = smooth_tick;
-+  if (master_clock->prev_tick)
-+    CLUTTER_NOTE (SCHEDULER, "Master clock [tick] %+ldus",
-+                  (long) (master_clock->cur_tick - master_clock->prev_tick));
-+  else
-+    CLUTTER_NOTE (SCHEDULER, "Master clock [tick] startup");
- 
- #ifdef CLUTTER_ENABLE_DEBUG
--  master_clock->remaining_budget = master_clock->frame_budget;
-+  master_clock->remaining_budget = master_clock->frame_interval;
- #endif
- 
-   /* We need to protect ourselves against stages being destroyed during
-@@ -580,7 +635,7 @@ clutter_clock_dispatch (GSource     *source,
- 
-   _clutter_threads_release_lock ();
- 
--  return TRUE;
-+  return G_SOURCE_CONTINUE;
- }
- 
- static void
-@@ -612,10 +667,7 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
-   self->idle = FALSE;
-   self->ensure_next_iteration = FALSE;
-   self->paused = FALSE;
--
--#ifdef CLUTTER_ENABLE_DEBUG
--  self->frame_budget = G_USEC_PER_SEC / 60;
--#endif
-+  self->frame_interval = G_USEC_PER_SEC / 60; /* Will be refined at runtime */
- 
-   g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
-   g_source_set_can_recurse (source, FALSE);
diff --git a/debian/patches/lp1763892-add-hardware-vsync-support.patch b/debian/patches/lp1763892-add-hardware-vsync-support.patch
new file mode 100644
index 0000000..acb9167
--- /dev/null
+++ b/debian/patches/lp1763892-add-hardware-vsync-support.patch
@@ -0,0 +1,456 @@
+From 1b1e64bb296bfa38857238666994d42df257c15a Mon Sep 17 00:00:00 2001
+From: Daniel van Vugt <[email protected]>
+Date: Wed, 27 Jun 2018 17:19:27 +0800
+Subject: [PATCH 1/3] renderer-native: Add hardware presentation timing
+
+Add support for getting hardware presentation times from KMS (Wayland
+sessions). Also implement cogl_get_clock_time which is required to compare
+and judge the age of presentation timestamps.
+
+For single monitor systems this is straightforward. For multi-monitor
+systems though we have to choose a display to sync to. The compositor
+already partially solves this for us in the case of only one display
+updating because it will only use the subset of monitors that are
+changing. In the case of multiple monitors consuming the same frame
+concurrently however, we choose the fastest one (in use at the time).
+Note however that we also need !73 to land in order to fully realize
+multiple monitors running at full speed.
+
+(cherry picked from commit e9e4b2b72ef63890c4225dc641da38482b2b13b5)
+---
+ src/Makefile.am                            | 25 +++++++-
+ src/backends/native/meta-gpu-kms.c         | 69 ++++++++++++++++++++--
+ src/backends/native/meta-gpu-kms.h         |  3 +
+ src/backends/native/meta-renderer-native.c | 38 +++++++++++-
+ src/meta-marshal.list                      |  1 +
+ 5 files changed, 128 insertions(+), 8 deletions(-)
+ create mode 100644 src/meta-marshal.list
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 811e2b86b..56d539836 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -51,6 +51,8 @@ mutter_built_sources = \
+ 	$(dbus_login1_built_sources)		\
+ 	meta/meta-enum-types.h			\
+ 	meta-enum-types.c			\
++	meta-marshal.c	        		\
++	meta-marshal.h		        	\
+ 	$(NULL)
+ 
+ if HAVE_REMOTE_DESKTOP
+@@ -677,6 +679,7 @@ EXTRA_DIST +=					\
+ 	libmutter.pc.in				\
+ 	meta-enum-types.h.in			\
+ 	meta-enum-types.c.in			\
++	meta-marshal.list			\
+ 	org.freedesktop.login1.xml		\
+ 	org.gnome.Mutter.DisplayConfig.xml	\
+ 	org.gnome.Mutter.IdleMonitor.xml	\
+@@ -690,7 +693,10 @@ BUILT_SOURCES =					\
+ 	$(libmutterinclude_built_headers)
+ 
+ MUTTER_STAMP_FILES = stamp-meta-enum-types.h
+-CLEANFILES += $(MUTTER_STAMP_FILES)
++CLEANFILES +=					\
++	$(MUTTER_STAMP_FILES)			\
++	meta-marshal.c	        		\
++	meta-marshal.h
+ 
+ meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
+ 	@true
+@@ -786,3 +792,20 @@ endef
+ 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
+ %-server-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/%.xml
+ 	$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
++
++meta_marshal_opts = --prefix=meta_marshal --internal
++
++meta-marshal.h: meta-marshal.list
++	$(AM_V_GEN)$(GLIB_GENMARSHAL) \
++		--header \
++		$(meta_marshal_opts) \
++		--output=$@ \
++		$<
++
++meta-marshal.c: meta-marshal.list meta-marshal.h
++	$(AM_V_GEN)$(GLIB_GENMARSHAL) \
++		--include-header=meta-marshal.h \
++		$(meta_marshal_opts) \
++		--body \
++		--output=$@ \
++		$<
+diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
+index c3c5d0d68..26c759031 100644
+--- a/src/backends/native/meta-gpu-kms.c
++++ b/src/backends/native/meta-gpu-kms.c
+@@ -27,6 +27,7 @@
+ #include <errno.h>
+ #include <poll.h>
+ #include <string.h>
++#include <time.h>
+ #include <xf86drm.h>
+ #include <xf86drmMode.h>
+ 
+@@ -51,6 +52,7 @@ typedef struct _MetaGpuKmsFlipClosureContainer
+ {
+   GClosure *flip_closure;
+   MetaGpuKms *gpu_kms;
++  MetaCrtc *crtc;
+ } MetaGpuKmsFlipClosureContainer;
+ 
+ struct _MetaGpuKms
+@@ -61,6 +63,8 @@ struct _MetaGpuKms
+   char *file_path;
+   GSource *source;
+ 
++  clockid_t clock_id;
++
+   drmModeConnector **connectors;
+   unsigned int n_connectors;
+ 
+@@ -165,18 +169,26 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
+ 
+ static void
+ invoke_flip_closure (GClosure   *flip_closure,
+-                     MetaGpuKms *gpu_kms)
++                     MetaGpuKms *gpu_kms,
++                     MetaCrtc   *crtc,
++                     int64_t     page_flip_time_ns)
+ {
+   GValue params[] = {
+     G_VALUE_INIT,
+-    G_VALUE_INIT
++    G_VALUE_INIT,
++    G_VALUE_INIT,
++    G_VALUE_INIT,
+   };
+ 
+   g_value_init (&params[0], G_TYPE_POINTER);
+   g_value_set_pointer (&params[0], flip_closure);
+   g_value_init (&params[1], G_TYPE_OBJECT);
+   g_value_set_object (&params[1], gpu_kms);
+-  g_closure_invoke (flip_closure, NULL, 2, params, NULL);
++  g_value_init (&params[2], G_TYPE_OBJECT);
++  g_value_set_object (&params[2], crtc);
++  g_value_init (&params[3], G_TYPE_INT64);
++  g_value_set_int64 (&params[3], page_flip_time_ns);
++  g_closure_invoke (flip_closure, NULL, 4, params, NULL);
+   g_closure_unref (flip_closure);
+ }
+ 
+@@ -216,6 +228,7 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
+ 
+ MetaGpuKmsFlipClosureContainer *
+ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
++                                MetaCrtc   *crtc,
+                                 GClosure   *flip_closure)
+ {
+   MetaGpuKmsFlipClosureContainer *closure_container;
+@@ -223,7 +236,8 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
+   closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
+   *closure_container = (MetaGpuKmsFlipClosureContainer) {
+     .flip_closure = flip_closure,
+-    .gpu_kms = gpu_kms
++    .gpu_kms = gpu_kms,
++    .crtc = crtc
+   };
+ 
+   return closure_container;
+@@ -263,6 +277,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
+       int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
+ 
+       closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
++                                                          crtc,
+                                                           flip_closure);
+ 
+       ret = drmModePageFlip (kms_fd,
+@@ -296,6 +311,23 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
+   return TRUE;
+ }
+ 
++static int64_t
++timespec_to_nanoseconds (const struct timespec *ts)
++{
++  const int64_t one_billion = 1000000000;
++
++  return ((int64_t) ts->tv_sec) * one_billion + ts->tv_nsec;
++}
++
++static int64_t
++timeval_to_nanoseconds (const struct timeval *tv)
++{
++  int64_t usec = ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec;
++  int64_t nsec = usec * 1000;
++
++  return nsec;
++}
++
+ static void
+ page_flip_handler (int           fd,
+                    unsigned int  frame,
+@@ -306,8 +338,12 @@ page_flip_handler (int           fd,
+   MetaGpuKmsFlipClosureContainer *closure_container = user_data;
+   GClosure *flip_closure = closure_container->flip_closure;
+   MetaGpuKms *gpu_kms = closure_container->gpu_kms;
++  struct timeval page_flip_time = {sec, usec};
+ 
+-  invoke_flip_closure (flip_closure, gpu_kms);
++  invoke_flip_closure (flip_closure,
++                       gpu_kms,
++                       closure_container->crtc,
++                       timeval_to_nanoseconds (&page_flip_time));
+   meta_gpu_kms_flip_closure_container_free (closure_container);
+ }
+ 
+@@ -380,6 +416,17 @@ meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
+   return gpu_kms->file_path;
+ }
+ 
++int64_t
++meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
++{
++  struct timespec ts;
++
++  if (clock_gettime (gpu_kms->clock_id, &ts))
++    return 0;
++
++  return timespec_to_nanoseconds (&ts);
++}
++
+ void
+ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
+                                   uint64_t    state)
+@@ -679,6 +726,17 @@ init_crtcs (MetaGpuKms       *gpu_kms,
+   meta_gpu_take_crtcs (gpu, crtcs);
+ }
+ 
++static void
++init_frame_clock (MetaGpuKms *gpu_kms)
++{
++  uint64_t uses_monotonic;
++
++  if (drmGetCap (gpu_kms->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic) != 0)
++    uses_monotonic = 0;
++
++  gpu_kms->clock_id = uses_monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME;
++}
++
+ static void
+ init_outputs (MetaGpuKms       *gpu_kms,
+               MetaKmsResources *resources)
+@@ -806,6 +864,7 @@ meta_gpu_kms_read_current (MetaGpu  *gpu,
+   init_modes (gpu_kms, resources.resources);
+   init_crtcs (gpu_kms, &resources);
+   init_outputs (gpu_kms, &resources);
++  init_frame_clock (gpu_kms);
+ 
+   meta_kms_resources_release (&resources);
+ 
+diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
+index 5f77f191a..3e3f45c7e 100644
+--- a/src/backends/native/meta-gpu-kms.h
++++ b/src/backends/native/meta-gpu-kms.h
+@@ -73,6 +73,8 @@ int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
+ 
+ const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms);
+ 
++int64_t meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms);
++
+ void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms,
+                                        int        *max_width,
+                                        int        *max_height);
+@@ -89,6 +91,7 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
+ float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
+ 
+ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
++                                                                 MetaCrtc   *crtc,
+                                                                  GClosure   *flip_closure);
+ 
+ void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index f58e6b3e0..b192c3641 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -62,6 +62,7 @@
+ #include "backends/native/meta-monitor-manager-kms.h"
+ #include "backends/native/meta-renderer-native.h"
+ #include "backends/native/meta-renderer-native-gles3.h"
++#include "meta-marshal.h"
+ #include "cogl/cogl.h"
+ #include "core/boxes-private.h"
+ 
+@@ -1159,6 +1160,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
+ static void
+ on_crtc_flipped (GClosure         *closure,
+                  MetaGpuKms       *gpu_kms,
++                 MetaCrtc         *crtc,
++                 int64_t           page_flip_time_ns,
+                  MetaRendererView *view)
+ {
+   ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
+@@ -1169,6 +1172,24 @@ on_crtc_flipped (GClosure         *closure,
+   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
+   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
++  CoglFrameInfo *frame_info;
++  float refresh_rate;
++
++  frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
++  refresh_rate = crtc && crtc->current_mode ?
++                 crtc->current_mode->refresh_rate :
++                 0.0f;
++
++  /* Only keep the frame info for the fastest CRTC in use, which may not be
++   * the first one to complete a flip. By only telling the compositor about the
++   * fastest monitor(s) we direct it to produce new frames fast enough to
++   * satisfy all monitors.
++   */
++  if (refresh_rate >= frame_info->refresh_rate)
++    {
++      frame_info->presentation_time = page_flip_time_ns;
++      frame_info->refresh_rate = refresh_rate;
++    }
+ 
+   if (gpu_kms != render_gpu)
+     {
+@@ -1299,7 +1320,9 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
+     return FALSE;
+ 
+   closure_container =
+-    meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
++    meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu,
++                                    NULL,
++                                    flip_closure);
+ 
+   acquire_attribs = (EGLAttrib[]) {
+     EGL_DRM_FLIP_EVENT_DATA_NV,
+@@ -1542,7 +1565,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
+   flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
+                                  g_object_ref (view),
+                                  (GClosureNotify) flip_closure_destroyed);
+-  g_closure_set_marshal (flip_closure, g_cclosure_marshal_VOID__OBJECT);
++  g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
+ 
+   /* Either flip the CRTC's of the monitor info, if we are drawing just part
+    * of the stage, or all of the CRTC's if we are drawing the whole stage.
+@@ -2687,6 +2710,15 @@ meta_renderer_native_create_offscreen (MetaRendererNative    *renderer,
+   return fb;
+ }
+ 
++static int64_t
++meta_renderer_native_get_clock_time (CoglContext *context)
++{
++  CoglRenderer *cogl_renderer = cogl_context_get_renderer (context);
++  MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data;
++
++  return meta_gpu_kms_get_current_time_ns (gpu_kms);
++}
++
+ static const CoglWinsysVtable *
+ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
+ {
+@@ -2715,6 +2747,8 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
+       vtable.onscreen_swap_buffers_with_damage =
+         meta_onscreen_native_swap_buffers_with_damage;
+ 
++      vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
++
+       vtable_inited = TRUE;
+     }
+ 
+diff --git a/src/meta-marshal.list b/src/meta-marshal.list
+new file mode 100644
+index 000000000..c1f4781d2
+--- /dev/null
++++ b/src/meta-marshal.list
+@@ -0,0 +1 @@
++VOID:OBJECT,OBJECT,INT64
+-- 
+2.18.1
+
+
+From 7204892bf5390cb68d498e9850490cc4bcbe5cca Mon Sep 17 00:00:00 2001
+From: Daniel van Vugt <[email protected]>
+Date: Tue, 10 Jul 2018 17:46:02 +0800
+Subject: [PATCH 2/3] renderer-native: Advertise _FEATURE_SWAP_THROTTLE
+
+Because it is implemented and always on. By advertising this fact
+the master clock is able to sync to the native refresh rate instead
+of always using the fallback of 60.00Hz.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=781296
+
+(cherry picked from commit e8c27603dd69d94793aed5e0525562669e8c0bca)
+---
+ src/backends/native/meta-renderer-native.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index b192c3641..929e9ca90 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -2005,6 +2005,13 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
+                   COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
+                   TRUE);
+ 
++  /* COGL_WINSYS_FEATURE_SWAP_THROTTLE is always true for this renderer
++   * because we have the call to wait_for_pending_flips on every frame.
++   */
++  COGL_FLAGS_SET (cogl_context->winsys_features,
++                  COGL_WINSYS_FEATURE_SWAP_THROTTLE,
++                  TRUE);
++
+ #ifdef HAVE_EGL_DEVICE
+   if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE)
+     COGL_FLAGS_SET (cogl_context->features,
+@@ -2639,8 +2646,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative   *renderer_native,
+     }
+ 
+   onscreen = cogl_onscreen_new (context, width, height);
+-  cogl_onscreen_set_swap_throttled (onscreen,
+-                                    _clutter_get_sync_to_vblank ());
++
++  /* We have wait_for_pending_flips hardcoded, so throttling always. */
++  cogl_onscreen_set_swap_throttled (onscreen, TRUE);
++  if (!_clutter_get_sync_to_vblank ())
++    g_warning ("Request to disable sync-to-vblank is being ignored. "
++               "MetaRendererNative does not support disabling it.");
+ 
+   if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
+     {
+-- 
+2.18.1
+
+
+From 0bd8cd5c587ad7c345557c2ea257d3892962dfb7 Mon Sep 17 00:00:00 2001
+From: Daniel van Vugt <[email protected]>
+Date: Fri, 30 Nov 2018 15:22:00 +0800
+Subject: [PATCH 3/3] renderer-native: Advertise
+ COGL_FEATURE_ID_PRESENTATION_TIME
+
+Since it's now implemented (e9e4b2b72e). Fortunately forgetting to
+advertise it didn't matter because there isn't any code yet that
+checks for it.
+
+(cherry picked from commit f6f188dad4c225bb2708e1abaac2c9a5557fe14c)
+---
+ src/backends/native/meta-renderer-native.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
+index 929e9ca90..6f4087e2e 100644
+--- a/src/backends/native/meta-renderer-native.c
++++ b/src/backends/native/meta-renderer-native.c
+@@ -1992,6 +1992,8 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
+   MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
+ #endif
+ 
++  COGL_FLAGS_SET (cogl_context->features,
++                  COGL_FEATURE_ID_PRESENTATION_TIME, TRUE);
+   COGL_FLAGS_SET (cogl_context->features,
+                   COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, TRUE);
+   /* TODO: remove this deprecated feature */
+-- 
+2.18.1
+
diff --git a/debian/patches/series b/debian/patches/series
index 0f14e78..b00a760 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,10 +1,10 @@
 theme-use-gtk_render_icon_suface-to-paint-button-icon.patch
 theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch
-clutter-Smooth-out-master-clock-to-smooth-visuals.patch
 bgo768531_workaround-startup-notifications.patch
 clutter-Avoid-rounding-compensation-when-invalidating-2D-.patch
 clutter-Fix-offscreen-effect-painting-of-clones.patch
 cogl-auto-texture-Avoid-a-double-free-crash.patch
 clutter-offscreen-effect-Disable-if-no-texture.patch
+lp1763892-add-hardware-vsync-support.patch
 debian/synaptics-support.patch
 debian/skip-texture-test.patch
-- 
ubuntu-desktop mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop

Reply via email to