From d32c1dd8cbb07614d5a70e87aeb9bafaad3b9242 Mon Sep 17 00:00:00 2001 From: Mingi Sung Date: Sat, 14 Sep 2024 12:04:52 +0900 Subject: [PATCH] 1:46.4+r18+g081b918ba-3: Add !3960 & Sync !1441 and merge !4015, !3958 into it & Remove !3934 Signed-off-by: Mingi Sung --- .SRCINFO | 15 +- PKGBUILD | 45 +-- mr1441.patch | 986 ++++++++++++++++++++++++++++++++++++++++++++------- mr3934.patch | 617 -------------------------------- mr3960.patch | 322 +++++++++++++++++ mr4015.patch | 345 ------------------ 6 files changed, 1201 insertions(+), 1129 deletions(-) delete mode 100644 mr3934.patch create mode 100644 mr3960.patch delete mode 100644 mr4015.patch diff --git a/.SRCINFO b/.SRCINFO index be2c3e1..73f0ea3 100644 --- a/.SRCINFO +++ b/.SRCINFO @@ -1,7 +1,7 @@ pkgbase = mutter-performance pkgdesc = A window manager for GNOME | Attempts to improve performances with non-upstreamed merge-requests and frequent stable branch resync pkgver = 46.4+r18+g081b918ba - pkgrel = 2 + pkgrel = 3 epoch = 1 url = https://gitlab.gnome.org/GNOME/mutter arch = x86_64 @@ -77,20 +77,17 @@ pkgbase = mutter-performance source = mr1441.patch source = mr3567.patch source = mr3751.patch - source = mr3934.patch - source = mr4015.patch + source = mr3960.patch sha256sums = 81978164d9f2715438fbc623c77ea7529332cac5c4c519e4781daa5bf1a315eb - sha256sums = 60638078a3f3c46da61f868c04b2a3424488510702648452c3e8214a3790e37b + sha256sums = 043d6f4abce085b5ecc3debf0d334cc9fe826d256a421a4cbbe6aee8cffce255 sha256sums = 2e474a574edad8dc047a53a920fc7cbe005cac0102907eef80a252fc556d0517 sha256sums = 4c15b0e6d0001c8c3feedf05a9140f7f17d52eb36ff7b8039e0281c1373ccdfe - sha256sums = c0ae2855247cddde806a320d031021fd0f7c867c61ac95af99ea3765f290bbf5 - sha256sums = 261d08c54142cd462b651e236565e2289074f53743f30afa9c62a1e20bff37e7 + sha256sums = 361af6ed4ff6039c3b24dca8cd737468b7a441ea9855f8033c8348ce1aab0f0c b2sums = aaed24cb5bac5f62096d44bfdf0e6acfff3944137a06f5cbd7fd1f18d03ebb816d02ab170c9128eafb023a339de3e7ea79480654687ec449d29f9e45d66218e3 - b2sums = 802cf82c0d4fa4514dc376bac57a65453df0ce789e6efac334d2f76a24349ad0a2b6e9ce02345839e8de719d7696dfcae911b1e66922103b2ec315e9fbaa8f01 + b2sums = 3231bdae36ae05892d2106199dc75a0dd8dc59b45bc77a51090ad35bec9e21420aeb86578e97fb64565b265beb7406a406362a06a091ef066965c7c9ea2fe50e b2sums = 65302b1fa24a7aba26915269fb694c7a64b134ee2062ec7e649036a3a41efb2f2f4110cff6194808af34985855ade641c5fb01f0b97536cd3c912892ea3a0d4c b2sums = f9f2284d7236d6072a818de3784a339c2d934490da8870876f49d4effd59ce807593ce8b8a3c5e06586fd5fd7e81fb31fedca84115acf1e71cfe23d4a5e727b3 - b2sums = 18e8d521336422f4c441979fe77ff22c60406e94cd2159c08bbfd127bf6b010dece55c7226b99a953c560b05194fe72e5c2140765577069d970c93479b573bcb - b2sums = a7ce3e4288ad4b14a6b7cb4d9e3f77fc27445f46e5439bc4fe85b696c63298487909a48d4bc4238333c9f9724ba1b5779c29ef8df6a61ac9eb78dd2e83de6502 + b2sums = 9517c7c84b20ff28ccb3cfd1168eb3ca294934df6088c7938b1ff659933043d2687031b2da1eac7eaf0a8cec21284147cb925aa08584563488fce1bcef361184 pkgname = mutter-performance groups = gnome diff --git a/PKGBUILD b/PKGBUILD index 211ff20..2e3f027 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -11,8 +11,8 @@ ### PACKAGE OPTIONS ## MERGE REQUESTS SELECTION -# Merge Requests List: ('579' '1441' '3567' '3751' '3934' '4015') -_merge_requests_to_use=('1441' '3751' '4015') +# Merge Requests List: ('579' '1441' '3567' '3751' '3960') +_merge_requests_to_use=('1441' '3751' '3960') ### IMPORTANT: Do no edit below this line unless you know what you're doing! @@ -21,7 +21,7 @@ _pkgname=mutter pkgname=mutter-performance epoch=1 pkgver=46.4+r18+g081b918ba -pkgrel=2 +pkgrel=3 pkgdesc="A window manager for GNOME | Attempts to improve performances with non-upstreamed merge-requests and frequent stable branch resync" url="https://gitlab.gnome.org/GNOME/mutter" arch=(x86_64 aarch64) @@ -105,20 +105,17 @@ source=("git+$url.git#commit=$_commit" 'mr1441.patch' 'mr3567.patch' 'mr3751.patch' - 'mr3934.patch' - 'mr4015.patch') + 'mr3960.patch') sha256sums=('81978164d9f2715438fbc623c77ea7529332cac5c4c519e4781daa5bf1a315eb' - '60638078a3f3c46da61f868c04b2a3424488510702648452c3e8214a3790e37b' + '043d6f4abce085b5ecc3debf0d334cc9fe826d256a421a4cbbe6aee8cffce255' '2e474a574edad8dc047a53a920fc7cbe005cac0102907eef80a252fc556d0517' '4c15b0e6d0001c8c3feedf05a9140f7f17d52eb36ff7b8039e0281c1373ccdfe' - 'c0ae2855247cddde806a320d031021fd0f7c867c61ac95af99ea3765f290bbf5' - '261d08c54142cd462b651e236565e2289074f53743f30afa9c62a1e20bff37e7') + '361af6ed4ff6039c3b24dca8cd737468b7a441ea9855f8033c8348ce1aab0f0c') b2sums=('aaed24cb5bac5f62096d44bfdf0e6acfff3944137a06f5cbd7fd1f18d03ebb816d02ab170c9128eafb023a339de3e7ea79480654687ec449d29f9e45d66218e3' - '802cf82c0d4fa4514dc376bac57a65453df0ce789e6efac334d2f76a24349ad0a2b6e9ce02345839e8de719d7696dfcae911b1e66922103b2ec315e9fbaa8f01' + '3231bdae36ae05892d2106199dc75a0dd8dc59b45bc77a51090ad35bec9e21420aeb86578e97fb64565b265beb7406a406362a06a091ef066965c7c9ea2fe50e' '65302b1fa24a7aba26915269fb694c7a64b134ee2062ec7e649036a3a41efb2f2f4110cff6194808af34985855ade641c5fb01f0b97536cd3c912892ea3a0d4c' 'f9f2284d7236d6072a818de3784a339c2d934490da8870876f49d4effd59ce807593ce8b8a3c5e06586fd5fd7e81fb31fedca84115acf1e71cfe23d4a5e727b3' - '18e8d521336422f4c441979fe77ff22c60406e94cd2159c08bbfd127bf6b010dece55c7226b99a953c560b05194fe72e5c2140765577069d970c93479b573bcb' - 'a7ce3e4288ad4b14a6b7cb4d9e3f77fc27445f46e5439bc4fe85b696c63298487909a48d4bc4238333c9f9724ba1b5779c29ef8df6a61ac9eb78dd2e83de6502') + '9517c7c84b20ff28ccb3cfd1168eb3ca294934df6088c7938b1ff659933043d2687031b2da1eac7eaf0a8cec21284147cb925aa08584563488fce1bcef361184') for mr in "${_merge_requests_to_use[@]}"; do if [ '3567' = "$mr" ]; then @@ -225,24 +222,12 @@ prepare() { # (mostly Chromium/Electron based apps with Ozone Wayland.) pick_mr '3751' 'mr3751.patch' 'patch' - # Title: kms/impl-device: Track dispatch duration in crtc_frame_deadline_dispatch - # Author: Michel Dänzer - # URL: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934 - # Type: 1 - # Status: 2 - # Comment: This fixes cursor stutter. - # Do not enable this if !1441 is enabled since it already includes !3934. - pick_mr '3934' 'mr3934.patch' 'patch' - - # Title: onscreen/native: Use EGLSyncs instead of cogl_framebuffer_finish - # Author: Gert - # URL: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4015 - # Type: 1 - # Status: 2 - # Comment: This can unblock the CPU in situations where the primary GPU wasn't done - # processing the queue by the time cogl_framebuffer_finish was called. - # It is not intended to be merged in its current state and more of a proof-of-concept. - pick_mr '4015' 'mr4015.patch' 'patch' + # Title: kms: Inhibit real time scheduling until initial mode set + # Author: Jonas Ådahl + # URL: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3960 + # Type: 3 + # Status: 4 + pick_mr '3960' 'mr3960.patch' 'patch' # Title: Draft: Dynamic triple/double buffering (v4) # Author: Daniel van Vugt @@ -250,7 +235,7 @@ prepare() { # Type: 1 # Status: 2 & 3 # Comment: Helps GPU frequencies to scale up. - # Backported: !3934. + # Backported: !3184 !3265 !3799 !3817 !3829 !3830 !3891 !3934 !3958 !4015 pick_mr '1441' 'mr1441.patch' 'patch' } diff --git a/mr1441.patch b/mr1441.patch index 98a196b..a2c2121 100644 --- a/mr1441.patch +++ b/mr1441.patch @@ -1,6 +1,6 @@ -From 21fe0f94e6472d94f8a4943442464eb01785d6bc Mon Sep 17 00:00:00 2001 +From 37bf13fe3de848b8d16e535bac92f3f4edd41751 Mon Sep 17 00:00:00 2001 From: Mingi Sung -Date: Wed, 28 Aug 2024 20:11:32 +0900 +Date: Sat, 14 Sep 2024 11:59:23 +0900 Subject: [PATCH] Merge branch 'sungmg-triple-buffering-v4-46' into gnome-46 Use triple buffering if and when the previous frame is running late. @@ -15,58 +15,67 @@ there's no latency penalty when the system is able to maintain full frame rate. Author: Daniel van Vugt Source: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441 -Commit: 7a1dbab76a49b6dde6813604a3776ced39be91e1 +Commit: 511a502e1a6ff6c88dcb650f1bee8f6eb894d1f6 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3265 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3799 +Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3817 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3829 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3830 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3891 Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934 +Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958 +Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4015 Signed-off-by: Mingi Sung --- - clutter/clutter/clutter-frame-clock.c | 384 +++++++++++++++---- - clutter/clutter/clutter-frame-clock.h | 15 +- - clutter/clutter/clutter-frame-private.h | 1 + - clutter/clutter/clutter-frame.c | 13 + - clutter/clutter/clutter-frame.h | 7 + - clutter/clutter/clutter-stage-view.c | 15 +- - clutter/clutter/clutter-stage-view.h | 2 + - cogl/cogl/cogl-onscreen-private.h | 5 +- - cogl/cogl/cogl-onscreen.c | 8 + - src/backends/meta-stage-impl.c | 2 + - src/backends/native/meta-crtc-kms.c | 10 + - src/backends/native/meta-crtc-native.c | 8 + - src/backends/native/meta-crtc-native.h | 3 + - src/backends/native/meta-crtc-virtual.c | 8 + - src/backends/native/meta-frame-native.c | 63 ++++ - src/backends/native/meta-frame-native.h | 20 + - src/backends/native/meta-kms-crtc.c | 63 +++- - src/backends/native/meta-kms-crtc.h | 5 + - src/backends/native/meta-kms-impl-device.c | 51 ++- - src/backends/native/meta-kms.c | 9 + - src/backends/native/meta-kms.h | 2 + - src/backends/native/meta-onscreen-native.c | 478 +++++++++++++++++------- - src/backends/native/meta-onscreen-native.h | 2 + - src/backends/native/meta-renderer-native.c | 34 +- - src/backends/native/meta-renderer-view-native.c | 41 ++ - src/core/util.c | 3 + - src/meta/meta-debug.h | 2 + - src/meta/util.h | 3 + - src/tests/meta-monitor-manager-test.c | 6 + - src/tests/native-kms-render.c | 106 +++++- - 30 files changed, 1125 insertions(+), 244 deletions(-) + clutter/clutter/clutter-frame-clock.c | 386 ++++++++++--- + clutter/clutter/clutter-frame-clock.h | 15 +- + clutter/clutter/clutter-frame-private.h | 1 + + clutter/clutter/clutter-frame.c | 13 + + clutter/clutter/clutter-frame.h | 7 + + clutter/clutter/clutter-stage-view.c | 15 +- + clutter/clutter/clutter-stage-view.h | 2 + + cogl/cogl/cogl-onscreen-private.h | 5 +- + cogl/cogl/cogl-onscreen.c | 8 + + src/backends/meta-egl.c | 94 +++ + src/backends/meta-egl.h | 23 + + src/backends/meta-stage-impl.c | 2 + + src/backends/native/meta-crtc-kms.c | 10 + + src/backends/native/meta-crtc-native.c | 8 + + src/backends/native/meta-crtc-native.h | 3 + + src/backends/native/meta-crtc-virtual.c | 8 + + src/backends/native/meta-frame-native.c | 63 ++ + src/backends/native/meta-frame-native.h | 20 + + src/backends/native/meta-kms-crtc.c | 70 ++- + src/backends/native/meta-kms-crtc.h | 5 + + src/backends/native/meta-kms-impl-device-atomic.c | 2 +- + src/backends/native/meta-kms-impl-device.c | 191 ++++++- + src/backends/native/meta-kms-update.c | 25 + + src/backends/native/meta-kms-update.h | 9 +- + src/backends/native/meta-kms.c | 9 + + src/backends/native/meta-kms.h | 2 + + src/backends/native/meta-onscreen-native.c | 665 +++++++++++++++------- + src/backends/native/meta-onscreen-native.h | 2 + + src/backends/native/meta-renderer-native.c | 34 +- + src/backends/native/meta-renderer-view-native.c | 41 ++ + src/core/util.c | 3 + + src/meta/meta-debug.h | 2 + + src/meta/util.h | 3 + + src/tests/meta-monitor-manager-test.c | 6 + + src/tests/native-kms-render.c | 106 +++- + 35 files changed, 1530 insertions(+), 328 deletions(-) diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c -index 30a319f604..c299705663 100644 +index 30a319f604..3418cb86c0 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c -@@ -42,6 +42,15 @@ enum +@@ -42,7 +42,16 @@ enum static guint signals[N_SIGNALS]; +-#define SYNC_DELAY_FALLBACK_FRACTION 0.875 +typedef enum +{ + TRIPLE_BUFFERING_MODE_NEVER, @@ -76,9 +85,10 @@ index 30a319f604..c299705663 100644 + +static TripleBufferingMode triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO; + - #define SYNC_DELAY_FALLBACK_FRACTION 0.875 ++#define SYNC_DELAY_FALLBACK_FRACTION 0.875f #define MINIMUM_REFRESH_RATE 30.f + @@ -70,8 +79,10 @@ typedef enum _ClutterFrameClockState CLUTTER_FRAME_CLOCK_STATE_IDLE, CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, @@ -212,8 +222,8 @@ index 30a319f604..c299705663 100644 frame_clock->shortterm_max_update_duration_us = CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us + - MAX (swap_to_rendering_done_us, swap_to_flip_us), -+ MAX (swap_to_rendering_done_us, -+ swap_to_flip_us + frame_clock->deadline_evasion_us), ++ MAX (swap_to_rendering_done_us, swap_to_flip_us) + ++ frame_clock->deadline_evasion_us, frame_clock->shortterm_max_update_duration_us, - frame_clock->refresh_interval_us); + 2 * frame_clock->refresh_interval_us); @@ -924,6 +934,156 @@ index e2b3a0b462..53ffa649bc 100644 CoglFrameClosure * cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, CoglFrameCallback callback, +diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c +index cc023f705c..bc188e80e6 100644 +--- a/src/backends/meta-egl.c ++++ b/src/backends/meta-egl.c +@@ -44,6 +44,11 @@ struct _MetaEgl + PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; + ++ PFNEGLCREATESYNCPROC eglCreateSync; ++ PFNEGLDESTROYSYNCPROC eglDestroySync; ++ PFNEGLWAITSYNCPROC eglWaitSync; ++ PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID; ++ + PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; + PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; + +@@ -1162,6 +1167,90 @@ meta_egl_query_display_attrib (MetaEgl *egl, + return TRUE; + } + ++gboolean ++meta_egl_create_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLenum type, ++ const EGLAttrib *attrib_list, ++ EGLSync *egl_sync, ++ GError **error) ++{ ++ if (!is_egl_proc_valid (egl->eglCreateSync, error)) ++ return FALSE; ++ ++ EGLSync sync; ++ ++ sync = egl->eglCreateSync (display, type, attrib_list); ++ ++ if (sync == EGL_NO_SYNC) ++ { ++ set_egl_error (error); ++ return FALSE; ++ } ++ ++ *egl_sync = sync; ++ ++ return TRUE; ++} ++ ++gboolean ++meta_egl_destroy_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ GError **error) ++{ ++ if (!is_egl_proc_valid (egl->eglDestroySync, error)) ++ return FALSE; ++ ++ if (!egl->eglDestroySync (display, sync)) ++ { ++ set_egl_error (error); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++gboolean ++meta_egl_wait_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ EGLint flags, ++ GError **error) ++{ ++ if (!is_egl_proc_valid (egl->eglWaitSync, error)) ++ return FALSE; ++ ++ if (!egl->eglWaitSync (display, sync, flags)) ++ { ++ set_egl_error (error); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++EGLint ++meta_egl_duplicate_native_fence_fd (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ GError **error) ++{ ++ if (!is_egl_proc_valid (egl->eglDupNativeFenceFDANDROID, error)) ++ return EGL_NO_NATIVE_FENCE_FD_ANDROID; ++ ++ EGLint fd = EGL_NO_NATIVE_FENCE_FD_ANDROID; ++ ++ fd = egl->eglDupNativeFenceFDANDROID (display, sync); ++ ++ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) ++ { ++ set_egl_error (error); ++ } ++ ++ return fd; ++} ++ + #define GET_EGL_PROC_ADDR(proc) \ + egl->proc = (void *) eglGetProcAddress (#proc); + +@@ -1175,6 +1264,11 @@ meta_egl_constructed (GObject *object) + GET_EGL_PROC_ADDR (eglCreateImageKHR); + GET_EGL_PROC_ADDR (eglDestroyImageKHR); + ++ GET_EGL_PROC_ADDR (eglCreateSync); ++ GET_EGL_PROC_ADDR (eglDestroySync); ++ GET_EGL_PROC_ADDR (eglWaitSync); ++ GET_EGL_PROC_ADDR (eglDupNativeFenceFDANDROID); ++ + GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL); + GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL); + +diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h +index 8b955c90c3..9078b47948 100644 +--- a/src/backends/meta-egl.h ++++ b/src/backends/meta-egl.h +@@ -276,3 +276,26 @@ gboolean meta_egl_query_display_attrib (MetaEgl *egl, + EGLint attribute, + EGLAttrib *value, + GError **error); ++ ++gboolean meta_egl_create_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLenum type, ++ const EGLAttrib *attrib_list, ++ EGLSync *egl_sync, ++ GError **error); ++ ++gboolean meta_egl_destroy_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ GError **error); ++ ++gboolean meta_egl_wait_sync (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ EGLint flags, ++ GError **error); ++ ++EGLint meta_egl_duplicate_native_fence_fd (MetaEgl *egl, ++ EGLDisplay display, ++ EGLSync sync, ++ GError **error); diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index 7aa24439d7..727e1a5f30 100644 --- a/src/backends/meta-stage-impl.c @@ -1147,7 +1307,7 @@ index f86d3b0b02..84bd43b8c6 100644 +meta_frame_native_get_damage (MetaFrameNative *frame_native, + int **rectangles); diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c -index a0872089a0..cad9f88ce5 100644 +index a0872089a0..50edfcbe33 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -28,8 +28,7 @@ @@ -1218,7 +1378,7 @@ index a0872089a0..cad9f88ce5 100644 vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode); next_deadline_us = next_presentation_us - (vblank_duration_us + -@@ -625,3 +653,26 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, +@@ -625,3 +653,33 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, return TRUE; } @@ -1242,8 +1402,15 @@ index a0872089a0..cad9f88ce5 100644 +int64_t +meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc) +{ -+ return MAX (crtc->shortterm_max_dispatch_duration_us, -+ crtc->deadline_evasion_us) + DEADLINE_EVASION_CONSTANT_US; ++ int64_t deadline_evasion_us; ++ ++ deadline_evasion_us = ++ MAX (crtc->shortterm_max_dispatch_duration_us, crtc->deadline_evasion_us); ++ ++ if (!deadline_evasion_us) ++ return 0; ++ ++ return deadline_evasion_us + DEADLINE_EVASION_CONSTANT_US; +} diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h index 580ee9a89c..b293f8e7cc 100644 @@ -1258,8 +1425,21 @@ index 580ee9a89c..b293f8e7cc 100644 + int64_t duration_us); + +int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc); +diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c +index 7812ec0421..488d24ac5d 100644 +--- a/src/backends/native/meta-kms-impl-device-atomic.c ++++ b/src/backends/native/meta-kms-impl-device-atomic.c +@@ -643,7 +643,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, + return FALSE; + } + +- if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT) ++ if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC) + { + int signaled_sync_file; + diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c -index 6758982a6a..6ce62cd697 100644 +index 6758982a6a..2a87dc0898 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -39,6 +39,7 @@ @@ -1270,7 +1450,7 @@ index 6758982a6a..6ce62cd697 100644 #include "backends/native/meta-thread-private.h" #include "meta-default-modes.h" -@@ -71,6 +72,7 @@ typedef struct _CrtcDeadline +@@ -71,9 +72,17 @@ typedef struct _CrtcDeadline GSource *source; gboolean armed; gboolean is_deadline_page_flip; @@ -1278,7 +1458,17 @@ index 6758982a6a..6ce62cd697 100644 int64_t expected_presentation_time_us; gboolean has_expected_presentation_time; } deadline; -@@ -1165,6 +1167,7 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame, ++ ++ struct { ++ MetaKmsUpdate *kms_update; ++ MetaKmsUpdateFlag flags; ++ MetaKmsCrtc *latch_crtc; ++ GSource *source; ++ } submitted_update; + } CrtcFrame; + + typedef enum _MetaDeadlineTimerState +@@ -1165,6 +1174,7 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame, timerfd_settime (crtc_frame->deadline.timer_fd, TFD_TIMER_ABSTIME, &its, NULL); @@ -1286,7 +1476,7 @@ index 6758982a6a..6ce62cd697 100644 crtc_frame->deadline.expected_presentation_time_us = next_presentation_us; crtc_frame->deadline.has_expected_presentation_time = next_presentation_us != 0; crtc_frame->deadline.armed = TRUE; -@@ -1197,7 +1200,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, +@@ -1197,7 +1207,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, CrtcFrame *crtc_frame = user_data; if (crtc_frame->deadline.is_deadline_page_flip && @@ -1295,7 +1485,7 @@ index 6758982a6a..6ce62cd697 100644 { struct timeval page_flip_timeval; int64_t presentation_time_us; -@@ -1210,7 +1213,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, +@@ -1210,7 +1220,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, if (crtc_frame->deadline.has_expected_presentation_time) { @@ -1304,7 +1494,7 @@ index 6758982a6a..6ce62cd697 100644 "Deadline page flip presentation time: %" G_GINT64_FORMAT " us, " "expected %" G_GINT64_FORMAT " us " "(diff: %" G_GINT64_FORMAT ")", -@@ -1221,7 +1224,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, +@@ -1221,7 +1231,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, } else { @@ -1313,7 +1503,7 @@ index 6758982a6a..6ce62cd697 100644 "Deadline page flip presentation time: %" G_GINT64_FORMAT " us", presentation_time_us); } -@@ -1390,11 +1393,16 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, +@@ -1390,11 +1400,16 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, GError **error) { CrtcFrame *crtc_frame = user_data; @@ -1331,7 +1521,7 @@ index 6758982a6a..6ce62cd697 100644 ret = read (crtc_frame->deadline.timer_fd, &timer_value, -@@ -1416,6 +1424,36 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, +@@ -1416,6 +1431,36 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, crtc_frame->crtc, g_steal_pointer (&crtc_frame->pending_update), META_KMS_UPDATE_FLAG_NONE); @@ -1368,20 +1558,289 @@ index 6758982a6a..6ce62cd697 100644 if (meta_kms_feedback_did_pass (feedback)) crtc_frame->deadline.is_deadline_page_flip = TRUE; disarm_crtc_frame_deadline_timer (crtc_frame); -@@ -1592,6 +1630,11 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, - meta_kms_device_handle_flush (priv->device, latch_crtc); +@@ -1429,6 +1474,8 @@ crtc_frame_free (CrtcFrame *crtc_frame) + g_clear_fd (&crtc_frame->deadline.timer_fd, NULL); + g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy); + g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free); ++ g_clear_pointer (&crtc_frame->submitted_update.kms_update, meta_kms_update_free); ++ g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy); + g_free (crtc_frame); + } - feedback = do_process (impl_device, latch_crtc, update, flags); +@@ -1530,6 +1577,79 @@ queue_update (MetaKmsImplDevice *impl_device, + } + } + ++static gpointer ++meta_kms_impl_device_update_ready (MetaThreadImpl *impl, ++ gpointer user_data, ++ GError **error) ++{ ++ CrtcFrame *crtc_frame = user_data; ++ MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc); ++ MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); ++ MetaKmsImplDevicePrivate *priv = ++ meta_kms_impl_device_get_instance_private (impl_device); ++ MetaKmsUpdate *update; ++ MetaKmsCrtc *latch_crtc; ++ MetaKmsFeedback *feedback; ++ ++ meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); ++ ++ g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy); ++ ++ update = g_steal_pointer (&crtc_frame->submitted_update.kms_update); ++ meta_kms_update_realize (update, impl_device); ++ ++ latch_crtc = g_steal_pointer (&crtc_frame->submitted_update.latch_crtc); ++ ++ if (crtc_frame->pending_page_flip && ++ !meta_kms_update_get_mode_sets (update)) ++ { ++ g_assert (latch_crtc); ++ ++ meta_topic (META_DEBUG_KMS, ++ "Queuing update on CRTC %u (%s): pending page flip", ++ meta_kms_crtc_get_id (latch_crtc), ++ priv->path); ++ ++ queue_update (impl_device, crtc_frame, update); ++ return GINT_TO_POINTER (TRUE); ++ } ++ ++ if (crtc_frame->pending_update) ++ { ++ meta_kms_update_merge_from (crtc_frame->pending_update, update); ++ meta_kms_update_free (update); ++ update = g_steal_pointer (&crtc_frame->pending_update); ++ disarm_crtc_frame_deadline_timer (crtc_frame); ++ } ++ ++ meta_kms_device_handle_flush (priv->device, latch_crtc); ++ ++ feedback = do_process (impl_device, latch_crtc, update, crtc_frame->submitted_update.flags); + + if (meta_kms_feedback_did_pass (feedback) && + crtc_frame->deadline.armed) + disarm_crtc_frame_deadline_timer (crtc_frame); + - meta_kms_feedback_unref (feedback); ++ meta_kms_feedback_unref (feedback); ++ ++ return GINT_TO_POINTER (TRUE); ++} ++ ++static gboolean ++is_fd_readable (int fd) ++{ ++ GPollFD poll_fd; ++ ++ poll_fd.fd = fd; ++ poll_fd.events = G_IO_IN; ++ poll_fd.revents = 0; ++ ++ if (!g_poll (&poll_fd, 1, 0)) ++ return FALSE; ++ ++ return (poll_fd.revents & (G_IO_IN | G_IO_NVAL)) != 0; ++} ++ + void + meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, + MetaKmsUpdate *update, +@@ -1537,10 +1657,15 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, + { + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); ++ MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device); ++ MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl); + g_autoptr (GError) error = NULL; + MetaKmsCrtc *latch_crtc; + CrtcFrame *crtc_frame; + MetaKmsFeedback *feedback; ++ g_autoptr (GSource) source = NULL; ++ g_autofree char *name = NULL; ++ int sync_fd = -1; + + meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl)); + +@@ -1561,38 +1686,58 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, + if (!ensure_device_file (impl_device, &error)) + goto err; + +- meta_kms_update_realize (update, impl_device); +- + crtc_frame = ensure_crtc_frame (impl_device, latch_crtc); + ++ if (crtc_frame->submitted_update.kms_update) ++ { ++ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_PENDING, ++ "Previously-submitted update wasn't ready yet"); ++ goto err; ++ } ++ + crtc_frame->await_flush = FALSE; ++ crtc_frame->submitted_update.kms_update = update; ++ crtc_frame->submitted_update.flags = flags; ++ crtc_frame->submitted_update.latch_crtc = latch_crtc; + +- if (crtc_frame->pending_page_flip && +- !meta_kms_update_get_mode_sets (update)) ++ if (is_using_deadline_timer (impl_device)) ++ sync_fd = meta_kms_update_get_sync_fd (update); ++ ++ if (sync_fd >= 0) + { +- g_assert (latch_crtc); ++ GList *l; + +- meta_topic (META_DEBUG_KMS, +- "Queuing update on CRTC %u (%s): pending page flip", +- meta_kms_crtc_get_id (latch_crtc), +- priv->path); ++ for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next) ++ { ++ MetaKmsPlaneAssignment *assignment = l->data; + +- queue_update (impl_device, crtc_frame, update); +- return; ++ assignment->flags |= META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC; ++ } + } + +- if (crtc_frame->pending_update) ++ if (sync_fd < 0 || ++ is_fd_readable (sync_fd)) + { +- meta_kms_update_merge_from (crtc_frame->pending_update, update); +- meta_kms_update_free (update); +- update = g_steal_pointer (&crtc_frame->pending_update); +- disarm_crtc_frame_deadline_timer (crtc_frame); ++ meta_kms_impl_device_update_ready (thread_impl, ++ crtc_frame, ++ NULL); ++ return; + } + +- meta_kms_device_handle_flush (priv->device, latch_crtc); ++ source = meta_thread_impl_register_fd (thread_impl, ++ sync_fd, ++ meta_kms_impl_device_update_ready, ++ crtc_frame); + +- feedback = do_process (impl_device, latch_crtc, update, flags); +- meta_kms_feedback_unref (feedback); ++ name = g_strdup_printf ("[mutter] KMS update sync_fd (crtc: %u, %s)", ++ meta_kms_crtc_get_id (latch_crtc), ++ priv->path); ++ g_source_set_name (source, name); ++ g_source_set_priority (source, G_PRIORITY_HIGH + 1); ++ g_source_set_can_recurse (source, FALSE); ++ g_source_set_ready_time (source, -1); ++ ++ crtc_frame->submitted_update.source = source; return; + err: +diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c +index b8c4137f9b..53a34b8c22 100644 +--- a/src/backends/native/meta-kms-update.c ++++ b/src/backends/native/meta-kms-update.c +@@ -20,6 +20,8 @@ + #include "backends/native/meta-kms-update.h" + #include "backends/native/meta-kms-update-private.h" + ++#include ++ + #include "backends/meta-display-config-shared.h" + #include "backends/native/meta-kms-connector.h" + #include "backends/native/meta-kms-crtc.h" +@@ -51,6 +53,8 @@ struct _MetaKmsUpdate + gboolean needs_modeset; + + MetaKmsImplDevice *impl_device; ++ ++ int sync_fd; + }; + + void +@@ -1136,6 +1140,8 @@ meta_kms_update_merge_from (MetaKmsUpdate *update, + merge_custom_page_flip_from (update, other_update); + merge_page_flip_listeners_from (update, other_update); + merge_result_listeners_from (update, other_update); ++ ++ meta_kms_update_set_sync_fd (update, g_steal_fd (&other_update->sync_fd)); + } + + gboolean +@@ -1152,6 +1158,7 @@ meta_kms_update_new (MetaKmsDevice *device) + update = g_new0 (MetaKmsUpdate, 1); + update->device = device; + update->is_latchable = TRUE; ++ update->sync_fd = -1; + + return update; + } +@@ -1175,6 +1182,7 @@ meta_kms_update_free (MetaKmsUpdate *update) + g_list_free_full (update->crtc_color_updates, + (GDestroyNotify) meta_kms_crtc_color_updates_free); + g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free); ++ g_clear_fd (&update->sync_fd, NULL); + + g_free (update); + } +@@ -1200,6 +1208,23 @@ meta_kms_update_get_latch_crtc (MetaKmsUpdate *update) + return update->latch_crtc; + } + ++int ++meta_kms_update_get_sync_fd (MetaKmsUpdate *update) ++{ ++ return update->sync_fd; ++} ++ ++void ++meta_kms_update_set_sync_fd (MetaKmsUpdate *update, ++ int sync_fd) ++{ ++ if (update->sync_fd == sync_fd) ++ return; ++ ++ g_clear_fd (&update->sync_fd, NULL); ++ update->sync_fd = sync_fd; ++} ++ + gboolean + meta_kms_update_is_empty (MetaKmsUpdate *update) + { +diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h +index 1951c80f60..ebb50cbaa8 100644 +--- a/src/backends/native/meta-kms-update.h ++++ b/src/backends/native/meta-kms-update.h +@@ -39,7 +39,7 @@ typedef enum _MetaKmsAssignPlaneFlag + META_KMS_ASSIGN_PLANE_FLAG_NONE = 0, + META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0, + META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL = 1 << 1, +- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT = 1 << 2, ++ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC = 1 << 2, + } MetaKmsAssignPlaneFlag; + + struct _MetaKmsPageFlipListenerVtable +@@ -157,6 +157,13 @@ void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, + MetaKmsCrtc *crtc, + const MetaGammaLut *gamma); + ++int ++meta_kms_update_get_sync_fd (MetaKmsUpdate *update); ++ ++void ++meta_kms_update_set_sync_fd (MetaKmsUpdate *update, ++ int sync_fd); ++ + void meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment, + const int *rectangles, + int n_rectangles); diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c -index d41fcefb5a..4809ca0593 100644 +index d41fcefb5a..37747b473f 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -63,6 +63,8 @@ struct _MetaKms @@ -1393,16 +1852,8 @@ index d41fcefb5a..4809ca0593 100644 }; G_DEFINE_TYPE (MetaKms, meta_kms, META_TYPE_THREAD) -@@ -354,6 +356,7 @@ static void - on_prepare_shutdown (MetaBackend *backend, - MetaKms *kms) - { -+ kms->shutting_down = TRUE; - meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); - meta_thread_flush_callbacks (META_THREAD (kms)); - -@@ -413,6 +416,12 @@ meta_kms_new (MetaBackend *backend, - return kms; +@@ -339,6 +341,12 @@ meta_kms_create_device (MetaKms *kms, + return device; } +gboolean @@ -1411,9 +1862,17 @@ index d41fcefb5a..4809ca0593 100644 + return kms->shutting_down; +} + - static void - meta_kms_finalize (GObject *object) + static gpointer + prepare_shutdown_in_impl (MetaThreadImpl *thread_impl, + gpointer user_data, +@@ -354,6 +362,7 @@ static void + on_prepare_shutdown (MetaBackend *backend, + MetaKms *kms) { ++ kms->shutting_down = TRUE; + meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); + meta_thread_flush_callbacks (META_THREAD (kms)); + diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index 7434014063..f6b19520be 100644 --- a/src/backends/native/meta-kms.h @@ -1428,10 +1887,18 @@ index 7434014063..f6b19520be 100644 MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 9b739faf39..6120eeec7b 100644 +index 9b739faf39..941647e12a 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c -@@ -76,7 +76,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState +@@ -29,6 +29,7 @@ + + #include "backends/native/meta-onscreen-native.h" + ++#include + #include + + #include "backends/meta-egl-ext.h" +@@ -76,7 +77,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState struct { MetaDrmBufferDumb *current_dumb_fb; @@ -1440,7 +1907,7 @@ index 9b739faf39..6120eeec7b 100644 } cpu; gboolean noted_primary_gpu_copy_ok; -@@ -102,12 +102,13 @@ struct _MetaOnscreenNative +@@ -102,12 +103,13 @@ struct _MetaOnscreenNative MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; @@ -1458,7 +1925,7 @@ index 9b739faf39..6120eeec7b 100644 } gbm; #ifdef HAVE_EGL_DEVICE -@@ -118,6 +119,9 @@ struct _MetaOnscreenNative +@@ -118,6 +120,9 @@ struct _MetaOnscreenNative } egl; #endif @@ -1468,7 +1935,7 @@ index 9b739faf39..6120eeec7b 100644 gboolean frame_sync_requested; gboolean frame_sync_enabled; -@@ -139,44 +143,37 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, +@@ -139,44 +144,37 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, static GQuark blit_source_quark = 0; @@ -1526,7 +1993,7 @@ index 9b739faf39..6120eeec7b 100644 } static void -@@ -214,7 +211,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) +@@ -214,7 +212,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) info = cogl_onscreen_pop_head_frame_info (onscreen); @@ -1535,7 +2002,7 @@ index 9b739faf39..6120eeec7b 100644 _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); -@@ -256,6 +253,7 @@ notify_view_crtc_presented (MetaRendererView *view, +@@ -256,6 +254,7 @@ notify_view_crtc_presented (MetaRendererView *view, meta_onscreen_native_notify_frame_complete (onscreen); meta_onscreen_native_swap_drm_fb (onscreen); @@ -1543,7 +2010,7 @@ index 9b739faf39..6120eeec7b 100644 } static void -@@ -305,15 +303,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, +@@ -305,15 +304,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view)); CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); @@ -1560,7 +2027,7 @@ index 9b739faf39..6120eeec7b 100644 } static void -@@ -379,7 +375,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, +@@ -379,7 +376,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, } meta_onscreen_native_notify_frame_complete (onscreen); @@ -1570,7 +2037,7 @@ index 9b739faf39..6120eeec7b 100644 } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { -@@ -440,18 +437,36 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, +@@ -440,18 +438,36 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ @@ -1610,7 +2077,7 @@ index 9b739faf39..6120eeec7b 100644 static void apply_transform (MetaCrtcKms *crtc_kms, MetaKmsPlaneAssignment *kms_plane_assignment, -@@ -528,12 +543,15 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -528,12 +544,15 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; @@ -1626,7 +2093,7 @@ index 9b739faf39..6120eeec7b 100644 MetaKmsPlaneAssignment *plane_assignment; graphene_rect_t src_rect; MtkRectangle dst_rect; -@@ -541,6 +559,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -541,6 +560,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, "Meta::OnscreenNative::flip_crtc()"); @@ -1636,7 +2103,7 @@ index 9b739faf39..6120eeec7b 100644 gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc)); -@@ -550,14 +571,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -550,14 +572,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: @@ -1657,7 +2124,7 @@ index 9b739faf39..6120eeec7b 100644 } else { -@@ -600,6 +621,10 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, +@@ -600,6 +622,10 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, #endif } @@ -1668,7 +2135,201 @@ index 9b739faf39..6120eeec7b 100644 meta_kms_update_add_page_flip_listener (kms_update, kms_crtc, &page_flip_listener_vtable, -@@ -947,12 +972,17 @@ static MetaDrmBufferDumb * +@@ -848,29 +874,63 @@ import_shared_framebuffer (CoglOnscreen *onscreen, + } + + static MetaDrmBuffer * +-copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, +- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, +- MetaRendererNativeGpuData *renderer_gpu_data, +- gboolean *egl_context_changed, +- MetaDrmBuffer *primary_gpu_fb) ++copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, ++ MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, ++ MetaRendererNativeGpuData *renderer_gpu_data, ++ MetaDrmBuffer *primary_gpu_fb, ++ GError **error) + { + MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; + MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); + MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native); ++ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); ++ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); ++ CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); ++ CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys; + MetaRenderDevice *render_device; +- EGLDisplay egl_display; +- GError *error = NULL; ++ EGLDisplay egl_display = NULL; + gboolean use_modifiers; + MetaDeviceFile *device_file; + MetaDrmBufferFlags flags; +- MetaDrmBufferGbm *buffer_gbm; ++ MetaDrmBufferGbm *buffer_gbm = NULL; + struct gbm_bo *bo; ++ EGLSync primary_gpu_egl_sync = EGL_NO_SYNC; ++ EGLSync secondary_gpu_egl_sync = EGL_NO_SYNC; ++ g_autofd int primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID; + + COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, + "copy_shared_framebuffer_gpu()"); + + if (renderer_gpu_data->secondary.needs_explicit_sync) +- cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); ++ { ++ if (!meta_egl_create_sync (egl, ++ cogl_renderer_egl->edpy, ++ EGL_SYNC_NATIVE_FENCE_ANDROID, ++ NULL, ++ &primary_gpu_egl_sync, ++ error)) ++ { ++ g_prefix_error (error, "Failed to create EGLSync on primary GPU: "); ++ return NULL; ++ } ++ ++ // According to the EGL_KHR_fence_sync specification we must ensure ++ // the fence command is flushed in this context to be able to await it ++ // in another (secondary GPU context) or we risk waiting indefinitely. ++ cogl_framebuffer_flush (COGL_FRAMEBUFFER (onscreen)); ++ ++ primary_gpu_sync_fence = ++ meta_egl_duplicate_native_fence_fd (egl, ++ cogl_renderer_egl->edpy, ++ primary_gpu_egl_sync, ++ error); ++ ++ if (primary_gpu_sync_fence == EGL_NO_NATIVE_FENCE_FD_ANDROID) ++ { ++ g_prefix_error (error, "Failed to duplicate EGLSync FD on primary GPU: "); ++ goto done; ++ } ++ } + + render_device = renderer_gpu_data->render_device; + egl_display = meta_render_device_get_egl_display (render_device); +@@ -880,15 +940,45 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + secondary_gpu_state->egl_surface, + secondary_gpu_state->egl_surface, + renderer_gpu_data->secondary.egl_context, +- &error)) ++ error)) + { +- g_warning ("Failed to make current: %s", error->message); +- g_error_free (error); +- return NULL; ++ g_prefix_error (error, "Failed to make current: "); ++ goto done; + } + +- *egl_context_changed = TRUE; ++ if (primary_gpu_sync_fence != EGL_NO_NATIVE_FENCE_FD_ANDROID) ++ { ++ EGLAttrib attribs[3]; ++ ++ attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; ++ attribs[1] = primary_gpu_sync_fence; ++ attribs[2] = EGL_NONE; + ++ if (!meta_egl_create_sync (egl, ++ egl_display, ++ EGL_SYNC_NATIVE_FENCE_ANDROID, ++ attribs, ++ &secondary_gpu_egl_sync, ++ error)) ++ { ++ g_prefix_error (error, "Failed to create EGLSync on secondary GPU: "); ++ goto done; ++ } ++ ++ // eglCreateSync takes ownership of an existing fd that is passed, so ++ // don't try to clean it up twice. ++ primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID; ++ ++ if (!meta_egl_wait_sync (egl, ++ egl_display, ++ secondary_gpu_egl_sync, ++ 0, ++ error)) ++ { ++ g_prefix_error (error, "Failed to wait for EGLSync on secondary GPU: "); ++ goto done; ++ } ++ } + + buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb); + bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); +@@ -898,21 +988,19 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + renderer_gpu_data->secondary.egl_context, + secondary_gpu_state->egl_surface, + bo, +- &error)) ++ error)) + { +- g_warning ("Failed to blit shared framebuffer: %s", error->message); +- g_error_free (error); +- return NULL; ++ g_prefix_error (error, "Failed to blit shared framebuffer: "); ++ goto done; + } + + if (!meta_egl_swap_buffers (egl, + egl_display, + secondary_gpu_state->egl_surface, +- &error)) ++ error)) + { +- g_warning ("Failed to swap buffers: %s", error->message); +- g_error_free (error); +- return NULL; ++ g_prefix_error (error, "Failed to swap buffers: "); ++ goto done; + } + + use_modifiers = meta_renderer_native_use_modifiers (renderer_native); +@@ -926,13 +1014,11 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + meta_drm_buffer_gbm_new_lock_front (device_file, + secondary_gpu_state->gbm.surface, + flags, +- &error); ++ error); + if (!buffer_gbm) + { +- g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s", +- error->message); +- g_error_free (error); +- return NULL; ++ g_prefix_error (error, "meta_drm_buffer_gbm_new_lock_front failed: "); ++ goto done; + } + + g_object_set_qdata_full (G_OBJECT (buffer_gbm), +@@ -940,19 +1026,41 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, + g_object_ref (primary_gpu_fb), + g_object_unref); + +- return META_DRM_BUFFER (buffer_gbm); ++done: ++ _cogl_winsys_egl_ensure_current (cogl_display); ++ ++ if (primary_gpu_egl_sync != EGL_NO_SYNC && ++ !meta_egl_destroy_sync (egl, ++ cogl_renderer_egl->edpy, ++ primary_gpu_egl_sync, ++ error)) ++ g_prefix_error (error, "Failed to destroy primary GPU EGLSync: "); ++ ++ if (secondary_gpu_egl_sync != EGL_NO_SYNC && ++ !meta_egl_destroy_sync (egl, ++ egl_display, ++ secondary_gpu_egl_sync, ++ error)) ++ g_prefix_error (error, "Failed to destroy secondary GPU EGLSync: "); ++ ++ return buffer_gbm ? META_DRM_BUFFER (buffer_gbm) : NULL; + } + + static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; @@ -1690,7 +2351,7 @@ index 9b739faf39..6120eeec7b 100644 } static MetaDrmBuffer * -@@ -1192,56 +1222,54 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, +@@ -1192,56 +1300,54 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, return copy; } @@ -1700,10 +2361,10 @@ index 9b739faf39..6120eeec7b 100644 - MetaDrmBuffer *primary_gpu_fb, - MetaDrmBuffer **secondary_gpu_fb) +static MetaDrmBuffer * -+acquire_front_buffer (CoglOnscreen *onscreen, -+ gboolean *egl_context_changed, -+ MetaDrmBuffer *primary_gpu_fb, -+ MetaDrmBuffer *secondary_gpu_fb) ++acquire_front_buffer (CoglOnscreen *onscreen, ++ MetaDrmBuffer *primary_gpu_fb, ++ MetaDrmBuffer *secondary_gpu_fb, ++ GError **error) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; @@ -1774,8 +2435,8 @@ index 9b739faf39..6120eeec7b 100644 + return copy_shared_framebuffer_gpu (onscreen, + secondary_gpu_state, + renderer_gpu_data, -+ egl_context_changed, -+ primary_gpu_fb); ++ primary_gpu_fb, ++ error); } + + g_assert_not_reached (); @@ -1783,7 +2444,7 @@ index 9b739faf39..6120eeec7b 100644 } static void -@@ -1284,10 +1312,36 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1284,10 +1390,36 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback, g_warning ("Page flip failed: %s", error->message); frame_info = cogl_onscreen_peek_head_frame_info (onscreen); @@ -1823,7 +2484,12 @@ index 9b739faf39..6120eeec7b 100644 } static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = { -@@ -1308,32 +1362,38 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1303,37 +1435,41 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + { + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); +- CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); + CoglRenderer *cogl_renderer = cogl_context->display->renderer; CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; @@ -1840,7 +2506,7 @@ index 9b739faf39..6120eeec7b 100644 - MetaKmsUpdate *kms_update; CoglOnscreenClass *parent_class; gboolean create_timestamp_query = TRUE; - gboolean egl_context_changed = FALSE; +- gboolean egl_context_changed = FALSE; - MetaPowerSave power_save_mode; g_autoptr (GError) error = NULL; MetaDrmBufferFlags buffer_flags; @@ -1870,22 +2536,45 @@ index 9b739faf39..6120eeec7b 100644 secondary_gpu_fb = update_secondary_gpu_state_pre_swap_buffers (onscreen, rectangles, -@@ -1400,21 +1460,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - #endif - } +@@ -1383,46 +1519,28 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + g_warning ("Failed to lock front buffer on %s: %s", + meta_device_file_get_path (render_device_file), + error->message); +- +- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; +- meta_onscreen_native_notify_frame_complete (onscreen); +- return; ++ goto swap_failed; + } + primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm)); +- break; +- case META_RENDERER_NATIVE_MODE_SURFACELESS: +- g_assert_not_reached (); +- break; +-#ifdef HAVE_EGL_DEVICE +- case META_RENDERER_NATIVE_MODE_EGL_DEVICE: +- break; +-#endif +- } +- - update_secondary_gpu_state_post_swap_buffers (onscreen, - &egl_context_changed, - primary_gpu_fb, - &secondary_gpu_fb); -+ buffer = acquire_front_buffer (onscreen, -+ &egl_context_changed, -+ primary_gpu_fb, -+ secondary_gpu_fb); ++ buffer = acquire_front_buffer (onscreen, ++ primary_gpu_fb, ++ secondary_gpu_fb, ++ &error); ++ if (buffer == NULL) ++ { ++ g_warning ("Failed to acquire front buffer: %s", error->message); ++ goto swap_failed; ++ } - switch (renderer_gpu_data->mode) - { - case META_RENDERER_NATIVE_MODE_GBM: +- switch (renderer_gpu_data->mode) +- { +- case META_RENDERER_NATIVE_MODE_GBM: - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - if (onscreen_native->secondary_gpu_state) - g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); @@ -1898,27 +2587,43 @@ index 9b739faf39..6120eeec7b 100644 { g_warning ("Failed to ensure KMS FB ID on %s: %s", meta_device_file_get_path (render_device_file), -@@ -1433,6 +1489,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + error->message); +- +- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; +- meta_onscreen_native_notify_frame_complete (onscreen); +- return; ++ goto swap_failed; + } + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: +@@ -1433,21 +1551,86 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } +- /* +- * If we changed EGL context, cogl will have the wrong idea about what is +- * current, making it fail to set it when it needs to. Avoid that by making +- * EGL_NO_CONTEXT current now, making cogl eventually set the correct +- * context. +- */ +- if (egl_context_changed) +- _cogl_winsys_egl_ensure_current (cogl_display); + assign_next_frame (onscreen_native, frame); -+ -+ clutter_frame_set_result (frame, -+ CLUTTER_FRAME_RESULT_PENDING_PRESENTED); -+ - /* - * If we changed EGL context, cogl will have the wrong idea about what is - * current, making it fail to set it when it needs to. Avoid that by making -@@ -1442,12 +1503,73 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, - if (egl_context_changed) - _cogl_winsys_egl_ensure_current (cogl_display); - kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc)); - kms_device = meta_kms_crtc_get_device (kms_crtc); ++ clutter_frame_set_result (frame, ++ CLUTTER_FRAME_RESULT_PENDING_PRESENTED); ++ + meta_frame_native_set_damage (frame_native, rectangles, n_rectangles); + onscreen_native->swaps_pending++; + try_post_latest_swap (onscreen); ++ return; ++ ++swap_failed: ++ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; ++ meta_onscreen_native_notify_frame_complete (onscreen); ++ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); +} + +static void @@ -1945,6 +2650,8 @@ index 9b739faf39..6120eeec7b 100644 + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + g_autoptr (ClutterFrame) frame = NULL; + MetaFrameNative *frame_native; ++ int sync_fd; ++ COGL_TRACE_SCOPED_ANCHOR (MetaRendererNativePostKmsUpdate); + + if (onscreen_native->next_frame == NULL || + onscreen_native->view == NULL || @@ -1986,7 +2693,7 @@ index 9b739faf39..6120eeec7b 100644 kms_update = meta_frame_native_ensure_kms_update (frame_native, kms_device); meta_kms_update_add_result_listener (kms_update, -@@ -1469,13 +1591,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1469,13 +1652,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, { meta_renderer_native_queue_power_save_page_flip (renderer_native, onscreen); @@ -1995,13 +2702,14 @@ index 9b739faf39..6120eeec7b 100644 return; } - COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate, +- COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate, - "Meta::OnscreenNative::swap_buffers_with_damage#post_pending_update()"); -+ "Meta::OnscreenNative::try_post_latest_swap#post_pending_update()"); ++ COGL_TRACE_BEGIN_ANCHORED (MetaRendererNativePostKmsUpdate, ++ "Meta::OnscreenNative::try_post_latest_swap#post_pending_update()"); switch (renderer_gpu_data->mode) { -@@ -1490,8 +1610,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1490,8 +1671,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update = meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_queue_mode_set_update (renderer_native, kms_update); @@ -2010,7 +2718,7 @@ index 9b739faf39..6120eeec7b 100644 return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) -@@ -1505,8 +1623,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1505,8 +1684,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_frame_native_steal_kms_update (frame_native); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -2019,7 +2727,7 @@ index 9b739faf39..6120eeec7b 100644 return; } break; -@@ -1522,8 +1638,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1522,8 +1699,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, kms_update); meta_renderer_native_post_mode_set_updates (renderer_native); @@ -2028,15 +2736,28 @@ index 9b739faf39..6120eeec7b 100644 return; } break; -@@ -1538,7 +1652,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, +@@ -1536,9 +1711,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, + meta_kms_device_get_path (kms_device)); + kms_update = meta_frame_native_steal_kms_update (frame_native); ++ sync_fd = cogl_context_get_latest_sync_fd (cogl_context); ++ meta_kms_update_set_sync_fd (kms_update, sync_fd); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); - clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED); } gboolean -@@ -1606,11 +1719,15 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1571,7 +1747,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, + assign_primary_plane (crtc_kms, + buffer, + test_update, +- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT, ++ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC, + &src_rect, + &dst_rect); + +@@ -1606,11 +1782,15 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, G_IO_ERROR_PERMISSION_DENIED)) { ClutterStageView *view = CLUTTER_STAGE_VIEW (onscreen_native->view); @@ -2054,7 +2775,7 @@ index 9b739faf39..6120eeec7b 100644 clutter_stage_view_add_redraw_clip (view, NULL); clutter_stage_view_schedule_update_now (view); } -@@ -1619,7 +1736,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, +@@ -1619,7 +1799,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); @@ -2063,7 +2784,7 @@ index 9b739faf39..6120eeec7b 100644 } static const MetaKmsResultListenerVtable scanout_result_listener_vtable = { -@@ -1671,16 +1788,28 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, +@@ -1671,16 +1851,28 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } @@ -2097,7 +2818,16 @@ index 9b739faf39..6120eeec7b 100644 frame_info->cpu_time_before_buffer_swap_us = g_get_monotonic_time (); -@@ -1786,11 +1915,15 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, +@@ -1701,7 +1893,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, + onscreen_native->view, + onscreen_native->crtc, + kms_update, +- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT, ++ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC, + NULL, + 0); + +@@ -1786,11 +1978,15 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, ClutterFrame *frame) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); @@ -2117,7 +2847,7 @@ index 9b739faf39..6120eeec7b 100644 maybe_update_frame_sync (onscreen_native, frame); } -@@ -1919,22 +2052,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1919,22 +2115,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); MetaFrameNative *frame_native = meta_frame_native_from_frame (frame); MetaKmsUpdate *kms_update; @@ -2205,7 +2935,7 @@ index 9b739faf39..6120eeec7b 100644 meta_kms_update_add_result_listener (kms_update, &finish_frame_result_listener_vtable, NULL, -@@ -1957,7 +2147,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, +@@ -1957,7 +2210,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, meta_kms_update_set_flushing (kms_update, kms_crtc); meta_kms_device_post_update (kms_device, kms_update, META_KMS_UPDATE_FLAG_NONE); @@ -2224,7 +2954,7 @@ index 9b739faf39..6120eeec7b 100644 } static gboolean -@@ -2865,15 +3065,17 @@ meta_onscreen_native_dispose (GObject *object) +@@ -2865,15 +3128,17 @@ meta_onscreen_native_dispose (GObject *object) meta_onscreen_native_detach (onscreen_native); diff --git a/mr3934.patch b/mr3934.patch deleted file mode 100644 index 87f2cca..0000000 --- a/mr3934.patch +++ /dev/null @@ -1,617 +0,0 @@ -From adb26372d0dc18c90293733f1c5f3b0479badf6c Mon Sep 17 00:00:00 2001 -From: Mingi Sung -Date: Wed, 28 Aug 2024 20:21:07 +0900 -Subject: [PATCH] Merge branch 'crtc_frame_deadline_dispatch-track-duration' - into gnome-46 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Track dispatch duration in crtc_frame_deadline_dispatch -and take it into account in meta_kms_crtc_get_deadline_evasion. - -This uses the same fundamental approach as clutter frame clock scheduling: - -Measure the deadline timer dispatch duration, keep track of the longest -duration, and set the timer to fire such that the longest measured -dispatch duration would result in it completing shortly before start of -vblank. - -Closes: #3612 - -Author: Michel Dänzer -Source: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934 -Commit: 88e7f353c482b2574927dbd06b483ebb3197379b - -Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184 -Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3265 - -Signed-off-by: Mingi Sung ---- - clutter/clutter/clutter-frame-clock.c | 12 ++++- - clutter/clutter/clutter-frame-clock.h | 4 ++ - clutter/clutter/clutter-stage-view.c | 4 ++ - clutter/clutter/clutter-stage-view.h | 2 + - src/backends/native/meta-crtc-kms.c | 10 ++++ - src/backends/native/meta-crtc-native.c | 8 ++++ - src/backends/native/meta-crtc-native.h | 3 ++ - src/backends/native/meta-crtc-virtual.c | 8 ++++ - src/backends/native/meta-kms-crtc.c | 63 ++++++++++++++++++++++--- - src/backends/native/meta-kms-crtc.h | 5 ++ - src/backends/native/meta-kms-impl-device.c | 51 ++++++++++++++++++-- - src/backends/native/meta-onscreen-native.c | 12 +++-- - src/backends/native/meta-renderer-view-native.c | 41 ++++++++++++++++ - src/core/util.c | 3 ++ - src/meta/meta-debug.h | 2 + - src/meta/util.h | 3 ++ - src/tests/meta-monitor-manager-test.c | 6 +++ - 17 files changed, 222 insertions(+), 15 deletions(-) - -diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c -index 30a319f604..4bba34887a 100644 ---- a/clutter/clutter/clutter-frame-clock.c -+++ b/clutter/clutter/clutter-frame-clock.c -@@ -137,6 +137,8 @@ struct _ClutterFrameClock - - int64_t last_dispatch_interval_us; - -+ int64_t deadline_evasion_us; -+ - char *output_name; - }; - -@@ -389,7 +391,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, - - frame_clock->shortterm_max_update_duration_us = - CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us + -- MAX (swap_to_rendering_done_us, swap_to_flip_us), -+ MAX (swap_to_rendering_done_us, -+ swap_to_flip_us + frame_clock->deadline_evasion_us), - frame_clock->shortterm_max_update_duration_us, - frame_clock->refresh_interval_us); - -@@ -1253,3 +1256,10 @@ clutter_frame_clock_class_init (ClutterFrameClockClass *klass) - G_TYPE_NONE, - 0); - } -+ -+void -+clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock, -+ int64_t deadline_evasion_us) -+{ -+ frame_clock->deadline_evasion_us = deadline_evasion_us; -+} -diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h -index a7be5ef316..6a940f48be 100644 ---- a/clutter/clutter/clutter-frame-clock.h -+++ b/clutter/clutter/clutter-frame-clock.h -@@ -106,3 +106,7 @@ void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, - int64_t flip_time_us); - - GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); -+ -+CLUTTER_EXPORT -+void clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock, -+ int64_t deadline_evasion_us); -diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c -index f5188e2acf..2aabe9aa4c 100644 ---- a/clutter/clutter/clutter-stage-view.c -+++ b/clutter/clutter/clutter-stage-view.c -@@ -740,6 +740,10 @@ clutter_stage_view_schedule_update (ClutterStageView *view) - { - ClutterStageViewPrivate *priv = - clutter_stage_view_get_instance_private (view); -+ ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view); -+ -+ if (view_class->schedule_update) -+ view_class->schedule_update (view); - - clutter_frame_clock_schedule_update (priv->frame_clock); - } -diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h -index c0888f7f94..bdaa065c00 100644 ---- a/clutter/clutter/clutter-stage-view.h -+++ b/clutter/clutter/clutter-stage-view.h -@@ -54,6 +54,8 @@ struct _ClutterStageViewClass - ClutterFrame * (* new_frame) (ClutterStageView *view); - - ClutterPaintFlag (* get_default_paint_flags) (ClutterStageView *view); -+ -+ void (* schedule_update) (ClutterStageView *view); - }; - - CLUTTER_EXPORT -diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c -index 3498f922a3..8cb0e935a7 100644 ---- a/src/backends/native/meta-crtc-kms.c -+++ b/src/backends/native/meta-crtc-kms.c -@@ -348,6 +348,15 @@ meta_crtc_kms_is_hw_cursor_supported (MetaCrtcNative *crtc_native) - return meta_kms_device_has_cursor_plane_for (kms_device, kms_crtc); - } - -+static int64_t -+meta_crtc_kms_get_deadline_evasion (MetaCrtcNative *crtc_native) -+{ -+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native); -+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); -+ -+ return meta_kms_crtc_get_deadline_evasion (kms_crtc); -+} -+ - MetaKmsPlane * - meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms) - { -@@ -479,6 +488,7 @@ meta_crtc_kms_class_init (MetaCrtcKmsClass *klass) - - crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled; - crtc_native_class->is_hw_cursor_supported = meta_crtc_kms_is_hw_cursor_supported; -+ crtc_native_class->get_deadline_evasion = meta_crtc_kms_get_deadline_evasion; - - signals[GAMMA_LUT_CHANGED] = - g_signal_new ("gamma-lut-changed", -diff --git a/src/backends/native/meta-crtc-native.c b/src/backends/native/meta-crtc-native.c -index fc280f696e..80406a5033 100644 ---- a/src/backends/native/meta-crtc-native.c -+++ b/src/backends/native/meta-crtc-native.c -@@ -39,6 +39,14 @@ meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native) - return klass->is_hw_cursor_supported (crtc_native); - } - -+int64_t -+meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native) -+{ -+ MetaCrtcNativeClass *klass = META_CRTC_NATIVE_GET_CLASS (crtc_native); -+ -+ return klass->get_deadline_evasion (crtc_native); -+} -+ - static void - meta_crtc_native_init (MetaCrtcNative *crtc_native) - { -diff --git a/src/backends/native/meta-crtc-native.h b/src/backends/native/meta-crtc-native.h -index 3fb4bc7586..1f9a2ed46c 100644 ---- a/src/backends/native/meta-crtc-native.h -+++ b/src/backends/native/meta-crtc-native.h -@@ -31,9 +31,12 @@ struct _MetaCrtcNativeClass - gboolean (* is_transform_handled) (MetaCrtcNative *crtc_native, - MetaMonitorTransform monitor_transform); - gboolean (* is_hw_cursor_supported) (MetaCrtcNative *crtc_native); -+ int64_t (* get_deadline_evasion) (MetaCrtcNative *crtc_native); - }; - - gboolean meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native, - MetaMonitorTransform transform); - - gboolean meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native); -+ -+int64_t meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native); -diff --git a/src/backends/native/meta-crtc-virtual.c b/src/backends/native/meta-crtc-virtual.c -index 76165eb1bd..00b599c612 100644 ---- a/src/backends/native/meta-crtc-virtual.c -+++ b/src/backends/native/meta-crtc-virtual.c -@@ -70,6 +70,12 @@ meta_crtc_virtual_is_hw_cursor_supported (MetaCrtcNative *crtc_native) - return TRUE; - } - -+static int64_t -+meta_crtc_virtual_get_deadline_evasion (MetaCrtcNative *crtc_native) -+{ -+ return 0; -+} -+ - static void - meta_crtc_virtual_init (MetaCrtcVirtual *crtc_virtual) - { -@@ -89,4 +95,6 @@ meta_crtc_virtual_class_init (MetaCrtcVirtualClass *klass) - meta_crtc_virtual_is_transform_handled; - crtc_native_class->is_hw_cursor_supported = - meta_crtc_virtual_is_hw_cursor_supported; -+ crtc_native_class->get_deadline_evasion = -+ meta_crtc_virtual_get_deadline_evasion; - } -diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c -index a0872089a0..cad9f88ce5 100644 ---- a/src/backends/native/meta-kms-crtc.c -+++ b/src/backends/native/meta-kms-crtc.c -@@ -28,8 +28,7 @@ - #include "backends/native/meta-kms-update-private.h" - #include "backends/native/meta-kms-utils.h" - --#define DEADLINE_EVASION_US 800 --#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000 -+#define DEADLINE_EVASION_CONSTANT_US 200 - - #define MINIMUM_REFRESH_RATE 30.f - -@@ -50,6 +49,10 @@ struct _MetaKmsCrtc - MetaKmsCrtcState current_state; - - MetaKmsCrtcPropTable prop_table; -+ -+ int64_t shortterm_max_dispatch_duration_us; -+ int64_t deadline_evasion_us; -+ int64_t deadline_evasion_update_time_us; - }; - - G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) -@@ -543,6 +546,33 @@ get_crtc_type_bitmask (MetaKmsCrtc *crtc) - } - } - -+static void -+maybe_update_deadline_evasion (MetaKmsCrtc *crtc, -+ int64_t next_presentation_time_us) -+{ -+ /* Do not update long-term max if there has been no measurement */ -+ if (!crtc->shortterm_max_dispatch_duration_us) -+ return; -+ -+ if (next_presentation_time_us - crtc->deadline_evasion_update_time_us < -+ G_USEC_PER_SEC) -+ return; -+ -+ if (crtc->deadline_evasion_us > crtc->shortterm_max_dispatch_duration_us) -+ { -+ /* Exponential drop-off toward the clamped short-term max */ -+ crtc->deadline_evasion_us -= -+ (crtc->deadline_evasion_us - crtc->shortterm_max_dispatch_duration_us) / 2; -+ } -+ else -+ { -+ crtc->deadline_evasion_us = crtc->shortterm_max_dispatch_duration_us; -+ } -+ -+ crtc->shortterm_max_dispatch_duration_us = 0; -+ crtc->deadline_evasion_update_time_us = next_presentation_time_us; -+} -+ - gboolean - meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, - int64_t *out_next_deadline_us, -@@ -610,10 +640,8 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, - * - */ - -- if (meta_is_topic_enabled (META_DEBUG_KMS)) -- deadline_evasion_us = DEADLINE_EVASION_WITH_KMS_TOPIC_US; -- else -- deadline_evasion_us = DEADLINE_EVASION_US; -+ deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc); -+ maybe_update_deadline_evasion (crtc, next_presentation_us); - - vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode); - next_deadline_us = next_presentation_us - (vblank_duration_us + -@@ -625,3 +653,26 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc, - - return TRUE; - } -+ -+void -+meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc, -+ int64_t duration_us) -+{ -+ int64_t refresh_interval_us; -+ -+ if (duration_us <= crtc->shortterm_max_dispatch_duration_us) -+ return; -+ -+ refresh_interval_us = -+ (int64_t) (0.5 + G_USEC_PER_SEC / -+ meta_calculate_drm_mode_refresh_rate (&crtc->current_state.drm_mode)); -+ -+ crtc->shortterm_max_dispatch_duration_us = MIN (duration_us, refresh_interval_us); -+} -+ -+int64_t -+meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc) -+{ -+ return MAX (crtc->shortterm_max_dispatch_duration_us, -+ crtc->deadline_evasion_us) + DEADLINE_EVASION_CONSTANT_US; -+} -diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h -index 580ee9a89c..b293f8e7cc 100644 ---- a/src/backends/native/meta-kms-crtc.h -+++ b/src/backends/native/meta-kms-crtc.h -@@ -65,3 +65,8 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc); - - META_EXPORT_TEST - gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc); -+ -+void meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc, -+ int64_t duration_us); -+ -+int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc); -diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c -index 6758982a6a..6ce62cd697 100644 ---- a/src/backends/native/meta-kms-impl-device.c -+++ b/src/backends/native/meta-kms-impl-device.c -@@ -39,6 +39,7 @@ - #include "backends/native/meta-kms-plane-private.h" - #include "backends/native/meta-kms-plane.h" - #include "backends/native/meta-kms-private.h" -+#include "backends/native/meta-kms-utils.h" - #include "backends/native/meta-thread-private.h" - - #include "meta-default-modes.h" -@@ -71,6 +72,7 @@ typedef struct _CrtcDeadline - GSource *source; - gboolean armed; - gboolean is_deadline_page_flip; -+ int64_t expected_deadline_time_us; - int64_t expected_presentation_time_us; - gboolean has_expected_presentation_time; - } deadline; -@@ -1165,6 +1167,7 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame, - timerfd_settime (crtc_frame->deadline.timer_fd, - TFD_TIMER_ABSTIME, &its, NULL); - -+ crtc_frame->deadline.expected_deadline_time_us = next_deadline_us; - crtc_frame->deadline.expected_presentation_time_us = next_presentation_us; - crtc_frame->deadline.has_expected_presentation_time = next_presentation_us != 0; - crtc_frame->deadline.armed = TRUE; -@@ -1197,7 +1200,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, - CrtcFrame *crtc_frame = user_data; - - if (crtc_frame->deadline.is_deadline_page_flip && -- meta_is_topic_enabled (META_DEBUG_KMS)) -+ meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE)) - { - struct timeval page_flip_timeval; - int64_t presentation_time_us; -@@ -1210,7 +1213,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, - - if (crtc_frame->deadline.has_expected_presentation_time) - { -- meta_topic (META_DEBUG_KMS, -+ meta_topic (META_DEBUG_KMS_DEADLINE, - "Deadline page flip presentation time: %" G_GINT64_FORMAT " us, " - "expected %" G_GINT64_FORMAT " us " - "(diff: %" G_GINT64_FORMAT ")", -@@ -1221,7 +1224,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc, - } - else - { -- meta_topic (META_DEBUG_KMS, -+ meta_topic (META_DEBUG_KMS_DEADLINE, - "Deadline page flip presentation time: %" G_GINT64_FORMAT " us", - presentation_time_us); - } -@@ -1390,11 +1393,16 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, - GError **error) - { - CrtcFrame *crtc_frame = user_data; -- MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc); -+ MetaKmsCrtc *crtc = crtc_frame->crtc; -+ MetaKmsDevice *device = meta_kms_crtc_get_device (crtc); - MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device); - g_autoptr (MetaKmsFeedback) feedback = NULL; - uint64_t timer_value; - ssize_t ret; -+ int64_t dispatch_time_us = 0, update_done_time_us, interval_us; -+ -+ if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE)) -+ dispatch_time_us = g_get_monotonic_time (); - - ret = read (crtc_frame->deadline.timer_fd, - &timer_value, -@@ -1416,6 +1424,36 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl, - crtc_frame->crtc, - g_steal_pointer (&crtc_frame->pending_update), - META_KMS_UPDATE_FLAG_NONE); -+ -+ update_done_time_us = g_get_monotonic_time (); -+ /* Calculate how long after the planned start of deadline dispatch it finished */ -+ interval_us = update_done_time_us - crtc_frame->deadline.expected_deadline_time_us; -+ -+ if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE)) -+ { -+ int64_t deadline_evasion_us, lateness_us, duration_us, vblank_delta_us; -+ -+ deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc); -+ lateness_us = dispatch_time_us - -+ crtc_frame->deadline.expected_deadline_time_us; -+ duration_us = update_done_time_us - dispatch_time_us; -+ vblank_delta_us = deadline_evasion_us - lateness_us - duration_us; -+ -+ meta_topic (META_DEBUG_KMS_DEADLINE, -+ "Deadline evasion %3"G_GINT64_FORMAT "µs, " -+ "dispatch started %3"G_GINT64_FORMAT "µs %s and " -+ "completed %3"G_GINT64_FORMAT "µs after that, " -+ "%3"G_GINT64_FORMAT "µs %s start of vblank.", -+ deadline_evasion_us, -+ ABS (lateness_us), -+ lateness_us >= 0 ? "late" : "early", -+ duration_us, -+ ABS (vblank_delta_us), -+ vblank_delta_us >= 0 ? "before" : "after"); -+ } -+ -+ meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us); -+ - if (meta_kms_feedback_did_pass (feedback)) - crtc_frame->deadline.is_deadline_page_flip = TRUE; - disarm_crtc_frame_deadline_timer (crtc_frame); -@@ -1592,6 +1630,11 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device, - meta_kms_device_handle_flush (priv->device, latch_crtc); - - feedback = do_process (impl_device, latch_crtc, update, flags); -+ -+ if (meta_kms_feedback_did_pass (feedback) && -+ crtc_frame->deadline.armed) -+ disarm_crtc_frame_deadline_timer (crtc_frame); -+ - meta_kms_feedback_unref (feedback); - return; - -diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 9b739faf39..b790c1e5c8 100644 ---- a/src/backends/native/meta-onscreen-native.c -+++ b/src/backends/native/meta-onscreen-native.c -@@ -1786,11 +1786,15 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen, - ClutterFrame *frame) - { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); -- MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); -- MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - -- meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), -- kms_crtc); -+ if (meta_get_debug_paint_flags () & META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY) -+ { -+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); -+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); -+ -+ meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), kms_crtc); -+ } -+ - maybe_update_frame_sync (onscreen_native, frame); - } - -diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c -index a04e2e3533..5699f9a558 100644 ---- a/src/backends/native/meta-renderer-view-native.c -+++ b/src/backends/native/meta-renderer-view-native.c -@@ -24,6 +24,7 @@ - - #include "backends/native/meta-renderer-view-native.h" - -+#include "backends/native/meta-crtc-native.h" - #include "backends/native/meta-frame-native.h" - - struct _MetaRendererViewNative -@@ -34,18 +35,58 @@ struct _MetaRendererViewNative - G_DEFINE_TYPE (MetaRendererViewNative, meta_renderer_view_native, - META_TYPE_RENDERER_VIEW) - -+static void -+update_frame_clock_deadline_evasion (MetaRendererView *renderer_view) -+{ -+ ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view); -+ ClutterFrameClock *frame_clock; -+ MetaCrtc *crtc; -+ MetaCrtcNative *crtc_native; -+ int64_t deadline_evasion_us; -+ -+ frame_clock = clutter_stage_view_get_frame_clock (stage_view); -+ crtc = meta_renderer_view_get_crtc (renderer_view); -+ crtc_native = META_CRTC_NATIVE (crtc); -+ -+ deadline_evasion_us = meta_crtc_native_get_deadline_evasion (crtc_native); -+ clutter_frame_clock_set_deadline_evasion (frame_clock, -+ deadline_evasion_us); -+} -+ -+static void -+meta_renderer_view_native_constructed (GObject *object) -+{ -+ MetaRendererView *renderer_view = META_RENDERER_VIEW (object); -+ -+ G_OBJECT_CLASS (meta_renderer_view_native_parent_class)->constructed (object); -+ -+ update_frame_clock_deadline_evasion (renderer_view); -+} -+ - static ClutterFrame * - meta_renderer_view_native_new_frame (ClutterStageView *stage_view) - { - return (ClutterFrame *) meta_frame_native_new (); - } - -+static void -+meta_renderer_view_native_schedule_update (ClutterStageView *stage_view) -+{ -+ MetaRendererView *renderer_view = META_RENDERER_VIEW (stage_view); -+ -+ update_frame_clock_deadline_evasion (renderer_view); -+} -+ - static void - meta_renderer_view_native_class_init (MetaRendererViewNativeClass *klass) - { -+ GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterStageViewClass *stage_view_class = CLUTTER_STAGE_VIEW_CLASS (klass); - -+ object_class->constructed = meta_renderer_view_native_constructed; -+ - stage_view_class->new_frame = meta_renderer_view_native_new_frame; -+ stage_view_class->schedule_update = meta_renderer_view_native_schedule_update; - } - - static void -diff --git a/src/core/util.c b/src/core/util.c -index 05a0dea398..f8a08c747f 100644 ---- a/src/core/util.c -+++ b/src/core/util.c -@@ -69,6 +69,7 @@ static const GDebugKey meta_debug_keys[] = { - { "color", META_DEBUG_COLOR }, - { "input-events", META_DEBUG_INPUT_EVENTS }, - { "eis", META_DEBUG_EIS }, -+ { "kms-deadline", META_DEBUG_KMS_DEADLINE }, - }; - - static gint verbose_topics = 0; -@@ -326,6 +327,8 @@ meta_topic_to_string (MetaDebugTopic topic) - return "INPUT_EVENTS"; - case META_DEBUG_EIS: - return "EIS"; -+ case META_DEBUG_KMS_DEADLINE: -+ return "KMS_DEADLINE"; - } - - return "WM"; -diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h -index b4c70144b7..2de9a89d75 100644 ---- a/src/meta/meta-debug.h -+++ b/src/meta/meta-debug.h -@@ -50,6 +50,7 @@ - * @META_DEBUG_COLOR: color management - * @META_DEBUG_INPUT_EVENTS: input events - * @META_DEBUG_EIS: eis state -+ * @META_DEBUG_KMS_DEADLINE: KMS deadline timers - */ - typedef enum - { -@@ -83,6 +84,7 @@ typedef enum - META_DEBUG_COLOR = 1 << 26, - META_DEBUG_INPUT_EVENTS = 1 << 27, - META_DEBUG_EIS = 1 << 28, -+ META_DEBUG_KMS_DEADLINE = 1 << 29, - } MetaDebugTopic; - - META_EXPORT -diff --git a/src/meta/util.h b/src/meta/util.h -index ca8ca2adeb..91ca6a8366 100644 ---- a/src/meta/util.h -+++ b/src/meta/util.h -@@ -51,11 +51,14 @@ void meta_fatal (const char *format, - * MetaDebugPaintFlag: - * @META_DEBUG_PAINT_NONE: default - * @META_DEBUG_PAINT_OPAQUE_REGION: paint opaque regions -+ * @META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY: make cursor updates await compositing -+ * frames - */ - typedef enum - { - META_DEBUG_PAINT_NONE = 0, - META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0, -+ META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY = 1 << 1, - } MetaDebugPaintFlag; - - META_EXPORT -diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c -index f9275160c3..fd37eab380 100644 ---- a/src/tests/meta-monitor-manager-test.c -+++ b/src/tests/meta-monitor-manager-test.c -@@ -517,6 +517,12 @@ meta_crtc_test_set_gamma_lut (MetaCrtc *crtc, - sizeof (uint16_t) * lut->size); - } - -+static int64_t -+meta_crtc_test_get_deadline_evasion (MetaCrtcNative *crtc_native) -+{ -+ return 0; -+} -+ - static void - meta_crtc_test_finalize (GObject *object) - { diff --git a/mr3960.patch b/mr3960.patch new file mode 100644 index 0000000..c018b03 --- /dev/null +++ b/mr3960.patch @@ -0,0 +1,322 @@ +From 36a1a74f7a6ea674e3911e89935256f1c6c5a149 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 20 Aug 2024 11:07:29 +0200 +Subject: [PATCH] kms: Inhibit real time scheduling until initial mode set + +We're already inhibiting real time scheduling when reading new KMS state +after hot plugs, as well as when during mode sets, due to the kernel not +being able to reliably handle these within the 250 ms limit. However, we +didn't do this during initial probing, which meant that occasionally +we'd run into these kind of issues during startup. + +Handle this by always inhibiting real time scheduling up front, and +don't uninhibit until all initially discovered device have finished +processing their initial mode set. + +Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3628 +Part-of: + +Signed-off-by: Mingi Sung +--- + src/backends/native/meta-backend-native.c | 3 ++ + src/backends/native/meta-kms-impl-device.c | 32 ++++++++++++++++++++++ + src/backends/native/meta-kms-impl.c | 20 ++++++++++++++ + src/backends/native/meta-kms-impl.h | 2 ++ + src/backends/native/meta-kms.c | 17 ++++++++++++ + src/backends/native/meta-kms.h | 2 ++ + src/backends/native/meta-thread-impl.c | 9 ++++++ + src/backends/native/meta-thread-impl.h | 4 +++ + src/backends/native/meta-thread.c | 26 ++++++++++++------ + 9 files changed, 106 insertions(+), 9 deletions(-) + +diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c +index 131a687e21..e3ed02894a 100644 +--- a/src/backends/native/meta-backend-native.c ++++ b/src/backends/native/meta-backend-native.c +@@ -609,6 +609,7 @@ init_gpus (MetaBackendNative *native, + { + MetaBackend *backend = META_BACKEND (native); + MetaUdev *udev = meta_backend_native_get_udev (native); ++ MetaKms *kms = meta_backend_native_get_kms (native); + g_autoptr (GError) local_error = NULL; + MetaUdevDeviceType device_type = 0; + GList *devices; +@@ -669,6 +670,8 @@ init_gpus (MetaBackendNative *native, + + g_list_free_full (devices, g_object_unref); + ++ meta_kms_notify_probed (kms); ++ + if (!meta_backend_is_headless (backend) && + g_list_length (meta_backend_get_gpus (backend)) == 0) + { +diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c +index 6758982a6a..f73aecac7a 100644 +--- a/src/backends/native/meta-kms-impl-device.c ++++ b/src/backends/native/meta-kms-impl-device.c +@@ -108,6 +108,8 @@ typedef struct _MetaKmsImplDevicePrivate + + GHashTable *crtc_frames; + ++ gboolean realtime_inhibited_pending_mode_set; ++ + MetaDeadlineTimerState deadline_timer_state; + + gboolean sync_file_retrieved; +@@ -1734,6 +1736,12 @@ process_mode_set_update (MetaKmsImplDevice *impl_device, + feedback = do_process (impl_device, NULL, update, flags); + meta_thread_uninhibit_realtime_in_impl (thread); + ++ if (priv->realtime_inhibited_pending_mode_set) ++ { ++ priv->realtime_inhibited_pending_mode_set = FALSE; ++ meta_thread_uninhibit_realtime_in_impl (thread); ++ } ++ + return feedback; + } + +@@ -1924,6 +1932,15 @@ meta_kms_impl_device_finalize (GObject *object) + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); + ++ if (priv->realtime_inhibited_pending_mode_set) ++ { ++ MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl); ++ MetaThread *thread = meta_thread_impl_get_thread (thread_impl); ++ ++ priv->realtime_inhibited_pending_mode_set = FALSE; ++ meta_thread_uninhibit_realtime_in_impl (thread); ++ } ++ + meta_kms_impl_remove_impl_device (priv->impl, impl_device); + + g_list_free_full (priv->planes, g_object_unref); +@@ -1973,6 +1990,16 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, + + update_connectors (impl_device, drm_resources, 0); + ++ if (!priv->crtcs) ++ { ++ MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl); ++ MetaThread *thread = meta_thread_impl_get_thread (thread_impl); ++ ++ g_warn_if_fail (priv->realtime_inhibited_pending_mode_set); ++ meta_thread_uninhibit_realtime_in_impl (thread); ++ priv->realtime_inhibited_pending_mode_set = FALSE; ++ } ++ + drmModeFreeResources (drm_resources); + + return TRUE; +@@ -2050,6 +2077,8 @@ meta_kms_impl_device_initable_init (GInitable *initable, + MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable); + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); ++ MetaThreadImpl *thread_impl = META_THREAD_IMPL (priv->impl); ++ MetaThread *thread = meta_thread_impl_get_thread (thread_impl); + int fd; + + if (!ensure_device_file (impl_device, error)) +@@ -2075,6 +2104,9 @@ meta_kms_impl_device_initable_init (GInitable *initable, + + priv->sync_file = -1; + ++ meta_thread_inhibit_realtime_in_impl (thread); ++ priv->realtime_inhibited_pending_mode_set = TRUE; ++ + return TRUE; + } + +diff --git a/src/backends/native/meta-kms-impl.c b/src/backends/native/meta-kms-impl.c +index 99019ca85f..e34af98202 100644 +--- a/src/backends/native/meta-kms-impl.c ++++ b/src/backends/native/meta-kms-impl.c +@@ -172,12 +172,32 @@ meta_kms_impl_finalize (GObject *object) + G_OBJECT_CLASS (meta_kms_impl_parent_class)->finalize (object); + } + ++static void ++meta_kms_impl_setup (MetaThreadImpl *thread_impl) ++{ ++ MetaThread *thread = meta_thread_impl_get_thread (thread_impl); ++ ++ meta_thread_inhibit_realtime_in_impl (thread); ++} ++ ++void ++meta_kms_impl_notify_probed (MetaKmsImpl *impl) ++{ ++ MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl); ++ MetaThread *thread = meta_thread_impl_get_thread (thread_impl); ++ ++ meta_thread_uninhibit_realtime_in_impl (thread); ++} ++ + static void + meta_kms_impl_class_init (MetaKmsImplClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ MetaThreadImplClass *thread_impl_class = META_THREAD_IMPL_CLASS (klass); + + object_class->finalize = meta_kms_impl_finalize; ++ ++ thread_impl_class->setup = meta_kms_impl_setup; + } + + MetaKmsUpdateFilter * +diff --git a/src/backends/native/meta-kms-impl.h b/src/backends/native/meta-kms-impl.h +index f8379fab28..582bebf5e6 100644 +--- a/src/backends/native/meta-kms-impl.h ++++ b/src/backends/native/meta-kms-impl.h +@@ -53,6 +53,8 @@ void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl); + + MetaKmsImpl * meta_kms_impl_new (MetaKms *kms); + ++void meta_kms_impl_notify_probed (MetaKmsImpl *impl); ++ + MetaKmsUpdateFilter * meta_kms_impl_add_update_filter (MetaKmsImpl *impl, + MetaKmsUpdateFilterFunc func, + gpointer user_data); +diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c +index d41fcefb5a..d989337a10 100644 +--- a/src/backends/native/meta-kms.c ++++ b/src/backends/native/meta-kms.c +@@ -413,6 +413,23 @@ meta_kms_new (MetaBackend *backend, + return kms; + } + ++static gpointer ++notify_probed_in_impl (MetaThreadImpl *thread_impl, ++ gpointer user_data, ++ GError **error) ++{ ++ meta_kms_impl_notify_probed (META_KMS_IMPL (thread_impl)); ++ return NULL; ++} ++ ++void ++meta_kms_notify_probed (MetaKms *kms) ++{ ++ meta_thread_post_impl_task (META_THREAD (kms), ++ notify_probed_in_impl, ++ NULL, NULL, NULL, NULL); ++} ++ + static void + meta_kms_finalize (GObject *object) + { +diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h +index 7434014063..057c7a2348 100644 +--- a/src/backends/native/meta-kms.h ++++ b/src/backends/native/meta-kms.h +@@ -64,6 +64,8 @@ MetaKms * meta_kms_new (MetaBackend *backend, + MetaKmsFlags flags, + GError **error); + ++void meta_kms_notify_probed (MetaKms *kms); ++ + META_EXPORT_TEST + void meta_kms_inhibit_kernel_thread (MetaKms *kms); + +diff --git a/src/backends/native/meta-thread-impl.c b/src/backends/native/meta-thread-impl.c +index 28ef349f7c..d02d49203f 100644 +--- a/src/backends/native/meta-thread-impl.c ++++ b/src/backends/native/meta-thread-impl.c +@@ -568,6 +568,15 @@ meta_thread_impl_dispatch (MetaThreadImpl *thread_impl) + return 1; + } + ++void ++meta_thread_impl_setup (MetaThreadImpl *thread_impl) ++{ ++ MetaThreadImplClass *klass = META_THREAD_IMPL_GET_CLASS (thread_impl); ++ ++ if (klass->setup) ++ klass->setup (thread_impl); ++} ++ + void + meta_thread_impl_run (MetaThreadImpl *thread_impl, + MetaThreadImplRunFlags flags) +diff --git a/src/backends/native/meta-thread-impl.h b/src/backends/native/meta-thread-impl.h +index 2083b3bf16..1837c465cb 100644 +--- a/src/backends/native/meta-thread-impl.h ++++ b/src/backends/native/meta-thread-impl.h +@@ -38,6 +38,8 @@ G_DECLARE_DERIVABLE_TYPE (MetaThreadImpl, meta_thread_impl, + struct _MetaThreadImplClass + { + GObjectClass parent_class; ++ ++ void (* setup) (MetaThreadImpl *thread_impl); + }; + + typedef enum _MetaThreadTaskFeedbackType +@@ -70,6 +72,8 @@ void meta_thread_impl_queue_task (MetaThreadImpl *thread_impl, + + void meta_thread_impl_terminate (MetaThreadImpl *thread_impl); + ++void meta_thread_impl_setup (MetaThreadImpl *thread_impl); ++ + void meta_thread_impl_run (MetaThreadImpl *thread_impl, + MetaThreadImplRunFlags flags); + +diff --git a/src/backends/native/meta-thread.c b/src/backends/native/meta-thread.c +index 08bd9b8fe2..5dcdb05eba 100644 +--- a/src/backends/native/meta-thread.c ++++ b/src/backends/native/meta-thread.c +@@ -333,22 +333,28 @@ request_normal_scheduling (MetaThread *thread, + } + + static gboolean +-should_use_realtime_scheduling_in_impl (MetaThread *thread) ++can_use_realtime_scheduling_in_impl (MetaThread *thread) + { + MetaThreadPrivate *priv = meta_thread_get_instance_private (thread); +- gboolean should_use_realtime_scheduling = FALSE; + + switch (priv->thread_type) + { + case META_THREAD_TYPE_USER: +- break; ++ return FALSE; + case META_THREAD_TYPE_KERNEL: +- if (priv->wants_realtime && priv->kernel.realtime_inhibit_count == 0) +- should_use_realtime_scheduling = TRUE; +- break; ++ return priv->wants_realtime; + } + +- return should_use_realtime_scheduling; ++ g_assert_not_reached (); ++} ++ ++static gboolean ++should_use_realtime_scheduling_in_impl (MetaThread *thread) ++{ ++ MetaThreadPrivate *priv = meta_thread_get_instance_private (thread); ++ ++ return (can_use_realtime_scheduling_in_impl (thread) && ++ priv->kernel.realtime_inhibit_count == 0); + } + + static void +@@ -417,11 +423,13 @@ thread_impl_func (gpointer user_data) + priv->kernel.realtime_inhibit_count = 0; + priv->kernel.is_realtime = FALSE; + ++ meta_thread_impl_setup (impl); ++ + sync_realtime_scheduling_in_impl (thread); + +- if (priv->kernel.is_realtime) ++ if (can_use_realtime_scheduling_in_impl (thread)) + { +- g_message ("Made thread '%s' realtime scheduled", priv->name); ++ g_message ("Thread '%s' will be using real time scheduling", priv->name); + run_flags |= META_THREAD_IMPL_RUN_FLAG_REALTIME; + } + +-- +2.46.0 + diff --git a/mr4015.patch b/mr4015.patch deleted file mode 100644 index a356922..0000000 --- a/mr4015.patch +++ /dev/null @@ -1,345 +0,0 @@ -From cf97df46f751470b6df99376840842afc211636d Mon Sep 17 00:00:00 2001 -From: Gert -Date: Thu, 12 Sep 2024 20:13:33 +0200 -Subject: [PATCH] onscreen/native: Use EGLSyncs instead of - cogl_framebuffer_finish - -cogl_framebuffer_finish can result in a CPU-side stall because it waits for -the primary GPU to flush and execute all commands that were queued before -that. By using a GPU-side EGLSync we can let the primary GPU inform us when -it is done with the queued commands instead. We then create another EGLSync -on the secondary GPU using the same fd so the primary GPU effectively -signals the secondary GPU when it is done rendering, causing the latter -to wait for the former before copying part of the frames it needs for -monitors attached to it directly. - -This solves the corruption that cogl_framebuffer_finish also solved, but -without needing a CPU-side stall. ---- - src/backends/meta-egl.c | 94 +++++++++++++++++++ - src/backends/meta-egl.h | 23 +++++ - src/backends/native/meta-onscreen-native.c | 100 ++++++++++++++++++--- - 3 files changed, 206 insertions(+), 11 deletions(-) - -diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c -index cc023f705c4..9e9fada375a 100644 ---- a/src/backends/meta-egl.c -+++ b/src/backends/meta-egl.c -@@ -44,6 +44,11 @@ struct _MetaEgl - PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR; - PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR; - -+ PFNEGLCREATESYNCPROC eglCreateSync; -+ PFNEGLDESTROYSYNCPROC eglDestroySync; -+ PFNEGLWAITSYNCPROC eglWaitSync; -+ PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID; -+ - PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL; - PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL; - -@@ -1162,6 +1167,90 @@ meta_egl_query_display_attrib (MetaEgl *egl, - return TRUE; - } - -+gboolean -+meta_egl_create_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLenum type, -+ const EGLAttrib *attrib_list, -+ EGLSync *egl_sync, -+ GError **error) -+{ -+ if (!is_egl_proc_valid (egl->eglCreateSync, error)) -+ return FALSE; -+ -+ EGLSync sync; -+ -+ sync = egl->eglCreateSync(display, type, attrib_list); -+ -+ if (sync == EGL_NO_SYNC) -+ { -+ set_egl_error (error); -+ return FALSE; -+ } -+ -+ *egl_sync = sync; -+ -+ return TRUE; -+} -+ -+gboolean -+meta_egl_destroy_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ GError **error) -+{ -+ if (!is_egl_proc_valid (egl->eglDestroySync, error)) -+ return FALSE; -+ -+ if (!egl->eglDestroySync (display, sync)) -+ { -+ set_egl_error (error); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+gboolean -+meta_egl_wait_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ EGLint flags, -+ GError **error) -+{ -+ if (!is_egl_proc_valid (egl->eglWaitSync, error)) -+ return FALSE; -+ -+ if (!egl->eglWaitSync (display, sync, flags)) -+ { -+ set_egl_error (error); -+ return FALSE; -+ } -+ -+ return TRUE; -+} -+ -+EGLint -+meta_egl_duplicate_native_fence_fd (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ GError **error) -+{ -+ if (!is_egl_proc_valid (egl->eglDupNativeFenceFDANDROID, error)) -+ return EGL_NO_NATIVE_FENCE_FD_ANDROID; -+ -+ EGLint fd = EGL_NO_NATIVE_FENCE_FD_ANDROID; -+ -+ fd = egl->eglDupNativeFenceFDANDROID (display, sync); -+ -+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) -+ { -+ set_egl_error (error); -+ } -+ -+ return fd; -+} -+ - #define GET_EGL_PROC_ADDR(proc) \ - egl->proc = (void *) eglGetProcAddress (#proc); - -@@ -1175,6 +1264,11 @@ meta_egl_constructed (GObject *object) - GET_EGL_PROC_ADDR (eglCreateImageKHR); - GET_EGL_PROC_ADDR (eglDestroyImageKHR); - -+ GET_EGL_PROC_ADDR (eglCreateSync); -+ GET_EGL_PROC_ADDR (eglDestroySync); -+ GET_EGL_PROC_ADDR (eglWaitSync); -+ GET_EGL_PROC_ADDR (eglDupNativeFenceFDANDROID); -+ - GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL); - GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL); - -diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h -index 8b955c90c38..55775c7a421 100644 ---- a/src/backends/meta-egl.h -+++ b/src/backends/meta-egl.h -@@ -276,3 +276,26 @@ gboolean meta_egl_query_display_attrib (MetaEgl *egl, - EGLint attribute, - EGLAttrib *value, - GError **error); -+ -+gboolean meta_egl_create_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLenum type, -+ const EGLAttrib *attrib_list, -+ EGLSync *egl_sync, -+ GError **error); -+ -+gboolean meta_egl_destroy_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ GError **error); -+ -+gboolean meta_egl_wait_sync (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ EGLint flags, -+ GError **error); -+ -+EGLint meta_egl_duplicate_native_fence_fd (MetaEgl *egl, -+ EGLDisplay display, -+ EGLSync sync, -+ GError **error); -\ No newline at end of file -diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c -index 1a31f04a164..4f80b394f65 100644 ---- a/src/backends/native/meta-onscreen-native.c -+++ b/src/backends/native/meta-onscreen-native.c -@@ -29,6 +29,7 @@ - - #include "backends/native/meta-onscreen-native.h" - -+#include - #include - - #include "backends/meta-egl-ext.h" -@@ -828,20 +829,53 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); - MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native); -+ CoglContext *cogl_context = cogl_framebuffer_get_context (COGL_FRAMEBUFFER (onscreen)); -+ CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys; - MetaRenderDevice *render_device; - EGLDisplay egl_display; -- GError *error = NULL; -+ g_autoptr (GError) error = NULL; - gboolean use_modifiers; - MetaDeviceFile *device_file; - MetaDrmBufferFlags flags; - MetaDrmBufferGbm *buffer_gbm; - struct gbm_bo *bo; -+ EGLSync primary_gpu_egl_sync = EGL_NO_SYNC; -+ EGLSync secondary_gpu_egl_sync = EGL_NO_SYNC; -+ g_autofd int primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID; - - COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, - "copy_shared_framebuffer_gpu()"); -- -+ - if (renderer_gpu_data->secondary.needs_explicit_sync) -- cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen)); -+ { -+ if (!meta_egl_create_sync (egl, -+ cogl_renderer_egl->edpy, -+ EGL_SYNC_NATIVE_FENCE_ANDROID, -+ NULL, -+ &primary_gpu_egl_sync, -+ &error)) -+ { -+ g_warning ("Failed to create EGLSync on primary GPU: %s", error->message); -+ return NULL; -+ } -+ -+ // According to the EGL_KHR_fence_sync specification we must ensure -+ // the fence command is flushed in this context to be able to await it -+ // in another (secondary GPU context) or we risk waiting indefinitely. -+ cogl_framebuffer_flush (COGL_FRAMEBUFFER (onscreen)); -+ -+ primary_gpu_sync_fence = -+ meta_egl_duplicate_native_fence_fd (egl, -+ cogl_renderer_egl->edpy, -+ primary_gpu_egl_sync, -+ &error); -+ -+ if (primary_gpu_sync_fence == EGL_NO_NATIVE_FENCE_FD_ANDROID) -+ { -+ g_warning ("Failed to duplicate EGLSync FD on primary GPU: %s", error->message); -+ goto out; -+ } -+ } - - render_device = renderer_gpu_data->render_device; - egl_display = meta_render_device_get_egl_display (render_device); -@@ -854,13 +888,45 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - &error)) - { - g_warning ("Failed to make current: %s", error->message); -- g_error_free (error); -- return NULL; -+ goto out; - } - - *egl_context_changed = TRUE; - -+ if (primary_gpu_sync_fence != EGL_NO_NATIVE_FENCE_FD_ANDROID) -+ { -+ EGLAttrib attribs[3]; -+ -+ attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; -+ attribs[1] = primary_gpu_sync_fence; -+ attribs[2] = EGL_NONE; -+ -+ if (!meta_egl_create_sync (egl, -+ egl_display, -+ EGL_SYNC_NATIVE_FENCE_ANDROID, -+ attribs, -+ &secondary_gpu_egl_sync, -+ &error)) -+ { -+ g_warning ("Failed to create EGLSync on secondary GPU: %s", error->message); -+ goto out; -+ } -+ -+ // eglCreateSync takes ownership of an existing fd that is passed, so -+ // don't try to clean it up twice. -+ primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID; - -+ if (!meta_egl_wait_sync (egl, -+ egl_display, -+ secondary_gpu_egl_sync, -+ 0, -+ &error)) -+ { -+ g_warning ("Failed to wait for EGLSync on secondary GPU: %s", error->message); -+ goto out; -+ } -+ } -+ - buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb); - bo = meta_drm_buffer_gbm_get_bo (buffer_gbm); - if (!meta_renderer_native_gles3_blit_shared_bo (egl, -@@ -872,8 +938,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - &error)) - { - g_warning ("Failed to blit shared framebuffer: %s", error->message); -- g_error_free (error); -- return NULL; -+ goto out; - } - - if (!meta_egl_swap_buffers (egl, -@@ -882,8 +947,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - &error)) - { - g_warning ("Failed to swap buffers: %s", error->message); -- g_error_free (error); -- return NULL; -+ goto out; - } - - use_modifiers = meta_renderer_native_use_modifiers (renderer_native); -@@ -902,8 +966,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - { - g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s", - error->message); -- g_error_free (error); -- return NULL; -+ goto out; - } - - g_object_set_qdata_full (G_OBJECT (buffer_gbm), -@@ -911,6 +974,21 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, - g_object_ref (primary_gpu_fb), - g_object_unref); - -+out: -+ if (primary_gpu_egl_sync != EGL_NO_SYNC && -+ !meta_egl_destroy_sync (egl, -+ cogl_renderer_egl->edpy, -+ primary_gpu_egl_sync, -+ &error)) -+ g_warning ("Failed to destroy primary GPU EGLSync: %s", error->message); -+ -+ if (secondary_gpu_egl_sync != EGL_NO_SYNC && -+ !meta_egl_destroy_sync (egl, -+ egl_display, -+ secondary_gpu_egl_sync, -+ &error)) -+ g_warning ("Failed to destroy secondary GPU EGLSync: %s", error->message); -+ - return META_DRM_BUFFER (buffer_gbm); - } - --- -GitLab