mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-29 18:08:29 +00:00
c/client: Win32 OpenGL client compositor
Co-authored-by: Milan Jaros <milan.jaros@vsb.cz> Co-authored-by: Jakob Bornecrantz <jakob@collabora.com>
This commit is contained in:
parent
afe84a2c35
commit
bdcc5be476
|
@ -54,6 +54,12 @@ 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
|
||||
)
|
||||
endif()
|
||||
if(XRT_HAVE_EGL)
|
||||
target_sources(comp_client PRIVATE client/comp_egl_client.c client/comp_egl_client.h)
|
||||
endif()
|
||||
|
|
242
src/xrt/compositor/client/comp_gl_win32_client.c
Normal file
242
src/xrt/compositor/client/comp_gl_win32_client.c
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Copyright 2019-2022, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Win32 client side glue to compositor implementation.
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @author Milan Jaros <milan.jaros@vsb.cz>
|
||||
* @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"
|
||||
|
||||
/*
|
||||
*
|
||||
* 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);
|
||||
|
||||
FreeLibrary(c->opengl);
|
||||
c->opengl = NULL;
|
||||
|
||||
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: %d (current %p -> app %p)", need_make_current,
|
||||
(void *)c->temp_context.hGLRC, (void *)app_ctx->hGLRC);
|
||||
|
||||
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: %d (app %p -> current %p)", need_make_current,
|
||||
(void *)app_ctx->hGLRC, (void *)c->temp_context.hGLRC);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static GLADapiproc
|
||||
client_gl_get_proc_addr(void *userptr, const char *name)
|
||||
{
|
||||
GLADapiproc ret = (GLADapiproc)wglGetProcAddress(name);
|
||||
if (ret == NULL) {
|
||||
ret = (GLADapiproc)GetProcAddress((HMODULE)userptr, name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct client_gl_win32_compositor *
|
||||
client_gl_win32_compositor_create(struct xrt_compositor_native *xcn, void *hDC, void *hGLRC)
|
||||
{
|
||||
// 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,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Make given context current if needed.
|
||||
*/
|
||||
|
||||
bool need_make_current = !context_matches(¤t_ctx, &app_ctx);
|
||||
|
||||
if (need_make_current && !context_make_current(&app_ctx)) {
|
||||
U_LOG_E("Failed to make WGL context current");
|
||||
// No need to restore on failure.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load functions.
|
||||
*/
|
||||
|
||||
HMODULE opengl = LoadLibraryW(L"opengl32.dll");
|
||||
|
||||
int wgl_result = gladLoadWGLUserPtr(hDC, client_gl_get_proc_addr, opengl);
|
||||
int gl_result = gladLoadGLUserPtr(client_gl_get_proc_addr, opengl);
|
||||
|
||||
if (glGetString != NULL) {
|
||||
U_LOG_D( //
|
||||
"OpenGL context:" //
|
||||
"\n\tGL_VERSION: %s" //
|
||||
"\n\tGL_RENDERER: %s" //
|
||||
"\n\tGL_VENDOR: %s", //
|
||||
glGetString(GL_VERSION), //
|
||||
glGetString(GL_RENDERER), //
|
||||
glGetString(GL_VENDOR)); //
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return to app context.
|
||||
*/
|
||||
|
||||
if (need_make_current && !context_make_current(¤t_ctx)) {
|
||||
U_LOG_E("Failed to make old WGL context current!");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checking of context.
|
||||
*/
|
||||
|
||||
// Only do error checking here.
|
||||
if (wgl_result == 0 || gl_result == 0) {
|
||||
U_LOG_E("Failed to load GLAD functions gladLoadWGL: 0x%08x, gladLoadGL: 0x%08x", wgl_result, gl_result);
|
||||
FreeLibrary(opengl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define CHECK_REQUIRED_EXTENSION(EXT) \
|
||||
do { \
|
||||
if (!GLAD_GL_##EXT) { \
|
||||
U_LOG_E("%s - Required OpenGL extension GL_" #EXT " not available", __func__); \
|
||||
FreeLibrary(opengl); \
|
||||
return NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
CHECK_REQUIRED_EXTENSION(EXT_memory_object); // why is this failing? the gpuinfo.org tool says I have it.
|
||||
CHECK_REQUIRED_EXTENSION(EXT_memory_object_win32);
|
||||
|
||||
#undef CHECK_REQUIRED_EXTENSION
|
||||
|
||||
|
||||
/*
|
||||
* Checking complete, create client compositor here.
|
||||
*/
|
||||
|
||||
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;
|
||||
// Same for the opengl library handle
|
||||
c->opengl = opengl;
|
||||
|
||||
if (!client_gl_compositor_init(&c->base, xcn, client_gl_context_begin, client_gl_context_end,
|
||||
client_gl_memobj_swapchain_create, NULL)) {
|
||||
U_LOG_E("Failed to init parent GL client compositor!");
|
||||
FreeLibrary(opengl);
|
||||
free(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c->base.base.base.destroy = client_gl_win32_compositor_destroy;
|
||||
|
||||
return c;
|
||||
}
|
64
src/xrt/compositor/client/comp_gl_win32_client.h
Normal file
64
src/xrt/compositor/client/comp_gl_win32_client.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2019-2022, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief OpenGL on Win32 client side glue to compositor header.
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @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;
|
||||
|
||||
//! The OpenGL library
|
||||
HMODULE opengl;
|
||||
};
|
||||
|
||||
/*!
|
||||
* 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, void *hDC, void *hGLRC);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
25
src/xrt/compositor/client/comp_gl_win32_glue.c
Normal file
25
src/xrt/compositor/client/comp_gl_win32_glue.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2019-2022, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Glue code to OpenGL Win32 client side code.
|
||||
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
|
||||
* @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, void *hDC, void *hGLRC)
|
||||
{
|
||||
struct client_gl_win32_compositor *xcc = client_gl_win32_compositor_create(xcn, hDC, hGLRC);
|
||||
|
||||
return &xcc->base.base;
|
||||
}
|
Loading…
Reference in a new issue