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:
Ryan Pavlik 2021-10-15 14:36:57 -05:00
parent afe84a2c35
commit bdcc5be476
4 changed files with 337 additions and 0 deletions

View file

@ -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()

View 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(&current_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(&current_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(&current_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;
}

View 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

View 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;
}