13#if defined(WITH_GHOST_X11)
18#if defined(WITH_GHOST_WAYLAND)
34 const std::vector<int64_t> &gpu_binding_formats,
const std::vector<int64_t> &runtime_formats)
36 if (gpu_binding_formats.empty()) {
40 auto res = std::find_first_of(gpu_binding_formats.begin(),
41 gpu_binding_formats.end(),
42 runtime_formats.begin(),
43 runtime_formats.end());
44 if (res == gpu_binding_formats.end()) {
56 glDeleteFramebuffers(1, &m_fbo);
63 std::string *r_requirement_info)
const override
65 int gl_major_version, gl_minor_version;
68 gl_major_version = ctx_gl.m_contextMajorVersion;
69 gl_minor_version = ctx_gl.m_contextMinorVersion;
70#elif defined(WITH_GHOST_X11) || defined(WITH_GHOST_WAYLAND)
73 gl_major_version = ctx_gl.m_contextMajorVersion;
74 gl_minor_version = ctx_gl.m_contextMinorVersion;
76# if defined(WITH_GHOST_X11)
79 gl_major_version = ctx_gl.m_contextMajorVersion;
80 gl_minor_version = ctx_gl.m_contextMinorVersion;
84 static PFN_xrGetOpenGLGraphicsRequirementsKHR s_xrGetOpenGLGraphicsRequirementsKHR_fn =
87 XrGraphicsRequirementsOpenGLKHR gpu_requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR};
88 const XrVersion gl_version = XR_MAKE_VERSION(gl_major_version, gl_minor_version, 0);
96 s_xrGetOpenGLGraphicsRequirementsKHR_fn =
nullptr;
98 if (!s_xrGetOpenGLGraphicsRequirementsKHR_fn &&
100 xrGetInstanceProcAddr(instance,
101 "xrGetOpenGLGraphicsRequirementsKHR",
102 (PFN_xrVoidFunction *)&s_xrGetOpenGLGraphicsRequirementsKHR_fn)))
104 s_xrGetOpenGLGraphicsRequirementsKHR_fn =
nullptr;
108 s_xrGetOpenGLGraphicsRequirementsKHR_fn(instance, system_id, &gpu_requirements);
110 if (r_requirement_info) {
111 std::ostringstream strstream;
112 strstream <<
"Min OpenGL version "
113 << XR_VERSION_MAJOR(gpu_requirements.minApiVersionSupported) <<
"."
114 << XR_VERSION_MINOR(gpu_requirements.minApiVersionSupported) << std::endl;
115 strstream <<
"Max OpenGL version "
116 << XR_VERSION_MAJOR(gpu_requirements.maxApiVersionSupported) <<
"."
117 << XR_VERSION_MINOR(gpu_requirements.maxApiVersionSupported) << std::endl;
119 *r_requirement_info = strstream.str();
122 return (gl_version >= gpu_requirements.minApiVersionSupported) &&
123 (gl_version <= gpu_requirements.maxApiVersionSupported);
128#if defined(WITH_GHOST_X11) || defined(WITH_GHOST_WAYLAND)
132 const bool is_ctx_egl =
dynamic_cast<GHOST_ContextEGL *
>(&ghost_ctx) !=
nullptr;
135 const bool is_wayland = (
136# if defined(WITH_GHOST_WAYLAND)
144# if defined(WITH_GHOST_WAYLAND)
146 oxr_binding.wl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR;
149 GHOST_ASSERT(
false,
"Unexpected State: logical error, unreachable!");
153# if defined(WITH_GHOST_X11)
155 oxr_binding.egl.type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX;
156# if XR_CURRENT_API_VERSION >= XR_MAKE_VERSION(1, 0, 29)
157 oxr_binding.egl.getProcAddress =
reinterpret_cast<PFN_xrEglGetProcAddressMNDX
>(
160 oxr_binding.egl.getProcAddress =
reinterpret_cast<PFNEGLGETPROCADDRESSPROC
>(
167 GHOST_ASSERT(
false,
"Unexpected State: built with only WAYLAND and no System found!");
172# if defined(WITH_GHOST_X11)
174 XVisualInfo *visual_info = glXGetVisualFromFBConfig(ctx_glx.m_display, ctx_glx.m_fbconfig);
176 oxr_binding.glx.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR;
185 GHOST_ASSERT(
false,
"Unexpected State: built without X11 and no EGL context is available!");
191 oxr_binding.wgl.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR;
197 glGenFramebuffers(1, &m_fbo);
201 GHOST_TXrSwapchainFormat &r_format,
202 bool &r_is_srgb_format)
const override
204 std::vector<int64_t> gpu_binding_formats = {
224 r_format = GHOST_kXrSwapchainFormatRGB10_A2;
227 r_format = GHOST_kXrSwapchainFormatRGBA16;
230 r_format = GHOST_kXrSwapchainFormatRGBA16F;
233 case GL_SRGB8_ALPHA8:
234 r_format = GHOST_kXrSwapchainFormatRGBA8;
237 r_is_srgb_format = (*result == GL_SRGB8_ALPHA8);
240 r_format = GHOST_kXrSwapchainFormatRGBA8;
241 r_is_srgb_format =
false;
249 std::vector<XrSwapchainImageOpenGLKHR> ogl_images(image_count);
250 std::vector<XrSwapchainImageBaseHeader *> base_images;
254 for (XrSwapchainImageOpenGLKHR &image : ogl_images) {
255 image.type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR;
256 base_images.push_back(
reinterpret_cast<XrSwapchainImageBaseHeader *
>(&image));
260 m_image_cache.push_back(std::move(ogl_images));
266 const GHOST_XrDrawViewInfo &draw_info)
override
268 XrSwapchainImageOpenGLKHR &ogl_swapchain_image =
reinterpret_cast<XrSwapchainImageOpenGLKHR &
>(
271 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
273 glFramebufferTexture2D(
274 GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ogl_swapchain_image.image, 0);
276 glBlitFramebuffer(draw_info.ofsx,
278 draw_info.ofsx + draw_info.width,
279 draw_info.ofsy + draw_info.height,
282 draw_info.ofsx + draw_info.width,
283 draw_info.ofsy + draw_info.height,
287 glBindFramebuffer(GL_FRAMEBUFFER, 0);
296 std::list<std::vector<XrSwapchainImageOpenGLKHR>> m_image_cache;
301static void ghost_format_to_dx_format(GHOST_TXrSwapchainFormat ghost_format,
302 bool expects_srgb_buffer,
303 DXGI_FORMAT &r_dx_format)
305 r_dx_format = DXGI_FORMAT_UNKNOWN;
307 switch (ghost_format) {
308 case GHOST_kXrSwapchainFormatRGBA8:
309 r_dx_format = expects_srgb_buffer ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB :
310 DXGI_FORMAT_R8G8B8A8_UNORM;
312 case GHOST_kXrSwapchainFormatRGBA16:
313 r_dx_format = DXGI_FORMAT_R16G16B16A16_UNORM;
315 case GHOST_kXrSwapchainFormatRGBA16F:
316 r_dx_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
318 case GHOST_kXrSwapchainFormatRGB10_A2:
319 r_dx_format = DXGI_FORMAT_R10G10B10A2_UNORM;
323 if (r_dx_format == DXGI_FORMAT_UNKNOWN) {
335 ~GHOST_XrGraphicsBindingD3D()
337 if (m_shared_resource) {
338 m_ghost_d3d_ctx->disposeSharedOpenGLResource(m_shared_resource);
340 if (m_ghost_d3d_ctx) {
348 XrSystemId system_id,
349 std::string *r_requirement_info)
const override
351 static PFN_xrGetD3D11GraphicsRequirementsKHR s_xrGetD3D11GraphicsRequirementsKHR_fn =
nullptr;
353 XrGraphicsRequirementsD3D11KHR gpu_requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
361 s_xrGetD3D11GraphicsRequirementsKHR_fn =
nullptr;
363 if (!s_xrGetD3D11GraphicsRequirementsKHR_fn &&
365 xrGetInstanceProcAddr(instance,
366 "xrGetD3D11GraphicsRequirementsKHR",
367 (PFN_xrVoidFunction *)&s_xrGetD3D11GraphicsRequirementsKHR_fn)))
369 s_xrGetD3D11GraphicsRequirementsKHR_fn =
nullptr;
373 s_xrGetD3D11GraphicsRequirementsKHR_fn(instance, system_id, &gpu_requirements);
375 if (r_requirement_info) {
376 std::ostringstream strstream;
377 strstream <<
"Minimum DirectX 11 Feature Level " << gpu_requirements.minFeatureLevel
380 *r_requirement_info = strstream.str();
383 return m_ghost_d3d_ctx->m_device->GetFeatureLevel() >= gpu_requirements.minFeatureLevel;
390 oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
391 oxr_binding.d3d11.device = m_ghost_d3d_ctx->m_device;
395 GHOST_TXrSwapchainFormat &r_format,
396 bool &r_is_srgb_format)
const override
398 std::vector<int64_t> gpu_binding_formats = {
401 DXGI_FORMAT_R10G10B10A2_UNORM,
402 DXGI_FORMAT_R16G16B16A16_UNORM,
404 DXGI_FORMAT_R16G16B16A16_FLOAT,
406 DXGI_FORMAT_R10G10B10A2_UNORM,
407 DXGI_FORMAT_R16G16B16A16_UNORM,
409 DXGI_FORMAT_R8G8B8A8_UNORM,
410 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
417 case DXGI_FORMAT_R10G10B10A2_UNORM:
418 r_format = GHOST_kXrSwapchainFormatRGB10_A2;
420 case DXGI_FORMAT_R16G16B16A16_UNORM:
421 r_format = GHOST_kXrSwapchainFormatRGBA16;
423 case DXGI_FORMAT_R16G16B16A16_FLOAT:
424 r_format = GHOST_kXrSwapchainFormatRGBA16F;
426 case DXGI_FORMAT_R8G8B8A8_UNORM:
427 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
428 r_format = GHOST_kXrSwapchainFormatRGBA8;
431 r_is_srgb_format = (*result == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
434 r_format = GHOST_kXrSwapchainFormatRGBA8;
435 r_is_srgb_format =
false;
443 std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
444 std::vector<XrSwapchainImageBaseHeader *> base_images;
448 for (XrSwapchainImageD3D11KHR &image : d3d_images) {
449 image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
450 base_images.push_back(
reinterpret_cast<XrSwapchainImageBaseHeader *
>(&image));
454 m_image_cache.push_back(std::move(d3d_images));
460 const GHOST_XrDrawViewInfo &draw_info)
override
462 XrSwapchainImageD3D11KHR &d3d_swapchain_image =
reinterpret_cast<XrSwapchainImageD3D11KHR &
>(
472 ID3D11RenderTargetView *rtv;
473 CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
474 DXGI_FORMAT_R8G8B8A8_UNORM);
476 m_ghost_ctx->m_device->CreateRenderTargetView(d3d_swapchain_image.texture, &rtv_desc, &rtv);
477 if (!m_shared_resource) {
479 ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer,
format);
480 m_shared_resource = m_ghost_ctx->createSharedOpenGLResource(
481 draw_info.width, draw_info.height,
format, rtv);
483 m_ghost_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
485 if (!m_shared_resource) {
487 ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer,
format);
488 m_shared_resource = m_ghost_d3d_ctx->createSharedOpenGLResource(
489 draw_info.width, draw_info.height,
format);
491 m_ghost_d3d_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
493 m_ghost_d3d_ctx->m_device_ctx->OMSetRenderTargets(0,
nullptr,
nullptr);
494 m_ghost_d3d_ctx->m_device_ctx->CopyResource(
495 d3d_swapchain_image.texture, m_ghost_d3d_ctx->getSharedTexture2D(m_shared_resource));
501 return m_ghost_d3d_ctx->isUpsideDown();
512 std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
520 case GHOST_kXrGraphicsOpenGL:
521 return std::make_unique<GHOST_XrGraphicsBindingOpenGL>();
523 case GHOST_kXrGraphicsD3D11:
524 return std::make_unique<GHOST_XrGraphicsBindingD3D>(context);
GHOST C-API function and type declarations.
#define GHOST_ASSERT(x, info)
static std::optional< int64_t > choose_swapchain_format_from_candidates(const std::vector< int64_t > &gpu_binding_formats, const std::vector< int64_t > &runtime_formats)
std::unique_ptr< GHOST_IXrGraphicsBinding > GHOST_XrGraphicsBindingCreateFromType(GHOST_TXrGraphicsBinding type, GHOST_Context &context)
EGLConfig getConfig() const
EGLDisplay getDisplay() const
EGLContext getContext() const
virtual bool isUpsideDown() const
union GHOST_IXrGraphicsBinding::@1476 oxr_binding
virtual bool needsUpsideDownDrawing(GHOST_Context &ghost_ctx) const =0
virtual std::vector< XrSwapchainImageBaseHeader * > createSwapchainImages(uint32_t image_count)=0
virtual bool checkVersionRequirements(class GHOST_Context &ghost_ctx, XrInstance instance, XrSystemId system_id, std::string *r_requirement_info) const =0
virtual std::optional< int64_t > chooseSwapchainFormat(const std::vector< int64_t > &runtime_formats, GHOST_TXrSwapchainFormat &r_format, bool &r_is_rgb_format) const =0
virtual void initFromGhostContext(class GHOST_Context &ghost_ctx)=0
virtual void submitToSwapchainImage(XrSwapchainImageBaseHeader &swapchain_image, const GHOST_XrDrawViewInfo &draw_info)=0
static GHOST_ContextD3D * createOffscreenContextD3D()
static GHOST_TSuccess disposeContextD3D(GHOST_ContextD3D *context)
~GHOST_XrGraphicsBindingOpenGL()
bool needsUpsideDownDrawing(GHOST_Context &ghost_ctx) const override
std::optional< int64_t > chooseSwapchainFormat(const std::vector< int64_t > &runtime_formats, GHOST_TXrSwapchainFormat &r_format, bool &r_is_srgb_format) const override
void initFromGhostContext(GHOST_Context &ghost_ctx) override
bool checkVersionRequirements(GHOST_Context &ghost_ctx, XrInstance instance, XrSystemId system_id, std::string *r_requirement_info) const override
std::vector< XrSwapchainImageBaseHeader * > createSwapchainImages(uint32_t image_count) override
void submitToSwapchainImage(XrSwapchainImageBaseHeader &swapchain_image, const GHOST_XrDrawViewInfo &draw_info) override