comp: Split OpenGL[ES] swapchain types

This commit is contained in:
Ryan Pavlik 2020-07-17 17:51:45 -05:00
parent 475192ec73
commit fc73ba0401
10 changed files with 562 additions and 86 deletions

View file

@ -49,6 +49,8 @@ if(XRT_HAVE_OPENGL OR XRT_HAVE_OPENGLES)
list(APPEND CLIENT_SOURCE_FILES
client/comp_gl_client.c
client/comp_gl_client.h
client/comp_gl_memobj_swapchain.c
client/comp_gl_memobj_swapchain.h
)
endif()
if(XRT_HAVE_OPENGL)
@ -59,6 +61,8 @@ endif()
if(XRT_HAVE_OPENGLES)
list(APPEND CLIENT_SOURCE_FILES
client/comp_gles_glue.c
client/comp_gl_eglimage_swapchain.c
client/comp_gl_eglimage_swapchain.h
)
endif()
if(XRT_HAVE_OPENGL AND XRT_HAVE_XLIB)

View file

@ -8,18 +8,26 @@
* @ingroup comp_client
*/
#define EGL_EGL_PROTOTYPES 0
#define EGL_NO_X11
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <xrt/xrt_config_os.h>
#include <xrt/xrt_config_have.h>
#include "ogl/egl_api.h"
#include "ogl/ogl_api.h"
#include <stdio.h>
#include <stdlib.h>
#include "client/comp_gl_client.h"
#include "client/comp_gl_memobj_swapchain.h"
#include "client/comp_gl_eglimage_swapchain.h"
#include "util/u_misc.h"
#include "xrt/xrt_gfx_egl.h"
#ifndef XRT_HAVE_EGL
#error "This file shouldn't be compiled without EGL"
#endif
// Not forward declared by mesa
typedef EGLBoolean EGLAPIENTRY (*PFNEGLMAKECURRENTPROC)(EGLDisplay dpy,
EGLSurface draw,
@ -40,15 +48,14 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn,
EGLDisplay display,
EGLConfig config,
EGLContext context,
PFNEGLGETPROCADDRESSPROC getProcAddress)
PFNEGLGETPROCADDRESSPROC get_gl_procaddr)
{
PFNEGLMAKECURRENTPROC eglMakeCurrent =
(PFNEGLMAKECURRENTPROC)getProcAddress("eglMakeCurrent");
if (!eglMakeCurrent) {
/* TODO: sort out logging here */
fprintf(stderr, "getProcAddress(eglMakeCurrent) failed\n");
return NULL;
}
#if defined(XRT_HAVE_OPENGL)
gladLoadGL(get_gl_procaddr);
#elif defined(XRT_HAVE_OPENGLES)
gladLoadGLES2(get_gl_procaddr);
#endif
gladLoadEGL(display, get_gl_procaddr);
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context)) {
fprintf(stderr, "Failed to make EGL context current\n");
@ -57,7 +64,19 @@ xrt_gfx_provider_create_gl_egl(struct xrt_compositor_native *xcn,
struct client_gl_compositor *c =
U_TYPED_CALLOC(struct client_gl_compositor);
if (!client_gl_compositor_init(c, xcn, getProcAddress)) {
#if defined(XRT_OS_ANDROID)
client_gl_swapchain_create_func sc_create = NULL;
#else
client_gl_swapchain_create_func sc_create =
client_gl_memobj_swapchain_create;
if (!GLAD_GL_EXT_memory_object && GLAD_EGL_EXT_image_dma_buf_import) {
sc_create = client_gl_eglimage_swapchain_create;
}
#endif
if (!client_gl_compositor_init(c, xcn, get_gl_procaddr, sc_create)) {
free(c);
fprintf(stderr, "Failed to initialize compositor\n");
return NULL;

View file

@ -42,26 +42,6 @@ client_gl_swapchain(struct xrt_swapchain *xsc)
*
*/
static void
client_gl_swapchain_destroy(struct xrt_swapchain *xsc)
{
struct client_gl_swapchain *sc = client_gl_swapchain(xsc);
uint32_t num_images = sc->base.base.num_images;
if (num_images > 0) {
glDeleteTextures(num_images, &sc->base.images[0]);
U_ZERO_ARRAY(sc->base.images);
glDeleteMemoryObjectsEXT(num_images, &sc->memory[0]);
U_ZERO_ARRAY(sc->base.images);
sc->base.base.num_images = 0;
}
// Destroy the native swapchain as well.
xrt_swapchain_destroy((struct xrt_swapchain **)&sc->xscn);
free(sc);
}
static xrt_result_t
client_gl_swapchain_acquire_image(struct xrt_swapchain *xsc,
uint32_t *out_index)
@ -285,54 +265,31 @@ client_gl_swapchain_create(struct xrt_compositor *xc,
}
assert(xscn != NULL);
struct xrt_swapchain *xsc = &xscn->base;
struct client_gl_swapchain *sc =
U_TYPED_CALLOC(struct client_gl_swapchain);
sc->base.base.destroy = client_gl_swapchain_destroy;
sc->base.base.acquire_image = client_gl_swapchain_acquire_image;
sc->base.base.wait_image = client_gl_swapchain_wait_image;
sc->base.base.release_image = client_gl_swapchain_release_image;
// Fetch the number of images from the native swapchain.
sc->base.base.num_images = xsc->num_images;
sc->xscn = xscn;
// Save texture binding
GLuint prev_texture = 0;
glGetIntegerv(info->array_size == 1 ? GL_TEXTURE_BINDING_2D
: GL_TEXTURE_BINDING_2D_ARRAY,
(GLint *)&prev_texture);
glGenTextures(xsc->num_images, sc->base.images);
for (uint32_t i = 0; i < xsc->num_images; i++) {
glBindTexture(info->array_size == 1 ? GL_TEXTURE_2D
: GL_TEXTURE_2D_ARRAY,
sc->base.images[i]);
}
glCreateMemoryObjectsEXT(xsc->num_images, &sc->memory[0]);
for (uint32_t i = 0; i < xsc->num_images; i++) {
GLint dedicated = GL_TRUE;
glMemoryObjectParameterivEXT(
sc->memory[i], GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated);
glImportMemoryFdEXT(sc->memory[i], xscn->images[i].size,
GL_HANDLE_TYPE_OPAQUE_FD_EXT,
xscn->images[i].handle);
struct xrt_swapchain *xsc = &xscn->base;
// We have consumed this handle now, make sure it's not freed
// again.
xscn->images[i].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID;
if (info->array_size == 1) {
glTextureStorageMem2DEXT(
sc->base.images[i], info->mip_count,
(GLuint)info->format, info->width, info->height,
sc->memory[i], 0);
} else {
glTextureStorageMem3DEXT(
sc->base.images[i], info->mip_count,
(GLuint)info->format, info->width, info->height,
info->array_size, sc->memory[i], 0);
}
struct client_gl_swapchain *sc = NULL;
if (NULL == c->create_swapchain(xc, info, xscn, &sc)) {
xrt_swapchain_destroy(&xsc);
return XRT_ERROR_OPENGL;
}
if (NULL == sc->base.base.acquire_image) {
sc->base.base.acquire_image = client_gl_swapchain_acquire_image;
}
if (NULL == sc->base.base.wait_image) {
sc->base.base.wait_image = client_gl_swapchain_wait_image;
}
if (NULL == sc->base.base.release_image) {
sc->base.base.release_image = client_gl_swapchain_release_image;
}
// Fetch the number of images from the native swapchain.
sc->base.base.num_images = xsc->num_images;
sc->xscn = xscn;
glBindTexture(info->array_size == 1 ? GL_TEXTURE_2D
: GL_TEXTURE_2D_ARRAY,
@ -361,7 +318,8 @@ client_gl_compositor_destroy(struct xrt_compositor *xc)
bool
client_gl_compositor_init(struct client_gl_compositor *c,
struct xrt_compositor_native *xcn,
client_gl_get_procaddr get_gl_procaddr)
client_gl_get_procaddr get_gl_procaddr,
client_gl_swapchain_create_func create_swapchain)
{
c->base.base.create_swapchain = client_gl_swapchain_create;
c->base.base.prepare_session = client_gl_compositor_prepare_session;
@ -377,6 +335,7 @@ client_gl_compositor_init(struct client_gl_compositor *c,
c->base.base.layer_commit = client_gl_compositor_layer_commit;
c->base.base.destroy = client_gl_compositor_destroy;
c->base.base.poll_events = client_gl_compositor_poll_events;
c->create_swapchain = create_swapchain;
c->xcn = xcn;
// Passthrough our formats from the native compositor to the client.
@ -395,6 +354,7 @@ client_gl_compositor_init(struct client_gl_compositor *c,
gladLoadGL(get_gl_procaddr);
#elif defined(XRT_HAVE_OPENGLES)
gladLoadGLES2(get_gl_procaddr);
gladLoadEGL(display, get_gl_procaddr);
#endif
// @todo log this to a proper logger.
#define CHECK_REQUIRED_EXTENSION(EXT) \

View file

@ -15,7 +15,6 @@
extern "C" {
#endif
/*
*
* Structs
@ -37,11 +36,30 @@ struct client_gl_swapchain
struct xrt_swapchain_gl base;
struct xrt_swapchain_native *xscn;
// GLuint
unsigned int memory[XRT_MAX_SWAPCHAIN_IMAGES];
};
/*!
* The type of a swapchain create constructor.
*
* Because our swapchain creation varies depending on available extensions and
* application choices, the swapchain constructor parameter to
* client_gl_compositor is parameterized.
*
* Note that the "common" swapchain creation function does some setup before
* invoking this, and some cleanup after.
*
* - Must populate `destroy`
* - Does not need to save/restore texture binding
*/
typedef struct xrt_swapchain *(*client_gl_swapchain_create_func)(
struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain_native *xscn,
struct client_gl_swapchain **out_sc);
typedef void (*client_gl_void_ptr_func)();
typedef client_gl_void_ptr_func (*client_gl_get_procaddr)(const char *name);
/*!
* @class client_gl_compositor
*
@ -55,6 +73,11 @@ struct client_gl_compositor
struct xrt_compositor_gl base;
struct xrt_compositor_native *xcn;
/*!
* Function pointer for creating the client swapchain.
*/
client_gl_swapchain_create_func create_swapchain;
};
@ -64,7 +87,6 @@ struct client_gl_compositor
*
*/
/*!
* Down-cast helper.
* @protected @memberof client_gl_compositor
@ -75,10 +97,6 @@ client_gl_compositor(struct xrt_compositor *xc)
return (struct client_gl_compositor *)xc;
}
typedef void (*client_gl_void_ptr_func)();
typedef client_gl_void_ptr_func (*client_gl_get_procaddr)(const char *name);
/*!
* Fill in a client_gl_compositor and do common OpenGL sanity checking.
*
@ -93,7 +111,8 @@ typedef client_gl_void_ptr_func (*client_gl_get_procaddr)(const char *name);
bool
client_gl_compositor_init(struct client_gl_compositor *c,
struct xrt_compositor_native *xcn,
client_gl_get_procaddr get_gl_procaddr);
client_gl_get_procaddr get_gl_procaddr,
client_gl_swapchain_create_func create_swapchain);
#ifdef __cplusplus

View file

@ -0,0 +1,232 @@
// Copyright 2019-2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief OpenGL client side glue to swapchain implementation -
* EGLImageKHR-backed.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_client
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include "util/u_misc.h"
#include <xrt/xrt_config_have.h>
#include <xrt/xrt_config_os.h>
#if defined(XRT_HAVE_EGL)
#include "ogl/egl_api.h"
#endif
#if defined(XRT_HAVE_OPENGL) || defined(XRT_HAVE_OPENGLES)
#include "ogl/ogl_api.h"
#endif
#include "client/comp_gl_client.h"
#include "client/comp_gl_eglimage_swapchain.h"
#include <inttypes.h>
/*!
* Down-cast helper.
* @private @memberof client_gl_eglimage_swapchain
*/
static inline struct client_gl_eglimage_swapchain *
client_gl_eglimage_swapchain(struct xrt_swapchain *xsc)
{
return (struct client_gl_eglimage_swapchain *)xsc;
}
/*
*
* Swapchain functions.
*
*/
// This is shared between "destroy" and an error cleanup
static void
client_gl_eglimage_swapchain_teardown_storage(
struct client_gl_eglimage_swapchain *sc)
{
uint32_t num_images = sc->base.base.base.num_images;
if (num_images > 0) {
glDeleteTextures(num_images, &sc->base.base.images[0]);
U_ZERO_ARRAY(sc->base.base.images);
for (uint32_t i = 0; i < num_images; ++i) {
if (sc->egl_images[i] != NULL) {
eglDestroyImageKHR(sc->display,
&(sc->egl_images[i]));
}
}
U_ZERO_ARRAY(sc->egl_images);
}
}
static void
client_gl_eglimage_swapchain_destroy(struct xrt_swapchain *xsc)
{
struct client_gl_eglimage_swapchain *sc =
client_gl_eglimage_swapchain(xsc);
client_gl_eglimage_swapchain_teardown_storage(sc);
sc->base.base.base.num_images = 0;
// Destroy the native swapchain as well.
xrt_swapchain_destroy((struct xrt_swapchain **)&sc->base.xscn);
free(sc);
}
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
/*
* See
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/drm/drm_fourcc.h
* for the "source of truth" for this data.
*/
#define XRT_FOURCC(A, B, C, D) \
((uint32_t)(A) | ((uint32_t)(B) << 8) | ((uint32_t)(C) << 16) | \
((uint32_t)(D) << 24))
static inline uint32_t
gl_format_to_drm_fourcc(uint64_t format)
{
switch (format) {
case GL_RGBA8:
return XRT_FOURCC('R', 'A', '2', '4'); /*DRM_FORMAT_RGBA8888*/
case GL_SRGB8_ALPHA8:
return XRT_FOURCC('R', 'A', '2', '4'); /*DRM_FORMAT_RGBA8888*/
case GL_RGB10_A2:
return XRT_FOURCC('A', 'B', '3',
'0'); /*DRM_FORMAT_ABGR2101010*/
#if 0
/* couldn't find a matching code? */
case GL_RGBA16F:
#endif
default:
printf("Cannot convert VK format 0x%016" PRIx64
" to DRM FOURCC format!\n",
format);
return 0;
}
}
static inline uint32_t
gl_format_to_bpp(uint64_t format)
{
switch (format) {
case GL_RGBA8: return 32; /*DRM_FORMAT_RGBA8888*/
case GL_SRGB8_ALPHA8: return 32; /*DRM_FORMAT_RGBA8888*/
case GL_RGB10_A2: return 32; /*DRM_FORMAT_ABGR2101010*/
#if 0
/* couldn't find a matching code? */
case GL_RGBA16F:
#endif
default:
printf("Cannot convert VK format 0x%016" PRIx64
" to DRM FOURCC format!\n",
format);
return 0;
}
}
#endif // defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
struct xrt_swapchain *
client_gl_eglimage_swapchain_create(
struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain_native *xscn,
struct client_gl_swapchain **out_sc)
{
if (xscn == NULL) {
return NULL;
}
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
uint32_t format = gl_format_to_drm_fourcc(info->format);
if (format == 0) {
return NULL;
}
uint32_t row_bits = gl_format_to_bpp(info->format) * info->width;
uint32_t row_pitch = row_bits / 8;
if (row_pitch * 8 < row_bits) {
// round up
row_pitch += 1;
}
#endif // defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
struct xrt_swapchain *native_xsc = &xscn->base;
struct client_gl_eglimage_swapchain *sc =
U_TYPED_CALLOC(struct client_gl_eglimage_swapchain);
struct xrt_swapchain_gl *xscgl = &sc->base.base;
struct xrt_swapchain *client_xsc = &xscgl->base;
client_xsc->destroy = client_gl_eglimage_swapchain_destroy;
// Fetch the number of images from the native swapchain.
client_xsc->num_images = native_xsc->num_images;
sc->base.xscn = xscn;
sc->display = eglGetCurrentDisplay();
glGenTextures(native_xsc->num_images, xscgl->images);
for (uint32_t i = 0; i < native_xsc->num_images; i++) {
#ifdef XRT_OS_ANDROID
glBindTexture(GL_TEXTURE_EXTERNAL_OES, xscgl->images[i]);
#else
glBindTexture(info->array_size == 1 ? GL_TEXTURE_2D
: GL_TEXTURE_2D_ARRAY,
xscgl->images[i]);
#endif
EGLClientBuffer native_buffer = NULL;
#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER)
native_buffer =
eglGetNativeClientBufferANDROID(xscn->images[i].handle);
if (NULL == native_buffer) {
client_gl_eglimage_swapchain_teardown_storage(sc);
free(sc);
return NULL;
}
EGLint attrs[] = {EGL_NONE};
EGLenum target = EGL_NATIVE_BUFFER_ANDROID;
#elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD)
EGLint attrs[] = {EGL_WIDTH,
info->width,
EGL_HEIGHT,
info->height,
EGL_LINUX_DRM_FOURCC_EXT,
format,
EGL_DMA_BUF_PLANE0_FD_EXT,
xscn->images[i].handle,
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
0,
EGL_DMA_BUF_PLANE0_PITCH_EXT,
row_pitch,
EGL_NONE};
EGLenum target = EGL_LINUX_DMA_BUF_EXT;
#endif
sc->egl_images[i] = eglCreateImageKHR(
sc->display, EGL_NO_CONTEXT, target, native_buffer, attrs);
if (NULL == sc->egl_images[i]) {
client_gl_eglimage_swapchain_teardown_storage(sc);
free(sc);
return NULL;
}
glEGLImageTargetTexture2DOES(
info->array_size == 1 ? GL_TEXTURE_2D : GL_TEXTURE_2D_ARRAY,
sc->egl_images[i]);
}
return &sc->base.base.base;
}

View file

@ -0,0 +1,56 @@
// Copyright 2019-2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief OpenGL client side glue using EGLImageKHR - header.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_client
*/
#pragma once
#include "comp_gl_client.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void *EGLImage;
typedef void *EGLDisplay;
/*!
* @class client_gl_eglimage_swapchain
*
* Wraps the real compositor swapchain providing a OpenGL based interface.
*
* Almost a one to one mapping to a OpenXR swapchain.
*
* @ingroup comp_client
* @implements xrt_swapchain_gl
*/
struct client_gl_eglimage_swapchain
{
struct client_gl_swapchain base;
EGLDisplay display;
// GLuint
EGLImage egl_images[XRT_MAX_SWAPCHAIN_IMAGES];
};
/*!
* Create a swapchain, belonging to a client_gl_compositor, that uses
* some way of producing an EGLImageKHR from the native buffer.
*
* This is used on Android and on desktop when the EGL extension is used.
*/
struct xrt_swapchain *
client_gl_eglimage_swapchain_create(
struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain_native *xscn,
struct client_gl_swapchain **out_sc);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,121 @@
// Copyright 2019-2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief OpenGL client side glue to compositor implementation.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_client
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <xrt/xrt_config_have.h>
#include "util/u_misc.h"
#include "ogl/ogl_api.h"
#include "client/comp_gl_client.h"
#include "client/comp_gl_memobj_swapchain.h"
#include <inttypes.h>
/*!
* Down-cast helper.
* @private @memberof client_gl_memobj_swapchain
*/
static inline struct client_gl_memobj_swapchain *
client_gl_memobj_swapchain(struct xrt_swapchain *xsc)
{
return (struct client_gl_memobj_swapchain *)xsc;
}
/*
*
* Swapchain functions.
*
*/
static void
client_gl_memobj_swapchain_destroy(struct xrt_swapchain *xsc)
{
struct client_gl_memobj_swapchain *sc = client_gl_memobj_swapchain(xsc);
uint32_t num_images = sc->base.base.base.num_images;
if (num_images > 0) {
glDeleteTextures(num_images, &sc->base.base.images[0]);
U_ZERO_ARRAY(sc->base.base.images);
glDeleteMemoryObjectsEXT(num_images, &sc->memory[0]);
U_ZERO_ARRAY(sc->memory);
sc->base.base.base.num_images = 0;
}
// Destroy the native swapchain as well.
xrt_swapchain_destroy((struct xrt_swapchain **)&sc->base.xscn);
free(sc);
}
struct xrt_swapchain *
client_gl_memobj_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain_native *xscn,
struct client_gl_swapchain **out_cglsc)
{
#if defined(XRT_OS_ANDROID)
return NULL;
#elif defined(XRT_OS_LINUX)
struct client_gl_compositor *c = client_gl_compositor(xc);
(void)c;
if (xscn == NULL) {
return NULL;
}
struct xrt_swapchain *native_xsc = &xscn->base;
struct client_gl_memobj_swapchain *sc =
U_TYPED_CALLOC(struct client_gl_memobj_swapchain);
struct xrt_swapchain_gl *xscgl = &sc->base.base;
struct xrt_swapchain *client_xsc = &xscgl->base;
client_xsc->destroy = client_gl_memobj_swapchain_destroy;
// Fetch the number of images from the native swapchain.
client_xsc->num_images = native_xsc->num_images;
sc->base.xscn = xscn;
glGenTextures(native_xsc->num_images, xscgl->images);
for (uint32_t i = 0; i < native_xsc->num_images; i++) {
glBindTexture(info->array_size == 1 ? GL_TEXTURE_2D
: GL_TEXTURE_2D_ARRAY,
xscgl->images[i]);
}
glCreateMemoryObjectsEXT(native_xsc->num_images, &sc->memory[0]);
for (uint32_t i = 0; i < native_xsc->num_images; i++) {
GLint dedicated = GL_TRUE;
glMemoryObjectParameterivEXT(
sc->memory[i], GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated);
glImportMemoryFdEXT(sc->memory[i], xscn->images[i].size,
GL_HANDLE_TYPE_OPAQUE_FD_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 client_xsc;
#endif
}

View file

@ -0,0 +1,55 @@
// Copyright 2019-2020, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief OpenGL client side glue using memory objects - header.
* @author Ryan Pavlik <ryan.pavlik@collabora.com>
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup comp_client
*/
#pragma once
#include "comp_gl_client.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* @class client_gl_memobj_swapchain
*
* Wraps the real compositor swapchain providing a OpenGL based interface.
*
* Almost a one to one mapping to a OpenXR swapchain.
*
* @ingroup comp_client
* @implements xrt_swapchain_gl
*/
struct client_gl_memobj_swapchain
{
struct client_gl_swapchain base;
// GLuint
unsigned int memory[XRT_MAX_SWAPCHAIN_IMAGES];
};
/*!
* Create a swapchain, belonging to a client_gl_compositor, that uses
* GL_memory_object and related extensions to access the native buffer.
*
* This is most commonly used on desktop OpenGL.
*
* @see client_gl_swapchain_create_func, client_gl_compositor_init
*/
struct xrt_swapchain *
client_gl_memobj_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain_native *xscn,
struct client_gl_swapchain **out_sc);
#ifdef __cplusplus
}
#endif

View file

@ -15,6 +15,7 @@
#include "xrt/xrt_gfx_xlib.h"
#include "client/comp_gl_xlib_client.h"
#include "client/comp_gl_memobj_swapchain.h"
/*!
@ -56,7 +57,8 @@ client_gl_xlib_compositor_create(struct xrt_compositor_native *xcn,
struct client_gl_xlib_compositor *c =
U_TYPED_CALLOC(struct client_gl_xlib_compositor);
if (!client_gl_compositor_init(&c->base, xcn, glXGetProcAddress)) {
if (!client_gl_compositor_init(&c->base, xcn, glXGetProcAddress,
client_gl_memobj_swapchain_create)) {
free(c);
return NULL;
}

View file

@ -48,6 +48,8 @@ if build_opengl or build_opengles
compositor_srcs += [
'client/comp_gl_client.c',
'client/comp_gl_client.h',
'client/comp_gl_memobj_swapchain.c',
'client/comp_gl_memobj_swapchain.h',
]
endif
@ -65,6 +67,12 @@ if build_opengles
compositor_deps += [opengles]
compositor_includes += [glad_include]
endif
if build_egl
compositor_srcs += [
'client/comp_gl_eglimage_swapchain.c',
'client/comp_gl_eglimage_swapchain.h',
]
endif
if build_opengl and build_xlib
compositor_srcs += [