Monado OpenXR Runtime
comp_multi_private.h
Go to the documentation of this file.
1 // Copyright 2021, Collabora, Ltd.
2 // SPDX-License-Identifier: BSL-1.0
3 /*!
4  * @file
5  * @brief System compositor capable of supporting multiple clients: internal structs.
6  * @author Jakob Bornecrantz <jakob@collabora.com>
7  * @ingroup comp_multi
8  */
9 
10 #pragma once
11 
12 #include "xrt/xrt_compiler.h"
13 #include "xrt/xrt_defines.h"
14 #include "xrt/xrt_compositor.h"
15 
16 #include "os/os_time.h"
17 #include "os/os_threading.h"
18 
19 #include "util/u_pacing.h"
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 
26 /*!
27  * Number of max active clients.
28  *
29  * @todo Move to `xrt_limits.h`, or make dynamic to remove limit.
30  * @ingroup comp_multi
31  */
32 #define MULTI_MAX_CLIENTS 64
33 
34 /*!
35  * Number of max active layers per @ref multi_compositor.
36  *
37  * @todo Move to `xrt_limits.h` and share.
38  * @ingroup comp_multi
39  */
40 #define MULTI_MAX_LAYERS 16
41 
42 
43 /*
44  *
45  * Native compositor.
46  *
47  */
48 
49 /*!
50  * Data for a single composition layer.
51  *
52  * Similar in function to @ref comp_layer
53  *
54  * @ingroup comp_multi
55  */
57 {
58  /*!
59  * Device to get pose from.
60  */
61  struct xrt_device *xdev;
62 
63  /*!
64  * Pointers to swapchains.
65  *
66  * How many are actually used depends on the value of @p data.type
67  */
68  struct xrt_swapchain *xscs[2 * XRT_MAX_VIEWS];
69 
70  /*!
71  * All basic (trivially-serializable) data associated with a layer,
72  * aside from which swapchain(s) are used.
73  */
74  struct xrt_layer_data data;
75 };
76 
77 /*!
78  * Render state for a single client, including all layers.
79  *
80  * @ingroup comp_multi
81  */
83 {
84  struct xrt_layer_frame_data data;
85  uint32_t layer_count;
86  struct multi_layer_entry layers[MULTI_MAX_LAYERS];
87  bool active;
88 };
89 
90 /*!
91  * A single compositor for feeding the layers from one session/app into
92  * the multi-client-capable system compositor.
93  *
94  * An instance (usually an IPC server instance) might have several of
95  * these at once, feeding layers to a single multi-client-capable system
96  * compositor.
97  *
98  * @ingroup comp_multi
99  * @implements xrt_compositor_native
100  */
102 {
104 
105  // Client info.
106  struct xrt_session_info xsi;
107 
108  //! Where events for this compositor should go.
110 
111  //! Owning system compositor.
113 
114  //! Used to implement wait frame, only used for in process.
116 
117  //! Used when waiting for the scheduled frame to complete.
119 
120  struct
121  {
122  bool visible;
123  bool focused;
124 
125  int64_t z_order;
126 
127  bool session_active;
128  } state;
129 
130  struct
131  {
132  //! Fence to wait for.
134 
135  //! Timeline semaphore to wait for.
137 
138  //! Timeline semaphore value to wait for.
139  uint64_t value;
140 
141  //! Frame id of frame being waited on.
142  int64_t frame_id;
143 
144  //! The wait thread itself
145  struct os_thread_helper oth;
146 
147  //! Have we gotten to the loop?
148  bool alive;
149 
150  //! Is the thread waiting, if so the client should block.
151  bool waiting;
152 
153  /*!
154  * Is the client thread blocked?
155  *
156  * Set to true by the client thread,
157  * cleared by the wait thread to release the client thread.
158  */
159  bool blocked;
160  } wait_thread;
161 
162  //! Lock for all of the slots.
163  struct os_mutex slot_lock;
164 
165  /*!
166  * The next which the next frames to be picked up will be displayed.
167  */
169 
170  /*!
171  * Currently being transferred or waited on.
172  * Not protected by the slot lock as it is only touched by the client thread.
173  */
174  struct multi_layer_slot progress;
175 
176  //! Scheduled frames for a future timepoint.
178 
179  /*!
180  * Fully ready to be used.
181  * Not protected by the slot lock as it is only touched by the main render loop thread.
182  */
184 
185  struct u_pacing_app *upa;
186 };
187 
188 /*!
189  * Small helper go from @ref xrt_compositor to @ref multi_compositor.
190  *
191  * @ingroup comp_multi
192  */
193 static inline struct multi_compositor *
195 {
196  return (struct multi_compositor *)xc;
197 }
198 
199 /*!
200  * Create a multi client wrapper compositor.
201  *
202  * @ingroup comp_multi
203  */
206  const struct xrt_session_info *xsi,
208  struct xrt_compositor_native **out_xcn);
209 
210 /*!
211  * Push a event to be delivered to the session that corresponds
212  * to the given @ref multi_compositor.
213  *
214  * @ingroup comp_multi
215  * @private @memberof multi_compositor
216  */
217 XRT_CHECK_RESULT xrt_result_t
218 multi_compositor_push_event(struct multi_compositor *mc, const union xrt_session_event *xse);
219 
220 /*!
221  * Deliver any scheduled frames at that is to be display at or after the given @p display_time_ns. Called by the render
222  * thread and copies data from multi_compositor::scheduled to multi_compositor::delivered while holding the slot_lock.
223  *
224  * @ingroup comp_multi
225  * @private @memberof multi_compositor
226  */
227 void
228 multi_compositor_deliver_any_frames(struct multi_compositor *mc, uint64_t display_time_ns);
229 
230 /*!
231  * Makes the current delivered frame as latched, called by the render thread.
232  * The list_and_timing_lock is held when this function is called.
233  *
234  * @ingroup comp_multi
235  * @private @memberof multi_compositor
236  */
237 void
238 multi_compositor_latch_frame_locked(struct multi_compositor *mc, uint64_t when_ns, int64_t system_frame_id);
239 
240 /*!
241  * Clears and retires the delivered frame, called by the render thread.
242  * The list_and_timing_lock is held when this function is called.
243  *
244  * @ingroup comp_multi
245  * @private @memberof multi_compositor
246  */
247 void
248 multi_compositor_retire_delivered_locked(struct multi_compositor *mc, uint64_t when_ns);
249 
250 
251 /*
252  *
253  * Multi-client-capable system compositor
254  *
255  */
256 
257 /*!
258  * State of the multi-client system compositor. Use to track the calling of native
259  * compositor methods @ref xrt_comp_begin_session and @ref xrt_comp_end_session.
260  *
261  * It is driven by the number of active app sessions.
262  *
263  * @ingroup comp_multi
264  */
266 {
267  /*!
268  * Invalid state, never used.
269  */
271 
272  /*!
273  * One of the initial states, the multi-client system compositor will
274  * make sure that its @ref xrt_compositor_native submits one frame.
275  *
276  * The session hasn't been started yet.
277  */
279 
280  /*!
281  * One of the initial state and post stopping state.
282  *
283  * The multi-client system compositor has called @ref xrt_comp_end_session
284  * on its @ref xrt_compositor_native.
285  */
287 
288  /*!
289  * The main session is running.
290  *
291  * The multi-client system compositor has called @ref xrt_comp_begin_session
292  * on its @ref xrt_compositor_native.
293  */
295 
296  /*!
297  * There are no active sessions and the multi-client system compositor is
298  * instructing the native compositor to draw one or more clear frames.
299  *
300  * The multi-client system compositor has not yet called @ref xrt_comp_begin_session
301  * on its @ref xrt_compositor_native.
302  */
304 };
305 
306 /*!
307  * The multi-client module (aka multi compositor) is system compositor that
308  * multiplexes access to a single @ref xrt_compositor_native, merging layers
309  * from one or more client apps/sessions. This object implements the
310  * @ref xrt_system_compositor, and gives each session a @ref multi_compositor,
311  * which implements @ref xrt_compositor_native.
312  *
313  * @ingroup comp_multi
314  * @implements xrt_system_compositor
315  */
317 {
318  //! Base interface.
320 
321  //! Extra functions to handle multi client.
323 
324  /*!
325  * Real native compositor, which this multi client module submits the
326  * combined layers of active @ref multi_compositor objects.
327  */
329 
330  /*!
331  * App pacer factory, when a new @ref multi_compositor is created a
332  * pacer is created from this factory.
333  */
335 
336  //! Render loop thread.
337  struct os_thread_helper oth;
338 
339  struct
340  {
341  /*!
342  * The state of the multi-client system compositor.
343  * This is updated on the multi_system_compositor::oth
344  * thread, aka multi-client system compositor main thread.
345  * It is driven by the active_count field.
346  */
348 
349  //! Number of active sessions, protected by oth.
350  uint64_t active_count;
351  } sessions;
352 
353  /*!
354  * This mutex protects the list of client compositor
355  * and the rendering timings on it.
356  */
358 
359  struct
360  {
361  uint64_t predicted_display_time_ns;
362  uint64_t predicted_display_period_ns;
363  uint64_t diff_ns;
364  } last_timings;
365 
366  //! List of active clients.
368 };
369 
370 /*!
371  * Cast helper
372  *
373  * @ingroup comp_multi
374  * @private @memberof multi_system_compositor
375  */
376 static inline struct multi_system_compositor *
378 {
379  return (struct multi_system_compositor *)xsc;
380 }
381 
382 /*!
383  * The client compositor calls this function to update when its session is
384  * started or stopped.
385  *
386  * @ingroup comp_multi
387  * @private @memberof multi_system_compositor
388  */
389 void
390 multi_system_compositor_update_session_status(struct multi_system_compositor *msc, bool active);
391 
392 
393 #ifdef __cplusplus
394 }
395 #endif
#define MULTI_MAX_LAYERS
Number of max active layers per multi_compositor.
Definition: comp_multi_private.h:40
xrt_result_t multi_compositor_create(struct multi_system_compositor *msc, const struct xrt_session_info *xsi, struct xrt_session_event_sink *xses, struct xrt_compositor_native **out_xcn)
Create a multi client wrapper compositor.
Definition: comp_multi_compositor.c:949
#define MULTI_MAX_CLIENTS
Number of max active clients.
Definition: comp_multi_private.h:32
multi_system_state
State of the multi-client system compositor.
Definition: comp_multi_private.h:266
@ MULTI_SYSTEM_STATE_INVALID
Invalid state, never used.
Definition: comp_multi_private.h:270
@ MULTI_SYSTEM_STATE_RUNNING
The main session is running.
Definition: comp_multi_private.h:294
@ MULTI_SYSTEM_STATE_STOPPING
There are no active sessions and the multi-client system compositor is instructing the native composi...
Definition: comp_multi_private.h:303
@ MULTI_SYSTEM_STATE_INIT_WARM_START
One of the initial states, the multi-client system compositor will make sure that its xrt_compositor_...
Definition: comp_multi_private.h:278
@ MULTI_SYSTEM_STATE_STOPPED
One of the initial state and post stopping state.
Definition: comp_multi_private.h:286
static struct multi_compositor * multi_compositor(struct xrt_compositor *xc)
Small helper go from xrt_compositor to multi_compositor.
Definition: comp_multi_private.h:194
enum xrt_result xrt_result_t
Result type used across Monado.
Wrapper around OS threading native functions.
Wrapper around OS native time functions.
A single compositor for feeding the layers from one session/app into the multi-client-capable system ...
Definition: comp_multi_private.h:102
struct multi_layer_slot scheduled
Scheduled frames for a future timepoint.
Definition: comp_multi_private.h:177
struct os_precise_sleeper scheduled_sleeper
Used when waiting for the scheduled frame to complete.
Definition: comp_multi_private.h:118
struct multi_system_compositor * msc
Owning system compositor.
Definition: comp_multi_private.h:112
uint64_t value
Timeline semaphore value to wait for.
Definition: comp_multi_private.h:139
struct xrt_session_event_sink * xses
Where events for this compositor should go.
Definition: comp_multi_private.h:109
struct xrt_compositor_semaphore * xcsem
Timeline semaphore to wait for.
Definition: comp_multi_private.h:136
struct os_mutex slot_lock
Lock for all of the slots.
Definition: comp_multi_private.h:163
struct os_thread_helper oth
The wait thread itself.
Definition: comp_multi_private.h:145
int64_t frame_id
Frame id of frame being waited on.
Definition: comp_multi_private.h:142
bool blocked
Is the client thread blocked?
Definition: comp_multi_private.h:159
struct multi_layer_slot delivered
Fully ready to be used.
Definition: comp_multi_private.h:183
struct os_precise_sleeper frame_sleeper
Used to implement wait frame, only used for in process.
Definition: comp_multi_private.h:115
struct xrt_compositor_fence * xcf
Fence to wait for.
Definition: comp_multi_private.h:133
bool alive
Have we gotten to the loop?
Definition: comp_multi_private.h:148
bool waiting
Is the thread waiting, if so the client should block.
Definition: comp_multi_private.h:151
uint64_t slot_next_frame_display
The next which the next frames to be picked up will be displayed.
Definition: comp_multi_private.h:168
struct multi_layer_slot progress
Currently being transferred or waited on.
Definition: comp_multi_private.h:174
Data for a single composition layer.
Definition: comp_multi_private.h:57
struct xrt_layer_data data
All basic (trivially-serializable) data associated with a layer, aside from which swapchain(s) are us...
Definition: comp_multi_private.h:74
struct xrt_swapchain * xscs[2 *XRT_MAX_VIEWS]
Pointers to swapchains.
Definition: comp_multi_private.h:68
struct xrt_device * xdev
Device to get pose from.
Definition: comp_multi_private.h:61
Render state for a single client, including all layers.
Definition: comp_multi_private.h:83
The multi-client module (aka multi compositor) is system compositor that multiplexes access to a sing...
Definition: comp_multi_private.h:317
struct xrt_multi_compositor_control xmcc
Extra functions to handle multi client.
Definition: comp_multi_private.h:322
struct multi_compositor * clients[64]
List of active clients.
Definition: comp_multi_private.h:367
enum multi_system_state state
The state of the multi-client system compositor.
Definition: comp_multi_private.h:347
struct os_thread_helper oth
Render loop thread.
Definition: comp_multi_private.h:337
struct u_pacing_app_factory * upaf
App pacer factory, when a new multi_compositor is created a pacer is created from this factory.
Definition: comp_multi_private.h:334
struct os_mutex list_and_timing_lock
This mutex protects the list of client compositor and the rendering timings on it.
Definition: comp_multi_private.h:357
uint64_t active_count
Number of active sessions, protected by oth.
Definition: comp_multi_private.h:350
struct xrt_compositor_native * xcn
Real native compositor, which this multi client module submits the combined layers of active multi_co...
Definition: comp_multi_private.h:328
struct xrt_system_compositor base
Base interface.
Definition: comp_multi_private.h:319
A wrapper around a native mutex.
Definition: os_threading.h:55
Definition: os_time.h:208
All in one helper that handles locking, waiting for change and starting a thread.
Definition: os_threading.h:453
Small helper that creates a app pacers, allows timing information to be collected and controlled to a...
Definition: u_pacing.h:619
This application pacing helper is designed to schedule the rendering time of clients that submit fram...
Definition: u_pacing.h:348
Compositor fence used for syncornization.
Definition: xrt_compositor.h:731
Main compositor server interface.
Definition: xrt_compositor.h:2196
struct xrt_compositor base
Base.
Definition: xrt_compositor.h:2198
Compositor semaphore used for synchronization, needs to be as capable as a Vulkan pipeline semaphore.
Definition: xrt_compositor.h:788
Common compositor client interface/base.
Definition: xrt_compositor.h:986
A single HMD or input device.
Definition: xrt_device.h:230
All the pure data values associated with a composition layer.
Definition: xrt_compositor.h:394
Per frame data for the layer submission calls, used in xrt_compositor::layer_begin.
Definition: xrt_compositor.h:478
Special functions to control multi session/clients.
Definition: xrt_compositor.h:2325
Used internally from producers of events to push events into session, some sinks might mutliplex even...
Definition: xrt_session.h:193
Session information, mostly overlay extension data.
Definition: xrt_compositor.h:930
Common swapchain interface/base.
Definition: xrt_compositor.h:536
The system compositor handles composition for a system.
Definition: xrt_compositor.h:2386
Shared pacing code.
Union of all session events, used to return multiple events through one call.
Definition: xrt_session.h:174
Header holding common defines.
Header declaring XRT graphics interfaces.
Common defines and enums for XRT.