mirror of
https://github.com/ocornut/imgui.git
synced 2026-08-21 06:41:09 +00:00
Backends+Examples: QNX Screen: added initial QNX support to backends and examples. (#9492)
This commit is contained in:
763
backends/imgui_impl_qnx.cpp
Normal file
763
backends/imgui_impl_qnx.cpp
Normal file
@@ -0,0 +1,763 @@
|
||||
// dear imgui: Platform Backend for QNX Screen
|
||||
// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan).
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols.
|
||||
// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels.
|
||||
// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button.
|
||||
// [X] Platform: Focus and window-size updates.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors).
|
||||
// [ ] Platform: Multi-viewport support.
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2026-07-30: Renamed backend from imgui_impl_screen to imgui_impl_qnx and embedded a compact keysym table.
|
||||
// 2026-07-29: Reworked keyboard handling from the proven qterm Screen path: authoritative modifier masks,
|
||||
// complete keypad/Hyper mapping, and QNX/X11 keysym-to-Unicode conversion.
|
||||
// 2026-07-29: Fixed keyboard handling: use KEY_CAP for physical keys, SYM for text, and honor Screen validity flags.
|
||||
// 2026-07-28: Initial QNX Screen backend.
|
||||
|
||||
#include "imgui.h"
|
||||
#ifndef IMGUI_DISABLE
|
||||
#include "imgui_impl_qnx.h"
|
||||
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <time.h>
|
||||
|
||||
static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym);
|
||||
|
||||
struct ImGui_ImplQNX_Data
|
||||
{
|
||||
screen_context_t Context;
|
||||
screen_window_t Window;
|
||||
uint64_t TimeNanoseconds;
|
||||
int MouseButtons;
|
||||
int ActiveTouchId;
|
||||
bool LeftSuper;
|
||||
bool RightSuper;
|
||||
|
||||
ImGui_ImplQNX_Data()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
ActiveTouchId = -1;
|
||||
}
|
||||
};
|
||||
|
||||
static ImGui_ImplQNX_Data* ImGui_ImplQNX_GetBackendData()
|
||||
{
|
||||
return ImGui::GetCurrentContext() != nullptr ? (ImGui_ImplQNX_Data*)ImGui::GetIO().BackendPlatformUserData : nullptr;
|
||||
}
|
||||
|
||||
static uint64_t ImGui_ImplQNX_GetTimeNanoseconds()
|
||||
{
|
||||
struct timespec timestamp = {};
|
||||
if (clock_gettime(CLOCK_MONOTONIC, ×tamp) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return (uint64_t)timestamp.tv_sec * UINT64_C(1000000000) + (uint64_t)timestamp.tv_nsec;
|
||||
}
|
||||
|
||||
static ImGuiKey ImGui_ImplQNX_KeyCodeToImGuiKey(int key_code)
|
||||
{
|
||||
switch (key_code)
|
||||
{
|
||||
case KEYCODE_TAB: return ImGuiKey_Tab;
|
||||
case KEYCODE_LEFT: return ImGuiKey_LeftArrow;
|
||||
case KEYCODE_RIGHT: return ImGuiKey_RightArrow;
|
||||
case KEYCODE_UP: return ImGuiKey_UpArrow;
|
||||
case KEYCODE_DOWN: return ImGuiKey_DownArrow;
|
||||
case KEYCODE_PG_UP: return ImGuiKey_PageUp;
|
||||
case KEYCODE_PG_DOWN: return ImGuiKey_PageDown;
|
||||
case KEYCODE_HOME: return ImGuiKey_Home;
|
||||
case KEYCODE_END: return ImGuiKey_End;
|
||||
case KEYCODE_INSERT: return ImGuiKey_Insert;
|
||||
case KEYCODE_DELETE: return ImGuiKey_Delete;
|
||||
case KEYCODE_BACKSPACE: return ImGuiKey_Backspace;
|
||||
case KEYCODE_SPACE: return ImGuiKey_Space;
|
||||
case KEYCODE_RETURN: return ImGuiKey_Enter;
|
||||
case KEYCODE_ESCAPE: return ImGuiKey_Escape;
|
||||
case KEYCODE_APOSTROPHE: return ImGuiKey_Apostrophe;
|
||||
case KEYCODE_COMMA: return ImGuiKey_Comma;
|
||||
case KEYCODE_MINUS: return ImGuiKey_Minus;
|
||||
case KEYCODE_PERIOD: return ImGuiKey_Period;
|
||||
case KEYCODE_SLASH: return ImGuiKey_Slash;
|
||||
case KEYCODE_SEMICOLON: return ImGuiKey_Semicolon;
|
||||
case KEYCODE_EQUAL: return ImGuiKey_Equal;
|
||||
case KEYCODE_LEFT_BRACKET: return ImGuiKey_LeftBracket;
|
||||
case KEYCODE_BACK_SLASH: return ImGuiKey_Backslash;
|
||||
case KEYCODE_RIGHT_BRACKET: return ImGuiKey_RightBracket;
|
||||
case KEYCODE_GRAVE: return ImGuiKey_GraveAccent;
|
||||
case KEYCODE_CAPS_LOCK: return ImGuiKey_CapsLock;
|
||||
case KEYCODE_SCROLL_LOCK: return ImGuiKey_ScrollLock;
|
||||
case KEYCODE_NUM_LOCK: return ImGuiKey_NumLock;
|
||||
case KEYCODE_PRINT: return ImGuiKey_PrintScreen;
|
||||
case KEYCODE_PAUSE: return ImGuiKey_Pause;
|
||||
case KEYCODE_KP_DIVIDE: return ImGuiKey_KeypadDivide;
|
||||
case KEYCODE_KP_MULTIPLY: return ImGuiKey_KeypadMultiply;
|
||||
case KEYCODE_KP_MINUS: return ImGuiKey_KeypadSubtract;
|
||||
case KEYCODE_KP_PLUS: return ImGuiKey_KeypadAdd;
|
||||
case KEYCODE_KP_ENTER: return ImGuiKey_KeypadEnter;
|
||||
// QNX reports keypad digits by their navigation key-cap names.
|
||||
case KEYCODE_KP_INSERT: return ImGuiKey_Keypad0;
|
||||
case KEYCODE_KP_END: return ImGuiKey_Keypad1;
|
||||
case KEYCODE_KP_DOWN: return ImGuiKey_Keypad2;
|
||||
case KEYCODE_KP_PG_DOWN: return ImGuiKey_Keypad3;
|
||||
case KEYCODE_KP_LEFT: return ImGuiKey_Keypad4;
|
||||
case KEYCODE_KP_FIVE: return ImGuiKey_Keypad5;
|
||||
case KEYCODE_KP_RIGHT: return ImGuiKey_Keypad6;
|
||||
case KEYCODE_KP_HOME: return ImGuiKey_Keypad7;
|
||||
case KEYCODE_KP_UP: return ImGuiKey_Keypad8;
|
||||
case KEYCODE_KP_PG_UP: return ImGuiKey_Keypad9;
|
||||
case KEYCODE_KP_DELETE: return ImGuiKey_KeypadDecimal;
|
||||
case KEYCODE_LEFT_CTRL: return ImGuiKey_LeftCtrl;
|
||||
case KEYCODE_LEFT_SHIFT: return ImGuiKey_LeftShift;
|
||||
case KEYCODE_LEFT_ALT: return ImGuiKey_LeftAlt;
|
||||
case KEYCODE_RIGHT_CTRL: return ImGuiKey_RightCtrl;
|
||||
case KEYCODE_RIGHT_SHIFT: return ImGuiKey_RightShift;
|
||||
case KEYCODE_RIGHT_ALT: return ImGuiKey_RightAlt;
|
||||
case KEYCODE_LEFT_HYPER: return ImGuiKey_LeftSuper;
|
||||
case KEYCODE_RIGHT_HYPER: return ImGuiKey_RightSuper;
|
||||
case KEYCODE_MENU: return ImGuiKey_Menu;
|
||||
case KEYCODE_ZERO: return ImGuiKey_0;
|
||||
case KEYCODE_ONE: return ImGuiKey_1;
|
||||
case KEYCODE_TWO: return ImGuiKey_2;
|
||||
case KEYCODE_THREE: return ImGuiKey_3;
|
||||
case KEYCODE_FOUR: return ImGuiKey_4;
|
||||
case KEYCODE_FIVE: return ImGuiKey_5;
|
||||
case KEYCODE_SIX: return ImGuiKey_6;
|
||||
case KEYCODE_SEVEN: return ImGuiKey_7;
|
||||
case KEYCODE_EIGHT: return ImGuiKey_8;
|
||||
case KEYCODE_NINE: return ImGuiKey_9;
|
||||
case KEYCODE_A: return ImGuiKey_A;
|
||||
case KEYCODE_B: return ImGuiKey_B;
|
||||
case KEYCODE_C: return ImGuiKey_C;
|
||||
case KEYCODE_D: return ImGuiKey_D;
|
||||
case KEYCODE_E: return ImGuiKey_E;
|
||||
case KEYCODE_F: return ImGuiKey_F;
|
||||
case KEYCODE_G: return ImGuiKey_G;
|
||||
case KEYCODE_H: return ImGuiKey_H;
|
||||
case KEYCODE_I: return ImGuiKey_I;
|
||||
case KEYCODE_J: return ImGuiKey_J;
|
||||
case KEYCODE_K: return ImGuiKey_K;
|
||||
case KEYCODE_L: return ImGuiKey_L;
|
||||
case KEYCODE_M: return ImGuiKey_M;
|
||||
case KEYCODE_N: return ImGuiKey_N;
|
||||
case KEYCODE_O: return ImGuiKey_O;
|
||||
case KEYCODE_P: return ImGuiKey_P;
|
||||
case KEYCODE_Q: return ImGuiKey_Q;
|
||||
case KEYCODE_R: return ImGuiKey_R;
|
||||
case KEYCODE_S: return ImGuiKey_S;
|
||||
case KEYCODE_T: return ImGuiKey_T;
|
||||
case KEYCODE_U: return ImGuiKey_U;
|
||||
case KEYCODE_V: return ImGuiKey_V;
|
||||
case KEYCODE_W: return ImGuiKey_W;
|
||||
case KEYCODE_X: return ImGuiKey_X;
|
||||
case KEYCODE_Y: return ImGuiKey_Y;
|
||||
case KEYCODE_Z: return ImGuiKey_Z;
|
||||
case KEYCODE_F1: return ImGuiKey_F1;
|
||||
case KEYCODE_F2: return ImGuiKey_F2;
|
||||
case KEYCODE_F3: return ImGuiKey_F3;
|
||||
case KEYCODE_F4: return ImGuiKey_F4;
|
||||
case KEYCODE_F5: return ImGuiKey_F5;
|
||||
case KEYCODE_F6: return ImGuiKey_F6;
|
||||
case KEYCODE_F7: return ImGuiKey_F7;
|
||||
case KEYCODE_F8: return ImGuiKey_F8;
|
||||
case KEYCODE_F9: return ImGuiKey_F9;
|
||||
case KEYCODE_F10: return ImGuiKey_F10;
|
||||
case KEYCODE_F11: return ImGuiKey_F11;
|
||||
case KEYCODE_F12: return ImGuiKey_F12;
|
||||
default: return ImGuiKey_None;
|
||||
}
|
||||
}
|
||||
|
||||
static void ImGui_ImplQNX_UpdateKeyModifiers(ImGuiIO& io, ImGui_ImplQNX_Data* bd, int modifiers, ImGuiKey key, bool down)
|
||||
{
|
||||
// SCREEN_PROPERTY_MODIFIERS is the authoritative state for Shift/Ctrl/Alt.
|
||||
// Tracking those keys locally loses sticky modifiers and can become stale if
|
||||
// a key transition is consumed elsewhere. qterm uses this same Screen state.
|
||||
if (key == ImGuiKey_LeftSuper)
|
||||
{
|
||||
bd->LeftSuper = down;
|
||||
}
|
||||
else if (key == ImGuiKey_RightSuper)
|
||||
{
|
||||
bd->RightSuper = down;
|
||||
}
|
||||
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, (modifiers & KEYMOD_CTRL) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, (modifiers & KEYMOD_SHIFT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, (modifiers & KEYMOD_ALT) != 0);
|
||||
io.AddKeyEvent(ImGuiMod_Super, bd->LeftSuper || bd->RightSuper);
|
||||
}
|
||||
|
||||
static void ImGui_ImplQNX_ClearModifierState(ImGuiIO& io, ImGui_ImplQNX_Data* bd)
|
||||
{
|
||||
bd->LeftSuper = false;
|
||||
bd->RightSuper = false;
|
||||
io.AddKeyEvent(ImGuiMod_Ctrl, false);
|
||||
io.AddKeyEvent(ImGuiMod_Shift, false);
|
||||
io.AddKeyEvent(ImGuiMod_Alt, false);
|
||||
io.AddKeyEvent(ImGuiMod_Super, false);
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_IsTextCodePoint(unsigned int code_point)
|
||||
{
|
||||
// At this point the QNX keysym has already been converted to Unicode.
|
||||
// Do not reject Unicode private-use characters: a user keymap may emit one.
|
||||
const bool surrogate = code_point >= 0xd800u && code_point <= 0xdfffu;
|
||||
const bool control = code_point < 0x20u || (code_point >= 0x7fu && code_point <= 0x9fu);
|
||||
return code_point <= IM_UNICODE_CODEPOINT_MAX && !surrogate && !control;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessKeyboardEvent(ImGui_ImplQNX_Data* bd, screen_event_t event)
|
||||
{
|
||||
int flags = 0;
|
||||
int modifiers = 0;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &flags) != 0 ||
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_MODIFIERS, &modifiers) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// KEY_CAP is the unmodified key identity used for ImGuiKey events. SYM is
|
||||
// the layout/modifier-translated QNX keysym used for text input.
|
||||
int key_cap = 0;
|
||||
int key_sym = 0;
|
||||
int scan_code = 0;
|
||||
const bool cap_valid = (flags & SCREEN_FLAG_CAP_VALID) != 0;
|
||||
const bool sym_valid = (flags & SCREEN_FLAG_SYM_VALID) != 0;
|
||||
const bool scan_valid = (flags & SCREEN_FLAG_SCAN_VALID) != 0;
|
||||
const bool down = (flags & (SCREEN_FLAG_KEY_DOWN | SCREEN_FLAG_KEY_REPEAT)) != 0;
|
||||
|
||||
if (cap_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &key_cap) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (sym_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &key_sym) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (scan_valid && screen_get_event_property_iv(event, SCREEN_PROPERTY_SCAN, &scan_code) != 0)
|
||||
{
|
||||
scan_code = 0;
|
||||
}
|
||||
|
||||
const ImGuiKey key = cap_valid ? ImGui_ImplQNX_KeyCodeToImGuiKey(key_cap) : ImGuiKey_None;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Modifier events must precede the ordinary key event in Dear ImGui's queue.
|
||||
// Unlike qterm, we still submit the individual modifier key because ImGui
|
||||
// exposes Left/Right Ctrl, Shift, Alt and Super as named keys.
|
||||
ImGui_ImplQNX_UpdateKeyModifiers(io, bd, modifiers, key, down);
|
||||
|
||||
if (key != ImGuiKey_None)
|
||||
{
|
||||
io.AddKeyEvent(key, down);
|
||||
io.SetKeyEventNativeData(key, key_cap, scan_code);
|
||||
}
|
||||
|
||||
bool text_added = false;
|
||||
if (down && sym_valid && key_sym >= 0)
|
||||
{
|
||||
const unsigned int keysym = (unsigned int)key_sym;
|
||||
// QNX special/function symbols begin at KEYCODE_PC_KEYS. Printable
|
||||
// symbols below that boundary use X11 keysym encoding. Also accept the
|
||||
// standard directly encoded UCS keysym form (0x01000000 | codepoint).
|
||||
if (keysym < (unsigned int)KEYCODE_PC_KEYS || (keysym & 0xff000000u) == 0x01000000u)
|
||||
{
|
||||
const unsigned int code_point = ImGui_ImplQNX_KeySymToUnicode(keysym);
|
||||
if (ImGui_ImplQNX_IsTextCodePoint(code_point))
|
||||
{
|
||||
io.AddInputCharacter(code_point);
|
||||
text_added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return key != ImGuiKey_None || text_added || cap_valid || sym_valid;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessPointerEvent(ImGui_ImplQNX_Data* bd, screen_event_t event)
|
||||
{
|
||||
int position[2] = {};
|
||||
int buttons = 0;
|
||||
int wheel_vertical = 0;
|
||||
int wheel_horizontal = 0;
|
||||
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 &&
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttons) != 0)
|
||||
{
|
||||
buttons = bd->MouseButtons;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_Mouse);
|
||||
io.AddMousePosEvent((float)position[0], (float)position[1]);
|
||||
|
||||
const int changed_buttons = buttons ^ bd->MouseButtons;
|
||||
if ((changed_buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(0, (buttons & SCREEN_LEFT_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
if ((changed_buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(1, (buttons & SCREEN_RIGHT_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
if ((changed_buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0)
|
||||
{
|
||||
io.AddMouseButtonEvent(2, (buttons & SCREEN_MIDDLE_MOUSE_BUTTON) != 0);
|
||||
}
|
||||
bd->MouseButtons = buttons;
|
||||
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheel_vertical) != 0)
|
||||
{
|
||||
wheel_vertical = 0;
|
||||
}
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_HORIZONTAL_WHEEL, &wheel_horizontal) != 0)
|
||||
{
|
||||
wheel_horizontal = 0;
|
||||
}
|
||||
if (wheel_vertical != 0 || wheel_horizontal != 0)
|
||||
{
|
||||
// Screen: up/left are negative. Dear ImGui: up/left are positive.
|
||||
io.AddMouseWheelEvent((float)-wheel_horizontal, (float)-wheel_vertical);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ImGui_ImplQNX_ProcessTouchEvent(ImGui_ImplQNX_Data* bd, screen_event_t event, int event_type)
|
||||
{
|
||||
int touch_id = -1;
|
||||
int position[2] = {};
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touch_id) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool is_release = event_type == SCREEN_EVENT_MTOUCH_RELEASE;
|
||||
if (bd->ActiveTouchId != -1 && touch_id != bd->ActiveTouchId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddMouseSourceEvent(ImGuiMouseSource_TouchScreen);
|
||||
|
||||
if (!is_release)
|
||||
{
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, position) != 0 &&
|
||||
screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, position) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
io.AddMousePosEvent((float)position[0], (float)position[1]);
|
||||
}
|
||||
|
||||
if (event_type == SCREEN_EVENT_MTOUCH_TOUCH)
|
||||
{
|
||||
bd->ActiveTouchId = touch_id;
|
||||
io.AddMouseButtonEvent(0, true);
|
||||
}
|
||||
else if (is_release)
|
||||
{
|
||||
io.AddMouseButtonEvent(0, false);
|
||||
io.AddMousePosEvent(-FLT_MAX, -FLT_MAX);
|
||||
bd->ActiveTouchId = -1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGui_ImplQNX_ProcessEvent(screen_event_t event)
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?");
|
||||
if (bd == nullptr || event == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int event_type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &event_type) != 0 || event_type == SCREEN_EVENT_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (event_type)
|
||||
{
|
||||
case SCREEN_EVENT_KEYBOARD:
|
||||
return ImGui_ImplQNX_ProcessKeyboardEvent(bd, event);
|
||||
case SCREEN_EVENT_POINTER:
|
||||
return ImGui_ImplQNX_ProcessPointerEvent(bd, event);
|
||||
case SCREEN_EVENT_MTOUCH_TOUCH:
|
||||
case SCREEN_EVENT_MTOUCH_MOVE:
|
||||
case SCREEN_EVENT_MTOUCH_RELEASE:
|
||||
return ImGui_ImplQNX_ProcessTouchEvent(bd, event, event_type);
|
||||
case SCREEN_EVENT_PROPERTY:
|
||||
{
|
||||
int property = 0;
|
||||
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_NAME, &property) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (property == SCREEN_PROPERTY_FOCUS)
|
||||
{
|
||||
int focused = 0;
|
||||
if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_FOCUS, &focused) == 0)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(focused != 0);
|
||||
if (focused == 0)
|
||||
{
|
||||
ImGui_ImplQNX_ClearModifierState(io, bd);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (property == SCREEN_PROPERTY_SIZE || property == SCREEN_PROPERTY_BUFFER_SIZE || property == SCREEN_PROPERTY_VISIBLE)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case SCREEN_EVENT_CLOSE:
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.AddFocusEvent(false);
|
||||
ImGui_ImplQNX_ClearModifierState(io, bd);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IMGUI_CHECKVERSION();
|
||||
IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!");
|
||||
IM_ASSERT(context != nullptr && window != nullptr);
|
||||
if (context == nullptr || window == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ImGui_ImplQNX_Data* bd = IM_NEW(ImGui_ImplQNX_Data)();
|
||||
io.BackendPlatformUserData = (void*)bd;
|
||||
io.BackendPlatformName = "imgui_impl_qnx";
|
||||
|
||||
bd->Context = context;
|
||||
bd->Window = window;
|
||||
bd->TimeNanoseconds = ImGui_ImplQNX_GetTimeNanoseconds();
|
||||
|
||||
int focused = 0;
|
||||
if (screen_get_window_property_iv(window, SCREEN_PROPERTY_FOCUS, &focused) == 0)
|
||||
{
|
||||
io.AddFocusEvent(focused != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplQNX_Shutdown()
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
|
||||
if (bd == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = nullptr;
|
||||
io.BackendPlatformUserData = nullptr;
|
||||
IM_DELETE(bd);
|
||||
}
|
||||
|
||||
void ImGui_ImplQNX_NewFrame()
|
||||
{
|
||||
ImGui_ImplQNX_Data* bd = ImGui_ImplQNX_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplQNX_Init()?");
|
||||
if (bd == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
int size[2] = {};
|
||||
if (screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_BUFFER_SIZE, size) != 0 ||
|
||||
size[0] <= 0 || size[1] <= 0)
|
||||
{
|
||||
size[0] = 0;
|
||||
size[1] = 0;
|
||||
(void)screen_get_window_property_iv(bd->Window, SCREEN_PROPERTY_SIZE, size);
|
||||
}
|
||||
if (size[0] > 0 && size[1] > 0)
|
||||
{
|
||||
io.DisplaySize = ImVec2((float)size[0], (float)size[1]);
|
||||
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
const uint64_t current_time = ImGui_ImplQNX_GetTimeNanoseconds();
|
||||
if (current_time > bd->TimeNanoseconds && bd->TimeNanoseconds != 0)
|
||||
{
|
||||
io.DeltaTime = (float)((double)(current_time - bd->TimeNanoseconds) / 1000000000.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
}
|
||||
bd->TimeNanoseconds = current_time;
|
||||
}
|
||||
|
||||
// Generated by Markus Kuhn's public-domain unicode/convmap.pl from X11 keysymdef.h and UnicodeData.
|
||||
// Original source: https://www.cl.cam.ac.uk/~mgk25/ucs/keysym2ucs.c
|
||||
// The table must remain sorted by keysym for the binary search below.
|
||||
struct ImGui_ImplQNX_KeySymPair
|
||||
{
|
||||
uint16_t KeySym;
|
||||
uint16_t Unicode;
|
||||
};
|
||||
|
||||
static const ImGui_ImplQNX_KeySymPair ImGui_ImplQNX_KeySymTable[] =
|
||||
{
|
||||
{ 0x01a1, 0x0104 }, { 0x01a2, 0x02d8 }, { 0x01a3, 0x0141 }, { 0x01a5, 0x013d },
|
||||
{ 0x01a6, 0x015a }, { 0x01a9, 0x0160 }, { 0x01aa, 0x015e }, { 0x01ab, 0x0164 },
|
||||
{ 0x01ac, 0x0179 }, { 0x01ae, 0x017d }, { 0x01af, 0x017b }, { 0x01b1, 0x0105 },
|
||||
{ 0x01b2, 0x02db }, { 0x01b3, 0x0142 }, { 0x01b5, 0x013e }, { 0x01b6, 0x015b },
|
||||
{ 0x01b7, 0x02c7 }, { 0x01b9, 0x0161 }, { 0x01ba, 0x015f }, { 0x01bb, 0x0165 },
|
||||
{ 0x01bc, 0x017a }, { 0x01bd, 0x02dd }, { 0x01be, 0x017e }, { 0x01bf, 0x017c },
|
||||
{ 0x01c0, 0x0154 }, { 0x01c3, 0x0102 }, { 0x01c5, 0x0139 }, { 0x01c6, 0x0106 },
|
||||
{ 0x01c8, 0x010c }, { 0x01ca, 0x0118 }, { 0x01cc, 0x011a }, { 0x01cf, 0x010e },
|
||||
{ 0x01d0, 0x0110 }, { 0x01d1, 0x0143 }, { 0x01d2, 0x0147 }, { 0x01d5, 0x0150 },
|
||||
{ 0x01d8, 0x0158 }, { 0x01d9, 0x016e }, { 0x01db, 0x0170 }, { 0x01de, 0x0162 },
|
||||
{ 0x01e0, 0x0155 }, { 0x01e3, 0x0103 }, { 0x01e5, 0x013a }, { 0x01e6, 0x0107 },
|
||||
{ 0x01e8, 0x010d }, { 0x01ea, 0x0119 }, { 0x01ec, 0x011b }, { 0x01ef, 0x010f },
|
||||
{ 0x01f0, 0x0111 }, { 0x01f1, 0x0144 }, { 0x01f2, 0x0148 }, { 0x01f5, 0x0151 },
|
||||
{ 0x01f8, 0x0159 }, { 0x01f9, 0x016f }, { 0x01fb, 0x0171 }, { 0x01fe, 0x0163 },
|
||||
{ 0x01ff, 0x02d9 }, { 0x02a1, 0x0126 }, { 0x02a6, 0x0124 }, { 0x02a9, 0x0130 },
|
||||
{ 0x02ab, 0x011e }, { 0x02ac, 0x0134 }, { 0x02b1, 0x0127 }, { 0x02b6, 0x0125 },
|
||||
{ 0x02b9, 0x0131 }, { 0x02bb, 0x011f }, { 0x02bc, 0x0135 }, { 0x02c5, 0x010a },
|
||||
{ 0x02c6, 0x0108 }, { 0x02d5, 0x0120 }, { 0x02d8, 0x011c }, { 0x02dd, 0x016c },
|
||||
{ 0x02de, 0x015c }, { 0x02e5, 0x010b }, { 0x02e6, 0x0109 }, { 0x02f5, 0x0121 },
|
||||
{ 0x02f8, 0x011d }, { 0x02fd, 0x016d }, { 0x02fe, 0x015d }, { 0x03a2, 0x0138 },
|
||||
{ 0x03a3, 0x0156 }, { 0x03a5, 0x0128 }, { 0x03a6, 0x013b }, { 0x03aa, 0x0112 },
|
||||
{ 0x03ab, 0x0122 }, { 0x03ac, 0x0166 }, { 0x03b3, 0x0157 }, { 0x03b5, 0x0129 },
|
||||
{ 0x03b6, 0x013c }, { 0x03ba, 0x0113 }, { 0x03bb, 0x0123 }, { 0x03bc, 0x0167 },
|
||||
{ 0x03bd, 0x014a }, { 0x03bf, 0x014b }, { 0x03c0, 0x0100 }, { 0x03c7, 0x012e },
|
||||
{ 0x03cc, 0x0116 }, { 0x03cf, 0x012a }, { 0x03d1, 0x0145 }, { 0x03d2, 0x014c },
|
||||
{ 0x03d3, 0x0136 }, { 0x03d9, 0x0172 }, { 0x03dd, 0x0168 }, { 0x03de, 0x016a },
|
||||
{ 0x03e0, 0x0101 }, { 0x03e7, 0x012f }, { 0x03ec, 0x0117 }, { 0x03ef, 0x012b },
|
||||
{ 0x03f1, 0x0146 }, { 0x03f2, 0x014d }, { 0x03f3, 0x0137 }, { 0x03f9, 0x0173 },
|
||||
{ 0x03fd, 0x0169 }, { 0x03fe, 0x016b }, { 0x047e, 0x203e }, { 0x04a1, 0x3002 },
|
||||
{ 0x04a2, 0x300c }, { 0x04a3, 0x300d }, { 0x04a4, 0x3001 }, { 0x04a5, 0x30fb },
|
||||
{ 0x04a6, 0x30f2 }, { 0x04a7, 0x30a1 }, { 0x04a8, 0x30a3 }, { 0x04a9, 0x30a5 },
|
||||
{ 0x04aa, 0x30a7 }, { 0x04ab, 0x30a9 }, { 0x04ac, 0x30e3 }, { 0x04ad, 0x30e5 },
|
||||
{ 0x04ae, 0x30e7 }, { 0x04af, 0x30c3 }, { 0x04b0, 0x30fc }, { 0x04b1, 0x30a2 },
|
||||
{ 0x04b2, 0x30a4 }, { 0x04b3, 0x30a6 }, { 0x04b4, 0x30a8 }, { 0x04b5, 0x30aa },
|
||||
{ 0x04b6, 0x30ab }, { 0x04b7, 0x30ad }, { 0x04b8, 0x30af }, { 0x04b9, 0x30b1 },
|
||||
{ 0x04ba, 0x30b3 }, { 0x04bb, 0x30b5 }, { 0x04bc, 0x30b7 }, { 0x04bd, 0x30b9 },
|
||||
{ 0x04be, 0x30bb }, { 0x04bf, 0x30bd }, { 0x04c0, 0x30bf }, { 0x04c1, 0x30c1 },
|
||||
{ 0x04c2, 0x30c4 }, { 0x04c3, 0x30c6 }, { 0x04c4, 0x30c8 }, { 0x04c5, 0x30ca },
|
||||
{ 0x04c6, 0x30cb }, { 0x04c7, 0x30cc }, { 0x04c8, 0x30cd }, { 0x04c9, 0x30ce },
|
||||
{ 0x04ca, 0x30cf }, { 0x04cb, 0x30d2 }, { 0x04cc, 0x30d5 }, { 0x04cd, 0x30d8 },
|
||||
{ 0x04ce, 0x30db }, { 0x04cf, 0x30de }, { 0x04d0, 0x30df }, { 0x04d1, 0x30e0 },
|
||||
{ 0x04d2, 0x30e1 }, { 0x04d3, 0x30e2 }, { 0x04d4, 0x30e4 }, { 0x04d5, 0x30e6 },
|
||||
{ 0x04d6, 0x30e8 }, { 0x04d7, 0x30e9 }, { 0x04d8, 0x30ea }, { 0x04d9, 0x30eb },
|
||||
{ 0x04da, 0x30ec }, { 0x04db, 0x30ed }, { 0x04dc, 0x30ef }, { 0x04dd, 0x30f3 },
|
||||
{ 0x04de, 0x309b }, { 0x04df, 0x309c }, { 0x05ac, 0x060c }, { 0x05bb, 0x061b },
|
||||
{ 0x05bf, 0x061f }, { 0x05c1, 0x0621 }, { 0x05c2, 0x0622 }, { 0x05c3, 0x0623 },
|
||||
{ 0x05c4, 0x0624 }, { 0x05c5, 0x0625 }, { 0x05c6, 0x0626 }, { 0x05c7, 0x0627 },
|
||||
{ 0x05c8, 0x0628 }, { 0x05c9, 0x0629 }, { 0x05ca, 0x062a }, { 0x05cb, 0x062b },
|
||||
{ 0x05cc, 0x062c }, { 0x05cd, 0x062d }, { 0x05ce, 0x062e }, { 0x05cf, 0x062f },
|
||||
{ 0x05d0, 0x0630 }, { 0x05d1, 0x0631 }, { 0x05d2, 0x0632 }, { 0x05d3, 0x0633 },
|
||||
{ 0x05d4, 0x0634 }, { 0x05d5, 0x0635 }, { 0x05d6, 0x0636 }, { 0x05d7, 0x0637 },
|
||||
{ 0x05d8, 0x0638 }, { 0x05d9, 0x0639 }, { 0x05da, 0x063a }, { 0x05e0, 0x0640 },
|
||||
{ 0x05e1, 0x0641 }, { 0x05e2, 0x0642 }, { 0x05e3, 0x0643 }, { 0x05e4, 0x0644 },
|
||||
{ 0x05e5, 0x0645 }, { 0x05e6, 0x0646 }, { 0x05e7, 0x0647 }, { 0x05e8, 0x0648 },
|
||||
{ 0x05e9, 0x0649 }, { 0x05ea, 0x064a }, { 0x05eb, 0x064b }, { 0x05ec, 0x064c },
|
||||
{ 0x05ed, 0x064d }, { 0x05ee, 0x064e }, { 0x05ef, 0x064f }, { 0x05f0, 0x0650 },
|
||||
{ 0x05f1, 0x0651 }, { 0x05f2, 0x0652 }, { 0x06a1, 0x0452 }, { 0x06a2, 0x0453 },
|
||||
{ 0x06a3, 0x0451 }, { 0x06a4, 0x0454 }, { 0x06a5, 0x0455 }, { 0x06a6, 0x0456 },
|
||||
{ 0x06a7, 0x0457 }, { 0x06a8, 0x0458 }, { 0x06a9, 0x0459 }, { 0x06aa, 0x045a },
|
||||
{ 0x06ab, 0x045b }, { 0x06ac, 0x045c }, { 0x06ae, 0x045e }, { 0x06af, 0x045f },
|
||||
{ 0x06b0, 0x2116 }, { 0x06b1, 0x0402 }, { 0x06b2, 0x0403 }, { 0x06b3, 0x0401 },
|
||||
{ 0x06b4, 0x0404 }, { 0x06b5, 0x0405 }, { 0x06b6, 0x0406 }, { 0x06b7, 0x0407 },
|
||||
{ 0x06b8, 0x0408 }, { 0x06b9, 0x0409 }, { 0x06ba, 0x040a }, { 0x06bb, 0x040b },
|
||||
{ 0x06bc, 0x040c }, { 0x06be, 0x040e }, { 0x06bf, 0x040f }, { 0x06c0, 0x044e },
|
||||
{ 0x06c1, 0x0430 }, { 0x06c2, 0x0431 }, { 0x06c3, 0x0446 }, { 0x06c4, 0x0434 },
|
||||
{ 0x06c5, 0x0435 }, { 0x06c6, 0x0444 }, { 0x06c7, 0x0433 }, { 0x06c8, 0x0445 },
|
||||
{ 0x06c9, 0x0438 }, { 0x06ca, 0x0439 }, { 0x06cb, 0x043a }, { 0x06cc, 0x043b },
|
||||
{ 0x06cd, 0x043c }, { 0x06ce, 0x043d }, { 0x06cf, 0x043e }, { 0x06d0, 0x043f },
|
||||
{ 0x06d1, 0x044f }, { 0x06d2, 0x0440 }, { 0x06d3, 0x0441 }, { 0x06d4, 0x0442 },
|
||||
{ 0x06d5, 0x0443 }, { 0x06d6, 0x0436 }, { 0x06d7, 0x0432 }, { 0x06d8, 0x044c },
|
||||
{ 0x06d9, 0x044b }, { 0x06da, 0x0437 }, { 0x06db, 0x0448 }, { 0x06dc, 0x044d },
|
||||
{ 0x06dd, 0x0449 }, { 0x06de, 0x0447 }, { 0x06df, 0x044a }, { 0x06e0, 0x042e },
|
||||
{ 0x06e1, 0x0410 }, { 0x06e2, 0x0411 }, { 0x06e3, 0x0426 }, { 0x06e4, 0x0414 },
|
||||
{ 0x06e5, 0x0415 }, { 0x06e6, 0x0424 }, { 0x06e7, 0x0413 }, { 0x06e8, 0x0425 },
|
||||
{ 0x06e9, 0x0418 }, { 0x06ea, 0x0419 }, { 0x06eb, 0x041a }, { 0x06ec, 0x041b },
|
||||
{ 0x06ed, 0x041c }, { 0x06ee, 0x041d }, { 0x06ef, 0x041e }, { 0x06f0, 0x041f },
|
||||
{ 0x06f1, 0x042f }, { 0x06f2, 0x0420 }, { 0x06f3, 0x0421 }, { 0x06f4, 0x0422 },
|
||||
{ 0x06f5, 0x0423 }, { 0x06f6, 0x0416 }, { 0x06f7, 0x0412 }, { 0x06f8, 0x042c },
|
||||
{ 0x06f9, 0x042b }, { 0x06fa, 0x0417 }, { 0x06fb, 0x0428 }, { 0x06fc, 0x042d },
|
||||
{ 0x06fd, 0x0429 }, { 0x06fe, 0x0427 }, { 0x06ff, 0x042a }, { 0x07a1, 0x0386 },
|
||||
{ 0x07a2, 0x0388 }, { 0x07a3, 0x0389 }, { 0x07a4, 0x038a }, { 0x07a5, 0x03aa },
|
||||
{ 0x07a7, 0x038c }, { 0x07a8, 0x038e }, { 0x07a9, 0x03ab }, { 0x07ab, 0x038f },
|
||||
{ 0x07ae, 0x0385 }, { 0x07af, 0x2015 }, { 0x07b1, 0x03ac }, { 0x07b2, 0x03ad },
|
||||
{ 0x07b3, 0x03ae }, { 0x07b4, 0x03af }, { 0x07b5, 0x03ca }, { 0x07b6, 0x0390 },
|
||||
{ 0x07b7, 0x03cc }, { 0x07b8, 0x03cd }, { 0x07b9, 0x03cb }, { 0x07ba, 0x03b0 },
|
||||
{ 0x07bb, 0x03ce }, { 0x07c1, 0x0391 }, { 0x07c2, 0x0392 }, { 0x07c3, 0x0393 },
|
||||
{ 0x07c4, 0x0394 }, { 0x07c5, 0x0395 }, { 0x07c6, 0x0396 }, { 0x07c7, 0x0397 },
|
||||
{ 0x07c8, 0x0398 }, { 0x07c9, 0x0399 }, { 0x07ca, 0x039a }, { 0x07cb, 0x039b },
|
||||
{ 0x07cc, 0x039c }, { 0x07cd, 0x039d }, { 0x07ce, 0x039e }, { 0x07cf, 0x039f },
|
||||
{ 0x07d0, 0x03a0 }, { 0x07d1, 0x03a1 }, { 0x07d2, 0x03a3 }, { 0x07d4, 0x03a4 },
|
||||
{ 0x07d5, 0x03a5 }, { 0x07d6, 0x03a6 }, { 0x07d7, 0x03a7 }, { 0x07d8, 0x03a8 },
|
||||
{ 0x07d9, 0x03a9 }, { 0x07e1, 0x03b1 }, { 0x07e2, 0x03b2 }, { 0x07e3, 0x03b3 },
|
||||
{ 0x07e4, 0x03b4 }, { 0x07e5, 0x03b5 }, { 0x07e6, 0x03b6 }, { 0x07e7, 0x03b7 },
|
||||
{ 0x07e8, 0x03b8 }, { 0x07e9, 0x03b9 }, { 0x07ea, 0x03ba }, { 0x07eb, 0x03bb },
|
||||
{ 0x07ec, 0x03bc }, { 0x07ed, 0x03bd }, { 0x07ee, 0x03be }, { 0x07ef, 0x03bf },
|
||||
{ 0x07f0, 0x03c0 }, { 0x07f1, 0x03c1 }, { 0x07f2, 0x03c3 }, { 0x07f3, 0x03c2 },
|
||||
{ 0x07f4, 0x03c4 }, { 0x07f5, 0x03c5 }, { 0x07f6, 0x03c6 }, { 0x07f7, 0x03c7 },
|
||||
{ 0x07f8, 0x03c8 }, { 0x07f9, 0x03c9 }, { 0x08a1, 0x23b7 }, { 0x08a2, 0x250c },
|
||||
{ 0x08a3, 0x2500 }, { 0x08a4, 0x2320 }, { 0x08a5, 0x2321 }, { 0x08a6, 0x2502 },
|
||||
{ 0x08a7, 0x23a1 }, { 0x08a8, 0x23a3 }, { 0x08a9, 0x23a4 }, { 0x08aa, 0x23a6 },
|
||||
{ 0x08ab, 0x239b }, { 0x08ac, 0x239d }, { 0x08ad, 0x239e }, { 0x08ae, 0x23a0 },
|
||||
{ 0x08af, 0x23a8 }, { 0x08b0, 0x23ac }, { 0x08bc, 0x2264 }, { 0x08bd, 0x2260 },
|
||||
{ 0x08be, 0x2265 }, { 0x08bf, 0x222b }, { 0x08c0, 0x2234 }, { 0x08c1, 0x221d },
|
||||
{ 0x08c2, 0x221e }, { 0x08c5, 0x2207 }, { 0x08c8, 0x223c }, { 0x08c9, 0x2243 },
|
||||
{ 0x08cd, 0x21d4 }, { 0x08ce, 0x21d2 }, { 0x08cf, 0x2261 }, { 0x08d6, 0x221a },
|
||||
{ 0x08da, 0x2282 }, { 0x08db, 0x2283 }, { 0x08dc, 0x2229 }, { 0x08dd, 0x222a },
|
||||
{ 0x08de, 0x2227 }, { 0x08df, 0x2228 }, { 0x08ef, 0x2202 }, { 0x08f6, 0x0192 },
|
||||
{ 0x08fb, 0x2190 }, { 0x08fc, 0x2191 }, { 0x08fd, 0x2192 }, { 0x08fe, 0x2193 },
|
||||
{ 0x09e0, 0x25c6 }, { 0x09e1, 0x2592 }, { 0x09e2, 0x2409 }, { 0x09e3, 0x240c },
|
||||
{ 0x09e4, 0x240d }, { 0x09e5, 0x240a }, { 0x09e8, 0x2424 }, { 0x09e9, 0x240b },
|
||||
{ 0x09ea, 0x2518 }, { 0x09eb, 0x2510 }, { 0x09ec, 0x250c }, { 0x09ed, 0x2514 },
|
||||
{ 0x09ee, 0x253c }, { 0x09ef, 0x23ba }, { 0x09f0, 0x23bb }, { 0x09f1, 0x2500 },
|
||||
{ 0x09f2, 0x23bc }, { 0x09f3, 0x23bd }, { 0x09f4, 0x251c }, { 0x09f5, 0x2524 },
|
||||
{ 0x09f6, 0x2534 }, { 0x09f7, 0x252c }, { 0x09f8, 0x2502 }, { 0x0aa1, 0x2003 },
|
||||
{ 0x0aa2, 0x2002 }, { 0x0aa3, 0x2004 }, { 0x0aa4, 0x2005 }, { 0x0aa5, 0x2007 },
|
||||
{ 0x0aa6, 0x2008 }, { 0x0aa7, 0x2009 }, { 0x0aa8, 0x200a }, { 0x0aa9, 0x2014 },
|
||||
{ 0x0aaa, 0x2013 }, { 0x0aae, 0x2026 }, { 0x0aaf, 0x2025 }, { 0x0ab0, 0x2153 },
|
||||
{ 0x0ab1, 0x2154 }, { 0x0ab2, 0x2155 }, { 0x0ab3, 0x2156 }, { 0x0ab4, 0x2157 },
|
||||
{ 0x0ab5, 0x2158 }, { 0x0ab6, 0x2159 }, { 0x0ab7, 0x215a }, { 0x0ab8, 0x2105 },
|
||||
{ 0x0abb, 0x2012 }, { 0x0abc, 0x2329 }, { 0x0abe, 0x232a }, { 0x0ac3, 0x215b },
|
||||
{ 0x0ac4, 0x215c }, { 0x0ac5, 0x215d }, { 0x0ac6, 0x215e }, { 0x0ac9, 0x2122 },
|
||||
{ 0x0aca, 0x2613 }, { 0x0acc, 0x25c1 }, { 0x0acd, 0x25b7 }, { 0x0ace, 0x25cb },
|
||||
{ 0x0acf, 0x25af }, { 0x0ad0, 0x2018 }, { 0x0ad1, 0x2019 }, { 0x0ad2, 0x201c },
|
||||
{ 0x0ad3, 0x201d }, { 0x0ad4, 0x211e }, { 0x0ad6, 0x2032 }, { 0x0ad7, 0x2033 },
|
||||
{ 0x0ad9, 0x271d }, { 0x0adb, 0x25ac }, { 0x0adc, 0x25c0 }, { 0x0add, 0x25b6 },
|
||||
{ 0x0ade, 0x25cf }, { 0x0adf, 0x25ae }, { 0x0ae0, 0x25e6 }, { 0x0ae1, 0x25ab },
|
||||
{ 0x0ae2, 0x25ad }, { 0x0ae3, 0x25b3 }, { 0x0ae4, 0x25bd }, { 0x0ae5, 0x2606 },
|
||||
{ 0x0ae6, 0x2022 }, { 0x0ae7, 0x25aa }, { 0x0ae8, 0x25b2 }, { 0x0ae9, 0x25bc },
|
||||
{ 0x0aea, 0x261c }, { 0x0aeb, 0x261e }, { 0x0aec, 0x2663 }, { 0x0aed, 0x2666 },
|
||||
{ 0x0aee, 0x2665 }, { 0x0af0, 0x2720 }, { 0x0af1, 0x2020 }, { 0x0af2, 0x2021 },
|
||||
{ 0x0af3, 0x2713 }, { 0x0af4, 0x2717 }, { 0x0af5, 0x266f }, { 0x0af6, 0x266d },
|
||||
{ 0x0af7, 0x2642 }, { 0x0af8, 0x2640 }, { 0x0af9, 0x260e }, { 0x0afa, 0x2315 },
|
||||
{ 0x0afb, 0x2117 }, { 0x0afc, 0x2038 }, { 0x0afd, 0x201a }, { 0x0afe, 0x201e },
|
||||
{ 0x0ba3, 0x003c }, { 0x0ba6, 0x003e }, { 0x0ba8, 0x2228 }, { 0x0ba9, 0x2227 },
|
||||
{ 0x0bc0, 0x00af }, { 0x0bc2, 0x22a5 }, { 0x0bc3, 0x2229 }, { 0x0bc4, 0x230a },
|
||||
{ 0x0bc6, 0x005f }, { 0x0bca, 0x2218 }, { 0x0bcc, 0x2395 }, { 0x0bce, 0x22a4 },
|
||||
{ 0x0bcf, 0x25cb }, { 0x0bd3, 0x2308 }, { 0x0bd6, 0x222a }, { 0x0bd8, 0x2283 },
|
||||
{ 0x0bda, 0x2282 }, { 0x0bdc, 0x22a2 }, { 0x0bfc, 0x22a3 }, { 0x0cdf, 0x2017 },
|
||||
{ 0x0ce0, 0x05d0 }, { 0x0ce1, 0x05d1 }, { 0x0ce2, 0x05d2 }, { 0x0ce3, 0x05d3 },
|
||||
{ 0x0ce4, 0x05d4 }, { 0x0ce5, 0x05d5 }, { 0x0ce6, 0x05d6 }, { 0x0ce7, 0x05d7 },
|
||||
{ 0x0ce8, 0x05d8 }, { 0x0ce9, 0x05d9 }, { 0x0cea, 0x05da }, { 0x0ceb, 0x05db },
|
||||
{ 0x0cec, 0x05dc }, { 0x0ced, 0x05dd }, { 0x0cee, 0x05de }, { 0x0cef, 0x05df },
|
||||
{ 0x0cf0, 0x05e0 }, { 0x0cf1, 0x05e1 }, { 0x0cf2, 0x05e2 }, { 0x0cf3, 0x05e3 },
|
||||
{ 0x0cf4, 0x05e4 }, { 0x0cf5, 0x05e5 }, { 0x0cf6, 0x05e6 }, { 0x0cf7, 0x05e7 },
|
||||
{ 0x0cf8, 0x05e8 }, { 0x0cf9, 0x05e9 }, { 0x0cfa, 0x05ea }, { 0x0da1, 0x0e01 },
|
||||
{ 0x0da2, 0x0e02 }, { 0x0da3, 0x0e03 }, { 0x0da4, 0x0e04 }, { 0x0da5, 0x0e05 },
|
||||
{ 0x0da6, 0x0e06 }, { 0x0da7, 0x0e07 }, { 0x0da8, 0x0e08 }, { 0x0da9, 0x0e09 },
|
||||
{ 0x0daa, 0x0e0a }, { 0x0dab, 0x0e0b }, { 0x0dac, 0x0e0c }, { 0x0dad, 0x0e0d },
|
||||
{ 0x0dae, 0x0e0e }, { 0x0daf, 0x0e0f }, { 0x0db0, 0x0e10 }, { 0x0db1, 0x0e11 },
|
||||
{ 0x0db2, 0x0e12 }, { 0x0db3, 0x0e13 }, { 0x0db4, 0x0e14 }, { 0x0db5, 0x0e15 },
|
||||
{ 0x0db6, 0x0e16 }, { 0x0db7, 0x0e17 }, { 0x0db8, 0x0e18 }, { 0x0db9, 0x0e19 },
|
||||
{ 0x0dba, 0x0e1a }, { 0x0dbb, 0x0e1b }, { 0x0dbc, 0x0e1c }, { 0x0dbd, 0x0e1d },
|
||||
{ 0x0dbe, 0x0e1e }, { 0x0dbf, 0x0e1f }, { 0x0dc0, 0x0e20 }, { 0x0dc1, 0x0e21 },
|
||||
{ 0x0dc2, 0x0e22 }, { 0x0dc3, 0x0e23 }, { 0x0dc4, 0x0e24 }, { 0x0dc5, 0x0e25 },
|
||||
{ 0x0dc6, 0x0e26 }, { 0x0dc7, 0x0e27 }, { 0x0dc8, 0x0e28 }, { 0x0dc9, 0x0e29 },
|
||||
{ 0x0dca, 0x0e2a }, { 0x0dcb, 0x0e2b }, { 0x0dcc, 0x0e2c }, { 0x0dcd, 0x0e2d },
|
||||
{ 0x0dce, 0x0e2e }, { 0x0dcf, 0x0e2f }, { 0x0dd0, 0x0e30 }, { 0x0dd1, 0x0e31 },
|
||||
{ 0x0dd2, 0x0e32 }, { 0x0dd3, 0x0e33 }, { 0x0dd4, 0x0e34 }, { 0x0dd5, 0x0e35 },
|
||||
{ 0x0dd6, 0x0e36 }, { 0x0dd7, 0x0e37 }, { 0x0dd8, 0x0e38 }, { 0x0dd9, 0x0e39 },
|
||||
{ 0x0dda, 0x0e3a }, { 0x0ddf, 0x0e3f }, { 0x0de0, 0x0e40 }, { 0x0de1, 0x0e41 },
|
||||
{ 0x0de2, 0x0e42 }, { 0x0de3, 0x0e43 }, { 0x0de4, 0x0e44 }, { 0x0de5, 0x0e45 },
|
||||
{ 0x0de6, 0x0e46 }, { 0x0de7, 0x0e47 }, { 0x0de8, 0x0e48 }, { 0x0de9, 0x0e49 },
|
||||
{ 0x0dea, 0x0e4a }, { 0x0deb, 0x0e4b }, { 0x0dec, 0x0e4c }, { 0x0ded, 0x0e4d },
|
||||
{ 0x0df0, 0x0e50 }, { 0x0df1, 0x0e51 }, { 0x0df2, 0x0e52 }, { 0x0df3, 0x0e53 },
|
||||
{ 0x0df4, 0x0e54 }, { 0x0df5, 0x0e55 }, { 0x0df6, 0x0e56 }, { 0x0df7, 0x0e57 },
|
||||
{ 0x0df8, 0x0e58 }, { 0x0df9, 0x0e59 }, { 0x0ea1, 0x3131 }, { 0x0ea2, 0x3132 },
|
||||
{ 0x0ea3, 0x3133 }, { 0x0ea4, 0x3134 }, { 0x0ea5, 0x3135 }, { 0x0ea6, 0x3136 },
|
||||
{ 0x0ea7, 0x3137 }, { 0x0ea8, 0x3138 }, { 0x0ea9, 0x3139 }, { 0x0eaa, 0x313a },
|
||||
{ 0x0eab, 0x313b }, { 0x0eac, 0x313c }, { 0x0ead, 0x313d }, { 0x0eae, 0x313e },
|
||||
{ 0x0eaf, 0x313f }, { 0x0eb0, 0x3140 }, { 0x0eb1, 0x3141 }, { 0x0eb2, 0x3142 },
|
||||
{ 0x0eb3, 0x3143 }, { 0x0eb4, 0x3144 }, { 0x0eb5, 0x3145 }, { 0x0eb6, 0x3146 },
|
||||
{ 0x0eb7, 0x3147 }, { 0x0eb8, 0x3148 }, { 0x0eb9, 0x3149 }, { 0x0eba, 0x314a },
|
||||
{ 0x0ebb, 0x314b }, { 0x0ebc, 0x314c }, { 0x0ebd, 0x314d }, { 0x0ebe, 0x314e },
|
||||
{ 0x0ebf, 0x314f }, { 0x0ec0, 0x3150 }, { 0x0ec1, 0x3151 }, { 0x0ec2, 0x3152 },
|
||||
{ 0x0ec3, 0x3153 }, { 0x0ec4, 0x3154 }, { 0x0ec5, 0x3155 }, { 0x0ec6, 0x3156 },
|
||||
{ 0x0ec7, 0x3157 }, { 0x0ec8, 0x3158 }, { 0x0ec9, 0x3159 }, { 0x0eca, 0x315a },
|
||||
{ 0x0ecb, 0x315b }, { 0x0ecc, 0x315c }, { 0x0ecd, 0x315d }, { 0x0ece, 0x315e },
|
||||
{ 0x0ecf, 0x315f }, { 0x0ed0, 0x3160 }, { 0x0ed1, 0x3161 }, { 0x0ed2, 0x3162 },
|
||||
{ 0x0ed3, 0x3163 }, { 0x0ed4, 0x11a8 }, { 0x0ed5, 0x11a9 }, { 0x0ed6, 0x11aa },
|
||||
{ 0x0ed7, 0x11ab }, { 0x0ed8, 0x11ac }, { 0x0ed9, 0x11ad }, { 0x0eda, 0x11ae },
|
||||
{ 0x0edb, 0x11af }, { 0x0edc, 0x11b0 }, { 0x0edd, 0x11b1 }, { 0x0ede, 0x11b2 },
|
||||
{ 0x0edf, 0x11b3 }, { 0x0ee0, 0x11b4 }, { 0x0ee1, 0x11b5 }, { 0x0ee2, 0x11b6 },
|
||||
{ 0x0ee3, 0x11b7 }, { 0x0ee4, 0x11b8 }, { 0x0ee5, 0x11b9 }, { 0x0ee6, 0x11ba },
|
||||
{ 0x0ee7, 0x11bb }, { 0x0ee8, 0x11bc }, { 0x0ee9, 0x11bd }, { 0x0eea, 0x11be },
|
||||
{ 0x0eeb, 0x11bf }, { 0x0eec, 0x11c0 }, { 0x0eed, 0x11c1 }, { 0x0eee, 0x11c2 },
|
||||
{ 0x0eef, 0x316d }, { 0x0ef0, 0x3171 }, { 0x0ef1, 0x3178 }, { 0x0ef2, 0x317f },
|
||||
{ 0x0ef3, 0x3181 }, { 0x0ef4, 0x3184 }, { 0x0ef5, 0x3186 }, { 0x0ef6, 0x318d },
|
||||
{ 0x0ef7, 0x318e }, { 0x0ef8, 0x11eb }, { 0x0ef9, 0x11f0 }, { 0x0efa, 0x11f9 },
|
||||
{ 0x0eff, 0x20a9 }, { 0x13a4, 0x20ac }, { 0x13bc, 0x0152 }, { 0x13bd, 0x0153 },
|
||||
{ 0x13be, 0x0178 }, { 0x20ac, 0x20ac },
|
||||
};
|
||||
|
||||
static unsigned int ImGui_ImplQNX_KeySymToUnicode(unsigned int keysym)
|
||||
{
|
||||
// Latin-1 keysyms map directly to Unicode.
|
||||
if ((keysym >= 0x0020u && keysym <= 0x007eu) ||
|
||||
(keysym >= 0x00a0u && keysym <= 0x00ffu))
|
||||
{
|
||||
return keysym;
|
||||
}
|
||||
|
||||
// X11-style directly encoded UCS keysyms use 0x01000000 | codepoint.
|
||||
if ((keysym & 0xff000000u) == 0x01000000u)
|
||||
{
|
||||
const unsigned int codepoint = keysym & 0x00ffffffu;
|
||||
return codepoint <= IM_UNICODE_CODEPOINT_MAX ? codepoint : 0u;
|
||||
}
|
||||
|
||||
int min = 0;
|
||||
int max = (int)(sizeof(ImGui_ImplQNX_KeySymTable) / sizeof(ImGui_ImplQNX_KeySymTable[0])) - 1;
|
||||
while (max >= min)
|
||||
{
|
||||
const int mid = min + (max - min) / 2;
|
||||
if (ImGui_ImplQNX_KeySymTable[mid].KeySym < keysym)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else if (ImGui_ImplQNX_KeySymTable[mid].KeySym > keysym)
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ImGui_ImplQNX_KeySymTable[mid].Unicode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
36
backends/imgui_impl_qnx.h
Normal file
36
backends/imgui_impl_qnx.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// dear imgui: Platform Backend for QNX Screen
|
||||
// This needs to be used along with a Renderer Backend (e.g. OpenGL3, Vulkan).
|
||||
|
||||
// Implemented features:
|
||||
// [X] Platform: Keyboard support. Uses io.AddKeyEvent() and native QNX key symbols.
|
||||
// [X] Platform: Mouse support. Handles position, three buttons and horizontal/vertical wheels.
|
||||
// [X] Platform: Touch support. Maps the first active touch contact to the primary mouse button.
|
||||
// [X] Platform: Focus and window-size updates.
|
||||
// Missing features or Issues:
|
||||
// [ ] Platform: Clipboard support.
|
||||
// [ ] Platform: Gamepad support.
|
||||
// [ ] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors).
|
||||
// [ ] Platform: Multi-viewport support.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
#ifndef IMGUI_DISABLE
|
||||
|
||||
#include <screen/screen.h>
|
||||
|
||||
// The application owns the Screen context, window and event object.
|
||||
// Poll events with screen_get_event() and pass each non-NONE event to ProcessEvent().
|
||||
IMGUI_IMPL_API bool ImGui_ImplQNX_Init(screen_context_t context, screen_window_t window);
|
||||
IMGUI_IMPL_API void ImGui_ImplQNX_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplQNX_NewFrame();
|
||||
IMGUI_IMPL_API bool ImGui_ImplQNX_ProcessEvent(screen_event_t event);
|
||||
|
||||
#endif // #ifndef IMGUI_DISABLE
|
||||
@@ -79,6 +79,7 @@ List of Platforms Backends:
|
||||
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
|
||||
imgui_impl_sdl2.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_sdl3.cpp ; SDL3 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
|
||||
imgui_impl_qnx.cpp ; QNX Screen
|
||||
imgui_impl_win32.cpp ; Win32 native API (Windows)
|
||||
imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@ Other Changes:
|
||||
- Per-viewport FramebufferScale for Apple/Retina screen is applied to draw lists:
|
||||
- AA Fringe is scaled accordingly.
|
||||
- Circle and Curves tessellation error are scaled accordingly.
|
||||
- Backends:
|
||||
- QNX: added QNX Screen backend. (#9492) [@mgorchak-blackberry]
|
||||
- Examples:
|
||||
- QNX+OpenGL3, QNX+Vulkan: added QNX Screen examples. (#9492) [@mgorchak-blackberry]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
@@ -117,6 +117,16 @@ Because this application doesn't create a window nor a graphic context, there's
|
||||
Please note that imgui_impl_null itself is a rather empty backend. We provide it for consistency but
|
||||
it is similarly easy to create a skeleton application without the null backend.
|
||||
|
||||
[example_qnx_opengl3/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_opengl3/) <BR>
|
||||
QNX Screen + OpenGL ES 3 example. <BR>
|
||||
= main.cpp + imgui_impl_qnx.cpp + imgui_impl_opengl3.cpp <BR>
|
||||
Uses the QNX recursive make build system and compiles the OpenGL3 renderer with `IMGUI_IMPL_OPENGL_ES3`.
|
||||
|
||||
[example_qnx_vulkan/](https://github.com/ocornut/imgui/blob/master/examples/example_qnx_vulkan/) <BR>
|
||||
QNX Screen + Vulkan example using `VK_QNX_screen_surface`. <BR>
|
||||
= main.cpp + imgui_impl_qnx.cpp + imgui_impl_vulkan.cpp <BR>
|
||||
Uses the QNX recursive make build system and the Vulkan backend's example helper structures.
|
||||
|
||||
[example_sdl2_directx11/](https://github.com/ocornut/imgui/blob/master/examples/example_sdl2_directx11/) <BR>
|
||||
SDL2 + DirectX11 example, Windows only. <BR>
|
||||
= main.cpp + imgui_impl_sdl2.cpp + imgui_impl_dx11.cpp <BR>
|
||||
|
||||
19
examples/example_qnx_opengl3/.gitignore
vendored
Normal file
19
examples/example_qnx_opengl3/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# ignore all files
|
||||
*
|
||||
|
||||
# unignore all dirs
|
||||
!/**/
|
||||
|
||||
# unignore all with extensions
|
||||
!*.*
|
||||
|
||||
# unignore makefiles
|
||||
!Makefile
|
||||
|
||||
# re-ignore qnx build artefacts
|
||||
*.o
|
||||
*.so*
|
||||
*.a
|
||||
*.pinfo
|
||||
*.dep
|
||||
*.gcno
|
||||
2
examples/example_qnx_opengl3/Makefile
Normal file
2
examples/example_qnx_opengl3/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
LIST=OS
|
||||
include recurse.mk
|
||||
29
examples/example_qnx_opengl3/README.md
Normal file
29
examples/example_qnx_opengl3/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Dear ImGui QNX Screen + OpenGL ES 3 example
|
||||
|
||||
This example uses:
|
||||
|
||||
- `imgui_impl_qnx.cpp` as the QNX Screen platform backend
|
||||
- `imgui_impl_opengl3.cpp` as the renderer backend
|
||||
- EGL to create an OpenGL ES 3 context and Screen window surface
|
||||
|
||||
`imgui_impl_opengl3.cpp` supports desktop OpenGL and OpenGL ES. On QNX this
|
||||
example compiles it with `IMGUI_IMPL_OPENGL_ES3` and uses `#version 300 es`.
|
||||
No separate Screen/OpenGL renderer backend is required.
|
||||
|
||||
## Build
|
||||
|
||||
Load the QNX SDP environment, then run:
|
||||
|
||||
```sh
|
||||
cd examples/example_qnx_opengl3
|
||||
make
|
||||
```
|
||||
|
||||
The QNX recursive make files build for the CPUs enabled in your SDP
|
||||
configuration and install the program as `example_qnx_opengl3`.
|
||||
|
||||
## Input
|
||||
|
||||
The application polls its `screen_context_t` event queue and forwards every
|
||||
non-`SCREEN_EVENT_NONE` event to `ImGui_ImplQNX_ProcessEvent()`.
|
||||
Escape exits the example.
|
||||
31
examples/example_qnx_opengl3/common.mk
Normal file
31
examples/example_qnx_opengl3/common.mk
Normal file
@@ -0,0 +1,31 @@
|
||||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
NAME=example_qnx_opengl3
|
||||
|
||||
SRCS = \
|
||||
main.cpp \
|
||||
imgui.cpp \
|
||||
imgui_demo.cpp \
|
||||
imgui_draw.cpp \
|
||||
imgui_tables.cpp \
|
||||
imgui_widgets.cpp \
|
||||
imgui_impl_qnx.cpp \
|
||||
imgui_impl_opengl3.cpp
|
||||
|
||||
EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
EXTRA_INCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -DIMGUI_IMPL_OPENGL_ES3
|
||||
LIBS += EGL GLESv2 screen m
|
||||
|
||||
INSTALLDIR=$(firstword $(INSTALLDIR_$(OS)) usr/bin)
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Dear ImGui QNX Screen and OpenGL ES 3 example
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qmacros.mk
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
||||
6
examples/example_qnx_opengl3/example_qnx_opengl3.use
Normal file
6
examples/example_qnx_opengl3/example_qnx_opengl3.use
Normal file
@@ -0,0 +1,6 @@
|
||||
Dear ImGui QNX Screen + OpenGL ES 3 example
|
||||
|
||||
Usage: example_qnx_opengl3
|
||||
|
||||
The example uses the fullscreen size reported by QNX Screen, displays the Dear ImGui demo UI,
|
||||
and exits when Escape is pressed or the Screen window receives a close event.
|
||||
299
examples/example_qnx_opengl3/main.cpp
Normal file
299
examples/example_qnx_opengl3/main.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
// Dear ImGui: standalone example application for QNX Screen + OpenGL ES 3
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_qnx.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <screen/screen.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
#ifndef EGL_OPENGL_ES3_BIT
|
||||
#ifdef EGL_OPENGL_ES3_BIT_KHR
|
||||
#define EGL_OPENGL_ES3_BIT EGL_OPENGL_ES3_BIT_KHR
|
||||
#else
|
||||
#define EGL_OPENGL_ES3_BIT 0x0040
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct QNXWindow
|
||||
{
|
||||
screen_context_t Context = nullptr;
|
||||
screen_window_t Window = nullptr;
|
||||
screen_event_t Event = nullptr;
|
||||
EGLDisplay Display = EGL_NO_DISPLAY;
|
||||
EGLContext GLContext = EGL_NO_CONTEXT;
|
||||
EGLSurface GLSurface = EGL_NO_SURFACE;
|
||||
int Size[2] = {};
|
||||
};
|
||||
|
||||
static bool CreateQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (screen_create_context(&window->Context, 0) != 0 ||
|
||||
screen_create_window(&window->Window, window->Context) != 0 ||
|
||||
screen_create_event(&window->Event) != 0)
|
||||
{
|
||||
fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// A newly created QNX Screen window reports the fullscreen dimensions.
|
||||
if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int usage = SCREEN_USAGE_OPENGL_ES2 | SCREEN_USAGE_OPENGL_ES3 | SCREEN_USAGE_NATIVE;
|
||||
const int transparency = SCREEN_TRANSPARENCY_NONE;
|
||||
const int swap_interval = 1;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SWAP_INTERVAL, &swap_interval) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
window->Display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (window->Display == EGL_NO_DISPLAY || eglInitialize(window->Display, nullptr, nullptr) != EGL_TRUE || eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "EGL initialization failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const EGLint config_attributes[] =
|
||||
{
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 24,
|
||||
EGL_STENCIL_SIZE, 8,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLConfig config = nullptr;
|
||||
EGLint config_count = 0;
|
||||
if (eglChooseConfig(window->Display, config_attributes, &config, 1, &config_count) != EGL_TRUE || config_count == 0)
|
||||
{
|
||||
fprintf(stderr, "eglChooseConfig() failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLint native_visual = 0;
|
||||
if (eglGetConfigAttrib(window->Display, config, EGL_NATIVE_VISUAL_ID, &native_visual) != EGL_TRUE ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_FORMAT, &native_visual) != 0 ||
|
||||
screen_create_window_buffers(window->Window, 2) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create QNX Screen buffers: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const EGLint context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
|
||||
window->GLContext = eglCreateContext(window->Display, config, EGL_NO_CONTEXT, context_attributes);
|
||||
window->GLSurface = eglCreateWindowSurface(window->Display, config, window->Window, nullptr);
|
||||
if (window->GLContext == EGL_NO_CONTEXT || window->GLSurface == EGL_NO_SURFACE ||
|
||||
eglMakeCurrent(window->Display, window->GLSurface, window->GLSurface, window->GLContext) != EGL_TRUE ||
|
||||
eglSwapInterval(window->Display, 1) != EGL_TRUE)
|
||||
{
|
||||
fprintf(stderr, "EGL context creation failed: 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
const int visible = 1;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DestroyQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (window->Display != EGL_NO_DISPLAY)
|
||||
{
|
||||
eglMakeCurrent(window->Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (window->GLSurface != EGL_NO_SURFACE)
|
||||
eglDestroySurface(window->Display, window->GLSurface);
|
||||
if (window->GLContext != EGL_NO_CONTEXT)
|
||||
eglDestroyContext(window->Display, window->GLContext);
|
||||
eglTerminate(window->Display);
|
||||
}
|
||||
if (window->Event != nullptr)
|
||||
screen_destroy_event(window->Event);
|
||||
if (window->Window != nullptr)
|
||||
screen_destroy_window(window->Window);
|
||||
if (window->Context != nullptr)
|
||||
screen_destroy_context(window->Context);
|
||||
}
|
||||
|
||||
static bool ProcessQNXEvents(QNXWindow* window)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (screen_get_event(window->Context, window->Event, 0) != 0)
|
||||
return false;
|
||||
|
||||
int type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_NONE)
|
||||
return true;
|
||||
|
||||
ImGui_ImplQNX_ProcessEvent(window->Event);
|
||||
if (type == SCREEN_EVENT_CLOSE)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_KEYBOARD)
|
||||
{
|
||||
int flags = 0;
|
||||
int key_cap = 0;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 &&
|
||||
screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 &&
|
||||
(flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup QNX Screen and EGL
|
||||
QNXWindow window;
|
||||
if (!CreateQNXWindow(&window))
|
||||
{
|
||||
DestroyQNXWindow(&window);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// GL ES 3.0 + GLSL 300 es
|
||||
const char* glsl_version = "#version 300 es";
|
||||
float main_scale = 1.0f;
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplQNX_Init(window.Context, window.Window);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (!ProcessQNXEvents(&window))
|
||||
done = true;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplQNX_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
|
||||
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
eglSwapBuffers(window.Display, window.GLSurface);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplQNX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
DestroyQNXWindow(&window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
examples/example_qnx_opengl3/nto/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=CPU
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
8
examples/example_qnx_opengl3/nto/aarch64/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/aarch64/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile
Normal file
1
examples/example_qnx_opengl3/nto/aarch64/o.le/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include ../../../common.mk
|
||||
8
examples/example_qnx_opengl3/nto/x86_64/Makefile
Normal file
8
examples/example_qnx_opengl3/nto/x86_64/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_opengl3/nto/x86_64/o/Makefile
Normal file
1
examples/example_qnx_opengl3/nto/x86_64/o/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include ../../../common.mk
|
||||
19
examples/example_qnx_vulkan/.gitignore
vendored
Normal file
19
examples/example_qnx_vulkan/.gitignore
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
# ignore all files
|
||||
*
|
||||
|
||||
# unignore all dirs
|
||||
!/**/
|
||||
|
||||
# unignore all with extensions
|
||||
!*.*
|
||||
|
||||
# unignore makefiles
|
||||
!Makefile
|
||||
|
||||
# re-ignore qnx build artefacts
|
||||
*.o
|
||||
*.so*
|
||||
*.a
|
||||
*.pinfo
|
||||
*.dep
|
||||
*.gcno
|
||||
2
examples/example_qnx_vulkan/Makefile
Normal file
2
examples/example_qnx_vulkan/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
LIST=OS
|
||||
include recurse.mk
|
||||
29
examples/example_qnx_vulkan/README.md
Normal file
29
examples/example_qnx_vulkan/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Dear ImGui QNX Screen + Vulkan example
|
||||
|
||||
This example uses:
|
||||
|
||||
- `imgui_impl_qnx.cpp` as the QNX Screen platform backend
|
||||
- the unmodified `imgui_impl_vulkan.cpp` renderer backend
|
||||
- `vkCreateScreenSurfaceQNX()` and `VK_QNX_screen_surface`
|
||||
|
||||
No separate Screen/Vulkan renderer backend is required. The QNX-specific work
|
||||
is limited to the Screen platform backend, native window setup, and Vulkan WSI
|
||||
surface creation.
|
||||
|
||||
## Build
|
||||
|
||||
Load the QNX SDP environment, then run:
|
||||
|
||||
```sh
|
||||
cd examples/example_qnx_vulkan
|
||||
make
|
||||
```
|
||||
|
||||
The build defines `VK_USE_PLATFORM_SCREEN_QNX` and links `libvulkan` and
|
||||
`libscreen`.
|
||||
|
||||
## Input and resize
|
||||
|
||||
The application forwards Screen input events to `ImGui_ImplQNX_ProcessEvent()`.
|
||||
It recreates the Vulkan swapchain when the Screen window size changes or Vulkan
|
||||
reports `VK_ERROR_OUT_OF_DATE_KHR` / `VK_SUBOPTIMAL_KHR`. Escape exits.
|
||||
31
examples/example_qnx_vulkan/common.mk
Normal file
31
examples/example_qnx_vulkan/common.mk
Normal file
@@ -0,0 +1,31 @@
|
||||
ifndef QCONFIG
|
||||
QCONFIG=qconfig.mk
|
||||
endif
|
||||
include $(QCONFIG)
|
||||
|
||||
NAME=example_qnx_vulkan
|
||||
|
||||
SRCS = \
|
||||
main.cpp \
|
||||
imgui.cpp \
|
||||
imgui_demo.cpp \
|
||||
imgui_draw.cpp \
|
||||
imgui_tables.cpp \
|
||||
imgui_widgets.cpp \
|
||||
imgui_impl_qnx.cpp \
|
||||
imgui_impl_vulkan.cpp
|
||||
|
||||
EXTRA_SRCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
EXTRA_INCVPATH += $(PROJECT_ROOT)/../.. $(PROJECT_ROOT)/../../backends
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -DVK_USE_PLATFORM_SCREEN_QNX=1
|
||||
LIBS += vulkan screen m
|
||||
|
||||
INSTALLDIR=$(firstword $(INSTALLDIR_$(OS)) usr/bin)
|
||||
|
||||
define PINFO
|
||||
PINFO DESCRIPTION=Dear ImGui QNX Screen and Vulkan example
|
||||
endef
|
||||
|
||||
include $(MKFILES_ROOT)/qmacros.mk
|
||||
include $(MKFILES_ROOT)/qtargets.mk
|
||||
7
examples/example_qnx_vulkan/example_qnx_vulkan.use
Normal file
7
examples/example_qnx_vulkan/example_qnx_vulkan.use
Normal file
@@ -0,0 +1,7 @@
|
||||
Dear ImGui QNX Screen + Vulkan example
|
||||
|
||||
Usage: example_qnx_vulkan
|
||||
|
||||
The example uses the fullscreen size reported by QNX Screen, creates a VK_QNX_screen_surface
|
||||
swapchain, displays the Dear ImGui demo UI, and exits when Escape is pressed
|
||||
or the Screen window receives a close event.
|
||||
626
examples/example_qnx_vulkan/main.cpp
Normal file
626
examples/example_qnx_vulkan/main.cpp
Normal file
@@ -0,0 +1,626 @@
|
||||
// Dear ImGui: standalone example application for QNX Screen + Vulkan
|
||||
|
||||
// Learn about Dear ImGui:
|
||||
// - FAQ https://dearimgui.com/faq
|
||||
// - Getting Started https://dearimgui.com/getting-started
|
||||
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
||||
// - Introduction, links and more at the top of imgui.cpp
|
||||
|
||||
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
|
||||
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
|
||||
// You will use those if you want to use this rendering backend in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#ifndef VK_USE_PLATFORM_SCREEN_QNX
|
||||
#define VK_USE_PLATFORM_SCREEN_QNX
|
||||
#endif
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_qnx.h"
|
||||
#include "imgui_impl_vulkan.h"
|
||||
#include <stdio.h> // printf, fprintf
|
||||
#include <stdlib.h> // abort
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/keycodes.h>
|
||||
#include <time.h>
|
||||
#include <screen/screen.h>
|
||||
|
||||
// Volk headers
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
#define VOLK_IMPLEMENTATION
|
||||
#include <volk.h>
|
||||
#endif
|
||||
|
||||
//#define APP_USE_UNLIMITED_FRAME_RATE
|
||||
#ifdef _DEBUG
|
||||
#define APP_USE_VULKAN_DEBUG_REPORT
|
||||
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
||||
#endif
|
||||
|
||||
// Data
|
||||
static VkAllocationCallbacks* g_Allocator = nullptr;
|
||||
static VkInstance g_Instance = VK_NULL_HANDLE;
|
||||
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||
static VkDevice g_Device = VK_NULL_HANDLE;
|
||||
static uint32_t g_QueueFamily = (uint32_t)-1;
|
||||
static VkQueue g_Queue = VK_NULL_HANDLE;
|
||||
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
|
||||
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
||||
static uint32_t g_MinImageCount = 2;
|
||||
static bool g_SwapChainRebuild = false;
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
if (err == VK_SUCCESS)
|
||||
return;
|
||||
fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
|
||||
if (err < 0)
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
|
||||
{
|
||||
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
||||
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
||||
return VK_FALSE;
|
||||
}
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
|
||||
{
|
||||
for (const VkExtensionProperties& p : properties)
|
||||
if (strcmp(p.extensionName, extension) == 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void SetupVulkan(ImVector<const char*> instance_extensions)
|
||||
{
|
||||
VkResult err;
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
volkInitialize();
|
||||
#endif
|
||||
|
||||
// Create Vulkan Instance
|
||||
{
|
||||
VkInstanceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
|
||||
// Enumerate available extensions
|
||||
uint32_t properties_count;
|
||||
ImVector<VkExtensionProperties> properties;
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr);
|
||||
properties.resize(properties_count);
|
||||
err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data);
|
||||
check_vk_result(err);
|
||||
|
||||
// Enable required extensions
|
||||
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||
instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
|
||||
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
|
||||
{
|
||||
instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Enabling validation layers
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
|
||||
create_info.enabledLayerCount = 1;
|
||||
create_info.ppEnabledLayerNames = layers;
|
||||
instance_extensions.push_back("VK_EXT_debug_report");
|
||||
#endif
|
||||
|
||||
// Create Vulkan Instance
|
||||
create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
|
||||
create_info.ppEnabledExtensionNames = instance_extensions.Data;
|
||||
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
||||
check_vk_result(err);
|
||||
#ifdef IMGUI_IMPL_VULKAN_USE_VOLK
|
||||
volkLoadInstance(g_Instance);
|
||||
#endif
|
||||
|
||||
// Setup the debug report callback
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
||||
IM_ASSERT(f_vkCreateDebugReportCallbackEXT != nullptr);
|
||||
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
||||
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||
debug_report_ci.pfnCallback = debug_report;
|
||||
debug_report_ci.pUserData = nullptr;
|
||||
err = f_vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
||||
check_vk_result(err);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Select Physical Device (GPU)
|
||||
g_PhysicalDevice = ImGui_ImplVulkanH_SelectPhysicalDevice(g_Instance);
|
||||
IM_ASSERT(g_PhysicalDevice != VK_NULL_HANDLE);
|
||||
|
||||
// Select graphics queue family
|
||||
g_QueueFamily = ImGui_ImplVulkanH_SelectQueueFamilyIndex(g_PhysicalDevice);
|
||||
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
|
||||
|
||||
// Create Logical Device (with 1 queue)
|
||||
{
|
||||
ImVector<const char*> device_extensions;
|
||||
device_extensions.push_back("VK_KHR_swapchain");
|
||||
|
||||
// Enumerate physical device extension
|
||||
uint32_t properties_count;
|
||||
ImVector<VkExtensionProperties> properties;
|
||||
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
|
||||
properties.resize(properties_count);
|
||||
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
|
||||
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
|
||||
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
|
||||
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
||||
#endif
|
||||
|
||||
const float queue_priority[] = { 1.0f };
|
||||
VkDeviceQueueCreateInfo queue_info[1] = {};
|
||||
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
||||
queue_info[0].queueCount = 1;
|
||||
queue_info[0].pQueuePriorities = queue_priority;
|
||||
VkDeviceCreateInfo create_info = {};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
|
||||
create_info.pQueueCreateInfos = queue_info;
|
||||
create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
|
||||
create_info.ppEnabledExtensionNames = device_extensions.Data;
|
||||
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
|
||||
check_vk_result(err);
|
||||
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
||||
}
|
||||
|
||||
// Create Descriptor Pool
|
||||
// If you wish to load e.g. additional textures you may need to alter pools sizes and maxSets.
|
||||
{
|
||||
VkDescriptorPoolSize pool_sizes[] =
|
||||
{
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE },
|
||||
{ VK_DESCRIPTOR_TYPE_SAMPLER, IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE },
|
||||
};
|
||||
VkDescriptorPoolCreateInfo pool_info = {};
|
||||
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
||||
pool_info.maxSets = 0;
|
||||
for (VkDescriptorPoolSize& pool_size : pool_sizes)
|
||||
pool_info.maxSets += pool_size.descriptorCount;
|
||||
pool_info.poolSizeCount = (uint32_t)IM_COUNTOF(pool_sizes);
|
||||
pool_info.pPoolSizes = pool_sizes;
|
||||
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
|
||||
// Your real engine/app may not use them.
|
||||
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
||||
{
|
||||
// Check for WSI support
|
||||
VkBool32 res;
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, surface, &res);
|
||||
if (res != VK_TRUE)
|
||||
{
|
||||
fprintf(stderr, "Error no WSI support on physical device 0\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Select Surface Format
|
||||
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
|
||||
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
|
||||
wd->Surface = surface;
|
||||
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_COUNTOF(requestSurfaceImageFormat), requestSurfaceColorSpace);
|
||||
|
||||
// Select Present Mode
|
||||
#ifdef APP_USE_UNLIMITED_FRAME_RATE
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
|
||||
#else
|
||||
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
||||
#endif
|
||||
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_COUNTOF(present_modes));
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// Create SwapChain, RenderPass, Framebuffer, etc.
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, 0);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
{
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
|
||||
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
||||
// Remove the debug report callback
|
||||
auto f_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
||||
f_vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
||||
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
||||
|
||||
vkDestroyDevice(g_Device, g_Allocator);
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void CleanupVulkanWindow(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroySurfaceKHR(g_Instance, wd->Surface, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
{
|
||||
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
g_SwapChainRebuild = true;
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
return;
|
||||
if (err != VK_SUBOPTIMAL_KHR)
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
|
||||
{
|
||||
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkResetFences(g_Device, 1, &fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
|
||||
check_vk_result(err);
|
||||
VkCommandBufferBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
|
||||
check_vk_result(err);
|
||||
}
|
||||
{
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = wd->RenderPass;
|
||||
info.framebuffer = fd->Framebuffer;
|
||||
info.renderArea.extent.width = wd->Width;
|
||||
info.renderArea.extent.height = wd->Height;
|
||||
info.clearValueCount = 1;
|
||||
info.pClearValues = &wd->ClearValue;
|
||||
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
|
||||
}
|
||||
|
||||
// Record dear imgui primitives into command buffer
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
|
||||
|
||||
// Submit command buffer
|
||||
vkCmdEndRenderPass(fd->CommandBuffer);
|
||||
{
|
||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &image_acquired_semaphore;
|
||||
info.pWaitDstStageMask = &wait_stage;
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &fd->CommandBuffer;
|
||||
info.signalSemaphoreCount = 1;
|
||||
info.pSignalSemaphores = &render_complete_semaphore;
|
||||
|
||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||
check_vk_result(err);
|
||||
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
|
||||
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
if (g_SwapChainRebuild)
|
||||
return;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &render_complete_semaphore;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
g_SwapChainRebuild = true;
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
return;
|
||||
if (err != VK_SUBOPTIMAL_KHR)
|
||||
check_vk_result(err);
|
||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
|
||||
}
|
||||
|
||||
|
||||
struct QNXWindow
|
||||
{
|
||||
screen_context_t Context = nullptr;
|
||||
screen_window_t Window = nullptr;
|
||||
screen_event_t Event = nullptr;
|
||||
int Size[2] = {};
|
||||
};
|
||||
|
||||
static bool CreateQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (screen_create_context(&window->Context, 0) != 0 ||
|
||||
screen_create_window(&window->Window, window->Context) != 0 ||
|
||||
screen_create_event(&window->Event) != 0)
|
||||
{
|
||||
fprintf(stderr, "QNX Screen initialization failed: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// A newly created QNX Screen window reports the fullscreen dimensions.
|
||||
if (screen_get_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 || window->Size[0] <= 0 || window->Size[1] <= 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to obtain QNX Screen window size: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
const int usage = SCREEN_USAGE_VULKAN | SCREEN_USAGE_NATIVE;
|
||||
const int transparency = SCREEN_TRANSPARENCY_NONE;
|
||||
if (screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_USAGE, &usage) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_SIZE, window->Size) != 0 ||
|
||||
screen_set_window_property_iv(window->Window, SCREEN_PROPERTY_TRANSPARENCY, &transparency) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to configure QNX Screen window: %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void DestroyQNXWindow(QNXWindow* window)
|
||||
{
|
||||
if (window->Event != nullptr)
|
||||
screen_destroy_event(window->Event);
|
||||
if (window->Window != nullptr)
|
||||
screen_destroy_window(window->Window);
|
||||
if (window->Context != nullptr)
|
||||
screen_destroy_context(window->Context);
|
||||
}
|
||||
|
||||
static bool ProcessQNXEvents(QNXWindow* window)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (screen_get_event(window->Context, window->Event, 0) != 0)
|
||||
return false;
|
||||
|
||||
int type = SCREEN_EVENT_NONE;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_TYPE, &type) != 0)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_NONE)
|
||||
return true;
|
||||
|
||||
ImGui_ImplQNX_ProcessEvent(window->Event);
|
||||
if (type == SCREEN_EVENT_CLOSE)
|
||||
return false;
|
||||
if (type == SCREEN_EVENT_KEYBOARD)
|
||||
{
|
||||
int flags = 0;
|
||||
int key_cap = 0;
|
||||
if (screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_FLAGS, &flags) == 0 &&
|
||||
screen_get_event_property_iv(window->Event, SCREEN_PROPERTY_KEY_CAP, &key_cap) == 0 &&
|
||||
(flags & SCREEN_FLAG_KEY_DOWN) != 0 && key_cap == KEYCODE_ESCAPE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void QNXSleep(int milliseconds)
|
||||
{
|
||||
struct timespec request = { milliseconds / 1000, (milliseconds % 1000) * 1000000L };
|
||||
nanosleep(&request, nullptr);
|
||||
}
|
||||
|
||||
// Main code
|
||||
int main(int, char**)
|
||||
{
|
||||
// Create window with Vulkan graphics context
|
||||
QNXWindow window;
|
||||
if (!CreateQNXWindow(&window))
|
||||
{
|
||||
DestroyQNXWindow(&window);
|
||||
return 1;
|
||||
}
|
||||
float main_scale = 1.0f;
|
||||
|
||||
ImVector<const char*> extensions;
|
||||
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||
extensions.push_back(VK_QNX_SCREEN_SURFACE_EXTENSION_NAME);
|
||||
SetupVulkan(extensions);
|
||||
|
||||
// Create Window Surface
|
||||
VkScreenSurfaceCreateInfoQNX surface_create_info = {};
|
||||
surface_create_info.sType = VK_STRUCTURE_TYPE_SCREEN_SURFACE_CREATE_INFO_QNX;
|
||||
surface_create_info.context = window.Context;
|
||||
surface_create_info.window = window.Window;
|
||||
VkSurfaceKHR surface;
|
||||
VkResult err = vkCreateScreenSurfaceQNX(g_Instance, &surface_create_info, g_Allocator, &surface);
|
||||
check_vk_result(err);
|
||||
|
||||
// Create Framebuffers
|
||||
int w = window.Size[0];
|
||||
int h = window.Size[1];
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
const int visible = 1;
|
||||
if (screen_set_window_property_iv(window.Window, SCREEN_PROPERTY_VISIBLE, &visible) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to show QNX Screen window: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsLight();
|
||||
|
||||
// Setup scaling
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
|
||||
style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor)
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplQNX_Init(window.Context, window.Window);
|
||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||
//init_info.ApiVersion = VK_API_VERSION_1_3; // Pass in your value of VkApplicationInfo::apiVersion, otherwise will default to header version.
|
||||
init_info.Instance = g_Instance;
|
||||
init_info.PhysicalDevice = g_PhysicalDevice;
|
||||
init_info.Device = g_Device;
|
||||
init_info.QueueFamily = g_QueueFamily;
|
||||
init_info.Queue = g_Queue;
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
|
||||
init_info.PipelineInfoMain.Subpass = 0;
|
||||
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info);
|
||||
|
||||
// Load Fonts
|
||||
// - If fonts are not explicitly loaded, Dear ImGui will select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap().
|
||||
// This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold.
|
||||
// - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit).
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//style.FontSizeBase = 20.0f;
|
||||
//io.Fonts->AddFontDefaultVector();
|
||||
//io.Fonts->AddFontDefaultBitmap();
|
||||
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf");
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf");
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf");
|
||||
//IM_ASSERT(font != nullptr);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
if (!ProcessQNXEvents(&window))
|
||||
done = true;
|
||||
|
||||
// Resize swap chain?
|
||||
int framebuffer_size[2] = {};
|
||||
if (screen_get_window_property_iv(window.Window, SCREEN_PROPERTY_SIZE, framebuffer_size) != 0)
|
||||
done = true;
|
||||
int fb_width = framebuffer_size[0];
|
||||
int fb_height = framebuffer_size[1];
|
||||
if (fb_width <= 0 || fb_height <= 0)
|
||||
{
|
||||
QNXSleep(10);
|
||||
continue;
|
||||
}
|
||||
if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height))
|
||||
{
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, 0);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
g_SwapChainRebuild = false;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplQNX_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
ImDrawData* draw_data = ImGui::GetDrawData();
|
||||
const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
|
||||
if (!is_minimized)
|
||||
{
|
||||
wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
|
||||
wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
|
||||
wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
|
||||
wd->ClearValue.color.float32[3] = clear_color.w;
|
||||
FrameRender(wd, draw_data);
|
||||
FramePresent(wd);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplQNX_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow(&g_MainWindowData);
|
||||
CleanupVulkan();
|
||||
|
||||
DestroyQNXWindow(&window);
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
examples/example_qnx_vulkan/nto/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=CPU
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
8
examples/example_qnx_vulkan/nto/aarch64/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/aarch64/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile
Normal file
1
examples/example_qnx_vulkan/nto/aarch64/o.le/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include ../../../common.mk
|
||||
8
examples/example_qnx_vulkan/nto/x86_64/Makefile
Normal file
8
examples/example_qnx_vulkan/nto/x86_64/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
LIST=VARIANT
|
||||
ifndef QRECURSE
|
||||
QRECURSE=recurse.mk
|
||||
ifdef QCONFIG
|
||||
QRDIR=$(dir $(QCONFIG))
|
||||
endif
|
||||
endif
|
||||
include $(QRDIR)$(QRECURSE)
|
||||
1
examples/example_qnx_vulkan/nto/x86_64/o/Makefile
Normal file
1
examples/example_qnx_vulkan/nto/x86_64/o/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
include ../../../common.mk
|
||||
Reference in New Issue
Block a user