Add basic QNX support.

This commit is contained in:
Mike Gorchak 2023-09-01 11:12:08 -04:00
parent e38d201415
commit 8458f21123
6 changed files with 354 additions and 0 deletions

View file

@ -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) {

View file

@ -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);

View file

@ -157,4 +157,28 @@
#define KEY_N 0x39
#define KEY_O 0x20
#define KEY_T 0x1C
#elif defined(VK_USE_PLATFORM_SCREEN_QNX)
#include <sys/keycodes.h>
#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

View file

@ -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
}

View file

@ -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

View file

@ -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