diff --git a/README.md b/README.md index fa39646c98..b4d43d71da 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,6 @@ -# Mutter +# Magpie -Mutter is a Wayland display server and X11 window manager and compositor library. - -When used as a Wayland display server, it runs on top of KMS and libinput. It -implements the compositor side of the Wayland core protocol as well as various -protocol extensions. It also has functionality related to running X11 -applications using Xwayland. - -When used on top of Xorg it acts as a X11 window manager and compositing manager. +Magpie is a X11 window manager and compositor library. It contains functionality related to, among other things, window management, window compositing, focus tracking, workspace management, keybindings and @@ -17,14 +10,25 @@ Internally it uses a fork of Cogl, a hardware acceleration abstraction library used to simplify usage of OpenGL pipelines, as well as a fork of Clutter, a scene graph and user interface toolkit. -Mutter is used by, for example, GNOME Shell, the GNOME core user interface, and -by Gala, elementary OS's window manager. It can also be run standalone, using -the command "mutter", but just running plain mutter is only intended for +Magpie is a soft-fork of GNOME's mutter at version 43 tailored to the requirements of the Budgie Desktop 10 series (from v10.8 and later). Magpie allows mutter based desktops such as GNOME Shell to co-exist since the key-components such as libmagpie are separated by both name and file-system install location. Magpie shares some Mutter shared files; therefore these need to be delivered/installed as part of the distribution from its mutter package. Alternatively these files can be delivered using the meson option "with_shared_components" where budgie-desktop is not required to co-exist with any mutter based desktops. + +/lib/udev/rules.d/61-mutter.rules +/usr/share/GConf/gsettings/mutter-schemas.convert +/usr/share/glib-2.0/schemas/org.gnome.mutter.gschema.xml +/usr/share/glib-2.0/schemas/org.gnome.mutter.wayland.gschema.xml +/usr/share/glib-2.0/schemas/org.gnome.mutter.x11.gschema.xml +/usr/share/gnome-control-center/keybindings/50-mutter-navigation.xml +/usr/share/gnome-control-center/keybindings/50-mutter-system.xml +/usr/share/gnome-control-center/keybindings/50-mutter-wayland.xml +/usr/share/gnome-control-center/keybindings/50-mutter-windows.xml + +Magpie is used by the Budgie Desktop as its window manager. It can also be run standalone, using +the command "magpie", but just running plain magpie is only intended for debugging purposes. ## Contributing -To contribute, open merge requests at https://gitlab.gnome.org/GNOME/mutter. +To contribute, open merge requests at https://github.com/buddiesofbudgie/magpie It can be useful to look at the documentation available at the [Wiki](https://gitlab.gnome.org/GNOME/mutter/-/wikis/home). @@ -51,21 +55,13 @@ message body than too little. ## Default branch -The default development branch is `main`. If you still have a local -checkout under the old name, use: -```sh -git checkout master -git branch -m master main -git fetch -git branch --unset-upstream -git branch -u origin/main -git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main +The default development branch is `main`. ``` ## License -Mutter is distributed under the terms of the GNU General Public License, +Magpie is distributed under the terms of the GNU General Public License, version 2 or later. See the [COPYING][license] file for detalis. -[bug-tracker]: https://gitlab.gnome.org/GNOME/mutter/issues +[bug-tracker]: https://github.com/buddiesofbudgie/magpie/issues [license]: COPYING diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c index 34d676f549..f89db2582c 100644 --- a/clutter/clutter/clutter-frame-clock.c +++ b/clutter/clutter/clutter-frame-clock.c @@ -45,6 +45,8 @@ typedef struct _EstimateQueue int next_index; } EstimateQueue; +static gboolean triple_buffering_disabled = FALSE; + #define SYNC_DELAY_FALLBACK_FRACTION 0.875 typedef struct _ClutterFrameListener @@ -65,8 +67,9 @@ typedef enum _ClutterFrameClockState CLUTTER_FRAME_CLOCK_STATE_INIT, CLUTTER_FRAME_CLOCK_STATE_IDLE, CLUTTER_FRAME_CLOCK_STATE_SCHEDULED, - CLUTTER_FRAME_CLOCK_STATE_DISPATCHING, - CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED, + CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE, + CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED, + CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO, } ClutterFrameClockState; struct _ClutterFrameClock @@ -96,6 +99,8 @@ struct _ClutterFrameClock /* Last KMS buffer submission time. */ int64_t last_flip_time_us; + ClutterFrameHint last_flip_hints; + /* Last few durations between dispatch start and buffer swap. */ EstimateQueue dispatch_to_swap_us; /* Last few durations between buffer swap and GPU rendering finish. */ @@ -228,6 +233,12 @@ void clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, ClutterFrameInfo *frame_info) { +#ifdef CLUTTER_ENABLE_DEBUG + const char *debug_state = + frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO ? + "Triple buffering" : "Double buffering"; +#endif + COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented, "Frame Clock (presented)"); @@ -290,7 +301,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, frame_info->cpu_time_before_buffer_swap_us; CLUTTER_NOTE (FRAME_TIMINGS, - "dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", + "%s: dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs", + debug_state, dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us); @@ -304,6 +316,10 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, frame_clock->got_measurements_last_frame = TRUE; } + else + { + CLUTTER_NOTE (FRAME_TIMINGS, "%s", debug_state); + } if (frame_info->refresh_rate > 1.0) { @@ -318,11 +334,18 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock, case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: g_warn_if_reached (); break; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; maybe_reschedule_update (frame_clock); break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + maybe_reschedule_update (frame_clock); + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + maybe_reschedule_update (frame_clock); + break; } } @@ -338,11 +361,18 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock) case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: g_warn_if_reached (); break; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; maybe_reschedule_update (frame_clock); break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + maybe_reschedule_update (frame_clock); + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + maybe_reschedule_update (frame_clock); + break; } } @@ -354,6 +384,7 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) int64_t max_swap_to_rendering_done_us = 0; int64_t max_swap_to_flip_us = 0; int64_t max_render_time_us; + int buffer_queue_latency_frames = 0; int i; refresh_interval_us = frame_clock->refresh_interval_us; @@ -361,7 +392,15 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) if (!frame_clock->got_measurements_last_frame || G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME)) - return refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; + { + int64_t ret = refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION; + + if (!triple_buffering_disabled && + frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE) + ret += refresh_interval_us; + + return ret; + } for (i = 0; i < ESTIMATE_QUEUE_LENGTH; ++i) { @@ -376,6 +415,27 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) frame_clock->swap_to_flip_us.values[i]); } + switch (frame_clock->state) + { + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + buffer_queue_latency_frames = 0; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + buffer_queue_latency_frames = 1; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + g_warn_if_reached (); + buffer_queue_latency_frames = 2; + break; + } + + max_swap_to_flip_us -= refresh_interval_us * buffer_queue_latency_frames; + if (max_swap_to_flip_us < 0) + max_swap_to_flip_us = 0; + /* Max render time shows how early the frame clock needs to be dispatched * to make it to the predicted next presentation time. It is composed of: * - An estimate of duration from dispatch start to buffer swap. @@ -392,8 +452,6 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock) frame_clock->vblank_duration_us + clutter_max_render_time_constant_us; - max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us); - return max_render_time_us; } @@ -407,7 +465,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, int64_t refresh_interval_us; int64_t min_render_time_allowed_us; int64_t max_render_time_allowed_us; - int64_t next_presentation_time_us; + int64_t next_presentation_time_us = 0; int64_t next_update_time_us; now_us = g_get_monotonic_time (); @@ -451,7 +509,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock, * */ last_presentation_time_us = frame_clock->last_presentation_time_us; - next_presentation_time_us = last_presentation_time_us + refresh_interval_us; + switch (frame_clock->state) + { + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + next_presentation_time_us = last_presentation_time_us + + refresh_interval_us; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + next_presentation_time_us = last_presentation_time_us + + 2 * refresh_interval_us; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + next_presentation_time_us = last_presentation_time_us + + 3 * refresh_interval_us; + break; + } /* * However, the last presentation could have happened more than a frame ago. @@ -562,8 +637,12 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock) frame_clock->pending_reschedule = TRUE; frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; break; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + frame_clock->pending_reschedule = TRUE; + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: break; } @@ -599,11 +678,17 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) case CLUTTER_FRAME_CLOCK_STATE_INIT: case CLUTTER_FRAME_CLOCK_STATE_IDLE: next_update_time_us = g_get_monotonic_time (); + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; break; case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: return; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + next_update_time_us = g_get_monotonic_time (); + frame_clock->state = + CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: frame_clock->pending_reschedule = TRUE; frame_clock->pending_reschedule_now = TRUE; return; @@ -612,7 +697,6 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock) g_warn_if_fail (next_update_time_us != -1); g_source_set_ready_time (frame_clock->source, next_update_time_us); - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; frame_clock->is_next_presentation_time_valid = FALSE; } @@ -631,6 +715,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) { case CLUTTER_FRAME_CLOCK_STATE_INIT: next_update_time_us = g_get_monotonic_time (); + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; break; case CLUTTER_FRAME_CLOCK_STATE_IDLE: calculate_next_update_time_us (frame_clock, @@ -638,11 +723,28 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) &frame_clock->next_presentation_time_us); frame_clock->is_next_presentation_time_valid = (frame_clock->next_presentation_time_us != 0); + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; break; case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: return; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + if (frame_clock->last_flip_hints & CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED || + triple_buffering_disabled) + { + /* Force double buffering, disable triple buffering */ + frame_clock->pending_reschedule = TRUE; + return; + } + + calculate_next_update_time_us (frame_clock, + &next_update_time_us, + &frame_clock->next_presentation_time_us); + frame_clock->is_next_presentation_time_valid = + (frame_clock->next_presentation_time_us != 0); + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: frame_clock->pending_reschedule = TRUE; return; } @@ -650,7 +752,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock) g_warn_if_fail (next_update_time_us != -1); g_source_set_ready_time (frame_clock->source, next_update_time_us); - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; } static void @@ -676,7 +777,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, frame_clock->refresh_interval_us; lateness_us = time_us - ideal_dispatch_time_us; - if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us) + if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us / 4) frame_clock->last_dispatch_lateness_us = 0; else frame_clock->last_dispatch_lateness_us = lateness_us; @@ -684,7 +785,21 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, frame_clock->last_dispatch_time_us = time_us; g_source_set_ready_time (frame_clock->source, -1); - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING; + switch (frame_clock->state) + { + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + g_warn_if_reached (); + return; + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO; + break; + } frame_count = frame_clock->frame_count++; @@ -709,25 +824,31 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock, frame_clock->listener.user_data); COGL_TRACE_END (ClutterFrameClockFrame); - switch (frame_clock->state) + switch (result) { - case CLUTTER_FRAME_CLOCK_STATE_INIT: - case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED: - g_warn_if_reached (); - break; - case CLUTTER_FRAME_CLOCK_STATE_IDLE: - case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: break; - case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING: - switch (result) + case CLUTTER_FRAME_RESULT_IDLE: + /* The frame was aborted; nothing to paint/present */ + switch (frame_clock->state) { - case CLUTTER_FRAME_RESULT_PENDING_PRESENTED: - frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED; + case CLUTTER_FRAME_CLOCK_STATE_INIT: + case CLUTTER_FRAME_CLOCK_STATE_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED: + g_warn_if_reached (); break; - case CLUTTER_FRAME_RESULT_IDLE: + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE: frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE; maybe_reschedule_update (frame_clock); break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED; + maybe_reschedule_update (frame_clock); + break; + case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO: + frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE; + maybe_reschedule_update (frame_clock); + break; } break; } @@ -760,10 +881,12 @@ frame_clock_source_dispatch (GSource *source, } void -clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, - int64_t flip_time_us) +clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, + int64_t flip_time_us, + ClutterFrameHint hints) { frame_clock->last_flip_time_us = flip_time_us; + frame_clock->last_flip_hints = hints; } GString * @@ -894,6 +1017,9 @@ clutter_frame_clock_class_init (ClutterFrameClockClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + if (!g_strcmp0 (g_getenv ("MUTTER_DEBUG_DISABLE_TRIPLE_BUFFERING"), "1")) + triple_buffering_disabled = TRUE; + object_class->dispose = clutter_frame_clock_dispose; signals[DESTROY] = diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h index 91e6b3a130..d750404d53 100644 --- a/clutter/clutter/clutter-frame-clock.h +++ b/clutter/clutter/clutter-frame-clock.h @@ -34,6 +34,12 @@ typedef enum _ClutterFrameResult CLUTTER_FRAME_RESULT_IDLE, } ClutterFrameResult; +typedef enum _ClutterFrameHint +{ + CLUTTER_FRAME_HINT_NONE = 0, + CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED = 1 << 0, +} ClutterFrameHint; + #define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ()) CLUTTER_EXPORT G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock, @@ -90,8 +96,9 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock, CLUTTER_EXPORT float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock); -void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock, - int64_t flip_time_us); +void clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock, + int64_t flip_time_us, + ClutterFrameHint hints); GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock); diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h index e0088564fc..06581492f5 100644 --- a/clutter/clutter/clutter-frame-private.h +++ b/clutter/clutter/clutter-frame-private.h @@ -24,6 +24,7 @@ struct _ClutterFrame { gboolean has_result; ClutterFrameResult result; + ClutterFrameHint hints; }; #define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 }) diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c index 3c708da9dc..63ae302af7 100644 --- a/clutter/clutter/clutter-frame.c +++ b/clutter/clutter/clutter-frame.c @@ -40,3 +40,16 @@ clutter_frame_set_result (ClutterFrame *frame, frame->result = result; frame->has_result = TRUE; } + +void +clutter_frame_set_hint (ClutterFrame *frame, + ClutterFrameHint hint) +{ + frame->hints |= hint; +} + +ClutterFrameHint +clutter_frame_get_hints (ClutterFrame *frame) +{ + return frame->hints; +} diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h index d3608e81ca..06c5f7f28a 100644 --- a/clutter/clutter/clutter-frame.h +++ b/clutter/clutter/clutter-frame.h @@ -33,4 +33,11 @@ void clutter_frame_set_result (ClutterFrame *frame, CLUTTER_EXPORT gboolean clutter_frame_has_result (ClutterFrame *frame); +CLUTTER_EXPORT +void clutter_frame_set_hint (ClutterFrame *frame, + ClutterFrameHint hint); + +CLUTTER_EXPORT +ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame); + #endif /* CLUTTER_FRAME_H */ diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 14f21024c0..914b91a181 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -1252,8 +1252,9 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock, _clutter_stage_window_redraw_view (stage_window, view, &frame); - clutter_frame_clock_record_flip_time (frame_clock, - g_get_monotonic_time ()); + clutter_frame_clock_record_flip (frame_clock, + g_get_monotonic_time (), + clutter_frame_get_hints (&frame)); clutter_stage_emit_after_paint (stage, view); diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build index b4ee4b7827..8dfa2b73a3 100644 --- a/clutter/clutter/meson.build +++ b/clutter/clutter/meson.build @@ -299,7 +299,7 @@ clutter_marshal = gnome.genmarshal('clutter-marshal', clutter_built_sources += clutter_marshal[0] clutter_built_headers += clutter_marshal[1] -libmutter_clutter_name = 'mutter-clutter-' + libmutter_api_version +libmutter_clutter_name = 'magpie-clutter-' + libmutter_api_version libmutter_clutter = shared_library(libmutter_clutter_name, sources: [ clutter_sources, @@ -398,9 +398,9 @@ install_headers(clutter_deprecated_headers, subdir: join_paths(clutter_clutter_includesubdir, 'deprecated')) pkg.generate(libmutter_clutter, - name: 'Mutters Clutter', + name: 'Magpie Clutter', filebase: libmutter_clutter_name, - description: 'Mutters Clutter Private Library', + description: 'Magpie Clutter Private Library', libraries: [m_dep], subdirs: join_paths(pkgname, 'clutter'), requires: [clutter_pkg_deps, libmutter_cogl_name], diff --git a/cogl/cogl-pango/meson.build b/cogl/cogl-pango/meson.build index ba8fe70bad..ffb2f2130f 100644 --- a/cogl/cogl-pango/meson.build +++ b/cogl/cogl-pango/meson.build @@ -20,7 +20,7 @@ cogl_pango_deps = [ libmutter_cogl_dep, ] -libmutter_cogl_pango = shared_library('mutter-cogl-pango-' + libmutter_api_version, +libmutter_cogl_pango = shared_library('magpie-cogl-pango-' + libmutter_api_version, sources: [cogl_pango_sources, cogl_pango_public_headers], version: '0.0.0', soversion: 0, @@ -69,7 +69,7 @@ install_headers(cogl_pango_public_headers, subdir: cogl_pango_includesubdir) pkg.generate(libmutter_cogl_pango, name: 'CoglPango', - filebase: 'mutter-cogl-pango-' + libmutter_api_version, + filebase: 'magpie-cogl-pango-' + libmutter_api_version, description: 'A text rendering for Cogl in mutter', subdirs: join_paths(pkgname, 'cogl'), requires: [cogl_pkg_deps, libmutter_cogl_name], diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h index dffe018d2e..e0215f750d 100644 --- a/cogl/cogl/cogl-onscreen-private.h +++ b/cogl/cogl/cogl-onscreen-private.h @@ -97,4 +97,7 @@ cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen); COGL_EXPORT CoglFrameInfo * cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen); +COGL_EXPORT unsigned int +cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen); + #endif /* __COGL_ONSCREEN_PRIVATE_H */ diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c index 842ececf7f..1e2b11dee6 100644 --- a/cogl/cogl/cogl-onscreen.c +++ b/cogl/cogl/cogl-onscreen.c @@ -508,6 +508,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen) return g_queue_pop_head (&priv->pending_frame_infos); } +unsigned int +cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen) +{ + CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen); + + return g_queue_get_length (&priv->pending_frame_infos); +} + CoglFrameClosure * cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen, CoglFrameCallback callback, diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build index ea23046798..453485b8ba 100644 --- a/cogl/cogl/meson.build +++ b/cogl/cogl/meson.build @@ -426,7 +426,7 @@ cogl_headers_all = [ cogl_deprecated_headers, ] -libmutter_cogl_name = 'mutter-cogl-' + libmutter_api_version +libmutter_cogl_name = 'magpie-cogl-' + libmutter_api_version libmutter_cogl = shared_library(libmutter_cogl_name, sources: [cogl_sources, cogl_headers_all], version: '0.0.0', @@ -483,7 +483,7 @@ install_headers(cogl_gl_prototype_headers, pkg.generate(libmutter_cogl, name: 'Cogl', filebase: libmutter_cogl_name, - description: 'An object oriented GL/GLES Abstraction/Utility Layer in mutter', + description: 'An object oriented GL/GLES Abstraction/Utility Layer in magpie', libraries: [m_dep], subdirs: join_paths(pkgname, 'cogl'), requires: [cogl_pkg_deps], diff --git a/data/61-magpie.rules b/data/61-magpie.rules new file mode 100644 index 0000000000..d3c32899ea --- /dev/null +++ b/data/61-magpie.rules @@ -0,0 +1,117 @@ +DRIVERS=="amdgpu", SUBSYSTEM=="drm", TAG+="magpie-device-disable-client-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1602", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1606", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x160a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x160b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x160d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x160e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1612", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1616", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x161a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x161b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x161d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x161e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1622", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1626", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x162a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x162b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x162d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x162e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1902", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1906", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x190a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x190b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x190e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1912", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1913", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1915", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1916", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1917", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x191a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x191b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x191d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x191e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1921", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1923", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1926", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1927", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x192a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x192b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x192d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1932", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x193a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x193b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x193d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x0a84", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1a84", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x1a85", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5a84", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5a85", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3184", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3185", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5902", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5906", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x590a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5908", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x590b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x590e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5913", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5915", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5917", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5912", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5916", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x591a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x591b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x591d", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x591e", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5921", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5923", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5926", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x5927", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x593b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x591c", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x87c0", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x87ca", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e90", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e93", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e99", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e9c", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e91", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e92", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e96", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e98", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e9a", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e9b", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3e94", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea9", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea5", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea6", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea7", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea8", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea1", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea4", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea0", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea3", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x3ea2", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9b21", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9ba0", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9ba2", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9ba4", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9ba5", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9ba8", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9baa", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bab", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bac", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9b41", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc0", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc2", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc4", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc5", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc6", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bc8", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bca", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bcb", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bcc", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9be6", TAG+="mutter-device-disable-kms-modifiers" +DRIVERS=="i915", SUBSYSTEM=="drm",ATTRS{vendor}=="0x8086", ATTRS{device}=="0x9bf6", TAG+="mutter-device-disable-kms-modifiers" +ENV{ID_PATH}=="platform-vkms", TAG+="magpie-device-ignore" diff --git a/data/magpie-schemas.convert b/data/magpie-schemas.convert new file mode 100644 index 0000000000..9513f41bdc --- /dev/null +++ b/data/magpie-schemas.convert @@ -0,0 +1,5 @@ +[org.buddiesofbudgie.magpie] +overlay-key = /apps/magpie/general/overlay_key +attach-modal-dialogs = /apps/magpie/general/attach_modal_dialogs +workspaces-only-on-primary = /apps/magpie/general/workspaces_only_on_primary +draggable-border-width = /apps/magpie/general/draggable_border_width diff --git a/data/magpie.desktop.in b/data/magpie.desktop.in new file mode 100644 index 0000000000..06daf9bb98 --- /dev/null +++ b/data/magpie.desktop.in @@ -0,0 +1,14 @@ +[Desktop Entry] +Type=Application +Name=Magpie` +Exec=magpie +NoDisplay=true +# name of loadable control center module +X-GNOME-WMSettingsModule=metacity +# name we put on the WM spec check window +X-GNOME-WMName=Magpie +# back compat only +X-GnomeWMSettingsLibrary=metacity +XX-GNOME-Autostart-Phase=WindowManager +X-GNOME-Provides=windowmanager +X-GNOME-Autostart-Notify=true diff --git a/data/meson.build b/data/meson.build index ae98321998..3b473c12e8 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,8 +1,8 @@ msgfmt = find_program('msgfmt') -custom_target('mutter.desktop', - input: 'mutter.desktop.in', - output: 'mutter.desktop', +custom_target('magpie.desktop', + input: 'magpie.desktop.in', + output: 'magpie.desktop', command: [ msgfmt, '--desktop', '--template', @@ -29,11 +29,13 @@ if have_wayland ] endif -install_data(keybinding_xml_files, - install_dir: gnome_keybindings_keysdir, -) +if have_shared_components + install_data(keybinding_xml_files, + install_dir: gnome_keybindings_keysdir, + ) +endif -xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules') +#xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules') gschema_config = configuration_data() gschema_config.set('GETTEXT_DOMAIN', meson.project_name()) @@ -41,28 +43,30 @@ gschema_config.set('XWAYLAND_GRAB_DEFAULT_ACCESS_RULES', xwayland_grab_default_access_rules) schemadir = join_paths(datadir, 'glib-2.0', 'schemas') -configure_file( - input: 'org.gnome.mutter.gschema.xml.in', - output: 'org.gnome.mutter.gschema.xml', - configuration: gschema_config, - install_dir: schemadir -) - -configure_file( - input: 'org.gnome.mutter.wayland.gschema.xml.in', - output: 'org.gnome.mutter.wayland.gschema.xml', - configuration: gschema_config, - install_dir: schemadir -) +if have_shared_components + configure_file( + input: 'org.gnome.mutter.gschema.xml.in', + output: 'org.gnome.mutter.gschema.xml', + configuration: gschema_config, + install_dir: schemadir + ) -install_data(['mutter-schemas.convert'], - install_dir: join_paths(datadir, 'GConf/gsettings'), -) + configure_file( + input: 'org.gnome.mutter.wayland.gschema.xml.in', + output: 'org.gnome.mutter.wayland.gschema.xml', + configuration: gschema_config, + install_dir: schemadir + ) -if have_libgudev - install_data(['61-mutter.rules'], - install_dir: join_paths(udev_dir, 'rules.d'), + install_data(['mutter-schemas.convert'], + install_dir: join_paths(datadir, 'GConf/gsettings'), ) + + if have_libgudev + install_data(['61-magpie.rules'], + install_dir: join_paths(udev_dir, 'rules.d'), + ) + endif endif subdir('dbus-interfaces') diff --git a/doc/man/mutter.1 b/doc/man/magpie.1 similarity index 100% rename from doc/man/mutter.1 rename to doc/man/magpie.1 diff --git a/doc/man/meson.build b/doc/man/meson.build index dd543269da..ce69a0693f 100644 --- a/doc/man/meson.build +++ b/doc/man/meson.build @@ -1 +1 @@ -install_man('mutter.1') +install_man('magpie.1') diff --git a/meson.build b/meson.build index d37eddd836..38b2edb905 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ -project('mutter', 'c', - version: '43.5', +project('magpie', 'c', + version: '0.9', meson_version: '>= 0.55.0', license: 'GPLv2+' ) @@ -7,7 +7,7 @@ project('mutter', 'c', split_version = meson.project_version().split('.') # API version, bump each development cycle -libmutter_api_version = '11' +libmutter_api_version = '1' mutter_srcdir = meson.current_source_dir() mutter_builddir = meson.current_build_dir() @@ -42,8 +42,8 @@ udev_req = '>= 228' gudev_req = '>= 232' # wayland version requirements -wayland_server_req = '>= 1.21' -wayland_protocols_req = '>= 1.26' +#wayland_server_req = '>= 1.21' +#wayland_protocols_req = '>= 1.26' # native backend version requirements libinput_req = '>= 1.19.0' @@ -95,7 +95,7 @@ pcdir = join_paths(libdir, 'pkgconfig') gettext_package = meson.project_name() localedir = join_paths(datadir, 'locale') -libmutter_name = 'mutter-' + libmutter_api_version +libmutter_name = 'magpie-' + libmutter_api_version mutter_installed_tests_datadir = join_paths( datadir, 'installed-tests', libmutter_name) @@ -128,7 +128,8 @@ dbus_dep = dependency('dbus-1') colord_dep = dependency('colord', version: colord_req) lcms2_dep = dependency('lcms2', version: lcms2_req) -have_wayland = get_option('wayland') +#have_wayland = get_option('wayland') +have_wayland = false # For now always require X11 support have_x11 = true have_xwayland = have_wayland # for now default to have_wayland @@ -259,7 +260,8 @@ endif have_egl_device = get_option('egl_device') -have_wayland_eglstream = get_option('wayland_eglstream') +#have_wayland_eglstream = get_option('wayland_eglstream') +have_wayland_eglstream = false if have_wayland_eglstream wayland_eglstream_protocols_dep = dependency('wayland-eglstream-protocols') dl_dep = cc.find_library('dl', required: true) @@ -311,7 +313,8 @@ if have_documentation fallback: ['gi-docgen', 'dummy_dep']) endif -have_tests = get_option('tests') +#have_tests = get_option('tests') +have_tests = false have_core_tests = false have_cogl_tests = false have_clutter_tests = false @@ -613,7 +616,8 @@ foreach function : optional_functions endif endforeach -xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules') +#xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules') +xwayland_grab_default_access_rules = '' cdata.set_quoted('XWAYLAND_GRAB_DEFAULT_ACCESS_RULES', xwayland_grab_default_access_rules) @@ -632,10 +636,12 @@ top_includepath = include_directories('.') subdir('cogl') subdir('clutter') +have_shared_components=get_option('with_shared_components') subdir('data') subdir('tools') subdir('src') subdir('po') + subdir('doc/man') if have_documentation subdir('doc/reference') @@ -656,10 +662,10 @@ summary('GLES2', have_gles2, section: 'Rendering APIs') summary('EGL', have_egl, section: 'Rendering APIs') summary('GLX', have_glx, section: 'Rendering APIs') -summary('Wayland', have_wayland, section: 'Options') -summary('Wayland EGLStream', have_wayland_eglstream, section: 'Options') +#summary('Wayland', have_wayland, section: 'Options') +#summary('Wayland EGLStream', have_wayland_eglstream, section: 'Options') summary('X11', have_x11, section: 'Options') -summary('XWayland', have_xwayland, section: 'Options') +#summary('XWayland', have_xwayland, section: 'Options') summary('Native Backend', have_native_backend, section: 'Options') summary('EGL Device', have_egl_device, section: 'Options') summary('Remote desktop', have_remote_desktop, section: 'Options') @@ -672,15 +678,15 @@ summary('Startup notification', have_startup_notification, section: 'Options') summary('Introspection', have_introspection, section: 'Options') summary('Documentation', have_documentation, section: 'Options') summary('Profiler', have_profiler, section: 'Options') -summary('Xwayland initfd', have_xwayland_initfd, section: 'Options') -summary('Xwayland listenfd', have_xwayland_listenfd, section: 'Options') +#summary('Xwayland initfd', have_xwayland_initfd, section: 'Options') +#summary('Xwayland listenfd', have_xwayland_listenfd, section: 'Options') summary('Safe X11 I/O errors', have_xsetioerrorexithandler, section: 'Options') -summary('Xwayland terminate delay', have_xwayland_terminate_delay, section: 'Options') - -summary('Enabled', have_tests, section: 'Tests') -summary('Core tests', have_core_tests, section: 'Tests') -summary('Cogl tests', have_cogl_tests, section: 'Tests') -summary('Clutter tests', have_clutter_tests, section: 'Tests') -summary('KVM tests', get_option('kvm_tests'), section: 'Tests') -summary('Installed tests', have_installed_tests, section: 'Tests') -summary('Coverage', get_option('b_coverage'), section: 'Tests') +#summary('Xwayland terminate delay', have_xwayland_terminate_delay, section: 'Options') + +#summary('Enabled', have_tests, section: 'Tests') +#summary('Core tests', have_core_tests, section: 'Tests') +#summary('Cogl tests', have_cogl_tests, section: 'Tests') +#summary('Clutter tests', have_clutter_tests, section: 'Tests') +#summary('KVM tests', get_option('kvm_tests'), section: 'Tests') +#summary('Installed tests', have_installed_tests, section: 'Tests') +#summary('Coverage', get_option('b_coverage'), section: 'Tests') diff --git a/meson_options.txt b/meson_options.txt index cddcc1a474..a36be2d152 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -33,11 +33,11 @@ option('glx', description: 'Enable GLX support' ) -option('wayland', - type: 'boolean', - value: true, - description: 'Enable Wayland support' -) +#option('wayland', +# type: 'boolean', +# value: false, +# description: 'Enable Wayland support' +#) option('systemd', type: 'boolean', @@ -59,7 +59,7 @@ option('remote_desktop', option('libgnome_desktop', type: 'boolean', - value: true, + value: false, description: 'Build with or without gnome-desktop' ) @@ -69,11 +69,11 @@ option('egl_device', description: 'Enable EGLDevice and EGLStream renderer support' ) -option('wayland_eglstream', - type: 'boolean', - value: false, - description: 'Enable Wayland EGLStream support client support' -) +#option('wayland_eglstream', +# type: 'boolean', +# value: false, +# description: 'Enable Wayland EGLStream support client support' +#) option('udev', type: 'boolean', @@ -129,53 +129,53 @@ option('docs', description: 'Enable gi-docgen documentation' ) -option('cogl_tests', - type: 'boolean', - value: true, - description: 'Enable cogl tests' -) - -option('clutter_tests', - type: 'boolean', - value: true, - description: 'Enable clutter tests' -) - -option('core_tests', - type: 'boolean', - value: true, - description: 'Enable mutter core tests' -) - -option('native_tests', - type: 'boolean', - value: true, - description: 'Enable mutter native backend tests' -) - -option('tests', - type: 'boolean', - value: true, - description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests' -) - -option('kvm_tests', - type: 'boolean', - value: false, - description: 'Enable running certain tests in a virtual machine with a custom built kernel' -) - -option('kvm_kernel_image', - type: 'string', - value: '', - description: 'Path to a Linux kernel image to be used for KVM testing' -) - -option('tty_tests', - type: 'boolean', - value: false, - description: 'Enable tests that must be run on a TTY (KMS tests without KVM)' -) +#option('cogl_tests', +# type: 'boolean', +# value: false, +# description: 'Enable cogl tests' +#) + +#option('clutter_tests', +# type: 'boolean', +# value: false, +# description: 'Enable clutter tests' +#) + +#option('core_tests', +# type: 'boolean', +# value: false, +# description: 'Enable mutter core tests' +#) + +#option('native_tests', +# type: 'boolean', +# value: false, +# description: 'Enable mutter native backend tests' +#) + +#option('tests', +# type: 'boolean', +# value: false, +# description: 'Enable tests globally. Specific test suites can be controlled with core_tests, clutter_tests, and cogl_tests' +#) + +#option('kvm_tests', +# type: 'boolean', +# value: false, +# description: 'Enable running certain tests in a virtual machine with a custom built kernel' +#) + +#option('kvm_kernel_image', +# type: 'string', +# value: '', +# description: 'Path to a Linux kernel image to be used for KVM testing' +#) + +#option('tty_tests', +# type: 'boolean', +# value: false, +# description: 'Enable tests that must be run on a TTY (KMS tests without KVM)' +#) option('profiler', type: 'boolean', @@ -183,11 +183,11 @@ option('profiler', description: 'Enable Sysprof tracing' ) -option('installed_tests', - type: 'boolean', - value: true, - description: 'Enable mutter installed tests' -) +#option('installed_tests', +# type: 'boolean', +# value: false, +# description: 'Enable mutter installed tests' +#) option('verbose', type: 'boolean', @@ -195,26 +195,32 @@ option('verbose', description: 'Enable verbose logging ability' ) -option('xwayland_path', - type: 'string', - value: '', - description: 'Path to Xwayland executable' -) +#option('xwayland_path', +# type: 'string', +# value: '', +# description: 'Path to Xwayland executable' +#) -option('xwayland_grab_default_access_rules', - type: 'string', - value: 'gnome-boxes,remote-viewer,virt-viewer,virt-manager,vinagre,vncviewer,Xephyr', - description: 'Comma delimited list of applications resources or class allowed to issue X11 grabs in Xwayland' -) +#option('xwayland_grab_default_access_rules', +# type: 'string', +# value: 'gnome-boxes,remote-viewer,virt-viewer,virt-manager,vinagre,vncviewer,Xephyr', +# description: 'Comma delimited list of applications resources or class allowed to issue X11 grabs in Xwayland' +#) -option('xwayland_initfd', - type: 'feature', - value: 'auto', - description: 'Whether -initfd argument is passed to Xwayland to guarantee services (e.g. gsd-xsettings) startup before applications' -) +#option('xwayland_initfd', +# type: 'feature', +# value: 'auto', +# description: 'Whether -initfd argument is passed to Xwayland to guarantee services (e.g. gsd-xsettings) startup before applications' +#) option('catch', type: 'boolean', value: false, description: 'Use catch to catch backtraces' ) + +option('with_shared_components', + type: 'boolean', + value: false, + description: 'Build components that are shared with Mutter' +) diff --git a/scripts/mkRelease.sh b/scripts/mkRelease.sh new file mode 100755 index 0000000000..fc4cc6b819 --- /dev/null +++ b/scripts/mkRelease.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +git submodule init +git submodule update + +VERSION="0.9" +NAME="magpie" +git-archive-all.sh --format tar --prefix ${NAME}-${VERSION}/ --verbose -t HEAD ${NAME}-${VERSION}.tar +xz -9 "${NAME}-${VERSION}.tar" + +gpg --default-key 1E1FB0017C998A8AE2C498A6C2EAA8A26ADC59EE --armor --detach-sign "${NAME}-${VERSION}.tar.xz" +gpg --verify "${NAME}-${VERSION}.tar.xz.asc" diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index 25d240d810..d8f009a75b 100644 --- a/src/backends/meta-stage-impl.c +++ b/src/backends/meta-stage-impl.c @@ -731,6 +731,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, { g_autoptr (GError) error = NULL; + clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED); + if (meta_stage_impl_scanout_view (stage_impl, stage_view, scanout, diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index 0bfd3f5ad5..3590608ee0 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -394,7 +394,7 @@ meta_crtc_kms_maybe_set_gamma (MetaCrtcKms *crtc_kms, if (!gamma) return; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc); meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, gamma->size, diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c index f4b42c56c1..81ce0c6278 100644 --- a/src/backends/native/meta-cursor-renderer-native.c +++ b/src/backends/native/meta-cursor-renderer-native.c @@ -58,19 +58,6 @@ #include "wayland/meta-wayland-buffer.h" #endif -/* When animating a cursor, we usually call drmModeSetCursor2 once per frame. - * Though, testing shows that we need to triple buffer the cursor buffer in - * order to avoid glitches when animating the cursor, at least when running on - * Intel. The reason for this might be (but is not confirmed to be) due to - * the user space gbm_bo cache, making us reuse and overwrite the kernel side - * buffer content before it was scanned out. To avoid this, we keep a user space - * reference to each buffer we set until at least one frame after it was drawn. - * In effect, this means we three active cursor gbm_bo's: one that that just has - * been set, one that was previously set and may or may not have been scanned - * out, and one pending that will be replaced if the cursor sprite changes. - */ -#define HW_CURSOR_BUFFER_COUNT 3 - static GQuark quark_cursor_sprite = 0; typedef struct _CrtcCursorData @@ -104,19 +91,10 @@ typedef struct _MetaCursorRendererNativeGpuData uint64_t cursor_height; } MetaCursorRendererNativeGpuData; -typedef enum _MetaCursorBufferState -{ - META_CURSOR_BUFFER_STATE_NONE, - META_CURSOR_BUFFER_STATE_SET, - META_CURSOR_BUFFER_STATE_INVALIDATED, -} MetaCursorBufferState; - typedef struct _MetaCursorNativeGpuState { MetaGpu *gpu; - unsigned int active_buffer_idx; - MetaCursorBufferState pending_buffer_state; - MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT]; + MetaDrmBuffer *buffer; } MetaCursorNativeGpuState; typedef struct _MetaCursorNativePrivate @@ -197,44 +175,17 @@ meta_cursor_renderer_native_finalize (GObject *object) G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object); } -static unsigned int -get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; -} - -static MetaDrmBuffer * -get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - unsigned int pending_buffer_idx; - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - return cursor_gpu_state->buffers[pending_buffer_idx]; -} - -static MetaDrmBuffer * -get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state) -{ - return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx]; -} - static void -set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms, - MetaDrmBuffer *buffer) +set_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, + MetaGpuKms *gpu_kms, + MetaDrmBuffer *buffer) { MetaCursorNativePrivate *cursor_priv; MetaCursorNativeGpuState *cursor_gpu_state; - unsigned int pending_buffer_idx; cursor_priv = ensure_cursor_priv (cursor_sprite); cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms); - - pending_buffer_idx = - get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - cursor_gpu_state->buffers[pending_buffer_idx] = buffer; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET; + cursor_gpu_state->buffer = buffer; } static void @@ -309,10 +260,7 @@ assign_cursor_plane (MetaCursorRendererNative *native, MetaKmsUpdate *kms_update; MetaKmsPlaneAssignment *plane_assignment; - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state); - else - buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); + buffer = cursor_gpu_state->buffer; kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); kms_device = meta_kms_crtc_get_device (kms_crtc); @@ -341,8 +289,8 @@ assign_cursor_plane (MetaCursorRendererNative *native, flags |= META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED; kms_update = - meta_kms_ensure_pending_update (meta_kms_device_get_kms (kms_device), - meta_kms_crtc_get_device (kms_crtc)); + meta_kms_ensure_pending_update_for_crtc (meta_kms_device_get_kms (kms_device), + kms_crtc); plane_assignment = meta_kms_update_assign_plane (kms_update, kms_crtc, cursor_plane, @@ -363,13 +311,6 @@ assign_cursor_plane (MetaCursorRendererNative *native, native); crtc_cursor_data->buffer = buffer; - - if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET) - { - cursor_gpu_state->active_buffer_idx = - (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT; - cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE; - } } static float @@ -494,7 +435,7 @@ unset_crtc_cursor (MetaCursorRendererNative *native, MetaKms *kms = meta_kms_device_get_kms (kms_device); MetaKmsUpdate *kms_update; - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc); meta_kms_update_unassign_plane (kms_update, kms_crtc, cursor_plane); } @@ -602,19 +543,7 @@ has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite, if (!cursor_gpu_state) return FALSE; - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_NONE: - return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL; - case META_CURSOR_BUFFER_STATE_SET: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - - return FALSE; + return cursor_gpu_state->buffer != NULL; } static void @@ -1119,16 +1048,14 @@ unset_crtc_cursor_renderer_privates (MetaGpu *gpu, static void cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state) { - int i; MetaDrmBuffer *active_buffer; - active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state); + active_buffer = cursor_gpu_state->buffer; if (active_buffer) unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu, active_buffer); - for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++) - g_clear_object (&cursor_gpu_state->buffers[i]); + g_clear_object (&cursor_gpu_state->buffer); g_free (cursor_gpu_state); } @@ -1165,14 +1092,7 @@ invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite) g_hash_table_iter_init (&iter, cursor_priv->gpu_states); while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state)) - { - unsigned int pending_buffer_idx; - - pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state); - g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]); - cursor_gpu_state->pending_buffer_state = - META_CURSOR_BUFFER_STATE_INVALIDATED; - } + g_clear_object (&cursor_gpu_state->buffer); } static void @@ -1410,35 +1330,7 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, return; } - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, buffer); -} - -static gboolean -is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite, - MetaGpuKms *gpu_kms) -{ - MetaCursorNativePrivate *cursor_priv; - MetaCursorNativeGpuState *cursor_gpu_state; - - cursor_priv = get_cursor_priv (cursor_sprite); - if (!cursor_priv) - return FALSE; - - cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); - if (!cursor_gpu_state) - return FALSE; - - switch (cursor_gpu_state->pending_buffer_state) - { - case META_CURSOR_BUFFER_STATE_SET: - case META_CURSOR_BUFFER_STATE_NONE: - return TRUE; - case META_CURSOR_BUFFER_STATE_INVALIDATED: - return FALSE; - } - - g_assert_not_reached (); - return FALSE; + set_cursor_sprite_buffer (cursor_sprite, gpu_kms, buffer); } static gboolean @@ -1605,7 +1497,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) return; - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && + if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) && is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) return; @@ -1750,8 +1642,8 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, return; } - set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms, - META_DRM_BUFFER (buffer_gbm)); + set_cursor_sprite_buffer (cursor_sprite, gpu_kms, + META_DRM_BUFFER (buffer_gbm)); } } #endif @@ -1775,7 +1667,7 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) return; - if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) && + if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) && is_cursor_scale_and_transform_valid (renderer, cursor_sprite)) return; diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c index ee9e19d2d9..0da9a77853 100644 --- a/src/backends/native/meta-kms-crtc.c +++ b/src/backends/native/meta-kms-crtc.c @@ -32,6 +32,12 @@ typedef struct _MetaKmsCrtcPropTable MetaKmsProp props[META_KMS_CRTC_N_PROPS]; } MetaKmsCrtcPropTable; +typedef struct +{ + MetaDrmBuffer *front, *back; + gboolean back_is_set; +} PlaneState; + struct _MetaKmsCrtc { GObject parent; @@ -44,6 +50,8 @@ struct _MetaKmsCrtc MetaKmsCrtcState current_state; MetaKmsCrtcPropTable prop_table; + + GHashTable *plane_states; }; G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT) @@ -403,20 +411,91 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device, return crtc; } +void +meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc, + uint32_t plane_id, + MetaDrmBuffer *buffer) +{ + gpointer key = GUINT_TO_POINTER (plane_id); + PlaneState *plane_state; + + plane_state = g_hash_table_lookup (crtc->plane_states, key); + if (plane_state == NULL) + { + plane_state = g_new0 (PlaneState, 1); + g_hash_table_insert (crtc->plane_states, key, plane_state); + } + + plane_state->back_is_set = TRUE; /* note buffer may be NULL */ + g_set_object (&plane_state->back, buffer); +} + +static void +swap_plane_buffers (gpointer key, + gpointer value, + gpointer user_data) +{ + PlaneState *plane_state = value; + + if (plane_state->back_is_set) + { + g_set_object (&plane_state->front, plane_state->back); + g_clear_object (&plane_state->back); + plane_state->back_is_set = FALSE; + } +} + +void +meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc) +{ + g_hash_table_foreach (crtc->plane_states, swap_plane_buffers, NULL); +} + +void +meta_kms_crtc_release_buffers (MetaKmsCrtc *crtc) +{ + g_hash_table_remove_all (crtc->plane_states); +} + +static void +meta_kms_crtc_dispose (GObject *object) +{ + MetaKmsCrtc *crtc = META_KMS_CRTC (object); + + meta_kms_crtc_release_buffers (crtc); + + G_OBJECT_CLASS (meta_kms_crtc_parent_class)->dispose (object); +} + static void meta_kms_crtc_finalize (GObject *object) { MetaKmsCrtc *crtc = META_KMS_CRTC (object); clear_gamma_state (&crtc->current_state); + g_hash_table_unref (crtc->plane_states); G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object); } +static void +destroy_plane_state (gpointer data) +{ + PlaneState *plane_state = data; + + g_clear_object (&plane_state->front); + g_clear_object (&plane_state->back); + g_free (plane_state); +} + static void meta_kms_crtc_init (MetaKmsCrtc *crtc) { crtc->current_state.gamma.size = 0; + crtc->plane_states = g_hash_table_new_full (NULL, + NULL, + NULL, + destroy_plane_state); } static void @@ -424,5 +503,6 @@ meta_kms_crtc_class_init (MetaKmsCrtcClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->dispose = meta_kms_crtc_dispose; object_class->finalize = meta_kms_crtc_finalize; } diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h index 54801dd96a..deafeb61e0 100644 --- a/src/backends/native/meta-kms-crtc.h +++ b/src/backends/native/meta-kms-crtc.h @@ -25,6 +25,7 @@ #include #include "backends/native/meta-kms-types.h" +#include "backends/native/meta-drm-buffer.h" #include "core/util-private.h" #include "meta/boxes.h" @@ -84,4 +85,12 @@ MetaKmsCrtcGamma * meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc, const uint16_t *green, const uint16_t *blue); +void meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc, + uint32_t plane_id, + MetaDrmBuffer *buffer); + +void meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc); + +void meta_kms_crtc_release_buffers (MetaKmsCrtc *crtc); + #endif /* META_KMS_CRTC_H */ diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c index e938e4522c..5271cbecf4 100644 --- a/src/backends/native/meta-kms-impl-device-atomic.c +++ b/src/backends/native/meta-kms-impl-device-atomic.c @@ -457,6 +457,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, { MetaKmsPlaneAssignment *plane_assignment = update_entry; MetaKmsPlane *plane = plane_assignment->plane; + MetaKmsUpdateFlag flags = (MetaKmsUpdateFlag) user_data; MetaDrmBuffer *buffer; MetaKmsFbDamage *fb_damage; uint32_t prop_id; @@ -609,6 +610,12 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, error)) return FALSE; } + + if (!(flags & META_KMS_UPDATE_FLAG_TEST_ONLY)) + meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc, + meta_kms_plane_get_id (plane), + buffer); + return TRUE; } @@ -986,7 +993,7 @@ meta_kms_impl_device_atomic_process_update (MetaKmsImplDevice *impl_device, req, blob_ids, meta_kms_update_get_plane_assignments (update), - NULL, + GUINT_TO_POINTER (flags), process_plane_assignment, &error)) goto err; diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c index 648de51c65..53d76291ad 100644 --- a/src/backends/native/meta-kms-impl-device-simple.c +++ b/src/backends/native/meta-kms-impl-device-simple.c @@ -486,6 +486,8 @@ process_mode_set (MetaKmsImplDevice *impl_device, return FALSE; } + meta_kms_crtc_on_scanout_started (crtc); + if (drm_mode) { g_hash_table_replace (impl_device_simple->cached_mode_sets, @@ -550,7 +552,7 @@ is_timestamp_earlier_than (uint64_t ts1, typedef struct _RetryPageFlipData { MetaKmsCrtc *crtc; - uint32_t fb_id; + MetaDrmBuffer *fb; MetaKmsPageFlipData *page_flip_data; float refresh_rate; uint64_t retry_time_us; @@ -563,6 +565,7 @@ retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data) g_assert (!retry_page_flip_data->page_flip_data); g_clear_pointer (&retry_page_flip_data->custom_page_flip, meta_kms_custom_page_flip_free); + g_clear_object (&retry_page_flip_data->fb); g_free (retry_page_flip_data); } @@ -630,16 +633,21 @@ retry_page_flips (gpointer user_data) } else { + uint32_t fb_id = + retry_page_flip_data->fb ? + meta_drm_buffer_get_fb_id (retry_page_flip_data->fb) : + 0; + meta_topic (META_DEBUG_KMS, "[simple] Retrying page flip on CRTC %u (%s) with %u", meta_kms_crtc_get_id (crtc), meta_kms_impl_device_get_path (impl_device), - retry_page_flip_data->fb_id); + fb_id); fd = meta_kms_impl_device_get_fd (impl_device); ret = drmModePageFlip (fd, meta_kms_crtc_get_id (crtc), - retry_page_flip_data->fb_id, + fb_id, DRM_MODE_PAGE_FLIP_EVENT, retry_page_flip_data->page_flip_data); } @@ -726,7 +734,7 @@ retry_page_flips (gpointer user_data) static void schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple, MetaKmsCrtc *crtc, - uint32_t fb_id, + MetaDrmBuffer *fb, float refresh_rate, MetaKmsPageFlipData *page_flip_data, MetaKmsCustomPageFlip *custom_page_flip) @@ -741,7 +749,7 @@ schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple, retry_page_flip_data = g_new0 (RetryPageFlipData, 1); *retry_page_flip_data = (RetryPageFlipData) { .crtc = crtc, - .fb_id = fb_id, + .fb = fb ? g_object_ref (fb) : NULL, .page_flip_data = page_flip_data, .refresh_rate = refresh_rate, .retry_time_us = retry_time_us, @@ -875,6 +883,8 @@ mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple, return FALSE; } + meta_kms_crtc_on_scanout_started (crtc); + if (!impl_device_simple->mode_set_fallback_feedback_source) { GSource *source; @@ -999,20 +1009,20 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device, cached_mode_set = get_cached_mode_set (impl_device_simple, crtc); if (cached_mode_set) { - uint32_t fb_id; + MetaDrmBuffer *fb; drmModeModeInfo *drm_mode; float refresh_rate; if (plane_assignment) - fb_id = meta_drm_buffer_get_fb_id (plane_assignment->buffer); + fb = plane_assignment->buffer; else - fb_id = 0; + fb = NULL; drm_mode = cached_mode_set->drm_mode; refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode); meta_kms_impl_device_hold_fd (impl_device); schedule_retry_page_flip (impl_device_simple, crtc, - fb_id, + fb, refresh_rate, page_flip_data, g_steal_pointer (&custom_page_flip)); @@ -1302,7 +1312,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, { case META_KMS_PLANE_TYPE_PRIMARY: /* Handled as part of the mode-set and page flip. */ - return TRUE; + goto assigned; case META_KMS_PLANE_TYPE_CURSOR: if (!process_cursor_plane_assignment (impl_device, update, plane_assignment, @@ -1316,7 +1326,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, } else { - return TRUE; + goto assigned; } case META_KMS_PLANE_TYPE_OVERLAY: error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED, @@ -1329,6 +1339,12 @@ process_plane_assignment (MetaKmsImplDevice *impl_device, } g_assert_not_reached (); + +assigned: + meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc, + meta_kms_plane_get_id (plane), + plane_assignment->buffer); + return TRUE; } static gboolean diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index d9ea276378..4eeb182f6e 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -1204,8 +1204,12 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device, void meta_kms_impl_device_prepare_shutdown (MetaKmsImplDevice *impl_device) { + MetaKmsImplDevicePrivate *priv = + meta_kms_impl_device_get_instance_private (impl_device); MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device); + g_list_foreach (priv->crtcs, (GFunc) meta_kms_crtc_release_buffers, NULL); + if (klass->prepare_shutdown) klass->prepare_shutdown (impl_device); diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c index c1c29905c6..a6fbaf2f88 100644 --- a/src/backends/native/meta-kms-page-flip.c +++ b/src/backends/native/meta-kms-page-flip.c @@ -25,6 +25,7 @@ #include "backends/native/meta-kms-impl.h" #include "backends/native/meta-kms-private.h" #include "backends/native/meta-kms-update.h" +#include "backends/native/meta-kms-crtc.h" typedef struct _MetaKmsPageFlipClosure { @@ -150,6 +151,8 @@ meta_kms_page_flip_data_flipped (MetaKms *kms, meta_assert_not_in_kms_impl (kms); + meta_kms_crtc_on_scanout_started (page_flip_data->crtc); + for (l = page_flip_data->closures; l; l = l->next) { MetaKmsPageFlipClosure *closure = l->data; diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h index 3a648ba0da..cfcf4b0505 100644 --- a/src/backends/native/meta-kms-update-private.h +++ b/src/backends/native/meta-kms-update-private.h @@ -137,6 +137,12 @@ uint64_t meta_kms_update_get_sequence_number (MetaKmsUpdate *update); META_EXPORT_TEST MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update); +gboolean meta_kms_update_includes_crtc (MetaKmsUpdate *update, + MetaKmsCrtc *crtc); + +void meta_kms_update_include_crtc (MetaKmsUpdate *update, + MetaKmsCrtc *crtc); + void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment, MetaKmsPlaneRotation rotation); diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c index 4c34000ef5..cbbf1a0dab 100644 --- a/src/backends/native/meta-kms-update.c +++ b/src/backends/native/meta-kms-update.c @@ -25,12 +25,14 @@ #include "backends/meta-display-config-shared.h" #include "backends/native/meta-kms-connector.h" #include "backends/native/meta-kms-crtc.h" +#include "backends/native/meta-kms-device.h" #include "backends/native/meta-kms-mode-private.h" #include "backends/native/meta-kms-plane.h" struct _MetaKmsUpdate { MetaKmsDevice *device; + GHashTable *crtcs; gboolean is_locked; uint64_t sequence_number; @@ -149,6 +151,7 @@ static void meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment) { g_clear_pointer (&plane_assignment->fb_damage, meta_kms_fb_damage_free); + g_clear_object (&plane_assignment->buffer); g_free (plane_assignment); } @@ -228,7 +231,7 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update, .update = update, .crtc = crtc, .plane = plane, - .buffer = buffer, + .buffer = g_object_ref (buffer), .src_rect = src_rect, .dst_rect = dst_rect, .flags = flags, @@ -237,6 +240,8 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update, update->plane_assignments = g_list_prepend (update->plane_assignments, plane_assignment); + g_hash_table_add (update->crtcs, crtc); + return plane_assignment; } @@ -251,6 +256,8 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update, g_assert (meta_kms_crtc_get_device (crtc) == update->device); g_assert (meta_kms_plane_get_device (plane) == update->device); + drop_plane_assignment (update, plane, NULL); + plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1); *plane_assignment = (MetaKmsPlaneAssignment) { .update = update, @@ -262,6 +269,8 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update, update->plane_assignments = g_list_prepend (update->plane_assignments, plane_assignment); + g_hash_table_add (update->crtcs, crtc); + return plane_assignment; } @@ -284,6 +293,8 @@ meta_kms_update_mode_set (MetaKmsUpdate *update, }; update->mode_sets = g_list_prepend (update->mode_sets, mode_set); + + g_hash_table_add (update->crtcs, crtc); } static MetaKmsConnectorUpdate * @@ -292,6 +303,8 @@ ensure_connector_update (MetaKmsUpdate *update, { GList *l; MetaKmsConnectorUpdate *connector_update; + MetaKmsDevice *device; + const MetaKmsConnectorState *state; for (l = update->connector_updates; l; l = l->next) { @@ -306,6 +319,23 @@ ensure_connector_update (MetaKmsUpdate *update, update->connector_updates = g_list_prepend (update->connector_updates, connector_update); + device = meta_kms_connector_get_device (connector); + state = meta_kms_connector_get_current_state (connector); + if (device && state && state->current_crtc_id) + { + GList *l; + + for (l = meta_kms_device_get_crtcs (device); l; l = l->next) + { + MetaKmsCrtc *kms_crtc = l->data; + + if (meta_kms_crtc_get_id (kms_crtc) == state->current_crtc_id) + { + g_hash_table_add (update->crtcs, kms_crtc); + break; + } + } + } return connector_update; } @@ -416,6 +446,8 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update, gamma = meta_kms_crtc_gamma_new (crtc, size, red, green, blue); update->crtc_gammas = g_list_prepend (update->crtc_gammas, gamma); + + g_hash_table_add (update->crtcs, crtc); } void @@ -679,6 +711,20 @@ meta_kms_update_get_device (MetaKmsUpdate *update) return update->device; } +gboolean +meta_kms_update_includes_crtc (MetaKmsUpdate *update, + MetaKmsCrtc *crtc) +{ + return g_hash_table_contains (update->crtcs, crtc); +} + +void +meta_kms_update_include_crtc (MetaKmsUpdate *update, + MetaKmsCrtc *crtc) +{ + g_hash_table_add (update->crtcs, crtc); +} + MetaKmsCustomPageFlip * meta_kms_update_take_custom_page_flip_func (MetaKmsUpdate *update) { @@ -707,12 +753,15 @@ meta_kms_update_new (MetaKmsDevice *device) update->device = device; update->sequence_number = sequence_number++; + update->crtcs = g_hash_table_new (NULL, NULL); + return update; } void meta_kms_update_free (MetaKmsUpdate *update) { + g_hash_table_destroy (update->crtcs); g_list_free_full (update->result_listeners, (GDestroyNotify) meta_kms_result_listener_free); g_list_free_full (update->plane_assignments, diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 21be532a2f..b8dba8d0e3 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -23,6 +23,7 @@ #include "backends/native/meta-kms-private.h" #include "backends/native/meta-backend-native.h" +#include "backends/native/meta-kms-crtc.h" #include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-impl.h" #include "backends/native/meta-kms-update-private.h" @@ -177,10 +178,17 @@ struct _MetaKms GList *pending_callbacks; guint callback_source_id; + + gboolean shutting_down; }; G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) +static MetaKmsFeedback * +meta_kms_post_update_sync (MetaKms *kms, + MetaKmsUpdate *update, + MetaKmsUpdateFlag flags); + void meta_kms_discard_pending_updates (MetaKms *kms) { @@ -247,12 +255,105 @@ meta_kms_take_pending_update (MetaKms *kms, return NULL; } +MetaKmsUpdate * +meta_kms_ensure_pending_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc) +{ + MetaKmsUpdate *update; + + update = meta_kms_get_pending_update_for_crtc (kms, crtc); + if (update == NULL) + { + update = meta_kms_update_new (meta_kms_crtc_get_device (crtc)); + meta_kms_update_include_crtc (update, crtc); + meta_kms_add_pending_update (kms, update); + } + + return update; +} + +static MetaKmsUpdate * +meta_kms_find_compatible_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc, + gboolean take) +{ + MetaKmsDevice *device; + MetaKmsUpdate *update; + GList *l; + + for (l = kms->pending_updates; l; l = l->next) + { + update = l->data; + if (meta_kms_update_includes_crtc (update, crtc)) + goto found; + } + + device = meta_kms_crtc_get_device (crtc); + + for (l = kms->pending_updates; l; l = l->next) + { + update = l->data; + if (meta_kms_update_get_device (update) == device && + meta_kms_update_get_mode_sets (update)) + goto found; + } + + return NULL; + +found: + if (take) + kms->pending_updates = g_list_delete_link (kms->pending_updates, l); + return update; +} + +MetaKmsUpdate * +meta_kms_get_pending_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc) +{ + return meta_kms_find_compatible_update_for_crtc (kms, crtc, FALSE); +} + +static MetaKmsUpdate * +meta_kms_take_pending_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc) +{ + return meta_kms_find_compatible_update_for_crtc (kms, crtc, TRUE); +} + MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, MetaKmsDevice *device, MetaKmsUpdateFlag flags) { MetaKmsUpdate *update; + + update = meta_kms_take_pending_update (kms, device); + if (!update) + return NULL; + + return meta_kms_post_update_sync (kms, update, flags); +} + +MetaKmsFeedback * +meta_kms_post_pending_update_for_crtc_sync (MetaKms *kms, + MetaKmsCrtc *crtc, + MetaKmsUpdateFlag flags) +{ + MetaKmsUpdate *update; + + update = meta_kms_take_pending_update_for_crtc (kms, crtc); + if (!update) + return NULL; + + return meta_kms_post_update_sync (kms, update, flags); +} + +static MetaKmsFeedback * +meta_kms_post_update_sync (MetaKms *kms, + MetaKmsUpdate *update, + MetaKmsUpdateFlag flags) +{ + MetaKmsDevice *device = meta_kms_update_get_device (update); MetaKmsFeedback *feedback; GList *result_listeners; GList *l; @@ -260,10 +361,6 @@ meta_kms_post_pending_update_sync (MetaKms *kms, COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync, "KMS (post update)"); - update = meta_kms_take_pending_update (kms, device); - if (!update) - return NULL; - meta_kms_update_lock (update); feedback = meta_kms_device_process_update_sync (device, update, flags); @@ -752,10 +849,18 @@ prepare_shutdown_in_impl (MetaKmsImpl *impl, void meta_kms_prepare_shutdown (MetaKms *kms) { + kms->shutting_down = TRUE; + meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL); flush_callbacks (kms); } +gboolean +meta_kms_is_shutting_down (MetaKms *kms) +{ + return kms->shutting_down; +} + static void meta_kms_finalize (GObject *object) { diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h index bd9fe5cead..e8fe2e418d 100644 --- a/src/backends/native/meta-kms.h +++ b/src/backends/native/meta-kms.h @@ -39,9 +39,15 @@ void meta_kms_discard_pending_updates (MetaKms *kms); MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms, MetaKmsDevice *device); +MetaKmsUpdate * meta_kms_ensure_pending_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc); + MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms, MetaKmsDevice *device); +MetaKmsUpdate * meta_kms_get_pending_update_for_crtc (MetaKms *kms, + MetaKmsCrtc *crtc); + MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, MetaKmsDevice *device, MetaKmsUpdateFlag flags); @@ -49,6 +55,10 @@ MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms, MetaKmsFeedback * meta_kms_post_test_update_sync (MetaKms *kms, MetaKmsUpdate *update); +MetaKmsFeedback * meta_kms_post_pending_update_for_crtc_sync (MetaKms *kms, + MetaKmsCrtc *device, + MetaKmsUpdateFlag flags); + void meta_kms_discard_pending_page_flips (MetaKms *kms); void meta_kms_notify_modes_set (MetaKms *kms); @@ -68,6 +78,8 @@ MetaKmsDevice * meta_kms_create_device (MetaKms *kms, void meta_kms_prepare_shutdown (MetaKms *kms); +gboolean meta_kms_is_shutting_down (MetaKms *kms); + MetaKms * meta_kms_new (MetaBackend *backend, MetaKmsFlags flags, GError **error); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index a107a99bb3..79cf789634 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -67,13 +67,12 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState struct { struct gbm_surface *surface; - MetaDrmBuffer *current_fb; - MetaDrmBuffer *next_fb; } gbm; struct { MetaDrmBufferDumb *current_dumb_fb; - MetaDrmBufferDumb *dumb_fbs[2]; + MetaDrmBufferDumb *dumb_fbs[3]; + MetaDrmBuffer *source_fbs[3]; } cpu; gboolean noted_primary_gpu_copy_ok; @@ -94,8 +93,8 @@ struct _MetaOnscreenNative struct { struct gbm_surface *surface; - MetaDrmBuffer *current_fb; MetaDrmBuffer *next_fb; + MetaDrmBuffer *stalled_fb; } gbm; #ifdef HAVE_EGL_DEVICE @@ -107,69 +106,25 @@ struct _MetaOnscreenNative #endif MetaRendererView *view; + + unsigned int swaps_pending; + struct { + int *rectangles; /* 4 x n_rectangles */ + int n_rectangles; + } next_post; }; G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native, COGL_TYPE_ONSCREEN_EGL) +static void +try_post_latest_swap (CoglOnscreen *onscreen); + static gboolean init_secondary_gpu_state (MetaRendererNative *renderer_native, CoglOnscreen *onscreen, GError **error); -static void -swap_secondary_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_set_object (&secondary_gpu_state->gbm.current_fb, - secondary_gpu_state->gbm.next_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); -} - -static void -free_current_secondary_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; - - secondary_gpu_state = onscreen_native->secondary_gpu_state; - if (!secondary_gpu_state) - return; - - g_clear_object (&secondary_gpu_state->gbm.current_fb); -} - -static void -free_current_bo (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - g_clear_object (&onscreen_native->gbm.current_fb); - free_current_secondary_bo (onscreen); -} - -static void -meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen) -{ - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); - - if (!onscreen_native->gbm.next_fb) - return; - - free_current_bo (onscreen); - - g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb); - g_clear_object (&onscreen_native->gbm.next_fb); - - swap_secondary_drm_fb (onscreen); -} - static void maybe_update_frame_info (MetaCrtc *crtc, CoglFrameInfo *frame_info, @@ -205,7 +160,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen) info = cogl_onscreen_pop_head_frame_info (onscreen); - g_assert (!cogl_onscreen_peek_head_frame_info (onscreen)); + g_assert (info); _cogl_onscreen_notify_frame_sync (onscreen, info); _cogl_onscreen_notify_complete (onscreen, info); @@ -234,7 +189,7 @@ notify_view_crtc_presented (MetaRendererView *view, maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence); meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); + try_post_latest_swap (onscreen); } static int64_t @@ -296,6 +251,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); + try_post_latest_swap (onscreen); } static void @@ -345,7 +301,7 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc, frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); - meta_onscreen_native_swap_drm_fb (onscreen); + try_post_latest_swap (onscreen); } static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = { @@ -406,18 +362,40 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data, } #endif /* HAVE_EGL_DEVICE */ -void -meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) +static void +drop_stalled_swap (CoglOnscreen *onscreen) { + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); CoglFrameInfo *frame_info; - meta_onscreen_native_swap_drm_fb (onscreen); + /* Remember we can't compare stalled_fb because it's not used by + * META_RENDERER_NATIVE_MODE_EGL_DEVICE. So we judge stalled to be whenever + * swaps_pending > 1. + */ + if (onscreen_native->swaps_pending <= 1) + return; + + onscreen_native->swaps_pending--; + + g_clear_object (&onscreen_native->gbm.stalled_fb); frame_info = cogl_onscreen_peek_tail_frame_info (onscreen); frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC; meta_onscreen_native_notify_frame_complete (onscreen); } +void +meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen) +{ + drop_stalled_swap (onscreen); + + /* If the monitor just woke up and the shell is fully idle (has nothing + * more to swap) then we just woke to an indefinitely black screen. Let's + * fix that using the last swap (which is never classified as "stalled"). + */ + try_post_latest_swap (onscreen); +} + static void meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaRendererView *view, @@ -436,8 +414,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, MetaKmsDevice *kms_device; MetaKms *kms; MetaKmsUpdate *kms_update; - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL; - MetaDrmBuffer *buffer; + g_autoptr (MetaDrmBuffer) buffer = NULL; MetaKmsPlaneAssignment *plane_assignment; COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs, @@ -446,7 +423,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); kms_device = meta_gpu_kms_get_kms_device (gpu_kms); kms = meta_kms_device_get_kms (kms_device); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc); g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc)); @@ -455,15 +432,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - if (gpu_kms == render_gpu) - { - buffer = onscreen_native->gbm.next_fb; - } - else - { - secondary_gpu_state = onscreen_native->secondary_gpu_state; - buffer = secondary_gpu_state->gbm.next_fb; - } + buffer = g_steal_pointer (&onscreen_native->gbm.next_fb); plane_assignment = meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, @@ -474,6 +443,11 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, meta_kms_plane_assignment_set_fb_damage (plane_assignment, rectangles, n_rectangles); } + + g_object_set_data_full (G_OBJECT (buffer), + "gbm_surface owner", + g_object_ref (onscreen), + (GDestroyNotify) g_object_unref); break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); @@ -509,7 +483,7 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes, "Onscreen (set CRTC modes)"); - kms_update = meta_kms_ensure_pending_update (kms, kms_device); + kms_update = meta_kms_ensure_pending_update_for_crtc (kms, kms_crtc); switch (renderer_gpu_data->mode) { @@ -537,13 +511,41 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, kms_update); } +static void +hold_primary_gpu_fb_for_secondary_gpu_scanout (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, + MetaDrmBuffer *primary_gpu_fb, + MetaDrmBuffer *secondary_gpu_fb) +{ + if (META_IS_DRM_BUFFER_DUMB (secondary_gpu_fb)) + { + MetaDrmBufferDumb *dumb_fb = META_DRM_BUFFER_DUMB (secondary_gpu_fb); + int i; + const int n = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); + + for (i = 0; i < n; i++) + { + if (dumb_fb == secondary_gpu_state->cpu.dumb_fbs[i]) + { + g_set_object (&secondary_gpu_state->cpu.source_fbs[i], + primary_gpu_fb); + break; + } + } + + g_warn_if_fail (i < n); + } +} + static void secondary_gpu_release_dumb (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { unsigned i; for (i = 0; i < G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); i++) - g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]); + { + g_clear_object (&secondary_gpu_state->cpu.dumb_fbs[i]); + g_clear_object (&secondary_gpu_state->cpu.source_fbs[i]); + } } static void @@ -568,8 +570,6 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta NULL); } - g_clear_object (&secondary_gpu_state->gbm.current_fb); - g_clear_object (&secondary_gpu_state->gbm.next_fb); g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy); secondary_gpu_release_dumb (secondary_gpu_state); @@ -577,11 +577,11 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta g_free (secondary_gpu_state); } -static gboolean +static MetaDrmBuffer * import_shared_framebuffer (CoglOnscreen *onscreen, - MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) + MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, + MetaDrmBuffer *primary_gpu_fb) { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRenderDevice *render_device; g_autoptr (GError) error = NULL; MetaDrmBuffer *imported_buffer; @@ -589,7 +589,7 @@ import_shared_framebuffer (CoglOnscreen *onscreen, render_device = secondary_gpu_state->renderer_gpu_data->render_device; imported_buffer = meta_render_device_import_dma_buf (render_device, - onscreen_native->gbm.next_fb, + primary_gpu_fb, &error); if (!imported_buffer) { @@ -603,16 +603,9 @@ import_shared_framebuffer (CoglOnscreen *onscreen, META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE); secondary_gpu_state->import_status = META_SHARED_FRAMEBUFFER_IMPORT_STATUS_FAILED; - return FALSE; + return NULL; } - /* - * next_fb may already contain a fallback buffer, so clear it only - * when we are sure to succeed. - */ - g_clear_object (&secondary_gpu_state->gbm.next_fb); - secondary_gpu_state->gbm.next_fb = imported_buffer; - if (secondary_gpu_state->import_status == META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE) { @@ -629,16 +622,16 @@ import_shared_framebuffer (CoglOnscreen *onscreen, secondary_gpu_state->import_status = META_SHARED_FRAMEBUFFER_IMPORT_STATUS_OK; - return TRUE; + return imported_buffer; } -static void +static MetaDrmBuffer * copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, MetaRendererNativeGpuData *renderer_gpu_data, - gboolean *egl_context_changed) + gboolean *egl_context_changed, + MetaDrmBuffer *primary_gpu_fb) { - MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (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); @@ -654,9 +647,6 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu, "FB Copy (secondary GPU)"); - g_warn_if_fail (secondary_gpu_state->gbm.next_fb == NULL); - g_clear_object (&secondary_gpu_state->gbm.next_fb); - render_device = renderer_gpu_data->render_device; egl_display = meta_render_device_get_egl_display (render_device); @@ -669,13 +659,13 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, { g_warning ("Failed to make current: %s", error->message); g_error_free (error); - return; + return NULL; } *egl_context_changed = TRUE; - buffer_gbm = META_DRM_BUFFER_GBM (onscreen_native->gbm.next_fb); + 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, gles3, @@ -687,7 +677,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, { g_warning ("Failed to blit shared framebuffer: %s", error->message); g_error_free (error); - return; + return NULL; } if (!meta_egl_swap_buffers (egl, @@ -697,7 +687,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, { g_warning ("Failed to swap buffers: %s", error->message); g_error_free (error); - return; + return NULL; } use_modifiers = meta_renderer_native_use_modifiers (renderer_native); @@ -717,25 +707,30 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen, g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s", error->message); g_error_free (error); - return; + return NULL; } - secondary_gpu_state->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); + return META_DRM_BUFFER (buffer_gbm); } static MetaDrmBufferDumb * secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state) { MetaDrmBufferDumb *current_dumb_fb; + const int n_dumb_fbs = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs); + int i; current_dumb_fb = secondary_gpu_state->cpu.current_dumb_fb; - if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[0]) - return secondary_gpu_state->cpu.dumb_fbs[1]; - else - return secondary_gpu_state->cpu.dumb_fbs[0]; + for (i = 0; i < n_dumb_fbs; i++) + { + if (current_dumb_fb == secondary_gpu_state->cpu.dumb_fbs[i]) + return secondary_gpu_state->cpu.dumb_fbs[(i + 1) % n_dumb_fbs]; + } + + return secondary_gpu_state->cpu.dumb_fbs[0]; } -static gboolean +static MetaDrmBuffer * copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscreen, MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, const int *rectangles, @@ -761,13 +756,13 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre if (!secondary_gpu_state || secondary_gpu_state->egl_surface == EGL_NO_SURFACE) - return FALSE; + return NULL; primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); primary_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, primary_gpu); if (!primary_gpu_data->secondary.has_EGL_EXT_image_dma_buf_import_modifiers) - return FALSE; + return NULL; buffer_dumb = secondary_gpu_get_next_dumb_buffer (secondary_gpu_state); buffer = META_DRM_BUFFER (buffer_dumb); @@ -790,7 +785,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre { meta_topic (META_DEBUG_KMS, "Failed to create DMA buffer: %s", error->message); - return FALSE; + return NULL; } dmabuf_fb = @@ -808,7 +803,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre meta_topic (META_DEBUG_KMS, "Failed to create DMA buffer for blitting: %s", error->message); - return FALSE; + return NULL; } /* Limit the number of individual copies to 16 */ #define MAX_RECTS 16 @@ -821,7 +816,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre &error)) { g_object_unref (dmabuf_fb); - return FALSE; + return NULL; } } else @@ -838,20 +833,19 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen *onscre &error)) { g_object_unref (dmabuf_fb); - return FALSE; + return NULL; } } } g_object_unref (dmabuf_fb); - g_set_object (&secondary_gpu_state->gbm.next_fb, buffer); secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; - return TRUE; + return g_object_ref (buffer); } -static void +static MetaDrmBuffer * copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state, MetaRendererNativeGpuData *renderer_gpu_data) @@ -903,17 +897,19 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen, cogl_object_unref (dumb_bitmap); - g_set_object (&secondary_gpu_state->gbm.next_fb, buffer); secondary_gpu_state->cpu.current_dumb_fb = buffer_dumb; + + return g_object_ref (buffer); } -static void +static MetaDrmBuffer * update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, const int *rectangles, int n_rectangles) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state; + MetaDrmBuffer *copy = NULL; COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers, "Onscreen (secondary gpu pre-swap-buffers)"); @@ -939,10 +935,11 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, /* prepare fallback */ G_GNUC_FALLTHROUGH; case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - if (!copy_shared_framebuffer_primary_gpu (onscreen, - secondary_gpu_state, - rectangles, - n_rectangles)) + copy = copy_shared_framebuffer_primary_gpu (onscreen, + secondary_gpu_state, + rectangles, + n_rectangles); + if (!copy) { if (!secondary_gpu_state->noted_primary_gpu_copy_failed) { @@ -952,9 +949,9 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, secondary_gpu_state->noted_primary_gpu_copy_failed = TRUE; } - copy_shared_framebuffer_cpu (onscreen, - secondary_gpu_state, - renderer_gpu_data); + copy = copy_shared_framebuffer_cpu (onscreen, + secondary_gpu_state, + renderer_gpu_data); } else if (!secondary_gpu_state->noted_primary_gpu_copy_ok) { @@ -966,11 +963,15 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen, break; } } + + return copy; } static void -update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, - gboolean *egl_context_changed) +update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, + gboolean *egl_context_changed, + MetaDrmBuffer *primary_gpu_fb, + MetaDrmBuffer **secondary_gpu_fb) { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; @@ -983,6 +984,7 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, if (secondary_gpu_state) { MetaRendererNativeGpuData *renderer_gpu_data; + g_autoptr (MetaDrmBuffer) next_fb = NULL; renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, @@ -990,23 +992,30 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen, switch (renderer_gpu_data->secondary.copy_mode) { case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO: - if (import_shared_framebuffer (onscreen, secondary_gpu_state)) + next_fb = import_shared_framebuffer (onscreen, + secondary_gpu_state, + primary_gpu_fb); + if (next_fb) break; - - /* The fallback was prepared in pre_swap_buffers */ + /* The fallback was prepared in pre_swap_buffers and is currently + * in secondary_gpu_fb. + */ renderer_gpu_data->secondary.copy_mode = META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY; G_GNUC_FALLTHROUGH; case META_SHARED_FRAMEBUFFER_COPY_MODE_PRIMARY: - /* Done before eglSwapBuffers. */ + next_fb = g_object_ref (*secondary_gpu_fb); break; case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU: - copy_shared_framebuffer_gpu (onscreen, - secondary_gpu_state, - renderer_gpu_data, - egl_context_changed); + next_fb = copy_shared_framebuffer_gpu (onscreen, + secondary_gpu_state, + renderer_gpu_data, + egl_context_changed, + primary_gpu_fb); break; } + + g_set_object (secondary_gpu_fb, next_fb); } } @@ -1040,34 +1049,39 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform; MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native; - MetaRenderer *renderer = META_RENDERER (renderer_native); - MetaBackend *backend = meta_renderer_get_backend (renderer); - MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); - MetaMonitorManager *monitor_manager = - meta_backend_get_monitor_manager (backend); - MetaKms *kms = meta_backend_native_get_kms (backend_native); MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaGpuKms *render_gpu = onscreen_native->render_gpu; MetaDeviceFile *render_device_file; ClutterFrame *frame = user_data; CoglOnscreenClass *parent_class; gboolean egl_context_changed = FALSE; - MetaPowerSave power_save_mode; g_autoptr (GError) error = NULL; MetaDrmBufferFlags buffer_flags; MetaDrmBufferGbm *buffer_gbm; - MetaKmsCrtc *kms_crtc; - MetaKmsDevice *kms_device; - MetaKmsUpdateFlag flags; - g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - const GError *feedback_error; + g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL; + g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL; + size_t rectangles_size; COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers, "Onscreen (swap-buffers)"); - update_secondary_gpu_state_pre_swap_buffers (onscreen, - rectangles, - n_rectangles); + if (meta_is_topic_enabled (META_DEBUG_KMS)) + { + unsigned int frames_pending = + cogl_onscreen_count_pending_frames (onscreen); + + meta_topic (META_DEBUG_KMS, + "Swap buffers: %u frames pending (%s-buffering)", + frames_pending, + frames_pending == 1 ? "double" : + frames_pending == 2 ? "triple" : + "?"); + } + + secondary_gpu_fb = + update_secondary_gpu_state_pre_swap_buffers (onscreen, + rectangles, + n_rectangles); parent_class = COGL_ONSCREEN_CLASS (meta_onscreen_native_parent_class); parent_class->swap_buffers_with_damage (onscreen, @@ -1083,9 +1097,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, switch (renderer_gpu_data->mode) { case META_RENDERER_NATIVE_MODE_GBM: - g_warn_if_fail (onscreen_native->gbm.next_fb == NULL); - g_clear_object (&onscreen_native->gbm.next_fb); - buffer_flags = META_DRM_BUFFER_FLAG_NONE; if (!meta_renderer_native_use_modifiers (renderer_native)) buffer_flags |= META_DRM_BUFFER_FLAG_DISABLE_MODIFIERS; @@ -1103,8 +1114,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, return; } - onscreen_native->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); - + primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm)); break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); @@ -1115,7 +1125,46 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, #endif } - update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed); + update_secondary_gpu_state_post_swap_buffers (onscreen, + &egl_context_changed, + primary_gpu_fb, + &secondary_gpu_fb); + + switch (renderer_gpu_data->mode) + { + case META_RENDERER_NATIVE_MODE_GBM: + if (onscreen_native->gbm.next_fb != NULL) + { + g_warn_if_fail (onscreen_native->gbm.stalled_fb == NULL); + drop_stalled_swap (onscreen); + g_assert (onscreen_native->gbm.stalled_fb == NULL); + onscreen_native->gbm.stalled_fb = + g_steal_pointer (&onscreen_native->gbm.next_fb); + } + + if (onscreen_native->secondary_gpu_state) + { + g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb); + hold_primary_gpu_fb_for_secondary_gpu_scanout ( + onscreen_native->secondary_gpu_state, + primary_gpu_fb, + secondary_gpu_fb); + } + else + { + g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb); + } + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + break; +#ifdef HAVE_EGL_DEVICE + case META_RENDERER_NATIVE_MODE_EGL_DEVICE: + break; +#endif + } + + clutter_frame_set_result (frame, + CLUTTER_FRAME_RESULT_PENDING_PRESENTED); /* * If we changed EGL context, cogl will have the wrong idea about what is @@ -1126,23 +1175,77 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, if (egl_context_changed) _cogl_winsys_egl_ensure_current (cogl_display); + rectangles_size = n_rectangles * 4 * sizeof (int); + onscreen_native->next_post.rectangles = + g_realloc (onscreen_native->next_post.rectangles, rectangles_size); + memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size); + onscreen_native->next_post.n_rectangles = n_rectangles; + + onscreen_native->swaps_pending++; + try_post_latest_swap (onscreen); +} + +static void +try_post_latest_swap (CoglOnscreen *onscreen) +{ + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer); + 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; + MetaRenderer *renderer = META_RENDERER (renderer_native); + MetaBackend *backend = meta_renderer_get_backend (renderer); + MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaKms *kms = meta_backend_native_get_kms (backend_native); + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + MetaPowerSave power_save_mode; + MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc); + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc); + MetaKmsUpdateFlag flags; + g_autoptr (MetaKmsFeedback) kms_feedback = NULL; + const GError *feedback_error; + unsigned int frames_pending = cogl_onscreen_count_pending_frames (onscreen); + + if (meta_kms_is_shutting_down (kms)) + { + meta_onscreen_native_discard_pending_swaps (onscreen); + return; + } + + if (onscreen_native->swaps_pending == 0) + return; + + g_assert (frames_pending >= onscreen_native->swaps_pending); + power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager); if (power_save_mode == META_POWER_SAVE_ON) { + unsigned int posts_pending; + + posts_pending = frames_pending - onscreen_native->swaps_pending; + if (posts_pending > 0) + return; /* wait for the next frame notification and then try again */ + + drop_stalled_swap (onscreen); + g_return_if_fail (onscreen_native->swaps_pending > 0); + onscreen_native->swaps_pending--; + ensure_crtc_modes (onscreen); meta_onscreen_native_flip_crtc (onscreen, onscreen_native->view, onscreen_native->crtc, META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE, - rectangles, - n_rectangles); + onscreen_native->next_post.rectangles, + onscreen_native->next_post.n_rectangles); } else { meta_renderer_native_queue_power_save_page_flip (renderer_native, onscreen); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); return; } @@ -1160,9 +1263,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, "Postponing primary plane composite update for CRTC %u (%s)", meta_kms_crtc_get_id (kms_crtc), meta_kms_device_get_path (kms_device)); - - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); return; } else if (meta_renderer_native_has_pending_mode_set (renderer_native)) @@ -1172,8 +1272,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_renderer_native_notify_mode_sets_reset (renderer_native); meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); return; } break; @@ -1186,8 +1284,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, { meta_renderer_native_notify_mode_sets_reset (renderer_native); meta_renderer_native_post_mode_set_updates (renderer_native); - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); return; } break; @@ -1200,18 +1296,16 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, meta_kms_device_get_path (kms_device)); flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); + kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms, + kms_crtc, + flags); + g_return_if_fail (kms_feedback != NULL); switch (meta_kms_feedback_get_result (kms_feedback)) { case META_KMS_FEEDBACK_PASSED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); break; case META_KMS_FEEDBACK_FAILED: - clutter_frame_set_result (frame, - CLUTTER_FRAME_RESULT_PENDING_PRESENTED); - feedback_error = meta_kms_feedback_get_error (kms_feedback); if (!g_error_matches (feedback_error, G_IO_ERROR, @@ -1298,6 +1392,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, return FALSE; } + /* Our direct scanout frame counts as 1, so more than that means we would + * be jumping the queue (and post would fail). + */ + if (cogl_onscreen_count_pending_frames (onscreen) > 1) + { + g_set_error_literal (error, + COGL_SCANOUT_ERROR, + COGL_SCANOUT_ERROR_INHIBITED, + "Direct scanout is inhibited during triple buffering"); + return FALSE; + } + renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, render_gpu); @@ -1350,7 +1456,9 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, meta_kms_device_get_path (kms_device)); flags = META_KMS_UPDATE_FLAG_PRESERVE_ON_ERROR; - kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags); + kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms, + kms_crtc, + flags); switch (meta_kms_feedback_get_result (kms_feedback)) { case META_KMS_FEEDBACK_PASSED: @@ -1364,7 +1472,6 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED)) break; - g_clear_object (&onscreen_native->gbm.next_fb); g_propagate_error (error, g_error_copy (feedback_error)); return FALSE; } @@ -1400,7 +1507,10 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, g_autoptr (MetaKmsFeedback) kms_feedback = NULL; const GError *error; - kms_update = meta_kms_get_pending_update (kms, kms_device); + if (cogl_onscreen_count_pending_frames (onscreen) > 0) + return; + + kms_update = meta_kms_get_pending_update_for_crtc (kms, kms_crtc); if (!kms_update) { clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE); @@ -1415,9 +1525,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, g_object_unref); flags = META_KMS_UPDATE_FLAG_NONE; - kms_feedback = meta_kms_post_pending_update_sync (kms, - kms_device, - flags); + kms_feedback = meta_kms_post_pending_update_for_crtc_sync (kms, + kms_crtc, + flags); switch (meta_kms_feedback_get_result (kms_feedback)) { case META_KMS_FEEDBACK_PASSED: @@ -1439,6 +1549,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, } } +void +meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen) +{ + MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); + + onscreen_native->swaps_pending = 0; + + g_clear_object (&onscreen_native->gbm.stalled_fb); + g_clear_object (&onscreen_native->gbm.next_fb); +} + static gboolean should_surface_be_sharable (CoglOnscreen *onscreen) { @@ -1987,6 +2108,21 @@ pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen) return DRM_FORMAT_INVALID; } +static void +dumb_toggle_notify (gpointer data, + GObject *object, + gboolean is_last_ref) +{ + MetaDrmBuffer **source_fb = data; + + g_return_if_fail (source_fb != NULL); + if (is_last_ref && *source_fb) + { + g_return_if_fail (META_IS_DRM_BUFFER (*source_fb)); + g_clear_object (source_fb); + } +} + static gboolean init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_native, CoglOnscreen *onscreen, @@ -2043,6 +2179,12 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative *renderer_nat } secondary_gpu_state->cpu.dumb_fbs[i] = META_DRM_BUFFER_DUMB (dumb_buffer); + g_object_add_toggle_ref (G_OBJECT (dumb_buffer), + dumb_toggle_notify, + &secondary_gpu_state->cpu.source_fbs[i]); + + /* It was incremented higher than we need by add_toggle_ref */ + g_object_unref (dumb_buffer); } /* @@ -2132,7 +2274,7 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native, onscreen_native->renderer_native = renderer_native; onscreen_native->render_gpu = render_gpu; onscreen_native->output = output; - onscreen_native->crtc = crtc; + onscreen_native->crtc = g_object_ref (crtc); return onscreen_native; } @@ -2153,7 +2295,6 @@ meta_onscreen_native_dispose (GObject *object) { case META_RENDERER_NATIVE_MODE_GBM: g_clear_object (&onscreen_native->gbm.next_fb); - free_current_bo (onscreen); break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); @@ -2181,9 +2322,12 @@ meta_onscreen_native_dispose (GObject *object) G_OBJECT_CLASS (meta_onscreen_native_parent_class)->dispose (object); + g_clear_object (&onscreen_native->crtc); g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy); g_clear_pointer (&onscreen_native->secondary_gpu_state, secondary_gpu_state_free); + g_clear_pointer (&onscreen_native->next_post.rectangles, g_free); + onscreen_native->next_post.n_rectangles = 0; } static void diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h index 8ea7ec2546..81b0eeaed5 100644 --- a/src/backends/native/meta-onscreen-native.h +++ b/src/backends/native/meta-onscreen-native.h @@ -42,6 +42,8 @@ void meta_onscreen_native_finish_frame (CoglOnscreen *onscreen, void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen); +void meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen); + gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, MetaDrmBuffer *fb); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index e27805d918..a99142e970 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -684,12 +684,18 @@ static gboolean dummy_power_save_page_flip_cb (gpointer user_data) { MetaRendererNative *renderer_native = user_data; + GList *old_list = + g_steal_pointer (&renderer_native->power_save_page_flip_onscreens); - g_list_foreach (renderer_native->power_save_page_flip_onscreens, + g_list_foreach (old_list, (GFunc) meta_onscreen_native_dummy_power_save_page_flip, NULL); - g_clear_list (&renderer_native->power_save_page_flip_onscreens, + g_clear_list (&old_list, g_object_unref); + + if (renderer_native->power_save_page_flip_onscreens != NULL) + return G_SOURCE_CONTINUE; + renderer_native->power_save_page_flip_source_id = 0; return G_SOURCE_REMOVE; @@ -701,6 +707,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na { const unsigned int timeout_ms = 100; + if (g_list_find (renderer_native->power_save_page_flip_onscreens, onscreen)) + return; + if (!renderer_native->power_save_page_flip_source_id) { renderer_native->power_save_page_flip_source_id = @@ -1409,6 +1418,26 @@ meta_renderer_native_create_view (MetaRenderer *renderer, return view; } +static void +discard_pending_swaps (MetaRenderer *renderer) +{ + GList *views = meta_renderer_get_views (renderer);; + GList *l; + + for (l = views; l; l = l->next) + { + ClutterStageView *stage_view = l->data; + CoglFramebuffer *fb = clutter_stage_view_get_onscreen (stage_view); + CoglOnscreen *onscreen; + + if (!COGL_IS_ONSCREEN (fb)) + continue; + + onscreen = COGL_ONSCREEN (fb); + meta_onscreen_native_discard_pending_swaps (onscreen); + } +} + static void keep_current_onscreens_alive (MetaRenderer *renderer) { @@ -1437,6 +1466,7 @@ meta_renderer_native_rebuild_views (MetaRenderer *renderer) MetaRendererClass *parent_renderer_class = META_RENDERER_CLASS (meta_renderer_native_parent_class); + discard_pending_swaps (renderer); meta_kms_discard_pending_page_flips (kms); meta_kms_discard_pending_updates (kms); diff --git a/src/compositor/plugins/meson.build b/src/compositor/plugins/meson.build index 9dd06814d9..4143a6671c 100644 --- a/src/compositor/plugins/meson.build +++ b/src/compositor/plugins/meson.build @@ -1,6 +1,6 @@ default_plugin_c_args = [ '-fPIC', - '-DG_LOG_DOMAIN="mutter"', + '-DG_LOG_DOMAIN="magpie"', '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), ] diff --git a/src/meson.build b/src/meson.build index 6790efa161..bae1b9e4ac 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1074,7 +1074,7 @@ libmutter = shared_library(libmutter_name, include_directories: mutter_includes, c_args: [ mutter_c_args, - '-DG_LOG_DOMAIN="libmutter"', + '-DG_LOG_DOMAIN="libmagie"', ], dependencies: [ libmutter_cogl_dep, @@ -1096,21 +1096,21 @@ libmutter_dep = declare_dependency( ], ) -mutter = executable('mutter', +mutter = executable('magpie', sources: [ files('core/mutter.c'), ], include_directories: mutter_includes, c_args: [ mutter_c_args, - '-DG_LOG_DOMAIN="mutter"', + '-DG_LOG_DOMAIN="magpie"', ], dependencies: [libmutter_dep], install_dir: bindir, install: true, ) if have_x11 - executable('mutter-restart-helper', + executable('magpie-restart-helper', sources: [ files('core/restart-helper.c'), ], @@ -1119,7 +1119,7 @@ if have_x11 ], c_args: [ mutter_c_args, - '-DG_LOG_DOMAIN="mutter-restart-helper"', + '-DG_LOG_DOMAIN="magpie-restart-helper"', ], dependencies: [ x11_dep, @@ -1171,15 +1171,15 @@ endif pkg.generate(libmutter, name: 'Meta', - filebase: 'libmutter-' + libmutter_api_version, - description: 'Mutter compositor and window manager library', + filebase: 'libmagpie-' + libmutter_api_version, + description: 'Magpie compositor and window manager library', subdirs: pkgname, requires: [mutter_pkg_deps, libmutter_clutter_name], version: meson.project_version(), variables: [ 'apiversion=' + libmutter_api_version, - 'girdir=${libdir}/mutter-' + libmutter_api_version, - 'typelibdir=${libdir}/mutter-' + libmutter_api_version, + 'girdir=${libdir}/magpie-' + libmutter_api_version, + 'typelibdir=${libdir}/magpie-' + libmutter_api_version, ], install_dir: pcdir, ) diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c index 6595eb5a29..42f7e62760 100644 --- a/src/tests/native-kms-render.c +++ b/src/tests/native-kms-render.c @@ -36,6 +36,8 @@ #include "tests/meta-wayland-test-driver.h" #include "tests/meta-wayland-test-utils.h" +#define N_FRAMES_PER_TEST 10 + typedef struct { int number_of_frames_left; @@ -43,7 +45,9 @@ typedef struct struct { int n_paints; - uint32_t fb_id; + int n_presentations; + int n_direct_scanouts; + GList *fb_ids; } scanout; gboolean wait_for_scanout; @@ -72,7 +76,7 @@ meta_test_kms_render_basic (void) gulong handler_id; test = (KmsRenderingTest) { - .number_of_frames_left = 10, + .number_of_frames_left = N_FRAMES_PER_TEST, .loop = g_main_loop_new (NULL, FALSE), }; handler_id = g_signal_connect (stage, "after-update", @@ -93,7 +97,6 @@ on_scanout_before_update (ClutterStage *stage, KmsRenderingTest *test) { test->scanout.n_paints = 0; - test->scanout.fb_id = 0; } static void @@ -103,6 +106,7 @@ on_scanout_before_paint (ClutterStage *stage, { CoglScanout *scanout; MetaDrmBuffer *buffer; + uint32_t fb_id; scanout = clutter_stage_view_peek_scanout (stage_view); if (!scanout) @@ -110,8 +114,14 @@ on_scanout_before_paint (ClutterStage *stage, g_assert_true (META_IS_DRM_BUFFER (scanout)); buffer = META_DRM_BUFFER (scanout); - test->scanout.fb_id = meta_drm_buffer_get_fb_id (buffer); - g_assert_cmpuint (test->scanout.fb_id, >, 0); + + fb_id = meta_drm_buffer_get_fb_id (buffer); + g_assert_cmpuint (fb_id, >, 0); + test->scanout.fb_ids = g_list_append (test->scanout.fb_ids, + GUINT_TO_POINTER (fb_id)); + + /* Triple buffering, but no higher */ + g_assert_cmpuint (g_list_length (test->scanout.fb_ids), <=, 2); } static void @@ -138,12 +148,12 @@ on_scanout_presented (ClutterStage *stage, MetaDeviceFile *device_file; GError *error = NULL; drmModeCrtc *drm_crtc; + uint32_t first_fb_id_expected; - if (test->scanout.n_paints > 0) + if (test->wait_for_scanout && test->scanout.fb_ids == NULL) return; - if (test->wait_for_scanout && test->scanout.fb_id == 0) - return; + test->scanout.n_presentations++; device_pool = meta_backend_native_get_device_pool (backend_native); @@ -162,15 +172,41 @@ on_scanout_presented (ClutterStage *stage, drm_crtc = drmModeGetCrtc (meta_device_file_get_fd (device_file), meta_kms_crtc_get_id (kms_crtc)); g_assert_nonnull (drm_crtc); - if (test->scanout.fb_id == 0) - g_assert_cmpuint (drm_crtc->buffer_id, !=, test->scanout.fb_id); + + if (test->scanout.fb_ids) + { + test->scanout.n_direct_scanouts++; + first_fb_id_expected = GPOINTER_TO_UINT (test->scanout.fb_ids->data); + test->scanout.fb_ids = g_list_delete_link (test->scanout.fb_ids, + test->scanout.fb_ids); + } else - g_assert_cmpuint (drm_crtc->buffer_id, ==, test->scanout.fb_id); + { + first_fb_id_expected = 0; + } + + /* The buffer ID won't match on the first frame because switching from + * triple buffered compositing to double buffered direct scanout takes + * an extra frame to drain the queue. Thereafter we are in direct scanout + * mode and expect the buffer IDs to match. + */ + if (test->scanout.n_presentations > 1) + { + if (first_fb_id_expected == 0) + g_assert_cmpuint (drm_crtc->buffer_id, !=, first_fb_id_expected); + else + g_assert_cmpuint (drm_crtc->buffer_id, ==, first_fb_id_expected); + } + drmModeFreeCrtc (drm_crtc); meta_device_file_release (device_file); - g_main_loop_quit (test->loop); + test->number_of_frames_left--; + if (test->number_of_frames_left <= 0) + g_main_loop_quit (test->loop); + else + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); } typedef enum @@ -209,7 +245,9 @@ meta_test_kms_render_client_scanout (void) g_assert_nonnull (wayland_test_client); test = (KmsRenderingTest) { + .number_of_frames_left = N_FRAMES_PER_TEST, .loop = g_main_loop_new (NULL, FALSE), + .scanout = {0}, .wait_for_scanout = TRUE, }; @@ -235,7 +273,8 @@ meta_test_kms_render_client_scanout (void) clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); g_main_loop_run (test.loop); - g_assert_cmpuint (test.scanout.fb_id, >, 0); + g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); + g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); g_debug ("Unmake fullscreen"); window = meta_find_window_from_title (test_context, "dma-buf-scanout-test"); @@ -257,10 +296,15 @@ meta_test_kms_render_client_scanout (void) g_assert_cmpint (buffer_rect.y, ==, 10); test.wait_for_scanout = FALSE; + test.number_of_frames_left = N_FRAMES_PER_TEST; + test.scanout.n_presentations = 0; + test.scanout.n_direct_scanouts = 0; + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); g_main_loop_run (test.loop); - g_assert_cmpuint (test.scanout.fb_id, ==, 0); + g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); + g_assert_cmpint (test.scanout.n_direct_scanouts, ==, 0); g_debug ("Moving back to 0, 0"); meta_window_move_frame (window, TRUE, 0, 0); @@ -272,10 +316,15 @@ meta_test_kms_render_client_scanout (void) g_assert_cmpint (buffer_rect.y, ==, 0); test.wait_for_scanout = TRUE; + test.number_of_frames_left = N_FRAMES_PER_TEST; + test.scanout.n_presentations = 0; + test.scanout.n_direct_scanouts = 0; + clutter_actor_queue_redraw (CLUTTER_ACTOR (stage)); g_main_loop_run (test.loop); - g_assert_cmpuint (test.scanout.fb_id, >, 0); + g_assert_cmpint (test.scanout.n_presentations, ==, N_FRAMES_PER_TEST); + g_assert_cmpint (test.scanout.n_direct_scanouts, ==, N_FRAMES_PER_TEST); g_signal_handler_disconnect (stage, before_update_handler_id); g_signal_handler_disconnect (stage, before_paint_handler_id);