From bb9394a46f2c541db7cfdf664bf4411a61afcba4 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 11 Nov 2019 07:47:34 -0800 Subject: Moved NativeApp to Tools module --- Common/NativeApp/src/Linux/LinuxMain.cpp | 526 ------------------------------- 1 file changed, 526 deletions(-) delete mode 100644 Common/NativeApp/src/Linux/LinuxMain.cpp (limited to 'Common/NativeApp/src/Linux') diff --git a/Common/NativeApp/src/Linux/LinuxMain.cpp b/Common/NativeApp/src/Linux/LinuxMain.cpp deleted file mode 100644 index fc26c8a..0000000 --- a/Common/NativeApp/src/Linux/LinuxMain.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/* Copyright 2015-2018 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#include -#include - -#include "PlatformDefinitions.h" -#include "NativeAppBase.h" -#include "StringTools.h" -#include "Timer.h" -#include "Errors.h" - - -#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB -# define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 -#endif - -#ifndef GLX_CONTEXT_MINOR_VERSION_ARB -# define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 -#endif - -#ifndef GLX_CONTEXT_FLAGS_ARB -# define GLX_CONTEXT_FLAGS_ARB 0x2094 -#endif - -#ifndef GLX_CONTEXT_DEBUG_BIT_ARB -# define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001 -#endif - -typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, int, const int*); - -static constexpr uint16_t WindowWidth = 1024; -static constexpr uint16_t WindowHeight = 768; -static constexpr uint16_t MinWindowWidth = 320; -static constexpr uint16_t MinWindowHeight = 240; - -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 - -// https://code.woboq.org/qt5/include/xcb/xcb_icccm.h.html -enum XCB_SIZE_HINT -{ - XCB_SIZE_HINT_US_POSITION = 1 << 0, - XCB_SIZE_HINT_US_SIZE = 1 << 1, - XCB_SIZE_HINT_P_POSITION = 1 << 2, - XCB_SIZE_HINT_P_SIZE = 1 << 3, - XCB_SIZE_HINT_P_MIN_SIZE = 1 << 4, - XCB_SIZE_HINT_P_MAX_SIZE = 1 << 5, - XCB_SIZE_HINT_P_RESIZE_INC = 1 << 6, - XCB_SIZE_HINT_P_ASPECT = 1 << 7, - XCB_SIZE_HINT_BASE_SIZE = 1 << 8, - XCB_SIZE_HINT_P_WIN_GRAVITY = 1 << 9 -}; - -struct xcb_size_hints_t -{ - uint32_t flags; /** User specified flags */ - int32_t x, y; /** User-specified position */ - int32_t width, height; /** User-specified size */ - int32_t min_width, min_height; /** Program-specified minimum size */ - int32_t max_width, max_height; /** Program-specified maximum size */ - int32_t width_inc, height_inc; /** Program-specified resize increments */ - int32_t min_aspect_num, min_aspect_den; /** Program-specified minimum aspect ratios */ - int32_t max_aspect_num, max_aspect_den; /** Program-specified maximum aspect ratios */ - int32_t base_width, base_height; /** Program-specified base size */ - uint32_t win_gravity; /** Program-specified window gravity */ -}; - -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() ); - - // https://stackoverflow.com/a/27771295 - xcb_size_hints_t hints = {}; - hints.flags = XCB_SIZE_HINT_P_MIN_SIZE; - hints.min_width = MinWindowWidth; - hints.min_height = MinWindowHeight; - xcb_change_property(info.connection, XCB_PROP_MODE_REPLACE, info.window, XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS, - 32, sizeof(xcb_size_hints_t), &hints); - - 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 TheApp(CreateApplication()); - - std::string Title = TheApp->GetAppTitle(); - auto xcbInfo = InitXCBConnectionAndWindow(Title); - if(!TheApp->InitVulkan(xcbInfo.connection, xcbInfo.window)) - return -1; - - xcb_flush(xcbInfo.connection); - - Timer timer; - auto PrevTime = timer.GetElapsedTime(); - Title = TheApp->GetAppTitle(); - 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(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(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 TheApp(CreateApplication()); - Display *display = XOpenDisplay(0); - - static int visual_attribs[] = - { - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_DOUBLEBUFFER, true, - - // The largest available total RGBA color buffer size (sum of GLX_RED_SIZE, - // GLX_GREEN_SIZE, GLX_BLUE_SIZE, and GLX_ALPHA_SIZE) of at least the minimum - // size specified for each color component is preferred. - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - - // The largest available depth buffer of at least GLX_DEPTH_SIZE size is preferred - GLX_DEPTH_SIZE, 24, - - //GLX_SAMPLE_BUFFERS, 1, - GLX_SAMPLES, 1, - None - }; - - int fbcount = 0; - GLXFBConfig *fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount); - if (!fbc) - { - LOG_ERROR_MESSAGE("Failed to retrieve a framebuffer config"); - return -1; - } - - XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[0]); - - XSetWindowAttributes swa; - swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); - swa.border_pixel = 0; - swa.event_mask = - StructureNotifyMask | - ExposureMask | - KeyPressMask | - KeyReleaseMask | - ButtonPressMask | - ButtonReleaseMask | - PointerMotionMask; - - 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."); - return -1; - } - - { - auto SizeHints = XAllocSizeHints(); - SizeHints->flags = PMinSize; - SizeHints->min_width = MinWindowWidth; - SizeHints->min_height = MinWindowHeight; - XSetWMNormalHints(display, win, SizeHints); - XFree(SizeHints); - } - - XMapWindow(display, win); - - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr; - { - // Create an oldstyle context first, to get the correct function pointer for glXCreateContextAttribsARB - GLXContext ctx_old = glXCreateContext(display, vi, 0, GL_TRUE); - glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); - glXMakeCurrent(display, None, NULL); - glXDestroyContext(display, ctx_old); - } - - if (glXCreateContextAttribsARB == nullptr) - { - LOG_ERROR("glXCreateContextAttribsARB entry point not found. Aborting."); - return -1; - } - - int Flags = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; -#ifdef _DEBUG - Flags |= GLX_CONTEXT_DEBUG_BIT_ARB; -#endif - - int major_version = 4; - int minor_version = 3; - static int context_attribs[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, major_version, - GLX_CONTEXT_MINOR_VERSION_ARB, minor_version, - GLX_CONTEXT_FLAGS_ARB, Flags, - None - }; - - constexpr int True = 1; - GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, True, context_attribs); - if (!ctx) - { - LOG_ERROR("Failed to create GL context."); - return -1; - } - XFree(fbc); - - - glXMakeCurrent(display, win, ctx); - TheApp->OnGLContextCreated(display, win); - std::string Title = TheApp->GetAppTitle(); - - Timer timer; - auto PrevTime = timer.GetElapsedTime(); - WindowTitleHelper TitleHelper(Title); - - while (true) - { - bool EscPressed = false; - XEvent xev; - // Handle all events in the queue - while(XCheckMaskEvent(display, 0xFFFFFFFF, &xev)) - { - TheApp->HandleXEvent(&xev); - switch(xev.type) - { - case KeyPress: - { - KeySym keysym; - char buffer[80]; - int num_char = XLookupString((XKeyEvent *)&xev, buffer, _countof(buffer), &keysym, 0); - EscPressed = (keysym==XK_Escape); - } - - case ConfigureNotify: - { - XConfigureEvent &xce = reinterpret_cast(xev); - if(xce.width != 0 && xce.height != 0) - TheApp->WindowResize(xce.width, xce.height); - break; - } - } - } - - if(EscPressed) - 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); - XStoreName(display, win, TitleWithFPS.c_str()); - } - - TheApp.reset(); - - ctx = glXGetCurrentContext(); - glXMakeCurrent(display, None, NULL); - glXDestroyContext(display, ctx); - XDestroyWindow(display, win); - XCloseDisplay(display); -} - -int main (int argc, char ** argv) -{ - bool UseVulkan = false; - -#if VULKAN_SUPPORTED - UseVulkan = true; - if (argc > 1) - { - const auto* Key = "-mode "; - const auto* pos = strstr(argv[1], Key); - if (pos != nullptr) - { - pos += strlen(Key); - while(*pos != 0 && *pos == ' ')++pos; - 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) - { - auto ret = xcb_main(); - if (ret >= 0) - { - return ret; - } - else - { - LOG_ERROR_MESSAGE("Failed to initialize the engine in Vulkan mode. Attempting to use OpenGL"); - } - } -#endif - - return x_main(); -} -- cgit v1.2.3