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

Proposed by Daniel van Vugt on 2019-03-13
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) (community) Approve on 2019-05-03
Ubuntu Desktop 2019-03-13 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.
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
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.

Daniel van Vugt (vanvugt) wrote :

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

Daniel van Vugt (vanvugt) wrote :

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

Daniel van Vugt (vanvugt) wrote :

Conflict fixed.

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

Daniel van Vugt (vanvugt) :
Daniel van Vugt (vanvugt) wrote :

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

Daniel van Vugt (vanvugt) :
Daniel van Vugt (vanvugt) :
Iain Lane (laney) :
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
Daniel van Vugt (vanvugt) wrote :

OK then.

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
1diff --git a/debian/changelog b/debian/changelog
2index 99219d6..b728846 100644
3--- a/debian/changelog
4+++ b/debian/changelog
5@@ -1,3 +1,12 @@
6+mutter (3.28.3+git20190124-0ubuntu18.04.3) UNRELEASED; urgency=medium
7+
8+ * Add support for high frame rate displays (LP: #1763892):
9+ - Drop clutter-Smooth-out-master-clock-to-smooth-visuals.patch
10+ - Add lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
11+ - Add lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
12+
13+ -- Daniel van Vugt <daniel.van.vugt@canonical.com> Mon, 29 Apr 2019 16:21:54 +0800
14+
15 mutter (3.28.3+git20190124-0ubuntu18.04.2) bionic; urgency=medium
16
17 * control: Add Breaks on budgie-desktop verions broken by this upload.
18diff --git a/debian/libmutter-2-0.symbols b/debian/libmutter-2-0.symbols
19index 1489074..89b3d01 100644
20--- a/debian/libmutter-2-0.symbols
21+++ b/debian/libmutter-2-0.symbols
22@@ -549,6 +549,7 @@ libmutter-2.so.0 libmutter-2-0 #MINVER#
23 meta_gpu_kms_error_quark@Base 3.28.2
24 meta_gpu_kms_flip_closure_container_free@Base 3.28.3+git20190124
25 meta_gpu_kms_flip_crtc@Base 3.28.2
26+ meta_gpu_kms_get_current_time_ns@Base 3.28.3+git20190124-0ubuntu18.04.3
27 meta_gpu_kms_get_fd@Base 3.28.2
28 meta_gpu_kms_get_file_path@Base 3.28.2
29 meta_gpu_kms_get_max_buffer_size@Base 3.28.2
30diff --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
31deleted file mode 100644
32index 2239837..0000000
33--- a/debian/patches/clutter-Smooth-out-master-clock-to-smooth-visuals.patch
34+++ /dev/null
35@@ -1,225 +0,0 @@
36-From: Daniel van Vugt <daniel.van.vugt@canonical.com>
37-Date: Fri, 16 Feb 2018 02:50:59 -0600
38-Subject: clutter: Smooth out master clock to smooth visuals
39-
40-Clutter's master clock was jittery because it included errors in cur_tick
41-such as dispatch delays due to other sources. Dispatch could also occur up
42-to 1ms early since GSource can only be timed to the millisecond. All of this
43-could impact the visual smoothness of animations as they are displayed on
44-the steady interval of the monitor, but spacially moving in less regular
45-steps derived from the dispatch times.
46-
47-The simple fix is to ignore any jitter in dispatch timing. Try a little
48-bit harder to use a precise interval that will better match the display
49-hardware, and smoother visuals will follow.
50-
51-Bug: https://gitlab.gnome.org/GNOME/mutter/issues/25
52-Forwarded: https://gitlab.gnome.org/GNOME/mutter/merge_requests/70
53----
54- clutter/clutter/clutter-master-clock-default.c | 134 +++++++++++++++++--------
55- 1 file changed, 93 insertions(+), 41 deletions(-)
56-
57-diff --git a/clutter/clutter/clutter-master-clock-default.c b/clutter/clutter/clutter-master-clock-default.c
58-index 7b2df0d..97b6d13 100644
59---- a/clutter/clutter/clutter-master-clock-default.c
60-+++ b/clutter/clutter/clutter-master-clock-default.c
61-@@ -69,8 +69,10 @@ struct _ClutterMasterClockDefault
62- /* the previous state of the clock, in usecs, used to compute the delta */
63- gint64 prev_tick;
64-
65-+ /* the ideal frame interval in usecs (inverse of your max refresh rate) */
66-+ gint64 frame_interval;
67-+
68- #ifdef CLUTTER_ENABLE_DEBUG
69-- gint64 frame_budget;
70- gint64 remaining_budget;
71- #endif
72-
73-@@ -264,6 +266,41 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
74- }
75- }
76-
77-+static gint64
78-+estimate_next_presentation_time (ClutterMasterClockDefault *master_clock)
79-+{
80-+ gint64 frame_phase, now, now_phase, undershoot;
81-+
82-+ /* In future if this was updated from the backend's (maximum) refresh rate
83-+ * then that would fix: https://bugzilla.gnome.org/show_bug.cgi?id=781296
84-+ */
85-+ master_clock->frame_interval = G_USEC_PER_SEC /
86-+ clutter_get_default_frame_rate ();
87-+
88-+ now = g_source_get_time (master_clock->source);
89-+ now_phase = now % master_clock->frame_interval;
90-+
91-+ /* To be precise we would like to use:
92-+ * frame_phase = a_recent_hardware_presentation_time % frame_interval;
93-+ * where hardware_presentation_time must be using the same clock as
94-+ * g_source_get_time. Unfortunately they're different clocks right now
95-+ * so we can't.
96-+ * Alternatively, we could replace g_source_get_time in future with the
97-+ * current time in the clutter/cogl presentation clock, but that function
98-+ * also doesn't exist yet.
99-+ * Until we can get either of those, zero is fine. It just means latency
100-+ * will be suboptimal by half a frame on average. We still get maximum
101-+ * smoothness this way...
102-+ */
103-+ frame_phase = 0;
104-+
105-+ undershoot = frame_phase - now_phase;
106-+ if (undershoot < 0)
107-+ undershoot += master_clock->frame_interval;
108-+
109-+ return now + undershoot;
110-+}
111-+
112- /*
113- * master_clock_next_frame_delay:
114- * @master_clock: a #ClutterMasterClock
115-@@ -276,7 +313,8 @@ master_clock_reschedule_stage_updates (ClutterMasterClockDefault *master_clock,
116- static gint
117- master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
118- {
119-- gint64 now, next;
120-+ gint64 now, target_presentation_time, ideal_render_start; /* timestamps */
121-+ gint64 ideal_prerender_time, lateness; /* deltas */
122- gint swap_delay;
123-
124- if (!master_clock_is_running (master_clock))
125-@@ -307,46 +345,45 @@ master_clock_next_frame_delay (ClutterMasterClockDefault *master_clock)
126- return 0;
127- }
128-
129-- if (master_clock->prev_tick == 0)
130-- {
131-- /* If we weren't previously running, then draw the next frame
132-- * immediately
133-- */
134-- CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately");
135-- return 0;
136-- }
137--
138-- /* Otherwise, wait at least 1/frame_rate seconds since we last
139-- * started a frame
140-- */
141- now = g_source_get_time (master_clock->source);
142-
143-- next = master_clock->prev_tick;
144--
145-- /* If time has gone backwards then there's no way of knowing how
146-- long we should wait so let's just dispatch immediately */
147-- if (now <= next)
148-+ /* As first preference, try to carry on smoothly from the previous frame,
149-+ * even if that means we start rendering frame 2 before frame 1 has been
150-+ * presented. This is why we ignore estimate_next_presentation_time here...
151-+ */
152-+ target_presentation_time = master_clock->prev_tick +
153-+ master_clock->frame_interval;
154-+ ideal_prerender_time = master_clock->frame_interval;
155-+ ideal_render_start = target_presentation_time - ideal_prerender_time;
156-+ lateness = now - ideal_render_start;
157-+
158-+ /* If we just woke from idle then try to improve the smoothness of the first
159-+ * two frames some more. Otherwise the first frame would appear too old
160-+ * relative to the second frame.
161-+ */
162-+ if (lateness >= master_clock->frame_interval)
163- {
164-- CLUTTER_NOTE (SCHEDULER, "Time has gone backwards");
165--
166-- return 0;
167-+ target_presentation_time = estimate_next_presentation_time (master_clock);
168-+ ideal_render_start = target_presentation_time - ideal_prerender_time;
169-+ lateness = now - ideal_render_start;
170- }
171-
172-- next += (1000000L / clutter_get_default_frame_rate ());
173--
174-- if (next <= now)
175-+ if (lateness > 0)
176- {
177-- CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs",
178-- 1000000L / (gulong) clutter_get_default_frame_rate ());
179--
180-+ CLUTTER_NOTE (SCHEDULER, "No wait required. We're already late.");
181- return 0;
182- }
183- else
184- {
185-- CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs",
186-- (next - now) / 1000);
187--
188-- return (next - now) / 1000;
189-+ /* We +1 here to avoid premature dispatches that would otherwise occur
190-+ * repeatedly during the 1ms before 'ideal_render_start'. We don't care
191-+ * if this makes the final dispatch 1ms late because the smoothing
192-+ * algorithm corrects that, and it's much better than attempting to
193-+ * render more frames than the hardware can physically display...
194-+ */
195-+ gint millisec_delay = -lateness / 1000 + 1;
196-+ CLUTTER_NOTE (SCHEDULER, "Waiting %dms", millisec_delay);
197-+ return millisec_delay;
198- }
199- }
200-
201-@@ -532,16 +569,34 @@ clutter_clock_dispatch (GSource *source,
202- ClutterMasterClockDefault *master_clock = clock_source->master_clock;
203- gboolean stages_updated = FALSE;
204- GSList *stages;
205--
206-- CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
207-+ gint64 smooth_tick;
208-
209- _clutter_threads_acquire_lock ();
210-
211- /* Get the time to use for this frame */
212-- master_clock->cur_tick = g_source_get_time (source);
213-+ smooth_tick = estimate_next_presentation_time (master_clock);
214-+ if (smooth_tick <= master_clock->prev_tick)
215-+ {
216-+ /* Ordinarily this will never happen. But after we fix bug 781296, it
217-+ * could happen in the rare case when the ideal frame_interval changes,
218-+ * such as video mode switching or hotplugging monitors. As such it is
219-+ * not considered a bug (unless it's happening without mode switching
220-+ * or hotplugging).
221-+ */
222-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] was premature (skipped)");
223-+ _clutter_threads_release_lock ();
224-+ return G_SOURCE_CONTINUE;
225-+ }
226-+
227-+ master_clock->cur_tick = smooth_tick;
228-+ if (master_clock->prev_tick)
229-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] %+ldus",
230-+ (long) (master_clock->cur_tick - master_clock->prev_tick));
231-+ else
232-+ CLUTTER_NOTE (SCHEDULER, "Master clock [tick] startup");
233-
234- #ifdef CLUTTER_ENABLE_DEBUG
235-- master_clock->remaining_budget = master_clock->frame_budget;
236-+ master_clock->remaining_budget = master_clock->frame_interval;
237- #endif
238-
239- /* We need to protect ourselves against stages being destroyed during
240-@@ -580,7 +635,7 @@ clutter_clock_dispatch (GSource *source,
241-
242- _clutter_threads_release_lock ();
243-
244-- return TRUE;
245-+ return G_SOURCE_CONTINUE;
246- }
247-
248- static void
249-@@ -612,10 +667,7 @@ clutter_master_clock_default_init (ClutterMasterClockDefault *self)
250- self->idle = FALSE;
251- self->ensure_next_iteration = FALSE;
252- self->paused = FALSE;
253--
254--#ifdef CLUTTER_ENABLE_DEBUG
255-- self->frame_budget = G_USEC_PER_SEC / 60;
256--#endif
257-+ self->frame_interval = G_USEC_PER_SEC / 60; /* Will be refined at runtime */
258-
259- g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
260- g_source_set_can_recurse (source, FALSE);
261diff --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
262new file mode 100644
263index 0000000..c28b267
264--- /dev/null
265+++ b/debian/patches/lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
266@@ -0,0 +1,363 @@
267+Description: renderer-native: Add hardware presentation timing
268+ Add support for getting hardware presentation times from KMS (Wayland
269+ sessions). Also implement cogl_get_clock_time which is required to compare
270+ and judge the age of presentation timestamps.
271+ .
272+ For single monitor systems this is straightforward. For multi-monitor
273+ systems though we have to choose a display to sync to. The compositor
274+ already partially solves this for us in the case of only one display
275+ updating because it will only use the subset of monitors that are
276+ changing. In the case of multiple monitors consuming the same frame
277+ concurrently however, we choose the fastest one (in use at the time).
278+ .
279+ Patch 1 of 2
280+Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
281+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/171 via backport branch https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
282+Bug: https://bugzilla.gnome.org/show_bug.cgi?id=781296
283+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
284+Forwarded: yes
285+Last-Update: 2019-03-13
286+
287+diff --git a/src/Makefile.am b/src/Makefile.am
288+index bcb3505c7..13862e940 100644
289+--- a/src/Makefile.am
290++++ b/src/Makefile.am
291+@@ -51,6 +51,8 @@ mutter_built_sources = \
292+ $(dbus_login1_built_sources) \
293+ meta/meta-enum-types.h \
294+ meta-enum-types.c \
295++ meta-marshal.c \
296++ meta-marshal.h \
297+ $(NULL)
298+
299+ if HAVE_REMOTE_DESKTOP
300+@@ -653,6 +655,7 @@ EXTRA_DIST += \
301+ libmutter.pc.in \
302+ meta-enum-types.h.in \
303+ meta-enum-types.c.in \
304++ meta-marshal.list \
305+ org.freedesktop.login1.xml \
306+ org.gnome.Mutter.DisplayConfig.xml \
307+ org.gnome.Mutter.IdleMonitor.xml \
308+@@ -666,7 +669,10 @@ BUILT_SOURCES = \
309+ $(libmutterinclude_built_headers)
310+
311+ MUTTER_STAMP_FILES = stamp-meta-enum-types.h
312+-CLEANFILES += $(MUTTER_STAMP_FILES)
313++CLEANFILES += \
314++ $(MUTTER_STAMP_FILES) \
315++ meta-marshal.c \
316++ meta-marshal.h
317+
318+ meta/meta-enum-types.h: stamp-meta-enum-types.h Makefile
319+ @true
320+@@ -760,3 +766,20 @@ endef
321+ $(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
322+ %-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
323+ $(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
324++
325++meta_marshal_opts = --prefix=meta_marshal --internal
326++
327++meta-marshal.h: meta-marshal.list
328++ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
329++ --header \
330++ $(meta_marshal_opts) \
331++ --output=$@ \
332++ $<
333++
334++meta-marshal.c: meta-marshal.list meta-marshal.h
335++ $(AM_V_GEN)$(GLIB_GENMARSHAL) \
336++ --include-header=meta-marshal.h \
337++ $(meta_marshal_opts) \
338++ --body \
339++ --output=$@ \
340++ $<
341+diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
342+index 815caf501..e931e70f7 100644
343+--- a/src/backends/native/meta-gpu-kms.c
344++++ b/src/backends/native/meta-gpu-kms.c
345+@@ -27,6 +27,7 @@
346+ #include <errno.h>
347+ #include <poll.h>
348+ #include <string.h>
349++#include <time.h>
350+ #include <xf86drm.h>
351+ #include <xf86drmMode.h>
352+
353+@@ -51,6 +52,7 @@ typedef struct _MetaGpuKmsFlipClosureContainer
354+ {
355+ GClosure *flip_closure;
356+ MetaGpuKms *gpu_kms;
357++ MetaCrtc *crtc;
358+ } MetaGpuKmsFlipClosureContainer;
359+
360+ struct _MetaGpuKms
361+@@ -61,6 +63,8 @@ struct _MetaGpuKms
362+ char *file_path;
363+ GSource *source;
364+
365++ clockid_t clock_id;
366++
367+ drmModeConnector **connectors;
368+ unsigned int n_connectors;
369+
370+@@ -166,18 +170,26 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
371+
372+ static void
373+ invoke_flip_closure (GClosure *flip_closure,
374+- MetaGpuKms *gpu_kms)
375++ MetaGpuKms *gpu_kms,
376++ MetaCrtc *crtc,
377++ int64_t page_flip_time_ns)
378+ {
379+ GValue params[] = {
380+ G_VALUE_INIT,
381+- G_VALUE_INIT
382++ G_VALUE_INIT,
383++ G_VALUE_INIT,
384++ G_VALUE_INIT,
385+ };
386+
387+ g_value_init (&params[0], G_TYPE_POINTER);
388+ g_value_set_pointer (&params[0], flip_closure);
389+ g_value_init (&params[1], G_TYPE_OBJECT);
390+ g_value_set_object (&params[1], gpu_kms);
391+- g_closure_invoke (flip_closure, NULL, 2, params, NULL);
392++ g_value_init (&params[2], G_TYPE_OBJECT);
393++ g_value_set_object (&params[2], crtc);
394++ g_value_init (&params[3], G_TYPE_INT64);
395++ g_value_set_int64 (&params[3], page_flip_time_ns);
396++ g_closure_invoke (flip_closure, NULL, 4, params, NULL);
397+ g_closure_unref (flip_closure);
398+ }
399+
400+@@ -217,6 +229,7 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
401+
402+ MetaGpuKmsFlipClosureContainer *
403+ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
404++ MetaCrtc *crtc,
405+ GClosure *flip_closure)
406+ {
407+ MetaGpuKmsFlipClosureContainer *closure_container;
408+@@ -224,7 +237,8 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
409+ closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
410+ *closure_container = (MetaGpuKmsFlipClosureContainer) {
411+ .flip_closure = flip_closure,
412+- .gpu_kms = gpu_kms
413++ .gpu_kms = gpu_kms,
414++ .crtc = crtc
415+ };
416+
417+ return closure_container;
418+@@ -264,6 +278,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
419+ int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
420+
421+ closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
422++ crtc,
423+ flip_closure);
424+
425+ ret = drmModePageFlip (kms_fd,
426+@@ -297,6 +312,23 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
427+ return TRUE;
428+ }
429+
430++static int64_t
431++timespec_to_nanoseconds (const struct timespec *ts)
432++{
433++ const int64_t one_billion = 1000000000;
434++
435++ return ((int64_t) ts->tv_sec) * one_billion + ts->tv_nsec;
436++}
437++
438++static int64_t
439++timeval_to_nanoseconds (const struct timeval *tv)
440++{
441++ int64_t usec = ((int64_t) tv->tv_sec) * G_USEC_PER_SEC + tv->tv_usec;
442++ int64_t nsec = usec * 1000;
443++
444++ return nsec;
445++}
446++
447+ static void
448+ page_flip_handler (int fd,
449+ unsigned int frame,
450+@@ -307,8 +339,12 @@ page_flip_handler (int fd,
451+ MetaGpuKmsFlipClosureContainer *closure_container = user_data;
452+ GClosure *flip_closure = closure_container->flip_closure;
453+ MetaGpuKms *gpu_kms = closure_container->gpu_kms;
454++ struct timeval page_flip_time = {sec, usec};
455+
456+- invoke_flip_closure (flip_closure, gpu_kms);
457++ invoke_flip_closure (flip_closure,
458++ gpu_kms,
459++ closure_container->crtc,
460++ timeval_to_nanoseconds (&page_flip_time));
461+ meta_gpu_kms_flip_closure_container_free (closure_container);
462+ }
463+
464+@@ -381,6 +417,17 @@ meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms)
465+ return gpu_kms->file_path;
466+ }
467+
468++int64_t
469++meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms)
470++{
471++ struct timespec ts;
472++
473++ if (clock_gettime (gpu_kms->clock_id, &ts))
474++ return 0;
475++
476++ return timespec_to_nanoseconds (&ts);
477++}
478++
479+ void
480+ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
481+ uint64_t state)
482+@@ -680,6 +727,17 @@ init_crtcs (MetaGpuKms *gpu_kms,
483+ meta_gpu_take_crtcs (gpu, crtcs);
484+ }
485+
486++static void
487++init_frame_clock (MetaGpuKms *gpu_kms)
488++{
489++ uint64_t uses_monotonic;
490++
491++ if (drmGetCap (gpu_kms->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &uses_monotonic) != 0)
492++ uses_monotonic = 0;
493++
494++ gpu_kms->clock_id = uses_monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME;
495++}
496++
497+ static void
498+ init_outputs (MetaGpuKms *gpu_kms,
499+ MetaKmsResources *resources)
500+@@ -809,6 +867,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
501+ init_modes (gpu_kms, resources.resources);
502+ init_crtcs (gpu_kms, &resources);
503+ init_outputs (gpu_kms, &resources);
504++ init_frame_clock (gpu_kms);
505+
506+ meta_kms_resources_release (&resources);
507+
508+diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
509+index 01c3f2c0c..6e7a2e56c 100644
510+--- a/src/backends/native/meta-gpu-kms.h
511++++ b/src/backends/native/meta-gpu-kms.h
512+@@ -81,6 +81,8 @@ int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);
513+
514+ const char * meta_gpu_kms_get_file_path (MetaGpuKms *gpu_kms);
515+
516++int64_t meta_gpu_kms_get_current_time_ns (MetaGpuKms *gpu_kms);
517++
518+ void meta_gpu_kms_get_max_buffer_size (MetaGpuKms *gpu_kms,
519+ int *max_width,
520+ int *max_height);
521+@@ -97,6 +99,7 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
522+ float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
523+
524+ MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
525++ MetaCrtc *crtc,
526+ GClosure *flip_closure);
527+
528+ void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
529+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
530+index 470da8845..f6adb3fee 100644
531+--- a/src/backends/native/meta-renderer-native.c
532++++ b/src/backends/native/meta-renderer-native.c
533+@@ -61,6 +61,7 @@
534+ #include "backends/native/meta-monitor-manager-kms.h"
535+ #include "backends/native/meta-renderer-native.h"
536+ #include "backends/native/meta-renderer-native-gles3.h"
537++#include "meta-marshal.h"
538+ #include "cogl/cogl.h"
539+ #include "core/boxes-private.h"
540+
541+@@ -1157,6 +1158,8 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
542+ static void
543+ on_crtc_flipped (GClosure *closure,
544+ MetaGpuKms *gpu_kms,
545++ MetaCrtc *crtc,
546++ int64_t page_flip_time_ns,
547+ MetaRendererView *view)
548+ {
549+ ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
550+@@ -1167,6 +1170,24 @@ on_crtc_flipped (GClosure *closure,
551+ MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
552+ MetaRendererNative *renderer_native = onscreen_native->renderer_native;
553+ MetaGpuKms *render_gpu = onscreen_native->render_gpu;
554++ CoglFrameInfo *frame_info;
555++ float refresh_rate;
556++
557++ frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
558++ refresh_rate = crtc && crtc->current_mode ?
559++ crtc->current_mode->refresh_rate :
560++ 0.0f;
561++
562++ /* Only keep the frame info for the fastest CRTC in use, which may not be
563++ * the first one to complete a flip. By only telling the compositor about the
564++ * fastest monitor(s) we direct it to produce new frames fast enough to
565++ * satisfy all monitors.
566++ */
567++ if (refresh_rate >= frame_info->refresh_rate)
568++ {
569++ frame_info->presentation_time = page_flip_time_ns;
570++ frame_info->refresh_rate = refresh_rate;
571++ }
572+
573+ if (gpu_kms != render_gpu)
574+ {
575+@@ -1297,7 +1318,9 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
576+ return FALSE;
577+
578+ closure_container =
579+- meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
580++ meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu,
581++ NULL,
582++ flip_closure);
583+
584+ acquire_attribs = (EGLAttrib[]) {
585+ EGL_DRM_FLIP_EVENT_DATA_NV,
586+@@ -1540,7 +1563,7 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
587+ flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
588+ g_object_ref (view),
589+ (GClosureNotify) flip_closure_destroyed);
590+- g_closure_set_marshal (flip_closure, g_cclosure_marshal_VOID__OBJECT);
591++ g_closure_set_marshal (flip_closure, meta_marshal_VOID__OBJECT_OBJECT_INT64);
592+
593+ /* Either flip the CRTC's of the monitor info, if we are drawing just part
594+ * of the stage, or all of the CRTC's if we are drawing the whole stage.
595+@@ -2673,6 +2696,15 @@ meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
596+ return fb;
597+ }
598+
599++static int64_t
600++meta_renderer_native_get_clock_time (CoglContext *context)
601++{
602++ CoglRenderer *cogl_renderer = cogl_context_get_renderer (context);
603++ MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data;
604++
605++ return meta_gpu_kms_get_current_time_ns (gpu_kms);
606++}
607++
608+ static const CoglWinsysVtable *
609+ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
610+ {
611+@@ -2701,6 +2733,8 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
612+ vtable.onscreen_swap_buffers_with_damage =
613+ meta_onscreen_native_swap_buffers_with_damage;
614+
615++ vtable.context_get_clock_time = meta_renderer_native_get_clock_time;
616++
617+ vtable_inited = TRUE;
618+ }
619+
620+diff --git a/src/meta-marshal.list b/src/meta-marshal.list
621+new file mode 100644
622+index 000000000..c1f4781d2
623+--- /dev/null
624++++ b/src/meta-marshal.list
625+@@ -0,0 +1 @@
626++VOID:OBJECT,OBJECT,INT64
627+--
628+2.20.1
629+
630diff --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
631new file mode 100644
632index 0000000..a80b993
633--- /dev/null
634+++ b/debian/patches/lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
635@@ -0,0 +1,49 @@
636+Description: renderer-native: Advertise _FEATURE_SWAP_THROTTLE
637+ Because it is implemented and always on. By advertising this fact
638+ the master clock is able to sync to the native refresh rate instead
639+ of always using the fallback of 60.00Hz.
640+ .
641+ Patch 2 of 2
642+Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
643+Origin: https://gitlab.gnome.org/GNOME/mutter/merge_requests/171 via backport branch https://gitlab.gnome.org/vanvugt/mutter/commits/add-vsync-3.28
644+Bug: https://bugzilla.gnome.org/show_bug.cgi?id=781296
645+Bug-Ubuntu: https://bugs.launchpad.net/bugs/1763892
646+Forwarded: yes
647+Last-Update: 2019-03-13
648+
649+diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
650+index f6adb3fee..fa2e9b7d3 100644
651+--- a/src/backends/native/meta-renderer-native.c
652++++ b/src/backends/native/meta-renderer-native.c
653+@@ -1997,6 +1997,13 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
654+ COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
655+ TRUE);
656+
657++ /* COGL_WINSYS_FEATURE_SWAP_THROTTLE is always true for this renderer
658++ * because we have the call to wait_for_pending_flips on every frame.
659++ */
660++ COGL_FLAGS_SET (cogl_context->winsys_features,
661++ COGL_WINSYS_FEATURE_SWAP_THROTTLE,
662++ TRUE);
663++
664+ #ifdef HAVE_EGL_DEVICE
665+ if (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_EGL_DEVICE)
666+ COGL_FLAGS_SET (cogl_context->features,
667+@@ -2625,8 +2632,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
668+ }
669+
670+ onscreen = cogl_onscreen_new (context, width, height);
671+- cogl_onscreen_set_swap_throttled (onscreen,
672+- _clutter_get_sync_to_vblank ());
673++
674++ /* We have wait_for_pending_flips hardcoded, so throttling always. */
675++ cogl_onscreen_set_swap_throttled (onscreen, TRUE);
676++ if (!_clutter_get_sync_to_vblank ())
677++ g_warning ("Request to disable sync-to-vblank is being ignored. "
678++ "MetaRendererNative does not support disabling it.");
679+
680+ if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
681+ {
682+--
683+2.20.1
684+
685diff --git a/debian/patches/series b/debian/patches/series
686index 198db5a..5d87807 100644
687--- a/debian/patches/series
688+++ b/debian/patches/series
689@@ -1,8 +1,9 @@
690 theme-use-gtk_render_icon_suface-to-paint-button-icon.patch
691 theme-load-icons-as-Gtk-does-with-fallback-and-RTL-suppor.patch
692-clutter-Smooth-out-master-clock-to-smooth-visuals.patch
693 clutter-Fix-offscreen-effect-painting-of-clones.patch
694 bgo768531_workaround-startup-notifications.patch
695+lp1763892-a-renderer-native-Add-hardware-presentation-timing.patch
696+lp1763892-b-renderer-native-Advertise-_FEATURE_SWAP_THROTTLE.patch
697 debian/synaptics-support.patch
698 debian/skip-failing-tests.patch
699 debian/skip-failing-tests-325.patch

Subscribers

People subscribed via source and target branches