From e03ee48dcea88427ac3272ccab70bb665b1618a4 Mon Sep 17 00:00:00 2001 From: Christoph Haag Date: Sat, 31 Oct 2020 18:39:16 +0100 Subject: [PATCH] comp: Transition to visible/focused after xrEndFrame, not xrWaitFrame The application synchronizes its frame loop by "by calling xrWaitFrame, xrBeginFrame and xrEndFrame in a loop." Applications can discard frames by not calling xrEndFrame. If initial frames are discarded, we should not consider the frame loop synchronized. Previously a sequence like xrBeginFrame, xrWaitFrame, xrBeginFrame, xrWaitFrame, xrPollEvent, xrBeginFrame failed because xrPollEvent the compositor emitted transitions to visible and focused but they were not emitted in the state tracker, because the oxr session had not internally tranisitioned to the synchronized state. --- src/xrt/compositor/main/comp_compositor.c | 15 ++++++--------- src/xrt/compositor/main/comp_compositor.h | 2 +- src/xrt/state_trackers/oxr/oxr_session.c | 5 +++++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/xrt/compositor/main/comp_compositor.c b/src/xrt/compositor/main/comp_compositor.c index afd58c7b1..da39a4391 100644 --- a/src/xrt/compositor/main/comp_compositor.c +++ b/src/xrt/compositor/main/comp_compositor.c @@ -210,9 +210,6 @@ compositor_wait_frame(struct xrt_compositor *xc, *predicted_display_time = c->last_next_display_time; *out_frame_id = c->last_next_display_time; - if (c->state == COMP_STATE_PREPARED) { - c->state = COMP_STATE_WAITED; - } return XRT_SUCCESS; } @@ -245,10 +242,6 @@ compositor_wait_frame(struct xrt_compositor *xc, *out_frame_id = c->last_next_display_time; c->last_next_display_time = next_display_time; - - if (c->state == COMP_STATE_PREPARED) { - c->state = COMP_STATE_WAITED; - } return XRT_SUCCESS; } } @@ -514,6 +507,10 @@ compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id) c->expected_app_duration_ns = c->app_profiling.last_end - c->app_profiling.last_begin; + if (c->state == COMP_STATE_PREPARED) { + c->state = COMP_STATE_COMMITTED; + } + // Now is a good point to garbage collect. comp_compositor_garbage_collect(c); return XRT_SUCCESS; @@ -535,8 +532,8 @@ compositor_poll_events(struct xrt_compositor *xc, case COMP_STATE_PREPARED: out_xce->state.type = XRT_COMPOSITOR_EVENT_NONE; break; - case COMP_STATE_WAITED: - COMP_DEBUG(c, "WAITED -> VISIBLE"); + case COMP_STATE_COMMITTED: + COMP_DEBUG(c, "COMMITTED -> VISIBLE"); out_xce->state.type = XRT_COMPOSITOR_EVENT_STATE_CHANGE; out_xce->state.visible = true; c->state = COMP_STATE_VISIBLE; diff --git a/src/xrt/compositor/main/comp_compositor.h b/src/xrt/compositor/main/comp_compositor.h index 9448704be..daea3a23e 100644 --- a/src/xrt/compositor/main/comp_compositor.h +++ b/src/xrt/compositor/main/comp_compositor.h @@ -129,7 +129,7 @@ enum comp_state { COMP_STATE_READY = 0, COMP_STATE_PREPARED = 1, - COMP_STATE_WAITED = 2, + COMP_STATE_COMMITTED = 2, COMP_STATE_VISIBLE = 3, COMP_STATE_FOCUSED = 4, }; diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index f9c872e2a..6245e6a07 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -1898,6 +1898,11 @@ oxr_session_frame_end(struct oxr_logger *log, do_synchronize_state_change(log, sess); + // For emitting state changes, the compositor has to know + // whether the client is synchronized, i.e. has called + // xrEndFrame, even with 0 layers. + CALL_CHK(xrt_comp_layer_commit(xc, -1)); + return oxr_session_success_result(sess); }