summaryrefslogtreecommitdiffstats
path: root/Common/NativeApp/src/Linux/LinuxMain.cpp
diff options
context:
space:
mode:
authorEgor <egor.yusov@gmail.com>2018-11-07 17:09:05 +0000
committerEgor <egor.yusov@gmail.com>2018-11-07 17:09:05 +0000
commit9d4f206c492acf25c1853174491e3e547db55cd3 (patch)
tree907efc4ed98c311fd976652ec60282a118d444e2 /Common/NativeApp/src/Linux/LinuxMain.cpp
parentUpdated cmake version in CI build scripts (diff)
downloadDiligentEngine-9d4f206c492acf25c1853174491e3e547db55cd3.tar.gz
DiligentEngine-9d4f206c492acf25c1853174491e3e547db55cd3.zip
Enabled Vulkan on Linux (closed https://github.com/DiligentGraphics/DiligentCore/issues/32)
Diffstat (limited to 'Common/NativeApp/src/Linux/LinuxMain.cpp')
-rw-r--r--Common/NativeApp/src/Linux/LinuxMain.cpp275
1 files changed, 263 insertions, 12 deletions
diff --git a/Common/NativeApp/src/Linux/LinuxMain.cpp b/Common/NativeApp/src/Linux/LinuxMain.cpp
index 648696c..84cde9e 100644
--- a/Common/NativeApp/src/Linux/LinuxMain.cpp
+++ b/Common/NativeApp/src/Linux/LinuxMain.cpp
@@ -48,11 +48,227 @@
#endif
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, int, const int*);
-
- using namespace Diligent;
-
-int main (int argc, char ** argv)
+static constexpr uint16_t WindowWidth = 1024;
+static constexpr uint16_t WindowHeight = 768;
+
+using namespace Diligent;
+
+namespace
+{
+
+class WindowTitleHelper
+{
+public:
+ WindowTitleHelper(std::string _Title) :
+ Title(std::move(_Title))
+ {}
+
+ std::string GetTitleWithFPS(double ElapsedTime)
+ {
+ double filterScale = 0.2;
+ FilteredFrameTime = FilteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
+ std::stringstream TitleWithFpsSS;
+ TitleWithFpsSS << Title;
+ TitleWithFpsSS << " - " << std::fixed << std::setprecision(1) << FilteredFrameTime * 1000;
+ TitleWithFpsSS << " ms (" << 1.0 / FilteredFrameTime << " fps)";
+ return TitleWithFpsSS.str();
+ }
+
+private:
+ const std::string Title;
+ double FilteredFrameTime = 0.0;
+};
+
+}
+
+#if VULKAN_SUPPORTED
+
+struct XCBInfo
+{
+ xcb_connection_t* connection = nullptr;
+ uint32_t window = 0;
+ uint16_t width = 0;
+ uint16_t height = 0;
+ xcb_intern_atom_reply_t* atom_wm_delete_window = nullptr;
+};
+
+XCBInfo InitXCBConnectionAndWindow(const std::string& Title)
+{
+ XCBInfo info;
+
+ int scr = 0;
+ info.connection = xcb_connect(nullptr, &scr);
+ if (info.connection == nullptr || xcb_connection_has_error(info.connection))
+ {
+ std::cerr << "Unable to make an XCB connection\n";
+ exit(-1);
+ }
+
+ const xcb_setup_t* setup = xcb_get_setup(info.connection);
+ xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
+ while (scr-- > 0)
+ xcb_screen_next(&iter);
+
+ auto screen = iter.data;
+
+ info.width = WindowWidth;
+ info.height = WindowHeight;
+
+ uint32_t value_mask, value_list[32];
+
+ info.window = xcb_generate_id(info.connection);
+
+ value_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+ value_list[0] = screen->black_pixel;
+ value_list[1] =
+ XCB_EVENT_MASK_KEY_RELEASE |
+ XCB_EVENT_MASK_KEY_PRESS |
+ XCB_EVENT_MASK_EXPOSURE |
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY |
+ XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_BUTTON_PRESS |
+ XCB_EVENT_MASK_BUTTON_RELEASE;
+
+ xcb_create_window(info.connection, XCB_COPY_FROM_PARENT, info.window, screen->root, 0, 0, info.width, info.height, 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list);
+
+ // Magic code that will send notification when window is destroyed
+ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(info.connection, 1, 12, "WM_PROTOCOLS");
+ xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(info.connection, cookie, 0);
+
+ xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(info.connection, 0, 16, "WM_DELETE_WINDOW");
+ info.atom_wm_delete_window = xcb_intern_atom_reply(info.connection, cookie2, 0);
+
+ xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, (*reply).atom, 4, 32, 1,
+ &(*info.atom_wm_delete_window).atom);
+ free(reply);
+
+ xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
+ 8, Title.length(), Title.c_str() );
+
+ xcb_map_window(info.connection, info.window);
+
+ // Force the x/y coordinates to 100,100 results are identical in consecutive
+ // runs
+ const uint32_t coords[] = {100, 100};
+ xcb_configure_window(info.connection, info.window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
+ xcb_flush(info.connection);
+
+ xcb_generic_event_t *e;
+ while ((e = xcb_wait_for_event(info.connection)))
+ {
+ if ((e->response_type & ~0x80) == XCB_EXPOSE) break;
+ }
+ return info;
+}
+
+void DestroyXCBConnectionAndWindow(XCBInfo &info)
+{
+ xcb_destroy_window(info.connection, info.window);
+ xcb_disconnect(info.connection);
+}
+
+int xcb_main()
+{
+ std::unique_ptr<NativeAppBase> TheApp(CreateApplication());
+
+ std::string Title = TheApp->GetAppTitle();
+ Title += " (Vulkan)";
+ auto xcbInfo = InitXCBConnectionAndWindow(Title);
+ TheApp->InitVulkan(xcbInfo.connection, xcbInfo.window);
+
+ xcb_flush(xcbInfo.connection);
+
+ Timer timer;
+ auto PrevTime = timer.GetElapsedTime();
+ WindowTitleHelper TitleHelper(Title);
+
+ while (true)
+ {
+ xcb_generic_event_t* event = nullptr;
+ bool Quit = false;
+ while ((event = xcb_poll_for_event(xcbInfo.connection)) != nullptr)
+ {
+ TheApp->HandleXCBEvent(event);
+ switch (event->response_type & 0x7f)
+ {
+ case XCB_CLIENT_MESSAGE:
+ if ((*(xcb_client_message_event_t*)event).data.data32[0] ==
+ (*xcbInfo.atom_wm_delete_window).atom)
+ {
+ Quit = true;
+ }
+ break;
+
+ case XCB_KEY_RELEASE:
+ {
+ const auto* keyEvent = reinterpret_cast<const xcb_key_release_event_t*>(event);
+ switch (keyEvent->detail)
+ {
+ #define KEY_ESCAPE 0x9
+ case KEY_ESCAPE:
+ Quit = true;
+ break;
+ }
+ }
+ break;
+
+ case XCB_DESTROY_NOTIFY:
+ Quit = true;
+ break;
+
+ case XCB_CONFIGURE_NOTIFY:
+ {
+ const auto* cfgEvent = reinterpret_cast<const xcb_configure_notify_event_t*>(event);
+ if ((cfgEvent->width != xcbInfo.width) || (cfgEvent->height != xcbInfo.height))
+ {
+ xcbInfo.width = cfgEvent->width;
+ xcbInfo.height = cfgEvent->height;
+ if ((xcbInfo.width > 0) && (xcbInfo.height > 0))
+ {
+ TheApp->WindowResize(xcbInfo.width, xcbInfo.height);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ free(event);
+ }
+
+ if (Quit)
+ break;
+
+ // Render the scene
+ auto CurrTime = timer.GetElapsedTime();
+ auto ElapsedTime = CurrTime - PrevTime;
+ PrevTime = CurrTime;
+
+ TheApp->Update(CurrTime, ElapsedTime);
+
+ TheApp->Render();
+
+ TheApp->Present();
+
+ auto TitleWithFPS = TitleHelper.GetTitleWithFPS(ElapsedTime);
+ xcb_change_property(xcbInfo.connection, XCB_PROP_MODE_REPLACE, xcbInfo.window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING,
+ 8, TitleWithFPS.length(), TitleWithFPS.c_str() );
+ xcb_flush(xcbInfo.connection);
+ }
+
+ TheApp.reset();
+ DestroyXCBConnectionAndWindow(xcbInfo);
+
+ return 0;
+}
+
+#endif
+
+
+int x_main()
{
std::unique_ptr<NativeAppBase> TheApp(CreateApplication());
Display *display = XOpenDisplay(0);
@@ -101,7 +317,7 @@ int main (int argc, char ** argv)
ButtonReleaseMask |
PointerMotionMask;
- Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 1024, 768, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
+ Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, WindowWidth, WindowHeight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
if (!win)
{
LOG_ERROR_MESSAGE("Failed to create window.");
@@ -153,10 +369,11 @@ int main (int argc, char ** argv)
glXMakeCurrent(display, win, ctx);
TheApp->OnGLContextCreated(display, win);
std::string Title = TheApp->GetAppTitle();
+ Title += " (OpenGL)";
Timer timer;
auto PrevTime = timer.GetElapsedTime();
- double filteredFrameTime = 0.0;
+ WindowTitleHelper TitleHelper(Title);
while (true)
{
@@ -200,12 +417,8 @@ int main (int argc, char ** argv)
TheApp->Present();
- double filterScale = 0.2;
- filteredFrameTime = filteredFrameTime * (1.0 - filterScale) + filterScale * ElapsedTime;
- std::stringstream fpsCounterSS;
- fpsCounterSS << " - " << std::fixed << std::setprecision(1) << filteredFrameTime * 1000;
- fpsCounterSS << " ms (" << 1.0 / filteredFrameTime << " fps)";
- XStoreName(display, win, (Title + fpsCounterSS.str()).c_str());
+ auto TitleWithFPS = TitleHelper.GetTitleWithFPS(ElapsedTime);
+ XStoreName(display, win, TitleWithFPS.c_str());
}
TheApp.reset();
@@ -216,3 +429,41 @@ int main (int argc, char ** argv)
XDestroyWindow(display, win);
XCloseDisplay(display);
}
+
+int main (int argc, char ** argv)
+{
+ bool UseVulkan = false;
+
+#ifdef VULKAN_SUPPORTED
+ UseVulkan = true;
+ if (argc > 1)
+ {
+ const auto* Key = "mode=";
+ const auto* pos = strstr(argv[1], Key);
+ if (pos != nullptr)
+ {
+ pos += strlen(Key);
+ if (strcasecmp(pos, "GL") == 0)
+ {
+ UseVulkan = false;
+ }
+ else if (strcasecmp(pos, "VK") == 0)
+ {
+ UseVulkan = true;
+ }
+ else
+ {
+ std::cerr << "Unknown device type. Only the following types are supported: GL, VK";
+ return -1;
+ }
+ }
+ }
+
+ if (UseVulkan)
+ {
+ return xcb_main();
+ }
+#endif
+
+ return x_main();
+} \ No newline at end of file