2021-11-12 08:43:54 +00:00
|
|
|
Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
|
|
|
|
Source: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1441
|
2021-11-24 14:38:22 +00:00
|
|
|
Editor: Joakim Soderlund <joakim.soderlund@gmail.com>
|
|
|
|
Editor: Sung Mingi <FiestaLake@protonmail.com>
|
|
|
|
Commit: 3b3978c60e6c67e5fe5262d528d5330bc12181d0
|
2021-11-12 08:43:54 +00:00
|
|
|
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.c b/clutter/clutter/clutter-frame-clock.c
|
|
|
|
index 16098b70f..27bbfd323 100644
|
|
|
|
--- a/clutter/clutter/clutter-frame-clock.c
|
|
|
|
+++ b/clutter/clutter/clutter-frame-clock.c
|
|
|
|
@@ -68,8 +68,9 @@ typedef enum _ClutterFrameClockState
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_INIT,
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_IDLE,
|
|
|
|
CLUTTER_FRAME_CLOCK_STATE_SCHEDULED,
|
|
|
|
- CLUTTER_FRAME_CLOCK_STATE_DISPATCHING,
|
|
|
|
- CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED,
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE,
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED,
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO,
|
|
|
|
} ClutterFrameClockState;
|
|
|
|
|
|
|
|
struct _ClutterFrameClock
|
|
|
|
@@ -99,6 +100,8 @@ struct _ClutterFrameClock
|
|
|
|
/* Last KMS buffer submission time. */
|
|
|
|
int64_t last_flip_time_us;
|
|
|
|
|
|
|
|
+ ClutterFrameHint last_flip_hints;
|
|
|
|
+
|
|
|
|
/* Last few durations between dispatch start and buffer swap. */
|
|
|
|
EstimateQueue dispatch_to_swap_us;
|
|
|
|
/* Last few durations between buffer swap and GPU rendering finish. */
|
|
|
|
@@ -278,9 +281,21 @@ clutter_frame_clock_notify_presented (ClutterFrameClock *frame_clock,
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
g_warn_if_reached ();
|
|
|
|
break;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
|
|
+ maybe_reschedule_update (frame_clock);
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ /* The GPU has caught up now so we can start using
|
|
|
|
+ * last_presentation_time_us again. But rather than dropping back to
|
|
|
|
+ * SCHEDULED, let's force a reschedule from IDLE. This way we'll get a
|
|
|
|
+ * more precise next update time based on last_presentation_time_us.
|
|
|
|
+ */
|
|
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
|
|
+ clutter_frame_clock_schedule_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;
|
|
|
|
}
|
|
|
|
@@ -296,11 +311,18 @@ clutter_frame_clock_notify_ready (ClutterFrameClock *frame_clock)
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
g_warn_if_reached ();
|
|
|
|
break;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
|
|
maybe_reschedule_update (frame_clock);
|
|
|
|
break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
+ maybe_reschedule_update (frame_clock);
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
+ maybe_reschedule_update (frame_clock);
|
|
|
|
+ break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -375,7 +397,8 @@ calculate_next_update_time_us (ClutterFrameClock *frame_clock,
|
|
|
|
|
|
|
|
refresh_interval_us = frame_clock->refresh_interval_us;
|
|
|
|
|
|
|
|
- if (frame_clock->last_presentation_time_us == 0)
|
|
|
|
+ if (frame_clock->last_presentation_time_us == 0 ||
|
|
|
|
+ frame_clock->state >= CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE)
|
|
|
|
{
|
|
|
|
*out_next_update_time_us =
|
|
|
|
frame_clock->last_dispatch_time_us ?
|
|
|
|
@@ -518,8 +541,12 @@ clutter_frame_clock_inhibit (ClutterFrameClock *frame_clock)
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
|
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
|
|
break;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -555,11 +582,17 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
next_update_time_us = g_get_monotonic_time ();
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
break;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
return;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ next_update_time_us = g_get_monotonic_time ();
|
|
|
|
+ frame_clock->state =
|
|
|
|
+ CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
|
|
|
frame_clock->pending_reschedule_now = TRUE;
|
|
|
|
return;
|
|
|
|
@@ -568,7 +601,6 @@ clutter_frame_clock_schedule_update_now (ClutterFrameClock *frame_clock)
|
|
|
|
g_warn_if_fail (next_update_time_us != -1);
|
|
|
|
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
frame_clock->is_next_presentation_time_valid = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -587,6 +619,7 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
|
|
{
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
next_update_time_us = g_get_monotonic_time ();
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
break;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
calculate_next_update_time_us (frame_clock,
|
|
|
|
@@ -594,11 +627,27 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
|
|
&frame_clock->next_presentation_time_us);
|
|
|
|
frame_clock->is_next_presentation_time_valid =
|
|
|
|
(frame_clock->next_presentation_time_us != 0);
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
break;
|
|
|
|
case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
return;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ if (frame_clock->last_flip_hints & CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED)
|
|
|
|
+ {
|
|
|
|
+ /* Force double buffering, disable triple buffering */
|
|
|
|
+ frame_clock->pending_reschedule = TRUE;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ calculate_next_update_time_us (frame_clock,
|
|
|
|
+ &next_update_time_us,
|
|
|
|
+ &frame_clock->next_presentation_time_us);
|
|
|
|
+ frame_clock->is_next_presentation_time_valid =
|
|
|
|
+ (frame_clock->next_presentation_time_us != 0);
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
frame_clock->pending_reschedule = TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
@@ -606,7 +655,6 @@ clutter_frame_clock_schedule_update (ClutterFrameClock *frame_clock)
|
|
|
|
g_warn_if_fail (next_update_time_us != -1);
|
|
|
|
|
|
|
|
g_source_set_ready_time (frame_clock->source, next_update_time_us);
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -624,7 +672,7 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
|
|
frame_clock->refresh_interval_us;
|
|
|
|
|
|
|
|
lateness_us = time_us - ideal_dispatch_time_us;
|
|
|
|
- if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us)
|
|
|
|
+ if (lateness_us < 0 || lateness_us >= frame_clock->refresh_interval_us / 4)
|
|
|
|
frame_clock->last_dispatch_lateness_us = 0;
|
|
|
|
else
|
|
|
|
frame_clock->last_dispatch_lateness_us = lateness_us;
|
|
|
|
@@ -632,7 +680,21 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
|
|
frame_clock->last_dispatch_time_us = time_us;
|
|
|
|
g_source_set_ready_time (frame_clock->source, -1);
|
|
|
|
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHING;
|
|
|
|
+ switch (frame_clock->state)
|
|
|
|
+ {
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
+ g_warn_if_reached ();
|
|
|
|
+ return;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
frame_count = frame_clock->frame_count++;
|
|
|
|
|
|
|
|
@@ -656,25 +718,31 @@ clutter_frame_clock_dispatch (ClutterFrameClock *frame_clock,
|
|
|
|
frame_clock->listener.user_data);
|
|
|
|
COGL_TRACE_END (ClutterFrameClockFrame);
|
|
|
|
|
|
|
|
- switch (frame_clock->state)
|
|
|
|
+ switch (result)
|
|
|
|
{
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED:
|
|
|
|
- g_warn_if_reached ();
|
|
|
|
- break;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
|
|
break;
|
|
|
|
- case CLUTTER_FRAME_CLOCK_STATE_DISPATCHING:
|
|
|
|
- switch (result)
|
|
|
|
+ case CLUTTER_FRAME_RESULT_IDLE:
|
|
|
|
+ /* The frame was aborted; nothing to paint/present */
|
|
|
|
+ switch (frame_clock->state)
|
|
|
|
{
|
|
|
|
- case CLUTTER_FRAME_RESULT_PENDING_PRESENTED:
|
|
|
|
- frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_PENDING_PRESENTED;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_INIT:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_IDLE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_SCHEDULED:
|
|
|
|
+ g_warn_if_reached ();
|
|
|
|
break;
|
|
|
|
- case CLUTTER_FRAME_RESULT_IDLE:
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE:
|
|
|
|
frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_IDLE;
|
|
|
|
maybe_reschedule_update (frame_clock);
|
|
|
|
break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE_AND_SCHEDULED:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_SCHEDULED;
|
|
|
|
+ maybe_reschedule_update (frame_clock);
|
|
|
|
+ break;
|
|
|
|
+ case CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_TWO:
|
|
|
|
+ frame_clock->state = CLUTTER_FRAME_CLOCK_STATE_DISPATCHED_ONE;
|
|
|
|
+ maybe_reschedule_update (frame_clock);
|
|
|
|
+ break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
@@ -696,10 +764,12 @@ frame_clock_source_dispatch (GSource *source,
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
-clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
|
|
|
- int64_t flip_time_us)
|
|
|
|
+clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock,
|
|
|
|
+ int64_t flip_time_us,
|
|
|
|
+ ClutterFrameHint hints)
|
|
|
|
{
|
|
|
|
frame_clock->last_flip_time_us = flip_time_us;
|
|
|
|
+ frame_clock->last_flip_hints = hints;
|
|
|
|
}
|
|
|
|
|
|
|
|
GString *
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-clock.h b/clutter/clutter/clutter-frame-clock.h
|
|
|
|
index e71b54987..a37024e2d 100644
|
|
|
|
--- a/clutter/clutter/clutter-frame-clock.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame-clock.h
|
|
|
|
@@ -34,6 +34,12 @@ typedef enum _ClutterFrameResult
|
|
|
|
CLUTTER_FRAME_RESULT_IDLE,
|
|
|
|
} ClutterFrameResult;
|
|
|
|
|
|
|
|
+typedef enum _ClutterFrameHint
|
|
|
|
+{
|
|
|
|
+ CLUTTER_FRAME_HINT_NONE = 0,
|
|
|
|
+ CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED = 1 << 0,
|
|
|
|
+} ClutterFrameHint;
|
|
|
|
+
|
|
|
|
#define CLUTTER_TYPE_FRAME_CLOCK (clutter_frame_clock_get_type ())
|
|
|
|
CLUTTER_EXPORT
|
|
|
|
G_DECLARE_FINAL_TYPE (ClutterFrameClock, clutter_frame_clock,
|
|
|
|
@@ -91,8 +97,9 @@ void clutter_frame_clock_remove_timeline (ClutterFrameClock *frame_clock,
|
|
|
|
CLUTTER_EXPORT
|
|
|
|
float clutter_frame_clock_get_refresh_rate (ClutterFrameClock *frame_clock);
|
|
|
|
|
|
|
|
-void clutter_frame_clock_record_flip_time (ClutterFrameClock *frame_clock,
|
|
|
|
- int64_t flip_time_us);
|
|
|
|
+void clutter_frame_clock_record_flip (ClutterFrameClock *frame_clock,
|
|
|
|
+ int64_t flip_time_us,
|
|
|
|
+ ClutterFrameHint hints);
|
|
|
|
|
|
|
|
GString * clutter_frame_clock_get_max_render_time_debug_info (ClutterFrameClock *frame_clock);
|
|
|
|
|
|
|
|
diff --git a/clutter/clutter/clutter-frame-private.h b/clutter/clutter/clutter-frame-private.h
|
|
|
|
index e0088564f..06581492f 100644
|
|
|
|
--- a/clutter/clutter/clutter-frame-private.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame-private.h
|
|
|
|
@@ -24,6 +24,7 @@ struct _ClutterFrame
|
|
|
|
{
|
|
|
|
gboolean has_result;
|
|
|
|
ClutterFrameResult result;
|
|
|
|
+ ClutterFrameHint hints;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define CLUTTER_FRAME_INIT ((ClutterFrame) { 0 })
|
|
|
|
diff --git a/clutter/clutter/clutter-frame.c b/clutter/clutter/clutter-frame.c
|
|
|
|
index 3c708da9d..63ae302af 100644
|
|
|
|
--- a/clutter/clutter/clutter-frame.c
|
|
|
|
+++ b/clutter/clutter/clutter-frame.c
|
|
|
|
@@ -40,3 +40,16 @@ clutter_frame_set_result (ClutterFrame *frame,
|
|
|
|
frame->result = result;
|
|
|
|
frame->has_result = TRUE;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+clutter_frame_set_hint (ClutterFrame *frame,
|
|
|
|
+ ClutterFrameHint hint)
|
|
|
|
+{
|
|
|
|
+ frame->hints |= hint;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ClutterFrameHint
|
|
|
|
+clutter_frame_get_hints (ClutterFrame *frame)
|
|
|
|
+{
|
|
|
|
+ return frame->hints;
|
|
|
|
+}
|
|
|
|
diff --git a/clutter/clutter/clutter-frame.h b/clutter/clutter/clutter-frame.h
|
|
|
|
index d3608e81c..06c5f7f28 100644
|
|
|
|
--- a/clutter/clutter/clutter-frame.h
|
|
|
|
+++ b/clutter/clutter/clutter-frame.h
|
|
|
|
@@ -33,4 +33,11 @@ void clutter_frame_set_result (ClutterFrame *frame,
|
|
|
|
CLUTTER_EXPORT
|
|
|
|
gboolean clutter_frame_has_result (ClutterFrame *frame);
|
|
|
|
|
|
|
|
+CLUTTER_EXPORT
|
|
|
|
+void clutter_frame_set_hint (ClutterFrame *frame,
|
|
|
|
+ ClutterFrameHint hint);
|
|
|
|
+
|
|
|
|
+CLUTTER_EXPORT
|
|
|
|
+ClutterFrameHint clutter_frame_get_hints (ClutterFrame *frame);
|
|
|
|
+
|
|
|
|
#endif /* CLUTTER_FRAME_H */
|
|
|
|
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
|
|
|
|
index 9b7345983..f8da6e37c 100644
|
|
|
|
--- a/clutter/clutter/clutter-stage-view.c
|
|
|
|
+++ b/clutter/clutter/clutter-stage-view.c
|
|
|
|
@@ -1189,8 +1189,9 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
|
|
|
|
|
|
|
|
_clutter_stage_window_redraw_view (stage_window, view, &frame);
|
|
|
|
|
|
|
|
- clutter_frame_clock_record_flip_time (frame_clock,
|
|
|
|
- g_get_monotonic_time ());
|
|
|
|
+ clutter_frame_clock_record_flip (frame_clock,
|
|
|
|
+ g_get_monotonic_time (),
|
|
|
|
+ clutter_frame_get_hints (&frame));
|
|
|
|
|
|
|
|
clutter_stage_emit_after_paint (stage, view);
|
|
|
|
|
|
|
|
diff --git a/cogl/cogl/cogl-onscreen-private.h b/cogl/cogl/cogl-onscreen-private.h
|
|
|
|
index dffe018d2..e0215f750 100644
|
|
|
|
--- a/cogl/cogl/cogl-onscreen-private.h
|
|
|
|
+++ b/cogl/cogl/cogl-onscreen-private.h
|
|
|
|
@@ -97,4 +97,7 @@ cogl_onscreen_peek_tail_frame_info (CoglOnscreen *onscreen);
|
|
|
|
COGL_EXPORT CoglFrameInfo *
|
|
|
|
cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen);
|
|
|
|
|
|
|
|
+COGL_EXPORT unsigned int
|
|
|
|
+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen);
|
|
|
|
+
|
|
|
|
#endif /* __COGL_ONSCREEN_PRIVATE_H */
|
|
|
|
diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c
|
|
|
|
index cff5df50c..6f159cbb2 100644
|
|
|
|
--- a/cogl/cogl/cogl-onscreen.c
|
|
|
|
+++ b/cogl/cogl/cogl-onscreen.c
|
|
|
|
@@ -497,6 +497,14 @@ cogl_onscreen_pop_head_frame_info (CoglOnscreen *onscreen)
|
|
|
|
return g_queue_pop_head (&priv->pending_frame_infos);
|
|
|
|
}
|
|
|
|
|
|
|
|
+unsigned int
|
|
|
|
+cogl_onscreen_count_pending_frames (CoglOnscreen *onscreen)
|
|
|
|
+{
|
|
|
|
+ CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
|
|
|
|
+
|
|
|
|
+ return g_queue_get_length (&priv->pending_frame_infos);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
CoglFrameClosure *
|
|
|
|
cogl_onscreen_add_frame_callback (CoglOnscreen *onscreen,
|
|
|
|
CoglFrameCallback callback,
|
|
|
|
diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c
|
|
|
|
index 28534ec81..bbed4fcf2 100644
|
|
|
|
--- a/src/backends/meta-stage-impl.c
|
|
|
|
+++ b/src/backends/meta-stage-impl.c
|
|
|
|
@@ -670,6 +670,8 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window,
|
|
|
|
{
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
+ clutter_frame_set_hint (frame, CLUTTER_FRAME_HINT_DIRECT_SCANOUT_ATTEMPTED);
|
|
|
|
+
|
|
|
|
if (meta_stage_impl_scanout_view (stage_impl,
|
|
|
|
stage_view,
|
|
|
|
scanout,
|
|
|
|
diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c
|
|
|
|
index effa0851d..24e089a88 100644
|
|
|
|
--- a/src/backends/native/meta-cursor-renderer-native.c
|
|
|
|
+++ b/src/backends/native/meta-cursor-renderer-native.c
|
|
|
|
@@ -64,19 +64,6 @@
|
|
|
|
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
|
|
|
#endif
|
|
|
|
|
|
|
|
-/* When animating a cursor, we usually call drmModeSetCursor2 once per frame.
|
|
|
|
- * Though, testing shows that we need to triple buffer the cursor buffer in
|
|
|
|
- * order to avoid glitches when animating the cursor, at least when running on
|
|
|
|
- * Intel. The reason for this might be (but is not confirmed to be) due to
|
|
|
|
- * the user space gbm_bo cache, making us reuse and overwrite the kernel side
|
|
|
|
- * buffer content before it was scanned out. To avoid this, we keep a user space
|
|
|
|
- * reference to each buffer we set until at least one frame after it was drawn.
|
|
|
|
- * In effect, this means we three active cursor gbm_bo's: one that that just has
|
|
|
|
- * been set, one that was previously set and may or may not have been scanned
|
|
|
|
- * out, and one pending that will be replaced if the cursor sprite changes.
|
|
|
|
- */
|
|
|
|
-#define HW_CURSOR_BUFFER_COUNT 3
|
|
|
|
-
|
|
|
|
static GQuark quark_cursor_sprite = 0;
|
|
|
|
|
|
|
|
typedef struct _CrtcCursorData
|
|
|
|
@@ -110,19 +97,10 @@ typedef struct _MetaCursorRendererNativeGpuData
|
|
|
|
uint64_t cursor_height;
|
|
|
|
} MetaCursorRendererNativeGpuData;
|
|
|
|
|
|
|
|
-typedef enum _MetaCursorBufferState
|
|
|
|
-{
|
|
|
|
- META_CURSOR_BUFFER_STATE_NONE,
|
|
|
|
- META_CURSOR_BUFFER_STATE_SET,
|
|
|
|
- META_CURSOR_BUFFER_STATE_INVALIDATED,
|
|
|
|
-} MetaCursorBufferState;
|
|
|
|
-
|
|
|
|
typedef struct _MetaCursorNativeGpuState
|
|
|
|
{
|
|
|
|
MetaGpu *gpu;
|
|
|
|
- unsigned int active_buffer_idx;
|
|
|
|
- MetaCursorBufferState pending_buffer_state;
|
|
|
|
- MetaDrmBuffer *buffers[HW_CURSOR_BUFFER_COUNT];
|
|
|
|
+ MetaDrmBuffer *buffer;
|
|
|
|
} MetaCursorNativeGpuState;
|
|
|
|
|
|
|
|
typedef struct _MetaCursorNativePrivate
|
|
|
|
@@ -199,44 +177,17 @@ meta_cursor_renderer_native_finalize (GObject *object)
|
|
|
|
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
-static unsigned int
|
|
|
|
-get_pending_cursor_sprite_buffer_index (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
|
|
-{
|
|
|
|
- return (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static MetaDrmBuffer *
|
|
|
|
-get_pending_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
|
|
-{
|
|
|
|
- unsigned int pending_buffer_idx;
|
|
|
|
-
|
|
|
|
- pending_buffer_idx =
|
|
|
|
- get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
|
|
- return cursor_gpu_state->buffers[pending_buffer_idx];
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static MetaDrmBuffer *
|
|
|
|
-get_active_cursor_sprite_buffer (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
|
|
-{
|
|
|
|
- return cursor_gpu_state->buffers[cursor_gpu_state->active_buffer_idx];
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void
|
|
|
|
-set_pending_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
|
|
- MetaGpuKms *gpu_kms,
|
|
|
|
- MetaDrmBuffer *buffer)
|
|
|
|
+set_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
|
|
+ MetaGpuKms *gpu_kms,
|
|
|
|
+ MetaDrmBuffer *buffer)
|
|
|
|
{
|
|
|
|
MetaCursorNativePrivate *cursor_priv;
|
|
|
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
|
|
|
- unsigned int pending_buffer_idx;
|
|
|
|
|
|
|
|
cursor_priv = ensure_cursor_priv (cursor_sprite);
|
|
|
|
cursor_gpu_state = ensure_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
|
|
-
|
|
|
|
- pending_buffer_idx =
|
|
|
|
- get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
|
|
- cursor_gpu_state->buffers[pending_buffer_idx] = buffer;
|
|
|
|
- cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_SET;
|
|
|
|
+ cursor_gpu_state->buffer = buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -311,10 +262,7 @@ assign_cursor_plane (MetaCursorRendererNative *native,
|
|
|
|
MetaKmsUpdate *kms_update;
|
|
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
|
|
|
|
- if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
|
|
|
- buffer = get_pending_cursor_sprite_buffer (cursor_gpu_state);
|
|
|
|
- else
|
|
|
|
- buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
|
|
|
+ buffer = cursor_gpu_state->buffer;
|
|
|
|
|
|
|
|
kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
|
|
kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
|
|
@@ -365,13 +313,6 @@ assign_cursor_plane (MetaCursorRendererNative *native,
|
|
|
|
native);
|
|
|
|
|
|
|
|
crtc_cursor_data->buffer = buffer;
|
|
|
|
-
|
|
|
|
- if (cursor_gpu_state->pending_buffer_state == META_CURSOR_BUFFER_STATE_SET)
|
|
|
|
- {
|
|
|
|
- cursor_gpu_state->active_buffer_idx =
|
|
|
|
- (cursor_gpu_state->active_buffer_idx + 1) % HW_CURSOR_BUFFER_COUNT;
|
|
|
|
- cursor_gpu_state->pending_buffer_state = META_CURSOR_BUFFER_STATE_NONE;
|
|
|
|
- }
|
|
|
|
}
|
|
|
|
|
|
|
|
static float
|
|
|
|
@@ -599,19 +540,7 @@ has_valid_cursor_sprite_buffer (MetaCursorSprite *cursor_sprite,
|
|
|
|
if (!cursor_gpu_state)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
- switch (cursor_gpu_state->pending_buffer_state)
|
|
|
|
- {
|
|
|
|
- case META_CURSOR_BUFFER_STATE_NONE:
|
|
|
|
- return get_active_cursor_sprite_buffer (cursor_gpu_state) != NULL;
|
|
|
|
- case META_CURSOR_BUFFER_STATE_SET:
|
|
|
|
- return TRUE;
|
|
|
|
- case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
|
|
|
- return FALSE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- g_assert_not_reached ();
|
|
|
|
-
|
|
|
|
- return FALSE;
|
|
|
|
+ return cursor_gpu_state->buffer != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -1114,16 +1043,14 @@ unset_crtc_cursor_renderer_privates (MetaGpu *gpu,
|
|
|
|
static void
|
|
|
|
cursor_gpu_state_free (MetaCursorNativeGpuState *cursor_gpu_state)
|
|
|
|
{
|
|
|
|
- int i;
|
|
|
|
MetaDrmBuffer *active_buffer;
|
|
|
|
|
|
|
|
- active_buffer = get_active_cursor_sprite_buffer (cursor_gpu_state);
|
|
|
|
+ active_buffer = cursor_gpu_state->buffer;
|
|
|
|
if (active_buffer)
|
|
|
|
unset_crtc_cursor_renderer_privates (cursor_gpu_state->gpu,
|
|
|
|
active_buffer);
|
|
|
|
|
|
|
|
- for (i = 0; i < HW_CURSOR_BUFFER_COUNT; i++)
|
|
|
|
- g_clear_object (&cursor_gpu_state->buffers[i]);
|
|
|
|
+ g_clear_object (&cursor_gpu_state->buffer);
|
|
|
|
g_free (cursor_gpu_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1160,14 +1087,7 @@ invalidate_cursor_gpu_state (MetaCursorSprite *cursor_sprite)
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, cursor_priv->gpu_states);
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state))
|
|
|
|
- {
|
|
|
|
- unsigned int pending_buffer_idx;
|
|
|
|
-
|
|
|
|
- pending_buffer_idx = get_pending_cursor_sprite_buffer_index (cursor_gpu_state);
|
|
|
|
- g_clear_object (&cursor_gpu_state->buffers[pending_buffer_idx]);
|
|
|
|
- cursor_gpu_state->pending_buffer_state =
|
|
|
|
- META_CURSOR_BUFFER_STATE_INVALIDATED;
|
|
|
|
- }
|
|
|
|
+ g_clear_object (&cursor_gpu_state->buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -1302,8 +1222,8 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
|
|
- META_DRM_BUFFER (buffer_gbm));
|
|
|
|
+ set_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
|
|
+ META_DRM_BUFFER (buffer_gbm));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
@@ -1311,34 +1231,6 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
-static gboolean
|
|
|
|
-is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
|
|
|
|
- MetaGpuKms *gpu_kms)
|
|
|
|
-{
|
|
|
|
- MetaCursorNativePrivate *cursor_priv;
|
|
|
|
- MetaCursorNativeGpuState *cursor_gpu_state;
|
|
|
|
-
|
|
|
|
- cursor_priv = get_cursor_priv (cursor_sprite);
|
|
|
|
- if (!cursor_priv)
|
|
|
|
- return FALSE;
|
|
|
|
-
|
|
|
|
- cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
|
|
|
- if (!cursor_gpu_state)
|
|
|
|
- return FALSE;
|
|
|
|
-
|
|
|
|
- switch (cursor_gpu_state->pending_buffer_state)
|
|
|
|
- {
|
|
|
|
- case META_CURSOR_BUFFER_STATE_SET:
|
|
|
|
- case META_CURSOR_BUFFER_STATE_NONE:
|
|
|
|
- return TRUE;
|
|
|
|
- case META_CURSOR_BUFFER_STATE_INVALIDATED:
|
|
|
|
- return FALSE;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- g_assert_not_reached ();
|
|
|
|
- return FALSE;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static gboolean
|
|
|
|
is_cursor_scale_and_transform_valid (MetaCursorRenderer *renderer,
|
|
|
|
MetaCursorSprite *cursor_sprite)
|
|
|
|
@@ -1503,7 +1395,7 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
|
|
|
return;
|
|
|
|
|
|
|
|
- if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
|
|
+ if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) &&
|
|
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
|
|
|
return;
|
|
|
|
|
|
|
|
@@ -1642,8 +1534,8 @@ realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- set_pending_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
|
|
- META_DRM_BUFFER (buffer_gbm));
|
|
|
|
+ set_cursor_sprite_buffer (cursor_sprite, gpu_kms,
|
|
|
|
+ META_DRM_BUFFER (buffer_gbm));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
@@ -1667,7 +1559,7 @@ realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
|
|
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
|
|
|
return;
|
|
|
|
|
|
|
|
- if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms) &&
|
|
|
|
+ if (has_valid_cursor_sprite_buffer (cursor_sprite, gpu_kms) &&
|
|
|
|
is_cursor_scale_and_transform_valid (renderer, cursor_sprite))
|
|
|
|
return;
|
|
|
|
|
|
|
|
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
|
2021-11-24 14:38:22 +00:00
|
|
|
index 4599f4455..ea2ca73a6 100644
|
2021-11-12 08:43:54 +00:00
|
|
|
--- a/src/backends/native/meta-kms-crtc.c
|
|
|
|
+++ b/src/backends/native/meta-kms-crtc.c
|
|
|
|
@@ -32,6 +32,12 @@ typedef struct _MetaKmsCrtcPropTable
|
|
|
|
MetaKmsProp props[META_KMS_CRTC_N_PROPS];
|
|
|
|
} MetaKmsCrtcPropTable;
|
|
|
|
|
|
|
|
+typedef struct
|
|
|
|
+{
|
|
|
|
+ MetaDrmBuffer *front, *back;
|
|
|
|
+ gboolean back_is_set;
|
|
|
|
+} PlaneState;
|
|
|
|
+
|
|
|
|
struct _MetaKmsCrtc
|
|
|
|
{
|
|
|
|
GObject parent;
|
|
|
|
@@ -44,6 +50,8 @@ struct _MetaKmsCrtc
|
|
|
|
MetaKmsCrtcState current_state;
|
|
|
|
|
|
|
|
MetaKmsCrtcPropTable prop_table;
|
|
|
|
+
|
|
|
|
+ GHashTable *plane_states;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaKmsCrtc, meta_kms_crtc, G_TYPE_OBJECT)
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -432,20 +440,86 @@ meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
|
2021-11-12 08:43:54 +00:00
|
|
|
return crtc;
|
|
|
|
}
|
|
|
|
|
|
|
|
+void
|
|
|
|
+meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc,
|
|
|
|
+ uint32_t plane_id,
|
|
|
|
+ MetaDrmBuffer *buffer)
|
|
|
|
+{
|
|
|
|
+ gpointer key = GUINT_TO_POINTER (plane_id);
|
|
|
|
+ PlaneState *plane_state;
|
|
|
|
+
|
|
|
|
+ plane_state = g_hash_table_lookup (crtc->plane_states, key);
|
|
|
|
+ if (plane_state == NULL)
|
|
|
|
+ {
|
|
|
|
+ plane_state = g_new0 (PlaneState, 1);
|
|
|
|
+ g_return_if_fail (plane_state);
|
|
|
|
+ g_hash_table_insert (crtc->plane_states, key, plane_state);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ plane_state->back_is_set = TRUE; /* note buffer may be NULL */
|
|
|
|
+ g_set_object (&plane_state->back, buffer);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+swap_plane_buffers (gpointer key,
|
|
|
|
+ gpointer value,
|
|
|
|
+ gpointer user_data)
|
|
|
|
+{
|
|
|
|
+ PlaneState *plane_state = value;
|
|
|
|
+
|
|
|
|
+ if (plane_state->back_is_set)
|
|
|
|
+ {
|
|
|
|
+ g_set_object (&plane_state->front, plane_state->back);
|
|
|
|
+ g_clear_object (&plane_state->back);
|
|
|
|
+ plane_state->back_is_set = FALSE;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc)
|
|
|
|
+{
|
|
|
|
+ g_hash_table_foreach (crtc->plane_states, swap_plane_buffers, NULL);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+meta_kms_crtc_dispose (GObject *object)
|
|
|
|
+{
|
|
|
|
+ MetaKmsCrtc *crtc = META_KMS_CRTC (object);
|
|
|
|
+
|
|
|
|
+ g_hash_table_remove_all (crtc->plane_states);
|
|
|
|
+
|
|
|
|
+ G_OBJECT_CLASS (meta_kms_crtc_parent_class)->dispose (object);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_kms_crtc_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaKmsCrtc *crtc = META_KMS_CRTC (object);
|
|
|
|
|
|
|
|
clear_gamma_state (&crtc->current_state);
|
|
|
|
+ g_hash_table_unref (crtc->plane_states);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_kms_crtc_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+destroy_plane_state (gpointer data)
|
|
|
|
+{
|
|
|
|
+ PlaneState *plane_state = data;
|
|
|
|
+
|
|
|
|
+ g_clear_object (&plane_state->front);
|
|
|
|
+ g_clear_object (&plane_state->back);
|
|
|
|
+ g_free (plane_state);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
static void
|
|
|
|
meta_kms_crtc_init (MetaKmsCrtc *crtc)
|
|
|
|
{
|
|
|
|
crtc->current_state.gamma.size = 0;
|
|
|
|
+ crtc->plane_states = g_hash_table_new_full (NULL,
|
|
|
|
+ NULL,
|
|
|
|
+ NULL,
|
|
|
|
+ destroy_plane_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -453,5 +527,6 @@ meta_kms_crtc_class_init (MetaKmsCrtcClass *klass)
|
2021-11-12 08:43:54 +00:00
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
+ object_class->dispose = meta_kms_crtc_dispose;
|
|
|
|
object_class->finalize = meta_kms_crtc_finalize;
|
|
|
|
}
|
|
|
|
diff --git a/src/backends/native/meta-kms-crtc.h b/src/backends/native/meta-kms-crtc.h
|
|
|
|
index 406ca3ac1..1a0d9f1b6 100644
|
|
|
|
--- a/src/backends/native/meta-kms-crtc.h
|
|
|
|
+++ b/src/backends/native/meta-kms-crtc.h
|
|
|
|
@@ -25,6 +25,7 @@
|
|
|
|
#include <xf86drmMode.h>
|
|
|
|
|
|
|
|
#include "backends/native/meta-kms-types.h"
|
|
|
|
+#include "backends/native/meta-drm-buffer.h"
|
|
|
|
#include "meta/boxes.h"
|
|
|
|
|
|
|
|
typedef struct _MetaKmsCrtcState
|
|
|
|
@@ -76,4 +77,10 @@ MetaKmsCrtcGamma * meta_kms_crtc_gamma_new (MetaKmsCrtc *crtc,
|
|
|
|
const uint16_t *green,
|
|
|
|
const uint16_t *blue);
|
|
|
|
|
|
|
|
+void meta_kms_crtc_remember_plane_buffer (MetaKmsCrtc *crtc,
|
|
|
|
+ uint32_t plane_id,
|
|
|
|
+ MetaDrmBuffer *buffer);
|
|
|
|
+
|
|
|
|
+void meta_kms_crtc_on_scanout_started (MetaKmsCrtc *crtc);
|
|
|
|
+
|
|
|
|
#endif /* META_KMS_CRTC_H */
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-atomic.c b/src/backends/native/meta-kms-impl-device-atomic.c
|
2021-11-24 14:38:22 +00:00
|
|
|
index e1adf20b3..3221168b7 100644
|
2021-11-12 08:43:54 +00:00
|
|
|
--- a/src/backends/native/meta-kms-impl-device-atomic.c
|
|
|
|
+++ b/src/backends/native/meta-kms-impl-device-atomic.c
|
|
|
|
@@ -495,6 +495,10 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
error))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc,
|
|
|
|
+ meta_kms_plane_get_id (plane),
|
|
|
|
+ buffer);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
@@ -522,6 +526,10 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
error))
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc,
|
|
|
|
+ meta_kms_plane_get_id (plane),
|
|
|
|
+ NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (plane_assignment->rotation)
|
|
|
|
diff --git a/src/backends/native/meta-kms-impl-device-simple.c b/src/backends/native/meta-kms-impl-device-simple.c
|
|
|
|
index 28d512720..2f3c99928 100644
|
|
|
|
--- a/src/backends/native/meta-kms-impl-device-simple.c
|
|
|
|
+++ b/src/backends/native/meta-kms-impl-device-simple.c
|
|
|
|
@@ -1275,7 +1275,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
{
|
|
|
|
case META_KMS_PLANE_TYPE_PRIMARY:
|
|
|
|
/* Handled as part of the mode-set and page flip. */
|
|
|
|
- return TRUE;
|
|
|
|
+ goto assigned;
|
|
|
|
case META_KMS_PLANE_TYPE_CURSOR:
|
|
|
|
if (!process_cursor_plane_assignment (impl_device, update,
|
|
|
|
plane_assignment,
|
|
|
|
@@ -1289,7 +1289,7 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
- return TRUE;
|
|
|
|
+ goto assigned;
|
|
|
|
}
|
|
|
|
case META_KMS_PLANE_TYPE_OVERLAY:
|
|
|
|
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
@@ -1302,6 +1302,12 @@ process_plane_assignment (MetaKmsImplDevice *impl_device,
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
+
|
|
|
|
+assigned:
|
|
|
|
+ meta_kms_crtc_remember_plane_buffer (plane_assignment->crtc,
|
|
|
|
+ meta_kms_plane_get_id (plane),
|
|
|
|
+ plane_assignment->buffer);
|
|
|
|
+ return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
diff --git a/src/backends/native/meta-kms-page-flip.c b/src/backends/native/meta-kms-page-flip.c
|
|
|
|
index 817f4e7c8..148d23740 100644
|
|
|
|
--- a/src/backends/native/meta-kms-page-flip.c
|
|
|
|
+++ b/src/backends/native/meta-kms-page-flip.c
|
|
|
|
@@ -24,6 +24,7 @@
|
|
|
|
#include "backends/native/meta-kms-impl.h"
|
|
|
|
#include "backends/native/meta-kms-private.h"
|
|
|
|
#include "backends/native/meta-kms-update.h"
|
|
|
|
+#include "backends/native/meta-kms-crtc.h"
|
|
|
|
|
|
|
|
typedef struct _MetaKmsPageFlipClosure
|
|
|
|
{
|
|
|
|
@@ -149,6 +150,8 @@ meta_kms_page_flip_data_flipped (MetaKms *kms,
|
|
|
|
|
|
|
|
meta_assert_not_in_kms_impl (kms);
|
|
|
|
|
|
|
|
+ meta_kms_crtc_on_scanout_started (page_flip_data->crtc);
|
|
|
|
+
|
|
|
|
for (l = page_flip_data->closures; l; l = l->next)
|
|
|
|
{
|
|
|
|
MetaKmsPageFlipClosure *closure = l->data;
|
|
|
|
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
|
|
|
|
index 71e5b423f..a98e8ade6 100644
|
|
|
|
--- a/src/backends/native/meta-kms-update.c
|
|
|
|
+++ b/src/backends/native/meta-kms-update.c
|
|
|
|
@@ -140,6 +140,7 @@ static void
|
|
|
|
meta_kms_plane_assignment_free (MetaKmsPlaneAssignment *plane_assignment)
|
|
|
|
{
|
|
|
|
g_clear_pointer (&plane_assignment->fb_damage, meta_kms_fb_damage_free);
|
|
|
|
+ g_clear_object (&plane_assignment->buffer);
|
|
|
|
g_free (plane_assignment);
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -220,7 +221,7 @@ meta_kms_update_assign_plane (MetaKmsUpdate *update,
|
|
|
|
.update = update,
|
|
|
|
.crtc = crtc,
|
|
|
|
.plane = plane,
|
|
|
|
- .buffer = buffer,
|
|
|
|
+ .buffer = g_object_ref (buffer),
|
|
|
|
.src_rect = src_rect,
|
|
|
|
.dst_rect = dst_rect,
|
|
|
|
.flags = flags,
|
|
|
|
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
|
|
|
|
index 0750278ae..061460b38 100644
|
|
|
|
--- a/src/backends/native/meta-kms.c
|
|
|
|
+++ b/src/backends/native/meta-kms.c
|
|
|
|
@@ -177,6 +177,8 @@ struct _MetaKms
|
|
|
|
|
|
|
|
GList *pending_callbacks;
|
|
|
|
guint callback_source_id;
|
|
|
|
+
|
|
|
|
+ gboolean shutting_down;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
|
|
|
|
@@ -277,6 +279,9 @@ meta_kms_post_pending_update_sync (MetaKms *kms,
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync,
|
|
|
|
"KMS (post update)");
|
|
|
|
|
|
|
|
+ if (kms->shutting_down)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
update = meta_kms_take_pending_update (kms, device);
|
|
|
|
if (!update)
|
|
|
|
return NULL;
|
|
|
|
@@ -757,6 +762,7 @@ prepare_shutdown_in_impl (MetaKmsImpl *impl,
|
|
|
|
void
|
|
|
|
meta_kms_prepare_shutdown (MetaKms *kms)
|
|
|
|
{
|
|
|
|
+ kms->shutting_down = TRUE;
|
|
|
|
meta_kms_run_impl_task_sync (kms, prepare_shutdown_in_impl, NULL, NULL);
|
|
|
|
flush_callbacks (kms);
|
|
|
|
}
|
|
|
|
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
|
2021-11-24 14:38:22 +00:00
|
|
|
index 00b2d9f89..eacfd2cc1 100644
|
2021-11-12 08:43:54 +00:00
|
|
|
--- a/src/backends/native/meta-onscreen-native.c
|
|
|
|
+++ b/src/backends/native/meta-onscreen-native.c
|
|
|
|
@@ -46,6 +46,8 @@
|
|
|
|
#include "backends/native/meta-renderer-native-gles3.h"
|
|
|
|
#include "backends/native/meta-renderer-native-private.h"
|
|
|
|
|
|
|
|
+#define MAX_CONCURRENT_POSTS 1
|
|
|
|
+
|
|
|
|
typedef enum _MetaSharedFramebufferImportStatus
|
|
|
|
{
|
|
|
|
/* Not tried importing yet. */
|
|
|
|
@@ -65,7 +67,6 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct gbm_surface *surface;
|
|
|
|
- MetaDrmBuffer *current_fb;
|
|
|
|
MetaDrmBuffer *next_fb;
|
|
|
|
} gbm;
|
|
|
|
|
|
|
|
@@ -92,8 +93,13 @@ struct _MetaOnscreenNative
|
|
|
|
|
|
|
|
struct {
|
|
|
|
struct gbm_surface *surface;
|
|
|
|
- MetaDrmBuffer *current_fb;
|
|
|
|
MetaDrmBuffer *next_fb;
|
|
|
|
+
|
|
|
|
+ struct {
|
|
|
|
+ uint32_t format;
|
|
|
|
+ uint32_t stride;
|
|
|
|
+ uint64_t modifier;
|
|
|
|
+ } last_flip;
|
|
|
|
} gbm;
|
|
|
|
|
|
|
|
#ifdef HAVE_EGL_DEVICE
|
|
|
|
@@ -105,69 +111,25 @@ struct _MetaOnscreenNative
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MetaRendererView *view;
|
|
|
|
+
|
|
|
|
+ unsigned int swaps_pending;
|
|
|
|
+ struct {
|
|
|
|
+ int *rectangles; /* 4 x n_rectangles */
|
|
|
|
+ int n_rectangles;
|
|
|
|
+ } next_post;
|
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
|
|
|
|
COGL_TYPE_ONSCREEN_EGL)
|
|
|
|
|
|
|
|
+static void
|
|
|
|
+post_latest_swap (CoglOnscreen *onscreen);
|
|
|
|
+
|
|
|
|
static gboolean
|
|
|
|
init_secondary_gpu_state (MetaRendererNative *renderer_native,
|
|
|
|
CoglOnscreen *onscreen,
|
|
|
|
GError **error);
|
|
|
|
|
|
|
|
-static void
|
|
|
|
-swap_secondary_drm_fb (CoglOnscreen *onscreen)
|
|
|
|
-{
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
|
|
-
|
|
|
|
- secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
|
|
- if (!secondary_gpu_state)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- g_set_object (&secondary_gpu_state->gbm.current_fb,
|
|
|
|
- secondary_gpu_state->gbm.next_fb);
|
|
|
|
- g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void
|
|
|
|
-free_current_secondary_bo (CoglOnscreen *onscreen)
|
|
|
|
-{
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
- MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
|
|
|
-
|
|
|
|
- secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
|
|
- if (!secondary_gpu_state)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- g_clear_object (&secondary_gpu_state->gbm.current_fb);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void
|
|
|
|
-free_current_bo (CoglOnscreen *onscreen)
|
|
|
|
-{
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
-
|
|
|
|
- g_clear_object (&onscreen_native->gbm.current_fb);
|
|
|
|
- free_current_secondary_bo (onscreen);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void
|
|
|
|
-meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
|
|
|
-{
|
|
|
|
- MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
-
|
|
|
|
- if (!onscreen_native->gbm.next_fb)
|
|
|
|
- return;
|
|
|
|
-
|
|
|
|
- free_current_bo (onscreen);
|
|
|
|
-
|
|
|
|
- g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
-
|
|
|
|
- swap_secondary_drm_fb (onscreen);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void
|
|
|
|
maybe_update_frame_info (MetaCrtc *crtc,
|
|
|
|
CoglFrameInfo *frame_info,
|
|
|
|
@@ -203,7 +165,7 @@ meta_onscreen_native_notify_frame_complete (CoglOnscreen *onscreen)
|
|
|
|
|
|
|
|
info = cogl_onscreen_pop_head_frame_info (onscreen);
|
|
|
|
|
|
|
|
- g_assert (!cogl_onscreen_peek_head_frame_info (onscreen));
|
|
|
|
+ g_assert (info);
|
|
|
|
|
|
|
|
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
|
|
|
_cogl_onscreen_notify_complete (onscreen, info);
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -226,11 +188,13 @@ notify_view_crtc_presented (MetaRendererView *view,
|
|
|
|
|
|
|
|
frame_info = cogl_onscreen_peek_head_frame_info (onscreen);
|
|
|
|
|
|
|
|
+ g_return_if_fail (frame_info != NULL);
|
|
|
|
+
|
|
|
|
crtc = META_CRTC (meta_crtc_kms_from_kms_crtc (kms_crtc));
|
2021-11-12 08:43:54 +00:00
|
|
|
maybe_update_frame_info (crtc, frame_info, time_us, flags, sequence);
|
|
|
|
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
|
|
+ post_latest_swap (onscreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int64_t
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -292,6 +256,7 @@ page_flip_feedback_ready (MetaKmsCrtc *kms_crtc,
|
2021-11-12 08:43:54 +00:00
|
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
+ post_latest_swap (onscreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -341,7 +306,7 @@ page_flip_feedback_discarded (MetaKmsCrtc *kms_crtc,
|
2021-11-12 08:43:54 +00:00
|
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
|
|
+ post_latest_swap (onscreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const MetaKmsPageFlipListenerVtable page_flip_listener_vtable = {
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -405,11 +370,10 @@ meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen)
|
2021-11-12 08:43:54 +00:00
|
|
|
{
|
|
|
|
CoglFrameInfo *frame_info;
|
|
|
|
|
|
|
|
- meta_onscreen_native_swap_drm_fb (onscreen);
|
|
|
|
-
|
|
|
|
frame_info = cogl_onscreen_peek_tail_frame_info (onscreen);
|
|
|
|
frame_info->flags |= COGL_FRAME_INFO_FLAG_SYMBOLIC;
|
|
|
|
meta_onscreen_native_notify_frame_complete (onscreen);
|
|
|
|
+ post_latest_swap (onscreen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -431,7 +395,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
MetaKms *kms;
|
|
|
|
MetaKmsUpdate *kms_update;
|
|
|
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL;
|
|
|
|
- MetaDrmBuffer *buffer;
|
|
|
|
+ g_autoptr (MetaDrmBuffer) buffer = NULL;
|
|
|
|
MetaKmsPlaneAssignment *plane_assignment;
|
|
|
|
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -442,7 +406,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|
|
|
kms = meta_kms_device_get_kms (kms_device);
|
|
|
|
kms_update = meta_kms_ensure_pending_update (kms, kms_device);
|
|
|
|
|
|
|
|
- g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
|
|
|
|
+ g_return_if_fail (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
|
|
|
|
|
|
|
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
render_gpu);
|
|
|
|
@@ -451,12 +415,14 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
|
|
if (gpu_kms == render_gpu)
|
|
|
|
{
|
|
|
|
- buffer = onscreen_native->gbm.next_fb;
|
|
|
|
+ buffer = g_object_ref (onscreen_native->gbm.next_fb);
|
|
|
|
+ g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
secondary_gpu_state = onscreen_native->secondary_gpu_state;
|
|
|
|
- buffer = secondary_gpu_state->gbm.next_fb;
|
|
|
|
+ buffer = g_object_ref (secondary_gpu_state->gbm.next_fb);
|
|
|
|
+ g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
|
|
}
|
|
|
|
|
|
|
|
plane_assignment = meta_crtc_kms_assign_primary_plane (crtc_kms,
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -468,6 +434,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
meta_kms_plane_assignment_set_fb_damage (plane_assignment,
|
|
|
|
rectangles, n_rectangles);
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ if (META_IS_DRM_BUFFER_GBM (buffer))
|
|
|
|
+ {
|
|
|
|
+ MetaDrmBufferGbm *buffer_gbm = META_DRM_BUFFER_GBM (buffer);
|
|
|
|
+ struct gbm_bo *gbm_bo = meta_drm_buffer_gbm_get_bo (buffer_gbm);
|
|
|
|
+
|
|
|
|
+ onscreen_native->gbm.last_flip.format = gbm_bo_get_format (gbm_bo);
|
|
|
|
+ onscreen_native->gbm.last_flip.modifier = gbm_bo_get_modifier (gbm_bo);
|
|
|
|
+ onscreen_native->gbm.last_flip.stride = gbm_bo_get_stride (gbm_bo);
|
|
|
|
+
|
|
|
|
+ g_object_set_data_full (G_OBJECT (buffer_gbm),
|
|
|
|
+ "gbm_surface owner",
|
|
|
|
+ g_object_ref (onscreen),
|
|
|
|
+ (GDestroyNotify) g_object_unref);
|
|
|
|
+ }
|
|
|
|
break;
|
|
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
|
|
g_assert_not_reached ();
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -556,7 +537,6 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
|
2021-11-12 08:43:54 +00:00
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
- g_clear_object (&secondary_gpu_state->gbm.current_fb);
|
|
|
|
g_clear_object (&secondary_gpu_state->gbm.next_fb);
|
|
|
|
g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy);
|
|
|
|
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1004,12 +984,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +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);
|
|
|
|
- MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
|
|
|
- MetaMonitorManager *monitor_manager =
|
|
|
|
- meta_backend_get_monitor_manager (backend);
|
|
|
|
- MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
|
|
|
MetaDeviceFile *render_device_file;
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1017,14 +991,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
CoglOnscreenClass *parent_class;
|
|
|
|
gboolean egl_context_changed = FALSE;
|
|
|
|
gboolean use_modifiers;
|
|
|
|
- MetaPowerSave power_save_mode;
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
MetaDrmBufferGbm *buffer_gbm;
|
|
|
|
- MetaKmsCrtc *kms_crtc;
|
|
|
|
- MetaKmsDevice *kms_device;
|
|
|
|
- MetaKmsUpdateFlag flags;
|
|
|
|
- g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
|
|
- const GError *feedback_error;
|
|
|
|
+ size_t rectangles_size;
|
|
|
|
|
|
|
|
COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
|
|
|
|
"Onscreen (swap-buffers)");
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1044,7 +1013,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|
|
|
switch (renderer_gpu_data->mode)
|
|
|
|
{
|
|
|
|
case META_RENDERER_NATIVE_MODE_GBM:
|
|
|
|
- g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
|
|
g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
|
|
|
|
use_modifiers = meta_renderer_native_use_modifiers (renderer_native);
|
|
|
|
@@ -1073,6 +1041,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
+ clutter_frame_set_result (frame,
|
|
|
|
+ CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
+
|
|
|
|
update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
|
|
|
|
|
|
|
|
/*
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1084,6 +1055,48 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
if (egl_context_changed)
|
|
|
|
_cogl_winsys_egl_ensure_current (cogl_display);
|
|
|
|
|
|
|
|
+ rectangles_size = n_rectangles * 4 * sizeof (int);
|
|
|
|
+ onscreen_native->next_post.rectangles =
|
|
|
|
+ g_realloc (onscreen_native->next_post.rectangles, rectangles_size);
|
|
|
|
+ memcpy (onscreen_native->next_post.rectangles, rectangles, rectangles_size);
|
|
|
|
+ onscreen_native->next_post.n_rectangles = n_rectangles;
|
|
|
|
+
|
|
|
|
+ onscreen_native->swaps_pending++;
|
|
|
|
+
|
|
|
|
+ /* The new frame is already counted by cogl so that's why it is "<=" */
|
|
|
|
+ if (cogl_onscreen_count_pending_frames (onscreen) <= MAX_CONCURRENT_POSTS)
|
|
|
|
+ post_latest_swap (onscreen);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+post_latest_swap (CoglOnscreen *onscreen)
|
|
|
|
+{
|
|
|
|
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
|
|
|
+ CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
|
|
|
|
+ CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
|
|
|
+ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
|
|
|
+ MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
|
|
|
+ MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
|
|
|
|
+ MetaRenderer *renderer = META_RENDERER (renderer_native);
|
|
|
|
+ MetaBackend *backend = meta_renderer_get_backend (renderer);
|
|
|
|
+ MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
|
|
|
|
+ MetaMonitorManager *monitor_manager =
|
|
|
|
+ meta_backend_get_monitor_manager (backend);
|
|
|
|
+ MetaKms *kms = meta_backend_native_get_kms (backend_native);
|
|
|
|
+ MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
+ MetaPowerSave power_save_mode;
|
|
|
|
+ MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
|
|
|
|
+ MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
|
|
|
|
+ MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
|
|
|
|
+ MetaKmsUpdateFlag flags;
|
|
|
|
+ g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
|
|
+ const GError *feedback_error;
|
|
|
|
+
|
|
|
|
+ if (onscreen_native->swaps_pending == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ onscreen_native->swaps_pending--;
|
|
|
|
+
|
|
|
|
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
|
|
|
|
if (power_save_mode == META_POWER_SAVE_ON)
|
|
|
|
{
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1092,15 +1105,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
onscreen_native->view,
|
|
|
|
onscreen_native->crtc,
|
|
|
|
META_KMS_PAGE_FLIP_LISTENER_FLAG_NONE,
|
|
|
|
- rectangles,
|
|
|
|
- n_rectangles);
|
|
|
|
+ onscreen_native->next_post.rectangles,
|
|
|
|
+ onscreen_native->next_post.n_rectangles);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
meta_renderer_native_queue_power_save_page_flip (renderer_native,
|
|
|
|
onscreen);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1118,9 +1129,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
"Postponing primary plane composite update for CRTC %u (%s)",
|
|
|
|
meta_kms_crtc_get_id (kms_crtc),
|
|
|
|
meta_kms_device_get_path (kms_device));
|
|
|
|
-
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (meta_renderer_native_has_pending_mode_set (renderer_native))
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1130,8 +1138,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
|
|
|
|
meta_renderer_native_notify_mode_sets_reset (renderer_native);
|
|
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1144,8 +1150,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
{
|
|
|
|
meta_renderer_native_notify_mode_sets_reset (renderer_native);
|
|
|
|
meta_renderer_native_post_mode_set_updates (renderer_native);
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1159,17 +1163,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
|
|
|
|
flags = META_KMS_UPDATE_FLAG_NONE;
|
|
|
|
kms_feedback = meta_kms_post_pending_update_sync (kms, kms_device, flags);
|
|
|
|
+ g_return_if_fail (kms_feedback != NULL);
|
|
|
|
|
|
|
|
switch (meta_kms_feedback_get_result (kms_feedback))
|
|
|
|
{
|
|
|
|
case META_KMS_FEEDBACK_PASSED:
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
break;
|
|
|
|
case META_KMS_FEEDBACK_FAILED:
|
|
|
|
- clutter_frame_set_result (frame,
|
|
|
|
- CLUTTER_FRAME_RESULT_PENDING_PRESENTED);
|
|
|
|
-
|
|
|
|
feedback_error = meta_kms_feedback_get_error (kms_feedback);
|
|
|
|
if (!g_error_matches (feedback_error,
|
|
|
|
G_IO_ERROR,
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1187,8 +1187,6 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
{
|
|
|
|
MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
|
|
|
|
const MetaCrtcConfig *crtc_config;
|
|
|
|
- MetaDrmBuffer *fb;
|
|
|
|
- struct gbm_bo *gbm_bo;
|
|
|
|
|
|
|
|
crtc_config = meta_crtc_get_config (onscreen_native->crtc);
|
|
|
|
if (crtc_config->transform != META_MONITOR_TRANSFORM_NORMAL)
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1200,23 +1198,13 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
if (!onscreen_native->gbm.surface)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
- fb = onscreen_native->gbm.current_fb ? onscreen_native->gbm.current_fb
|
|
|
|
- : onscreen_native->gbm.next_fb;
|
|
|
|
- if (!fb)
|
2021-11-24 14:38:22 +00:00
|
|
|
- return FALSE;
|
|
|
|
-
|
2021-11-12 08:43:54 +00:00
|
|
|
- if (!META_IS_DRM_BUFFER_GBM (fb))
|
2021-11-24 14:38:22 +00:00
|
|
|
+ if (drm_format != onscreen_native->gbm.last_flip.format)
|
2021-11-12 08:43:54 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
- gbm_bo = meta_drm_buffer_gbm_get_bo (META_DRM_BUFFER_GBM (fb));
|
|
|
|
-
|
|
|
|
- if (gbm_bo_get_format (gbm_bo) != drm_format)
|
|
|
|
- return FALSE;
|
|
|
|
-
|
|
|
|
- if (gbm_bo_get_modifier (gbm_bo) != drm_modifier)
|
2021-11-24 14:38:22 +00:00
|
|
|
+ if (drm_modifier != onscreen_native->gbm.last_flip.modifier)
|
|
|
|
return FALSE;
|
|
|
|
|
2021-11-12 08:43:54 +00:00
|
|
|
- if (gbm_bo_get_stride (gbm_bo) != stride)
|
|
|
|
+ if (stride != onscreen_native->gbm.last_flip.stride)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1272,6 +1260,16 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ /* The new frame is already counted by cogl so that's why it is ">" */
|
|
|
|
+ if (cogl_onscreen_count_pending_frames (onscreen) > MAX_CONCURRENT_POSTS)
|
|
|
|
+ {
|
|
|
|
+ g_set_error_literal (error,
|
|
|
|
+ COGL_SCANOUT_ERROR,
|
|
|
|
+ COGL_SCANOUT_ERROR_INHIBITED,
|
|
|
|
+ "Direct scanout is inhibited during triple buffering");
|
|
|
|
+ return FALSE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
|
|
|
render_gpu);
|
|
|
|
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1338,7 +1336,6 @@ meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
|
|
|
|
break;
|
|
|
|
|
|
|
|
- g_clear_object (&onscreen_native->gbm.next_fb);
|
|
|
|
g_propagate_error (error, g_error_copy (feedback_error));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -1374,6 +1371,9 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
|
2021-11-12 08:43:54 +00:00
|
|
|
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
|
|
|
|
const GError *error;
|
|
|
|
|
|
|
|
+ if (cogl_onscreen_count_pending_frames (onscreen) >= MAX_CONCURRENT_POSTS)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
kms_update = meta_kms_get_pending_update (kms, kms_device);
|
|
|
|
if (!kms_update)
|
|
|
|
{
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -2069,10 +2069,10 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
|
|
|
|
"height", height,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
- onscreen_native->renderer_native = renderer_native;
|
|
|
|
- onscreen_native->render_gpu = render_gpu;
|
|
|
|
- onscreen_native->output = output;
|
|
|
|
- onscreen_native->crtc = crtc;
|
|
|
|
+ onscreen_native->renderer_native = g_object_ref (renderer_native);
|
|
|
|
+ onscreen_native->render_gpu = g_object_ref (render_gpu);
|
|
|
|
+ onscreen_native->output = g_object_ref (output);
|
|
|
|
+ onscreen_native->crtc = g_object_ref (crtc);
|
|
|
|
|
|
|
|
return onscreen_native;
|
|
|
|
}
|
|
|
|
@@ -2095,8 +2095,6 @@ meta_onscreen_native_dispose (GObject *object)
|
2021-11-12 08:43:54 +00:00
|
|
|
/* flip state takes a reference on the onscreen so there should
|
|
|
|
* never be outstanding flips when we reach here. */
|
|
|
|
g_warn_if_fail (onscreen_native->gbm.next_fb == NULL);
|
|
|
|
-
|
|
|
|
- free_current_bo (onscreen);
|
|
|
|
break;
|
|
|
|
case META_RENDERER_NATIVE_MODE_SURFACELESS:
|
|
|
|
g_assert_not_reached ();
|
2021-11-24 14:38:22 +00:00
|
|
|
@@ -2127,6 +2125,13 @@ meta_onscreen_native_dispose (GObject *object)
|
2021-11-12 08:43:54 +00:00
|
|
|
g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy);
|
|
|
|
g_clear_pointer (&onscreen_native->secondary_gpu_state,
|
|
|
|
secondary_gpu_state_free);
|
|
|
|
+ g_clear_pointer (&onscreen_native->next_post.rectangles, g_free);
|
|
|
|
+ onscreen_native->next_post.n_rectangles = 0;
|
2021-11-24 14:38:22 +00:00
|
|
|
+
|
|
|
|
+ g_clear_object (&onscreen_native->crtc);
|
|
|
|
+ g_clear_object (&onscreen_native->output);
|
|
|
|
+ g_clear_object (&onscreen_native->render_gpu);
|
|
|
|
+ g_clear_object (&onscreen_native->renderer_native);
|
2021-11-12 08:43:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-11-24 14:38:22 +00:00
|
|
|
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
|
|
|
|
index eb6771b80..f39b0e004 100644
|
|
|
|
--- a/src/backends/native/meta-renderer-native.c
|
|
|
|
+++ b/src/backends/native/meta-renderer-native.c
|
|
|
|
@@ -593,12 +593,18 @@ static gboolean
|
|
|
|
dummy_power_save_page_flip_cb (gpointer user_data)
|
|
|
|
{
|
|
|
|
MetaRendererNative *renderer_native = user_data;
|
|
|
|
+ GList *old_list =
|
|
|
|
+ g_steal_pointer (&renderer_native->power_save_page_flip_onscreens);
|
|
|
|
|
|
|
|
- g_list_foreach (renderer_native->power_save_page_flip_onscreens,
|
|
|
|
+ g_list_foreach (old_list,
|
|
|
|
(GFunc) meta_onscreen_native_dummy_power_save_page_flip,
|
|
|
|
NULL);
|
|
|
|
- g_clear_list (&renderer_native->power_save_page_flip_onscreens,
|
|
|
|
+ g_clear_list (&old_list,
|
|
|
|
g_object_unref);
|
|
|
|
+
|
|
|
|
+ if (renderer_native->power_save_page_flip_onscreens != NULL)
|
|
|
|
+ return G_SOURCE_CONTINUE;
|
|
|
|
+
|
|
|
|
renderer_native->power_save_page_flip_source_id = 0;
|
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|