The open source OpenXR runtime
at prediction-2 268 lines 7.9 kB view raw
1// Copyright 2019-2022, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief OpenGL client side glue to compositor header. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup comp_client 8 */ 9 10#pragma once 11 12#include "xrt/xrt_compositor.h" 13#include "os/os_threading.h" 14 15#ifdef __cplusplus 16extern "C" { 17#endif 18 19/* 20 * 21 * Structs 22 * 23 */ 24 25struct client_gl_compositor; 26 27/*! 28 * @class client_gl_swapchain 29 * 30 * Wraps the real compositor swapchain providing a OpenGL based interface. 31 * 32 * Almost a one to one mapping to a OpenXR swapchain. 33 * 34 * @ingroup comp_client 35 * @implements xrt_swapchain_gl 36 */ 37struct client_gl_swapchain 38{ 39 //! Implements @ref xrt_swapchain_gl 40 struct xrt_swapchain_gl base; 41 42 struct xrt_swapchain_native *xscn; 43 44 //! The texture target of images in this swapchain. 45 uint32_t tex_target; 46 47 /*! 48 * The compositor this swapchain was created on. Used when swapchain functions need to use the GL context. 49 * 50 * Not an owning pointer. 51 */ 52 struct client_gl_compositor *gl_compositor; 53}; 54 55/*! 56 * What's the reason to make the context current, this is needed currently for 57 * EGL where we have to create a shared context in some cases. But when we 58 * want to synchronize (insert a fence or call glFinish) we can not use the 59 * shared context and must use the context that the app provided on creation. 60 */ 61enum client_gl_context_reason 62{ 63 /*! 64 * Used when the compositor needs to insert a fence in the command 65 * stream of the apps context, this needs to be done in the given 66 * context and not the shared one that may be created. 67 */ 68 CLIENT_GL_CONTEXT_REASON_SYNCHRONIZE, 69 /*! 70 * Any other reason to make the context current, 71 * the shared may be used by now. 72 */ 73 CLIENT_GL_CONTEXT_REASON_OTHER, 74}; 75 76/*! 77 * Fetches the OpenGL context that is current on this thread and makes the 78 * OpenGL context given in the graphics binding current instead. Only one thread 79 * at a time can operate on the sections between 80 * @ref client_gl_context_begin_locked_func_t and 81 * @ref client_gl_context_end_locked_func_t, 82 * therefore @ref client_gl_context_end_locked_func_t MUST be called to avoid 83 * blocking the next thread calling @ref client_gl_context_begin_locked_func_t. 84 * 85 * This function must be called with the context_mutex locked held, that is 86 * handled by the helper function @ref client_gl_compositor_context_begin. 87 * 88 * If the return value is not XRT_SUCCESS, 89 * @ref client_gl_context_end_locked_func_t should not be called. 90 */ 91typedef xrt_result_t (*client_gl_context_begin_locked_func_t)(struct xrt_compositor *xc, 92 enum client_gl_context_reason reason); 93 94/*! 95 * Makes the OpenGL context current that was current before 96 * @ref client_gl_context_begin_locked_func_t was called. 97 * 98 * This function must be called with the context_mutex locked held, successful 99 * call to @ref client_gl_compositor_context_begin will ensure that. The lock is 100 * not released by this function, but @ref client_gl_compositor_context_end does 101 * release it. 102 */ 103typedef void (*client_gl_context_end_locked_func_t)(struct xrt_compositor *xc, enum client_gl_context_reason reason); 104 105/*! 106 * The type of a swapchain create constructor. 107 * 108 * Because our swapchain creation varies depending on available extensions and 109 * application choices, the swapchain constructor parameter to 110 * client_gl_compositor is parameterized. 111 * 112 * Note that the "common" swapchain creation function does some setup before 113 * invoking this, and some cleanup after. 114 * 115 * - Must populate `destroy` 116 * - Does not need to save/restore texture binding 117 */ 118typedef struct xrt_swapchain *(*client_gl_swapchain_create_func_t)(struct xrt_compositor *xc, 119 const struct xrt_swapchain_create_info *info, 120 struct xrt_swapchain_native *xscn, 121 struct client_gl_swapchain **out_sc); 122 123/*! 124 * The type of a fence insertion function. 125 * 126 * This function is called in xrt_compositor::layer_commit. 127 * 128 * The returned graphics sync handle is given to xrt_compositor::layer_commit. 129 */ 130typedef xrt_result_t (*client_gl_insert_fence_func_t)(struct xrt_compositor *xc, 131 xrt_graphics_sync_handle_t *out_handle); 132 133/*! 134 * @class client_gl_compositor 135 * 136 * Wraps the real compositor providing a OpenGL based interface. 137 * 138 * @ingroup comp_client 139 * @implements xrt_compositor_gl 140 */ 141struct client_gl_compositor 142{ 143 struct xrt_compositor_gl base; 144 145 struct xrt_compositor_native *xcn; 146 147 /*! 148 * Function pointer for making the OpenGL context current. 149 */ 150 client_gl_context_begin_locked_func_t context_begin_locked; 151 152 /*! 153 * Function pointer for restoring prior OpenGL context. 154 */ 155 client_gl_context_end_locked_func_t context_end_locked; 156 157 /*! 158 * Function pointer for creating the client swapchain. 159 */ 160 client_gl_swapchain_create_func_t create_swapchain; 161 162 /*! 163 * Function pointer for inserting fences on 164 * xrt_compositor::layer_commit. 165 */ 166 client_gl_insert_fence_func_t insert_fence; 167 168 /*! 169 * @ref client_gl_xlib_compositor::app_context can only be current on one thread; block other threads while we 170 * know it is bound to a thread. 171 */ 172 struct os_mutex context_mutex; 173 174 bool renderdoc_enabled; 175}; 176 177 178/* 179 * 180 * Functions and helpers. 181 * 182 */ 183 184/*! 185 * Down-cast helper. 186 * @protected @memberof client_gl_compositor 187 */ 188static inline struct client_gl_compositor * 189client_gl_compositor(struct xrt_compositor *xc) 190{ 191 return (struct client_gl_compositor *)xc; 192} 193 194/*! 195 * Fill in a client_gl_compositor and do common OpenGL readiness checking. 196 * 197 * OpenGL can have multiple backing window systems we have to interact with, so 198 * there isn't just one unified OpenGL client constructor. 199 * 200 * Moves ownership of provided xcn to the client_gl_compositor. 201 * 202 * Be sure to load your GL loader/wrapper (GLAD) before calling into here, it 203 * won't be called for you. 204 * 205 * @public @memberof client_gl_compositor 206 * @see xrt_compositor_native, client_gl_compositor_fini 207 */ 208bool 209client_gl_compositor_init(struct client_gl_compositor *c, 210 struct xrt_compositor_native *xcn, 211 client_gl_context_begin_locked_func_t context_begin, 212 client_gl_context_end_locked_func_t context_end, 213 client_gl_swapchain_create_func_t create_swapchain, 214 client_gl_insert_fence_func_t insert_fence); 215 216/*! 217 * Free all resources from the client_gl_compositor, does not free the 218 * @ref client_gl_compositor itself. Nor does it free the 219 * @ref xrt_compositor_native given at init as that is not owned by us. 220 * 221 * @public @memberof client_gl_compositor 222 */ 223void 224client_gl_compositor_fini(struct client_gl_compositor *c); 225 226/*! 227 * @copydoc client_gl_context_begin_locked_func_t 228 * 229 * Helper for calling through the function pointer. 230 * 231 * @public @memberof client_gl_compositor 232 */ 233static inline xrt_result_t 234client_gl_compositor_context_begin(struct xrt_compositor *xc, enum client_gl_context_reason reason) 235{ 236 struct client_gl_compositor *cgc = client_gl_compositor(xc); 237 238 os_mutex_lock(&cgc->context_mutex); 239 240 xrt_result_t xret = cgc->context_begin_locked(xc, reason); 241 if (xret != XRT_SUCCESS) { 242 os_mutex_unlock(&cgc->context_mutex); 243 } 244 245 return xret; 246} 247 248/*! 249 * @copydoc client_gl_context_end_locked_func_t 250 * 251 * Helper for calling through the function pointer. 252 * 253 * @public @memberof client_gl_compositor 254 */ 255static inline void 256client_gl_compositor_context_end(struct xrt_compositor *xc, enum client_gl_context_reason reason) 257{ 258 struct client_gl_compositor *cgc = client_gl_compositor(xc); 259 260 cgc->context_end_locked(xc, reason); 261 262 os_mutex_unlock(&cgc->context_mutex); 263} 264 265 266#ifdef __cplusplus 267} 268#endif