Daniel van Vugt has proposed merging 
~vanvugt/ubuntu/+source/mutter:fix-lp1763892-cosmic into 
~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/cosmic.

Commit message:
Remove 60 FPS limitation, thus supporting high frame rates

For Xorg the only fix required was to remove the spurious patch:
  clutter-Smooth-out-master-clock-to-smooth-visuals.patch
which had the effect of imposing a secondary 60 FPS limitation.
That patch never landed upstream.

For Wayland you need both the above fix, and the introduction of
hardware vsync support which was upstreamed in mutter 3.32 and is
backported to 3.30 in the new patch:
  lp1763892-add-hardware-vsync-support.patch

https://bugs.launchpad.net/bugs/1763892

Requested reviews:
  Ubuntu Server Dev import team (usd-import-team)

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

*** Launchpad is refusing to display a diff right now. But you can still view 
it by clicking on the last commit ID.
-- 
Your team Ubuntu Desktop is subscribed to branch 
~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 <daniel.van.v...@canonical.com>  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 <daniel.van.v...@canonical.com>
-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 <daniel.van.v...@canonical.com>
+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 <daniel.van.v...@canonical.com>
+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 <daniel.van.v...@canonical.com>
+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
ubuntu-desktop@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-desktop

Reply via email to