diff --git a/profiler/src/Backend.hpp b/profiler/src/Backend.hpp index 2f4262a3..f4a031bb 100644 --- a/profiler/src/Backend.hpp +++ b/profiler/src/Backend.hpp @@ -11,7 +11,7 @@ class RunQueue; class Backend { public: - Backend( const char* title, const std::function& redraw, RunQueue* mainThreadTasks ); + Backend( const char* title, const std::function& redraw, const std::function& scaleChanged, RunQueue* mainThreadTasks ); ~Backend(); void Show(); diff --git a/profiler/src/BackendGlfw.cpp b/profiler/src/BackendGlfw.cpp index f3525ee9..51897111 100644 --- a/profiler/src/BackendGlfw.cpp +++ b/profiler/src/BackendGlfw.cpp @@ -60,7 +60,7 @@ static void glfw_window_iconify_callback( GLFWwindow*, int iconified ) } -Backend::Backend( const char* title, const std::function& redraw, RunQueue* mainThreadTasks ) +Backend::Backend( const char* title, const std::function& redraw, const std::function& scaleChanged, RunQueue* mainThreadTasks ) { glfwSetErrorCallback( glfw_error_callback ); if( !glfwInit() ) exit( 1 ); diff --git a/profiler/src/BackendWayland.cpp b/profiler/src/BackendWayland.cpp index feea6379..fa5b55fa 100644 --- a/profiler/src/BackendWayland.cpp +++ b/profiler/src/BackendWayland.cpp @@ -160,10 +160,12 @@ constexpr ImGuiKey s_keyTable[] = { }; static std::function s_redraw; +static std::function s_scaleChanged; static RunQueue* s_mainThreadTasks; static struct wl_display* s_dpy; static struct wl_compositor* s_comp; +static uint32_t s_comp_version; static struct wl_surface* s_surf; static struct wl_egl_window* s_eglWin; static struct wl_shm* s_shm; @@ -194,6 +196,7 @@ struct Output { int32_t scale; wl_output* obj; + bool entered; }; static std::unordered_map> s_output; static int s_maxScale = 1; @@ -207,6 +210,19 @@ static uint64_t s_time; static wl_fixed_t s_wheelAxisX, s_wheelAxisY; static bool s_wheel; +static void RecomputeScale() +{ + // On wl_compositor >= 6 the scale is sent explicitly via wl_surface.preferred_buffer_scale. + if ( s_comp_version >= 6 ) return; + + int max = 1; + for( auto& out : s_output ) + { + if( out.second->entered && out.second->scale > max ) max = out.second->scale; + } + s_maxScale = max; +} + static void PointerEnter( void*, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surf, wl_fixed_t sx, wl_fixed_t sy ) { wl_pointer_set_cursor( pointer, serial, s_cursorSurf, s_cursorX, s_cursorY ); @@ -471,12 +487,7 @@ static void OutputMode( void*, struct wl_output* output, uint32_t flags, int32_t static void OutputDone( void*, struct wl_output* output ) { - int max = 1; - for( auto& out : s_output ) - { - if( out.second->scale > max ) max = out.second->scale; - } - s_maxScale = max; + RecomputeScale(); } static void OutputScale( void* data, struct wl_output* output, int32_t scale ) @@ -506,7 +517,8 @@ static void RegistryGlobal( void*, struct wl_registry* reg, uint32_t name, const { if( strcmp( interface, wl_compositor_interface.name ) == 0 ) { - s_comp = (wl_compositor*)wl_registry_bind( reg, name, &wl_compositor_interface, 4 ); + s_comp_version = version; + s_comp = (wl_compositor*)wl_registry_bind( reg, name, &wl_compositor_interface, version >= 6 ? 6 : 4 ); } else if( strcmp( interface, wl_shm_interface.name ) == 0 ) { @@ -529,7 +541,7 @@ static void RegistryGlobal( void*, struct wl_registry* reg, uint32_t name, const else if( strcmp( interface, wl_output_interface.name ) == 0 ) { auto output = (wl_output*)wl_registry_bind( reg, name, &wl_output_interface, 2 ); - auto ptr = std::make_unique( Output { 1, output } ); + auto ptr = std::make_unique( Output { 1, output, false } ); wl_output_add_listener( output, &outputListener, ptr.get() ); s_output.emplace( name, std::move( ptr ) ); } @@ -545,6 +557,7 @@ static void RegistryGlobalRemove( void*, struct wl_registry* reg, uint32_t name if( it == s_output.end() ) return; wl_output_destroy( it->second->obj ); s_output.erase( it ); + RecomputeScale(); } constexpr struct wl_registry_listener registryListener = { @@ -603,6 +616,43 @@ constexpr struct xdg_toplevel_listener toplevelListener = { .close = XdgToplevelClose }; +static void SurfaceEnter( void*, struct wl_surface* surface, struct wl_output* output ) +{ + for ( auto& out : s_output ) + { + if ( out.second->obj == output ) + { + out.second->entered = true; + RecomputeScale(); + break; + } + } +} + +static void SurfaceLeave( void*, struct wl_surface* surface, struct wl_output* output ) +{ + for ( auto& out : s_output ) + { + if ( out.second->obj == output ) + { + out.second->entered = false; + RecomputeScale(); + break; + } + } +} + +static void SurfacePreferredBufferScale( void*, struct wl_surface* surface, int32_t scale ) +{ + s_maxScale = scale; +} + +constexpr struct wl_surface_listener surfaceListener = { + .enter = SurfaceEnter, + .leave = SurfaceLeave, + .preferred_buffer_scale = SurfacePreferredBufferScale, +}; + static void SetupCursor() { auto env_xcursor_theme = getenv( "XCURSOR_THEME" ); @@ -624,9 +674,10 @@ static void SetupCursor() s_cursorY = cursor->images[0]->hotspot_y / s_maxScale; } -Backend::Backend( const char* title, const std::function& redraw, RunQueue* mainThreadTasks ) +Backend::Backend( const char* title, const std::function& redraw, const std::function& scaleChanged, RunQueue* mainThreadTasks ) { s_redraw = redraw; + s_scaleChanged = scaleChanged; s_mainThreadTasks = mainThreadTasks; s_w = m_winPos.w; s_h = m_winPos.h; @@ -645,6 +696,7 @@ Backend::Backend( const char* title, const std::function& redraw, RunQue if( !s_seat ) { fprintf( stderr, "No wayland seat!\n" ); exit( 1 ); } s_surf = wl_compositor_create_surface( s_comp ); + wl_surface_add_listener( s_surf, &surfaceListener, nullptr ); s_eglWin = wl_egl_window_create( s_surf, m_winPos.w, m_winPos.h ); s_xdgSurf = xdg_wm_base_get_xdg_surface( s_wm, s_surf ); xdg_surface_add_listener( s_xdgSurf, &xdgSurfaceListener, nullptr ); @@ -781,6 +833,7 @@ void Backend::NewFrame( int& w, int& h ) { if( s_prevScale != s_maxScale ) { + s_scaleChanged( s_maxScale ); SetupCursor(); wl_surface_set_buffer_scale( s_surf, s_maxScale ); s_prevScale = s_maxScale; diff --git a/profiler/src/main.cpp b/profiler/src/main.cpp index 3e386525..c44ca768 100644 --- a/profiler/src/main.cpp +++ b/profiler/src/main.cpp @@ -95,6 +95,7 @@ static ConnectionHistory* connHist; static std::atomic viewShutdown { ViewShutdown::False }; static double animTime = 0; static float dpiScale = 1.f; +static bool dpiScaleOverriddenFromEnv = false; static Filters* filt; static RunQueue mainThreadTasks; static uint32_t updateVersion = 0; @@ -197,6 +198,15 @@ static bool SaveConfig() return true; } +static void ScaleChanged( float scale ) +{ + if ( dpiScaleOverriddenFromEnv ) return; + if ( dpiScale == scale ) return; + + dpiScale = scale; + SetupDPIScale( dpiScale, s_fixedWidth, s_bigFont, s_smallFont ); +} + int main( int argc, char** argv ) { sprintf( title, "Tracy Profiler %i.%i.%i", tracy::Version::Major, tracy::Version::Minor, tracy::Version::Patch ); @@ -297,7 +307,7 @@ int main( int argc, char** argv ) LoadConfig(); ImGuiTracyContext imguiContext; - Backend backend( title, DrawContents, &mainThreadTasks ); + Backend backend( title, DrawContents, ScaleChanged, &mainThreadTasks ); tracy::InitTexture(); iconTex = tracy::MakeTexture(); zigzagTex = tracy::MakeTexture( true ); @@ -310,7 +320,11 @@ int main( int argc, char** argv ) if( envDpiScale ) { const auto cnv = atof( envDpiScale ); - if( cnv != 0 ) dpiScale = cnv; + if( cnv != 0 ) + { + dpiScale = cnv; + dpiScaleOverriddenFromEnv = true; + } } SetupDPIScale( dpiScale, s_fixedWidth, s_bigFont, s_smallFont );