diff --git a/build.sh b/build.sh index bd35c0a0..d7f0069b 100755 --- a/build.sh +++ b/build.sh @@ -142,20 +142,20 @@ configure() { dependencies git submodule update --init --depth 50 if [[ ! -f "build/meson64/build.ninja" ]]; then - meson build/meson64 --libdir lib/mangohud/lib64 --prefix /usr -Dappend_libdir_mangohud=false ${CONFIGURE_OPTS} + meson build/meson64 --libdir lib/mangohud/lib64 --prefix /usr -Dappend_libdir_mangohud=false $@ ${CONFIGURE_OPTS} fi if [[ ! -f "build/meson32/build.ninja" ]]; then export CC="gcc -m32" export CXX="g++ -m32" export PKG_CONFIG_PATH="/usr/lib32/pkgconfig:/usr/lib/i386-linux-gnu/pkgconfig:/usr/lib/pkgconfig:${PKG_CONFIG_PATH_32}" export LLVM_CONFIG="/usr/bin/llvm-config32" - meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false ${CONFIGURE_OPTS} + meson build/meson32 --libdir lib/mangohud/lib32 --prefix /usr -Dappend_libdir_mangohud=false $@ ${CONFIGURE_OPTS} fi } build() { if [[ ! -f "build/meson64/build.ninja" ]]; then - configure + configure $@ fi DESTDIR="$PWD/build/release" ninja -C build/meson32 install DESTDIR="$PWD/build/release" ninja -C build/meson64 install @@ -243,12 +243,32 @@ usage() { echo -e "\trelease\t\tBuilds a MangoHud release tar package" } -for a in $@; do - case $a in - "") build;; - "pull") git pull;; - "configure") configure;; - "build") build;; +if [[ -z $@ ]]; then + usage no-args +fi + +while [ $# -gt 0 ]; do + OPTS=() + arg="$1" + shift + + while [ $# -gt 0 ] ; do + case $1 in + -*) + OPTS+=("$1") + shift + ;; + *) + break + ;; + esac; + done + + echo -e "\e[1mCommand:\e[92m" $arg "\e[94m"${OPTS[@]}"\e[39m\e[0m" + case $arg in + "pull") git pull ${OPTS[@]};; + "configure") configure ${OPTS[@]};; + "build") build ${OPTS[@]};; "package") package;; "install") install;; "reinstall") reinstall;; @@ -259,8 +279,3 @@ for a in $@; do usage esac done - -if [[ -z $@ ]]; then - usage no-args -fi - diff --git a/data/mangohud.1 b/data/mangohud.1 new file mode 100644 index 00000000..be473871 --- /dev/null +++ b/data/mangohud.1 @@ -0,0 +1,53 @@ +.\" Manpage for mangohud. +.TH mangohud 1 "" "" "mangohud" + +.SH NAME +mangohud \- enable MangoHud on any application + +.SH SYNOPSIS +\fBmangohud\fR COMMAND + +.SH DESCRIPTION +MangoHud is a Vulkan/OpenGL overlay for monitoring FPS, temperatures, CPU/GPU load and more. + +.SH USAGE +MangoHud can be enabled for Vulkan applications by setting \fBMANGOHUD=1\fR as envrionment variable. +.br +To load MangoHud for any application, including OpenGL applications, the \fBmangohud\fR executable can be used. It preloads a library via ld into the application. +.br +Note: some OpenGL applications may also need dlsym hooking. This can be done by setting \fBMANGOHUD_DLSYM=1\fR as envrionment variable. + +.SH CONFIG +MangoHud comes with a config file which can be used to set configuration options globally or per application. The priorities of different config files are: +.LP +.RS 4 +/path/to/application/MangoHud.conf +.br +$XDG_CONFIG_HOME/MangoHud/{application_name}.conf +.br +$XDG_CONFIG_HOME/MangoHud/MangoHud.conf +.RS -4 +.LP +An example config file is located in /usr/share/doc/mangohud/MangoHud.conf, containing all available options. +.LP +A custom config file location can also be specified with the \fBMANGOHUD_CONFIGFILE\fR envrionment variable. +.br +Config options can also be set with the \fBMANGOHUD_CONFIG\fR envrionment variable. This takes priority over any config file. + +.SH EXAMPLES +OpenGL: \fBmangohud glxgears\fR +.br +Vulkan: \fBMANGOHUD=1 vkcube\fR +.br +Steam: set your launch option to \fBmangohud %command%\fR +.br +Lutris: add \fBmangohud\fR to the Command prefix setting +.br +OpenGL with dlsym: \fBMANGOHUD_DLSYM=1 mangohud glxgears\fR +.br +Custom config options: \fBMANGOHUD_CONFIG="gpu_stats=0,font_size=12" mangohud glxgears\fR + +.SH ABOUT +MangoHud development takes place at \fIhttps://github.com/flightlessmango/MangoHud\fR. +.br +Benchmarks created with MangoHud can be uploaded to \fIhttps://flightlessmango.com\fR. diff --git a/data/meson.build b/data/meson.build new file mode 100644 index 00000000..2a77575c --- /dev/null +++ b/data/meson.build @@ -0,0 +1,4 @@ +install_man( + files('mangohud.1'), + install_dir: join_paths(get_option('mandir'), 'man1'), +) diff --git a/meson.build b/meson.build index 01f210ac..c880a5c3 100644 --- a/meson.build +++ b/meson.build @@ -208,3 +208,4 @@ dearimgui_sp = subproject('dearimgui') dearimgui_dep = dearimgui_sp.get_variable('dearimgui_dep') subdir('src') +subdir('data') diff --git a/src/dbus.cpp b/src/dbus.cpp index a7c23911..a6fc76f8 100644 --- a/src/dbus.cpp +++ b/src/dbus.cpp @@ -143,7 +143,7 @@ namespace dbusmgr { bool dbus_manager::get_media_player_metadata(metadata& meta, std::string name) { if (name == "") name = m_active_player; if (name == "") return false; - meta.clear(); + meta = {}; dbus_get_player_property(*this, meta, name.c_str(), "Metadata"); dbus_get_player_property(*this, meta, name.c_str(), "PlaybackStatus"); meta.valid = (meta.artists.size() || !meta.title.empty()); diff --git a/src/dbus_info.h b/src/dbus_info.h index f1b25332..36e48dcb 100644 --- a/src/dbus_info.h +++ b/src/dbus_info.h @@ -26,14 +26,6 @@ struct metadata { bool valid = false; bool got_song_data = false; bool got_playback_data = false; - - void clear() { - artists.clear(); - title.clear(); - album.clear(); - artUrl.clear(); - valid = false; - } }; struct mutexed_metadata { diff --git a/src/logging.cpp b/src/logging.cpp index 04c69d52..143801aa 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -156,4 +156,9 @@ void Logger::notify_data_valid() { void Logger::upload_last_log() { if(m_log_files.empty()) return; std::thread(upload_file, m_log_files.back()).detach(); +} + +void Logger::upload_last_logs() { + if(m_log_files.empty()) return; + std::thread(upload_files, m_log_files).detach(); } \ No newline at end of file diff --git a/src/logging.h b/src/logging.h index 38478fbe..7bcfc0a5 100644 --- a/src/logging.h +++ b/src/logging.h @@ -49,6 +49,7 @@ public: void clear_log_data() noexcept { m_log_array.clear(); } void upload_last_log(); + void upload_last_logs(); private: std::vector m_log_array; std::vector m_log_files; diff --git a/src/overlay.cpp b/src/overlay.cpp index 47417f57..76fba58d 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -229,6 +229,7 @@ static void unmap_object(uint64_t obj) void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font) { auto& io = ImGui::GetIO(); + ImGui::GetIO().FontGlobalScale = params.font_scale; // set here too so ImGui::CalcTextSize is correct float font_size = params.font_size; if (font_size < FLT_EPSILON) font_size = 24; @@ -669,6 +670,8 @@ void init_gpu_stats(uint32_t& vendorID, overlay_params& params) params.enabled[OVERLAY_PARAM_ENABLED_gpu_stats] = false; } } + if (!params.permit_upload) + printf("MANGOHUD: Uploading is disabled (permit_upload = 0)\n"); } void init_system_info(){ @@ -797,7 +800,7 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par reload_cfg_press = now; } } - + if (params.permit_upload && elapsedUpload >= keyPressDelay){ #ifdef HAVE_X11 pressed = keys_are_pressed(params.upload_log); @@ -809,6 +812,17 @@ void check_keybinds(struct swapchain_stats& sw_stats, struct overlay_params& par logger->upload_last_log(); } } + if (params.permit_upload && elapsedUpload >= keyPressDelay){ +#ifdef HAVE_X11 + pressed = keys_are_pressed(params.upload_logs); +#else + pressed = false; +#endif + if (pressed){ + last_upload_press = now; + logger->upload_last_logs(); + } + } } void calculate_benchmark_data(void *params_void){ @@ -1132,11 +1146,16 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if(not logger) logger = std::make_unique(¶ms); uint32_t f_idx = (data.n_frames - 1) % ARRAY_SIZE(data.frames_stats); uint64_t frame_timing = data.frames_stats[f_idx].stats[OVERLAY_PLOTS_frame_timing]; - static float char_width = ImGui::CalcTextSize("A").x; + static float ralign_width = 0, old_scale = 0; window_size = ImVec2(params.width, params.height); unsigned height = ImGui::GetIO().DisplaySize.y; auto now = Clock::now(); + if (old_scale != params.font_scale) { + ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + old_scale = params.font_scale; + } + if (!params.no_display){ ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); if (params.enabled[OVERLAY_PARAM_ENABLED_version]){ @@ -1156,14 +1175,14 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& gpu_text = params.gpu_text.c_str(); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.gpu_color), "%s", gpu_text); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", gpu_info.load); + right_aligned_text(ralign_width, "%i", gpu_info.load); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); // ImGui::SameLine(150); // ImGui::Text("%s", "%"); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", gpu_info.temp); + right_aligned_text(ralign_width, "%i", gpu_info.temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1171,7 +1190,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", gpu_info.CoreClock); + right_aligned_text(ralign_width, "%i", gpu_info.CoreClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1179,7 +1198,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", gpu_info.powerUsage); + right_aligned_text(ralign_width, "%i", gpu_info.powerUsage); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("W"); @@ -1195,7 +1214,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& cpu_text = params.cpu_text.c_str(); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.cpu_color), "%s", cpu_text); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%d", data.total_cpu); + right_aligned_text(ralign_width, "%d", data.total_cpu); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); // ImGui::SameLine(150); @@ -1203,7 +1222,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", cpuStats.GetCPUDataTotal().temp); + right_aligned_text(ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -1220,11 +1239,11 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.cpu_color),"%i", i); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", int(cpuData.percent)); + right_aligned_text(ralign_width, "%i", int(cpuData.percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", cpuData.mhz); + right_aligned_text(ralign_width, "%i", cpuData.mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1245,7 +1264,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_read]){ ImGui::TableNextCell(); float val = data.io.diff.read * 1000000 / sampling; - right_aligned_text(char_width * 4, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1254,7 +1273,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& if (params.enabled[OVERLAY_PARAM_ENABLED_io_write]){ ImGui::TableNextCell(); float val = data.io.diff.write * 1000000 / sampling; - right_aligned_text(char_width * 4, val < 100 ? "%.1f" : "%.f", val); + right_aligned_text(ralign_width, val < 100 ? "%.1f" : "%.f", val); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("MiB/s"); @@ -1265,14 +1284,14 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.vram_color), "VRAM"); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%.1f", gpu_info.memoryUsed); + right_aligned_text(ralign_width, "%.1f", gpu_info.memoryUsed); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); ImGui::PopFont(); if (params.enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%i", gpu_info.MemClock); + right_aligned_text(ralign_width, "%i", gpu_info.MemClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("MHz"); @@ -1283,7 +1302,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.ram_color), "RAM"); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%.1f", memused); + right_aligned_text(ralign_width, "%.1f", memused); ImGui::SameLine(0,1.0f); ImGui::PushFont(data.font1); ImGui::Text("GiB"); @@ -1293,13 +1312,13 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::TableNextRow(); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.engine_color), "%s", is_vulkan ? data.engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%.0f", data.fps); + right_aligned_text(ralign_width, "%.0f", data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("FPS"); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(char_width * 4, "%.1f", 1000 / data.fps); + right_aligned_text(ralign_width, "%.1f", 1000 / data.fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(data.font1); ImGui::Text("ms"); @@ -2504,7 +2523,7 @@ static VkResult overlay_QueuePresentKHR( } using namespace std::chrono_literals; - + if (fps_limit_stats.targetFrameTime > 0s){ fps_limit_stats.frameStart = Clock::now(); FpsLimiter(fps_limit_stats); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 447eac25..bdd76a15 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -113,11 +113,18 @@ parse_upload_log(const char *str) return parse_string_to_keysym_vec(str); } +static std::vector +parse_upload_logs(const char *str) +{ + return parse_string_to_keysym_vec(str); +} + #else #define parse_toggle_hud(x) {} #define parse_toggle_logging(x) {} #define parse_reload_cfg(x) {} #define parse_upload_log(x) {} +#define parse_upload_logs(x) {} #endif static uint32_t @@ -479,6 +486,7 @@ parse_overlay_config(struct overlay_params *params, params->toggle_logging = { XK_Shift_L, XK_F2 }; params->reload_cfg = { XK_Shift_L, XK_F4 }; params->upload_log = { XK_Shift_L, XK_F3 }; + params->upload_logs = { XK_Control_L, XK_F3 }; #endif // first pass with env var @@ -573,11 +581,6 @@ parse_overlay_config(struct overlay_params *params, #ifdef HAVE_DBUS if (params->enabled[OVERLAY_PARAM_ENABLED_media_player]) { - // lock mutexes for config file change notifier thread - { - std::lock_guard lk(main_metadata.mtx); - main_metadata.meta.clear(); - } dbusmgr::dbus_mgr.init(params->media_player_name); } else { dbusmgr::dbus_mgr.deinit(); diff --git a/src/overlay_params.h b/src/overlay_params.h index f721f0fe..5294d391 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -70,6 +70,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(toggle_logging) \ OVERLAY_PARAM_CUSTOM(reload_cfg) \ OVERLAY_PARAM_CUSTOM(upload_log) \ + OVERLAY_PARAM_CUSTOM(upload_logs) \ OVERLAY_PARAM_CUSTOM(offset_x) \ OVERLAY_PARAM_CUSTOM(offset_y) \ OVERLAY_PARAM_CUSTOM(background_alpha) \ @@ -165,6 +166,7 @@ struct overlay_params { std::vector toggle_logging; std::vector reload_cfg; std::vector upload_log; + std::vector upload_logs; std::string time_format, output_file; std::string pci_dev; std::string media_player_name;