2024-09-15 05:07:15 +00:00
|
|
|
From e1d79da6a8267f2e1598feb8d0e0889d138c77ca Mon Sep 17 00:00:00 2001
|
2024-07-30 08:28:28 +00:00
|
|
|
From: Mingi Sung <sungmg@saltyming.net>
|
2024-09-15 05:07:15 +00:00
|
|
|
Date: Sun, 15 Sep 2024 14:00:51 +0900
|
2024-08-28 11:31:05 +00:00
|
|
|
Subject: [PATCH] Merge branch 'sungmg-triple-buffering-v4-46' into gnome-46
|
2022-04-02 05:32:56 +00:00
|
|
|
|
|
|
|
Use triple buffering if and when the previous frame is running late.
|
|
|
|
This means the next frame will be dispatched on time instead of also starting
|
|
|
|
late.
|
|
|
|
|
|
|
|
It also triggers a GPU clock boost if deemed necessary by the driver.
|
|
|
|
Although frequency scaling is not required to get a performance gain here
|
|
|
|
because even a fixed frequency GPU will benefit from not over-sleeping anymore.
|
|
|
|
If the previous frame is not running late then we stick to double buffering so
|
|
|
|
there's no latency penalty when the system is able to maintain full frame rate.
|
|
|
|
|
2024-07-30 08:28:28 +00:00
|
|
|
Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
|
|
Source: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441
|
2024-09-14 03:04:52 +00:00
|
|
|
Commit: 511a502e1a6ff6c88dcb650f1bee8f6eb894d1f6
|
2024-08-05 03:39:17 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3184
|
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3265
|
2024-08-05 03:39:17 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3799
|
2024-09-14 03:04:52 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3817
|
2024-08-05 03:39:17 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3829
|
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3830
|
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3891
|
2024-08-14 08:34:14 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3934
|
2024-09-14 03:04:52 +00:00
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3958
|
|
|
|
Backported: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4015
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-07-30 08:28:28 +00:00
|
|
|
Signed-off-by: Mingi Sung <sungmg@saltyming.net>
|
2024-05-08 13:03:56 +00:00
|
|
|
---
|
2024-09-14 03:04:52 +00:00
|
|
|
clutter/clutter/clutter-frame-clock.c | 386 ++++++++++---
|
|
|
|
clutter/clutter/clutter-frame-clock.h | 15 +-
|
|
|
|
clutter/clutter/clutter-frame-private.h | 1 +
|
|
|
|
clutter/clutter/clutter-frame.c | 13 +
|
|
|
|
clutter/clutter/clutter-frame.h | 7 +
|
|
|
|
clutter/clutter/clutter-stage-view.c | 15 +-
|
|
|
|
clutter/clutter/clutter-stage-view.h | 2 +
|
|
|
|
cogl/cogl/cogl-onscreen-private.h | 5 +-
|
|
|
|
cogl/cogl/cogl-onscreen.c | 8 +
|
|
|
|
src/backends/meta-egl.c | 94 +++
|
|
|
|
src/backends/meta-egl.h | 23 +
|
|
|
|
src/backends/meta-stage-impl.c | 2 +
|
|
|
|
src/backends/native/meta-crtc-kms.c | 10 +
|
|
|
|
src/backends/native/meta-crtc-native.c | 8 +
|
|
|
|
src/backends/native/meta-crtc-native.h | 3 +
|
|
|
|
src/backends/native/meta-crtc-virtual.c | 8 +
|
|
|
|
src/backends/native/meta-frame-native.c | 63 ++
|
|
|
|
src/backends/native/meta-frame-native.h | 20 +
|
|
|
|
src/backends/native/meta-kms-crtc.c | 70 ++-
|
|
|
|
src/backends/native/meta-kms-crtc.h | 5 +
|
|
|
|
src/backends/native/meta-kms-impl-device-atomic.c | 2 +-
|
|
|
|
src/backends/native/meta-kms-impl-device.c | 191 ++++++-
|
|
|
|
src/backends/native/meta-kms-update.c | 25 +
|
|
|
|
src/backends/native/meta-kms-update.h | 9 +-
|
|
|
|
src/backends/native/meta-kms.c | 9 +
|
|
|
|
src/backends/native/meta-kms.h | 2 +
|
|
|
|
src/backends/native/meta-onscreen-native.c | 665 +++++++++++++++-------
|
|
|
|
src/backends/native/meta-onscreen-native.h | 2 +
|
|
|
|
src/backends/native/meta-renderer-native.c | 34 +-
|
|
|
|
src/backends/native/meta-renderer-view-native.c | 41 ++
|
|
|
|
src/core/util.c | 3 +
|
|
|
|
src/meta/meta-debug.h | 2 +
|
|
|
|
src/meta/util.h | 3 +
|
|
|
|
src/tests/meta-monitor-manager-test.c | 6 +
|
|
|
|
src/tests/native-kms-render.c | 106 +++-
|
|
|
|
35 files changed, 1530 insertions(+), 328 deletions(-)
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
2024-09-14 03:04:52 +00:00
|
|
|
index 30a319f604..3418cb86c0 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -42,7 +42,16 @@ enum
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static guint signals[N_SIGNALS];
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
-#define SYNC_DELAY_FALLBACK_FRACTION 0.875
|
2024-06-23 12:05:15 +00:00
|
|
|
+typedef enum
|
2023-10-10 05:21:14 +00:00
|
|
|
+{
|
2024-06-23 12:05:15 +00:00
|
|
|
+ TRIPLE_BUFFERING_MODE_NEVER,
|
|
|
|
+ TRIPLE_BUFFERING_MODE_AUTO,
|
|
|
|
+ TRIPLE_BUFFERING_MODE_ALWAYS,
|
|
|
|
+} TripleBufferingMode;
|
2023-10-10 05:21:14 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+static TripleBufferingMode triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO;
|
2023-10-10 05:21:14 +00:00
|
|
|
+
|
2024-09-14 03:04:52 +00:00
|
|
|
+#define SYNC_DELAY_FALLBACK_FRACTION 0.875f
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
#define MINIMUM_REFRESH_RATE 30.f
|
2024-09-14 03:04:52 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
@@ -70,8 +79,10 @@ typedef enum _ClutterFrameClockState
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_IDLE,
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW,
|
|
|
|
- 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_ONE_AND_SCHEDULED_NOW,
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO,
|
|
|
|
} ClutterFrameClockState;
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
struct _ClutterFrameClock
|
|
|
|
@@ -92,6 +103,7 @@ struct _ClutterFrameClock
|
|
|
|
ClutterFrameClockMode mode;
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
int64_t last_dispatch_time_us;
|
|
|
|
+ int64_t prev_last_dispatch_time_us;
|
|
|
|
int64_t last_dispatch_lateness_us;
|
|
|
|
int64_t last_presentation_time_us;
|
|
|
|
int64_t next_update_time_us;
|
|
|
|
@@ -113,6 +125,9 @@ struct _ClutterFrameClock
|
|
|
|
int64_t vblank_duration_us;
|
|
|
|
/* Last KMS buffer submission time. */
|
|
|
|
int64_t last_flip_time_us;
|
|
|
|
+ int64_t prev_last_flip_time_us;
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ ClutterFrameHint last_flip_hints;
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
/* Last time we promoted short-term maximum to long-term one */
|
|
|
|
int64_t longterm_promotion_us;
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -137,6 +152,8 @@ struct _ClutterFrameClock
|
|
|
|
|
|
|
|
int64_t last_dispatch_interval_us;
|
|
|
|
|
|
|
|
+ int64_t deadline_evasion_us;
|
|
|
|
+
|
|
|
|
char *output_name;
|
|
|
|
};
|
|
|
|
|
|
|
|
@@ -247,10 +264,6 @@ static void
|
2024-06-23 12:05:15 +00:00
|
|
|
maybe_update_longterm_max_duration_us (ClutterFrameClock *frame_clock,
|
|
|
|
ClutterFrameInfo *frame_info)
|
2023-10-10 05:21:14 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
- /* Do not update long-term max if there has been no measurement */
|
|
|
|
- if (!frame_clock->shortterm_max_update_duration_us)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
if ((frame_info->presentation_time - frame_clock->longterm_promotion_us) <
|
|
|
|
G_USEC_PER_SEC)
|
|
|
|
return;
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -277,6 +290,12 @@ void
|
2024-06-23 12:05:15 +00:00
|
|
|
clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
|
|
ClutterFrameInfo *frame_info)
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
+#ifdef CLUTTER_ENABLE_DEBUG
|
|
|
|
+ const char *debug_state =
|
|
|
|
+ frame_clock->state == CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO ?
|
|
|
|
+ "Triple buffering" : "Double buffering";
|
|
|
|
+#endif
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (ClutterFrameClockNotifyPresented,
|
|
|
|
"Clutter::FrameClock::presented()");
|
|
|
|
COGL_TRACE_DESCRIBE (ClutterFrameClockNotifyPresented,
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -366,22 +385,54 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->got_measurements_last_frame = FALSE;
|
|
|
|
|
|
|
|
- if (frame_info->cpu_time_before_buffer_swap_us != 0 &&
|
|
|
|
- frame_info->has_valid_gpu_rendering_duration)
|
|
|
|
+ if ((frame_info->cpu_time_before_buffer_swap_us != 0 &&
|
|
|
|
+ frame_info->has_valid_gpu_rendering_duration) ||
|
|
|
|
+ frame_clock->ever_got_measurements)
|
2023-11-09 07:48:47 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
int64_t dispatch_to_swap_us, swap_to_rendering_done_us, swap_to_flip_us;
|
|
|
|
+ int64_t dispatch_time_us = 0, flip_time_us = 0;
|
2024-08-14 08:34:14 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ switch (frame_clock->state)
|
|
|
|
+ {
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ g_warn_if_reached ();
|
|
|
|
+ G_GNUC_FALLTHROUGH;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ dispatch_time_us = frame_clock->last_dispatch_time_us;
|
|
|
|
+ flip_time_us = frame_clock->last_flip_time_us;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
+ dispatch_time_us = frame_clock->prev_last_dispatch_time_us;
|
|
|
|
+ flip_time_us = frame_clock->prev_last_flip_time_us;
|
|
|
|
+ break;
|
|
|
|
+ }
|
2024-08-14 08:34:14 +00:00
|
|
|
|
|
|
|
- dispatch_to_swap_us =
|
|
|
|
- frame_info->cpu_time_before_buffer_swap_us -
|
|
|
|
- frame_clock->last_dispatch_time_us;
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (frame_info->cpu_time_before_buffer_swap_us == 0)
|
|
|
|
+ {
|
2024-08-05 03:39:17 +00:00
|
|
|
+ /* User thread cursor-only updates with no "swap": we do know
|
|
|
|
+ * the combined time from dispatch to flip at least.
|
|
|
|
+ */
|
2024-06-23 12:05:15 +00:00
|
|
|
+ dispatch_to_swap_us = 0;
|
2024-08-05 03:39:17 +00:00
|
|
|
+ swap_to_flip_us = flip_time_us - dispatch_time_us;
|
2024-06-23 12:05:15 +00:00
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ dispatch_to_swap_us = frame_info->cpu_time_before_buffer_swap_us -
|
|
|
|
+ dispatch_time_us;
|
|
|
|
+ swap_to_flip_us = flip_time_us -
|
|
|
|
+ frame_info->cpu_time_before_buffer_swap_us;
|
|
|
|
+ }
|
|
|
|
swap_to_rendering_done_us =
|
|
|
|
frame_info->gpu_rendering_duration_ns / 1000;
|
|
|
|
- swap_to_flip_us =
|
|
|
|
- frame_clock->last_flip_time_us -
|
|
|
|
- frame_info->cpu_time_before_buffer_swap_us;
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
CLUTTER_NOTE (FRAME_TIMINGS,
|
|
|
|
- "update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
|
|
|
+ "%s: update2dispatch %ld µs, dispatch2swap %ld µs, swap2render %ld µs, swap2flip %ld µs",
|
|
|
|
+ debug_state,
|
|
|
|
frame_clock->last_dispatch_lateness_us,
|
|
|
|
dispatch_to_swap_us,
|
|
|
|
swap_to_rendering_done_us,
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -389,9 +440,10 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
|
|
|
|
|
|
frame_clock->shortterm_max_update_duration_us =
|
2024-06-23 12:05:15 +00:00
|
|
|
CLAMP (frame_clock->last_dispatch_lateness_us + dispatch_to_swap_us +
|
2024-08-14 08:34:14 +00:00
|
|
|
- MAX (swap_to_rendering_done_us, swap_to_flip_us),
|
2024-09-14 03:04:52 +00:00
|
|
|
+ MAX (swap_to_rendering_done_us, swap_to_flip_us) +
|
|
|
|
+ frame_clock->deadline_evasion_us,
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->shortterm_max_update_duration_us,
|
|
|
|
- frame_clock->refresh_interval_us);
|
|
|
|
+ 2 * frame_clock->refresh_interval_us);
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
maybe_update_longterm_max_duration_us (frame_clock, frame_info);
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -400,7 +452,8 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
2024-06-23 12:05:15 +00:00
|
|
|
else
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
- CLUTTER_NOTE (FRAME_TIMINGS, "update2dispatch %ld µs",
|
|
|
|
+ CLUTTER_NOTE (FRAME_TIMINGS, "%s: update2dispatch %ld µs",
|
|
|
|
+ debug_state,
|
|
|
|
frame_clock->last_dispatch_lateness_us);
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -418,11 +471,22 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
g_warn_if_reached ();
|
2024-05-08 13:03:56 +00:00
|
|
|
break;
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW;
|
|
|
|
+ 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;
|
|
|
|
}
|
|
|
|
}
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -440,26 +504,37 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
g_warn_if_reached ();
|
2024-05-08 13:03:56 +00:00
|
|
|
break;
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW;
|
|
|
|
+ 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;
|
|
|
|
}
|
2023-11-09 07:48:47 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
-static int64_t
|
|
|
|
-clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
|
|
|
+static gboolean
|
|
|
|
+clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock,
|
|
|
|
+ int64_t *max_render_time_us)
|
|
|
|
{
|
|
|
|
int64_t refresh_interval_us;
|
|
|
|
- int64_t max_render_time_us;
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
refresh_interval_us = frame_clock->refresh_interval_us;
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
if (!frame_clock->ever_got_measurements ||
|
|
|
|
G_UNLIKELY (clutter_paint_debug_flags &
|
|
|
|
CLUTTER_DEBUG_DISABLE_DYNAMIC_MAX_RENDER_TIME))
|
|
|
|
- return refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION;
|
|
|
|
+ return FALSE;
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
/* Max render time shows how early the frame clock needs to be dispatched
|
|
|
|
* to make it to the predicted next presentation time. It is an estimate of
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -473,15 +548,15 @@ clutter_frame_clock_compute_max_render_time_us (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
* - The duration of vertical blank.
|
|
|
|
* - A constant to account for variations in the above estimates.
|
|
|
|
*/
|
|
|
|
- max_render_time_us =
|
|
|
|
+ *max_render_time_us =
|
|
|
|
MAX (frame_clock->longterm_max_update_duration_us,
|
|
|
|
frame_clock->shortterm_max_update_duration_us) +
|
|
|
|
frame_clock->vblank_duration_us +
|
|
|
|
clutter_max_render_time_constant_us;
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- max_render_time_us = CLAMP (max_render_time_us, 0, refresh_interval_us);
|
|
|
|
+ *max_render_time_us = CLAMP (*max_render_time_us, 0, 2 * refresh_interval_us);
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- return max_render_time_us;
|
|
|
|
+ return TRUE;
|
|
|
|
}
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -496,7 +571,9 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
int64_t min_render_time_allowed_us;
|
|
|
|
int64_t max_render_time_allowed_us;
|
|
|
|
int64_t next_presentation_time_us;
|
|
|
|
+ int64_t next_smooth_presentation_time_us = 0;
|
|
|
|
int64_t next_update_time_us;
|
|
|
|
+ gboolean max_render_time_is_known;
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
now_us = g_get_monotonic_time ();
|
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -516,10 +593,13 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
min_render_time_allowed_us = refresh_interval_us / 2;
|
|
|
|
- max_render_time_allowed_us =
|
|
|
|
- clutter_frame_clock_compute_max_render_time_us (frame_clock);
|
|
|
|
|
|
|
|
- if (min_render_time_allowed_us > max_render_time_allowed_us)
|
|
|
|
+ max_render_time_is_known =
|
|
|
|
+ clutter_frame_clock_compute_max_render_time_us (frame_clock,
|
|
|
|
+ &max_render_time_allowed_us);
|
2022-04-02 05:32:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (max_render_time_is_known &&
|
|
|
|
+ min_render_time_allowed_us > max_render_time_allowed_us)
|
|
|
|
min_render_time_allowed_us = max_render_time_allowed_us;
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
/*
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -540,7 +620,29 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
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:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ next_smooth_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:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ next_smooth_presentation_time_us = last_presentation_time_us +
|
|
|
|
+ 2 * refresh_interval_us;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_warn_if_reached (); /* quad buffering would be a bug */
|
2024-06-23 12:05:15 +00:00
|
|
|
+ next_smooth_presentation_time_us = last_presentation_time_us +
|
|
|
|
+ 3 * refresh_interval_us;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ next_presentation_time_us = next_smooth_presentation_time_us;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* However, the last presentation could have happened more than a frame ago.
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -607,7 +709,7 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (frame_clock->last_presentation_flags & CLUTTER_FRAME_INFO_FLAG_VSYNC &&
|
|
|
|
- next_presentation_time_us != last_presentation_time_us + refresh_interval_us)
|
|
|
|
+ next_presentation_time_us != next_smooth_presentation_time_us)
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
/* There was an idle period since the last presentation, so there seems
|
|
|
|
* be no constantly updating actor. In this case it's best to start
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -619,6 +721,24 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
+ /* If the max render time isn't known then using the current value of
|
|
|
|
+ * next_presentation_time_us is suboptimal. Targeting always one frame
|
|
|
|
+ * prior to that we'd lose the ability to scale up to triple buffering
|
|
|
|
+ * on late presentation. But targeting two frames prior we would be
|
|
|
|
+ * always triple buffering even when not required.
|
|
|
|
+ * So the algorithm for deciding when to scale up to triple buffering
|
|
|
|
+ * in the absence of render time measurements is to simply target full
|
|
|
|
+ * frame rate. If we're keeping up then we'll stay double buffering. If
|
|
|
|
+ * we're not keeping up then this will switch us to triple buffering.
|
|
|
|
+ */
|
|
|
|
+ if (!max_render_time_is_known)
|
2024-05-08 13:03:56 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ max_render_time_allowed_us =
|
2024-08-05 03:39:17 +00:00
|
|
|
+ (int64_t) (refresh_interval_us * SYNC_DELAY_FALLBACK_FRACTION);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ next_presentation_time_us =
|
|
|
|
+ last_presentation_time_us + refresh_interval_us;
|
2024-05-08 13:03:56 +00:00
|
|
|
+ }
|
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
while (next_presentation_time_us - min_render_time_allowed_us < now_us)
|
|
|
|
next_presentation_time_us += refresh_interval_us;
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -650,7 +770,9 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock,
|
2024-03-24 04:54:32 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
refresh_interval_us = frame_clock->refresh_interval_us;
|
2024-03-24 04:54:32 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (frame_clock->last_presentation_time_us == 0)
|
|
|
|
+ if (frame_clock->last_presentation_time_us == 0 ||
|
|
|
|
+ !clutter_frame_clock_compute_max_render_time_us (frame_clock,
|
|
|
|
+ &max_render_time_allowed_us))
|
|
|
|
{
|
|
|
|
*out_next_update_time_us =
|
|
|
|
frame_clock->last_dispatch_time_us ?
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -663,9 +785,6 @@ calculate_next_variable_update_time_us (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-03-24 04:54:32 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- max_render_time_allowed_us =
|
|
|
|
- clutter_frame_clock_compute_max_render_time_us (frame_clock);
|
|
|
|
-
|
|
|
|
last_presentation_time_us = frame_clock->last_presentation_time_us;
|
|
|
|
next_presentation_time_us = last_presentation_time_us + refresh_interval_us;
|
2024-03-24 04:54:32 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -739,8 +858,17 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->pending_reschedule_now = 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_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
|
|
+ frame_clock->pending_reschedule_now = 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;
|
|
|
|
}
|
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -759,6 +887,25 @@ clutter_frame_clock_uninhibit (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
maybe_reschedule_update (frame_clock);
|
2024-03-24 04:54:32 +00:00
|
|
|
}
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+static gboolean
|
|
|
|
+want_triple_buffering (ClutterFrameClock *frame_clock)
|
|
|
|
+{
|
|
|
|
+ switch (triple_buffering_mode)
|
|
|
|
+ {
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_NEVER:
|
|
|
|
+ return FALSE;
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_AUTO:
|
|
|
|
+ return frame_clock->mode == CLUTTER_FRAME_CLOCK_MODE_FIXED &&
|
|
|
|
+ !(frame_clock->last_flip_hints &
|
|
|
|
+ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED);
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_ALWAYS:
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ g_assert_not_reached ();
|
|
|
|
+ return FALSE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
void
|
|
|
|
clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
2024-03-24 04:54:32 +00:00
|
|
|
{
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -776,11 +923,24 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW;
|
|
|
|
break;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
|
|
|
return;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ frame_clock->state =
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ if (want_triple_buffering (frame_clock))
|
|
|
|
+ {
|
|
|
|
+ frame_clock->state =
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ G_GNUC_FALLTHROUGH;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
|
|
|
frame_clock->pending_reschedule_now = TRUE;
|
|
|
|
return;
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -809,13 +969,17 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->next_update_time_us = next_update_time_us;
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW;
|
2024-03-24 04:54:32 +00:00
|
|
|
}
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
void
|
|
|
|
clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
|
|
{
|
|
|
|
int64_t next_update_time_us = -1;
|
|
|
|
+ TripleBufferingMode current_mode = triple_buffering_mode;
|
|
|
|
+
|
|
|
|
+ if (current_mode == TRIPLE_BUFFERING_MODE_AUTO &&
|
|
|
|
+ !want_triple_buffering (frame_clock))
|
|
|
|
+ current_mode = TRIPLE_BUFFERING_MODE_NEVER;
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
if (frame_clock->inhibit_count > 0)
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -831,12 +995,33 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
return;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
break;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
|
|
|
return;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ switch (current_mode)
|
|
|
|
+ {
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_NEVER:
|
|
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
|
|
+ return;
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_AUTO:
|
|
|
|
+ frame_clock->state =
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
|
|
+ break;
|
|
|
|
+ case TRIPLE_BUFFERING_MODE_ALWAYS:
|
|
|
|
+ next_update_time_us = g_get_monotonic_time ();
|
|
|
|
+ frame_clock->next_presentation_time_us = 0;
|
|
|
|
+ frame_clock->is_next_presentation_time_valid = FALSE;
|
|
|
|
+ frame_clock->state =
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
|
|
+ goto got_update_time;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -861,11 +1046,11 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
2024-06-23 12:05:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+got_update_time:
|
|
|
|
g_warn_if_fail (next_update_time_us != -1);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->next_update_time_us = next_update_time_us;
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
void
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -881,6 +1066,8 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock,
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
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:
|
2024-05-08 13:03:56 +00:00
|
|
|
break;
|
2024-06-23 12:05:15 +00:00
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -891,8 +1078,14 @@ clutter_frame_clock_set_mode (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->pending_reschedule_now = 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_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
|
|
+ frame_clock->pending_reschedule_now = TRUE;
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
break;
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -928,7 +1121,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_clock->refresh_interval_us;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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;
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -949,10 +1142,27 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
#endif
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ frame_clock->prev_last_dispatch_time_us = frame_clock->last_dispatch_time_us;
|
|
|
|
frame_clock->last_dispatch_time_us = time_us;
|
|
|
|
g_source_set_ready_time (frame_clock->source, -1);
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO;
|
|
|
|
+ break;
|
|
|
|
+ }
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_count = frame_clock->frame_count++;
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -983,26 +1193,36 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
result = iface->frame (frame_clock, frame, frame_clock->listener.user_data);
|
|
|
|
COGL_TRACE_END (ClutterFrameClockFrame);
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- switch (frame_clock->state)
|
|
|
|
+ switch (result)
|
|
|
|
{
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
- g_warn_if_reached ();
|
2024-08-14 08:34:14 +00:00
|
|
|
- break;
|
2024-06-23 12:05:15 +00:00
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
2024-08-14 08:34:14 +00:00
|
|
|
+ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
|
|
break;
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW:
|
|
|
|
+ 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_ONE_AND_SCHEDULED_NOW:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED_NOW;
|
|
|
|
+ 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;
|
|
|
|
}
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -1035,21 +1255,31 @@ frame_clock_source_dispatch (GSource *source,
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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->prev_last_flip_time_us = frame_clock->last_flip_time_us;
|
|
|
|
frame_clock->last_flip_time_us = flip_time_us;
|
|
|
|
+ frame_clock->last_flip_hints = hints;
|
2021-11-12 08:43:54 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
GString *
|
|
|
|
clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock)
|
|
|
|
{
|
|
|
|
+ int64_t max_render_time_us;
|
|
|
|
int64_t max_update_duration_us;
|
|
|
|
GString *string;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- string = g_string_new (NULL);
|
|
|
|
- g_string_append_printf (string, "Max render time: %ld µs",
|
|
|
|
- clutter_frame_clock_compute_max_render_time_us (frame_clock));
|
|
|
|
+ string = g_string_new ("Max render time: ");
|
|
|
|
+ if (!clutter_frame_clock_compute_max_render_time_us (frame_clock,
|
|
|
|
+ &max_render_time_us))
|
|
|
|
+ {
|
|
|
|
+ g_string_append (string, "unknown");
|
|
|
|
+ return string;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ g_string_append_printf (string, "%ld µs", max_render_time_us);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
if (frame_clock->got_measurements_last_frame)
|
|
|
|
g_string_append_printf (string, " =");
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -1216,8 +1446,6 @@ clutter_frame_clock_dispose (GObject *object)
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
ClutterFrameClock *frame_clock = CLUTTER_FRAME_CLOCK (object);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_warn_if_fail (frame_clock->state != CLUTTER_FRAME_CLOCK_STATE_DISPATCHING);
|
|
|
|
-
|
|
|
|
if (frame_clock->source)
|
|
|
|
{
|
|
|
|
g_signal_emit (frame_clock, signals[DESTROY], 0);
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -1241,6 +1469,15 @@ static void
|
2024-06-23 12:05:15 +00:00
|
|
|
clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
+ const char *mode_str;
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ mode_str = g_getenv ("MUTTER_DEBUG_TRIPLE_BUFFERING");
|
|
|
|
+ if (!g_strcmp0 (mode_str, "never"))
|
|
|
|
+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_NEVER;
|
|
|
|
+ else if (!g_strcmp0 (mode_str, "auto"))
|
|
|
|
+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_AUTO;
|
|
|
|
+ else if (!g_strcmp0 (mode_str, "always"))
|
|
|
|
+ triple_buffering_mode = TRIPLE_BUFFERING_MODE_ALWAYS;
|
|
|
|
|
|
|
|
object_class->dispose = clutter_frame_clock_dispose;
|
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -1253,3 +1490,10 @@ clutter_frame_clock_class_init (ClutterFrameClockClass *klass)
|
|
|
|
G_TYPE_NONE,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock,
|
|
|
|
+ int64_t deadline_evasion_us)
|
|
|
|
+{
|
|
|
|
+ frame_clock->deadline_evasion_us = deadline_evasion_us;
|
|
|
|
+}
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
|
2024-08-14 08:34:14 +00:00
|
|
|
index a7be5ef316..23e3357d3a 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-frame-clock.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame-clock.h
|
|
|
|
@@ -33,6 +33,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;
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
|
|
|
|
CLUTTER_EXPORT
|
|
|
|
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -102,7 +108,12 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
2024-06-23 12:05:15 +00:00
|
|
|
CLUTTER_EXPORT
|
|
|
|
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
-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);
|
2024-08-14 08:34:14 +00:00
|
|
|
+
|
|
|
|
+CLUTTER_EXPORT
|
|
|
|
+void clutter_frame_clock_set_deadline_evasion (ClutterFrameClock *frame_clock,
|
|
|
|
+ int64_t deadline_evasion_us);
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h
|
2024-07-30 08:28:28 +00:00
|
|
|
index ef66b874ed..ce140560a8 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-frame-private.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame-private.h
|
|
|
|
@@ -36,6 +36,7 @@ struct _ClutterFrame
|
|
|
|
|
|
|
|
gboolean has_result;
|
|
|
|
ClutterFrameResult result;
|
|
|
|
+ ClutterFrameHint hints;
|
|
|
|
};
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
CLUTTER_EXPORT
|
|
|
|
diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c
|
2024-07-30 08:28:28 +00:00
|
|
|
index 7436f9f182..53c289b2c5 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-frame.c
|
|
|
|
+++ b/clutter/clutter/clutter-frame.c
|
|
|
|
@@ -115,3 +115,16 @@ clutter_frame_set_result (ClutterFrame *frame,
|
|
|
|
frame->result = result;
|
|
|
|
frame->has_result = TRUE;
|
|
|
|
}
|
|
|
|
+
|
2024-05-08 13:03:56 +00:00
|
|
|
+void
|
2024-06-23 12:05:15 +00:00
|
|
|
+clutter_frame_set_hint (ClutterFrame *frame,
|
|
|
|
+ ClutterFrameHint hint)
|
2024-05-08 13:03:56 +00:00
|
|
|
+{
|
2024-06-23 12:05:15 +00:00
|
|
|
+ frame->hints |= hint;
|
|
|
|
+}
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ClutterFrameHint
|
|
|
|
+clutter_frame_get_hints (ClutterFrame *frame)
|
|
|
|
+{
|
|
|
|
+ return frame->hints;
|
2024-05-08 13:03:56 +00:00
|
|
|
+}
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h
|
2024-07-30 08:28:28 +00:00
|
|
|
index 34f0770bd7..c7b3d02acb 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-frame.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame.h
|
|
|
|
@@ -54,4 +54,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);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+CLUTTER_EXPORT
|
|
|
|
+ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame);
|
|
|
|
+
|
|
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterFrame, clutter_frame_unref)
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
2024-08-14 08:34:14 +00:00
|
|
|
index f5188e2acf..a89a520efb 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/clutter/clutter/clutter-stage-view.c
|
|
|
|
+++ b/clutter/clutter/clutter-stage-view.c
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -740,6 +740,10 @@ clutter_stage_view_schedule_update (ClutterStageView *view)
|
|
|
|
{
|
|
|
|
ClutterStageViewPrivate *priv =
|
|
|
|
clutter_stage_view_get_instance_private (view);
|
|
|
|
+ ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
|
|
|
|
+
|
|
|
|
+ if (view_class->schedule_update)
|
|
|
|
+ view_class->schedule_update (view);
|
|
|
|
|
|
|
|
clutter_frame_clock_schedule_update (priv->frame_clock);
|
|
|
|
}
|
|
|
|
@@ -898,14 +902,21 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
_clutter_stage_window_redraw_view (stage_window, view, frame);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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, frame);
|
|
|
|
|
|
|
|
if (_clutter_context_get_show_fps ())
|
|
|
|
end_frame_timing_measurement (view);
|
|
|
|
}
|
|
|
|
+ else
|
2024-05-08 13:03:56 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ clutter_frame_clock_record_flip (frame_clock,
|
|
|
|
+ g_get_monotonic_time (),
|
|
|
|
+ clutter_frame_get_hints (frame));
|
2024-05-08 13:03:56 +00:00
|
|
|
+ }
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
_clutter_stage_window_finish_frame (stage_window, view, frame);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h
|
|
|
|
index c0888f7f94..bdaa065c00 100644
|
|
|
|
--- a/clutter/clutter/clutter-stage-view.h
|
|
|
|
+++ b/clutter/clutter/clutter-stage-view.h
|
|
|
|
@@ -54,6 +54,8 @@ struct _ClutterStageViewClass
|
|
|
|
ClutterFrame * (* new_frame) (ClutterStageView *view);
|
|
|
|
|
|
|
|
ClutterPaintFlag (* get_default_paint_flags) (ClutterStageView *view);
|
|
|
|
+
|
|
|
|
+ void (* schedule_update) (ClutterStageView *view);
|
|
|
|
};
|
|
|
|
|
|
|
|
CLUTTER_EXPORT
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h
|
2024-08-05 03:39:17 +00:00
|
|
|
index 959a60533b..cfd45a6250 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/cogl/cogl/cogl-onscreen-private.h
|
|
|
|
+++ b/cogl/cogl/cogl-onscreen-private.h
|
|
|
|
@@ -78,4 +78,7 @@ COGL_EXPORT CoglFrameInfo *
|
|
|
|
cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
COGL_EXPORT CoglFrameInfo *
|
|
|
|
-cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen);
|
|
|
|
+cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen);
|
|
|
|
+
|
|
|
|
+COGL_EXPORT unsigned int
|
2024-08-05 03:39:17 +00:00
|
|
|
+cogl_onscreen_get_pending_frame_count (CoglOnscreen *onscreen);
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c
|
2024-08-28 11:31:05 +00:00
|
|
|
index e2b3a0b462..53ffa649bc 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/cogl/cogl/cogl-onscreen.c
|
|
|
|
+++ b/cogl/cogl/cogl-onscreen.c
|
2024-08-28 11:31:05 +00:00
|
|
|
@@ -514,6 +514,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen)
|
2024-06-23 12:05:15 +00:00
|
|
|
return g_queue_pop_head (&priv->pending_frame_infos);
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+unsigned int
|
2024-08-05 03:39:17 +00:00
|
|
|
+cogl_onscreen_get_pending_frame_count (CoglOnscreen *onscreen)
|
2024-06-23 12:05:15 +00:00
|
|
|
+{
|
|
|
|
+ CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ return g_queue_get_length (&priv->pending_frame_infos);
|
|
|
|
+}
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
CoglFrameClosure *
|
|
|
|
cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen,
|
|
|
|
CoglFrameCallback callback,
|
2024-09-14 03:04:52 +00:00
|
|
|
diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c
|
|
|
|
index cc023f705c..bc188e80e6 100644
|
|
|
|
--- a/src/backends/meta-egl.c
|
|
|
|
+++ b/src/backends/meta-egl.c
|
|
|
|
@@ -44,6 +44,11 @@ struct _MetaEgl
|
|
|
|
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
|
|
|
|
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
|
|
|
|
|
|
|
|
+ PFNEGLCREATESYNCPROC eglCreateSync;
|
|
|
|
+ PFNEGLDESTROYSYNCPROC eglDestroySync;
|
|
|
|
+ PFNEGLWAITSYNCPROC eglWaitSync;
|
|
|
|
+ PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
|
|
|
|
+
|
|
|
|
PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplayWL;
|
|
|
|
PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL;
|
|
|
|
|
|
|
|
@@ -1162,6 +1167,90 @@ meta_egl_query_display_attrib (MetaEgl *egl,
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
+gboolean
|
|
|
|
+meta_egl_create_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLenum type,
|
|
|
|
+ const EGLAttrib *attrib_list,
|
|
|
|
+ EGLSync *egl_sync,
|
|
|
|
+ GError **error)
|
|
|
|
+{
|
|
|
|
+ if (!is_egl_proc_valid (egl->eglCreateSync, error))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ EGLSync sync;
|
|
|
|
+
|
|
|
|
+ sync = egl->eglCreateSync (display, type, attrib_list);
|
|
|
|
+
|
|
|
|
+ if (sync == EGL_NO_SYNC)
|
|
|
|
+ {
|
|
|
|
+ set_egl_error (error);
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ *egl_sync = sync;
|
|
|
|
+
|
|
|
|
+ return TRUE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+gboolean
|
|
|
|
+meta_egl_destroy_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ GError **error)
|
|
|
|
+{
|
|
|
|
+ if (!is_egl_proc_valid (egl->eglDestroySync, error))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ if (!egl->eglDestroySync (display, sync))
|
|
|
|
+ {
|
|
|
|
+ set_egl_error (error);
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return TRUE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+gboolean
|
|
|
|
+meta_egl_wait_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ EGLint flags,
|
|
|
|
+ GError **error)
|
|
|
|
+{
|
|
|
|
+ if (!is_egl_proc_valid (egl->eglWaitSync, error))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ if (!egl->eglWaitSync (display, sync, flags))
|
|
|
|
+ {
|
|
|
|
+ set_egl_error (error);
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return TRUE;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+EGLint
|
|
|
|
+meta_egl_duplicate_native_fence_fd (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ GError **error)
|
|
|
|
+{
|
|
|
|
+ if (!is_egl_proc_valid (egl->eglDupNativeFenceFDANDROID, error))
|
|
|
|
+ return EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
|
|
|
+
|
|
|
|
+ EGLint fd = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
|
|
|
+
|
|
|
|
+ fd = egl->eglDupNativeFenceFDANDROID (display, sync);
|
|
|
|
+
|
|
|
|
+ if (fd == EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
|
|
|
+ {
|
|
|
|
+ set_egl_error (error);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return fd;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
#define GET_EGL_PROC_ADDR(proc) \
|
|
|
|
egl->proc = (void *) eglGetProcAddress (#proc);
|
|
|
|
|
|
|
|
@@ -1175,6 +1264,11 @@ meta_egl_constructed (GObject *object)
|
|
|
|
GET_EGL_PROC_ADDR (eglCreateImageKHR);
|
|
|
|
GET_EGL_PROC_ADDR (eglDestroyImageKHR);
|
|
|
|
|
|
|
|
+ GET_EGL_PROC_ADDR (eglCreateSync);
|
|
|
|
+ GET_EGL_PROC_ADDR (eglDestroySync);
|
|
|
|
+ GET_EGL_PROC_ADDR (eglWaitSync);
|
|
|
|
+ GET_EGL_PROC_ADDR (eglDupNativeFenceFDANDROID);
|
|
|
|
+
|
|
|
|
GET_EGL_PROC_ADDR (eglBindWaylandDisplayWL);
|
|
|
|
GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL);
|
|
|
|
|
|
|
|
diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h
|
|
|
|
index 8b955c90c3..9078b47948 100644
|
|
|
|
--- a/src/backends/meta-egl.h
|
|
|
|
+++ b/src/backends/meta-egl.h
|
|
|
|
@@ -276,3 +276,26 @@ gboolean meta_egl_query_display_attrib (MetaEgl *egl,
|
|
|
|
EGLint attribute,
|
|
|
|
EGLAttrib *value,
|
|
|
|
GError **error);
|
|
|
|
+
|
|
|
|
+gboolean meta_egl_create_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLenum type,
|
|
|
|
+ const EGLAttrib *attrib_list,
|
|
|
|
+ EGLSync *egl_sync,
|
|
|
|
+ GError **error);
|
|
|
|
+
|
|
|
|
+gboolean meta_egl_destroy_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ GError **error);
|
|
|
|
+
|
|
|
|
+gboolean meta_egl_wait_sync (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ EGLint flags,
|
|
|
|
+ GError **error);
|
|
|
|
+
|
|
|
|
+EGLint meta_egl_duplicate_native_fence_fd (MetaEgl *egl,
|
|
|
|
+ EGLDisplay display,
|
|
|
|
+ EGLSync sync,
|
|
|
|
+ GError **error);
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c
|
2024-07-30 08:28:28 +00:00
|
|
|
index 7aa24439d7..727e1a5f30 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/meta-stage-impl.c
|
|
|
|
+++ b/src/backends/meta-stage-impl.c
|
|
|
|
@@ -774,6 +774,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window,
|
|
|
|
{
|
|
|
|
g_autoptr (GError) error = NULL;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
if (meta_stage_impl_scanout_view (stage_impl,
|
|
|
|
stage_view,
|
|
|
|
scanout,
|
2024-08-14 08:34:14 +00:00
|
|
|
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
|
|
|
|
index 3498f922a3..8cb0e935a7 100644
|
|
|
|
--- a/src/backends/native/meta-crtc-kms.c
|
|
|
|
+++ b/src/backends/native/meta-crtc-kms.c
|
|
|
|
@@ -348,6 +348,15 @@ meta_crtc_kms_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|
|
|
return meta_kms_device_has_cursor_plane_for (kms_device, kms_crtc);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int64_t
|
|
|
|
+meta_crtc_kms_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
|
|
|
+{
|
|
|
|
+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc_native);
|
|
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
|
|
+
|
|
|
|
+ return meta_kms_crtc_get_deadline_evasion (kms_crtc);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
MetaKmsPlane *
|
|
|
|
meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms)
|
|
|
|
{
|
|
|
|
@@ -479,6 +488,7 @@ meta_crtc_kms_class_init (MetaCrtcKmsClass *klass)
|
|
|
|
|
|
|
|
crtc_native_class->is_transform_handled = meta_crtc_kms_is_transform_handled;
|
|
|
|
crtc_native_class->is_hw_cursor_supported = meta_crtc_kms_is_hw_cursor_supported;
|
|
|
|
+ crtc_native_class->get_deadline_evasion = meta_crtc_kms_get_deadline_evasion;
|
|
|
|
|
|
|
|
signals[GAMMA_LUT_CHANGED] =
|
|
|
|
g_signal_new ("gamma-lut-changed",
|
|
|
|
diff --git a/src/backends/native/meta-crtc-native.c b/src/backends/native/meta-crtc-native.c
|
|
|
|
index fc280f696e..80406a5033 100644
|
|
|
|
--- a/src/backends/native/meta-crtc-native.c
|
|
|
|
+++ b/src/backends/native/meta-crtc-native.c
|
|
|
|
@@ -39,6 +39,14 @@ meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|
|
|
return klass->is_hw_cursor_supported (crtc_native);
|
|
|
|
}
|
|
|
|
|
|
|
|
+int64_t
|
|
|
|
+meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
|
|
|
+{
|
|
|
|
+ MetaCrtcNativeClass *klass = META_CRTC_NATIVE_GET_CLASS (crtc_native);
|
|
|
|
+
|
|
|
|
+ return klass->get_deadline_evasion (crtc_native);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_crtc_native_init (MetaCrtcNative *crtc_native)
|
|
|
|
{
|
|
|
|
diff --git a/src/backends/native/meta-crtc-native.h b/src/backends/native/meta-crtc-native.h
|
|
|
|
index 3fb4bc7586..1f9a2ed46c 100644
|
|
|
|
--- a/src/backends/native/meta-crtc-native.h
|
|
|
|
+++ b/src/backends/native/meta-crtc-native.h
|
|
|
|
@@ -31,9 +31,12 @@ struct _MetaCrtcNativeClass
|
|
|
|
gboolean (* is_transform_handled) (MetaCrtcNative *crtc_native,
|
|
|
|
MetaMonitorTransform monitor_transform);
|
|
|
|
gboolean (* is_hw_cursor_supported) (MetaCrtcNative *crtc_native);
|
|
|
|
+ int64_t (* get_deadline_evasion) (MetaCrtcNative *crtc_native);
|
|
|
|
};
|
|
|
|
|
|
|
|
gboolean meta_crtc_native_is_transform_handled (MetaCrtcNative *crtc_native,
|
|
|
|
MetaMonitorTransform transform);
|
|
|
|
|
|
|
|
gboolean meta_crtc_native_is_hw_cursor_supported (MetaCrtcNative *crtc_native);
|
|
|
|
+
|
|
|
|
+int64_t meta_crtc_native_get_deadline_evasion (MetaCrtcNative *crtc_native);
|
|
|
|
diff --git a/src/backends/native/meta-crtc-virtual.c b/src/backends/native/meta-crtc-virtual.c
|
|
|
|
index 76165eb1bd..00b599c612 100644
|
|
|
|
--- a/src/backends/native/meta-crtc-virtual.c
|
|
|
|
+++ b/src/backends/native/meta-crtc-virtual.c
|
|
|
|
@@ -70,6 +70,12 @@ meta_crtc_virtual_is_hw_cursor_supported (MetaCrtcNative *crtc_native)
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int64_t
|
|
|
|
+meta_crtc_virtual_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_crtc_virtual_init (MetaCrtcVirtual *crtc_virtual)
|
|
|
|
{
|
|
|
|
@@ -89,4 +95,6 @@ meta_crtc_virtual_class_init (MetaCrtcVirtualClass *klass)
|
|
|
|
meta_crtc_virtual_is_transform_handled;
|
|
|
|
crtc_native_class->is_hw_cursor_supported =
|
|
|
|
meta_crtc_virtual_is_hw_cursor_supported;
|
|
|
|
+ crtc_native_class->get_deadline_evasion =
|
|
|
|
+ meta_crtc_virtual_get_deadline_evasion;
|
|
|
|
}
|
2024-08-05 03:39:17 +00:00
|
|
|
diff --git a/src/backends/native/meta-frame-native.c b/src/backends/native/meta-frame-native.c
|
|
|
|
index 146144db0e..8dc9dba9b9 100644
|
|
|
|
--- a/src/backends/native/meta-frame-native.c
|
|
|
|
+++ b/src/backends/native/meta-frame-native.c
|
|
|
|
@@ -27,7 +27,15 @@ struct _MetaFrameNative
|
|
|
|
{
|
|
|
|
ClutterFrame base;
|
|
|
|
|
|
|
|
+ MetaDrmBuffer *buffer;
|
|
|
|
+ CoglScanout *scanout;
|
|
|
|
+
|
|
|
|
MetaKmsUpdate *kms_update;
|
|
|
|
+
|
|
|
|
+ struct {
|
|
|
|
+ int n_rectangles;
|
|
|
|
+ int *rectangles; /* 4 x n_rectangles */
|
|
|
|
+ } damage;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -35,6 +43,10 @@ meta_frame_native_release (ClutterFrame *frame)
|
|
|
|
{
|
|
|
|
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
|
|
|
|
|
|
|
+ g_clear_pointer (&frame_native->damage.rectangles, g_free);
|
|
|
|
+ g_clear_object (&frame_native->buffer);
|
|
|
|
+ g_clear_object (&frame_native->scanout);
|
|
|
|
+
|
|
|
|
g_return_if_fail (!frame_native->kms_update);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -76,3 +88,54 @@ meta_frame_native_has_kms_update (MetaFrameNative *frame_native)
|
|
|
|
{
|
|
|
|
return !!frame_native->kms_update;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_frame_native_set_buffer (MetaFrameNative *frame_native,
|
|
|
|
+ MetaDrmBuffer *buffer)
|
|
|
|
+{
|
|
|
|
+ g_set_object (&frame_native->buffer, buffer);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+MetaDrmBuffer *
|
|
|
|
+meta_frame_native_get_buffer (MetaFrameNative *frame_native)
|
|
|
|
+{
|
|
|
|
+ return frame_native->buffer;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_frame_native_set_scanout (MetaFrameNative *frame_native,
|
|
|
|
+ CoglScanout *scanout)
|
|
|
|
+{
|
|
|
|
+ g_set_object (&frame_native->scanout, scanout);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+CoglScanout *
|
|
|
|
+meta_frame_native_get_scanout (MetaFrameNative *frame_native)
|
|
|
|
+{
|
|
|
|
+ return frame_native->scanout;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_frame_native_set_damage (MetaFrameNative *frame_native,
|
|
|
|
+ const int *rectangles,
|
|
|
|
+ int n_rectangles)
|
|
|
|
+{
|
|
|
|
+ size_t rectangles_size;
|
|
|
|
+
|
|
|
|
+ rectangles_size = n_rectangles * 4 * sizeof (int);
|
|
|
|
+
|
|
|
|
+ frame_native->damage.rectangles =
|
|
|
|
+ g_realloc (frame_native->damage.rectangles, rectangles_size);
|
|
|
|
+ memcpy (frame_native->damage.rectangles, rectangles, rectangles_size);
|
|
|
|
+ frame_native->damage.n_rectangles = n_rectangles;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+meta_frame_native_get_damage (MetaFrameNative *frame_native,
|
|
|
|
+ int **rectangles)
|
|
|
|
+{
|
|
|
|
+ if (rectangles)
|
|
|
|
+ *rectangles = frame_native->damage.rectangles;
|
|
|
|
+
|
|
|
|
+ return frame_native->damage.n_rectangles;
|
|
|
|
+}
|
|
|
|
diff --git a/src/backends/native/meta-frame-native.h b/src/backends/native/meta-frame-native.h
|
|
|
|
index f86d3b0b02..84bd43b8c6 100644
|
|
|
|
--- a/src/backends/native/meta-frame-native.h
|
|
|
|
+++ b/src/backends/native/meta-frame-native.h
|
|
|
|
@@ -17,6 +17,7 @@
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
+#include "backends/native/meta-backend-native-types.h"
|
|
|
|
#include "backends/native/meta-kms-types.h"
|
|
|
|
#include "clutter/clutter.h"
|
|
|
|
#include "core/util-private.h"
|
|
|
|
@@ -36,3 +37,22 @@ MetaKmsUpdate * meta_frame_native_steal_kms_update (MetaFrameNative *frame_nativ
|
|
|
|
|
|
|
|
META_EXPORT_TEST
|
|
|
|
gboolean meta_frame_native_has_kms_update (MetaFrameNative *frame_native);
|
|
|
|
+
|
|
|
|
+void meta_frame_native_set_buffer (MetaFrameNative *frame_native,
|
|
|
|
+ MetaDrmBuffer *buffer);
|
|
|
|
+
|
|
|
|
+MetaDrmBuffer * meta_frame_native_get_buffer (MetaFrameNative *frame_native);
|
|
|
|
+
|
|
|
|
+void meta_frame_native_set_scanout (MetaFrameNative *frame_native,
|
|
|
|
+ CoglScanout *scanout);
|
|
|
|
+
|
|
|
|
+CoglScanout * meta_frame_native_get_scanout (MetaFrameNative *frame_native);
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_frame_native_set_damage (MetaFrameNative *frame_native,
|
|
|
|
+ const int *rectangles,
|
|
|
|
+ int n_rectangles);
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+meta_frame_native_get_damage (MetaFrameNative *frame_native,
|
|
|
|
+ int **rectangles);
|
2024-08-14 08:34:14 +00:00
|
|
|
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
|
2024-09-14 03:04:52 +00:00
|
|
|
index a0872089a0..50edfcbe33 100644
|
2024-08-14 08:34:14 +00:00
|
|
|
--- a/src/backends/native/meta-kms-crtc.c
|
|
|
|
+++ b/src/backends/native/meta-kms-crtc.c
|
|
|
|
@@ -28,8 +28,7 @@
|
|
|
|
#include "backends/native/meta-kms-update-private.h"
|
|
|
|
#include "backends/native/meta-kms-utils.h"
|
|
|
|
|
|
|
|
-#define DEADLINE_EVASION_US 800
|
|
|
|
-#define DEADLINE_EVASION_WITH_KMS_TOPIC_US 1000
|
|
|
|
+#define DEADLINE_EVASION_CONSTANT_US 200
|
|
|
|
|
|
|
|
#define MINIMUM_REFRESH_RATE 30.f
|
|
|
|
|
|
|
|
@@ -50,6 +49,10 @@ struct _MetaKmsCrtc
|
|
|
|
MetaKmsCrtcState current_state;
|
|
|
|
|
|
|
|
MetaKmsCrtcPropTable prop_table;
|
|
|
|
+
|
|
|
|
+ int64_t shortterm_max_dispatch_duration_us;
|
|
|
|
+ int64_t deadline_evasion_us;
|
|
|
|
+ int64_t deadline_evasion_update_time_us;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
|
|
|
|
@@ -543,6 +546,33 @@ get_crtc_type_bitmask (MetaKmsCrtc *crtc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+maybe_update_deadline_evasion (MetaKmsCrtc *crtc,
|
|
|
|
+ int64_t next_presentation_time_us)
|
|
|
|
+{
|
|
|
|
+ /* Do not update long-term max if there has been no measurement */
|
|
|
|
+ if (!crtc->shortterm_max_dispatch_duration_us)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (next_presentation_time_us - crtc->deadline_evasion_update_time_us <
|
|
|
|
+ G_USEC_PER_SEC)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (crtc->deadline_evasion_us > crtc->shortterm_max_dispatch_duration_us)
|
|
|
|
+ {
|
|
|
|
+ /* Exponential drop-off toward the clamped short-term max */
|
|
|
|
+ crtc->deadline_evasion_us -=
|
|
|
|
+ (crtc->deadline_evasion_us - crtc->shortterm_max_dispatch_duration_us) / 2;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ crtc->deadline_evasion_us = crtc->shortterm_max_dispatch_duration_us;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ crtc->shortterm_max_dispatch_duration_us = 0;
|
|
|
|
+ crtc->deadline_evasion_update_time_us = next_presentation_time_us;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
gboolean
|
|
|
|
meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
|
|
|
int64_t *out_next_deadline_us,
|
|
|
|
@@ -610,10 +640,8 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
- if (meta_is_topic_enabled (META_DEBUG_KMS))
|
|
|
|
- deadline_evasion_us = DEADLINE_EVASION_WITH_KMS_TOPIC_US;
|
|
|
|
- else
|
|
|
|
- deadline_evasion_us = DEADLINE_EVASION_US;
|
|
|
|
+ deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
|
|
|
|
+ maybe_update_deadline_evasion (crtc, next_presentation_us);
|
|
|
|
|
|
|
|
vblank_duration_us = meta_calculate_drm_mode_vblank_duration_us (drm_mode);
|
|
|
|
next_deadline_us = next_presentation_us - (vblank_duration_us +
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -625,3 +653,33 @@ meta_kms_crtc_determine_deadline (MetaKmsCrtc *crtc,
|
2024-08-14 08:34:14 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
|
|
|
|
+ int64_t duration_us)
|
|
|
|
+{
|
|
|
|
+ int64_t refresh_interval_us;
|
|
|
|
+
|
|
|
|
+ if (duration_us <= crtc->shortterm_max_dispatch_duration_us)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ refresh_interval_us =
|
|
|
|
+ (int64_t) (0.5 + G_USEC_PER_SEC /
|
|
|
|
+ meta_calculate_drm_mode_refresh_rate (&crtc->current_state.drm_mode));
|
|
|
|
+
|
|
|
|
+ crtc->shortterm_max_dispatch_duration_us = MIN (duration_us, refresh_interval_us);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int64_t
|
|
|
|
+meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc)
|
|
|
|
+{
|
2024-09-14 03:04:52 +00:00
|
|
|
+ int64_t deadline_evasion_us;
|
|
|
|
+
|
|
|
|
+ deadline_evasion_us =
|
|
|
|
+ MAX (crtc->shortterm_max_dispatch_duration_us, crtc->deadline_evasion_us);
|
|
|
|
+
|
|
|
|
+ if (!deadline_evasion_us)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ return deadline_evasion_us + DEADLINE_EVASION_CONSTANT_US;
|
2024-08-14 08:34:14 +00:00
|
|
|
+}
|
|
|
|
diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h
|
|
|
|
index 580ee9a89c..b293f8e7cc 100644
|
|
|
|
--- a/src/backends/native/meta-kms-crtc.h
|
|
|
|
+++ b/src/backends/native/meta-kms-crtc.h
|
|
|
|
@@ -65,3 +65,8 @@ int meta_kms_crtc_get_idx (MetaKmsCrtc *crtc);
|
|
|
|
|
|
|
|
META_EXPORT_TEST
|
|
|
|
gboolean meta_kms_crtc_is_active (MetaKmsCrtc *crtc);
|
|
|
|
+
|
|
|
|
+void meta_kms_crtc_update_shortterm_max_dispatch_duration (MetaKmsCrtc *crtc,
|
|
|
|
+ int64_t duration_us);
|
|
|
|
+
|
|
|
|
+int64_t meta_kms_crtc_get_deadline_evasion (MetaKmsCrtc *crtc);
|
2024-09-14 03:04:52 +00:00
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c
|
|
|
|
index 7812ec0421..488d24ac5d 100644
|
|
|
|
--- a/src/backends/native/meta-kms-impl-device-atomic.c
|
|
|
|
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
|
|
|
|
@@ -643,7 +643,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
- if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT)
|
|
|
|
+ if (plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC)
|
|
|
|
{
|
|
|
|
int signaled_sync_file;
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
|
2024-09-15 05:07:15 +00:00
|
|
|
index e48cffc4f1..a0de4158ac 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/native/meta-kms-impl-device.c
|
|
|
|
+++ b/src/backends/native/meta-kms-impl-device.c
|
2024-08-14 08:34:14 +00:00
|
|
|
@@ -39,6 +39,7 @@
|
|
|
|
#include "backends/native/meta-kms-plane-private.h"
|
|
|
|
#include "backends/native/meta-kms-plane.h"
|
|
|
|
#include "backends/native/meta-kms-private.h"
|
|
|
|
+#include "backends/native/meta-kms-utils.h"
|
|
|
|
#include "backends/native/meta-thread-private.h"
|
|
|
|
|
|
|
|
#include "meta-default-modes.h"
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -71,9 +72,17 @@ typedef struct _CrtcDeadline
|
2024-08-14 08:34:14 +00:00
|
|
|
GSource *source;
|
|
|
|
gboolean armed;
|
|
|
|
gboolean is_deadline_page_flip;
|
|
|
|
+ int64_t expected_deadline_time_us;
|
|
|
|
int64_t expected_presentation_time_us;
|
|
|
|
gboolean has_expected_presentation_time;
|
|
|
|
} deadline;
|
2024-09-14 03:04:52 +00:00
|
|
|
+
|
|
|
|
+ struct {
|
|
|
|
+ MetaKmsUpdate *kms_update;
|
|
|
|
+ MetaKmsUpdateFlag flags;
|
|
|
|
+ MetaKmsCrtc *latch_crtc;
|
|
|
|
+ GSource *source;
|
|
|
|
+ } submitted_update;
|
|
|
|
} CrtcFrame;
|
|
|
|
|
|
|
|
typedef enum _MetaDeadlineTimerState
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1167,6 +1176,7 @@ arm_crtc_frame_deadline_timer (CrtcFrame *crtc_frame,
|
2024-08-14 08:34:14 +00:00
|
|
|
timerfd_settime (crtc_frame->deadline.timer_fd,
|
|
|
|
TFD_TIMER_ABSTIME, &its, NULL);
|
|
|
|
|
|
|
|
+ crtc_frame->deadline.expected_deadline_time_us = next_deadline_us;
|
|
|
|
crtc_frame->deadline.expected_presentation_time_us = next_presentation_us;
|
|
|
|
crtc_frame->deadline.has_expected_presentation_time = next_presentation_us != 0;
|
|
|
|
crtc_frame->deadline.armed = TRUE;
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1199,7 +1209,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
2024-08-14 08:34:14 +00:00
|
|
|
CrtcFrame *crtc_frame = user_data;
|
|
|
|
|
|
|
|
if (crtc_frame->deadline.is_deadline_page_flip &&
|
|
|
|
- meta_is_topic_enabled (META_DEBUG_KMS))
|
|
|
|
+ meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
|
|
|
{
|
|
|
|
struct timeval page_flip_timeval;
|
|
|
|
int64_t presentation_time_us;
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1212,7 +1222,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
2024-08-14 08:34:14 +00:00
|
|
|
|
|
|
|
if (crtc_frame->deadline.has_expected_presentation_time)
|
|
|
|
{
|
|
|
|
- meta_topic (META_DEBUG_KMS,
|
|
|
|
+ meta_topic (META_DEBUG_KMS_DEADLINE,
|
|
|
|
"Deadline page flip presentation time: %" G_GINT64_FORMAT " us, "
|
|
|
|
"expected %" G_GINT64_FORMAT " us "
|
|
|
|
"(diff: %" G_GINT64_FORMAT ")",
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1223,7 +1233,7 @@ crtc_page_flip_feedback_flipped (MetaKmsCrtc *crtc,
|
2024-08-14 08:34:14 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
- meta_topic (META_DEBUG_KMS,
|
|
|
|
+ meta_topic (META_DEBUG_KMS_DEADLINE,
|
|
|
|
"Deadline page flip presentation time: %" G_GINT64_FORMAT " us",
|
|
|
|
presentation_time_us);
|
|
|
|
}
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1392,11 +1402,16 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
|
2024-08-14 08:34:14 +00:00
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
CrtcFrame *crtc_frame = user_data;
|
|
|
|
- MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
|
|
|
|
+ MetaKmsCrtc *crtc = crtc_frame->crtc;
|
|
|
|
+ MetaKmsDevice *device = meta_kms_crtc_get_device (crtc);
|
|
|
|
MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
|
|
|
g_autoptr (MetaKmsFeedback) feedback = NULL;
|
|
|
|
uint64_t timer_value;
|
|
|
|
ssize_t ret;
|
|
|
|
+ int64_t dispatch_time_us = 0, update_done_time_us, interval_us;
|
|
|
|
+
|
|
|
|
+ if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
|
|
|
+ dispatch_time_us = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
ret = read (crtc_frame->deadline.timer_fd,
|
|
|
|
&timer_value,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1418,6 +1433,36 @@ crtc_frame_deadline_dispatch (MetaThreadImpl *thread_impl,
|
2024-08-14 08:34:14 +00:00
|
|
|
crtc_frame->crtc,
|
|
|
|
g_steal_pointer (&crtc_frame->pending_update),
|
|
|
|
META_KMS_UPDATE_FLAG_NONE);
|
|
|
|
+
|
|
|
|
+ update_done_time_us = g_get_monotonic_time ();
|
|
|
|
+ /* Calculate how long after the planned start of deadline dispatch it finished */
|
|
|
|
+ interval_us = update_done_time_us - crtc_frame->deadline.expected_deadline_time_us;
|
|
|
|
+
|
|
|
|
+ if (meta_is_topic_enabled (META_DEBUG_KMS_DEADLINE))
|
|
|
|
+ {
|
|
|
|
+ int64_t deadline_evasion_us, lateness_us, duration_us, vblank_delta_us;
|
|
|
|
+
|
|
|
|
+ deadline_evasion_us = meta_kms_crtc_get_deadline_evasion (crtc);
|
|
|
|
+ lateness_us = dispatch_time_us -
|
|
|
|
+ crtc_frame->deadline.expected_deadline_time_us;
|
|
|
|
+ duration_us = update_done_time_us - dispatch_time_us;
|
|
|
|
+ vblank_delta_us = deadline_evasion_us - lateness_us - duration_us;
|
|
|
|
+
|
|
|
|
+ meta_topic (META_DEBUG_KMS_DEADLINE,
|
|
|
|
+ "Deadline evasion %3"G_GINT64_FORMAT "µs, "
|
|
|
|
+ "dispatch started %3"G_GINT64_FORMAT "µs %s and "
|
|
|
|
+ "completed %3"G_GINT64_FORMAT "µs after that, "
|
|
|
|
+ "%3"G_GINT64_FORMAT "µs %s start of vblank.",
|
|
|
|
+ deadline_evasion_us,
|
|
|
|
+ ABS (lateness_us),
|
|
|
|
+ lateness_us >= 0 ? "late" : "early",
|
|
|
|
+ duration_us,
|
|
|
|
+ ABS (vblank_delta_us),
|
|
|
|
+ vblank_delta_us >= 0 ? "before" : "after");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ meta_kms_crtc_update_shortterm_max_dispatch_duration (crtc, interval_us);
|
|
|
|
+
|
|
|
|
if (meta_kms_feedback_did_pass (feedback))
|
|
|
|
crtc_frame->deadline.is_deadline_page_flip = TRUE;
|
|
|
|
disarm_crtc_frame_deadline_timer (crtc_frame);
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1431,6 +1476,8 @@ crtc_frame_free (CrtcFrame *crtc_frame)
|
2024-09-14 03:04:52 +00:00
|
|
|
g_clear_fd (&crtc_frame->deadline.timer_fd, NULL);
|
|
|
|
g_clear_pointer (&crtc_frame->deadline.source, g_source_destroy);
|
|
|
|
g_clear_pointer (&crtc_frame->pending_update, meta_kms_update_free);
|
|
|
|
+ g_clear_pointer (&crtc_frame->submitted_update.kms_update, meta_kms_update_free);
|
|
|
|
+ g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
|
|
|
g_free (crtc_frame);
|
|
|
|
}
|
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1539,6 +1586,79 @@ queue_update (MetaKmsImplDevice *impl_device,
|
2024-09-14 03:04:52 +00:00
|
|
|
}
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
+static gpointer
|
|
|
|
+meta_kms_impl_device_update_ready (MetaThreadImpl *impl,
|
|
|
|
+ gpointer user_data,
|
|
|
|
+ GError **error)
|
|
|
|
+{
|
|
|
|
+ CrtcFrame *crtc_frame = user_data;
|
|
|
|
+ MetaKmsDevice *device = meta_kms_crtc_get_device (crtc_frame->crtc);
|
|
|
|
+ MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
|
|
|
|
+ MetaKmsImplDevicePrivate *priv =
|
|
|
|
+ meta_kms_impl_device_get_instance_private (impl_device);
|
|
|
|
+ MetaKmsUpdate *update;
|
|
|
|
+ MetaKmsCrtc *latch_crtc;
|
|
|
|
+ MetaKmsFeedback *feedback;
|
|
|
|
+
|
|
|
|
+ meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
|
|
|
+
|
|
|
|
+ g_clear_pointer (&crtc_frame->submitted_update.source, g_source_destroy);
|
|
|
|
+
|
|
|
|
+ update = g_steal_pointer (&crtc_frame->submitted_update.kms_update);
|
|
|
|
+ meta_kms_update_realize (update, impl_device);
|
|
|
|
+
|
|
|
|
+ latch_crtc = g_steal_pointer (&crtc_frame->submitted_update.latch_crtc);
|
|
|
|
+
|
|
|
|
+ if (crtc_frame->pending_page_flip &&
|
|
|
|
+ !meta_kms_update_get_mode_sets (update))
|
|
|
|
+ {
|
|
|
|
+ g_assert (latch_crtc);
|
|
|
|
+
|
|
|
|
+ meta_topic (META_DEBUG_KMS,
|
|
|
|
+ "Queuing update on CRTC %u (%s): pending page flip",
|
|
|
|
+ meta_kms_crtc_get_id (latch_crtc),
|
|
|
|
+ priv->path);
|
|
|
|
+
|
|
|
|
+ queue_update (impl_device, crtc_frame, update);
|
|
|
|
+ return GINT_TO_POINTER (TRUE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (crtc_frame->pending_update)
|
|
|
|
+ {
|
|
|
|
+ meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
|
|
|
+ meta_kms_update_free (update);
|
|
|
|
+ update = g_steal_pointer (&crtc_frame->pending_update);
|
|
|
|
+ disarm_crtc_frame_deadline_timer (crtc_frame);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ meta_kms_device_handle_flush (priv->device, latch_crtc);
|
|
|
|
+
|
|
|
|
+ feedback = do_process (impl_device, latch_crtc, update, crtc_frame->submitted_update.flags);
|
2024-08-14 08:34:14 +00:00
|
|
|
+
|
|
|
|
+ if (meta_kms_feedback_did_pass (feedback) &&
|
|
|
|
+ crtc_frame->deadline.armed)
|
|
|
|
+ disarm_crtc_frame_deadline_timer (crtc_frame);
|
|
|
|
+
|
2024-09-14 03:04:52 +00:00
|
|
|
+ meta_kms_feedback_unref (feedback);
|
|
|
|
+
|
|
|
|
+ return GINT_TO_POINTER (TRUE);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static gboolean
|
|
|
|
+is_fd_readable (int fd)
|
|
|
|
+{
|
|
|
|
+ GPollFD poll_fd;
|
|
|
|
+
|
|
|
|
+ poll_fd.fd = fd;
|
|
|
|
+ poll_fd.events = G_IO_IN;
|
|
|
|
+ poll_fd.revents = 0;
|
|
|
|
+
|
|
|
|
+ if (!g_poll (&poll_fd, 1, 0))
|
|
|
|
+ return FALSE;
|
|
|
|
+
|
|
|
|
+ return (poll_fd.revents & (G_IO_IN | G_IO_NVAL)) != 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
void
|
|
|
|
meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
|
|
|
MetaKmsUpdate *update,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1546,10 +1666,15 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
2024-09-14 03:04:52 +00:00
|
|
|
{
|
|
|
|
MetaKmsImplDevicePrivate *priv =
|
|
|
|
meta_kms_impl_device_get_instance_private (impl_device);
|
|
|
|
+ MetaKmsImpl *kms_impl = meta_kms_impl_device_get_impl (impl_device);
|
|
|
|
+ MetaThreadImpl *thread_impl = META_THREAD_IMPL (kms_impl);
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
MetaKmsCrtc *latch_crtc;
|
|
|
|
CrtcFrame *crtc_frame;
|
|
|
|
MetaKmsFeedback *feedback;
|
|
|
|
+ g_autoptr (GSource) source = NULL;
|
|
|
|
+ g_autofree char *name = NULL;
|
|
|
|
+ int sync_fd = -1;
|
|
|
|
|
|
|
|
meta_assert_in_kms_impl (meta_kms_impl_get_kms (priv->impl));
|
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1570,38 +1695,58 @@ meta_kms_impl_device_handle_update (MetaKmsImplDevice *impl_device,
|
2024-09-14 03:04:52 +00:00
|
|
|
if (!ensure_device_file (impl_device, &error))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
- meta_kms_update_realize (update, impl_device);
|
|
|
|
-
|
|
|
|
crtc_frame = ensure_crtc_frame (impl_device, latch_crtc);
|
|
|
|
|
|
|
|
+ if (crtc_frame->submitted_update.kms_update)
|
|
|
|
+ {
|
|
|
|
+ g_set_error (&error, G_IO_ERROR, G_IO_ERROR_PENDING,
|
|
|
|
+ "Previously-submitted update wasn't ready yet");
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
crtc_frame->await_flush = FALSE;
|
|
|
|
+ crtc_frame->submitted_update.kms_update = update;
|
|
|
|
+ crtc_frame->submitted_update.flags = flags;
|
|
|
|
+ crtc_frame->submitted_update.latch_crtc = latch_crtc;
|
|
|
|
|
|
|
|
- if (crtc_frame->pending_page_flip &&
|
|
|
|
- !meta_kms_update_get_mode_sets (update))
|
|
|
|
+ if (is_using_deadline_timer (impl_device))
|
|
|
|
+ sync_fd = meta_kms_update_get_sync_fd (update);
|
|
|
|
+
|
|
|
|
+ if (sync_fd >= 0)
|
|
|
|
{
|
|
|
|
- g_assert (latch_crtc);
|
|
|
|
+ GList *l;
|
|
|
|
|
|
|
|
- meta_topic (META_DEBUG_KMS,
|
|
|
|
- "Queuing update on CRTC %u (%s): pending page flip",
|
|
|
|
- meta_kms_crtc_get_id (latch_crtc),
|
|
|
|
- priv->path);
|
|
|
|
+ for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
|
|
|
|
+ {
|
|
|
|
+ MetaKmsPlaneAssignment *assignment = l->data;
|
|
|
|
|
|
|
|
- queue_update (impl_device, crtc_frame, update);
|
|
|
|
- return;
|
|
|
|
+ assignment->flags |= META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC;
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
- if (crtc_frame->pending_update)
|
|
|
|
+ if (sync_fd < 0 ||
|
|
|
|
+ is_fd_readable (sync_fd))
|
|
|
|
{
|
|
|
|
- meta_kms_update_merge_from (crtc_frame->pending_update, update);
|
|
|
|
- meta_kms_update_free (update);
|
|
|
|
- update = g_steal_pointer (&crtc_frame->pending_update);
|
|
|
|
- disarm_crtc_frame_deadline_timer (crtc_frame);
|
|
|
|
+ meta_kms_impl_device_update_ready (thread_impl,
|
|
|
|
+ crtc_frame,
|
|
|
|
+ NULL);
|
|
|
|
+ return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- meta_kms_device_handle_flush (priv->device, latch_crtc);
|
|
|
|
+ source = meta_thread_impl_register_fd (thread_impl,
|
|
|
|
+ sync_fd,
|
|
|
|
+ meta_kms_impl_device_update_ready,
|
|
|
|
+ crtc_frame);
|
|
|
|
|
|
|
|
- feedback = do_process (impl_device, latch_crtc, update, flags);
|
|
|
|
- meta_kms_feedback_unref (feedback);
|
|
|
|
+ name = g_strdup_printf ("[mutter] KMS update sync_fd (crtc: %u, %s)",
|
|
|
|
+ meta_kms_crtc_get_id (latch_crtc),
|
|
|
|
+ priv->path);
|
|
|
|
+ g_source_set_name (source, name);
|
|
|
|
+ g_source_set_priority (source, G_PRIORITY_HIGH + 1);
|
|
|
|
+ g_source_set_can_recurse (source, FALSE);
|
|
|
|
+ g_source_set_ready_time (source, -1);
|
|
|
|
+
|
|
|
|
+ crtc_frame->submitted_update.source = source;
|
2024-08-14 08:34:14 +00:00
|
|
|
return;
|
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
err:
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
|
2024-09-15 05:07:15 +00:00
|
|
|
index fc605bec18..a5da81f0c5 100644
|
2024-09-14 03:04:52 +00:00
|
|
|
--- a/src/backends/native/meta-kms-update.c
|
|
|
|
+++ b/src/backends/native/meta-kms-update.c
|
|
|
|
@@ -20,6 +20,8 @@
|
|
|
|
#include "backends/native/meta-kms-update.h"
|
|
|
|
#include "backends/native/meta-kms-update-private.h"
|
|
|
|
|
|
|
|
+#include <glib/gstdio.h>
|
|
|
|
+
|
|
|
|
#include "backends/meta-display-config-shared.h"
|
|
|
|
#include "backends/native/meta-kms-connector.h"
|
|
|
|
#include "backends/native/meta-kms-crtc.h"
|
|
|
|
@@ -51,6 +53,8 @@ struct _MetaKmsUpdate
|
|
|
|
gboolean needs_modeset;
|
|
|
|
|
|
|
|
MetaKmsImplDevice *impl_device;
|
|
|
|
+
|
|
|
|
+ int sync_fd;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
@@ -1136,6 +1140,8 @@ meta_kms_update_merge_from (MetaKmsUpdate *update,
|
|
|
|
merge_custom_page_flip_from (update, other_update);
|
|
|
|
merge_page_flip_listeners_from (update, other_update);
|
|
|
|
merge_result_listeners_from (update, other_update);
|
|
|
|
+
|
|
|
|
+ meta_kms_update_set_sync_fd (update, g_steal_fd (&other_update->sync_fd));
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
@@ -1152,6 +1158,7 @@ meta_kms_update_new (MetaKmsDevice *device)
|
|
|
|
update = g_new0 (MetaKmsUpdate, 1);
|
|
|
|
update->device = device;
|
|
|
|
update->is_latchable = TRUE;
|
|
|
|
+ update->sync_fd = -1;
|
|
|
|
|
|
|
|
return update;
|
|
|
|
}
|
|
|
|
@@ -1175,6 +1182,7 @@ meta_kms_update_free (MetaKmsUpdate *update)
|
|
|
|
g_list_free_full (update->crtc_color_updates,
|
|
|
|
(GDestroyNotify) meta_kms_crtc_color_updates_free);
|
|
|
|
g_clear_pointer (&update->custom_page_flip, meta_kms_custom_page_flip_free);
|
|
|
|
+ g_clear_fd (&update->sync_fd, NULL);
|
|
|
|
|
|
|
|
g_free (update);
|
|
|
|
}
|
|
|
|
@@ -1200,6 +1208,23 @@ meta_kms_update_get_latch_crtc (MetaKmsUpdate *update)
|
|
|
|
return update->latch_crtc;
|
|
|
|
}
|
|
|
|
|
|
|
|
+int
|
|
|
|
+meta_kms_update_get_sync_fd (MetaKmsUpdate *update)
|
|
|
|
+{
|
|
|
|
+ return update->sync_fd;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_kms_update_set_sync_fd (MetaKmsUpdate *update,
|
|
|
|
+ int sync_fd)
|
|
|
|
+{
|
|
|
|
+ if (update->sync_fd == sync_fd)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ g_clear_fd (&update->sync_fd, NULL);
|
|
|
|
+ update->sync_fd = sync_fd;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
gboolean
|
|
|
|
meta_kms_update_is_empty (MetaKmsUpdate *update)
|
|
|
|
{
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
|
|
|
|
index 1951c80f60..ebb50cbaa8 100644
|
|
|
|
--- a/src/backends/native/meta-kms-update.h
|
|
|
|
+++ b/src/backends/native/meta-kms-update.h
|
|
|
|
@@ -39,7 +39,7 @@ typedef enum _MetaKmsAssignPlaneFlag
|
|
|
|
META_KMS_ASSIGN_PLANE_FLAG_NONE = 0,
|
|
|
|
META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0,
|
|
|
|
META_KMS_ASSIGN_PLANE_FLAG_ALLOW_FAIL = 1 << 1,
|
|
|
|
- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT = 1 << 2,
|
|
|
|
+ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC = 1 << 2,
|
|
|
|
} MetaKmsAssignPlaneFlag;
|
|
|
|
|
|
|
|
struct _MetaKmsPageFlipListenerVtable
|
|
|
|
@@ -157,6 +157,13 @@ void meta_kms_update_set_crtc_gamma (MetaKmsUpdate *update,
|
|
|
|
MetaKmsCrtc *crtc,
|
|
|
|
const MetaGammaLut *gamma);
|
|
|
|
|
|
|
|
+int
|
|
|
|
+meta_kms_update_get_sync_fd (MetaKmsUpdate *update);
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_kms_update_set_sync_fd (MetaKmsUpdate *update,
|
|
|
|
+ int sync_fd);
|
|
|
|
+
|
|
|
|
void meta_kms_plane_assignment_set_fb_damage (MetaKmsPlaneAssignment *plane_assignment,
|
|
|
|
const int *rectangles,
|
|
|
|
int n_rectangles);
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
|
2024-09-15 05:07:15 +00:00
|
|
|
index d989337a10..4253a2adc8 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/native/meta-kms.c
|
|
|
|
+++ b/src/backends/native/meta-kms.c
|
|
|
|
@@ -63,6 +63,8 @@ struct _MetaKms
|
|
|
|
int kernel_thread_inhibit_count;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
MetaKmsCursorManager *cursor_manager;
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ gboolean shutting_down;
|
|
|
|
};
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
G_DEFINE_TYPE (MetaKms, meta_kms, META_TYPE_THREAD)
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -339,6 +341,12 @@ meta_kms_create_device (MetaKms *kms,
|
|
|
|
return device;
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+gboolean
|
|
|
|
+meta_kms_is_shutting_down (MetaKms *kms)
|
2024-05-08 13:03:56 +00:00
|
|
|
+{
|
2024-06-23 12:05:15 +00:00
|
|
|
+ return kms->shutting_down;
|
|
|
|
+}
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-09-14 03:04:52 +00:00
|
|
|
static gpointer
|
|
|
|
prepare_shutdown_in_impl (MetaThreadImpl *thread_impl,
|
|
|
|
gpointer user_data,
|
|
|
|
@@ -354,6 +362,7 @@ static void
|
|
|
|
on_prepare_shutdown (MetaBackend *backend,
|
|
|
|
MetaKms *kms)
|
2024-06-23 12:05:15 +00:00
|
|
|
{
|
2024-09-14 03:04:52 +00:00
|
|
|
+ kms->shutting_down = TRUE;
|
|
|
|
meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL);
|
|
|
|
meta_thread_flush_callbacks (META_THREAD (kms));
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h
|
2024-09-15 05:07:15 +00:00
|
|
|
index 057c7a2348..0d6986529c 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/native/meta-kms.h
|
|
|
|
+++ b/src/backends/native/meta-kms.h
|
|
|
|
@@ -60,6 +60,8 @@ MetaKmsDevice * meta_kms_create_device (MetaKms *kms,
|
|
|
|
MetaKmsDeviceFlag flags,
|
|
|
|
GError **error);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+gboolean meta_kms_is_shutting_down (MetaKms *kms);
|
|
|
|
+
|
|
|
|
MetaKms * meta_kms_new (MetaBackend *backend,
|
|
|
|
MetaKmsFlags flags,
|
|
|
|
GError **error);
|
2024-05-08 13:03:56 +00:00
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
2024-09-15 05:07:15 +00:00
|
|
|
index 34709dccf1..c9162d31b8 100644
|
2024-05-08 13:03:56 +00:00
|
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -29,6 +29,7 @@
|
|
|
|
|
|
|
|
#include "backends/native/meta-onscreen-native.h"
|
|
|
|
|
|
|
|
+#include <glib/gstdio.h>
|
|
|
|
#include <drm_fourcc.h>
|
|
|
|
|
|
|
|
#include "backends/meta-egl-ext.h"
|
|
|
|
@@ -76,7 +77,7 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
2024-05-08 13:03:56 +00:00
|
|
|
|
|
|
|
struct {
|
|
|
|
MetaDrmBufferDumb *current_dumb_fb;
|
|
|
|
- MetaDrmBufferDumb *dumb_fbs[2];
|
|
|
|
+ MetaDrmBufferDumb *dumb_fbs[3];
|
|
|
|
} cpu;
|
2021-11-12 08:43:54 +00:00
|
|
|
|
2024-05-08 13:03:56 +00:00
|
|
|
gboolean noted_primary_gpu_copy_ok;
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -102,12 +103,13 @@ struct _MetaOnscreenNative
|
2024-08-05 03:39:17 +00:00
|
|
|
|
|
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
|
|
|
|
|
|
+ ClutterFrame *presented_frame;
|
|
|
|
+ ClutterFrame *posted_frame;
|
|
|
|
+ ClutterFrame *stalled_frame;
|
|
|
|
+ ClutterFrame *next_frame;
|
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
struct {
|
|
|
|
struct gbm_surface *surface;
|
2024-08-05 03:39:17 +00:00
|
|
|
- MetaDrmBuffer *current_fb;
|
|
|
|
- MetaDrmBuffer *next_fb;
|
|
|
|
- CoglScanout *current_scanout;
|
|
|
|
- CoglScanout *next_scanout;
|
2024-06-23 12:05:15 +00:00
|
|
|
} gbm;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
#ifdef HAVE_EGL_DEVICE
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -118,6 +120,9 @@ struct _MetaOnscreenNative
|
2024-08-05 03:39:17 +00:00
|
|
|
} egl;
|
|
|
|
#endif
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ gboolean needs_flush;
|
|
|
|
+ unsigned int swaps_pending;
|
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
gboolean frame_sync_requested;
|
|
|
|
gboolean frame_sync_enabled;
|
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -139,44 +144,37 @@ G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static GQuark blit_source_quark = 0;
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+try_post_latest_swap (CoglOnscreen *onscreen);
|
2023-10-10 05:21:14 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+static void
|
|
|
|
+post_finish_frame (MetaOnscreenNative *onscreen_native,
|
|
|
|
+ MetaKmsUpdate *kms_update);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
|
|
|
static gboolean
|
2024-06-23 12:05:15 +00:00
|
|
|
init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
|
|
CoglOnscreen *onscreen,
|
|
|
|
GError **error);
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
-static void
|
|
|
|
-free_current_bo (CoglOnscreen *onscreen)
|
|
|
|
-{
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
-
|
|
|
|
- g_clear_object (&onscreen_native->gbm.current_fb);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.current_scanout);
|
|
|
|
-}
|
|
|
|
-
|
2023-10-10 05:21:14 +00:00
|
|
|
static void
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
2023-10-10 05:21:14 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (!onscreen_native->gbm.next_fb)
|
2024-08-05 03:39:17 +00:00
|
|
|
+ if (!onscreen_native->posted_frame)
|
2024-06-23 12:05:15 +00:00
|
|
|
return;
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- free_current_bo (onscreen);
|
2024-08-05 03:39:17 +00:00
|
|
|
-
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
2024-08-05 03:39:17 +00:00
|
|
|
- g_set_object (&onscreen_native->gbm.current_scanout,
|
2024-06-23 12:05:15 +00:00
|
|
|
- onscreen_native->gbm.next_scanout);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_scanout);
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref);
|
|
|
|
+ onscreen_native->presented_frame =
|
|
|
|
+ g_steal_pointer (&onscreen_native->posted_frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
|
|
|
-meta_onscreen_native_clear_next_fb (CoglOnscreen *onscreen)
|
|
|
|
+meta_onscreen_native_clear_posted_fb (CoglOnscreen *onscreen)
|
|
|
|
{
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_scanout);
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_clear_pointer (&onscreen_native->posted_frame, clutter_frame_unref);
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -214,7 +212,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen)
|
2024-03-24 04:54:32 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
info = cogl_onscreen_pop_head_frame_info (onscreen);
|
2021-11-24 14:38:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_assert (!cogl_onscreen_peek_head_frame_info (onscreen));
|
|
|
|
+ g_return_if_fail (info);
|
2022-04-02 05:32:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
|
|
|
_cogl_onscreen_notify_complete (onscreen, info);
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -256,6 +254,7 @@ notify_view_crtc_presented (MetaRendererView *view,
|
2024-06-23 12:05:15 +00:00
|
|
|
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
meta_onscreen_native_swap_drm_fb (onscreen);
|
|
|
|
+ try_post_latest_swap (onscreen);
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -305,15 +304,13 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc,
|
2024-06-23 12:05:15 +00:00
|
|
|
CoglFramebuffer *framebuffer =
|
|
|
|
clutter_stage_view_get_onscreen (CLUTTER_STAGE_VIEW (view));
|
|
|
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
CoglFrameInfo *frame_info;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
|
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_warn_if_fail (!onscreen_native->gbm.next_fb);
|
|
|
|
-
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
+ try_post_latest_swap (onscreen);
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -379,7 +376,8 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
2024-08-28 11:31:05 +00:00
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- meta_onscreen_native_clear_next_fb (onscreen);
|
|
|
|
+ meta_onscreen_native_clear_posted_fb (onscreen);
|
|
|
|
+ try_post_latest_swap (onscreen);
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = {
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -440,18 +438,36 @@ custom_egl_stream_page_flip (gpointer custom_page_flip_data,
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
2024-06-23 12:05:15 +00:00
|
|
|
#endif /* HAVE_EGL_DEVICE */
|
|
|
|
|
|
|
|
-void
|
|
|
|
-meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen)
|
|
|
|
+static void
|
|
|
|
+drop_stalled_swap (CoglOnscreen *onscreen)
|
|
|
|
{
|
|
|
|
CoglFrameInfo *frame_info;
|
|
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
|
|
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
|
|
+ if (onscreen_native->swaps_pending <= 1)
|
|
|
|
+ return;
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ onscreen_native->swaps_pending--;
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_clear_pointer (&onscreen_native->stalled_frame, clutter_frame_unref);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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);
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ /* 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
|
|
|
|
apply_transform (MetaCrtcKms *crtc_kms,
|
|
|
|
MetaKmsPlaneAssignment *kms_plane_assignment,
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -528,12 +544,15 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2024-08-05 03:39:17 +00:00
|
|
|
{
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
|
|
|
+ g_autoptr (ClutterFrame) frame = NULL;
|
|
|
|
+ MetaFrameNative *frame_native;
|
|
|
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
|
|
|
MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
|
|
|
|
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
|
|
MetaRendererNativeGpuData *renderer_gpu_data;
|
|
|
|
MetaGpuKms *gpu_kms;
|
|
|
|
MetaDrmBuffer *buffer;
|
|
|
|
+ CoglScanout *scanout;
|
|
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
graphene_rect_t src_rect;
|
|
|
|
MtkRectangle dst_rect;
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -541,6 +560,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2024-08-05 03:39:17 +00:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
|
|
|
|
"Meta::OnscreenNative::flip_crtc()");
|
|
|
|
|
|
|
|
+ frame = g_steal_pointer (&onscreen_native->next_frame);
|
|
|
|
+ g_return_if_fail (frame);
|
|
|
|
+
|
|
|
|
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
|
|
|
|
|
|
|
g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
|
2024-09-14 03:04:52 +00:00
|
|
|
@@ -550,14 +572,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
switch (renderer_gpu_data->mode)
|
2022-04-02 05:32:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
|
|
- buffer = onscreen_native->gbm.next_fb;
|
2024-08-05 03:39:17 +00:00
|
|
|
+ frame_native = meta_frame_native_from_frame (frame);
|
|
|
|
+ buffer = meta_frame_native_get_buffer (frame_native);
|
|
|
|
+ scanout = meta_frame_native_get_scanout (frame_native);
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (onscreen_native->gbm.next_scanout)
|
2024-08-05 03:39:17 +00:00
|
|
|
+ if (scanout)
|
2024-06-23 12:05:15 +00:00
|
|
|
{
|
|
|
|
- cogl_scanout_get_src_rect (onscreen_native->gbm.next_scanout,
|
2024-08-05 03:39:17 +00:00
|
|
|
- &src_rect);
|
2024-06-23 12:05:15 +00:00
|
|
|
- cogl_scanout_get_dst_rect (onscreen_native->gbm.next_scanout,
|
2024-08-05 03:39:17 +00:00
|
|
|
- &dst_rect);
|
|
|
|
+ cogl_scanout_get_src_rect (scanout, &src_rect);
|
|
|
|
+ cogl_scanout_get_dst_rect (scanout, &dst_rect);
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
else
|
2024-08-05 03:39:17 +00:00
|
|
|
{
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -601,6 +623,10 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2024-08-05 03:39:17 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
+ g_warn_if_fail (!onscreen_native->posted_frame);
|
|
|
|
+ g_clear_pointer (&onscreen_native->posted_frame, clutter_frame_unref);
|
|
|
|
+ onscreen_native->posted_frame = g_steal_pointer (&frame);
|
|
|
|
+
|
|
|
|
meta_kms_update_add_page_flip_listener (kms_update,
|
|
|
|
kms_crtc,
|
|
|
|
&page_flip_listener_vtable,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -849,29 +875,63 @@ import_shared_framebuffer (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static MetaDrmBuffer *
|
|
|
|
-copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
|
|
- MetaRendererNativeGpuData *renderer_gpu_data,
|
|
|
|
- gboolean *egl_context_changed,
|
|
|
|
- MetaDrmBuffer *primary_gpu_fb)
|
|
|
|
+copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
|
|
|
+ MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
|
|
|
|
+ MetaRendererNativeGpuData *renderer_gpu_data,
|
|
|
|
+ MetaDrmBuffer *primary_gpu_fb,
|
|
|
|
+ GError **error)
|
|
|
|
{
|
|
|
|
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
|
|
MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
|
|
|
|
MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native);
|
|
|
|
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
|
|
+ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
|
|
|
+ CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
|
|
|
+ CoglRendererEGL *cogl_renderer_egl = cogl_context->display->renderer->winsys;
|
|
|
|
MetaRenderDevice *render_device;
|
|
|
|
- EGLDisplay egl_display;
|
|
|
|
- GError *error = NULL;
|
|
|
|
+ EGLDisplay egl_display = NULL;
|
|
|
|
gboolean use_modifiers;
|
|
|
|
MetaDeviceFile *device_file;
|
|
|
|
MetaDrmBufferFlags flags;
|
|
|
|
- MetaDrmBufferGbm *buffer_gbm;
|
|
|
|
+ MetaDrmBufferGbm *buffer_gbm = NULL;
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
+ EGLSync primary_gpu_egl_sync = EGL_NO_SYNC;
|
|
|
|
+ EGLSync secondary_gpu_egl_sync = EGL_NO_SYNC;
|
|
|
|
+ g_autofd int primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
|
|
|
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (CopySharedFramebufferSecondaryGpu,
|
|
|
|
"copy_shared_framebuffer_gpu()");
|
|
|
|
|
|
|
|
if (renderer_gpu_data->secondary.needs_explicit_sync)
|
|
|
|
- cogl_framebuffer_finish (COGL_FRAMEBUFFER (onscreen));
|
|
|
|
+ {
|
|
|
|
+ if (!meta_egl_create_sync (egl,
|
|
|
|
+ cogl_renderer_egl->edpy,
|
|
|
|
+ EGL_SYNC_NATIVE_FENCE_ANDROID,
|
|
|
|
+ NULL,
|
|
|
|
+ &primary_gpu_egl_sync,
|
|
|
|
+ error))
|
|
|
|
+ {
|
|
|
|
+ g_prefix_error (error, "Failed to create EGLSync on primary GPU: ");
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // According to the EGL_KHR_fence_sync specification we must ensure
|
|
|
|
+ // the fence command is flushed in this context to be able to await it
|
|
|
|
+ // in another (secondary GPU context) or we risk waiting indefinitely.
|
|
|
|
+ cogl_framebuffer_flush (COGL_FRAMEBUFFER (onscreen));
|
|
|
|
+
|
|
|
|
+ primary_gpu_sync_fence =
|
|
|
|
+ meta_egl_duplicate_native_fence_fd (egl,
|
|
|
|
+ cogl_renderer_egl->edpy,
|
|
|
|
+ primary_gpu_egl_sync,
|
|
|
|
+ error);
|
|
|
|
+
|
|
|
|
+ if (primary_gpu_sync_fence == EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
|
|
|
+ {
|
|
|
|
+ g_prefix_error (error, "Failed to duplicate EGLSync FD on primary GPU: ");
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
|
|
render_device = renderer_gpu_data->render_device;
|
|
|
|
egl_display = meta_render_device_get_egl_display (render_device);
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -881,15 +941,45 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
secondary_gpu_state->egl_surface,
|
|
|
|
secondary_gpu_state->egl_surface,
|
|
|
|
renderer_gpu_data->secondary.egl_context,
|
|
|
|
- &error))
|
|
|
|
+ error))
|
|
|
|
{
|
|
|
|
- g_warning ("Failed to make current: %s", error->message);
|
|
|
|
- g_error_free (error);
|
|
|
|
- return NULL;
|
|
|
|
+ g_prefix_error (error, "Failed to make current: ");
|
|
|
|
+ goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
- *egl_context_changed = TRUE;
|
|
|
|
+ if (primary_gpu_sync_fence != EGL_NO_NATIVE_FENCE_FD_ANDROID)
|
|
|
|
+ {
|
|
|
|
+ EGLAttrib attribs[3];
|
2024-09-15 05:07:15 +00:00
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
+ attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID;
|
|
|
|
+ attribs[1] = primary_gpu_sync_fence;
|
|
|
|
+ attribs[2] = EGL_NONE;
|
2024-09-15 05:07:15 +00:00
|
|
|
+
|
2024-09-14 03:04:52 +00:00
|
|
|
+ if (!meta_egl_create_sync (egl,
|
|
|
|
+ egl_display,
|
|
|
|
+ EGL_SYNC_NATIVE_FENCE_ANDROID,
|
|
|
|
+ attribs,
|
|
|
|
+ &secondary_gpu_egl_sync,
|
|
|
|
+ error))
|
|
|
|
+ {
|
|
|
|
+ g_prefix_error (error, "Failed to create EGLSync on secondary GPU: ");
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // eglCreateSync takes ownership of an existing fd that is passed, so
|
|
|
|
+ // don't try to clean it up twice.
|
|
|
|
+ primary_gpu_sync_fence = EGL_NO_NATIVE_FENCE_FD_ANDROID;
|
|
|
|
+
|
|
|
|
+ if (!meta_egl_wait_sync (egl,
|
|
|
|
+ egl_display,
|
|
|
|
+ secondary_gpu_egl_sync,
|
|
|
|
+ 0,
|
|
|
|
+ error))
|
|
|
|
+ {
|
|
|
|
+ g_prefix_error (error, "Failed to wait for EGLSync on secondary GPU: ");
|
|
|
|
+ goto done;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
|
|
|
|
buffer_gbm = META_DRM_BUFFER_GBM (primary_gpu_fb);
|
|
|
|
bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -899,21 +989,19 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
renderer_gpu_data->secondary.egl_context,
|
|
|
|
secondary_gpu_state->egl_surface,
|
|
|
|
bo,
|
|
|
|
- &error))
|
|
|
|
+ error))
|
|
|
|
{
|
|
|
|
- g_warning ("Failed to blit shared framebuffer: %s", error->message);
|
|
|
|
- g_error_free (error);
|
|
|
|
- return NULL;
|
|
|
|
+ g_prefix_error (error, "Failed to blit shared framebuffer: ");
|
|
|
|
+ goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!meta_egl_swap_buffers (egl,
|
|
|
|
egl_display,
|
|
|
|
secondary_gpu_state->egl_surface,
|
|
|
|
- &error))
|
|
|
|
+ error))
|
|
|
|
{
|
|
|
|
- g_warning ("Failed to swap buffers: %s", error->message);
|
|
|
|
- g_error_free (error);
|
|
|
|
- return NULL;
|
|
|
|
+ g_prefix_error (error, "Failed to swap buffers: ");
|
|
|
|
+ goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
use_modifiers = meta_renderer_native_use_modifiers (renderer_native);
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -927,13 +1015,11 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
meta_drm_buffer_gbm_new_lock_front (device_file,
|
|
|
|
secondary_gpu_state->gbm.surface,
|
|
|
|
flags,
|
|
|
|
- &error);
|
|
|
|
+ error);
|
|
|
|
if (!buffer_gbm)
|
|
|
|
{
|
|
|
|
- g_warning ("meta_drm_buffer_gbm_new_lock_front failed: %s",
|
|
|
|
- error->message);
|
|
|
|
- g_error_free (error);
|
|
|
|
- return NULL;
|
|
|
|
+ g_prefix_error (error, "meta_drm_buffer_gbm_new_lock_front failed: ");
|
|
|
|
+ goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_set_qdata_full (G_OBJECT (buffer_gbm),
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -941,19 +1027,41 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
g_object_ref (primary_gpu_fb),
|
|
|
|
g_object_unref);
|
|
|
|
|
|
|
|
- return META_DRM_BUFFER (buffer_gbm);
|
|
|
|
+done:
|
|
|
|
+ _cogl_winsys_egl_ensure_current (cogl_display);
|
|
|
|
+
|
|
|
|
+ if (primary_gpu_egl_sync != EGL_NO_SYNC &&
|
|
|
|
+ !meta_egl_destroy_sync (egl,
|
|
|
|
+ cogl_renderer_egl->edpy,
|
|
|
|
+ primary_gpu_egl_sync,
|
|
|
|
+ error))
|
|
|
|
+ g_prefix_error (error, "Failed to destroy primary GPU EGLSync: ");
|
|
|
|
+
|
|
|
|
+ if (secondary_gpu_egl_sync != EGL_NO_SYNC &&
|
|
|
|
+ !meta_egl_destroy_sync (egl,
|
|
|
|
+ egl_display,
|
|
|
|
+ secondary_gpu_egl_sync,
|
|
|
|
+ error))
|
|
|
|
+ g_prefix_error (error, "Failed to destroy secondary GPU EGLSync: ");
|
|
|
|
+
|
|
|
|
+ return buffer_gbm ? META_DRM_BUFFER (buffer_gbm) : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaDrmBufferDumb *
|
2024-06-23 12:05:15 +00:00
|
|
|
secondary_gpu_get_next_dumb_buffer (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
|
2023-11-09 07:48:47 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
MetaDrmBufferDumb *current_dumb_fb;
|
|
|
|
+ const int n_dumb_fbs = G_N_ELEMENTS (secondary_gpu_state->cpu.dumb_fbs);
|
|
|
|
+ int i;
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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];
|
|
|
|
}
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static MetaDrmBuffer *
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1193,56 +1301,54 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen,
|
2024-08-05 03:39:17 +00:00
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void
|
|
|
|
-update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
|
|
|
|
- gboolean *egl_context_changed,
|
|
|
|
- MetaDrmBuffer *primary_gpu_fb,
|
|
|
|
- MetaDrmBuffer **secondary_gpu_fb)
|
|
|
|
+static MetaDrmBuffer *
|
2024-09-14 03:04:52 +00:00
|
|
|
+acquire_front_buffer (CoglOnscreen *onscreen,
|
|
|
|
+ MetaDrmBuffer *primary_gpu_fb,
|
|
|
|
+ MetaDrmBuffer *secondary_gpu_fb,
|
|
|
|
+ GError **error)
|
2024-08-05 03:39:17 +00:00
|
|
|
{
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
|
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
|
|
+ MetaRendererNativeGpuData *renderer_gpu_data;
|
|
|
|
+ MetaDrmBuffer *imported_fb;
|
|
|
|
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePostSwapBuffers,
|
|
|
|
- "update_secondary_gpu_state_post_swap_buffers()");
|
|
|
|
+ "acquire_front_buffer()");
|
|
|
|
|
|
|
|
secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
|
|
- if (secondary_gpu_state)
|
|
|
|
- {
|
|
|
|
- MetaRendererNativeGpuData *renderer_gpu_data;
|
|
|
|
- g_autoptr (MetaDrmBuffer) next_fb = NULL;
|
|
|
|
+ if (!secondary_gpu_state)
|
|
|
|
+ return g_object_ref (primary_gpu_fb);
|
|
|
|
|
|
|
|
- renderer_gpu_data =
|
|
|
|
- meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
- secondary_gpu_state->gpu_kms);
|
|
|
|
- switch (renderer_gpu_data->secondary.copy_mode)
|
|
|
|
- {
|
|
|
|
- case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO:
|
|
|
|
- next_fb = import_shared_framebuffer (onscreen,
|
|
|
|
+ renderer_gpu_data =
|
|
|
|
+ meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
+ secondary_gpu_state->gpu_kms);
|
|
|
|
+ switch (renderer_gpu_data->secondary.copy_mode)
|
|
|
|
+ {
|
|
|
|
+ case META_SHARED_FRAMEBUFFER_COPY_MODE_ZERO:
|
|
|
|
+ imported_fb = import_shared_framebuffer (onscreen,
|
|
|
|
secondary_gpu_state,
|
|
|
|
primary_gpu_fb);
|
|
|
|
- if (next_fb)
|
|
|
|
- break;
|
|
|
|
- /* 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:
|
|
|
|
- next_fb = g_object_ref (*secondary_gpu_fb);
|
|
|
|
- break;
|
|
|
|
- case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU:
|
|
|
|
- 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);
|
|
|
|
+ if (imported_fb)
|
|
|
|
+ return imported_fb;
|
|
|
|
+ /* 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:
|
|
|
|
+ return g_object_ref (secondary_gpu_fb);
|
|
|
|
+ case META_SHARED_FRAMEBUFFER_COPY_MODE_SECONDARY_GPU:
|
|
|
|
+ return copy_shared_framebuffer_gpu (onscreen,
|
|
|
|
+ secondary_gpu_state,
|
|
|
|
+ renderer_gpu_data,
|
2024-09-14 03:04:52 +00:00
|
|
|
+ primary_gpu_fb,
|
|
|
|
+ error);
|
2024-08-05 03:39:17 +00:00
|
|
|
}
|
|
|
|
+
|
|
|
|
+ g_assert_not_reached ();
|
|
|
|
+ return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1285,10 +1391,36 @@ swap_buffer_result_feedback (const MetaKmsFeedback *kms_feedback,
|
2024-06-23 12:05:15 +00:00
|
|
|
g_warning ("Page flip failed: %s", error->message);
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
|
|
|
- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- meta_onscreen_native_clear_next_fb (onscreen);
|
|
|
|
+ /* After resuming from suspend, drop_stalled_swap might have done this
|
|
|
|
+ * already and emptied the frame_info queue.
|
|
|
|
+ */
|
|
|
|
+ if (frame_info)
|
|
|
|
+ {
|
|
|
|
+ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
+ meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ meta_onscreen_native_clear_posted_fb (onscreen);
|
2024-08-05 03:39:17 +00:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+assign_next_frame (MetaOnscreenNative *onscreen_native,
|
|
|
|
+ ClutterFrame *frame)
|
|
|
|
+{
|
|
|
|
+ CoglOnscreen *onscreen = COGL_ONSCREEN (onscreen_native);
|
|
|
|
+
|
|
|
|
+ if (onscreen_native->next_frame != NULL)
|
|
|
|
+ {
|
|
|
|
+ g_warn_if_fail (onscreen_native->stalled_frame == NULL);
|
|
|
|
+ drop_stalled_swap (onscreen);
|
|
|
|
+ g_warn_if_fail (onscreen_native->stalled_frame == NULL);
|
|
|
|
+ g_clear_pointer (&onscreen_native->stalled_frame, clutter_frame_unref);
|
|
|
|
+ onscreen_native->stalled_frame =
|
|
|
|
+ g_steal_pointer (&onscreen_native->next_frame);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ onscreen_native->next_frame = clutter_frame_ref (frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static const MetaKmsResultListenerVtable swap_buffer_result_listener_vtable = {
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1304,37 +1436,41 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
{
|
|
|
|
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
|
|
CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
|
|
|
- CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
|
|
|
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
2024-06-23 12:05:15 +00:00
|
|
|
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);
|
|
|
|
- MetaMonitorManager *monitor_manager =
|
|
|
|
- meta_backend_get_monitor_manager (backend);
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
|
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
|
|
|
MetaDeviceFile *render_device_file;
|
|
|
|
ClutterFrame *frame = user_data;
|
2024-08-05 03:39:17 +00:00
|
|
|
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
- MetaKmsUpdate *kms_update;
|
|
|
|
CoglOnscreenClass *parent_class;
|
|
|
|
gboolean create_timestamp_query = TRUE;
|
2024-09-14 03:04:52 +00:00
|
|
|
- gboolean egl_context_changed = FALSE;
|
2024-06-23 12:05:15 +00:00
|
|
|
- MetaPowerSave power_save_mode;
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
MetaDrmBufferFlags buffer_flags;
|
|
|
|
MetaDrmBufferGbm *buffer_gbm;
|
|
|
|
g_autoptr (MetaDrmBuffer) primary_gpu_fb = NULL;
|
|
|
|
g_autoptr (MetaDrmBuffer) secondary_gpu_fb = NULL;
|
|
|
|
- MetaKmsCrtc *kms_crtc;
|
|
|
|
- MetaKmsDevice *kms_device;
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_autoptr (MetaDrmBuffer) buffer = NULL;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
|
|
|
"Meta::OnscreenNative::swap_buffers_with_damage()");
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (meta_is_topic_enabled (META_DEBUG_KMS))
|
2024-05-08 13:03:56 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ unsigned int frames_pending =
|
2024-08-05 03:39:17 +00:00
|
|
|
+ cogl_onscreen_get_pending_frame_count (onscreen);
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
+ meta_topic (META_DEBUG_KMS,
|
|
|
|
+ "Swap buffers: %u frames pending (%s-buffering)",
|
|
|
|
+ frames_pending,
|
|
|
|
+ frames_pending == 1 ? "double" :
|
|
|
|
+ frames_pending == 2 ? "triple" :
|
|
|
|
+ "?");
|
2024-05-08 13:03:56 +00:00
|
|
|
+ }
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
secondary_gpu_fb =
|
|
|
|
update_secondary_gpu_state_pre_swap_buffers (onscreen,
|
|
|
|
rectangles,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1384,46 +1520,28 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
g_warning ("Failed to lock front buffer on %s: %s",
|
|
|
|
meta_device_file_get_path (render_device_file),
|
|
|
|
error->message);
|
|
|
|
-
|
|
|
|
- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
- meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- return;
|
|
|
|
+ goto swap_failed;
|
|
|
|
}
|
2024-08-05 03:39:17 +00:00
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
primary_gpu_fb = META_DRM_BUFFER (g_steal_pointer (&buffer_gbm));
|
|
|
|
- break;
|
|
|
|
- case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
|
|
- g_assert_not_reached ();
|
|
|
|
- break;
|
|
|
|
-#ifdef HAVE_EGL_DEVICE
|
|
|
|
- case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
+ buffer = acquire_front_buffer (onscreen,
|
|
|
|
+ primary_gpu_fb,
|
|
|
|
+ secondary_gpu_fb,
|
|
|
|
+ &error);
|
|
|
|
+ if (buffer == NULL)
|
|
|
|
+ {
|
|
|
|
+ g_warning ("Failed to acquire front buffer: %s", error->message);
|
|
|
|
+ goto swap_failed;
|
|
|
|
+ }
|
2024-08-05 03:39:17 +00:00
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
- update_secondary_gpu_state_post_swap_buffers (onscreen,
|
|
|
|
- &egl_context_changed,
|
|
|
|
- primary_gpu_fb,
|
|
|
|
- &secondary_gpu_fb);
|
|
|
|
+ meta_frame_native_set_buffer (frame_native, buffer);
|
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
- switch (renderer_gpu_data->mode)
|
|
|
|
- {
|
|
|
|
- case META_RENDERER_NATIVE_MODE_GBM:
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
2024-08-05 03:39:17 +00:00
|
|
|
- if (onscreen_native->secondary_gpu_state)
|
|
|
|
- g_set_object (&onscreen_native->gbm.next_fb, secondary_gpu_fb);
|
|
|
|
- else
|
|
|
|
- g_set_object (&onscreen_native->gbm.next_fb, primary_gpu_fb);
|
2024-09-15 05:07:15 +00:00
|
|
|
-
|
2024-08-05 03:39:17 +00:00
|
|
|
- if (!meta_drm_buffer_ensure_fb_id (onscreen_native->gbm.next_fb, &error))
|
|
|
|
+ if (!meta_drm_buffer_ensure_fb_id (buffer, &error))
|
|
|
|
{
|
|
|
|
g_warning ("Failed to ensure KMS FB ID on %s: %s",
|
|
|
|
meta_device_file_get_path (render_device_file),
|
2024-09-14 03:04:52 +00:00
|
|
|
error->message);
|
|
|
|
-
|
|
|
|
- frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
- meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- return;
|
|
|
|
+ goto swap_failed;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1434,21 +1552,86 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
#endif
|
|
|
|
}
|
2023-10-10 05:21:14 +00:00
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
- /*
|
|
|
|
- * If we changed EGL context, cogl will have the wrong idea about what is
|
|
|
|
- * current, making it fail to set it when it needs to. Avoid that by making
|
|
|
|
- * EGL_NO_CONTEXT current now, making cogl eventually set the correct
|
|
|
|
- * context.
|
|
|
|
- */
|
|
|
|
- if (egl_context_changed)
|
|
|
|
- _cogl_winsys_egl_ensure_current (cogl_display);
|
2024-08-05 03:39:17 +00:00
|
|
|
+ assign_next_frame (onscreen_native, frame);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (onscreen_native->crtc));
|
|
|
|
- kms_device = meta_kms_crtc_get_device (kms_crtc);
|
2024-09-14 03:04:52 +00:00
|
|
|
+ clutter_frame_set_result (frame,
|
|
|
|
+ CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ meta_frame_native_set_damage (frame_native, rectangles, n_rectangles);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ onscreen_native->swaps_pending++;
|
|
|
|
+ try_post_latest_swap (onscreen);
|
2024-09-14 03:04:52 +00:00
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+swap_failed:
|
|
|
|
+ frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
+ meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
2024-06-23 12:05:15 +00:00
|
|
|
+}
|
|
|
|
+
|
|
|
|
+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);
|
|
|
|
+ MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
|
|
|
+ MetaMonitorManager *monitor_manager =
|
|
|
|
+ meta_backend_get_monitor_manager (backend);
|
|
|
|
+ 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);
|
|
|
|
+ MetaKmsUpdate *kms_update;
|
|
|
|
+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
|
|
+ g_autoptr (ClutterFrame) frame = NULL;
|
|
|
|
+ MetaFrameNative *frame_native;
|
2024-09-14 03:04:52 +00:00
|
|
|
+ int sync_fd;
|
|
|
|
+ COGL_TRACE_SCOPED_ANCHOR (MetaRendererNativePostKmsUpdate);
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ if (onscreen_native->next_frame == NULL ||
|
2024-06-23 12:05:15 +00:00
|
|
|
+ onscreen_native->view == NULL ||
|
|
|
|
+ meta_kms_is_shutting_down (kms))
|
|
|
|
+ return;
|
|
|
|
|
|
|
|
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
|
|
|
|
if (power_save_mode == META_POWER_SAVE_ON)
|
|
|
|
{
|
|
|
|
+ unsigned int frames_pending =
|
2024-08-05 03:39:17 +00:00
|
|
|
+ cogl_onscreen_get_pending_frame_count (onscreen);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ unsigned int posts_pending;
|
2024-08-05 03:39:17 +00:00
|
|
|
+ int n_rectangles;
|
|
|
|
+ int *rectangles;
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
+ g_assert (frames_pending >= onscreen_native->swaps_pending);
|
|
|
|
+ posts_pending = frames_pending - onscreen_native->swaps_pending;
|
|
|
|
+ if (posts_pending > 0)
|
|
|
|
+ return; /* wait for the next frame notification and then try again */
|
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ frame = clutter_frame_ref (onscreen_native->next_frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ frame_native = meta_frame_native_from_frame (frame);
|
2024-08-05 03:39:17 +00:00
|
|
|
+ n_rectangles = meta_frame_native_get_damage (frame_native, &rectangles);
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
+ if (onscreen_native->swaps_pending == 0)
|
2024-05-08 13:03:56 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (frame_native)
|
|
|
|
+ {
|
|
|
|
+ kms_update = meta_frame_native_steal_kms_update (frame_native);
|
|
|
|
+ if (kms_update)
|
|
|
|
+ post_finish_frame (onscreen_native, kms_update);
|
|
|
|
+ }
|
2024-05-08 13:03:56 +00:00
|
|
|
+ return;
|
|
|
|
+ }
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ drop_stalled_swap (onscreen);
|
|
|
|
+ onscreen_native->swaps_pending--;
|
2023-11-09 07:48:47 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
kms_update = meta_frame_native_ensure_kms_update (frame_native,
|
|
|
|
kms_device);
|
|
|
|
meta_kms_update_add_result_listener (kms_update,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1470,13 +1653,11 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_renderer_native_queue_power_save_page_flip (renderer_native,
|
|
|
|
onscreen);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
2024-05-08 13:03:56 +00:00
|
|
|
return;
|
2024-06-23 12:05:15 +00:00
|
|
|
}
|
|
|
|
|
2024-09-14 03:04:52 +00:00
|
|
|
- COGL_TRACE_BEGIN_SCOPED (MetaRendererNativePostKmsUpdate,
|
2024-08-05 03:39:17 +00:00
|
|
|
- "Meta::OnscreenNative::swap_buffers_with_damage#post_pending_update()");
|
2024-09-14 03:04:52 +00:00
|
|
|
+ COGL_TRACE_BEGIN_ANCHORED (MetaRendererNativePostKmsUpdate,
|
|
|
|
+ "Meta::OnscreenNative::try_post_latest_swap#post_pending_update()");
|
2024-08-05 03:39:17 +00:00
|
|
|
|
|
|
|
switch (renderer_gpu_data->mode)
|
|
|
|
{
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1491,8 +1672,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
kms_update = meta_frame_native_steal_kms_update (frame_native);
|
|
|
|
meta_renderer_native_queue_mode_set_update (renderer_native,
|
|
|
|
kms_update);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
2024-05-08 13:03:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-06-23 12:05:15 +00:00
|
|
|
else if (meta_renderer_native_has_pending_mode_set (renderer_native))
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1506,8 +1685,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2023-11-09 07:48:47 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_frame_native_steal_kms_update (frame_native);
|
|
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1523,8 +1700,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
kms_update);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1537,9 +1712,10 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
meta_kms_device_get_path (kms_device));
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
kms_update = meta_frame_native_steal_kms_update (frame_native);
|
2024-09-14 03:04:52 +00:00
|
|
|
+ sync_fd = cogl_context_get_latest_sync_fd (cogl_context);
|
|
|
|
+ meta_kms_update_set_sync_fd (kms_update, sync_fd);
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_kms_device_post_update (kms_device, kms_update,
|
|
|
|
META_KMS_UPDATE_FLAG_NONE);
|
|
|
|
- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
}
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
gboolean
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1572,7 +1748,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
assign_primary_plane (crtc_kms,
|
|
|
|
buffer,
|
|
|
|
test_update,
|
|
|
|
- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT,
|
|
|
|
+ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC,
|
|
|
|
&src_rect,
|
|
|
|
&dst_rect);
|
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1607,11 +1783,15 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback,
|
2024-08-05 03:39:17 +00:00
|
|
|
G_IO_ERROR_PERMISSION_DENIED))
|
|
|
|
{
|
|
|
|
ClutterStageView *view = CLUTTER_STAGE_VIEW (onscreen_native->view);
|
|
|
|
+ ClutterFrame *posted_frame = onscreen_native->posted_frame;
|
|
|
|
+ MetaFrameNative *posted_frame_native =
|
|
|
|
+ meta_frame_native_from_frame (posted_frame);
|
|
|
|
+ CoglScanout *scanout =
|
|
|
|
+ meta_frame_native_get_scanout (posted_frame_native);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
g_warning ("Direct scanout page flip failed: %s", error->message);
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- cogl_scanout_notify_failed (onscreen_native->gbm.next_scanout,
|
2024-08-05 03:39:17 +00:00
|
|
|
- onscreen);
|
|
|
|
+ cogl_scanout_notify_failed (scanout, onscreen);
|
2024-06-23 12:05:15 +00:00
|
|
|
clutter_stage_view_add_redraw_clip (view, NULL);
|
|
|
|
clutter_stage_view_schedule_update_now (view);
|
2024-08-05 03:39:17 +00:00
|
|
|
}
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1620,7 +1800,7 @@ scanout_result_feedback (const MetaKmsFeedback *kms_feedback,
|
2024-06-23 12:05:15 +00:00
|
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- meta_onscreen_native_clear_next_fb (onscreen);
|
|
|
|
+ meta_onscreen_native_clear_posted_fb (onscreen);
|
2022-10-27 14:41:22 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static const MetaKmsResultListenerVtable scanout_result_listener_vtable = {
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1672,16 +1852,28 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ /* Our direct scanout frame counts as 1, so more than that means we would
|
|
|
|
+ * be jumping the queue (and post would fail).
|
|
|
|
+ */
|
2024-08-05 03:39:17 +00:00
|
|
|
+ if (cogl_onscreen_get_pending_frame_count (onscreen) > 1)
|
2024-06-23 12:05:15 +00:00
|
|
|
+ {
|
|
|
|
+ g_set_error_literal (error,
|
|
|
|
+ COGL_SCANOUT_ERROR,
|
|
|
|
+ COGL_SCANOUT_ERROR_INHIBITED,
|
|
|
|
+ "Direct scanout is inhibited during triple buffering");
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
2022-10-27 14:41:22 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
render_gpu);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-08-05 03:39:17 +00:00
|
|
|
g_warn_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM);
|
|
|
|
- g_warn_if_fail (!onscreen_native->gbm.next_fb);
|
|
|
|
- g_warn_if_fail (!onscreen_native->gbm.next_scanout);
|
|
|
|
|
|
|
|
- g_set_object (&onscreen_native->gbm.next_scanout, scanout);
|
|
|
|
- g_set_object (&onscreen_native->gbm.next_fb,
|
|
|
|
- META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)));
|
|
|
|
+ assign_next_frame (onscreen_native, frame);
|
|
|
|
+
|
|
|
|
+ meta_frame_native_set_scanout (frame_native, scanout);
|
|
|
|
+ meta_frame_native_set_buffer (frame_native,
|
|
|
|
+ META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)));
|
|
|
|
|
|
|
|
frame_info->cpu_time_before_buffer_swap_us = g_get_monotonic_time ();
|
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1702,7 +1894,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
2024-09-14 03:04:52 +00:00
|
|
|
onscreen_native->view,
|
|
|
|
onscreen_native->crtc,
|
|
|
|
kms_update,
|
|
|
|
- META_KMS_ASSIGN_PLANE_FLAG_DIRECT_SCANOUT,
|
|
|
|
+ META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1787,11 +1979,15 @@ meta_onscreen_native_before_redraw (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
ClutterFrame *frame)
|
|
|
|
{
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
- MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
|
|
|
- MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc),
|
|
|
|
- kms_crtc);
|
2024-08-14 08:34:14 +00:00
|
|
|
+ if (meta_get_debug_paint_flags () & META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY)
|
|
|
|
+ {
|
|
|
|
+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
|
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
|
|
+
|
|
|
|
+ meta_kms_device_await_flush (meta_kms_crtc_get_device (kms_crtc), kms_crtc);
|
|
|
|
+ }
|
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
maybe_update_frame_sync (onscreen_native, frame);
|
|
|
|
}
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1920,22 +2116,79 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
|
|
MetaFrameNative *frame_native = meta_frame_native_from_frame (frame);
|
|
|
|
MetaKmsUpdate *kms_update;
|
2024-08-05 03:39:17 +00:00
|
|
|
+ unsigned int frames_pending = cogl_onscreen_get_pending_frame_count (onscreen);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ unsigned int swaps_pending = onscreen_native->swaps_pending;
|
|
|
|
+ unsigned int posts_pending = frames_pending - swaps_pending;
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- kms_update = meta_frame_native_steal_kms_update (frame_native);
|
|
|
|
- if (!kms_update)
|
|
|
|
+ onscreen_native->needs_flush |= meta_kms_device_handle_flush (kms_device,
|
|
|
|
+ kms_crtc);
|
|
|
|
+
|
|
|
|
+ if (!meta_frame_native_has_kms_update (frame_native))
|
|
|
|
{
|
|
|
|
- if (meta_kms_device_handle_flush (kms_device, kms_crtc))
|
|
|
|
- {
|
|
|
|
- kms_update = meta_kms_update_new (kms_device);
|
|
|
|
- meta_kms_update_set_flushing (kms_update, kms_crtc);
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
+ if (!onscreen_native->needs_flush || posts_pending)
|
|
|
|
{
|
|
|
|
clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (posts_pending && !swaps_pending)
|
|
|
|
+ {
|
|
|
|
+ g_return_if_fail (meta_frame_native_has_kms_update (frame_native));
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_warn_if_fail (onscreen_native->next_frame == NULL);
|
2022-10-27 14:41:22 +00:00
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref);
|
|
|
|
+ onscreen_native->next_frame = clutter_frame_ref (frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ kms_update = meta_frame_native_steal_kms_update (frame_native);
|
|
|
|
+
|
|
|
|
+ if (posts_pending && swaps_pending)
|
2022-10-27 14:41:22 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ MetaFrameNative *older_frame_native;
|
|
|
|
+ MetaKmsUpdate *older_kms_update;
|
|
|
|
+
|
|
|
|
+ g_return_if_fail (kms_update);
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_return_if_fail (onscreen_native->next_frame != NULL);
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
+ older_frame_native =
|
2024-08-05 03:39:17 +00:00
|
|
|
+ meta_frame_native_from_frame (onscreen_native->next_frame);
|
2024-06-23 12:05:15 +00:00
|
|
|
+ older_kms_update =
|
|
|
|
+ meta_frame_native_ensure_kms_update (older_frame_native, kms_device);
|
|
|
|
+ meta_kms_update_merge_from (older_kms_update, kms_update);
|
|
|
|
+ meta_kms_update_free (kms_update);
|
|
|
|
+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_IDLE);
|
|
|
|
+ return;
|
2022-10-27 14:41:22 +00:00
|
|
|
+ }
|
2024-06-23 12:05:15 +00:00
|
|
|
+
|
|
|
|
+ if (!kms_update)
|
2022-10-27 14:41:22 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ kms_update = meta_kms_update_new (kms_device);
|
|
|
|
+ g_warn_if_fail (onscreen_native->needs_flush);
|
2022-10-27 14:41:22 +00:00
|
|
|
+ }
|
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (onscreen_native->needs_flush)
|
2022-10-27 14:41:22 +00:00
|
|
|
+ {
|
2024-06-23 12:05:15 +00:00
|
|
|
+ meta_kms_update_set_flushing (kms_update, kms_crtc);
|
|
|
|
+ onscreen_native->needs_flush = FALSE;
|
2022-10-27 14:41:22 +00:00
|
|
|
+ }
|
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ post_finish_frame (onscreen_native, kms_update);
|
|
|
|
+
|
|
|
|
+ clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+post_finish_frame (MetaOnscreenNative *onscreen_native,
|
|
|
|
+ MetaKmsUpdate *kms_update)
|
|
|
|
+{
|
|
|
|
+ MetaCrtc *crtc = onscreen_native->crtc;
|
|
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
|
|
|
|
+ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
|
|
+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
|
|
+
|
|
|
|
meta_kms_update_add_result_listener (kms_update,
|
|
|
|
&finish_frame_result_listener_vtable,
|
|
|
|
NULL,
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -1958,7 +2211,17 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_kms_update_set_flushing (kms_update, kms_crtc);
|
|
|
|
meta_kms_device_post_update (kms_device, kms_update,
|
|
|
|
META_KMS_UPDATE_FLAG_NONE);
|
|
|
|
- clutter_frame_set_result (frame, CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen)
|
|
|
|
+{
|
|
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
+
|
|
|
|
+ onscreen_native->swaps_pending = 0;
|
|
|
|
+
|
2024-08-05 03:39:17 +00:00
|
|
|
+ g_clear_pointer (&onscreen_native->stalled_frame, clutter_frame_unref);
|
|
|
|
+ g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref);
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static gboolean
|
2024-09-15 05:07:15 +00:00
|
|
|
@@ -2863,15 +3126,17 @@ meta_onscreen_native_dispose (GObject *object)
|
2024-08-05 03:39:17 +00:00
|
|
|
|
|
|
|
meta_onscreen_native_detach (onscreen_native);
|
|
|
|
|
|
|
|
+ g_clear_pointer (&onscreen_native->next_frame, clutter_frame_unref);
|
|
|
|
+ g_clear_pointer (&onscreen_native->stalled_frame, clutter_frame_unref);
|
|
|
|
+ g_clear_pointer (&onscreen_native->posted_frame, clutter_frame_unref);
|
|
|
|
+ g_clear_pointer (&onscreen_native->presented_frame, clutter_frame_unref);
|
|
|
|
+
|
|
|
|
renderer_gpu_data =
|
|
|
|
meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
onscreen_native->render_gpu);
|
|
|
|
switch (renderer_gpu_data->mode)
|
2024-06-23 12:05:15 +00:00
|
|
|
{
|
|
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
2024-08-05 03:39:17 +00:00
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_scanout);
|
2024-06-23 12:05:15 +00:00
|
|
|
- free_current_bo (onscreen);
|
|
|
|
break;
|
|
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h
|
2024-07-30 08:28:28 +00:00
|
|
|
index 0e1193325a..e30357d19d 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/native/meta-onscreen-native.h
|
|
|
|
+++ b/src/backends/native/meta-onscreen-native.h
|
|
|
|
@@ -48,6 +48,8 @@ void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen);
|
|
|
|
gboolean meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
|
|
|
CoglScanout *scanout);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+void meta_onscreen_native_discard_pending_swaps (CoglOnscreen *onscreen);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
void meta_onscreen_native_set_view (CoglOnscreen *onscreen,
|
|
|
|
MetaRendererView *view);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
2024-09-15 05:07:15 +00:00
|
|
|
index 2fcf6dfd56..03b41dfcad 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
|
|
@@ -731,12 +731,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);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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);
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (renderer_native->power_save_page_flip_onscreens != NULL)
|
|
|
|
+ return G_SOURCE_CONTINUE;
|
|
|
|
+
|
|
|
|
renderer_native->power_save_page_flip_source_id = 0;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
@@ -748,6 +754,9 @@ meta_renderer_native_queue_power_save_page_flip (MetaRendererNative *renderer_na
|
|
|
|
{
|
|
|
|
const unsigned int timeout_ms = 100;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ 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 =
|
|
|
|
@@ -1529,6 +1538,26 @@ detach_onscreens (MetaRenderer *renderer)
|
|
|
|
}
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+static void
|
|
|
|
+discard_pending_swaps (MetaRenderer *renderer)
|
|
|
|
+{
|
|
|
|
+ GList *views = meta_renderer_get_views (renderer);;
|
|
|
|
+ GList *l;
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ for (l = views; l; l = l->next)
|
|
|
|
+ {
|
|
|
|
+ ClutterStageView *stage_view = l->data;
|
|
|
|
+ CoglFramebuffer *fb = clutter_stage_view_get_onscreen (stage_view);
|
|
|
|
+ CoglOnscreen *onscreen;
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ if (!COGL_IS_ONSCREEN (fb))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ onscreen = COGL_ONSCREEN (fb);
|
|
|
|
+ meta_onscreen_native_discard_pending_swaps (onscreen);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_renderer_native_rebuild_views (MetaRenderer *renderer)
|
|
|
|
{
|
|
|
|
@@ -1539,6 +1568,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);
|
|
|
|
g_hash_table_remove_all (renderer_native->mode_set_updates);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-08-14 08:34:14 +00:00
|
|
|
diff --git a/src/backends/native/meta-renderer-view-native.c b/src/backends/native/meta-renderer-view-native.c
|
|
|
|
index a04e2e3533..5699f9a558 100644
|
|
|
|
--- a/src/backends/native/meta-renderer-view-native.c
|
|
|
|
+++ b/src/backends/native/meta-renderer-view-native.c
|
|
|
|
@@ -24,6 +24,7 @@
|
|
|
|
|
|
|
|
#include "backends/native/meta-renderer-view-native.h"
|
|
|
|
|
|
|
|
+#include "backends/native/meta-crtc-native.h"
|
|
|
|
#include "backends/native/meta-frame-native.h"
|
|
|
|
|
|
|
|
struct _MetaRendererViewNative
|
|
|
|
@@ -34,18 +35,58 @@ struct _MetaRendererViewNative
|
|
|
|
G_DEFINE_TYPE (MetaRendererViewNative, meta_renderer_view_native,
|
|
|
|
META_TYPE_RENDERER_VIEW)
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+update_frame_clock_deadline_evasion (MetaRendererView *renderer_view)
|
|
|
|
+{
|
|
|
|
+ ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view);
|
|
|
|
+ ClutterFrameClock *frame_clock;
|
|
|
|
+ MetaCrtc *crtc;
|
|
|
|
+ MetaCrtcNative *crtc_native;
|
|
|
|
+ int64_t deadline_evasion_us;
|
|
|
|
+
|
|
|
|
+ frame_clock = clutter_stage_view_get_frame_clock (stage_view);
|
|
|
|
+ crtc = meta_renderer_view_get_crtc (renderer_view);
|
|
|
|
+ crtc_native = META_CRTC_NATIVE (crtc);
|
|
|
|
+
|
|
|
|
+ deadline_evasion_us = meta_crtc_native_get_deadline_evasion (crtc_native);
|
|
|
|
+ clutter_frame_clock_set_deadline_evasion (frame_clock,
|
|
|
|
+ deadline_evasion_us);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+meta_renderer_view_native_constructed (GObject *object)
|
|
|
|
+{
|
|
|
|
+ MetaRendererView *renderer_view = META_RENDERER_VIEW (object);
|
|
|
|
+
|
|
|
|
+ G_OBJECT_CLASS (meta_renderer_view_native_parent_class)->constructed (object);
|
|
|
|
+
|
|
|
|
+ update_frame_clock_deadline_evasion (renderer_view);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static ClutterFrame *
|
|
|
|
meta_renderer_view_native_new_frame (ClutterStageView *stage_view)
|
|
|
|
{
|
|
|
|
return (ClutterFrame *) meta_frame_native_new ();
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+meta_renderer_view_native_schedule_update (ClutterStageView *stage_view)
|
|
|
|
+{
|
|
|
|
+ MetaRendererView *renderer_view = META_RENDERER_VIEW (stage_view);
|
|
|
|
+
|
|
|
|
+ update_frame_clock_deadline_evasion (renderer_view);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_renderer_view_native_class_init (MetaRendererViewNativeClass *klass)
|
|
|
|
{
|
|
|
|
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
ClutterStageViewClass *stage_view_class = CLUTTER_STAGE_VIEW_CLASS (klass);
|
|
|
|
|
|
|
|
+ object_class->constructed = meta_renderer_view_native_constructed;
|
|
|
|
+
|
|
|
|
stage_view_class->new_frame = meta_renderer_view_native_new_frame;
|
|
|
|
+ stage_view_class->schedule_update = meta_renderer_view_native_schedule_update;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
diff --git a/src/core/util.c b/src/core/util.c
|
|
|
|
index 05a0dea398..f8a08c747f 100644
|
|
|
|
--- a/src/core/util.c
|
|
|
|
+++ b/src/core/util.c
|
|
|
|
@@ -69,6 +69,7 @@ static const GDebugKey meta_debug_keys[] = {
|
|
|
|
{ "color", META_DEBUG_COLOR },
|
|
|
|
{ "input-events", META_DEBUG_INPUT_EVENTS },
|
|
|
|
{ "eis", META_DEBUG_EIS },
|
|
|
|
+ { "kms-deadline", META_DEBUG_KMS_DEADLINE },
|
|
|
|
};
|
|
|
|
|
|
|
|
static gint verbose_topics = 0;
|
|
|
|
@@ -326,6 +327,8 @@ meta_topic_to_string (MetaDebugTopic topic)
|
|
|
|
return "INPUT_EVENTS";
|
|
|
|
case META_DEBUG_EIS:
|
|
|
|
return "EIS";
|
|
|
|
+ case META_DEBUG_KMS_DEADLINE:
|
|
|
|
+ return "KMS_DEADLINE";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "WM";
|
|
|
|
diff --git a/src/meta/meta-debug.h b/src/meta/meta-debug.h
|
|
|
|
index b4c70144b7..2de9a89d75 100644
|
|
|
|
--- a/src/meta/meta-debug.h
|
|
|
|
+++ b/src/meta/meta-debug.h
|
|
|
|
@@ -50,6 +50,7 @@
|
|
|
|
* @META_DEBUG_COLOR: color management
|
|
|
|
* @META_DEBUG_INPUT_EVENTS: input events
|
|
|
|
* @META_DEBUG_EIS: eis state
|
|
|
|
+ * @META_DEBUG_KMS_DEADLINE: KMS deadline timers
|
|
|
|
*/
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
@@ -83,6 +84,7 @@ typedef enum
|
|
|
|
META_DEBUG_COLOR = 1 << 26,
|
|
|
|
META_DEBUG_INPUT_EVENTS = 1 << 27,
|
|
|
|
META_DEBUG_EIS = 1 << 28,
|
|
|
|
+ META_DEBUG_KMS_DEADLINE = 1 << 29,
|
|
|
|
} MetaDebugTopic;
|
|
|
|
|
|
|
|
META_EXPORT
|
|
|
|
diff --git a/src/meta/util.h b/src/meta/util.h
|
|
|
|
index ca8ca2adeb..91ca6a8366 100644
|
|
|
|
--- a/src/meta/util.h
|
|
|
|
+++ b/src/meta/util.h
|
|
|
|
@@ -51,11 +51,14 @@ void meta_fatal (const char *format,
|
|
|
|
* MetaDebugPaintFlag:
|
|
|
|
* @META_DEBUG_PAINT_NONE: default
|
|
|
|
* @META_DEBUG_PAINT_OPAQUE_REGION: paint opaque regions
|
|
|
|
+ * @META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY: make cursor updates await compositing
|
|
|
|
+ * frames
|
|
|
|
*/
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
META_DEBUG_PAINT_NONE = 0,
|
|
|
|
META_DEBUG_PAINT_OPAQUE_REGION = 1 << 0,
|
|
|
|
+ META_DEBUG_PAINT_SYNC_CURSOR_PRIMARY = 1 << 1,
|
|
|
|
} MetaDebugPaintFlag;
|
|
|
|
|
|
|
|
META_EXPORT
|
|
|
|
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
|
|
|
|
index f9275160c3..fd37eab380 100644
|
|
|
|
--- a/src/tests/meta-monitor-manager-test.c
|
|
|
|
+++ b/src/tests/meta-monitor-manager-test.c
|
|
|
|
@@ -517,6 +517,12 @@ meta_crtc_test_set_gamma_lut (MetaCrtc *crtc,
|
|
|
|
sizeof (uint16_t) * lut->size);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static int64_t
|
|
|
|
+meta_crtc_test_get_deadline_evasion (MetaCrtcNative *crtc_native)
|
|
|
|
+{
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_crtc_test_finalize (GObject *object)
|
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
diff --git a/src/tests/native-kms-render.c b/src/tests/native-kms-render.c
|
2024-07-30 08:28:28 +00:00
|
|
|
index f5ebc23fec..2f870fdc33 100644
|
2024-06-23 12:05:15 +00:00
|
|
|
--- a/src/tests/native-kms-render.c
|
|
|
|
+++ b/src/tests/native-kms-render.c
|
|
|
|
@@ -39,6 +39,8 @@
|
|
|
|
#include "tests/meta-wayland-test-driver.h"
|
|
|
|
#include "tests/meta-wayland-test-utils.h"
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+#define N_FRAMES_PER_TEST 30
|
|
|
|
+
|
|
|
|
typedef struct
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
int number_of_frames_left;
|
|
|
|
@@ -46,12 +48,15 @@ typedef struct
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
struct {
|
|
|
|
int n_paints;
|
|
|
|
- uint32_t fb_id;
|
|
|
|
+ int n_presentations;
|
|
|
|
+ int n_direct_scanouts;
|
|
|
|
+ GList *fb_ids;
|
|
|
|
} scanout;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
gboolean wait_for_scanout;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
+ int scanouts_attempted;
|
|
|
|
gboolean scanout_sabotaged;
|
|
|
|
gboolean fallback_painted;
|
|
|
|
guint repaint_guard_id;
|
|
|
|
@@ -101,7 +106,7 @@ meta_test_kms_render_basic (void)
|
|
|
|
gulong handler_id;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
|
|
|
test = (KmsRenderingTest) {
|
2024-06-23 12:05:15 +00:00
|
|
|
- .number_of_frames_left = 10,
|
2024-05-08 13:03:56 +00:00
|
|
|
+ .number_of_frames_left = N_FRAMES_PER_TEST,
|
|
|
|
.loop = g_main_loop_new (NULL, FALSE),
|
|
|
|
};
|
2024-06-23 12:05:15 +00:00
|
|
|
handler_id = g_signal_connect (stage, "after-update",
|
|
|
|
@@ -123,7 +128,6 @@ on_scanout_before_update (ClutterStage *stage,
|
|
|
|
KmsRenderingTest *test)
|
2024-05-08 13:03:56 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
test->scanout.n_paints = 0;
|
|
|
|
- test->scanout.fb_id = 0;
|
|
|
|
}
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
|
|
|
@@ -135,6 +139,7 @@ on_scanout_before_paint (ClutterStage *stage,
|
|
|
|
CoglScanout *scanout;
|
|
|
|
CoglScanoutBuffer *scanout_buffer;
|
|
|
|
MetaDrmBuffer *buffer;
|
|
|
|
+ uint32_t fb_id;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
scanout = clutter_stage_view_peek_scanout (stage_view);
|
|
|
|
if (!scanout)
|
|
|
|
@@ -143,8 +148,13 @@ on_scanout_before_paint (ClutterStage *stage,
|
|
|
|
scanout_buffer = cogl_scanout_get_buffer (scanout);
|
|
|
|
g_assert_true (META_IS_DRM_BUFFER (scanout_buffer));
|
|
|
|
buffer = META_DRM_BUFFER (scanout_buffer);
|
|
|
|
- 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));
|
2024-05-08 13:03:56 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ /* Triple buffering, but no higher */
|
|
|
|
+ g_assert_cmpuint (g_list_length (test->scanout.fb_ids), <=, 2);
|
2024-05-08 13:03:56 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
|
|
|
@@ -173,12 +183,12 @@ on_scanout_presented (ClutterStage *stage,
|
|
|
|
MetaDeviceFile *device_file;
|
|
|
|
GError *error = NULL;
|
|
|
|
drmModeCrtc *drm_crtc;
|
|
|
|
+ uint32_t first_fb_id_expected;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (test->wait_for_scanout && test->scanout.n_paints > 0)
|
|
|
|
+ if (test->wait_for_scanout && test->scanout.fb_ids == NULL)
|
|
|
|
return;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (test->wait_for_scanout && test->scanout.fb_id == 0)
|
|
|
|
- return;
|
|
|
|
+ test->scanout.n_presentations++;
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
device_pool = meta_backend_native_get_device_pool (backend_native);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
@@ -197,15 +207,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);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
meta_device_file_release (device_file);
|
2024-05-08 13:03:56 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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));
|
2022-10-27 14:41:22 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
typedef enum
|
|
|
|
@@ -244,7 +280,9 @@ meta_test_kms_render_client_scanout (void)
|
|
|
|
g_assert_nonnull (wayland_test_client);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
test = (KmsRenderingTest) {
|
|
|
|
+ .number_of_frames_left = N_FRAMES_PER_TEST,
|
|
|
|
.loop = g_main_loop_new (NULL, FALSE),
|
|
|
|
+ .scanout = {0},
|
|
|
|
.wait_for_scanout = TRUE,
|
|
|
|
};
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
@@ -270,7 +308,8 @@ meta_test_kms_render_client_scanout (void)
|
|
|
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
|
|
|
g_main_loop_run (test.loop);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
g_debug ("Unmake fullscreen");
|
|
|
|
window = meta_find_window_from_title (test_context, "dma-buf-scanout-test");
|
|
|
|
@@ -292,10 +331,15 @@ meta_test_kms_render_client_scanout (void)
|
|
|
|
g_assert_cmpint (buffer_rect.y, ==, 10);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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;
|
2022-10-27 14:41:22 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
|
|
|
g_main_loop_run (test.loop);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
g_debug ("Moving back to 0, 0");
|
|
|
|
meta_window_move_frame (window, TRUE, 0, 0);
|
|
|
|
@@ -307,10 +351,15 @@ meta_test_kms_render_client_scanout (void)
|
|
|
|
g_assert_cmpint (buffer_rect.y, ==, 0);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
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);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- 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);
|
2022-10-27 14:41:22 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
g_signal_handler_disconnect (stage, before_update_handler_id);
|
|
|
|
g_signal_handler_disconnect (stage, before_paint_handler_id);
|
|
|
|
@@ -364,6 +413,15 @@ on_scanout_fallback_before_paint (ClutterStage *stage,
|
|
|
|
if (!scanout)
|
|
|
|
return;
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
+ test->scanout_fallback.scanouts_attempted++;
|
2023-05-02 10:55:11 +00:00
|
|
|
+
|
2024-06-23 12:05:15 +00:00
|
|
|
+ /* The first scanout candidate frame will get composited due to triple
|
|
|
|
+ * buffering draining the queue to drop to double buffering. So don't
|
|
|
|
+ * sabotage that first frame.
|
|
|
|
+ */
|
|
|
|
+ if (test->scanout_fallback.scanouts_attempted < 2)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
g_assert_false (test->scanout_fallback.scanout_sabotaged);
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
if (is_atomic_mode_setting (kms_device))
|
|
|
|
@@ -401,6 +459,15 @@ on_scanout_fallback_paint_view (ClutterStage *stage,
|
|
|
|
g_clear_handle_id (&test->scanout_fallback.repaint_guard_id,
|
|
|
|
g_source_remove);
|
|
|
|
test->scanout_fallback.fallback_painted = TRUE;
|
|
|
|
+ test->scanout_fallback.scanout_sabotaged = FALSE;
|
|
|
|
+ }
|
|
|
|
+ else if (test->scanout_fallback.scanouts_attempted == 1)
|
|
|
|
+ {
|
|
|
|
+ /* Now that we've seen the first scanout attempt that was inhibited by
|
|
|
|
+ * triple buffering, try a second frame. The second one should scanout
|
|
|
|
+ * and will be sabotaged.
|
|
|
|
+ */
|
|
|
|
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
|
|
|
}
|
2023-05-02 10:55:11 +00:00
|
|
|
}
|
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
@@ -410,11 +477,11 @@ on_scanout_fallback_presented (ClutterStage *stage,
|
|
|
|
ClutterFrameInfo *frame_info,
|
|
|
|
KmsRenderingTest *test)
|
2023-05-02 10:55:11 +00:00
|
|
|
{
|
2024-06-23 12:05:15 +00:00
|
|
|
- if (!test->scanout_fallback.scanout_sabotaged)
|
|
|
|
- return;
|
|
|
|
+ if (test->scanout_fallback.fallback_painted)
|
|
|
|
+ g_main_loop_quit (test->loop);
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
- g_assert_true (test->scanout_fallback.fallback_painted);
|
|
|
|
- g_main_loop_quit (test->loop);
|
|
|
|
+ test->number_of_frames_left--;
|
|
|
|
+ g_assert_cmpint (test->number_of_frames_left, >, 0);
|
|
|
|
}
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
static void
|
|
|
|
@@ -443,6 +510,7 @@ meta_test_kms_render_client_scanout_fallback (void)
|
|
|
|
g_assert_nonnull (wayland_test_client);
|
2023-05-02 10:55:11 +00:00
|
|
|
|
2024-06-23 12:05:15 +00:00
|
|
|
test = (KmsRenderingTest) {
|
|
|
|
+ .number_of_frames_left = N_FRAMES_PER_TEST,
|
|
|
|
.loop = g_main_loop_new (NULL, FALSE),
|
|
|
|
};
|
2023-05-02 10:55:11 +00:00
|
|
|
|