// Copyright 2022, Collabora, Ltd. // SPDX-License-Identifier: BSL-1.0 /*! * @file * @brief OpenGL tests. * @author Rylie Pavlik */ #include "mock/mock_compositor.h" #include "client/comp_gl_client.h" #include "catch_amalgamated.hpp" #include "util/u_handles.h" #include "ogl/ogl_api.h" #include "xrt/xrt_config_os.h" #include "xrt/xrt_config_vulkan.h" #include "xrt/xrt_deleters.hpp" #include #include #if defined(XRT_OS_WINDOWS) #include "client/comp_gl_win32_client.h" #elif defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT) #include "client/comp_gl_xlib_client.h" #else #error "not implemented" #endif #include TEST_CASE("opengl_client_compositor", "[.][needgpu]") { xrt_compositor_native *xcn = mock_create_native_compositor(); struct mock_compositor *mc = mock_compositor(&(xcn->base)); REQUIRE(SDL_Init(SDL_INIT_VIDEO) == 0); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); auto *window = SDL_CreateWindow("Tests", 100, 100, 320, 240, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); REQUIRE(window); SDL_SysWMinfo info{}; SDL_VERSION(&info.version); REQUIRE(SDL_GetWindowWMInfo(window, &info)); auto context = SDL_GL_CreateContext(window); SDL_GL_MakeCurrent(window, context); #if defined(XRT_OS_WINDOWS) HDC hDC = info.info.win.hdc; HGLRC hGLRC = wglGetCurrentContext(); struct client_gl_win32_compositor *c = client_gl_win32_compositor_create(xcn, hDC, hGLRC); #elif defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT) Display *display = info.info.x11.display; struct client_gl_xlib_compositor *c = client_gl_xlib_compositor_create(xcn, display, 0, nullptr, nullptr, (GLXContext)context); #else #error "not implemented" #endif REQUIRE(c); struct xrt_compositor *xc = &c->base.base.base; SECTION("Swapchain create and import") { struct Data { bool nativeCreateCalled = false; bool nativeImportCalled = false; } data; mc->userdata = &data; mc->compositor_hooks.create_swapchain = [](struct mock_compositor *mc, struct mock_compositor_swapchain *mcsc, const struct xrt_swapchain_create_info *info, struct xrt_swapchain **out_xsc) { auto *data = static_cast(mc->userdata); data->nativeCreateCalled = true; return XRT_SUCCESS; }; mc->compositor_hooks.import_swapchain = [](struct mock_compositor *mc, struct mock_compositor_swapchain *mcsc, const struct xrt_swapchain_create_info *info, struct xrt_image_native *native_images, uint32_t image_count, struct xrt_swapchain **out_xscc) { auto *data = static_cast(mc->userdata); data->nativeImportCalled = true; // need to release the native handles to avoid leaks for (uint32_t i = 0; i < image_count; ++i) { u_graphics_buffer_unref(&native_images[i].handle); } return XRT_SUCCESS; }; xrt_swapchain_create_info xsci{}; xsci.format = GL_SRGB8_ALPHA8; xsci.bits = (xrt_swapchain_usage_bits)(XRT_SWAPCHAIN_USAGE_COLOR | XRT_SWAPCHAIN_USAGE_SAMPLED); xsci.sample_count = 1; xsci.width = 800; xsci.height = 600; xsci.face_count = 1; xsci.array_size = 1; xsci.mip_count = 1; SECTION("Swapchain Create") { struct xrt_swapchain *xsc = nullptr; // This will fail because the mock compositor doesn't actually import, but it will get far // enough to trigger our hook and update the flag. xrt_comp_create_swapchain(xc, &xsci, &xsc); // OpenGL should always create using the native compositor CHECK_FALSE(data.nativeImportCalled); CHECK(data.nativeCreateCalled); xrt_swapchain_reference(&xsc, nullptr); } } xrt_comp_destroy(&xc); xrt_comp_native_destroy(&xcn); SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); }