The open source OpenXR runtime
1// Copyright 2023-2024, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Special code for managing a variable tracked swapchain.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup aux_util
8 */
9
10#pragma once
11
12#include "os/os_threading.h"
13#include "xrt/xrt_compositor.h"
14
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20
21/*!
22 * A struct for debugging one or more native images.
23 *
24 * @ingroup aux_util
25 */
26struct u_native_images_debug
27{
28 //! Is initialised/destroyed when added or root is removed.
29 struct os_mutex mutex;
30
31 /*!
32 * Process unique id for the set of images, protected by @p mutex,
33 * allows caching of imports. Created by @ref u_limited_unique_id_get.
34 */
35 xrt_limited_unique_id_t limited_unique_id;
36
37 //! List to current set of native images, protected by @p mutex.
38 struct xrt_image_native *native_images;
39
40 //! Count of @p native_images, protected by @p mutex.
41 uint32_t native_image_count;
42
43 /*!
44 * Information needed to import the native images, information in the
45 * struct is immutable, the pointer is protected by @p mutex.
46 */
47 const struct xrt_swapchain_create_info *xscci;
48
49 /*!
50 * The native image that was last filled in by the source, only
51 * valid if @p native_images is non-null, protected by @p mutex.
52 */
53 uint32_t active_index;
54
55 //! Should the image be flipped in y direction.
56 bool flip_y;
57};
58
59/*!
60 * Must be called before variable is tracked.
61 *
62 * @ingroup aux_util
63 */
64static inline void
65u_native_images_debug_init(struct u_native_images_debug *unid)
66{
67 os_mutex_init(&unid->mutex);
68}
69
70/*!
71 * Must not be called while variable longer tracked, after @p u_var_remove_root.
72 *
73 * @ingroup aux_util
74 */
75static inline void
76u_native_images_debug_destroy(struct u_native_images_debug *unid)
77{
78 os_mutex_destroy(&unid->mutex);
79 unid->native_images = NULL;
80 unid->native_image_count = 0;
81 unid->xscci = NULL;
82 unid->active_index = 0;
83 unid->flip_y = false;
84}
85
86/*!
87 * Simple lock helper.
88 *
89 * @ingroup aux_util
90 */
91static inline void
92u_native_images_debug_lock(struct u_native_images_debug *unid)
93{
94 os_mutex_lock(&unid->mutex);
95}
96
97/*!
98 * Simple lock helper.
99 *
100 * @ingroup aux_util
101 */
102static inline void
103u_native_images_debug_unlock(struct u_native_images_debug *unid)
104{
105 os_mutex_unlock(&unid->mutex);
106}
107
108/*!
109 * Helper function to update all variables, must be called with the lock held.
110 *
111 * @ingroup aux_util
112 */
113static inline void
114u_native_images_debug_set_locked(struct u_native_images_debug *unid,
115 xrt_limited_unique_id_t limited_unique_id,
116 struct xrt_image_native *native_images,
117 uint32_t native_image_count,
118 const struct xrt_swapchain_create_info *xscci,
119 uint32_t active_index,
120 bool flip_y)
121{
122 unid->limited_unique_id = limited_unique_id;
123 unid->native_images = native_images;
124 unid->native_image_count = native_image_count;
125 unid->active_index = active_index;
126 unid->xscci = xscci;
127 unid->flip_y = flip_y;
128}
129
130/*!
131 * Updates all variables atomically by holding the lock.
132 *
133 * @ingroup aux_util
134 */
135static inline void
136u_native_images_debug_set(struct u_native_images_debug *unid,
137 xrt_limited_unique_id_t limited_unique_id,
138 struct xrt_image_native *native_images,
139 uint32_t native_image_count,
140 const struct xrt_swapchain_create_info *xscci,
141 uint32_t active_index,
142 bool flip_y)
143{
144 u_native_images_debug_lock(unid);
145 u_native_images_debug_set_locked( //
146 unid, //
147 limited_unique_id, //
148 native_images, //
149 native_image_count, //
150 xscci, //
151 active_index, //
152 flip_y); //
153 u_native_images_debug_unlock(unid);
154}
155
156/*!
157 * Clear all variables, must be called with the lock held.
158 *
159 * @ingroup aux_util
160 */
161static inline void
162u_native_images_debug_clear_locked(struct u_native_images_debug *unid)
163{
164 unid->limited_unique_id.data = 0;
165 unid->xscci = NULL;
166 unid->active_index = 0;
167 unid->native_images = NULL;
168 unid->native_image_count = 0;
169}
170
171/*!
172 * Clear all variables atomically by holding the lock, still valid to use.
173 *
174 * @ingroup aux_util
175 */
176static inline void
177u_native_images_debug_clear(struct u_native_images_debug *unid)
178{
179 u_native_images_debug_lock(unid);
180 u_native_images_debug_clear_locked(unid);
181 u_native_images_debug_unlock(unid);
182}
183
184
185/*
186 *
187 * Swapchain.
188 *
189 */
190
191/*!
192 * Allows to debug image that is in GPU memory.
193 *
194 * @ingroup aux_util
195 */
196struct u_swapchain_debug
197{
198 //! Base for native image debugging.
199 struct u_native_images_debug base;
200
201 //! Protected by @p base::mutex.
202 struct xrt_swapchain_native *xscn;
203};
204
205/*!
206 * Must be called before variable is tracked.
207 *
208 * @ingroup aux_util
209 */
210static inline void
211u_swapchain_debug_init(struct u_swapchain_debug *uscd)
212{
213 u_native_images_debug_init(&uscd->base);
214}
215
216/*!
217 * Updates all variables atomically by holding the lock.
218 *
219 * @ingroup aux_util
220 */
221static inline void
222u_swapchain_debug_set(struct u_swapchain_debug *uscd,
223 struct xrt_swapchain_native *xscn,
224 const struct xrt_swapchain_create_info *xscci,
225 uint32_t active_index,
226 bool flip_y)
227{
228 u_native_images_debug_lock(&uscd->base);
229
230 u_native_images_debug_set_locked( //
231 &uscd->base, //
232 xscn->limited_unique_id, //
233 xscn->images, //
234 xscn->base.image_count, //
235 xscci, //
236 active_index, //
237 flip_y); //
238
239 xrt_swapchain_native_reference(&uscd->xscn, xscn);
240
241 u_native_images_debug_unlock(&uscd->base);
242}
243
244/*!
245 * Clear all variables atomically by holding the lock, still valid to use.
246 *
247 * @ingroup aux_util
248 */
249static inline void
250u_swapchain_debug_clear(struct u_swapchain_debug *uscd)
251{
252 u_native_images_debug_lock(&uscd->base);
253 u_native_images_debug_clear_locked(&uscd->base);
254 xrt_swapchain_native_reference(&uscd->xscn, NULL);
255 u_native_images_debug_unlock(&uscd->base);
256}
257
258/*!
259 * Must not be called while variable longer tracked, after @p u_var_remove_root.
260 *
261 * @ingroup aux_util
262 */
263static inline void
264u_swapchain_debug_destroy(struct u_swapchain_debug *uscd)
265{
266 xrt_swapchain_native_reference(&uscd->xscn, NULL);
267 uscd->base.active_index = 0;
268 os_mutex_destroy(&uscd->base.mutex);
269}
270
271/*!
272 * Simple lock helper.
273 *
274 * @ingroup aux_util
275 */
276static inline void
277u_swapchain_debug_lock(struct u_swapchain_debug *uscd)
278{
279 u_native_images_debug_lock(&uscd->base);
280}
281
282/*!
283 * Simple lock helper.
284 *
285 * @ingroup aux_util
286 */
287static inline void
288u_swapchain_debug_unlock(struct u_swapchain_debug *uscd)
289{
290 u_native_images_debug_unlock(&uscd->base);
291}
292
293
294#ifdef __cplusplus
295}
296#endif