diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index 8ce58be57034135162eeb0ffad136b44f1546c81..8fdadfbba2e3f6daaee0057f47f57a6fe7242d2b 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -27,6 +27,9 @@ if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES) if(XRT_HAVE_EGL) target_sources(aux_ogl PRIVATE ogl/egl_api.c ogl/egl_api.h) endif() + if(XRT_HAVE_OPENGL AND WIN32) + target_sources(aux_ogl PRIVATE ogl/wgl_api.c ogl/wgl_api.h) + endif() if(XRT_HAVE_OPENGLES) target_link_libraries(aux_ogl PUBLIC EGL::EGL) endif() diff --git a/src/xrt/auxiliary/ogl/wgl_api.c b/src/xrt/auxiliary/ogl/wgl_api.c new file mode 100644 index 0000000000000000000000000000000000000000..33a1073c6172644659410b4e906f913db81273a1 --- /dev/null +++ b/src/xrt/auxiliary/ogl/wgl_api.c @@ -0,0 +1,10 @@ +// Copyright 2022, James Hogan <james@albanarts.com> +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief WGL API wrapper. + * @author James Hogan <james@albanarts.com> + * @ingroup aux_ogl + */ + +#include "../../external/glad/src/wgl.c" diff --git a/src/xrt/auxiliary/ogl/wgl_api.h b/src/xrt/auxiliary/ogl/wgl_api.h new file mode 100644 index 0000000000000000000000000000000000000000..bfff2cfc05d341878109676d92e3d1d40505a3b7 --- /dev/null +++ b/src/xrt/auxiliary/ogl/wgl_api.h @@ -0,0 +1,17 @@ +// Copyright 2022, James Hogan <james@albanarts.com> +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief GLX API wrapper header. + * @author James Hogan <james@albanarts.com> + * @ingroup aux_ogl + */ + +#pragma once + +#include "xrt/xrt_gfx_win32.h" + +typedef void (*GLADapiproc)(void); +typedef GLADapiproc (*GLADloadfunc)(const char *name); +int +gladLoadWGL(HDC hdc, GLADloadfunc load); diff --git a/src/xrt/compositor/CMakeLists.txt b/src/xrt/compositor/CMakeLists.txt index 9040a6d98fc807bce250dcd117f71d5681f7f4d5..fb6522a16d7b3d839d52dbcca3892f79f8cdc574 100644 --- a/src/xrt/compositor/CMakeLists.txt +++ b/src/xrt/compositor/CMakeLists.txt @@ -54,6 +54,14 @@ if(XRT_HAVE_OPENGL_GLX AND XRT_HAVE_XLIB) target_link_libraries(comp_client PRIVATE OpenGL::GLX) endif() +if(XRT_HAVE_OPENGL AND WIN32) + target_sources( + comp_client PRIVATE client/comp_gl_win32_client.c client/comp_gl_win32_client.h + client/comp_gl_win32_glue.c + ) + target_link_libraries(comp_client PRIVATE ${OPENGL_gl_LIBRARY}) +endif() + if(XRT_HAVE_EGL) target_sources(comp_client PRIVATE client/comp_egl_client.c client/comp_egl_client.h) endif() diff --git a/src/xrt/compositor/client/comp_gl_memobj_swapchain.c b/src/xrt/compositor/client/comp_gl_memobj_swapchain.c index 2556f0d56b26604761d0c9f5659762321fb5a305..6bcbe9a767614a0c9c5ebf926c873f3ac22e8425 100644 --- a/src/xrt/compositor/client/comp_gl_memobj_swapchain.c +++ b/src/xrt/compositor/client/comp_gl_memobj_swapchain.c @@ -125,6 +125,55 @@ client_gl_memobj_swapchain_create(struct xrt_compositor *xc, } } + *out_cglsc = &sc->base; + return &sc->base.base.base; +#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE) + struct client_gl_compositor *c = client_gl_compositor(xc); + (void)c; + + if (xscn == NULL) { + return NULL; + } + + GLuint binding_enum = 0; + GLuint tex_target = 0; + ogl_texture_target_for_swapchain_info(info, &tex_target, &binding_enum); + struct xrt_swapchain *native_xsc = &xscn->base; + + struct client_gl_memobj_swapchain *sc = U_TYPED_CALLOC(struct client_gl_memobj_swapchain); + sc->base.base.base.destroy = client_gl_memobj_swapchain_destroy; + sc->base.base.base.reference.count = 1; + sc->base.base.base.image_count = + native_xsc->image_count; // Fetch the number of images from the native swapchain. + sc->base.xscn = xscn; + sc->base.tex_target = tex_target; + + sc->base.gl_compositor = c; + + struct xrt_swapchain_gl *xscgl = &sc->base.base; + glGenTextures(native_xsc->image_count, xscgl->images); + + glCreateMemoryObjectsEXT(native_xsc->image_count, &sc->memory[0]); + for (uint32_t i = 0; i < native_xsc->image_count; i++) { + glBindTexture(tex_target, xscgl->images[i]); + + GLint dedicated = xscn->images[i].use_dedicated_allocation ? GL_TRUE : GL_FALSE; + glMemoryObjectParameterivEXT(sc->memory[i], GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated); + glImportMemoryWin32HandleEXT(sc->memory[i], xscn->images[i].size, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, + xscn->images[i].handle); + + // We have consumed this now, make sure it's not freed again. + xscn->images[i].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; + + if (info->array_size == 1) { + glTextureStorageMem2DEXT(xscgl->images[i], info->mip_count, (GLuint)info->format, info->width, + info->height, sc->memory[i], 0); + } else { + glTextureStorageMem3DEXT(xscgl->images[i], info->mip_count, (GLuint)info->format, info->width, + info->height, info->array_size, sc->memory[i], 0); + } + } + *out_cglsc = &sc->base; return &sc->base.base.base; #else diff --git a/src/xrt/compositor/client/comp_gl_win32_client.c b/src/xrt/compositor/client/comp_gl_win32_client.c new file mode 100644 index 0000000000000000000000000000000000000000..4cdc9ade64418efa3c8a3cb750771268026697e4 --- /dev/null +++ b/src/xrt/compositor/client/comp_gl_win32_client.c @@ -0,0 +1,252 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Win32 client side glue to compositor implementation. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup comp_client + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "util/u_misc.h" +#include "util/u_logging.h" + +#include "xrt/xrt_gfx_win32.h" + +#include "client/comp_gl_win32_client.h" +#include "client/comp_gl_memobj_swapchain.h" + +#include "ogl/ogl_api.h" +#include "ogl/wgl_api.h" + +/////////////////// +#include <glad/gl.h> + +static void * +get_proc(const char *namez); + +#include <windows.h> +static HMODULE libGL; + +typedef PROC(GLAD_API_PTR *PFNWGLGETPROCADDRESSPROC)(LPCSTR lpszProc); +static PFNWGLGETPROCADDRESSPROC gladGetProcAddressPtr; + +static int +open_gl(void) +{ + libGL = LoadLibraryW(L"opengl32.dll"); + if (libGL != NULL) { + void (*tmp)(void); + tmp = (void (*)(void))GetProcAddress(libGL, "wglGetProcAddress"); + gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC)tmp; + return gladGetProcAddressPtr != NULL; + } + + return 0; +} + +static void +close_gl(void) +{ + if (libGL != NULL) { + FreeLibrary((HMODULE)libGL); + libGL = NULL; + } +} + +static void * +get_proc(const char *namez) +{ + void *result = NULL; + if (libGL == NULL) + return NULL; + +#if !defined(__APPLE__) && !defined(__HAIKU__) + if (gladGetProcAddressPtr != NULL) { + result = gladGetProcAddressPtr(namez); + } +#endif + if (result == NULL) { +#if defined(_WIN32) || defined(__CYGWIN__) + result = (void *)GetProcAddress((HMODULE)libGL, namez); +#else + result = dlsym(libGL, namez); +#endif + } + + return result; +} + +int +gladLoadGL2(void) +{ + int status = 0; + + if (open_gl()) { + status = gladLoadGL(&get_proc); + close_gl(); + } + + return status; +} +/////////////////// + +/* + * + * OpenGL context helper. + * + */ + +static inline bool +context_matches(const struct client_gl_context *a, const struct client_gl_context *b) +{ + return a->hDC == b->hDC && a->hGLRC == b->hGLRC; +} + +static inline void +context_save_current(struct client_gl_context *current_ctx) +{ + current_ctx->hDC = wglGetCurrentDC(); + current_ctx->hGLRC = wglGetCurrentContext(); +} + +static inline bool +context_make_current(const struct client_gl_context *ctx_to_make_current) +{ + if (wglMakeCurrent(ctx_to_make_current->hDC, ctx_to_make_current->hGLRC)) { + return true; + } + return false; +} + +/*! + * Down-cast helper. + * + * @private @memberof client_gl_win32_compositor + */ +static inline struct client_gl_win32_compositor * +client_gl_win32_compositor(struct xrt_compositor *xc) +{ + return (struct client_gl_win32_compositor *)xc; +} + +static void +client_gl_win32_compositor_destroy(struct xrt_compositor *xc) +{ + struct client_gl_win32_compositor *c = client_gl_win32_compositor(xc); + + client_gl_compositor_close(&c->base); + + free(c); +} + +static xrt_result_t +client_gl_context_begin(struct xrt_compositor *xc) +{ + struct client_gl_win32_compositor *c = client_gl_win32_compositor(xc); + + struct client_gl_context *app_ctx = &c->app_context; + + os_mutex_lock(&c->base.context_mutex); + + context_save_current(&c->temp_context); + + bool need_make_current = !context_matches(&c->temp_context, app_ctx); + + U_LOG_T("GL Context begin: need makeCurrent"); + + if (need_make_current && !context_make_current(app_ctx)) { + os_mutex_unlock(&c->base.context_mutex); + + U_LOG_E("Failed to make WGL context current"); + // No need to restore on failure. + return XRT_ERROR_OPENGL; + } + + return XRT_SUCCESS; +} + +static void +client_gl_context_end(struct xrt_compositor *xc) +{ + struct client_gl_win32_compositor *c = client_gl_win32_compositor(xc); + + struct client_gl_context *app_ctx = &c->app_context; + + struct client_gl_context *current_wgl_context = &c->temp_context; + + bool need_make_current = !context_matches(&c->temp_context, app_ctx); + + U_LOG_T("GL Context end: need makeCurrent"); + + if (need_make_current && !context_make_current(current_wgl_context)) { + U_LOG_E("Failed to make old WGL context current!"); + // fall through to os_mutex_unlock even if we didn't succeed in restoring the context + } + + os_mutex_unlock(&c->base.context_mutex); +} + +struct client_gl_win32_compositor * +client_gl_win32_compositor_create(struct xrt_compositor_native *xcn, HDC hDC, HGLRC hGLRC) +{ + gladLoadGL2(); + + // Save old GLX context. + struct client_gl_context current_ctx; + context_save_current(¤t_ctx); + + // The context and drawables given from the app. + struct client_gl_context app_ctx = { + .hDC = hDC, + .hGLRC = hGLRC, + }; + + + bool need_make_current = !context_matches(¤t_ctx, &app_ctx); + + U_LOG_T("GL Compositor create: need makeCurrent"); + + if (need_make_current && !context_make_current(&app_ctx)) { + U_LOG_E("Failed to make GLX context current"); + // No need to restore on failure. + return NULL; + } + + gladLoadGL2(); + + U_LOG_T("GL Compositor create: need makeCurrent"); + + if (need_make_current && !context_make_current(¤t_ctx)) { + U_LOG_E("Failed to make old GLX context current!"); + } + +#define CHECK_REQUIRED_EXTENSION(EXT) \ + do { \ + if (!GLAD_##EXT) { \ + U_LOG_E("%s - Required OpenGL extension " #EXT " not available", __func__); \ + return NULL; \ + } \ + } while (0) + + CHECK_REQUIRED_EXTENSION(GL_EXT_memory_object); + +#undef CHECK_REQUIRED_EXTENSION + + struct client_gl_win32_compositor *c = U_TYPED_CALLOC(struct client_gl_win32_compositor); + + // Move the app context to the struct. + c->app_context = app_ctx; + + if (!client_gl_compositor_init(&c->base, xcn, client_gl_context_begin, client_gl_context_end, + client_gl_memobj_swapchain_create, NULL)) { + free(c); + return NULL; + } + + c->base.base.base.destroy = client_gl_win32_compositor_destroy; + + return c; +} diff --git a/src/xrt/compositor/client/comp_gl_win32_client.h b/src/xrt/compositor/client/comp_gl_win32_client.h new file mode 100644 index 0000000000000000000000000000000000000000..83ba6fe7f8d24bc9652939f87c72c0835a7a1a79 --- /dev/null +++ b/src/xrt/compositor/client/comp_gl_win32_client.h @@ -0,0 +1,60 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief OpenGL on Win32 client side glue to compositor header. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup comp_client + */ + +#pragma once + +#include "xrt/xrt_gfx_win32.h" +#include "client/comp_gl_client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct client_gl_context +{ + HDC hDC; + HGLRC hGLRC; +}; + +/*! + * @class client_gl_win32_compositor + * A client facing win32 OpenGL base compositor. + * + * @ingroup comp_client + * @extends client_gl_compositor + */ +struct client_gl_win32_compositor +{ + //! OpenGL compositor wrapper base. + struct client_gl_compositor base; + + /*! + * Temporary storage for "current" OpenGL context while app_context is + * made current using context_begin/context_end. We only need one because + * app_context can only be made current in one thread at a time too. + */ + struct client_gl_context temp_context; + + //! GL context provided in graphics binding. + struct client_gl_context app_context; +}; + +/*! + * Create a new client_gl_win32_compositor. + * + * @public @memberof client_gl_win32_compositor + * @see xrt_compositor_native + */ +struct client_gl_win32_compositor * +client_gl_win32_compositor_create(struct xrt_compositor_native *xcn, HDC hDC, HGLRC hGLRC); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/compositor/client/comp_gl_win32_glue.c b/src/xrt/compositor/client/comp_gl_win32_glue.c new file mode 100644 index 0000000000000000000000000000000000000000..3fe6402fbc3aac21c0ba99f5f19098bafae014bb --- /dev/null +++ b/src/xrt/compositor/client/comp_gl_win32_glue.c @@ -0,0 +1,24 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Glue code to OpenGL win32 client side code. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup comp_client + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "xrt/xrt_gfx_win32.h" + +#include "client/comp_gl_win32_client.h" + + +struct xrt_compositor_gl * +xrt_gfx_provider_create_gl_win32(struct xrt_compositor_native *xcn, HDC hDC, HGLRC hGLRC) +{ + struct client_gl_win32_compositor *xcc = client_gl_win32_compositor_create(xcn, hDC, hGLRC); + + return &xcc->base.base; +} diff --git a/src/xrt/include/xrt/xrt_gfx_win32.h b/src/xrt/include/xrt/xrt_gfx_win32.h new file mode 100644 index 0000000000000000000000000000000000000000..8ad971c5f95bface8af482624ef61856f449dd2d --- /dev/null +++ b/src/xrt/include/xrt/xrt_gfx_win32.h @@ -0,0 +1,30 @@ +// Copyright 2019, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Header defining a XRT graphics provider. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup xrt_iface + */ + +#pragma once + +#include "xrt/xrt_device.h" +#include "xrt/xrt_compositor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * Create an OpenGL compositor client using win32. + * + * @ingroup xrt_iface + * @public @memberof xrt_compositor_native + */ +struct xrt_compositor_gl * +xrt_gfx_provider_create_gl_win32(struct xrt_compositor_native *xcn, HDC hDC, HGLRC hGLRC); + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/state_trackers/oxr/CMakeLists.txt b/src/xrt/state_trackers/oxr/CMakeLists.txt index 5d0bc54b8d359c1cc9cc4987f321acd2234bed99..cb1f6820c4dae2b192693a4b09e0ac69b8126376 100644 --- a/src/xrt/state_trackers/oxr/CMakeLists.txt +++ b/src/xrt/state_trackers/oxr/CMakeLists.txt @@ -64,6 +64,11 @@ if(XRT_HAVE_OPENGL_GLX AND XRT_HAVE_XLIB) target_sources(st_oxr PRIVATE oxr_session_gfx_gl_xlib.c) endif() +if(XRT_HAVE_OPENGL AND WIN32) + target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_WIN32) + target_sources(st_oxr PRIVATE oxr_session_gfx_gl_win32.c) +endif() + if(XRT_HAVE_EGL) target_compile_definitions(st_oxr PRIVATE XR_USE_PLATFORM_EGL) target_sources(st_oxr PRIVATE oxr_session_gfx_egl.c) diff --git a/src/xrt/state_trackers/oxr/oxr_api_verify.h b/src/xrt/state_trackers/oxr/oxr_api_verify.h index bd6cc5da37f8b0784e4cfe189a33957cb20d4063..e5d010fb7a513381f7d2b38d0358debfba7e74d4 100644 --- a/src/xrt/state_trackers/oxr/oxr_api_verify.h +++ b/src/xrt/state_trackers/oxr/oxr_api_verify.h @@ -260,6 +260,11 @@ XrResult oxr_verify_XrGraphicsBindingOpenGLXlibKHR(struct oxr_logger * /*log*/, const XrGraphicsBindingOpenGLXlibKHR * /*next*/); #endif // defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL) +#if defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) +XrResult +oxr_verify_XrGraphicsBindingOpenGLWin32KHR(struct oxr_logger * /*log*/, const XrGraphicsBindingOpenGLWin32KHR * /*next*/); +#endif // defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) + #if defined(XR_USE_GRAPHICS_API_VULKAN) XrResult oxr_verify_XrGraphicsBindingVulkanKHR(struct oxr_logger * /*log*/, const XrGraphicsBindingVulkanKHR * /*next*/); diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h index e5fc0d3917e765163ece02db66ad14dd0c621145..885361d6a02cc6abd4cdd0abdc3358e44b2baa4d 100644 --- a/src/xrt/state_trackers/oxr/oxr_objects.h +++ b/src/xrt/state_trackers/oxr/oxr_objects.h @@ -1007,6 +1007,15 @@ oxr_session_populate_gl_xlib(struct oxr_logger *log, struct oxr_session *sess); #endif // XR_USE_PLATFORM_XLIB +#ifdef XR_USE_PLATFORM_WIN32 + +XrResult +oxr_session_populate_gl_win32(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsBindingOpenGLWin32KHR const *next, + struct oxr_session *sess); +#endif // XR_USE_PLATFORM_WIN32 + #endif // XR_USE_GRAPHICS_API_OPENGL #if defined(XR_USE_GRAPHICS_API_OPENGL) || defined(XR_USE_GRAPHICS_API_OPENGL_ES) diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index a3dce932c2d38243a84ee496c00c7092b2aaba40..0d84e0dec77f77ba0f1ab2d25fd6096584dbcc18 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -16,6 +16,10 @@ #include "xrt/xrt_gfx_xlib.h" #endif // XR_USE_PLATFORM_XLIB +#ifdef XR_USE_PLATFORM_WIN32 +#include "xrt/xrt_gfx_win32.h" +#endif // XR_USE_PLATFORM_WIN32 + #ifdef XRT_HAVE_VULKAN #include "xrt/xrt_gfx_vk.h" #endif // XRT_HAVE_VULKAN @@ -664,6 +668,21 @@ oxr_session_create_impl(struct oxr_logger *log, } #endif +#if defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) + XrGraphicsBindingOpenGLWin32KHR const *opengl_win32 = OXR_GET_INPUT_FROM_CHAIN( + createInfo, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, XrGraphicsBindingOpenGLWin32KHR); + if (opengl_win32 != NULL) { + if (!sys->gotten_requirements) { + return oxr_error(log, XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING, + "Has not called " + "xrGetOpenGLGraphicsRequirementsKHR"); + } + + OXR_SESSION_ALLOCATE(log, sys, *out_session); + OXR_ALLOCATE_NATIVE_COMPOSITOR(log, xsi, *out_session); + return oxr_session_populate_gl_win32(log, sys, opengl_win32, *out_session); + } +#endif #if defined(XR_USE_PLATFORM_ANDROID) && defined(XR_USE_GRAPHICS_API_OPENGL_ES) XrGraphicsBindingOpenGLESAndroidKHR const *opengles_android = OXR_GET_INPUT_FROM_CHAIN( diff --git a/src/xrt/state_trackers/oxr/oxr_session_gfx_gl_win32.c b/src/xrt/state_trackers/oxr/oxr_session_gfx_gl_win32.c new file mode 100644 index 0000000000000000000000000000000000000000..602c4327df19faf099e86ded35e959d29cdccd0e --- /dev/null +++ b/src/xrt/state_trackers/oxr/oxr_session_gfx_gl_win32.c @@ -0,0 +1,49 @@ +// Copyright 2018-2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Holds OpenGL-specific session functions. + * @author Jakob Bornecrantz <jakob@collabora.com> + * @ingroup oxr_main + * @ingroup comp_client + */ + +#ifndef XR_USE_PLATFORM_WIN32 +#error "Must build this file with WIN32 enabled!" +#endif + +#ifndef XR_USE_GRAPHICS_API_OPENGL +#error "Must build this file with OpenGL enabled!" +#endif + +#include <stdlib.h> + +#include "util/u_misc.h" + +#include "oxr_objects.h" +#include "oxr_logger.h" +#include "oxr_two_call.h" +#include "oxr_handle.h" + +#include "xrt/xrt_instance.h" +#include "xrt/xrt_gfx_win32.h" + + +XrResult +oxr_session_populate_gl_win32(struct oxr_logger *log, + struct oxr_system *sys, + XrGraphicsBindingOpenGLWin32KHR const *next, + struct oxr_session *sess) +{ + struct xrt_compositor_native *xcn = sess->xcn; + struct xrt_compositor_gl *xcgl = xrt_gfx_provider_create_gl_win32(xcn, next->hDC, next->hGLRC); + + if (xcgl == NULL) { + return oxr_error(log, XR_ERROR_INITIALIZATION_FAILED, "Failed to create an win32 client compositor"); + } + + sess->compositor = &xcgl->base; + sess->create_swapchain = oxr_swapchain_gl_create; + + return XR_SUCCESS; +} diff --git a/src/xrt/state_trackers/oxr/oxr_swapchain.c b/src/xrt/state_trackers/oxr/oxr_swapchain.c index 1e368cd3c193cc445893ad9fa5c164efdc66682e..d2034c32857b4cdb1f41b9764e665ec176cc2550 100644 --- a/src/xrt/state_trackers/oxr/oxr_swapchain.c +++ b/src/xrt/state_trackers/oxr/oxr_swapchain.c @@ -10,6 +10,7 @@ #include <stdlib.h> #include "xrt/xrt_gfx_xlib.h" +#include "xrt/xrt_gfx_win32.h" #include "util/u_debug.h" #include "util/u_misc.h" diff --git a/src/xrt/state_trackers/oxr/oxr_swapchain_gl.c b/src/xrt/state_trackers/oxr/oxr_swapchain_gl.c index 7e2b858ef865f443749342fbf87fe07af7818f8f..8c7fdfb5618a7e0b41d1890ebdff6f4d64a05c64 100644 --- a/src/xrt/state_trackers/oxr/oxr_swapchain_gl.c +++ b/src/xrt/state_trackers/oxr/oxr_swapchain_gl.c @@ -12,6 +12,7 @@ #include <stdlib.h> #include "xrt/xrt_gfx_xlib.h" +#include "xrt/xrt_gfx_win32.h" #include "util/u_debug.h" #include "oxr_objects.h" diff --git a/src/xrt/state_trackers/oxr/oxr_swapchain_vk.c b/src/xrt/state_trackers/oxr/oxr_swapchain_vk.c index 8b164ef3b5dc57e108cfe8c2f15140227ee6f6ca..e6e0b52c364188cc6dea26a0b204c1f648eb846b 100644 --- a/src/xrt/state_trackers/oxr/oxr_swapchain_vk.c +++ b/src/xrt/state_trackers/oxr/oxr_swapchain_vk.c @@ -11,6 +11,7 @@ #include <stdlib.h> #include "xrt/xrt_gfx_xlib.h" +#include "xrt/xrt_gfx_win32.h" #include "util/u_debug.h" #include "oxr_objects.h" diff --git a/src/xrt/state_trackers/oxr/oxr_verify.c b/src/xrt/state_trackers/oxr/oxr_verify.c index 689210dd2b3910ec9471834aa1e052116959cfd6..f3c050acdaa3915d808f62680a36f0888290a0b4 100644 --- a/src/xrt/state_trackers/oxr/oxr_verify.c +++ b/src/xrt/state_trackers/oxr/oxr_verify.c @@ -464,6 +464,15 @@ oxr_verify_XrSessionCreateInfo(struct oxr_logger *log, } #endif // defined(OXR_HAVE_KHR_opengl_enable) && defined(XR_USE_PLATFORM_XLIB) +#if defined(OXR_HAVE_KHR_opengl_enable) && defined(XR_USE_PLATFORM_WIN32) + XrGraphicsBindingOpenGLWin32KHR const *opengl_win32 = OXR_GET_INPUT_FROM_CHAIN( + createInfo, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, XrGraphicsBindingOpenGLWin32KHR); + if (opengl_win32 != NULL) { + OXR_VERIFY_EXTENSION(log, inst, KHR_opengl_enable); + return oxr_verify_XrGraphicsBindingOpenGLWin32KHR(log, opengl_win32); + } +#endif // defined(OXR_HAVE_KHR_opengl_enable) && defined(XR_USE_PLATFORM_WIN32) + #if defined(OXR_HAVE_KHR_vulkan_enable) || defined(OXR_HAVE_KHR_vulkan_enable2) /* XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR aliased to * XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR */ @@ -551,6 +560,27 @@ oxr_verify_XrGraphicsBindingOpenGLXlibKHR(struct oxr_logger *log, const XrGraphi #endif // defined(XR_USE_PLATFORM_XLIB) && defined(XR_USE_GRAPHICS_API_OPENGL) +#if defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) + +XrResult +oxr_verify_XrGraphicsBindingOpenGLWin32KHR(struct oxr_logger *log, const XrGraphicsBindingOpenGLWin32KHR *next) +{ + if (next->type != XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) { + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "Graphics binding has invalid type"); + } + + if (next->hDC == NULL) { + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "hDC is NULL"); + } + + if (next->hGLRC == NULL) { + return oxr_error(log, XR_ERROR_VALIDATION_FAILURE, "hGLRC is NULL"); + } + + return XR_SUCCESS; +} + +#endif // defined(XR_USE_PLATFORM_WIN32) && defined(XR_USE_GRAPHICS_API_OPENGL) #ifdef XR_USE_GRAPHICS_API_VULKAN