From b86f1a907a44d5aab2d7cb824bab9164fdbbfbc7 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Wed, 27 Jul 2022 00:57:42 +0200 Subject: [PATCH] Move all GLFW code to a separate class. --- profiler/build/win32/Tracy.vcxproj | 6 +- profiler/build/win32/Tracy.vcxproj.filters | 18 +- profiler/src/Backend.hpp | 34 ++++ profiler/src/BackendGlfw.cpp | 194 +++++++++++++++++++++ profiler/src/ImGuiContext.cpp | 18 ++ profiler/src/ImGuiContext.hpp | 16 ++ profiler/src/NativeWindow.cpp | 34 ---- profiler/src/NativeWindow.hpp | 6 - profiler/src/main.cpp | 181 ++++--------------- 9 files changed, 310 insertions(+), 197 deletions(-) create mode 100644 profiler/src/Backend.hpp create mode 100644 profiler/src/BackendGlfw.cpp create mode 100644 profiler/src/ImGuiContext.cpp create mode 100644 profiler/src/ImGuiContext.hpp delete mode 100644 profiler/src/NativeWindow.cpp delete mode 100644 profiler/src/NativeWindow.hpp diff --git a/profiler/build/win32/Tracy.vcxproj b/profiler/build/win32/Tracy.vcxproj index cbfd688f..d152129d 100644 --- a/profiler/build/win32/Tracy.vcxproj +++ b/profiler/build/win32/Tracy.vcxproj @@ -195,14 +195,15 @@ + + - @@ -316,6 +317,7 @@ + @@ -324,10 +326,10 @@ + - diff --git a/profiler/build/win32/Tracy.vcxproj.filters b/profiler/build/win32/Tracy.vcxproj.filters index 0eae1031..7b3e7a32 100644 --- a/profiler/build/win32/Tracy.vcxproj.filters +++ b/profiler/build/win32/Tracy.vcxproj.filters @@ -51,9 +51,6 @@ src - - src - server @@ -348,6 +345,12 @@ src + + src + + + src + @@ -488,9 +491,6 @@ server - - src - src @@ -707,6 +707,12 @@ src + + src + + + src + diff --git a/profiler/src/Backend.hpp b/profiler/src/Backend.hpp new file mode 100644 index 00000000..5c1df8c1 --- /dev/null +++ b/profiler/src/Backend.hpp @@ -0,0 +1,34 @@ +#ifndef __BACKEND_HPP__ +#define __BACKEND_HPP__ + +#include +#include + +#include "WindowPosition.hpp" + +class RunQueue; + +class Backend +{ +public: + Backend( const char* title, std::function redraw, RunQueue* mainThreadTasks ); + ~Backend(); + + void Show(); + void Run(); + + void NewFrame( int& w, int& h ); + void EndFrame(); + + void SetIcon( uint8_t* data, int w, int h ); + void SetTitle( const char* title ); + + float GetDpiScale(); + void* GetNativeWindow(); + +private: + WindowPosition m_winPos; + int m_w, m_h; +}; + +#endif diff --git a/profiler/src/BackendGlfw.cpp b/profiler/src/BackendGlfw.cpp new file mode 100644 index 00000000..a5318773 --- /dev/null +++ b/profiler/src/BackendGlfw.cpp @@ -0,0 +1,194 @@ +#include "imgui/imgui_impl_glfw.h" +#include "imgui/imgui_impl_opengl3.h" +#include "imgui/imgui_impl_opengl3_loader.h" + +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# define GLFW_EXPOSE_NATIVE_WIN32 +# include +#elif defined __linux__ +# ifdef DISPLAY_SERVER_X11 +# define GLFW_EXPOSE_NATIVE_X11 +# elif defined DISPLAY_SERVER_WAYLAND +# define GLFW_EXPOSE_NATIVE_WAYLAND +# else +# error "unsupported linux display server" +# endif +# include +#endif + +#include "Backend.hpp" +#include "RunQueue.hpp" + + +static GLFWwindow* s_window; +static std::function s_redraw; +static RunQueue* s_mainThreadTasks; + +static void glfw_error_callback( int error, const char* description ) +{ + fprintf(stderr, "Error %d: %s\n", error, description); +} + + +Backend::Backend( const char* title, std::function redraw, RunQueue* mainThreadTasks ) +{ + glfwSetErrorCallback( glfw_error_callback ); + if( !glfwInit() ) exit( 1 ); +#ifdef DISPLAY_SERVER_WAYLAND + glfwWindowHint( GLFW_ALPHA_BITS, 0 ); +#else + glfwWindowHint(GLFW_VISIBLE, 0 ); +#endif + glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 ); + glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 ); + glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE ); +#if __APPLE__ + glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE ); +#endif + s_window = glfwCreateWindow( m_winPos.w, m_winPos.h, title, NULL, NULL ); + if( !s_window ) exit( 1 ); + + glfwSetWindowPos( s_window, m_winPos.x, m_winPos.y ); +#ifdef GLFW_MAXIMIZED + if( m_winPos.maximize ) glfwMaximizeWindow( s_window ); +#endif + + glfwMakeContextCurrent( s_window ); + glfwSwapInterval( 1 ); // Enable vsync + glfwSetWindowRefreshCallback( s_window, []( GLFWwindow* ) { s_redraw(); } ); + + ImGui_ImplGlfw_InitForOpenGL( s_window, true ); + ImGui_ImplOpenGL3_Init( "#version 150" ); + + s_redraw = redraw; + s_mainThreadTasks = mainThreadTasks; +} + +Backend::~Backend() +{ +#ifdef GLFW_MAXIMIZED + uint32_t maximized = glfwGetWindowAttrib( s_window, GLFW_MAXIMIZED ); + if( maximized ) glfwRestoreWindow( s_window ); +#else + uint32_t maximized = 0; +#endif + m_winPos.maximize = maximized; + + glfwGetWindowPos( s_window, &m_winPos.x, &m_winPos.y ); + glfwGetWindowSize( s_window, &m_winPos.w, &m_winPos.h ); + + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + + glfwDestroyWindow( s_window ); + + glfwTerminate(); +} + +void Backend::Show() +{ + glfwShowWindow( s_window ); +} + +void Backend::Run() +{ + while( !glfwWindowShouldClose( s_window ) ) + { + glfwPollEvents(); + if( glfwGetWindowAttrib( s_window, GLFW_ICONIFIED ) ) + { + std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); + continue; + } + s_redraw(); + if( !glfwGetWindowAttrib( s_window, GLFW_FOCUSED ) ) + { + std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); + } + s_mainThreadTasks->Run(); + } +} + +void Backend::NewFrame( int& w, int& h ) +{ + glfwGetFramebufferSize( s_window, &w, &h ); + m_w = w; + m_h = h; + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); +} + +void Backend::EndFrame() +{ + const ImVec4 clear_color = ImColor( 114, 144, 154 ); + + ImGui::Render(); + glViewport( 0, 0, m_w, m_h ); + glClearColor( clear_color.x, clear_color.y, clear_color.z, clear_color.w ); + glClear( GL_COLOR_BUFFER_BIT ); + ImGui_ImplOpenGL3_RenderDrawData( ImGui::GetDrawData() ); + + // Update and Render additional Platform Windows + // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. + // For this specific demo app we could also call glfwMakeContextCurrent(window) directly) + if( ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable ) + { + GLFWwindow* backup_current_context = glfwGetCurrentContext(); + ImGui::UpdatePlatformWindows(); + ImGui::RenderPlatformWindowsDefault(); + glfwMakeContextCurrent( backup_current_context ); + } + + glfwSwapBuffers( s_window ); +} + +void Backend::SetIcon( uint8_t* data, int w, int h ) +{ + GLFWimage icon; + icon.width = w; + icon.height = h; + icon.pixels = data; + glfwSetWindowIcon( s_window, 1, &icon ); +} + +void Backend::SetTitle( const char* title ) +{ + glfwSetWindowTitle( s_window, title ); +} + +float Backend::GetDpiScale() +{ +#if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 ) + auto monitor = glfwGetWindowMonitor( s_window ); + if( !monitor ) monitor = glfwGetPrimaryMonitor(); + if( monitor ) + { + float x, y; + glfwGetMonitorContentScale( monitor, &x, &y ); + return x; + } +#endif + return 1; +} + +void* Backend::GetNativeWindow() +{ +#ifdef _WIN32 + return (void*)glfwGetWin32Window( s_window ); +#elif defined __linux__ +# ifdef DISPLAY_SERVER_X11 + return (void*)glfwGetX11Window( s_window ); +# elif defined DISPLAY_SERVER_WAYLAND + return (void*)glfwGetWaylandWindow( s_window ); +# endif +#else + return nullptr; +#endif +} diff --git a/profiler/src/ImGuiContext.cpp b/profiler/src/ImGuiContext.cpp new file mode 100644 index 00000000..2858a684 --- /dev/null +++ b/profiler/src/ImGuiContext.cpp @@ -0,0 +1,18 @@ +#include +#include "../../server/TracyStorage.hpp" +#include "ImGuiContext.hpp" + +ImGuiTracyContext::ImGuiTracyContext() + : m_iniFilename( tracy::GetSavePath( "imgui.ini" ) ) +{ + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + io.IniFilename = m_iniFilename.c_str(); + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_DockingEnable; +} + +ImGuiTracyContext::~ImGuiTracyContext() +{ + ImGui::DestroyContext(); +} diff --git a/profiler/src/ImGuiContext.hpp b/profiler/src/ImGuiContext.hpp new file mode 100644 index 00000000..b489cf65 --- /dev/null +++ b/profiler/src/ImGuiContext.hpp @@ -0,0 +1,16 @@ +#ifndef __IMGUICONTEXT_HPP__ +#define __IMGUICONTEXT_HPP__ + +#include + +class ImGuiTracyContext +{ +public: + ImGuiTracyContext(); + ~ImGuiTracyContext(); + +private: + std::string m_iniFilename; +}; + +#endif diff --git a/profiler/src/NativeWindow.cpp b/profiler/src/NativeWindow.cpp deleted file mode 100644 index 94031cdc..00000000 --- a/profiler/src/NativeWindow.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "NativeWindow.hpp" - -#include - -#ifdef _WIN32 -# define GLFW_EXPOSE_NATIVE_WIN32 -# include -#elif defined __linux__ -# ifdef DISPLAY_SERVER_X11 -# define GLFW_EXPOSE_NATIVE_X11 -# elif defined DISPLAY_SERVER_WAYLAND -# define GLFW_EXPOSE_NATIVE_WAYLAND -# else -# error "unsupported linux display server" -# endif -# include -#endif - -extern GLFWwindow* s_glfwWindow; - -void* GetMainWindowNative() -{ -#ifdef _WIN32 - return (void*)glfwGetWin32Window( s_glfwWindow ); -#elif defined __linux__ -# ifdef DISPLAY_SERVER_X11 - return (void*)glfwGetX11Window( s_glfwWindow ); -# elif defined DISPLAY_SERVER_WAYLAND - return (void*)glfwGetWaylandWindow( s_glfwWindow ); -# endif -#else - return nullptr; -#endif -} diff --git a/profiler/src/NativeWindow.hpp b/profiler/src/NativeWindow.hpp deleted file mode 100644 index 499b3395..00000000 --- a/profiler/src/NativeWindow.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __NATIVEWINDOW_HPP__ -#define __NATIVEWINDOW_HPP__ - -void* GetMainWindowNative(); - -#endif diff --git a/profiler/src/main.cpp b/profiler/src/main.cpp index 05356b24..6dde4156 100644 --- a/profiler/src/main.cpp +++ b/profiler/src/main.cpp @@ -4,16 +4,12 @@ #include #include #include -#include "imgui/imgui_impl_glfw.h" -#include "imgui/imgui_impl_opengl3.h" -#include "imgui/imgui_impl_opengl3_loader.h" #include #include #include #include #include #include -#include #include #include #include @@ -54,38 +50,16 @@ #include "icon.hpp" +#include "Backend.hpp" #include "ConnectionHistory.hpp" #include "Filters.hpp" #include "Fonts.hpp" #include "HttpRequest.hpp" -#include "NativeWindow.hpp" +#include "ImGuiContext.hpp" #include "ResolvService.hpp" #include "RunQueue.hpp" -#include "WindowPosition.hpp" -static void glfw_error_callback(int error, const char* description) -{ - fprintf(stderr, "Error %d: %s\n", error, description); -} - -GLFWwindow* s_glfwWindow = nullptr; -static bool s_customTitle = false; -static void SetWindowTitleCallback( const char* title ) -{ - assert( s_glfwWindow ); - char tmp[1024]; - sprintf( tmp, "%s - Tracy Profiler %i.%i.%i", title, tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch ); - glfwSetWindowTitle( s_glfwWindow, tmp ); - s_customTitle = true; -} - -static void DrawContents(); -static void WindowRefreshCallback( GLFWwindow* window ) -{ - DrawContents(); -} - struct ClientData { int64_t time; @@ -123,6 +97,23 @@ static uint8_t* iconPx; static int iconX, iconY; static void* iconTex; static int iconTexSz; +static Backend* bptr; +static bool s_customTitle = false; + +static void SetWindowTitleCallback( const char* title ) +{ + char tmp[1024]; + sprintf( tmp, "%s - Tracy Profiler %i.%i.%i", title, tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch ); + bptr->SetTitle( tmp ); + s_customTitle = true; +} + +static void* GetMainWindowNative() +{ + return bptr->GetNativeWindow(); +} + +static void DrawContents(); void RunOnMainThread( std::function cb, bool forceDelay = false ) { @@ -204,7 +195,6 @@ int main( int argc, char** argv ) } } - WindowPosition winPos; ConnectionHistory connHistory; Filters filters; @@ -223,61 +213,24 @@ int main( int argc, char** argv ) } ); } ); - // Setup window - glfwSetErrorCallback(glfw_error_callback); - if( !glfwInit() ) return 1; -#ifdef DISPLAY_SERVER_WAYLAND - glfwWindowHint(GLFW_ALPHA_BITS, 0); -#else - glfwWindowHint(GLFW_VISIBLE, 0); -#endif - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#if __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - GLFWwindow* window = glfwCreateWindow( winPos.w, winPos.h, title, NULL, NULL); - if( !window ) return 1; - iconPx = stbi_load_from_memory( (const stbi_uc*)Icon_data, Icon_size, &iconX, &iconY, nullptr, 4 ); - { - GLFWimage icon; - icon.width = iconX; - icon.height = iconY; - icon.pixels = iconPx; - glfwSetWindowIcon( window, 1, &icon ); - } - - glfwSetWindowPos( window, winPos.x, winPos.y ); -#ifdef GLFW_MAXIMIZED - if( winPos.maximize ) glfwMaximizeWindow( window ); -#endif - s_glfwWindow = window; - glfwMakeContextCurrent(window); - glfwSwapInterval(1); // Enable vsync - glfwSetWindowRefreshCallback( window, WindowRefreshCallback ); + ImGuiTracyContext imguiContext; + Backend backend( title, DrawContents, &mainThreadTasks ); + backend.SetIcon( iconPx, iconX, iconY ); + bptr = &backend; +#if 0 #ifdef _WIN32 typedef UINT(*GDFS)(void); GDFS getDpiForSystem = nullptr; HMODULE dll = GetModuleHandleW(L"user32.dll"); if( dll != INVALID_HANDLE_VALUE ) getDpiForSystem = (GDFS)GetProcAddress(dll, "GetDpiForSystem"); if( getDpiForSystem ) dpiScale = getDpiForSystem() / 96.f; -#elif defined __linux__ -# if GLFW_VERSION_MAJOR > 3 || ( GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 3 ) - auto monitor = glfwGetWindowMonitor( window ); - if( !monitor ) monitor = glfwGetPrimaryMonitor(); - if( monitor ) - { - float x, y; - glfwGetMonitorContentScale( monitor, &x, &y ); - dpiScale = x; - } -# endif +#endif #endif + dpiScale = backend.GetDpiScale(); const auto envDpiScale = getenv( "TRACY_DPI_SCALE" ); if( envDpiScale ) { @@ -285,17 +238,6 @@ int main( int argc, char** argv ) if( cnv != 0 ) dpiScale = cnv; } - // Setup ImGui binding - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - std::string iniFileName = tracy::GetSavePath( "imgui.ini" ); - io.IniFilename = iniFileName.c_str(); - io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard | ImGuiConfigFlags_DockingEnable; - - ImGui_ImplGlfw_InitForOpenGL( window, true ); - ImGui_ImplOpenGL3_Init( "#version 150" ); - iconTex = tracy::MakeTexture(); SetupDPIScale( dpiScale, s_fixedWidth, s_bigFont, s_smallFont ); @@ -313,57 +255,21 @@ int main( int argc, char** argv ) NFD_Init(); #endif - glfwShowWindow( window ); - - // Main loop - while (!glfwWindowShouldClose(window)) - { - glfwPollEvents(); - if( glfwGetWindowAttrib( window, GLFW_ICONIFIED ) ) - { - std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); - continue; - } - DrawContents(); - if( !glfwGetWindowAttrib( window, GLFW_FOCUSED ) ) - { - std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) ); - } - mainThreadTasks.Run(); - } + backend.Show(); + backend.Run(); if( loadThread.joinable() ) loadThread.join(); if( updateThread.joinable() ) updateThread.join(); if( updateNotesThread.joinable() ) updateNotesThread.join(); view.reset(); -#ifdef GLFW_MAXIMIZED - uint32_t maximized = glfwGetWindowAttrib( window, GLFW_MAXIMIZED ); - if( maximized ) glfwRestoreWindow( window ); -#else - uint32_t maximized = 0; -#endif - winPos.maximize = maximized; - - glfwGetWindowPos( window, &winPos.x, &winPos.y ); - glfwGetWindowSize( window, &winPos.w, &winPos.h ); - tracy::FreeTexture( iconTex, RunOnMainThread ); - - // Cleanup - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(window); + free( iconPx ); #ifndef TRACY_NO_FILESELECTOR NFD_Quit(); #endif - glfwTerminate(); - free( iconPx ); - return 0; } @@ -374,13 +280,8 @@ static void DrawContents() static uint16_t reconnectPort; static bool showFilter = false; - const ImVec4 clear_color = ImColor( 114, 144, 154 ); - int display_w, display_h; - glfwGetFramebufferSize(s_glfwWindow, &display_w, &display_h); - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); + bptr->NewFrame( display_w, display_h ); ImGui::NewFrame(); tracy::MouseFrame(); @@ -391,7 +292,7 @@ static void DrawContents() if( s_customTitle ) { s_customTitle = false; - glfwSetWindowTitle( s_glfwWindow, title ); + bptr->SetTitle( title ); } const auto time = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch() ).count(); @@ -964,23 +865,5 @@ static void DrawContents() ImGui::EndPopup(); } - // Rendering - ImGui::Render(); - glViewport(0, 0, display_w, display_h); - glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - // Update and Render additional Platform Windows - // (Platform functions may change the current OpenGL context, so we save/restore it to make it easier to paste this code elsewhere. - // For this specific demo app we could also call glfwMakeContextCurrent(window) directly) - if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable) - { - GLFWwindow* backup_current_context = glfwGetCurrentContext(); - ImGui::UpdatePlatformWindows(); - ImGui::RenderPlatformWindowsDefault(); - glfwMakeContextCurrent(backup_current_context); - } - - glfwSwapBuffers(s_glfwWindow); + bptr->EndFrame(); }