diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index 4ada82de..c6a4ac43 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -117,7 +117,7 @@ void imgui_create(void *ctx) // Setup Dear ImGui style ImGui::StyleColorsDark(); //ImGui::StyleColorsClassic(); - convert_colors(false, sw_stats, params); + HUDElements.convert_colors(false, params); glGetIntegerv (GL_VIEWPORT, last_vp.v); glGetIntegerv (GL_SCISSOR_BOX, last_sb.v); @@ -175,6 +175,8 @@ void imgui_render(unsigned int width, unsigned int height) ImGuiContext *saved_ctx = ImGui::GetCurrentContext(); ImGui::SetCurrentContext(state.imgui_ctx); ImGui::GetIO().DisplaySize = ImVec2(width, height); + if (HUDElements.colors.update) + HUDElements.convert_colors(params); ImGui_ImplOpenGL3_NewFrame(); ImGui::NewFrame(); diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 1142ea27..5f0c492a 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1,9 +1,90 @@ #include +#include #include "hud_elements.h" #include "cpu.h" #include "memory.h" #include "mesa/util/macros.h" +// Cut from https://github.com/ocornut/imgui/pull/2943 +// Probably move to ImGui +float SRGBToLinear(float in) +{ + if (in <= 0.04045f) + return in / 12.92f; + else + return powf((in + 0.055f) / 1.055f, 2.4f); +} + +float LinearToSRGB(float in) +{ + if (in <= 0.0031308f) + return in * 12.92f; + else + return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; +} + +ImVec4 SRGBToLinear(ImVec4 col) +{ + col.x = SRGBToLinear(col.x); + col.y = SRGBToLinear(col.y); + col.z = SRGBToLinear(col.z); + // Alpha component is already linear + + return col; +} + +ImVec4 LinearToSRGB(ImVec4 col) +{ + col.x = LinearToSRGB(col.x); + col.y = LinearToSRGB(col.y); + col.z = LinearToSRGB(col.z); + // Alpha component is already linear + + return col; +} + +void HudElements::convert_colors(struct overlay_params& params) +{ + HUDElements.colors.update = false; + auto convert = [](unsigned color) -> ImVec4 { + ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); + if (HUDElements.colors.convert) + return SRGBToLinear(fc); + return fc; + }; + + HUDElements.colors.cpu = convert(params.cpu_color); + HUDElements.colors.gpu = convert(params.gpu_color); + HUDElements.colors.vram = convert(params.vram_color); + HUDElements.colors.ram = convert(params.ram_color); + HUDElements.colors.engine = convert(params.engine_color); + HUDElements.colors.io = convert(params.io_color); + HUDElements.colors.frametime = convert(params.frametime_color); + HUDElements.colors.background = convert(params.background_color); + HUDElements.colors.text = convert(params.text_color); + HUDElements.colors.media_player = convert(params.media_player_color); + HUDElements.colors.wine = convert(params.wine_color); + HUDElements.colors.gpu_load_high = convert(params.gpu_load_color[0]); + HUDElements.colors.gpu_load_med = convert(params.gpu_load_color[1]); + HUDElements.colors.gpu_load_low = convert(params.gpu_load_color[2]); + HUDElements.colors.cpu_load_high = convert(params.cpu_load_color[0]); + HUDElements.colors.cpu_load_med = convert(params.cpu_load_color[1]); + HUDElements.colors.cpu_load_low = convert(params.cpu_load_color[2]); + + ImGuiStyle& style = ImGui::GetStyle(); + style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); + style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); + style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); + style.Colors[ImGuiCol_Text] = convert(params.text_color); + style.CellPadding.y = params.cellpadding_y * real_font_size.y; +} + +void HudElements::convert_colors(bool do_conv, struct overlay_params& params) +{ + HUDElements.colors.convert = do_conv; + convert_colors(params); +} + void HudElements::time(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_time]){ ImGui::TableNextRow(); @@ -23,56 +104,56 @@ void HudElements::gpu_stats(){ ImGui::TableNextRow(); const char* gpu_text; if (HUDElements.params->gpu_text.empty()) - gpu_text = "GPU"; + gpu_text = "GPU"; else - gpu_text = HUDElements.params->gpu_text.c_str(); - ImGui::TextColored(HUDElements.sw_stats->colors.gpu, "%s", gpu_text); + gpu_text = HUDElements.params->gpu_text.c_str(); + ImGui::TextColored(HUDElements.colors.gpu, "%s", gpu_text); ImGui::TableNextCell(); - auto text_color = HUDElements.sw_stats->colors.text; + auto text_color = HUDElements.colors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_load_change]){ - struct LOAD_DATA gpu_data = {HUDElements.sw_stats->colors.gpu_load_high, - HUDElements.sw_stats->colors.gpu_load_med, - HUDElements.sw_stats->colors.gpu_load_low, - HUDElements.params->gpu_load_value[0], - HUDElements.params->gpu_load_value[1] - }; - - - auto load_color = change_on_load_temp(gpu_data, gpu_info.load); - right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(load_color,"%%"); + struct LOAD_DATA gpu_data = { + HUDElements.colors.gpu_load_high, + HUDElements.colors.gpu_load_med, + HUDElements.colors.gpu_load_low, + HUDElements.params->gpu_load_value[0], + HUDElements.params->gpu_load_value[1] + }; + + auto load_color = change_on_load_temp(gpu_data, gpu_info.load); + right_aligned_text(load_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(load_color,"%%"); } else { - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load); - ImGui::SameLine(0, 1.0f); - ImGui::TextColored(text_color,"%%"); - // ImGui::SameLine(150); - // ImGui::Text("%s", "%"); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.load); + ImGui::SameLine(0, 1.0f); + ImGui::TextColored(text_color,"%%"); + // ImGui::SameLine(150); + // ImGui::Text("%s", "%"); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_temp]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp); - ImGui::SameLine(0, 1.0f); - ImGui::Text("°C"); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.temp); + ImGui::SameLine(0, 1.0f); + ImGui::Text("°C"); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock] || HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) - ImGui::TableNextRow(); + ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_core_clock]){ - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MHz"); - ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.CoreClock); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MHz"); + ImGui::PopFont(); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_power]) { - ImGui::TableNextCell(); - right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage); - ImGui::SameLine(0, 1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("W"); - ImGui::PopFont(); + ImGui::TableNextCell(); + right_aligned_text(text_color, HUDElements.ralign_width, "%i", gpu_info.powerUsage); + ImGui::SameLine(0, 1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("W"); + ImGui::PopFont(); } } } @@ -82,22 +163,23 @@ void HudElements::cpu_stats(){ ImGui::TableNextRow(); const char* cpu_text; if (HUDElements.params->cpu_text.empty()) - cpu_text = "CPU"; + cpu_text = "CPU"; else - cpu_text = HUDElements.params->cpu_text.c_str(); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "%s", cpu_text); + cpu_text = HUDElements.params->cpu_text.c_str(); + + ImGui::TextColored(HUDElements.colors.cpu, "%s", cpu_text); ImGui::TableNextCell(); - auto text_color = HUDElements.sw_stats->colors.text; + auto text_color = HUDElements.colors.text; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_load_change]){ int cpu_load_percent = int(cpuStats.GetCPUDataTotal().percent); - struct LOAD_DATA cpu_data = {HUDElements.sw_stats->colors.cpu_load_high, - HUDElements.sw_stats->colors.cpu_load_med, - HUDElements.sw_stats->colors.cpu_load_low, - HUDElements.params->cpu_load_value[0], - HUDElements.params->cpu_load_value[1] - }; - - + struct LOAD_DATA cpu_data = { + HUDElements.colors.cpu_load_high, + HUDElements.colors.cpu_load_med, + HUDElements.colors.cpu_load_low, + HUDElements.params->cpu_load_value[0], + HUDElements.params->cpu_load_value[1] + }; + auto load_color = change_on_load_temp(cpu_data, cpu_load_percent); right_aligned_text(load_color, HUDElements.ralign_width, "%d", cpu_load_percent); ImGui::SameLine(0, 1.0f); @@ -111,7 +193,7 @@ void HudElements::cpu_stats(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_temp]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().temp); ImGui::SameLine(0, 1.0f); ImGui::Text("°C"); } @@ -119,7 +201,7 @@ void HudElements::cpu_stats(){ ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_mhz]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().cpu_mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -127,7 +209,7 @@ void HudElements::cpu_stats(){ } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_cpu_power]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuStats.GetCPUDataTotal().power); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("W"); @@ -142,17 +224,17 @@ void HudElements::core_load(){ for (const CPUData &cpuData : cpuStats.GetCPUData()) { ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu, "CPU"); + ImGui::TextColored(HUDElements.colors.cpu, "CPU"); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.cpu,"%i", i); + ImGui::TextColored(HUDElements.colors.cpu,"%i", i); ImGui::PopFont(); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent)); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", int(cpuData.percent)); ImGui::SameLine(0, 1.0f); ImGui::Text("%%"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", cpuData.mhz); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", cpuData.mhz); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -166,29 +248,29 @@ void HudElements::io_stats(){ auto sampling = HUDElements.params->fps_sampling_period; ImGui::TableNextRow(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RD"); + ImGui::TextColored(HUDElements.colors.io, "IO RD"); else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO RW"); + ImGui::TextColored(HUDElements.colors.io, "IO RW"); else if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write] && !HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]) - ImGui::TextColored(HUDElements.sw_stats->colors.io, "IO WR"); + ImGui::TextColored(HUDElements.colors.io, "IO WR"); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_read]){ - ImGui::TableNextCell(); - float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling; - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.read * 1000000 / sampling; + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); } if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_io_write]){ - ImGui::TableNextCell(); - float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling; - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); - ImGui::SameLine(0,1.0f); - ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("MiB/s"); - ImGui::PopFont(); + ImGui::TableNextCell(); + float val = HUDElements.sw_stats->io.diff.write * 1000000 / sampling; + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, val < 100 ? "%.1f" : "%.f", val); + ImGui::SameLine(0,1.0f); + ImGui::PushFont(HUDElements.sw_stats->font1); + ImGui::Text("MiB/s"); + ImGui::PopFont(); } } } @@ -196,16 +278,16 @@ void HudElements::io_stats(){ void HudElements::vram(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vram]){ ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.vram, "VRAM"); + ImGui::TextColored(HUDElements.colors.vram, "VRAM"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", gpu_info.memoryUsed); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("GiB"); ImGui::PopFont(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_mem_clock]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%i", gpu_info.MemClock); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("MHz"); @@ -214,12 +296,12 @@ void HudElements::vram(){ } } void HudElements::ram(){ -#ifdef __gnu_linux__ +#ifdef __gnu_linux__ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_ram]){ ImGui::TableNextRow(); - ImGui::TextColored(HUDElements.sw_stats->colors.ram, "RAM"); + ImGui::TextColored(HUDElements.colors.ram, "RAM"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", memused); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", memused); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("GiB"); @@ -232,18 +314,18 @@ void HudElements::fps(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps]){ ImGui::TableNextRow(); if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_fps] && HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); } - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.is_vulkan ? HUDElements.sw_stats->engineName.c_str() : "OpenGL"); ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.0f", HUDElements.sw_stats->fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("FPS"); ImGui::PopFont(); if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_frametime]){ ImGui::TableNextCell(); - right_aligned_text(HUDElements.sw_stats->colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%.1f", 1000 / HUDElements.sw_stats->fps); ImGui::SameLine(0, 1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); ImGui::Text("ms"); @@ -256,33 +338,34 @@ void HudElements::gpu_name(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_gpu_name] && !HUDElements.sw_stats->gpuName.empty()){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.sw_stats->gpuName.c_str()); ImGui::PopFont(); } } + void HudElements::engine_version(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_engine_version]){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); if (HUDElements.is_vulkan) { if ((HUDElements.sw_stats->engineName == "DXVK" || HUDElements.sw_stats->engineName == "VKD3D")){ - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s/%d.%d.%d", HUDElements.sw_stats->engineVersion.c_str(), HUDElements.sw_stats->version_vk.major, HUDElements.sw_stats->version_vk.minor, HUDElements.sw_stats->version_vk.patch); } else { - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%d.%d.%d", HUDElements.sw_stats->version_vk.major, HUDElements.sw_stats->version_vk.minor, HUDElements.sw_stats->version_vk.patch); } } else { - ImGui::TextColored(HUDElements.sw_stats->colors.engine, - "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, - HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); + ImGui::TextColored(HUDElements.colors.engine, + "%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor, + HUDElements.sw_stats->version_gl.is_gles ? " ES" : ""); } ImGui::PopFont(); } @@ -292,7 +375,7 @@ void HudElements::vulkan_driver(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_vulkan_driver] && !HUDElements.sw_stats->driverName.empty()){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, + ImGui::TextColored(HUDElements.colors.engine, "%s", HUDElements.sw_stats->driverName.c_str()); ImGui::PopFont(); } @@ -302,7 +385,7 @@ void HudElements::arch(){ if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_arch]){ ImGui::TableNextRow(); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "" MANGOHUD_ARCH); + ImGui::TextColored(HUDElements.colors.engine, "%s", "" MANGOHUD_ARCH); ImGui::PopFont(); } } @@ -312,7 +395,7 @@ void HudElements::wine(){ ImGui::TableNextRow(); if (!wineVersion.empty()){ ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.wine, "%s", wineVersion.c_str()); + ImGui::TextColored(HUDElements.colors.wine, "%s", wineVersion.c_str()); ImGui::PopFont(); } } @@ -323,7 +406,7 @@ void HudElements::frame_timing(){ ImGui::TableNextRow(); ImGui::Dummy(ImVec2(0.0f, real_font_size.y)); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "Frametime"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "Frametime"); ImGui::PopFont(); ImGui::TableNextRow(); char hash[40]; @@ -334,20 +417,20 @@ void HudElements::frame_timing(){ double min_time = 0.0f; double max_time = 50.0f; if (HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ - ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, + ImGui::PlotHistogram(hash, get_time_stat, HUDElements.sw_stats, ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, NULL, min_time, max_time, ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); } else { - ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, - ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, - NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); + ImGui::PlotLines(hash, get_time_stat, HUDElements.sw_stats, + ARRAY_SIZE(HUDElements.sw_stats->frames_stats), 0, + NULL, min_time, max_time, + ImVec2(ImGui::GetContentRegionAvailWidth() * 2.5, 50)); } ImGui::PopStyleColor(); ImGui::SameLine(0,1.0f); ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); //frame_timing / 1000.f); + ImGui::Text("%.1f ms", 1000 / HUDElements.sw_stats->fps); ImGui::PopFont(); } } @@ -378,6 +461,7 @@ void HudElements::graphs(){ { arr.push_back(0); } + if (value == "cpu_load"){ for (auto& it : graph_data){ arr.push_back(float(it.cpu_load)); @@ -385,7 +469,7 @@ void HudElements::graphs(){ } HUDElements.max = 100; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Load"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Load"); ImGui::PopFont(); } @@ -396,7 +480,7 @@ void HudElements::graphs(){ } HUDElements.max = 100; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Load"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Load"); ImGui::PopFont(); } @@ -409,10 +493,11 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.cpu_temp_max) HUDElements.cpu_temp_max = arr.back(); + HUDElements.max = HUDElements.cpu_temp_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "CPU Temp"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "CPU Temp"); ImGui::PopFont(); } @@ -425,13 +510,14 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_temp_max) HUDElements.gpu_temp_max = arr.back(); + HUDElements.max = HUDElements.gpu_temp_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Temp"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Temp"); ImGui::PopFont(); } - + if (value == "gpu_core_clock"){ for (auto& it : graph_data){ arr.push_back(float(it.gpu_core_clock)); @@ -439,10 +525,11 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_core_max) HUDElements.gpu_core_max = arr.back(); + HUDElements.max = HUDElements.gpu_core_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Core Clock"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Core Clock"); ImGui::PopFont(); } @@ -453,22 +540,24 @@ void HudElements::graphs(){ } if (int(arr.back()) > HUDElements.gpu_mem_max) HUDElements.gpu_mem_max = arr.back(); + HUDElements.max = HUDElements.gpu_mem_max; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "GPU Mem Clock"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "GPU Mem Clock"); ImGui::PopFont(); } - + if (value == "vram"){ for (auto& it : graph_data){ arr.push_back(float(it.gpu_vram_used)); arr.erase(arr.begin()); } + HUDElements.max = gpu_info.memoryTotal; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "VRAM"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "VRAM"); ImGui::PopFont(); } @@ -479,12 +568,14 @@ void HudElements::graphs(){ arr.push_back(float(it.ram_used)); arr.erase(arr.begin()); } + HUDElements.max = memmax; HUDElements.min = 0; ImGui::PushFont(HUDElements.sw_stats->font1); - ImGui::TextColored(HUDElements.sw_stats->colors.engine, "%s", "RAM"); + ImGui::TextColored(HUDElements.colors.engine, "%s", "RAM"); ImGui::PopFont(); } + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f)); ImGui::TableNextRow(); if (!HUDElements.params->enabled[OVERLAY_PARAM_ENABLED_histogram]){ @@ -518,7 +609,7 @@ void HudElements::sort_elements(std::pair option){ if (param == "engine_version") { ordered_functions.push_back({engine_version, value}); } if (param == "gpu_name") { ordered_functions.push_back({gpu_name, value}); } if (param == "vulkan_driver") { ordered_functions.push_back({vulkan_driver, value}); } - if (param == "arch") { ordered_functions.push_back({arch, value}); } + if (param == "arch") { ordered_functions.push_back({arch, value}); } if (param == "wine") { ordered_functions.push_back({wine, value}); } if (param == "frame_timing") { ordered_functions.push_back({frame_timing, value}); } if (param == "media_player") { ordered_functions.push_back({media_player, value}); } diff --git a/src/hud_elements.h b/src/hud_elements.h index c1ebc64b..026221de 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -39,6 +39,29 @@ class HudElements{ static void frame_timing(); static void media_player(); static void graphs(); + + void convert_colors(struct overlay_params& params); + void convert_colors(bool do_conv, struct overlay_params& params); + struct hud_colors { + bool convert, update; + ImVec4 cpu, + gpu, + vram, + ram, + engine, + io, + frametime, + background, + text, + media_player, + wine, + gpu_load_high, + gpu_load_med, + gpu_load_low, + cpu_load_high, + cpu_load_med, + cpu_load_low; + } colors {}; }; extern HudElements HUDElements; diff --git a/src/overlay.cpp b/src/overlay.cpp index 08db33f0..ea449ef3 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include "overlay.h" #include "logging.h" @@ -10,7 +9,11 @@ #include "timing.hpp" #include "mesa/util/macros.h" #include "string_utils.h" +#ifdef HAVE_DBUS +float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; +#endif +bool open = false; struct benchmark_stats benchmark; struct fps_limit fps_limit_stats {}; ImVec2 real_font_size; @@ -144,3 +147,286 @@ void calculate_benchmark_data(void *params_void){ entry.first.append(max_label_size - entry.first.length(), ' '); } } + + +float get_time_stat(void *_data, int _idx) +{ + struct swapchain_stats *data = (struct swapchain_stats *) _data; + if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) + return 0.0f; + int idx = ARRAY_SIZE(data->frames_stats) + + data->n_frames < ARRAY_SIZE(data->frames_stats) ? + _idx - data->n_frames : + _idx + data->n_frames; + idx %= ARRAY_SIZE(data->frames_stats); + /* Time stats are in us. */ + return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; +} + +void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) +{ + unsigned width = ImGui::GetIO().DisplaySize.x; + unsigned height = ImGui::GetIO().DisplaySize.y; + float margin = 10.0f; + if (params.offset_x > 0 || params.offset_y > 0) + margin = 0.0f; + + ImGui::SetNextWindowBgAlpha(params.background_alpha); + ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); + ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); + switch (params.position) { + case LAYER_POSITION_TOP_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_LEFT: + data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_BOTTOM_RIGHT: + data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + case LAYER_POSITION_TOP_CENTER: + data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); + ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); + break; + } +} + +void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) +{ + ImVec2 pos = ImGui::GetCursorPos(); + char buffer[32] {}; + + va_list args; + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + + ImVec2 sz = ImGui::CalcTextSize(buffer); + ImGui::SetCursorPosX(pos.x + off_x - sz.x); + //ImGui::Text("%s", buffer); + ImGui::TextColored(col,"%s",buffer); +} + +float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) +{ + //float cw = ImGui::GetContentRegionAvailWidth() * 3; // only table cell worth of width + float cw = ImGui::GetWindowContentRegionMax().x - ImGui::GetStyle().WindowPadding.x; + float new_pos_x = ImGui::GetCursorPosX(); + left_limit = cw - tw + new_pos_x; + right_limit = new_pos_x; + + if (cw < tw) { + new_pos_x += pos; + // acts as a delay before it starts scrolling again + if (new_pos_x < left_limit) + return left_limit; + else if (new_pos_x > right_limit) + return right_limit; + else + return new_pos_x; + } + return new_pos_x; +} + +#ifdef HAVE_DBUS +void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) +{ + if (meta.meta.valid) { + auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); + ImGui::Dummy(ImVec2(0.0f, 20.0f)); + //ImGui::PushFont(data.font1); + + if (meta.ticker.needs_recalc) { + meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; + meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; + meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; + meta.ticker.longest = std::max(std::max( + meta.ticker.tw0, + meta.ticker.tw1), + meta.ticker.tw2); + meta.ticker.needs_recalc = false; + } + + float new_pos, left_limit = 0, right_limit = 0; + get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); + + if (meta.ticker.pos < left_limit - g_overflow * .5f) { + meta.ticker.dir = -1; + meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; + } else if (meta.ticker.pos > right_limit + g_overflow) { + meta.ticker.dir = 1; + meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; + } + + meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; + + for (auto order : params.media_player_order) { + switch (order) { + case MP_ORDER_TITLE: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.title.c_str()); + } + break; + case MP_ORDER_ARTIST: + { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); + } + break; + case MP_ORDER_ALBUM: + { + //ImGui::NewLine(); + if (!meta.meta.album.empty()) { + new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); + ImGui::SetCursorPosX(new_pos); + ImGui::TextColored(color, "%s", meta.meta.album.c_str()); + } + } + break; + default: break; + } + } + + if (!meta.meta.playing) { + ImGui::TextColored(color, "(paused)"); + } + + //ImGui::PopFont(); + ImGui::PopStyleVar(); + } +} +#endif + +void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, unsigned height, Clock::time_point now){ + // TODO, FIX LOG_DURATION FOR BENCHMARK + int benchHeight = (2 + benchmark.percentile_data.size()) * real_font_size.x + 10.0f + 58; + ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); + if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); + else + ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); + + float display_time = std::chrono::duration(now - logger->last_log_end()).count(); + static float display_for = 10.0f; + float alpha; + if(params.background_alpha != 0){ + if (display_for >= display_time){ + alpha = display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } else { + alpha = 6.0 - display_time * params.background_alpha; + if (alpha >= params.background_alpha){ + ImGui::SetNextWindowBgAlpha(params.background_alpha); + }else{ + ImGui::SetNextWindowBgAlpha(alpha); + } + } + } else { + if (display_for >= display_time){ + alpha = display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } else { + alpha = 6.0 - display_time * 0.0001; + ImGui::SetNextWindowBgAlpha(params.background_alpha); + } + } + ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); + static const char* finished = "Logging Finished"; + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); + ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", finished); + ImGui::Dummy(ImVec2(0.0f, 8.0f)); + char duration[20]; + snprintf(duration, sizeof(duration), "Duration: %.1fs", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).count()); + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(duration).x / 2)); + ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", duration); + for (auto& data_ : benchmark.percentile_data){ + char buffer[20]; + snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); + ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); + } + float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); + ImVec4 plotColor = HUDElements.colors.frametime; + plotColor.w = alpha / params.background_alpha; + ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); + ImGui::Dummy(ImVec2(0.0f, 8.0f)); + if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) + ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + else + ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); + ImGui::PopStyleColor(2); + ImGui::End(); +} + +ImVec4 change_on_load_temp(LOAD_DATA& data, int current) +{ + if (current >= data.high_load){ + return data.color_high; + } + else if (current >= data.med_load){ + float diff = float(current - data.med_load) / float(data.high_load - data.med_load); + float x = (data.color_high.x - data.color_med.x) * diff; + float y = (data.color_high.y - data.color_med.y) * diff; + float z = (data.color_high.z - data.color_med.z) * diff; + return ImVec4(data.color_med.x + x, data.color_med.y + y, data.color_med.z + z, 1.0); + } else { + float diff = float(current) / float(data.med_load); + float x = (data.color_med.x - data.color_low.x) * diff; + float y = (data.color_med.y - data.color_low.y) * diff; + float z = (data.color_med.z - data.color_low.z) * diff; + return ImVec4(data.color_low.x + x, data.color_low.y + y, data.color_low.z + z, 1.0); + } +} + +void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) +{ + HUDElements.sw_stats = &data; HUDElements.params = ¶ms; + HUDElements.is_vulkan = is_vulkan; + ImGui::GetIO().FontGlobalScale = params.font_scale; + if(not logger) logger = std::make_unique(¶ms); + 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) { + HUDElements.ralign_width = ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; + old_scale = params.font_scale; + } + + if (!params.no_display){ + ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); + ImGui::BeginTable("hud", params.table_columns, ImGuiTableFlags_NoClipX); + HUDElements.place = 0; + for (auto& func : HUDElements.ordered_functions){ + func.first(); + HUDElements.place += 1; + } + ImGui::EndTable(); + + if(logger->is_active()) + ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); + window_size = ImVec2(window_size.x, ImGui::GetCursorPosY() + 10.0f); + ImGui::End(); + if((now - logger->last_log_end()) < 12s) + render_benchmark(data, params, window_size, height, now); + } +} diff --git a/src/overlay.h b/src/overlay.h index b3b5360f..72fd0ac8 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -53,25 +53,6 @@ struct swapchain_stats { std::string deviceName; std::string gpuName; std::string driverName; - struct { - ImVec4 cpu, - gpu, - vram, - ram, - engine, - io, - frametime, - background, - text, - media_player, - wine, - gpu_load_high, - gpu_load_med, - gpu_load_low, - cpu_load_high, - cpu_load_med, - cpu_load_low; - } colors; }; struct fps_limit { @@ -116,9 +97,8 @@ void FpsLimiter(struct fps_limit& stats); void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats); void calculate_benchmark_data(void *params_void); void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); -void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params); void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...); -ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current); +ImVec4 change_on_load_temp(LOAD_DATA& data, int current); float get_time_stat(void *_data, int _idx); #ifdef HAVE_DBUS diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index e9af1d2d..a7d10627 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -633,16 +633,15 @@ parse_overlay_config(struct overlay_params *params, ¶ms->cpu_load_color[0], ¶ms->cpu_load_color[1], ¶ms->cpu_load_color[2], - }; for (auto color : colors){ - *color = - IM_COL32(RGBGetRValue(*color), + *color = + IM_COL32(RGBGetRValue(*color), RGBGetGValue(*color), RGBGetBValue(*color), 255); - } + } if (!params->table_columns) params->table_columns = 3; @@ -678,8 +677,10 @@ parse_overlay_config(struct overlay_params *params, main_metadata.meta.valid = false; } #endif + if(!params->output_file.empty()) printf("MANGOHUD: output_file is Deprecated, use output_folder instead\n"); + auto real_size = params->font_size * params->font_scale; real_font_size = ImVec2(real_size, real_size / 2); HUDElements.params = params; @@ -689,4 +690,7 @@ parse_overlay_config(struct overlay_params *params, for (auto& option : HUDElements.options) HUDElements.sort_elements(option); } + + // Needs ImGui context but it is null here for OpenGL so just note it and update somewhere else + HUDElements.colors.update = true; } diff --git a/src/vulkan.cpp b/src/vulkan.cpp index 11ea2966..1358be9b 100644 --- a/src/vulkan.cpp +++ b/src/vulkan.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -64,11 +63,6 @@ #include "pci_ids.h" #include "timing.hpp" -#ifdef HAVE_DBUS -float g_overflow = 50.f /* 3333ms * 0.5 / 16.6667 / 2 (to edge and back) */; -#endif - -bool open = false; string gpuString,wineVersion,wineProcess; float offset_x, offset_y, hudSpacing; int hudFirstRow, hudSecondRow; @@ -689,293 +683,15 @@ static void snapshot_swapchain_frame(struct swapchain_data *data) // } } -float get_time_stat(void *_data, int _idx) -{ - struct swapchain_stats *data = (struct swapchain_stats *) _data; - if ((ARRAY_SIZE(data->frames_stats) - _idx) > data->n_frames) - return 0.0f; - int idx = ARRAY_SIZE(data->frames_stats) + - data->n_frames < ARRAY_SIZE(data->frames_stats) ? - _idx - data->n_frames : - _idx + data->n_frames; - idx %= ARRAY_SIZE(data->frames_stats); - /* Time stats are in us. */ - return data->frames_stats[idx].stats[data->stat_selector] / data->time_dividor; -} - -void position_layer(struct swapchain_stats& data, struct overlay_params& params, ImVec2 window_size) -{ - unsigned width = ImGui::GetIO().DisplaySize.x; - unsigned height = ImGui::GetIO().DisplaySize.y; - float margin = 10.0f; - if (params.offset_x > 0 || params.offset_y > 0) - margin = 0.0f; - - ImGui::SetNextWindowBgAlpha(params.background_alpha); - ImGui::SetNextWindowSize(window_size, ImGuiCond_Always); - ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,-3)); - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, params.alpha); - switch (params.position) { - case LAYER_POSITION_TOP_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_LEFT: - data.main_window_pos = ImVec2(margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_BOTTOM_RIGHT: - data.main_window_pos = ImVec2(width - window_size.x - margin + params.offset_x, height - window_size.y - margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - case LAYER_POSITION_TOP_CENTER: - data.main_window_pos = ImVec2((width / 2) - (window_size.x / 2), margin + params.offset_y); - ImGui::SetNextWindowPos(data.main_window_pos, ImGuiCond_Always); - break; - } -} - -void right_aligned_text(ImVec4& col, float off_x, const char *fmt, ...) -{ - ImVec2 pos = ImGui::GetCursorPos(); - char buffer[32] {}; - - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - - ImVec2 sz = ImGui::CalcTextSize(buffer); - ImGui::SetCursorPosX(pos.x + off_x - sz.x); - //ImGui::Text("%s", buffer); - ImGui::TextColored(col,"%s",buffer); -} - -float get_ticker_limited_pos(float pos, float tw, float& left_limit, float& right_limit) -{ - float cw = ImGui::GetContentRegionAvailWidth(); - float new_pos_x = ImGui::GetCursorPosX(); - left_limit = cw - tw + new_pos_x; - right_limit = new_pos_x; - - if (cw < tw) { - new_pos_x += pos; - // acts as a delay before it starts scrolling again - if (new_pos_x < left_limit) - return left_limit; - else if (new_pos_x > right_limit) - return right_limit; - else - return new_pos_x; - } - return new_pos_x; -} - -#ifdef HAVE_DBUS -void render_mpris_metadata(struct overlay_params& params, mutexed_metadata& meta, uint64_t frame_timing, bool is_main) -{ - if (meta.meta.valid) { - auto color = ImGui::ColorConvertU32ToFloat4(params.media_player_color); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8,0)); - ImGui::Dummy(ImVec2(0.0f, 20.0f)); - //ImGui::PushFont(data.font1); - - if (meta.ticker.needs_recalc) { - meta.ticker.tw0 = ImGui::CalcTextSize(meta.meta.title.c_str()).x; - meta.ticker.tw1 = ImGui::CalcTextSize(meta.meta.artists.c_str()).x; - meta.ticker.tw2 = ImGui::CalcTextSize(meta.meta.album.c_str()).x; - meta.ticker.longest = std::max(std::max( - meta.ticker.tw0, - meta.ticker.tw1), - meta.ticker.tw2); - meta.ticker.needs_recalc = false; - } - - float new_pos, left_limit = 0, right_limit = 0; - get_ticker_limited_pos(meta.ticker.pos, meta.ticker.longest, left_limit, right_limit); - - if (meta.ticker.pos < left_limit - g_overflow * .5f) { - meta.ticker.dir = -1; - meta.ticker.pos = (left_limit - g_overflow * .5f) + 1.f /* random */; - } else if (meta.ticker.pos > right_limit + g_overflow) { - meta.ticker.dir = 1; - meta.ticker.pos = (right_limit + g_overflow) - 1.f /* random */; - } - - meta.ticker.pos -= .5f * (frame_timing / 16666.7f) * meta.ticker.dir; - - for (auto order : params.media_player_order) { - switch (order) { - case MP_ORDER_TITLE: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw0, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.title.c_str()); - } - break; - case MP_ORDER_ARTIST: - { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw1, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.artists.c_str()); - } - break; - case MP_ORDER_ALBUM: - { - //ImGui::NewLine(); - if (!meta.meta.album.empty()) { - new_pos = get_ticker_limited_pos(meta.ticker.pos, meta.ticker.tw2, left_limit, right_limit); - ImGui::SetCursorPosX(new_pos); - ImGui::TextColored(color, "%s", meta.meta.album.c_str()); - } - } - break; - default: break; - } - } - - if (!meta.meta.playing) { - ImGui::TextColored(color, "(paused)"); - } - - //ImGui::PopFont(); - ImGui::PopStyleVar(); - } -} -#endif - -void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, unsigned height, Clock::time_point now){ - // TODO, FIX LOG_DURATION FOR BENCHMARK - int benchHeight = (2 + benchmark.percentile_data.size()) * real_font_size.x + 10.0f + 58; - ImGui::SetNextWindowSize(ImVec2(window_size.x, benchHeight), ImGuiCond_Always); - if (height - (window_size.y + data.main_window_pos.y + 5) < benchHeight) - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y - benchHeight - 5), ImGuiCond_Always); - else - ImGui::SetNextWindowPos(ImVec2(data.main_window_pos.x, data.main_window_pos.y + window_size.y + 5), ImGuiCond_Always); - - float display_time = std::chrono::duration(now - logger->last_log_end()).count(); - static float display_for = 10.0f; - float alpha; - if(params.background_alpha != 0){ - if (display_for >= display_time){ - alpha = display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } else { - alpha = 6.0 - display_time * params.background_alpha; - if (alpha >= params.background_alpha){ - ImGui::SetNextWindowBgAlpha(params.background_alpha); - }else{ - ImGui::SetNextWindowBgAlpha(alpha); - } - } - } else { - if (display_for >= display_time){ - alpha = display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } else { - alpha = 6.0 - display_time * 0.0001; - ImGui::SetNextWindowBgAlpha(params.background_alpha); - } - } - ImGui::Begin("Benchmark", &open, ImGuiWindowFlags_NoDecoration); - static const char* finished = "Logging Finished"; - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(finished).x / 2)); - ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", finished); - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - char duration[20]; - snprintf(duration, sizeof(duration), "Duration: %.1fs", std::chrono::duration(logger->last_log_end() - logger->last_log_begin()).count()); - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(duration).x / 2)); - ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s", duration); - for (auto& data_ : benchmark.percentile_data){ - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%s %.1f", data_.first.c_str(), data_.second); - ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2 )- (ImGui::CalcTextSize(buffer).x / 2)); - ImGui::TextColored(ImVec4(1.0, 1.0, 1.0, alpha / params.background_alpha), "%s %.1f", data_.first.c_str(), data_.second); - } - float max = *max_element(benchmark.fps_data.begin(), benchmark.fps_data.end()); - ImVec4 plotColor = data.colors.frametime; - plotColor.w = alpha / params.background_alpha; - ImGui::PushStyleColor(ImGuiCol_PlotLines, plotColor); - ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0, 0.0, 0.0, alpha / params.background_alpha)); - ImGui::Dummy(ImVec2(0.0f, 8.0f)); - if (params.enabled[OVERLAY_PARAM_ENABLED_histogram]) - ImGui::PlotHistogram("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - else - ImGui::PlotLines("", benchmark.fps_data.data(), benchmark.fps_data.size(), 0, "", 0.0f, max + 10, ImVec2(ImGui::GetContentRegionAvailWidth(), 50)); - ImGui::PopStyleColor(2); - ImGui::End(); -} - - -ImVec4 change_on_load_temp (struct LOAD_DATA& data, int current) { - if (current >= data.high_load){ - return data.color_high; - } - else if (current >= data.med_load){ - float diff = float(current - data.med_load) / float(data.high_load - data.med_load); - float x = (data.color_high.x - data.color_med.x) * diff; - float y = (data.color_high.y - data.color_med.y) * diff; - float z = (data.color_high.z - data.color_med.z) * diff; - return ImVec4(data.color_med.x + x, data.color_med.y + y, data.color_med.z + z, 1.0); - } else { - float diff = float(current) / float(data.med_load); - float x = (data.color_med.x - data.color_low.x) * diff; - float y = (data.color_med.y - data.color_low.y) * diff; - float z = (data.color_med.z - data.color_low.z) * diff; - return ImVec4(data.color_low.x + x, data.color_low.y + y, data.color_low.z + z, 1.0); - } -} - -void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) -{ - HUDElements.sw_stats = &data; HUDElements.params = ¶ms; - HUDElements.is_vulkan = is_vulkan; - ImGui::GetIO().FontGlobalScale = params.font_scale; - if(not logger) logger = std::make_unique(¶ms); - 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) { - HUDElements.ralign_width = ralign_width = ImGui::CalcTextSize("A").x * 4 /* characters */; - old_scale = params.font_scale; - } - - if (!params.no_display){ - ImGui::Begin("Main", &open, ImGuiWindowFlags_NoDecoration); - ImGui::BeginTable("hud", params.table_columns, ImGuiTableFlags_NoClipX); - HUDElements.place = 0; - for (auto& func : HUDElements.ordered_functions){ - func.first(); - HUDElements.place += 1; - } - ImGui::EndTable(); - - if(logger->is_active()) - ImGui::GetWindowDrawList()->AddCircleFilled(ImVec2(data.main_window_pos.x + window_size.x - 15, data.main_window_pos.y + 15), 10, params.engine_color, 20); - window_size = ImVec2(window_size.x, ImGui::GetCursorPosY() + 10.0f); - ImGui::End(); - if((now - logger->last_log_end()) < 12s) - render_benchmark(data, params, window_size, height, now); - } -} - static void compute_swapchain_display(struct swapchain_data *data) { struct device_data *device_data = data->device; struct instance_data *instance_data = device_data->instance; ImGui::SetCurrentContext(data->imgui_context); + if (HUDElements.colors.update) + HUDElements.convert_colors(instance_data->params); + ImGui::NewFrame(); { scoped_lock lk(instance_data->notifier.mutex); @@ -1712,81 +1428,6 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) // update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); } -// Cut from https://github.com/ocornut/imgui/pull/2943 -// Probably move to ImGui -float SRGBToLinear(float in) -{ - if (in <= 0.04045f) - return in / 12.92f; - else - return powf((in + 0.055f) / 1.055f, 2.4f); -} - -float LinearToSRGB(float in) -{ - if (in <= 0.0031308f) - return in * 12.92f; - else - return 1.055f * powf(in, 1.0f / 2.4f) - 0.055f; -} - -ImVec4 SRGBToLinear(ImVec4 col) -{ - col.x = SRGBToLinear(col.x); - col.y = SRGBToLinear(col.y); - col.z = SRGBToLinear(col.z); - // Alpha component is already linear - - return col; -} - -ImVec4 LinearToSRGB(ImVec4 col) -{ - col.x = LinearToSRGB(col.x); - col.y = LinearToSRGB(col.y); - col.z = LinearToSRGB(col.z); - // Alpha component is already linear - - return col; -} - -void convert_colors(bool do_conv, struct swapchain_stats& sw_stats, struct overlay_params& params) -{ - auto convert = [&do_conv](unsigned color) -> ImVec4 { - ImVec4 fc = ImGui::ColorConvertU32ToFloat4(color); - if (do_conv) - return SRGBToLinear(fc); - return fc; - }; - - sw_stats.colors.cpu = convert(params.cpu_color); - sw_stats.colors.gpu = convert(params.gpu_color); - sw_stats.colors.vram = convert(params.vram_color); - sw_stats.colors.ram = convert(params.ram_color); - sw_stats.colors.engine = convert(params.engine_color); - sw_stats.colors.io = convert(params.io_color); - sw_stats.colors.frametime = convert(params.frametime_color); - sw_stats.colors.background = convert(params.background_color); - sw_stats.colors.text = convert(params.text_color); - sw_stats.colors.media_player = convert(params.media_player_color); - sw_stats.colors.wine = convert(params.wine_color); - sw_stats.colors.gpu_load_high = convert(params.gpu_load_color[0]); - sw_stats.colors.gpu_load_med = convert(params.gpu_load_color[1]); - sw_stats.colors.gpu_load_low = convert(params.gpu_load_color[2]); - sw_stats.colors.cpu_load_high = convert(params.cpu_load_color[0]); - sw_stats.colors.cpu_load_med = convert(params.cpu_load_color[1]); - sw_stats.colors.cpu_load_low = convert(params.cpu_load_color[2]); - - - - ImGuiStyle& style = ImGui::GetStyle(); - style.Colors[ImGuiCol_PlotLines] = convert(params.frametime_color); - style.Colors[ImGuiCol_PlotHistogram] = convert(params.frametime_color); - style.Colors[ImGuiCol_WindowBg] = convert(params.background_color); - style.Colors[ImGuiCol_Text] = convert(params.text_color); - style.CellPadding.y = params.cellpadding_y * real_font_size.y; -} - // TODO probably needs colorspace check too static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, struct overlay_params& params) { @@ -1831,7 +1472,7 @@ static void convert_colors_vk(VkFormat format, struct swapchain_stats& sw_stats, break; } - convert_colors(do_conv, sw_stats, params); + HUDElements.convert_colors(do_conv, params); } static void setup_swapchain_data(struct swapchain_data *data,