c/multi: Start and stop the native session

This depends on the number of active app sessions.
This commit is contained in:
Jakob Bornecrantz 2022-06-16 21:48:19 +01:00 committed by Jakob Bornecrantz
parent 601143bfb7
commit 2632c2239d
3 changed files with 160 additions and 8 deletions

View file

@ -458,7 +458,12 @@ multi_compositor_begin_session(struct xrt_compositor *xc, enum xrt_view_type typ
COMP_TRACE_MARKER();
struct multi_compositor *mc = multi_compositor(xc);
(void)mc;
assert(!mc->state.session_active);
if (!mc->state.session_active) {
multi_system_compositor_update_session_status(mc->msc, true);
mc->state.session_active = true;
}
return XRT_SUCCESS;
}
@ -469,7 +474,12 @@ multi_compositor_end_session(struct xrt_compositor *xc)
COMP_TRACE_MARKER();
struct multi_compositor *mc = multi_compositor(xc);
(void)mc;
assert(mc->state.session_active);
if (mc->state.session_active) {
multi_system_compositor_update_session_status(mc->msc, false);
mc->state.session_active = false;
}
return XRT_SUCCESS;
}
@ -829,6 +839,11 @@ multi_compositor_destroy(struct xrt_compositor *xc)
struct multi_compositor *mc = multi_compositor(xc);
if (mc->state.session_active) {
multi_system_compositor_update_session_status(mc->msc, false);
mc->state.session_active = false;
}
os_mutex_lock(&mc->msc->list_and_timing_lock);
// Remove it from the list of clients.

View file

@ -124,6 +124,8 @@ struct multi_compositor
} current;
int64_t z_order;
bool session_active;
} state;
struct
@ -224,6 +226,42 @@ multi_compositor_deliver_any_frames(struct multi_compositor *mc, uint64_t displa
*
*/
/*!
* State of the multi compositor system, use to track the calling of native
* compositor methods @ref xrt_comp_begin_session and @ref xrt_comp_end_session.
*
* It is driven by the number of active app sessions.
*
* @ingroup comp_multi
*/
enum multi_system_state
{
/*!
* Initial state and post stopping state.
*
* The multi system compositor have called @ref xrt_comp_end_session
* on it's @ref xrt_compositor_native.
*/
MULTI_SYSTEM_STATE_STOPPED,
/*!
* The main session is running.
*
* The multi system compositor have called @ref xrt_comp_begin_session
* on it's @ref xrt_compositor_native.
*/
MULTI_SYSTEM_STATE_RUNNING,
/*!
* There are no active sessions and the multi compositor system is
* drawing on or more clear frames.
*
* The multi system compositor have not yet @ref xrt_comp_begin_session
* on it's @ref xrt_compositor_native.
*/
MULTI_SYSTEM_STATE_STOPPING,
};
/*!
* The multi compositor system, multiplexes access to the native compositors
* and tracks some state needed.
@ -246,6 +284,19 @@ struct multi_system_compositor
//! Render loop thread.
struct os_thread_helper oth;
struct
{
/*!
* The state of the multi compositor system, this is updated on
* the oth thread, aka multi compositor system main thread.
* It is driven by the active_count field.
*/
enum multi_system_state state;
//! Number of active sessions, protected by oth.
uint64_t active_count;
} sessions;
/*!
* This mutex protects the list of client compositor
* and the rendering timings on it.
@ -268,6 +319,14 @@ multi_system_compositor(struct xrt_system_compositor *xsc)
return (struct multi_system_compositor *)xsc;
}
/*!
* The client compositor calls this function to update when it's session is
* started or stopped.
*
* @ingroup comp_multi
*/
void
multi_system_compositor_update_session_status(struct multi_system_compositor *msc, bool active);
#ifdef __cplusplus

View file

@ -353,6 +353,43 @@ wait_frame(struct xrt_compositor *xc, int64_t frame_id, uint64_t wake_up_time_ns
xrt_comp_mark_frame(xc, frame_id, XRT_COMPOSITOR_FRAME_POINT_WOKE, now_ns);
}
static void
update_session_state_locked(struct multi_system_compositor *msc)
{
struct xrt_compositor *xc = &msc->xcn->base;
//! @todo Don't make this a hack.
enum xrt_view_type view_type = XRT_VIEW_TYPE_STEREO;
switch (msc->sessions.state) {
case MULTI_SYSTEM_STATE_STOPPED:
if (msc->sessions.active_count == 0) {
break;
}
U_LOG_I("Starting native session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
msc->sessions.state = MULTI_SYSTEM_STATE_RUNNING;
xrt_comp_begin_session(xc, view_type);
break;
case MULTI_SYSTEM_STATE_RUNNING:
if (msc->sessions.active_count > 0) {
break;
}
U_LOG_I("Stopping main session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
msc->sessions.state = MULTI_SYSTEM_STATE_STOPPING;
break;
case MULTI_SYSTEM_STATE_STOPPING:
U_LOG_I("Stopped main session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
msc->sessions.state = MULTI_SYSTEM_STATE_STOPPED;
xrt_comp_end_session(xc);
break;
default: assert(false);
}
}
static int
multi_main_loop(struct multi_system_compositor *msc)
{
@ -362,13 +399,23 @@ multi_main_loop(struct multi_system_compositor *msc)
struct xrt_compositor *xc = &msc->xcn->base;
//! @todo Don't make this a hack.
enum xrt_view_type view_type = XRT_VIEW_TYPE_STEREO;
xrt_comp_begin_session(xc, view_type);
// Protect the thread state and the sessions state.
os_thread_helper_lock(&msc->oth);
while (os_thread_helper_is_running_locked(&msc->oth)) {
// Updates msc->sessions.active depending on active client sessions.
update_session_state_locked(msc);
if (msc->sessions.state == MULTI_SYSTEM_STATE_STOPPED) {
// Sleep and wait to be signaled.
os_thread_helper_wait_locked(&msc->oth);
// Loop back to running and session check.
continue;
}
// Unlock the thread after the checks has been done.
os_thread_helper_unlock(&msc->oth);
int64_t frame_id = -1;
@ -412,7 +459,17 @@ multi_main_loop(struct multi_system_compositor *msc)
os_thread_helper_lock(&msc->oth);
}
xrt_comp_end_session(xc);
// Clean up the sessions state.
switch (msc->sessions.state) {
case MULTI_SYSTEM_STATE_RUNNING:
case MULTI_SYSTEM_STATE_STOPPING:
U_LOG_I("Stopped native session, shutting down.");
xrt_comp_end_session(xc);
break;
case MULTI_SYSTEM_STATE_STOPPED: break;
default: assert(false);
}
os_thread_helper_unlock(&msc->oth);
return 0;
@ -524,6 +581,25 @@ system_compositor_destroy(struct xrt_system_compositor *xsc)
*
*/
void
multi_system_compositor_update_session_status(struct multi_system_compositor *msc, bool active)
{
os_thread_helper_lock(&msc->oth);
if (active) {
assert(msc->sessions.active_count < UINT32_MAX);
msc->sessions.active_count++;
// If the thread is sleeping wake it up.
os_thread_helper_signal_locked(&msc->oth);
} else {
assert(msc->sessions.active_count > 0);
msc->sessions.active_count--;
}
os_thread_helper_unlock(&msc->oth);
}
xrt_result_t
comp_multi_create_system_compositor(struct xrt_compositor_native *xcn,
struct u_pacing_app_factory *upaf,
@ -540,6 +616,8 @@ comp_multi_create_system_compositor(struct xrt_compositor_native *xcn,
msc->base.info = *xsci;
msc->upaf = upaf;
msc->xcn = xcn;
msc->sessions.state = MULTI_SYSTEM_STATE_STOPPED;
msc->sessions.active_count = 0;
os_mutex_init(&msc->list_and_timing_lock);