diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4ddef4052..b865258df 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,6 +35,13 @@ endif() if(XRT_HAVE_VULKAN) list(APPEND tests tests_comp_client_vulkan) endif() +if(XRT_HAVE_OPENGL + AND XRT_HAVE_SDL2 + AND (WIN32 OR VK_USE_PLATFORM_XLIB_XRANDR_EXT) + ) + set(_have_opengl_test ON) + list(APPEND tests tests_comp_client_opengl) +endif() if(XRT_BUILD_DRIVER_HANDTRACKING) list(APPEND tests tests_levenbergmarquardt) endif() @@ -58,7 +65,15 @@ target_link_libraries(tests_rational PRIVATE aux_math) target_link_libraries(tests_pose PRIVATE aux_math) if(XRT_BUILD_DRIVER_HANDTRACKING) - target_link_libraries(tests_levenbergmarquardt PRIVATE aux_math t_ht_mercury_includes t_ht_mercury_kine_lm_includes t_ht_mercury t_ht_mercury_kine_lm) + target_link_libraries( + tests_levenbergmarquardt + PRIVATE + aux_math + t_ht_mercury_includes + t_ht_mercury_kine_lm_includes + t_ht_mercury + t_ht_mercury_kine_lm + ) endif() if(XRT_HAVE_D3D11) @@ -71,5 +86,13 @@ if(XRT_HAVE_D3D12) endif() if(XRT_HAVE_VULKAN) - target_link_libraries(tests_comp_client_vulkan PRIVATE comp_client comp_mock comp_util aux_vk) + target_link_libraries( + tests_comp_client_vulkan PRIVATE comp_client comp_mock comp_util aux_vk + ) +endif() + +if(_have_opengl_test) + target_link_libraries( + tests_comp_client_opengl PRIVATE comp_client comp_mock aux_ogl ${SDL2_LIBRARIES} + ) endif() diff --git a/tests/tests_comp_client_opengl.cpp b/tests/tests_comp_client_opengl.cpp new file mode 100644 index 000000000..9cc754405 --- /dev/null +++ b/tests/tests_comp_client_opengl.cpp @@ -0,0 +1,131 @@ +// Copyright 2022, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief OpenGL tests. + * @author Ryan Pavlik + */ + + +#include "mock/mock_compositor.h" +#include "client/comp_gl_client.h" + +#include "catch/catch.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(); +}