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 (¶ms[0], G_TYPE_POINTER); + g_value_set_pointer (¶ms[0], flip_closure); + g_value_init (¶ms[1], G_TYPE_OBJECT); + g_value_set_object (¶ms[1], gpu_kms); +- g_closure_invoke (flip_closure, NULL, 2, params, NULL); ++ g_value_init (¶ms[2], G_TYPE_OBJECT); ++ g_value_set_object (¶ms[2], crtc); ++ g_value_init (¶ms[3], G_TYPE_INT64); ++ g_value_set_int64 (¶ms[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
