···124124 } current;
125125126126 int64_t z_order;
127127+128128+ bool session_active;
127129 } state;
128130129131 struct
···225227 */
226228227229/*!
230230+ * State of the multi compositor system, use to track the calling of native
231231+ * compositor methods @ref xrt_comp_begin_session and @ref xrt_comp_end_session.
232232+ *
233233+ * It is driven by the number of active app sessions.
234234+ *
235235+ * @ingroup comp_multi
236236+ */
237237+enum multi_system_state
238238+{
239239+ /*!
240240+ * Initial state and post stopping state.
241241+ *
242242+ * The multi system compositor have called @ref xrt_comp_end_session
243243+ * on it's @ref xrt_compositor_native.
244244+ */
245245+ MULTI_SYSTEM_STATE_STOPPED,
246246+247247+ /*!
248248+ * The main session is running.
249249+ *
250250+ * The multi system compositor have called @ref xrt_comp_begin_session
251251+ * on it's @ref xrt_compositor_native.
252252+ */
253253+ MULTI_SYSTEM_STATE_RUNNING,
254254+255255+ /*!
256256+ * There are no active sessions and the multi compositor system is
257257+ * drawing on or more clear frames.
258258+ *
259259+ * The multi system compositor have not yet @ref xrt_comp_begin_session
260260+ * on it's @ref xrt_compositor_native.
261261+ */
262262+ MULTI_SYSTEM_STATE_STOPPING,
263263+};
264264+265265+/*!
228266 * The multi compositor system, multiplexes access to the native compositors
229267 * and tracks some state needed.
230268 *
···246284 //! Render loop thread.
247285 struct os_thread_helper oth;
248286287287+ struct
288288+ {
289289+ /*!
290290+ * The state of the multi compositor system, this is updated on
291291+ * the oth thread, aka multi compositor system main thread.
292292+ * It is driven by the active_count field.
293293+ */
294294+ enum multi_system_state state;
295295+296296+ //! Number of active sessions, protected by oth.
297297+ uint64_t active_count;
298298+ } sessions;
299299+249300 /*!
250301 * This mutex protects the list of client compositor
251302 * and the rendering timings on it.
···268319 return (struct multi_system_compositor *)xsc;
269320}
270321322322+/*!
323323+ * The client compositor calls this function to update when it's session is
324324+ * started or stopped.
325325+ *
326326+ * @ingroup comp_multi
327327+ */
328328+void
329329+multi_system_compositor_update_session_status(struct multi_system_compositor *msc, bool active);
271330272331273332#ifdef __cplusplus
+84-6
src/xrt/compositor/multi/comp_multi_system.c
···353353 xrt_comp_mark_frame(xc, frame_id, XRT_COMPOSITOR_FRAME_POINT_WOKE, now_ns);
354354}
355355356356+static void
357357+update_session_state_locked(struct multi_system_compositor *msc)
358358+{
359359+ struct xrt_compositor *xc = &msc->xcn->base;
360360+361361+ //! @todo Don't make this a hack.
362362+ enum xrt_view_type view_type = XRT_VIEW_TYPE_STEREO;
363363+364364+ switch (msc->sessions.state) {
365365+ case MULTI_SYSTEM_STATE_STOPPED:
366366+ if (msc->sessions.active_count == 0) {
367367+ break;
368368+ }
369369+370370+ U_LOG_I("Starting native session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
371371+ msc->sessions.state = MULTI_SYSTEM_STATE_RUNNING;
372372+ xrt_comp_begin_session(xc, view_type);
373373+ break;
374374+375375+ case MULTI_SYSTEM_STATE_RUNNING:
376376+ if (msc->sessions.active_count > 0) {
377377+ break;
378378+ }
379379+ U_LOG_I("Stopping main session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
380380+ msc->sessions.state = MULTI_SYSTEM_STATE_STOPPING;
381381+ break;
382382+383383+ case MULTI_SYSTEM_STATE_STOPPING:
384384+ U_LOG_I("Stopped main session, %u active app session(s).", (uint32_t)msc->sessions.active_count);
385385+ msc->sessions.state = MULTI_SYSTEM_STATE_STOPPED;
386386+ xrt_comp_end_session(xc);
387387+ break;
388388+389389+ default: assert(false);
390390+ }
391391+}
392392+356393static int
357394multi_main_loop(struct multi_system_compositor *msc)
358395{
···362399363400 struct xrt_compositor *xc = &msc->xcn->base;
364401365365- //! @todo Don't make this a hack.
366366- enum xrt_view_type view_type = XRT_VIEW_TYPE_STEREO;
367367-368368- xrt_comp_begin_session(xc, view_type);
369369-402402+ // Protect the thread state and the sessions state.
370403 os_thread_helper_lock(&msc->oth);
404404+371405 while (os_thread_helper_is_running_locked(&msc->oth)) {
406406+407407+ // Updates msc->sessions.active depending on active client sessions.
408408+ update_session_state_locked(msc);
409409+410410+ if (msc->sessions.state == MULTI_SYSTEM_STATE_STOPPED) {
411411+ // Sleep and wait to be signaled.
412412+ os_thread_helper_wait_locked(&msc->oth);
413413+414414+ // Loop back to running and session check.
415415+ continue;
416416+ }
417417+418418+ // Unlock the thread after the checks has been done.
372419 os_thread_helper_unlock(&msc->oth);
373420374421 int64_t frame_id = -1;
···412459 os_thread_helper_lock(&msc->oth);
413460 }
414461415415- xrt_comp_end_session(xc);
462462+ // Clean up the sessions state.
463463+ switch (msc->sessions.state) {
464464+ case MULTI_SYSTEM_STATE_RUNNING:
465465+ case MULTI_SYSTEM_STATE_STOPPING:
466466+ U_LOG_I("Stopped native session, shutting down.");
467467+ xrt_comp_end_session(xc);
468468+ break;
469469+ case MULTI_SYSTEM_STATE_STOPPED: break;
470470+ default: assert(false);
471471+ }
472472+416473 os_thread_helper_unlock(&msc->oth);
417474418475 return 0;
···524581 *
525582 */
526583584584+void
585585+multi_system_compositor_update_session_status(struct multi_system_compositor *msc, bool active)
586586+{
587587+ os_thread_helper_lock(&msc->oth);
588588+589589+ if (active) {
590590+ assert(msc->sessions.active_count < UINT32_MAX);
591591+ msc->sessions.active_count++;
592592+593593+ // If the thread is sleeping wake it up.
594594+ os_thread_helper_signal_locked(&msc->oth);
595595+ } else {
596596+ assert(msc->sessions.active_count > 0);
597597+ msc->sessions.active_count--;
598598+ }
599599+600600+ os_thread_helper_unlock(&msc->oth);
601601+}
602602+527603xrt_result_t
528604comp_multi_create_system_compositor(struct xrt_compositor_native *xcn,
529605 struct u_pacing_app_factory *upaf,
···540616 msc->base.info = *xsci;
541617 msc->upaf = upaf;
542618 msc->xcn = xcn;
619619+ msc->sessions.state = MULTI_SYSTEM_STATE_STOPPED;
620620+ msc->sessions.active_count = 0;
543621544622 os_mutex_init(&msc->list_and_timing_lock);
545623