blob: 686b65e5bab5cc84a81e78c08a2939d1d6dc146e [file] [log] [blame]
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
* deal in the Materials without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Materials, and to permit persons to whom the Materials are
* furnished to do so, subject to the following conditions:
*
* The above copyright notice(s) and this permission notice shall be included in
* all copies or substantial portions of the Materials.
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
*
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
* USE OR OTHER DEALINGS IN THE MATERIALS.
*
* Author: Charles Giessen <charles@lunarg.com>
*/
#include "test_environment.h"
#if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
#include <X11/Xutil.h>
#endif
class RegressionTests : public ::testing::Test {
protected:
virtual void SetUp() { env = std::unique_ptr<SingleICDShim>(new SingleICDShim(TestICDDetails(TEST_ICD_PATH_VERSION_2))); }
virtual void TearDown() { env.reset(); }
std::unique_ptr<SingleICDShim> env;
int width = 100;
int height = 100;
};
#if defined(VK_USE_PLATFORM_WIN32_KHR)
// MS-Windows event handling function:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProcA(hWnd, uMsg, wParam, lParam); }
TEST_F(RegressionTests, CreateSurfaceWin32) {
auto& driver = env->get_test_icd();
driver.SetICDAPIVersion(VK_MAKE_VERSION(1, 0, 0));
driver.SetMinICDInterfaceVersion(5);
driver.AddInstanceExtension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
driver.AddInstanceExtension(Extension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME));
driver.enable_icd_wsi = true;
InstWrapper inst{env->vulkan_functions};
inst.create_info = driver.GetVkInstanceCreateInfo();
inst.CheckCreate();
WNDCLASSEX win_class;
const char* app_short_name = "loader_surface_test";
HINSTANCE h_instance = GetModuleHandle(nullptr); // Windows Instance
HWND h_wnd = nullptr; // window handle
// Initialize the window class structure:
win_class.cbSize = sizeof(WNDCLASSEX);
win_class.style = CS_HREDRAW | CS_VREDRAW;
win_class.lpfnWndProc = WndProc;
win_class.cbClsExtra = 0;
win_class.cbWndExtra = 0;
win_class.hInstance = h_instance;
win_class.hIcon = LoadIconA(nullptr, IDI_APPLICATION);
win_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
win_class.lpszMenuName = nullptr;
win_class.lpszClassName = app_short_name;
win_class.hIconSm = LoadIconA(nullptr, IDI_WINLOGO);
// Register window class:
EXPECT_TRUE(RegisterClassExA(&win_class) != NULL);
// Create window with the registered class:
RECT wr = {0, 0, width, height};
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
h_wnd = CreateWindowExA(0,
app_short_name, // class name
app_short_name, // app name
// WS_VISIBLE | WS_SYSMENU |
WS_OVERLAPPEDWINDOW, // window style
width, height, // x/y coords
wr.right - wr.left, // width
wr.bottom - wr.top, // height
nullptr, // handle to parent
nullptr, // handle to menu
h_instance, // hInstance
nullptr); // no extra parameters
EXPECT_TRUE(h_wnd != nullptr);
VkSurfaceKHR surface{};
VkWin32SurfaceCreateInfoKHR surf_create_info{};
surf_create_info.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
surf_create_info.hwnd = h_wnd;
surf_create_info.hinstance = h_instance;
ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateWin32SurfaceKHR(inst, &surf_create_info, nullptr, &surface));
ASSERT_TRUE(surface != VK_NULL_HANDLE);
// ASSERT_EQ(driver.is_using_icd_wsi, UsingICDProvidedWSI::not_using);
env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
DestroyWindow(h_wnd);
}
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
TEST_F(RegressionTests, CreateSurfaceXCB) {
auto& driver = env->get_test_icd();
driver.SetICDAPIVersion(VK_MAKE_VERSION(1, 0, 0));
driver.SetMinICDInterfaceVersion(5);
driver.AddInstanceExtension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
driver.AddInstanceExtension(Extension(VK_KHR_XCB_SURFACE_EXTENSION_NAME));
driver.enable_icd_wsi = true;
InstWrapper inst{env->vulkan_functions};
inst.create_info = driver.GetVkInstanceCreateInfo();
inst.CheckCreate();
xcb_connection_t* xcb_connection;
xcb_screen_t* xcb_screen;
xcb_window_t xcb_window;
//--Init Connection--
const xcb_setup_t* setup;
xcb_screen_iterator_t iter;
int scr;
// API guarantees non-null xcb_connection
xcb_connection = xcb_connect(nullptr, &scr);
int conn_error = xcb_connection_has_error(xcb_connection);
ASSERT_EQ(conn_error, 0);
setup = xcb_get_setup(xcb_connection);
iter = xcb_setup_roots_iterator(setup);
while (scr-- > 0) {
xcb_screen_next(&iter);
}
xcb_screen = iter.data;
xcb_window = xcb_generate_id(xcb_connection);
xcb_create_window(xcb_connection, XCB_COPY_FROM_PARENT, xcb_window, xcb_screen->root, 0, 0, width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT, xcb_screen->root_visual, 0, nullptr);
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection, 1, 12, "WM_PROTOCOLS");
xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(xcb_connection, cookie, 0);
free(reply);
VkXcbSurfaceCreateInfoKHR xcb_createInfo;
xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
xcb_createInfo.pNext = nullptr;
xcb_createInfo.flags = 0;
xcb_createInfo.connection = xcb_connection;
xcb_createInfo.window = xcb_window;
VkSurfaceKHR surface{};
ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateXcbSurfaceKHR(inst, &xcb_createInfo, nullptr, &surface));
ASSERT_TRUE(surface != VK_NULL_HANDLE);
env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
xcb_destroy_window(xcb_connection, xcb_window);
xcb_disconnect(xcb_connection);
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
TEST_F(RegressionTests, CreateSurfaceXLIB) {
auto& driver = env->get_test_icd();
driver.SetICDAPIVersion(VK_MAKE_VERSION(1, 0, 0));
driver.SetMinICDInterfaceVersion(5);
driver.AddInstanceExtension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
driver.AddInstanceExtension(Extension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME));
driver.enable_icd_wsi = true;
InstWrapper inst{env->vulkan_functions};
inst.create_info = driver.GetVkInstanceCreateInfo();
inst.CheckCreate();
Display* xlib_display;
Window xlib_window;
long visualMask = VisualScreenMask;
int numberOfVisuals;
xlib_display = XOpenDisplay(nullptr);
ASSERT_NE(xlib_display, nullptr);
XVisualInfo vInfoTemplate = {};
vInfoTemplate.screen = DefaultScreen(xlib_display);
XVisualInfo* visualInfo = XGetVisualInfo(xlib_display, visualMask, &vInfoTemplate, &numberOfVisuals);
xlib_window = XCreateWindow(xlib_display, RootWindow(xlib_display, vInfoTemplate.screen), 0, 0, width, height, 0,
visualInfo->depth, InputOutput, visualInfo->visual, 0, nullptr);
XSync(xlib_display, false);
XFree(visualInfo);
VkXlibSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.dpy = xlib_display;
createInfo.window = xlib_window;
VkSurfaceKHR surface;
ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateXlibSurfaceKHR(inst, &createInfo, nullptr, &surface));
ASSERT_TRUE(surface != VK_NULL_HANDLE);
env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
XDestroyWindow(xlib_display, xlib_window);
XCloseDisplay(xlib_display);
}
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
struct WaylandState {
wl_display* display{};
wl_registry* registry{};
wl_compositor* compositor{};
wl_surface* surface{};
};
static void wayland_registry_global(void* data, struct wl_registry* registry, uint32_t id, const char* interface,
uint32_t version) {
WaylandState* wayland = static_cast<WaylandState*>(data);
if (string_eq(interface, "wl_compositor")) {
wayland->compositor = (struct wl_compositor*)wl_registry_bind(registry, id, &wl_compositor_interface, 1);
wayland->surface = wl_compositor_create_surface(wayland->compositor);
}
}
static void wayland_registry_global_remove(void* data, struct wl_registry* registry, uint32_t id) {}
static const struct wl_registry_listener wayland_registry_listener = {wayland_registry_global, wayland_registry_global_remove};
TEST_F(RegressionTests, CreateSurfaceWayland) {
auto& driver = env->get_test_icd();
driver.SetICDAPIVersion(VK_MAKE_VERSION(1, 0, 0));
driver.SetMinICDInterfaceVersion(5);
driver.AddInstanceExtension(Extension(VK_KHR_SURFACE_EXTENSION_NAME));
driver.AddInstanceExtension(Extension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME));
driver.enable_icd_wsi = true;
InstWrapper inst{env->vulkan_functions};
inst.create_info = driver.GetVkInstanceCreateInfo();
inst.CheckCreate();
WaylandState wayland;
wayland.display = wl_display_connect(nullptr);
ASSERT_NE(wayland.display, nullptr);
wayland.registry = wl_display_get_registry(wayland.display);
wl_registry_add_listener(wl_display_get_registry(wayland.display), &wayland_registry_listener, static_cast<void*>(&wayland));
wl_display_roundtrip(wayland.display);
wl_registry_destroy(wayland.registry);
VkWaylandSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.display = wayland.display;
createInfo.surface = wayland.surface;
VkSurfaceKHR surface;
ASSERT_EQ(VK_SUCCESS, env->vulkan_functions.vkCreateWaylandSurfaceKHR(inst, &createInfo, nullptr, &surface));
ASSERT_TRUE(surface != VK_NULL_HANDLE);
env->vulkan_functions.vkDestroySurfaceKHR(inst, surface, nullptr);
wl_display_disconnect(wayland.display);
}
#endif