mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 04:36:07 +00:00
comp: Split OpenGL[ES] swapchain types
This commit is contained in:
parent
475192ec73
commit
fc73ba0401
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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
|
||||
|
|
232
src/xrt/compositor/client/comp_gl_eglimage_swapchain.c
Normal file
232
src/xrt/compositor/client/comp_gl_eglimage_swapchain.c
Normal 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;
|
||||
}
|
56
src/xrt/compositor/client/comp_gl_eglimage_swapchain.h
Normal file
56
src/xrt/compositor/client/comp_gl_eglimage_swapchain.h
Normal 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
|
121
src/xrt/compositor/client/comp_gl_memobj_swapchain.c
Normal file
121
src/xrt/compositor/client/comp_gl_memobj_swapchain.c
Normal 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
|
||||
}
|
55
src/xrt/compositor/client/comp_gl_memobj_swapchain.h
Normal file
55
src/xrt/compositor/client/comp_gl_memobj_swapchain.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 += [
|
||||
|
|
Loading…
Reference in a new issue