Merge ~vanvugt/ubuntu/+source/mutter:fix-lp1763892-bionic into ~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic

Proposed by Daniel van Vugt
Status: Merged
Merged at revision: 133e6ba2d6ced7cea3fd6142d50f38c2eec5c184
Proposed branch: ~vanvugt/ubuntu/+source/mutter:fix-lp1763892-bionic
Merge into: ~ubuntu-desktop/ubuntu/+source/mutter:ubuntu/bionic
Diff against target: 699 lines (+424/-226)
6 files modified
debian/changelog (+9/-0)
debian/libmutter-2-0.symbols (+1/-0)
debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch (+363/-0)
debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch (+49/-0)
debian/patches/series (+2/-1)
dev/null (+0/-225)
Reviewer Review Type Date Requested Status
Marco Trevisan (Treviño) Approve
Ubuntu Desktop Pending
Review via email: mp+364362@code.launchpad.net

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 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.28 in two commits/patches:

  lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
  lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch

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

To post a comment you must log in.
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Do you have the upstream merge proposal for the backport branch too?

However, being this something upstream too, LGTM.

We we can include this in the next SRU round.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

> Do you have the upstream merge proposal for the backport branch too?

The upstream upstream link is https://gitlab.gnome.org/GNOME/mutter/merge_requests/171 and the backport branch is https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28 . But I have stopped creating MRs for backport branches in cases like this where I only want to generate a web page/patch for it because it annoyed Jonas and he asked me to stop.

In cases where an upstream backport is desired then I would create another MR. But since this is arguably an enhancement for hardware enablement I feel like it wouldn't qualify for a proper upstream backport.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

It looks like this might be held up because the previous version is held up (bug 1811900)

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I guess there are probably conflicts here now. Although LP isn't saying so.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Conflict fixed.

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

See the inline diff for the added-symbol.
I'd like to have a SRU upload without it since we don't need to use anywhere else

Revision history for this message
Daniel van Vugt (vanvugt) :
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) :
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Sorry I keep forgetting to save my inline comments. This is from a few hours ago...

Revision history for this message
Daniel van Vugt (vanvugt) :
Revision history for this message
Daniel van Vugt (vanvugt) :
Revision history for this message
Iain Lane (laney) :
Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

I've merged this one in https://code.launchpad.net/~3v1n0/ubuntu/+source/mutter/+git/mutter/+merge/366676

So I guess we can close this.

review: Approve
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

OK then.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Hmm, I don't see any close or reject option (any more). I can only delete the MP. So I will wait for the above to land first and then will permanently delete this one.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 99219d6..b728846 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
1mutter (3.28.3+git20190124-0ubuntu18.04.3) UNRELEASED; urgency=medium
2
3 * Add support for high frame rate displays (LP: #1763892):
4 - Drop clutter-Smooth-out-master-clock-to-smooth-visuals.patch
5 - Add lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
6 - Add lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
7
8 -- Daniel van Vugt <daniel.van.vugt@canonical.com> Mon, 29 Apr 2019 16:21:54 +0800
9
1mutter (3.28.3+git20190124-0ubuntu18.04.2) bionic; urgency=medium10mutter (3.28.3+git20190124-0ubuntu18.04.2) bionic; urgency=medium
211
3 * control: Add Breaks on budgie-desktop verions broken by this upload.12 * control: Add Breaks on budgie-desktop verions broken by this upload.
diff --git a/debian/libmutter-2-0.symbols b/debian/libmutter-2-0.symbols
index 1489074..89b3d01 100644
--- a/debian/libmutter-2-0.symbols
+++ b/debian/libmutter-2-0.symbols
@@ -549,6 +549,7 @@ libmutter-2.so.0 libmutter-2-0 #MINVER#
549 meta_gpu_kms_error_quark@Base 3.28.2549 meta_gpu_kms_error_quark@Base 3.28.2
550 meta_gpu_kms_flip_closure_container_free@Base 3.28.3+git20190124550 meta_gpu_kms_flip_closure_container_free@Base 3.28.3+git20190124
551 meta_gpu_kms_flip_crtc@Base 3.28.2551 meta_gpu_kms_flip_crtc@Base 3.28.2
552 meta_gpu_kms_get_current_time_ns@Base 3.28.3+git20190124-0ubuntu18.04.3
552 meta_gpu_kms_get_fd@Base 3.28.2553 meta_gpu_kms_get_fd@Base 3.28.2
553 meta_gpu_kms_get_file_path@Base 3.28.2554 meta_gpu_kms_get_file_path@Base 3.28.2
554 meta_gpu_kms_get_max_buffer_size@Base 3.28.2555 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
555deleted file mode 100644556deleted file mode 100644
index 2239837..0000000
--- a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
+++ /dev/null
@@ -1,225 +0,0 @@
1From: Daniel van Vugt <daniel.van.vugt@canonical.com>
2Date: Fri, 16 Feb 2018 02:50:59 -0600
3Subject: clutter: Smooth out master clock to smooth visuals
4
5Clutter's master clock was jittery because it included errors in cur_tick
6such as dispatch delays due to other sources. Dispatch could also occur up
7to 1ms early since GSource can only be timed to the millisecond. All of this
8could impact the visual smoothness of animations as they are displayed on
9the steady interval of the monitor, but spacially moving in less regular
10steps derived from the dispatch times.
11
12The simple fix is to ignore any jitter in dispatch timing. Try a little
13bit harder to use a precise interval that will better match the display
14hardware, and smoother visuals will follow.
15
16Bug: https://gitlab.gnome.org/GNOME/mutter/issues/25
17Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/70
18---
19 clutter/clutter/clutter-master-clock-default.c | 134 +++++++++++++++++--------
20 1 file changed, 93 insertions(+), 41 deletions(-)
21
22diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c
23index 7b2df0d..97b6d13 100644
24--- a/clutter/clutter/clutter-master-clock-default.c
25+++ b/clutter/clutter/clutter-master-clock-default.c
26@@ -69,8 +69,10 @@ struct _ClutterMasterClockDefault
27 /* the previous state of the clock, in usecs, used to compute the delta */
28 gint64 prev_tick;
29
30+ /* the ideal frame interval in usecs (inverse of your max refresh rate) */
31+ gint64 frame_interval;
32+
33 #ifdef CLUTTER_ENABLE_DEBUG
34- gint64 frame_budget;
35 gint64 remaining_budget;
36 #endif
37
38@@ -264,6 +266,41 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
39 }
40 }
41
42+static gint64
43+estimate_next_presentation_time (ClutterMasterClockDefault *master_clock)
44+{
45+ gint64 frame_phase, now, now_phase, undershoot;
46+
47+ /* In future if this was updated from the backend's (maximum) refresh rate
48+ * then that would fix: https://bugzilla.gnome.org/show_bug.cgi?id=781296
49+ */
50+ master_clock->frame_interval = G_USEC_PER_SEC /
51+ clutter_get_default_frame_rate ();
52+
53+ now = g_source_get_time (master_clock->source);
54+ now_phase = now % master_clock->frame_interval;
55+
56+ /* To be precise we would like to use:
57+ * frame_phase = a_recent_hardware_presentation_time % frame_interval;
58+ * where hardware_presentation_time must be using the same clock as
59+ * g_source_get_time. Unfortunately they're different clocks right now
60+ * so we can't.
61+ * Alternatively, we could replace g_source_get_time in future with the
62+ * current time in the clutter/cogl presentation clock, but that function
63+ * also doesn't exist yet.
64+ * Until we can get either of those, zero is fine. It just means latency
65+ * will be suboptimal by half a frame on average. We still get maximum
66+ * smoothness this way...
67+ */
68+ frame_phase = 0;
69+
70+ undershoot = frame_phase - now_phase;
71+ if (undershoot < 0)
72+ undershoot += master_clock->frame_interval;
73+
74+ return now + undershoot;
75+}
76+
77 /*
78 * master_clock_next_frame_delay:
79 * @master_clock: a #ClutterMasterClock
80@@ -276,7 +313,8 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
81 static gint
82 master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
83 {
84- gint64 now, next;
85+ gint64 now, target_presentation_time, ideal_render_start; /* timestamps */
86+ gint64 ideal_prerender_time, lateness; /* deltas */
87 gint swap_delay;
88
89 if (!master_clock_is_running (master_clock))
90@@ -307,46 +345,45 @@ master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
91 return 0;
92 }
93
94- if (master_clock->prev_tick == 0)
95- {
96- /* If we weren't previously running, then draw the next frame
97- * immediately
98- */
99- CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
100- return 0;
101- }
102-
103- /* Otherwise, wait at least 1/frame_rate seconds since we last
104- * started a frame
105- */
106 now = g_source_get_time (master_clock->source);
107
108- next = master_clock->prev_tick;
109-
110- /* If time has gone backwards then there's no way of knowing how
111- long we should wait so let's just dispatch immediately */
112- if (now <= next)
113+ /* As first preference, try to carry on smoothly from the previous frame,
114+ * even if that means we start rendering frame 2 before frame 1 has been
115+ * presented. This is why we ignore estimate_next_presentation_time here...
116+ */
117+ target_presentation_time = master_clock->prev_tick +
118+ master_clock->frame_interval;
119+ ideal_prerender_time = master_clock->frame_interval;
120+ ideal_render_start = target_presentation_time - ideal_prerender_time;
121+ lateness = now - ideal_render_start;
122+
123+ /* If we just woke from idle then try to improve the smoothness of the first
124+ * two frames some more. Otherwise the first frame would appear too old
125+ * relative to the second frame.
126+ */
127+ if (lateness >= master_clock->frame_interval)
128 {
129- CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
130-
131- return 0;
132+ target_presentation_time = estimate_next_presentation_time (master_clock);
133+ ideal_render_start = target_presentation_time - ideal_prerender_time;
134+ lateness = now - ideal_render_start;
135 }
136
137- next += (1000000L / clutter_get_default_frame_rate ());
138-
139- if (next <= now)
140+ if (lateness > 0)
141 {
142- CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
143- 1000000L / (gulong) clutter_get_default_frame_rate ());
144-
145+ CLUTTER_NOTE (SCHEDULER, "No wait required. We're already late.");
146 return 0;
147 }
148 else
149 {
150- CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
151- (next - now) / 1000);
152-
153- return (next - now) / 1000;
154+ /* We +1 here to avoid premature dispatches that would otherwise occur
155+ * repeatedly during the 1ms before 'ideal_render_start'. We don't care
156+ * if this makes the final dispatch 1ms late because the smoothing
157+ * algorithm corrects that, and it's much better than attempting to
158+ * render more frames than the hardware can physically display...
159+ */
160+ gint millisec_delay = -lateness / 1000 + 1;
161+ CLUTTER_NOTE (SCHEDULER, "Waiting %dms", millisec_delay);
162+ return millisec_delay;
163 }
164 }
165
166@@ -532,16 +569,34 @@ clutter_clock_dispatch (GSource *source,
167 ClutterMasterClockDefault *master_clock = clock_source->master_clock;
168 gboolean stages_updated = FALSE;
169 GSList *stages;
170-
171- CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
172+ gint64 smooth_tick;
173
174 _clutter_threads_acquire_lock ();
175
176 /* Get the time to use for this frame */
177- master_clock->cur_tick = g_source_get_time (source);
178+ smooth_tick = estimate_next_presentation_time (master_clock);
179+ if (smooth_tick <= master_clock->prev_tick)
180+ {
181+ /* Ordinarily this will never happen. But after we fix bug 781296, it
182+ * could happen in the rare case when the ideal frame_interval changes,
183+ * such as video mode switching or hotplugging monitors. As such it is
184+ * not considered a bug (unless it's happening without mode switching
185+ * or hotplugging).
186+ */
187+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] was premature (skipped)");
188+ _clutter_threads_release_lock ();
189+ return G_SOURCE_CONTINUE;
190+ }
191+
192+ master_clock->cur_tick = smooth_tick;
193+ if (master_clock->prev_tick)
194+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] %+ldus",
195+ (long) (master_clock->cur_tick - master_clock->prev_tick));
196+ else
197+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] startup");
198
199 #ifdef CLUTTER_ENABLE_DEBUG
200- master_clock->remaining_budget = master_clock->frame_budget;
201+ master_clock->remaining_budget = master_clock->frame_interval;
202 #endif
203
204 /* We need to protect ourselves against stages being destroyed during
205@@ -580,7 +635,7 @@ clutter_clock_dispatch (GSource *source,
206
207 _clutter_threads_release_lock ();
208
209- return TRUE;
210+ return G_SOURCE_CONTINUE;
211 }
212
213 static void
214@@ -612,10 +667,7 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
215 self->idle = FALSE;
216 self->ensure_next_iteration = FALSE;
217 self->paused = FALSE;
218-
219-#ifdef CLUTTER_ENABLE_DEBUG
220- self->frame_budget = G_USEC_PER_SEC / 60;
221-#endif
222+ self->frame_interval = G_USEC_PER_SEC / 60; /* Will be refined at runtime */
223
224 g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
225 g_source_set_can_recurse (source, FALSE);
diff --git a/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch b/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
226new file mode 1006440new file mode 100644
index 0000000..c28b267
--- /dev/null
+++ b/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
@@ -0,0 +1,363 @@
1Description: renderer-native: Add hardware presentation timing
2 Add support for getting hardware presentation times from KMS (Wayland
3 sessions). Also implement cogl_get_clock_time which is required to compare
4 and judge the age of presentation timestamps.
5 .
6 For single monitor systems this is straightforward. For multi-monitor
7 systems though we have to choose a display to sync to. The compositor
8 already partially solves this for us in the case of only one display
9 updating because it will only use the subset of monitors that are
10 changing. In the case of multiple monitors consuming the same frame
11 concurrently however, we choose the fastest one (in use at the time).
12 .
13 Patch 1 of 2
14Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
15Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/171 via backport branch https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
16Bug: https://bugzilla.gnome.org/show_bug.cgi?id=781296
17Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
18Forwarded: yes
19Last-Update: 2019-03-13
20
21diff --git a/src/Makefile.am b/src/Makefile.am
22index bcb3505c7..13862e940 100644
23--- a/src/Makefile.am
24+++ b/src/Makefile.am
25@@ -51,6 +51,8 @@ mutter_built_sources = \
26 $(dbus_login1_built_sources) \
27 meta/meta-enum-types.h \
28 meta-enum-types.c \
29+ meta-marshal.c \
30+ meta-marshal.h \
31 $(NULL)
32
33 if HAVE_REMOTE_DESKTOP
34@@ -653,6 +655,7 @@ EXTRA_DIST += \
35 libmutter.pc.in \
36 meta-enum-types.h.in \
37 meta-enum-types.c.in \
38+ meta-marshal.list \
39 org.freedesktop.login1.xml \
40 org.gnome.Mutter.DisplayConfig.xml \
41 org.gnome.Mutter.IdleMonitor.xml \
42@@ -666,7 +669,10 @@ BUILT_SOURCES = \
43 $(libmutterinclude_built_headers)
44
45 MUTTER_STAMP_FILES = stamp-meta-enum-types.h
46-CLEANFILES += $(MUTTER_STAMP_FILES)
47+CLEANFILES += \
48+ $(MUTTER_STAMP_FILES) \
49+ meta-marshal.c \
50+ meta-marshal.h
51
52 meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
53 @true
54@@ -760,3 +766,20 @@ endef
55 $(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
56 %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
57 $(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
58+
59+meta_marshal_opts = --prefix=meta_marshal --internal
60+
61+meta-marshal.h: meta-marshal.list
62+ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
63+ --header \
64+ $(meta_marshal_opts) \
65+ --output=$@ \
66+ $<
67+
68+meta-marshal.c: meta-marshal.list meta-marshal.h
69+ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
70+ --include-header=meta-marshal.h \
71+ $(meta_marshal_opts) \
72+ --body \
73+ --output=$@ \
74+ $<
75diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
76index 815caf501..e931e70f7 100644
77--- a/src/backends/native/meta-gpu-kms.c
78+++ b/src/backends/native/meta-gpu-kms.c
79@@ -27,6 +27,7 @@
80 #include <errno.h>
81 #include <poll.h>
82 #include <string.h>
83+#include <time.h>
84 #include <xf86drm.h>
85 #include <xf86drmMode.h>
86
87@@ -51,6 +52,7 @@ typedef struct _MetaGpuKmsFlipClosureContainer
88 {
89 GClosure *flip_closure;
90 MetaGpuKms *gpu_kms;
91+ MetaCrtc *crtc;
92 } MetaGpuKmsFlipClosureContainer;
93
94 struct _MetaGpuKms
95@@ -61,6 +63,8 @@ struct _MetaGpuKms
96 char *file_path;
97 GSource *source;
98
99+ clockid_t clock_id;
100+
101 drmModeConnector **connectors;
102 unsigned int n_connectors;
103
104@@ -166,18 +170,26 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
105
106 static void
107 invoke_flip_closure (GClosure *flip_closure,
108- MetaGpuKms *gpu_kms)
109+ MetaGpuKms *gpu_kms,
110+ MetaCrtc *crtc,
111+ int64_t page_flip_time_ns)
112 {
113 GValue params[] = {
114 G_VALUE_INIT,
115- G_VALUE_INIT
116+ G_VALUE_INIT,
117+ G_VALUE_INIT,
118+ G_VALUE_INIT,
119 };
120
121 g_value_init (&params[0], G_TYPE_POINTER);
122 g_value_set_pointer (&params[0], flip_closure);
123 g_value_init (&params[1], G_TYPE_OBJECT);
124 g_value_set_object (&params[1], gpu_kms);
125- g_closure_invoke (flip_closure, NULL, 2, params, NULL);
126+ g_value_init (&params[2], G_TYPE_OBJECT);
127+ g_value_set_object (&params[2], crtc);
128+ g_value_init (&params[3], G_TYPE_INT64);
129+ g_value_set_int64 (&params[3], page_flip_time_ns);
130+ g_closure_invoke (flip_closure, NULL, 4, params, NULL);
131 g_closure_unref (flip_closure);
132 }
133
134@@ -217,6 +229,7 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
135
136 MetaGpuKmsFlipClosureContainer *
137 meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
138+ MetaCrtc *crtc,
139 GClosure *flip_closure)
140 {
141 MetaGpuKmsFlipClosureContainer *closure_container;
142@@ -224,7 +237,8 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
143 closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
144 *closure_container = (MetaGpuKmsFlipClosureContainer) {
145 .flip_closure = flip_closure,
146- .gpu_kms = gpu_kms
147+ .gpu_kms = gpu_kms,
148+ .crtc = crtc
149 };
150
151 return closure_container;
152@@ -264,6 +278,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
153 int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
154
155 closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
156+ crtc,
157 flip_closure);
158
159 ret = drmModePageFlip (kms_fd,
160@@ -297,6 +312,23 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
161 return TRUE;
162 }
163
164+static int64_t
165+timespec_to_nanoseconds (const struct timespec *ts)
166+{
167+ const int64_t one_billion = 1000000000;
168+
169+ return ((int64_t) ts->tv_sec) * one_billion + ts->tv_nsec;
170+}
171+
172+static int64_t
173+timeval_to_nanoseconds (const struct timeval *tv)
174+{
175+ int64_t usec = ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec;
176+ int64_t nsec = usec * 1000;
177+
178+ return nsec;
179+}
180+
181 static void
182 page_flip_handler (int fd,
183 unsigned int frame,
184@@ -307,8 +339,12 @@ page_flip_handler (int fd,
185 MetaGpuKmsFlipClosureContainer *closure_container = user_data;
186 GClosure *flip_closure = closure_container->flip_closure;
187 MetaGpuKms *gpu_kms = closure_container->gpu_kms;
188+ struct timeval page_flip_time = {sec, usec};
189
190- invoke_flip_closure (flip_closure, gpu_kms);
191+ invoke_flip_closure (flip_closure,
192+ gpu_kms,
193+ closure_container->crtc,
194+ timeval_to_nanoseconds (&page_flip_time));
195 meta_gpu_kms_flip_closure_container_free (closure_container);
196 }
197
198@@ -381,6 +417,17 @@ meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
199 return gpu_kms->file_path;
200 }
201
202+int64_t
203+meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
204+{
205+ struct timespec ts;
206+
207+ if (clock_gettime (gpu_kms->clock_id, &ts))
208+ return 0;
209+
210+ return timespec_to_nanoseconds (&ts);
211+}
212+
213 void
214 meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
215 uint64_t state)
216@@ -680,6 +727,17 @@ init_crtcs (MetaGpuKms *gpu_kms,
217 meta_gpu_take_crtcs (gpu, crtcs);
218 }
219
220+static void
221+init_frame_clock (MetaGpuKms *gpu_kms)
222+{
223+ uint64_t uses_monotonic;
224+
225+ if (drmGetCap (gpu_kms->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic) != 0)
226+ uses_monotonic = 0;
227+
228+ gpu_kms->clock_id = uses_monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME;
229+}
230+
231 static void
232 init_outputs (MetaGpuKms *gpu_kms,
233 MetaKmsResources *resources)
234@@ -809,6 +867,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
235 init_modes (gpu_kms, resources.resources);
236 init_crtcs (gpu_kms, &resources);
237 init_outputs (gpu_kms, &resources);
238+ init_frame_clock (gpu_kms);
239
240 meta_kms_resources_release (&resources);
241
242diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
243index 01c3f2c0c..6e7a2e56c 100644
244--- a/src/backends/native/meta-gpu-kms.h
245+++ b/src/backends/native/meta-gpu-kms.h
246@@ -81,6 +81,8 @@ int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
247
248 const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms);
249
250+int64_t meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms);
251+
252 void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms,
253 int *max_width,
254 int *max_height);
255@@ -97,6 +99,7 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
256 float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
257
258 MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
259+ MetaCrtc *crtc,
260 GClosure *flip_closure);
261
262 void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
263diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
264index 470da8845..f6adb3fee 100644
265--- a/src/backends/native/meta-renderer-native.c
266+++ b/src/backends/native/meta-renderer-native.c
267@@ -61,6 +61,7 @@
268 #include "backends/native/meta-monitor-manager-kms.h"
269 #include "backends/native/meta-renderer-native.h"
270 #include "backends/native/meta-renderer-native-gles3.h"
271+#include "meta-marshal.h"
272 #include "cogl/cogl.h"
273 #include "core/boxes-private.h"
274
275@@ -1157,6 +1158,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
276 static void
277 on_crtc_flipped (GClosure *closure,
278 MetaGpuKms *gpu_kms,
279+ MetaCrtc *crtc,
280+ int64_t page_flip_time_ns,
281 MetaRendererView *view)
282 {
283 ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
284@@ -1167,6 +1170,24 @@ on_crtc_flipped (GClosure *closure,
285 MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
286 MetaRendererNative *renderer_native = onscreen_native->renderer_native;
287 MetaGpuKms *render_gpu = onscreen_native->render_gpu;
288+ CoglFrameInfo *frame_info;
289+ float refresh_rate;
290+
291+ frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
292+ refresh_rate = crtc && crtc->current_mode ?
293+ crtc->current_mode->refresh_rate :
294+ 0.0f;
295+
296+ /* Only keep the frame info for the fastest CRTC in use, which may not be
297+ * the first one to complete a flip. By only telling the compositor about the
298+ * fastest monitor(s) we direct it to produce new frames fast enough to
299+ * satisfy all monitors.
300+ */
301+ if (refresh_rate >= frame_info->refresh_rate)
302+ {
303+ frame_info->presentation_time = page_flip_time_ns;
304+ frame_info->refresh_rate = refresh_rate;
305+ }
306
307 if (gpu_kms != render_gpu)
308 {
309@@ -1297,7 +1318,9 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
310 return FALSE;
311
312 closure_container =
313- meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
314+ meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu,
315+ NULL,
316+ flip_closure);
317
318 acquire_attribs = (EGLAttrib[]) {
319 EGL_DRM_FLIP_EVENT_DATA_NV,
320@@ -1540,7 +1563,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
321 flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
322 g_object_ref (view),
323 (GClosureNotify) flip_closure_destroyed);
324- g_closure_set_marshal (flip_closure, g_cclosure_marshal_VOID__OBJECT);
325+ g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
326
327 /* Either flip the CRTC's of the monitor info, if we are drawing just part
328 * of the stage, or all of the CRTC's if we are drawing the whole stage.
329@@ -2673,6 +2696,15 @@ meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
330 return fb;
331 }
332
333+static int64_t
334+meta_renderer_native_get_clock_time (CoglContext *context)
335+{
336+ CoglRenderer *cogl_renderer = cogl_context_get_renderer (context);
337+ MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data;
338+
339+ return meta_gpu_kms_get_current_time_ns (gpu_kms);
340+}
341+
342 static const CoglWinsysVtable *
343 get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
344 {
345@@ -2701,6 +2733,8 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
346 vtable.onscreen_swap_buffers_with_damage =
347 meta_onscreen_native_swap_buffers_with_damage;
348
349+ vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
350+
351 vtable_inited = TRUE;
352 }
353
354diff --git a/src/meta-marshal.list b/src/meta-marshal.list
355new file mode 100644
356index 000000000..c1f4781d2
357--- /dev/null
358+++ b/src/meta-marshal.list
359@@ -0,0 +1 @@
360+VOID:OBJECT,OBJECT,INT64
361--
3622.20.1
363
diff --git a/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch b/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
0new file mode 100644364new file mode 100644
index 0000000..a80b993
--- /dev/null
+++ b/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
@@ -0,0 +1,49 @@
1Description: renderer-native: Advertise _FEATURE_SWAP_THROTTLE
2 Because it is implemented and always on. By advertising this fact
3 the master clock is able to sync to the native refresh rate instead
4 of always using the fallback of 60.00Hz.
5 .
6 Patch 2 of 2
7Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
8Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/171 via backport branch https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
9Bug: https://bugzilla.gnome.org/show_bug.cgi?id=781296
10Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
11Forwarded: yes
12Last-Update: 2019-03-13
13
14diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
15index f6adb3fee..fa2e9b7d3 100644
16--- a/src/backends/native/meta-renderer-native.c
17+++ b/src/backends/native/meta-renderer-native.c
18@@ -1997,6 +1997,13 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
19 COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
20 TRUE);
21
22+ /* COGL_WINSYS_FEATURE_SWAP_THROTTLE is always true for this renderer
23+ * because we have the call to wait_for_pending_flips on every frame.
24+ */
25+ COGL_FLAGS_SET (cogl_context->winsys_features,
26+ COGL_WINSYS_FEATURE_SWAP_THROTTLE,
27+ TRUE);
28+
29 #ifdef HAVE_EGL_DEVICE
30 if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE)
31 COGL_FLAGS_SET (cogl_context->features,
32@@ -2625,8 +2632,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
33 }
34
35 onscreen = cogl_onscreen_new (context, width, height);
36- cogl_onscreen_set_swap_throttled (onscreen,
37- _clutter_get_sync_to_vblank ());
38+
39+ /* We have wait_for_pending_flips hardcoded, so throttling always. */
40+ cogl_onscreen_set_swap_throttled (onscreen, TRUE);
41+ if (!_clutter_get_sync_to_vblank ())
42+ g_warning ("Request to disable sync-to-vblank is being ignored. "
43+ "MetaRendererNative does not support disabling it.");
44
45 if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
46 {
47--
482.20.1
49
diff --git a/debian/patches/series b/debian/patches/series
index 198db5a..5d87807 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,8 +1,9 @@
1theme-use-gtk_render_icon_suface-to-paint-button-icon.patch1theme-use-gtk_render_icon_suface-to-paint-button-icon.patch
2theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch2theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch
3clutter-Smooth-out-master-clock-to-smooth-visuals.patch
4clutter-Fix-offscreen-effect-painting-of-clones.patch3clutter-Fix-offscreen-effect-painting-of-clones.patch
5bgo768531_workaround-startup-notifications.patch4bgo768531_workaround-startup-notifications.patch
5lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
6lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
6debian/synaptics-support.patch7debian/synaptics-support.patch
7debian/skip-failing-tests.patch8debian/skip-failing-tests.patch
8debian/skip-failing-tests-325.patch9debian/skip-failing-tests-325.patch

Subscribers

People subscribed via source and target branches