diff --git a/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c b/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c index e1662c35d..659d7fcdb 100644 --- a/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c +++ b/src/xrt/compositor/client/comp_gl_eglimage_swapchain.c @@ -1,4 +1,5 @@ // Copyright 2019-2021, Collabora, Ltd. +// Copyright 2026, NVIDIA CORPORATION. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -9,20 +10,15 @@ * @ingroup comp_client */ -#include -#include -#include -#include +#include "xrt/xrt_config_have.h" +#include "xrt/xrt_config_os.h" +#include "xrt/xrt_handles.h" #include "util/u_misc.h" #include "util/u_logging.h" #include "util/u_debug.h" #include "util/u_handles.h" -#include -#include -#include - #include "ogl/egl_api.h" #include "ogl/ogl_api.h" #include "ogl/ogl_helpers.h" @@ -31,11 +27,16 @@ #include "client/comp_egl_client.h" #include "client/comp_gl_eglimage_swapchain.h" +#include +#include +#include +#include #ifdef XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER #include #endif + static enum u_logging_level log_level; #define EGL_SC_TRACE(...) U_LOG_IFL_T(log_level, __VA_ARGS__) @@ -178,10 +179,12 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, log_level = debug_get_log_option_egl_swapchain_log(); if (xscn == NULL) { - EGL_SC_ERROR("Native compositor is null"); + // Should never hit this path. + EGL_SC_ERROR("Native swapchain is null!"); return NULL; } + #if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) uint32_t format = gl_format_to_drm_fourcc(info->format); if (format == 0) { @@ -201,26 +204,40 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, } #endif // defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) - struct xrt_swapchain *native_xsc = &xscn->base; + + /* + * Native images setup. + */ + + const uint32_t image_count = xscn->base.image_count; + struct xrt_image_native *native_images = xscn->images; + + + /* + * Fill out the swapchain. + */ + + GLuint binding_enum = 0; + GLuint tex_target = 0; + ogl_texture_target_for_swapchain_info(info, &tex_target, &binding_enum); struct client_gl_eglimage_swapchain *sc = U_TYPED_CALLOC(struct client_gl_eglimage_swapchain); sc->base.base.base.destroy = client_gl_eglimage_swapchain_destroy; sc->base.base.base.reference.count = 1; - sc->base.base.base.image_count = - native_xsc->image_count; // Fetch the number of images from the native swapchain. + sc->base.base.base.image_count = image_count; + sc->base.tex_target = tex_target; sc->base.xscn = xscn; sc->display = ceglc->current.dpy; - struct xrt_swapchain_gl *xscgl = &sc->base.base; - glGenTextures(native_xsc->image_count, xscgl->images); + /* + * Create the EGL & OpenGL resources. + */ - GLuint binding_enum = 0; - GLuint tex_target = 0; - ogl_texture_target_for_swapchain_info(info, &tex_target, &binding_enum); - sc->base.tex_target = tex_target; + struct xrt_swapchain_gl *xscgl = &sc->base.base; + glGenTextures(image_count, xscgl->images); - for (uint32_t i = 0; i < native_xsc->image_count; i++) { + for (uint32_t i = 0; i < image_count; i++) { // Bind new texture name to the target. glBindTexture(tex_target, xscgl->images[i]); @@ -230,29 +247,28 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, #if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_AHARDWAREBUFFER) // see // https://android.googlesource.com/platform/cts/+/e59c1e8ef5c19ff49bd53dd5d039f9a773d877ec/tests/tests/nativehardware/jni/AHardwareBufferGLTest.cpp#1416 - native_buffer = eglGetNativeClientBufferANDROID(xscn->images[i].handle); + native_buffer = eglGetNativeClientBufferANDROID(native_images[i].handle); AHardwareBuffer_Desc desc; - AHardwareBuffer_describe(xscn->images[i].handle, &desc); + AHardwareBuffer_describe(native_images[i].handle, &desc); if (NULL == native_buffer) { EGL_SC_ERROR("eglGetNativeClientBufferANDROID failed"); - client_gl_eglimage_swapchain_teardown_storage(sc); - free(sc); - return NULL; + goto error; } + + EGLint protected = (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? EGL_TRUE : EGL_FALSE; + + // clang-format off EGLint attrs[] = { - EGL_IMAGE_PRESERVED_KHR, - EGL_TRUE, - EGL_PROTECTED_CONTENT_EXT, - (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? EGL_TRUE : EGL_FALSE, - EGL_NONE, - EGL_NONE, - EGL_NONE, + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_PROTECTED_CONTENT_EXT, protected, + EGL_NONE, EGL_NONE, // Reserved for sRGB + EGL_NONE, // Terminator }; + // clang-format on - EGL_SC_INFO("EGL_PROTECTED_CONTENT_EXT %s", - (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) ? "TRUE" : "FALSE"); + EGL_SC_INFO("EGL_PROTECTED_CONTENT_EXT %s", protected ? "TRUE" : "FALSE"); if (is_gl_format_srgb(info->format)) { attrs[4] = EGL_GL_COLORSPACE_KHR; @@ -261,21 +277,18 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, EGLenum source = EGL_NATIVE_BUFFER_ANDROID; #elif defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) - EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, - EGL_TRUE, - 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}; + // clang-format off + EGLint attrs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_WIDTH, info->width, + EGL_HEIGHT, info->height, + EGL_LINUX_DRM_FOURCC_EXT, format, + EGL_DMA_BUF_PLANE0_FD_EXT, native_images[i].handle, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, + EGL_DMA_BUF_PLANE0_PITCH_EXT, row_pitch, + EGL_NONE, // Terminator + }; + // clang-format on EGLenum source = EGL_LINUX_DMA_BUF_EXT; #else #error "need port" @@ -283,10 +296,9 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, sc->egl_images[i] = eglCreateImageKHR(sc->display, EGL_NO_CONTEXT, source, native_buffer, attrs); if (EGL_NO_IMAGE_KHR == sc->egl_images[i]) { EGL_SC_ERROR("eglCreateImageKHR failed"); - client_gl_eglimage_swapchain_teardown_storage(sc); - free(sc); - return NULL; + goto error; } + /*! * @todo this matches the behavior of the Google test, but is * not itself tested or fully rationalized. @@ -302,5 +314,13 @@ client_gl_eglimage_swapchain_create(struct xrt_compositor *xc, } *out_sc = &sc->base; + return &sc->base.base.base; + + +error: + client_gl_eglimage_swapchain_teardown_storage(sc); + free(sc); + + return NULL; } diff --git a/src/xrt/compositor/client/comp_gl_memobj_swapchain.c b/src/xrt/compositor/client/comp_gl_memobj_swapchain.c index fb278f9ae..1f26d4f6b 100644 --- a/src/xrt/compositor/client/comp_gl_memobj_swapchain.c +++ b/src/xrt/compositor/client/comp_gl_memobj_swapchain.c @@ -1,4 +1,5 @@ // Copyright 2019-2022, Collabora, Ltd. +// Copyright 2026, NVIDIA CORPORATION. // SPDX-License-Identifier: BSL-1.0 /*! * @file @@ -7,15 +8,11 @@ * @ingroup comp_client */ -#include -#include -#include -#include - -#include -#include +#include "xrt/xrt_config_have.h" +#include "xrt/xrt_handles.h" #include "util/u_misc.h" +#include "util/u_logging.h" #include "ogl/ogl_api.h" #include "ogl/ogl_helpers.h" @@ -23,6 +20,11 @@ #include "client/comp_gl_client.h" #include "client/comp_gl_memobj_swapchain.h" +#include +#include +#include +#include + /*! * Down-cast helper. @@ -98,42 +100,59 @@ client_gl_memobj_swapchain_create(struct xrt_compositor *xc, struct client_gl_compositor *c = client_gl_compositor(xc); (void)c; -#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) || defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE) if (xscn == NULL) { + // Should never hit this path. + U_LOG_E("Native swapchain is null!"); return NULL; } + +#if defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_FD) || defined(XRT_GRAPHICS_BUFFER_HANDLE_IS_WIN32_HANDLE) + /* + * Native images setup. + */ + + const uint32_t image_count = xscn->base.image_count; + struct xrt_image_native *native_images = xscn->images; + + + /* + * Fill out the swapchain. + */ + GLuint binding_enum = 0; GLuint tex_target = 0; ogl_texture_target_for_swapchain_info(info, &tex_target, &binding_enum); - struct xrt_swapchain *native_xsc = &xscn->base; struct client_gl_memobj_swapchain *sc = U_TYPED_CALLOC(struct client_gl_memobj_swapchain); sc->base.base.base.destroy = client_gl_memobj_swapchain_destroy; sc->base.base.base.reference.count = 1; - sc->base.base.base.image_count = - native_xsc->image_count; // Fetch the number of images from the native swapchain. + sc->base.base.base.image_count = image_count; sc->base.xscn = xscn; sc->base.tex_target = tex_target; - sc->base.gl_compositor = c; + + /* + * Create the OpenGL resources. + */ + struct xrt_swapchain_gl *xscgl = &sc->base.base; - glGenTextures(native_xsc->image_count, xscgl->images); + glGenTextures(image_count, xscgl->images); + glCreateMemoryObjectsEXT(image_count, &sc->memory[0]); - glCreateMemoryObjectsEXT(native_xsc->image_count, &sc->memory[0]); - for (uint32_t i = 0; i < native_xsc->image_count; i++) { + for (uint32_t i = 0; i < image_count; i++) { glBindTexture(tex_target, xscgl->images[i]); - GLint dedicated = xscn->images[i].use_dedicated_allocation ? GL_TRUE : GL_FALSE; + GLint dedicated = native_images[i].use_dedicated_allocation ? GL_TRUE : GL_FALSE; glMemoryObjectParameterivEXT(sc->memory[i], GL_DEDICATED_MEMORY_OBJECT_EXT, &dedicated); - if (!client_gl_memobj_swapchain_import(sc->memory[i], xscn->images[i].size, xscn->images[i].handle)) { + if (!client_gl_memobj_swapchain_import(sc->memory[i], native_images[i].size, native_images[i].handle)) { continue; } // We have consumed this now, make sure it's not freed again. - xscn->images[i].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; + native_images[i].handle = XRT_GRAPHICS_BUFFER_HANDLE_INVALID; if (info->array_size == 1) { glTexStorageMem2DEXT(tex_target, info->mip_count, (GLuint)info->format, info->width, @@ -145,6 +164,7 @@ client_gl_memobj_swapchain_create(struct xrt_compositor *xc, } *out_cglsc = &sc->base; + return &sc->base.base.base; #else