From 8458f21123bf3cac11185eda5c949b49578ed8ad Mon Sep 17 00:00:00 2001 From: Mike Gorchak Date: Fri, 1 Sep 2023 11:12:08 -0400 Subject: [PATCH] Add basic QNX support. --- base/VulkanSwapChain.cpp | 10 ++ base/VulkanSwapChain.h | 2 + base/keycodes.hpp | 24 +++ base/vulkanexamplebase.cpp | 293 +++++++++++++++++++++++++++++++++ base/vulkanexamplebase.h | 23 +++ examples/triangle/triangle.cpp | 2 + 6 files changed, 354 insertions(+) diff --git a/base/VulkanSwapChain.cpp b/base/VulkanSwapChain.cpp index fcc17be4..5c63ac31 100644 --- a/base/VulkanSwapChain.cpp +++ b/base/VulkanSwapChain.cpp @@ -25,6 +25,8 @@ void VulkanSwapChain::initSurface(xcb_connection_t* connection, xcb_window_t win void VulkanSwapChain::initSurface(void* view) #elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT)) void VulkanSwapChain::initSurface(uint32_t width, uint32_t height) +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) +void VulkanSwapChain::initSurface(screen_context_t screen_context, screen_window_t screen_window) #endif { VkResult err = VK_SUCCESS; @@ -83,6 +85,14 @@ void VulkanSwapChain::initSurface(uint32_t width, uint32_t height) vks::tools::exitFatal("Could not fetch function pointer for the headless extension!", -1); } err = fpCreateHeadlessSurfaceEXT(instance, &surfaceCreateInfo, nullptr, &surface); +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + VkScreenSurfaceCreateInfoQNX surfaceCreateInfo = {}; + surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX; + surfaceCreateInfo.pNext = NULL; + surfaceCreateInfo.flags = 0; + surfaceCreateInfo.context = screen_context; + surfaceCreateInfo.window = screen_window; + err = vkCreateScreenSurfaceQNX(instance, &surfaceCreateInfo, NULL, &surface); #endif if (err != VK_SUCCESS) { diff --git a/base/VulkanSwapChain.h b/base/VulkanSwapChain.h index 8163ad4c..36bc171b 100644 --- a/base/VulkanSwapChain.h +++ b/base/VulkanSwapChain.h @@ -65,6 +65,8 @@ public: #if defined(_DIRECT2DISPLAY) void createDirect2DisplaySurface(uint32_t width, uint32_t height); #endif +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + void initSurface(screen_context_t screen_context, screen_window_t screen_window); #endif void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device); void create(uint32_t* width, uint32_t* height, bool vsync = false, bool fullscreen = false); diff --git a/base/keycodes.hpp b/base/keycodes.hpp index ca4fd5aa..f683e245 100644 --- a/base/keycodes.hpp +++ b/base/keycodes.hpp @@ -157,4 +157,28 @@ #define KEY_N 0x39 #define KEY_O 0x20 #define KEY_T 0x1C + +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) +#include + +#define KEY_ESCAPE KEYCODE_ESCAPE +#define KEY_F1 KEYCODE_F1 +#define KEY_F2 KEYCODE_F2 +#define KEY_F3 KEYCODE_F3 +#define KEY_F4 KEYCODE_F4 +#define KEY_W KEYCODE_W +#define KEY_A KEYCODE_A +#define KEY_S KEYCODE_S +#define KEY_D KEYCODE_D +#define KEY_P KEYCODE_P +#define KEY_SPACE KEYCODE_SPACE +#define KEY_KPADD KEYCODE_KP_PLUS +#define KEY_KPSUB KEYCODE_KP_MINUS +#define KEY_B KEYCODE_B +#define KEY_F KEYCODE_F +#define KEY_L KEYCODE_L +#define KEY_N KEYCODE_N +#define KEY_O KEYCODE_O +#define KEY_T KEYCODE_T + #endif diff --git a/base/vulkanexamplebase.cpp b/base/vulkanexamplebase.cpp index 36d64499..23fe39d8 100644 --- a/base/vulkanexamplebase.cpp +++ b/base/vulkanexamplebase.cpp @@ -52,6 +52,8 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation) instanceExtensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); #elif defined(VK_USE_PLATFORM_HEADLESS_EXT) instanceExtensions.push_back(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME); +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + instanceExtensions.push_back(VK_QNX_SCREEN_SURFACE_EXTENSION_NAME); #endif // Get extensions supported by the instance and store for later use @@ -666,6 +668,14 @@ void VulkanExampleBase::renderLoop() } #elif (defined(VK_USE_PLATFORM_MACOS_MVK) && defined(VK_EXAMPLE_XCODE_GENERATED)) [NSApp run]; +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + while (!quit) { + handleEvent(); + + if (prepared) { + nextFrame(); + } + } #endif // Flush device to make sure all resources can be freed if (device != VK_NULL_HANDLE) { @@ -961,6 +971,10 @@ VulkanExampleBase::~VulkanExampleBase() #elif defined(VK_USE_PLATFORM_XCB_KHR) xcb_destroy_window(connection, window); xcb_disconnect(connection); +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + screen_destroy_event(screen_event); + screen_destroy_window(screen_window); + screen_destroy_context(screen_context); #endif } @@ -2664,6 +2678,283 @@ void VulkanExampleBase::handleEvent(const xcb_generic_event_t *event) break; } } +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) +void VulkanExampleBase::handleEvent() +{ + int size[2] = { 0, 0 }; + screen_window_t win; + static int mouse_buttons = 0; + int pos[2]; + int val; + int keyflags; + int rc; + + while (!screen_get_event(screen_context, screen_event, paused ? ~0 : 0)) { + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_TYPE of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if (val == SCREEN_EVENT_NONE) { + break; + } + switch (val) { + case SCREEN_EVENT_KEYBOARD: + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_FLAGS, &keyflags); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_FLAGS of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SYM, &val); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_SYM of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if ((keyflags & KEY_SYM_VALID) == KEY_SYM_VALID) { + switch (val) { + case KEYCODE_ESCAPE: + quit = true; + break; + case KEYCODE_W: + if (keyflags & KEY_DOWN) { + camera.keys.up = true; + } else { + camera.keys.up = false; + } + break; + case KEYCODE_S: + if (keyflags & KEY_DOWN) { + camera.keys.down = true; + } else { + camera.keys.down = false; + } + break; + case KEYCODE_A: + if (keyflags & KEY_DOWN) { + camera.keys.left = true; + } else { + camera.keys.left = false; + } + break; + case KEYCODE_D: + if (keyflags & KEY_DOWN) { + camera.keys.right = true; + } else { + camera.keys.right = false; + } + break; + case KEYCODE_P: + paused = !paused; + break; + case KEYCODE_F1: + UIOverlay.visible = !UIOverlay.visible; + UIOverlay.updated = true; + break; + default: + break; + } + + if ((keyflags & KEY_DOWN) == KEY_DOWN) { + if ((val >= 0x20) && (val <= 0xFF)) { + keyPressed(val); + } + } + } + break; + case SCREEN_EVENT_PROPERTY: + rc = screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_WINDOW, (void **)&win); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_WINDOW of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_NAME, &val); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_NAME of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if (win == screen_window) { + switch(val) { + case SCREEN_PROPERTY_SIZE: + rc = screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, size); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_SIZE of the window in the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + width = size[0]; + height = size[1]; + windowResize(); + break; + default: + /* We are not interested in any other events for now */ + break; + } + } + break; + case SCREEN_EVENT_POINTER: + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &val); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_BUTTONS of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if ((mouse_buttons & SCREEN_LEFT_MOUSE_BUTTON) == 0) { + if ((val & SCREEN_LEFT_MOUSE_BUTTON) == SCREEN_LEFT_MOUSE_BUTTON) { + mouseButtons.left = true; + } + } else { + if ((val & SCREEN_LEFT_MOUSE_BUTTON) == 0) { + mouseButtons.left = false; + } + } + if ((mouse_buttons & SCREEN_RIGHT_MOUSE_BUTTON) == 0) { + if ((val & SCREEN_RIGHT_MOUSE_BUTTON) == SCREEN_RIGHT_MOUSE_BUTTON) { + mouseButtons.right = true; + } + } else { + if ((val & SCREEN_RIGHT_MOUSE_BUTTON) == 0) { + mouseButtons.right = false; + } + } + if ((mouse_buttons & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) { + if ((val & SCREEN_MIDDLE_MOUSE_BUTTON) == SCREEN_MIDDLE_MOUSE_BUTTON) { + mouseButtons.middle = true; + } + } else { + if ((val & SCREEN_MIDDLE_MOUSE_BUTTON) == 0) { + mouseButtons.middle = false; + } + } + mouse_buttons = val; + + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_MOUSE_WHEEL, &val); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_MOUSE_WHEEL of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if (val != 0) { + camera.translate(glm::vec3(0.0f, 0.0f, (float)val * 0.005f)); + viewUpdated = true; + } + + rc = screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_POSITION, pos); + if (rc) { + printf("Cannot get SCREEN_PROPERTY_DISPLACEMENT of the event! (%s)\n", strerror(errno)); + fflush(stdout); + quit = true; + break; + } + if ((pos[0] != 0) || (pos[1] != 0)) { + handleMouseMove(pos[0], pos[1]); + } + updateOverlay(); + break; + } + } +} + +void VulkanExampleBase::setupWindow() +{ + const char *idstr = name.c_str(); + int size[2]; + int usage = SCREEN_USAGE_VULKAN; + int rc; + + if (screen_pipeline_set) { + usage |= SCREEN_USAGE_OVERLAY; + } + + rc = screen_create_context(&screen_context, 0); + if (rc) { + printf("Cannot create QNX Screen context!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + rc = screen_create_window(&screen_window, screen_context); + if (rc) { + printf("Cannot create QNX Screen window!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + rc = screen_create_event(&screen_event); + if (rc) { + printf("Cannot create QNX Screen event!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + + /* Set window caption */ + screen_set_window_property_cv(screen_window, SCREEN_PROPERTY_ID_STRING, strlen(idstr), idstr); + + /* Setup VULKAN usage flags */ + rc = screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_USAGE, &usage); + if (rc) { + printf("Cannot set SCREEN_USAGE_VULKAN flag!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + + if ((width == 0) || (height == 0) || (settings.fullscreen) || use_window_size) { + rc = screen_get_window_property_iv(screen_window, SCREEN_PROPERTY_SIZE, size); + if (rc) { + printf("Cannot obtain current window size!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + width = size[0]; + height = size[1]; + } else { + size[0] = width; + size[1] = height; + rc = screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_SIZE, size); + if (rc) { + printf("Cannot set window size!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + } + + if (screen_pos_set) { + rc = screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_POSITION, screen_pos); + if (rc) { + printf("Cannot set window position!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + } + + if (screen_pipeline_set) { + rc = screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_PIPELINE, &screen_pipeline); + if (rc) { + printf("Cannot set pipeline id!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + } + + if (screen_zorder_set) { + rc = screen_set_window_property_iv(screen_window, SCREEN_PROPERTY_ZORDER, &screen_zorder); + if (rc) { + printf("Cannot set z-order of the window!\n"); + fflush(stdout); + exit(EXIT_FAILURE); + } + } +} #else void VulkanExampleBase::setupWindow() { @@ -2949,6 +3240,8 @@ void VulkanExampleBase::initSwapchain() swapChain.initSurface(connection, window); #elif (defined(_DIRECT2DISPLAY) || defined(VK_USE_PLATFORM_HEADLESS_EXT)) swapChain.initSurface(width, height); +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + swapChain.initSurface(screen_context, screen_window); #endif } diff --git a/base/vulkanexamplebase.h b/base/vulkanexamplebase.h index 19fa6569..71f15a83 100644 --- a/base/vulkanexamplebase.h +++ b/base/vulkanexamplebase.h @@ -269,6 +269,11 @@ public: xcb_intern_atom_reply_t *atom_wm_delete_window; #elif defined(VK_USE_PLATFORM_HEADLESS_EXT) bool quit = false; +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + screen_context_t screen_context = nullptr; + screen_window_t screen_window = nullptr; + screen_event_t screen_event = nullptr; + bool quit = false; #endif VulkanExampleBase(bool enableValidation = false); @@ -342,6 +347,9 @@ public: xcb_window_t setupWindow(); void initxcbConnection(); void handleEvent(const xcb_generic_event_t *event); +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) + void setupWindow(); + void handleEvent(); #else void setupWindow(); #endif @@ -532,4 +540,19 @@ int main(const int argc, const char *argv[]) \ #else #define VULKAN_EXAMPLE_MAIN() #endif + +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) +#define VULKAN_EXAMPLE_MAIN() \ +VulkanExample *vulkanExample; \ +int main(const int argc, const char *argv[]) \ +{ \ + for (int i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; \ + vulkanExample = new VulkanExample(); \ + vulkanExample->initVulkan(); \ + vulkanExample->setupWindow(); \ + vulkanExample->prepare(); \ + vulkanExample->renderLoop(); \ + delete(vulkanExample); \ + return 0; \ +} #endif diff --git a/examples/triangle/triangle.cpp b/examples/triangle/triangle.cpp index 4e37d517..7ffb3a97 100644 --- a/examples/triangle/triangle.cpp +++ b/examples/triangle/triangle.cpp @@ -1170,4 +1170,6 @@ int main(const int argc, const char *argv[]) } return 0; } +#elif defined(VK_USE_PLATFORM_SCREEN_QNX) +VULKAN_EXAMPLE_MAIN() #endif