diff --git a/README.md b/README.md index acd61bf9..078fa5ab 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,11 @@ A partial list of parameters are below. See the config file for a complete list. | `ram`
`vram` | Displays system RAM/VRAM usage | | `full` | Enables all of the above config options | | `font_size=` | Customizeable font size (default=24) | +| `font_size_text=` | Customizeable font size for other text like media metadata (default=24) | +| `font_scale=` | Set global font scale (default=1.0) | +| `font_file` | Change default font (set location to .TTF/.OTF file ) | +| `font_file_text` | Change text font. Otherwise `font_file` is used | +| `font_glyph_ranges` | Specify extra font glyph ranges, comma separated: `korean`, `chinese`, `chinese_simplified`, `japanese`, `cyrillic`, `thai`, `vietnamese`, `latin_ext_a`, `latin_ext_b`. If you experience crashes or text is just squares, reduce font size or glyph ranges. | | `width=`
`height=` | Customizeable hud dimensions (in pixels) | | `position=` | Location of the hud: `top-left` (default), `top-right`, `bottom-left`, `bottom-right`, `top-center` | | `offset_x` `offset_y` | Hud position offsets | @@ -147,7 +152,6 @@ A partial list of parameters are below. See the config file for a complete list. | `background_alpha` | Set the opacity of the background `0.0-1.0` | | `read_cfg` | Add to MANGOHUD_CONFIG as first parameter to also load config file. Otherwise only MANGOHUD_CONFIG parameters are used. | | `output_file` | Define name and location of the output file (Required for logging) | -| `font_file` | Change default font (set location to .TTF/.OTF file ) | | `log_duration` | Set amount of time the logging will run for (in seconds) | | `vsync`
`gl_vsync` | Set vsync for OpenGL or Vulkan | | `media_player` | Show media player metadata | diff --git a/bin/MangoHud.conf b/bin/MangoHud.conf index 652a933f..4ab60e1e 100644 --- a/bin/MangoHud.conf +++ b/bin/MangoHud.conf @@ -48,8 +48,22 @@ frame_timing ### Change the hud font size (default is 24) font_size=24 +# font_scale=1.0 +# font_size_text=24 # font_scale_media_player = 0.55 +### Change default font (set location to .TTF/.OTF file ) +## Set font for the whole hud +# font_file= + +## Set font only for text like media player metadata +# font_file_text= + +## Set font glyph ranges. Defaults to latin-only. Don't forget to set font_file/text_font_file to font that supports these. +## Probably don't enable all at once because of memory usage and hardware limits concerns. +## If you experience crashes or text is just squares, reduce glyph range or reduce font size. +# font_glyph_ranges=korean, chinese, chinese_simplified, japanese, cyrillic, thai, vietnamese, latin_ext_a, latin_ext_b + ### Change the hud position (default is top-left) position=top-left @@ -91,9 +105,6 @@ background_alpha=0.5 # background_color=020202 # media_player_color=FFFFFF -### Change default font (set location to .TTF/.OTF file ) -# font_file - ### Show media player metadata # media_player # media_player_name = spotify @@ -118,4 +129,4 @@ background_alpha=0.5 ### Define name and location of the output file (Required for logging) # output_file ### Permit uploading logs directly to Flightlessmango.com -# permit_upload=1 \ No newline at end of file +# permit_upload=1 diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index f23b12e8..bde2dbac 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -45,8 +45,6 @@ struct GLVec struct state { ImGuiContext *imgui_ctx = nullptr; - ImFont* font = nullptr; - ImFont* font1 = nullptr; }; static GLVec last_vp {}, last_sb {}; @@ -133,8 +131,7 @@ void imgui_create(void *ctx) GLint current_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); - create_fonts(params, state.font, state.font1); - sw_stats.font1 = state.font1; + create_fonts(params, sw_stats.font1, sw_stats.font_text); // Restore global context or ours might clash with apps that use Dear ImGui ImGui::SetCurrentContext(saved_ctx); diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index 92bcdce2..38633d23 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -72,6 +72,8 @@ #include +#include "overlay.h" + namespace MangoHud { // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have. @@ -110,7 +112,7 @@ static bool ImGui_ImplOpenGL3_CreateFontsTexture() ImGuiIO& io = ImGui::GetIO(); unsigned char* pixels; int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory. + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); // Upload texture to graphics system GLint last_texture; @@ -123,7 +125,14 @@ static bool ImGui_ImplOpenGL3_CreateFontsTexture() if (g_IsGLES || g_GlVersion >= 200) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + // FIXME can compress? + glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pixels); + +#ifndef NDEBUG + GLint compFlag= 0; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compFlag); + fprintf(stderr, "GL tex compressed: %s\n", compFlag ? "yes" : "no"); +#endif // Store our identifier io.Fonts->TexID = (ImTextureID)(intptr_t)g_FontTexture; @@ -252,7 +261,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects() "varying vec4 Frag_Color;\n" "void main()\n" "{\n" - " gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n" + " gl_FragColor = Frag_Color * vec4(1, 1, 1, texture2D(Texture, Frag_UV.st).a);\n" "}\n"; const GLchar* fragment_shader_glsl_130 = @@ -262,7 +271,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects() "out vec4 Out_Color;\n" "void main()\n" "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + " Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).a);\n" "}\n"; const GLchar* fragment_shader_glsl_300_es = @@ -273,7 +282,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects() "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + " Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).a);\n" "}\n"; const GLchar* fragment_shader_glsl_410_core = @@ -283,7 +292,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects() "layout (location = 0) out vec4 Out_Color;\n" "void main()\n" "{\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + " Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).a);\n" "}\n"; #ifndef NDEBUG @@ -547,7 +556,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x); int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y); - if (fb_width <= 0 || fb_height <= 0) + if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount == 0) return; // Backup GL state diff --git a/src/overlay.cpp b/src/overlay.cpp index ed189b10..902ceb4f 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -181,7 +181,6 @@ struct swapchain_data { std::list draws; /* List of struct overlay_draw */ - ImFont* font = nullptr; bool font_uploaded; VkImage font_image; VkImageView font_image_view; @@ -253,39 +252,80 @@ static void unmap_object(uint64_t obj) /**/ -void create_fonts(const overlay_params& params, ImFont*& default_font, ImFont*& small_font) +#define CHAR_CELSIUS "\xe2\x84\x83" +#define CHAR_FAHRENHEIT "\xe2\x84\x89" + +void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font) { auto& io = ImGui::GetIO(); - int font_size = params.font_size; - if (!font_size) + float font_size = params.font_size; + if (font_size < FLT_EPSILON) font_size = 24; - static const ImWchar glyph_ranges[] = + float font_size_text = params.font_size_text; + if (font_size_text < FLT_EPSILON) + font_size_text = font_size; + + static const ImWchar default_range[] = { 0x0020, 0x00FF, // Basic Latin + Latin Supplement - 0x0100, 0x017f, // Latin Extended-A - 0x0400, 0x052F, // Cyrillic + Cyrillic Supplement - 0x2DE0, 0x2DFF, // Cyrillic Extended-A - 0xA640, 0xA69F, // Cyrillic Extended-B + //0x0100, 0x017F, // Latin Extended-A + //0x2103, 0x2103, // Degree Celsius + //0x2109, 0x2109, // Degree Fahrenheit 0, }; + ImVector glyph_ranges; + ImFontGlyphRangesBuilder builder; + builder.AddRanges(io.Fonts->GetGlyphRangesDefault()); + if (params.font_glyph_ranges & FG_KOREAN) + builder.AddRanges(io.Fonts->GetGlyphRangesKorean()); + if (params.font_glyph_ranges & FG_CHINESE_FULL) + builder.AddRanges(io.Fonts->GetGlyphRangesChineseFull()); + if (params.font_glyph_ranges & FG_CHINESE_SIMPLIFIED) + builder.AddRanges(io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + if (params.font_glyph_ranges & FG_JAPANESE) + builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Not exactly Shift JIS compatible? + if (params.font_glyph_ranges & FG_CYRILLIC) + builder.AddRanges(io.Fonts->GetGlyphRangesCyrillic()); + if (params.font_glyph_ranges & FG_THAI) + builder.AddRanges(io.Fonts->GetGlyphRangesThai()); + if (params.font_glyph_ranges & FG_VIETNAMESE) + builder.AddRanges(io.Fonts->GetGlyphRangesVietnamese()); + if (params.font_glyph_ranges & FG_LATIN_EXT_A) { + static const ImWchar latin_ext_a[] { 0x0100, 0x017F, 0 }; + builder.AddRanges(latin_ext_a); + } + if (params.font_glyph_ranges & FG_LATIN_EXT_B) { + static const ImWchar latin_ext_b[] { 0x0180, 0x024F, 0 }; + builder.AddRanges(latin_ext_b); + } + builder.BuildRanges(&glyph_ranges); + + // If both font_file and text_font_file are the same then just use "default" font + bool same_font = (params.font_file == params.font_file_text || params.font_file_text.empty()); + bool same_size = (font_size == font_size_text); + // ImGui takes ownership of the data, no need to free it if (!params.font_file.empty() && file_exists(params.font_file)) { - default_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, glyph_ranges); - small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, io.Fonts->GetGlyphRangesDefault()); + io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size, nullptr, same_font && same_size ? glyph_ranges.Data : default_range); + small_font = io.Fonts->AddFontFromFileTTF(params.font_file.c_str(), font_size * 0.55f, nullptr, default_range); } else { const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); - default_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, io.Fonts->GetGlyphRangesDefault()); - small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55, nullptr, io.Fonts->GetGlyphRangesDefault()); + io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size, nullptr, default_range); + small_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_size * 0.55f, nullptr, default_range); } -} -// FIXME "temporary" hack until Dear ImGui has an actual API for this -void scale_default_font(ImFont& scaled_font, float scale) -{ - scaled_font = *ImGui::GetIO().Fonts->Fonts[0]; - scaled_font.Scale = scale; + auto font_file_text = params.font_file_text; + if (font_file_text.empty()) + font_file_text = params.font_file; + + if ((!same_font || !same_size) && file_exists(font_file_text)) + text_font = io.Fonts->AddFontFromFileTTF(font_file_text.c_str(), font_size_text, nullptr, glyph_ranges.Data); + else + text_font = io.Fonts->Fonts[0]; + + io.Fonts->Build(); } static VkLayerInstanceCreateInfo *get_instance_chain_info(const VkInstanceCreateInfo *pCreateInfo, @@ -1044,7 +1084,7 @@ static void render_mpris_metadata(struct overlay_params& params, metadata& meta, 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 = 6 * params.font_size + 10.0f + 58; + int benchHeight = 6 * params.font_size * params.font_scale + 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); @@ -1111,6 +1151,7 @@ void render_benchmark(swapchain_stats& data, struct overlay_params& params, ImVe void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& window_size, bool is_vulkan) { + ImGui::GetIO().FontGlobalScale = params.font_scale; 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; @@ -1349,7 +1390,7 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } if (params.enabled[OVERLAY_PARAM_ENABLED_frame_timing]){ - ImGui::Dummy(ImVec2(0.0f, params.font_size / 2)); + ImGui::Dummy(ImVec2(0.0f, params.font_size * params.font_scale / 2)); ImGui::PushFont(data.font1); ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(params.engine_color), "%s", "Frametime"); ImGui::PopFont(); @@ -1366,12 +1407,12 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& ImGui::PlotHistogram(hash, get_time_stat, &data, ARRAY_SIZE(data.frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * 2.2, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); } else { ImGui::PlotLines(hash, get_time_stat, &data, ARRAY_SIZE(data.frames_stats), 0, NULL, min_time, max_time, - ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * 2.2, 50)); + ImVec2(ImGui::GetContentRegionAvailWidth() - params.font_size * params.font_scale * 2.2, 50)); } ImGui::PopStyleColor(); } @@ -1383,8 +1424,8 @@ void render_imgui(swapchain_stats& data, struct overlay_params& params, ImVec2& } #ifdef HAVE_DBUS - ImFont scaled_font; - scale_default_font(scaled_font, params.font_scale_media_player); + ImFont scaled_font = *data.font_text; + scaled_font.Scale = params.font_scale_media_player; ImGui::PushFont(&scaled_font); render_mpris_metadata(params, main_metadata, frame_timing, true); render_mpris_metadata(params, generic_mpris, frame_timing, false); @@ -1436,21 +1477,33 @@ static uint32_t vk_memory_type(struct device_data *data, return 0xFFFFFFFF; // Unable to find memoryType } -static void ensure_swapchain_fonts(struct swapchain_data *data, - VkCommandBuffer command_buffer) +static void update_image_descriptor(struct swapchain_data *data, VkImageView image_view, VkDescriptorSet set) { - if (data->font_uploaded) - return; - - data->font_uploaded = true; - struct device_data *device_data = data->device; - ImGuiIO& io = ImGui::GetIO(); - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - size_t upload_size = width * height * 4 * sizeof(char); + /* Descriptor set */ + VkDescriptorImageInfo desc_image[1] = {}; + desc_image[0].sampler = data->font_sampler; + desc_image[0].imageView = image_view; + desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkWriteDescriptorSet write_desc[1] = {}; + write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write_desc[0].dstSet = set; + write_desc[0].descriptorCount = 1; + write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write_desc[0].pImageInfo = desc_image; + device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); +} +static void upload_image_data(struct device_data *device_data, + VkCommandBuffer command_buffer, + void *pixels, + VkDeviceSize upload_size, + uint32_t width, + uint32_t height, + VkBuffer& upload_buffer, + VkDeviceMemory& upload_buffer_mem, + VkImage image) +{ /* Upload buffer */ VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; @@ -1458,10 +1511,10 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; VK_CHECK(device_data->vtable.CreateBuffer(device_data->device, &buffer_info, - NULL, &data->upload_font_buffer)); + NULL, &upload_buffer)); VkMemoryRequirements upload_buffer_req; device_data->vtable.GetBufferMemoryRequirements(device_data->device, - data->upload_font_buffer, + upload_buffer, &upload_buffer_req); VkMemoryAllocateInfo upload_alloc_info = {}; upload_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; @@ -1472,24 +1525,24 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &upload_alloc_info, NULL, - &data->upload_font_buffer_mem)); + &upload_buffer_mem)); VK_CHECK(device_data->vtable.BindBufferMemory(device_data->device, - data->upload_font_buffer, - data->upload_font_buffer_mem, 0)); + upload_buffer, + upload_buffer_mem, 0)); /* Upload to Buffer */ char* map = NULL; VK_CHECK(device_data->vtable.MapMemory(device_data->device, - data->upload_font_buffer_mem, + upload_buffer_mem, 0, upload_size, 0, (void**)(&map))); memcpy(map, pixels, upload_size); VkMappedMemoryRange range[1] = {}; range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[0].memory = data->upload_font_buffer_mem; + range[0].memory = upload_buffer_mem; range[0].size = upload_size; VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 1, range)); device_data->vtable.UnmapMemory(device_data->device, - data->upload_font_buffer_mem); + upload_buffer_mem); /* Copy buffer to image */ VkImageMemoryBarrier copy_barrier[1] = {}; @@ -1499,7 +1552,7 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - copy_barrier[0].image = data->font_image; + copy_barrier[0].image = image; copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; copy_barrier[0].subresourceRange.levelCount = 1; copy_barrier[0].subresourceRange.layerCount = 1; @@ -1516,8 +1569,8 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, region.imageExtent.height = height; region.imageExtent.depth = 1; device_data->vtable.CmdCopyBufferToImage(command_buffer, - data->upload_font_buffer, - data->font_image, + upload_buffer, + image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); @@ -1529,7 +1582,7 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - use_barrier[0].image = data->font_image; + use_barrier[0].image = image; use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; use_barrier[0].subresourceRange.levelCount = 1; use_barrier[0].subresourceRange.layerCount = 1; @@ -1540,9 +1593,90 @@ static void ensure_swapchain_fonts(struct swapchain_data *data, 0, NULL, 0, NULL, 1, use_barrier); +} - /* Store our identifier */ - io.Fonts->TexID = (ImTextureID)(intptr_t)data->font_image; +static VkDescriptorSet create_image_with_desc(struct swapchain_data *data, + uint32_t width, + uint32_t height, + VkFormat format, + VkImage& image, + VkDeviceMemory& image_mem, + VkImageView& image_view) +{ + struct device_data *device_data = data->device; + + VkImageCreateInfo image_info = {}; + image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format; + image_info.extent.width = width; + image_info.extent.height = height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, + NULL, &image)); + VkMemoryRequirements font_image_req; + device_data->vtable.GetImageMemoryRequirements(device_data->device, + image, &font_image_req); + VkMemoryAllocateInfo image_alloc_info = {}; + image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + image_alloc_info.allocationSize = font_image_req.size; + image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + font_image_req.memoryTypeBits); + VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, + NULL, &image_mem)); + VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, + image, + image_mem, 0)); + + /* Font image view */ + VkImageViewCreateInfo view_info = {}; + view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view_info.image = image; + view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; + view_info.format = format; + view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view_info.subresourceRange.levelCount = 1; + view_info.subresourceRange.layerCount = 1; + VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, + NULL, &image_view)); + + VkDescriptorSet descriptor_set; + + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.descriptorPool = data->descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &data->descriptor_layout; + VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, + &alloc_info, + &descriptor_set)); + + update_image_descriptor(data, image_view, descriptor_set); + return descriptor_set; +} + +static void ensure_swapchain_fonts(struct swapchain_data *data, + VkCommandBuffer command_buffer) +{ + struct device_data *device_data = data->device; + if (data->font_uploaded) + return; + + data->font_uploaded = true; + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); + size_t upload_size = width * height * 1 * sizeof(char); + upload_image_data(device_data, command_buffer, pixels, upload_size, width, height, data->upload_font_buffer, data->upload_font_buffer_mem, data->font_image); } static void CreateOrResizeBuffer(struct device_data *data, @@ -1652,100 +1786,110 @@ static struct overlay_draw *render_swapchain_display(struct swapchain_data *data index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); } - /* Upload vertex & index data */ - ImDrawVert* vtx_dst = NULL; - ImDrawIdx* idx_dst = NULL; - VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, - 0, vertex_size, 0, (void**)(&vtx_dst))); - VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, - 0, index_size, 0, (void**)(&idx_dst))); - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); - memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - vtx_dst += cmd_list->VtxBuffer.Size; - idx_dst += cmd_list->IdxBuffer.Size; - } - VkMappedMemoryRange range[2] = {}; - range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[0].memory = draw->vertex_buffer_mem; - range[0].size = VK_WHOLE_SIZE; - range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; - range[1].memory = draw->index_buffer_mem; - range[1].size = VK_WHOLE_SIZE; - VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); - device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); - device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); - - /* Bind pipeline and descriptor sets */ - device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); - VkDescriptorSet desc_set[1] = { data->descriptor_set }; - device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, - data->pipeline_layout, 0, 1, desc_set, 0, NULL); - - /* Bind vertex & index buffers */ - VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; - VkDeviceSize vertex_offset[1] = { 0 }; - device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); - device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); - - /* Setup viewport */ - VkViewport viewport; - viewport.x = 0; - viewport.y = 0; - viewport.width = draw_data->DisplaySize.x; - viewport.height = draw_data->DisplaySize.y; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); - - - /* Setup scale and translation through push constants : - * - * Our visible imgui space lies from draw_data->DisplayPos (top left) to - * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin - * is typically (0,0) for single viewport apps. - */ - float scale[2]; - scale[0] = 2.0f / draw_data->DisplaySize.x; - scale[1] = 2.0f / draw_data->DisplaySize.y; - float translate[2]; - translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; - translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; - device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, - VK_SHADER_STAGE_VERTEX_BIT, - sizeof(float) * 0, sizeof(float) * 2, scale); - device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, - VK_SHADER_STAGE_VERTEX_BIT, - sizeof(float) * 2, sizeof(float) * 2, translate); - - // Render the command lists: - int vtx_offset = 0; - int idx_offset = 0; - ImVec2 display_pos = draw_data->DisplayPos; - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - // Apply scissor/clipping rectangle - // FIXME: We could clamp width/height based on clamped min/max values. - VkRect2D scissor; - scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; - scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; - scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); - scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? - device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); - - // Draw - device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); - - idx_offset += pcmd->ElemCount; - } - vtx_offset += cmd_list->VtxBuffer.Size; - } + /* Upload vertex & index data */ + ImDrawVert* vtx_dst = NULL; + ImDrawIdx* idx_dst = NULL; + VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->vertex_buffer_mem, + 0, vertex_size, 0, (void**)(&vtx_dst))); + VK_CHECK(device_data->vtable.MapMemory(device_data->device, draw->index_buffer_mem, + 0, index_size, 0, (void**)(&idx_dst))); + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); + memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.Size; + idx_dst += cmd_list->IdxBuffer.Size; + } + VkMappedMemoryRange range[2] = {}; + range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[0].memory = draw->vertex_buffer_mem; + range[0].size = VK_WHOLE_SIZE; + range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; + range[1].memory = draw->index_buffer_mem; + range[1].size = VK_WHOLE_SIZE; + VK_CHECK(device_data->vtable.FlushMappedMemoryRanges(device_data->device, 2, range)); + device_data->vtable.UnmapMemory(device_data->device, draw->vertex_buffer_mem); + device_data->vtable.UnmapMemory(device_data->device, draw->index_buffer_mem); + + /* Bind pipeline and descriptor sets */ + device_data->vtable.CmdBindPipeline(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, data->pipeline); + +#if 1 // disable if using >1 font textures + VkDescriptorSet desc_set[1] = { + //data->descriptor_set + reinterpret_cast(ImGui::GetIO().Fonts->Fonts[0]->ContainerAtlas->TexID) + }; + device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->pipeline_layout, 0, 1, desc_set, 0, NULL); +#endif + + /* Bind vertex & index buffers */ + VkBuffer vertex_buffers[1] = { draw->vertex_buffer }; + VkDeviceSize vertex_offset[1] = { 0 }; + device_data->vtable.CmdBindVertexBuffers(draw->command_buffer, 0, 1, vertex_buffers, vertex_offset); + device_data->vtable.CmdBindIndexBuffer(draw->command_buffer, draw->index_buffer, 0, VK_INDEX_TYPE_UINT16); + + /* Setup viewport */ + VkViewport viewport; + viewport.x = 0; + viewport.y = 0; + viewport.width = draw_data->DisplaySize.x; + viewport.height = draw_data->DisplaySize.y; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + device_data->vtable.CmdSetViewport(draw->command_buffer, 0, 1, &viewport); + + + /* Setup scale and translation through push constants : + * + * Our visible imgui space lies from draw_data->DisplayPos (top left) to + * draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin + * is typically (0,0) for single viewport apps. + */ + float scale[2]; + scale[0] = 2.0f / draw_data->DisplaySize.x; + scale[1] = 2.0f / draw_data->DisplaySize.y; + float translate[2]; + translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0]; + translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1]; + device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, + sizeof(float) * 0, sizeof(float) * 2, scale); + device_data->vtable.CmdPushConstants(draw->command_buffer, data->pipeline_layout, + VK_SHADER_STAGE_VERTEX_BIT, + sizeof(float) * 2, sizeof(float) * 2, translate); + + // Render the command lists: + int vtx_offset = 0; + int idx_offset = 0; + ImVec2 display_pos = draw_data->DisplayPos; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + // Apply scissor/clipping rectangle + // FIXME: We could clamp width/height based on clamped min/max values. + VkRect2D scissor; + scissor.offset.x = (int32_t)(pcmd->ClipRect.x - display_pos.x) > 0 ? (int32_t)(pcmd->ClipRect.x - display_pos.x) : 0; + scissor.offset.y = (int32_t)(pcmd->ClipRect.y - display_pos.y) > 0 ? (int32_t)(pcmd->ClipRect.y - display_pos.y) : 0; + scissor.extent.width = (uint32_t)(pcmd->ClipRect.z - pcmd->ClipRect.x); + scissor.extent.height = (uint32_t)(pcmd->ClipRect.w - pcmd->ClipRect.y + 1); // FIXME: Why +1 here? + device_data->vtable.CmdSetScissor(draw->command_buffer, 0, 1, &scissor); +#if 0 //enable if using >1 font textures or use texture array + VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId }; + device_data->vtable.CmdBindDescriptorSets(draw->command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, + data->pipeline_layout, 0, 1, desc_set, 0, NULL); +#endif + // Draw + device_data->vtable.CmdDrawIndexed(draw->command_buffer, pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.Size; + } device_data->vtable.CmdEndRenderPass(draw->command_buffer); @@ -1896,6 +2040,7 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) NULL, &data->descriptor_layout)); /* Descriptor set */ +/* VkDescriptorSetAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.descriptorPool = data->descriptor_pool; @@ -1904,6 +2049,7 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) VK_CHECK(device_data->vtable.AllocateDescriptorSets(device_data->device, &alloc_info, &data->descriptor_set)); +*/ /* Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full * 3d projection matrix @@ -2025,68 +2171,21 @@ static void setup_swapchain_data_pipeline(struct swapchain_data *data) device_data->vtable.DestroyShaderModule(device_data->device, vert_module, NULL); device_data->vtable.DestroyShaderModule(device_data->device, frag_module, NULL); + create_fonts(device_data->instance->params, data->sw_stats.font1, data->sw_stats.font_text); + ImGuiIO& io = ImGui::GetIO(); - create_fonts(device_data->instance->params, data->font, data->sw_stats.font1); unsigned char* pixels; int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - - /* Font image */ - VkImageCreateInfo image_info = {}; - image_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image_info.imageType = VK_IMAGE_TYPE_2D; - image_info.format = VK_FORMAT_R8G8B8A8_UNORM; - image_info.extent.width = width; - image_info.extent.height = height; - image_info.extent.depth = 1; - image_info.mipLevels = 1; - image_info.arrayLayers = 1; - image_info.samples = VK_SAMPLE_COUNT_1_BIT; - image_info.tiling = VK_IMAGE_TILING_OPTIMAL; - image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VK_CHECK(device_data->vtable.CreateImage(device_data->device, &image_info, - NULL, &data->font_image)); - VkMemoryRequirements font_image_req; - device_data->vtable.GetImageMemoryRequirements(device_data->device, - data->font_image, &font_image_req); - VkMemoryAllocateInfo image_alloc_info = {}; - image_alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - image_alloc_info.allocationSize = font_image_req.size; - image_alloc_info.memoryTypeIndex = vk_memory_type(device_data, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - font_image_req.memoryTypeBits); - VK_CHECK(device_data->vtable.AllocateMemory(device_data->device, &image_alloc_info, - NULL, &data->font_mem)); - VK_CHECK(device_data->vtable.BindImageMemory(device_data->device, - data->font_image, - data->font_mem, 0)); - /* Font image view */ - VkImageViewCreateInfo view_info = {}; - view_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view_info.image = data->font_image; - view_info.viewType = VK_IMAGE_VIEW_TYPE_2D; - view_info.format = VK_FORMAT_R8G8B8A8_UNORM; - view_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - view_info.subresourceRange.levelCount = 1; - view_info.subresourceRange.layerCount = 1; - VK_CHECK(device_data->vtable.CreateImageView(device_data->device, &view_info, - NULL, &data->font_image_view)); + // upload default font to VkImage + io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height); + io.Fonts->TexID = (ImTextureID)create_image_with_desc(data, width, height, VK_FORMAT_R8_UNORM, data->font_image, data->font_mem, data->font_image_view); +#ifndef NDEBUG + std::cerr << "MANGOHUD: Default font tex size: " << width << "x" << height << "px (" << (width*height*1) << " bytes)" << "\n"; +#endif - /* Descriptor set */ - VkDescriptorImageInfo desc_image[1] = {}; - desc_image[0].sampler = data->font_sampler; - desc_image[0].imageView = data->font_image_view; - desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - VkWriteDescriptorSet write_desc[1] = {}; - write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write_desc[0].dstSet = data->descriptor_set; - write_desc[0].descriptorCount = 1; - write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - write_desc[0].pImageInfo = desc_image; - device_data->vtable.UpdateDescriptorSets(device_data->device, 1, write_desc, 0, NULL); +// if (data->descriptor_set) +// update_image_descriptor(data, data->font_image_view[0], data->descriptor_set); } void imgui_custom_style(struct overlay_params& params){ @@ -2710,9 +2809,9 @@ static VkResult overlay_CreateInstance( // Adjust height for DXVK/VKD3D version number if (engineName == "DXVK" || engineName == "VKD3D"){ if (instance_data->params.font_size){ - instance_data->params.height += instance_data->params.font_size / 2; + instance_data->params.height += instance_data->params.font_size * instance_data->params.font_scale / 2; } else { - instance_data->params.height += 24 / 2; + instance_data->params.height += 24 * instance_data->params.font_scale / 2; } } diff --git a/src/overlay.frag b/src/overlay.frag index 313a8880..dc6bb007 100644 --- a/src/overlay.frag +++ b/src/overlay.frag @@ -10,5 +10,5 @@ layout(location = 0) in struct{ void main() { - fColor = In.Color * texture(sTexture, In.UV.st); + fColor = In.Color * vec4(1, 1, 1, texture(sTexture, In.UV.st).r); } diff --git a/src/overlay.h b/src/overlay.h index cb66dcc8..67e1a579 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -18,6 +20,7 @@ struct swapchain_stats { struct frame_stat frames_stats[200]; ImFont* font1 = nullptr; + ImFont* font_text = nullptr; std::string time; double fps; struct iostats io; @@ -77,4 +80,4 @@ void FpsLimiter(struct fps_limit& stats); void imgui_custom_style(struct overlay_params& params); void get_device_name(int32_t vendorID, int32_t deviceID, struct swapchain_stats& sw_stats); void calculate_benchmark_data(void); -void create_fonts(const overlay_params& params, ImFont*& default_font, ImFont*& small_font); +void create_fonts(const overlay_params& params, ImFont*& small_font, ImFont*& text_font); diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index 39556f16..a597be2e 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -202,6 +202,38 @@ parse_media_player_order(const char *str) return order; } +static uint32_t +parse_font_glyph_ranges(const char *str) +{ + uint32_t fg = 0; + std::stringstream ss(str); + std::string token; + while (std::getline(ss, token, ',')) { + trim(token); + std::transform(token.begin(), token.end(), token.begin(), ::tolower); + + if (token == "korean") + fg |= FG_KOREAN; + else if (token == "chinese") + fg |= FG_CHINESE_FULL; + else if (token == "chinese_simplified") + fg |= FG_CHINESE_SIMPLIFIED; + else if (token == "japanese") + fg |= FG_JAPANESE; + else if (token == "cyrillic") + fg |= FG_CYRILLIC; + else if (token == "thai") + fg |= FG_THAI; + else if (token == "vietnamese") + fg |= FG_VIETNAMESE; + else if (token == "latin_ext_a") + fg |= FG_LATIN_EXT_A; + else if (token == "latin_ext_b") + fg |= FG_LATIN_EXT_B; + } + return fg; +} + #define parse_width(s) parse_unsigned(s) #define parse_height(s) parse_unsigned(s) #define parse_vsync(s) parse_unsigned(s) @@ -212,6 +244,7 @@ parse_media_player_order(const char *str) #define parse_time_format(s) parse_str(s) #define parse_output_file(s) parse_path(s) #define parse_font_file(s) parse_path(s) +#define parse_font_file_text(s) parse_path(s) #define parse_io_read(s) parse_unsigned(s) #define parse_io_write(s) parse_unsigned(s) #define parse_pci_dev(s) parse_str(s) @@ -221,6 +254,8 @@ parse_media_player_order(const char *str) #define parse_gpu_text(s) parse_str(s) #define parse_log_interval(s) parse_unsigned(s) #define parse_font_size(s) parse_float(s) +#define parse_font_size_text(s) parse_float(s) +#define parse_font_scale(s) parse_float(s) #define parse_background_alpha(s) parse_float(s) #define parse_alpha(s) parse_float(s) #define parse_permit_upload(s) parse_unsigned(s) @@ -389,6 +424,7 @@ parse_overlay_config(struct overlay_params *params, params->text_color = 0xffffff; params->media_player_color = 0xffffff; params->media_player_name = "spotify"; + params->font_scale = 1.0f; params->font_scale_media_player = 0.55f; params->log_interval = 100; params->media_player_order = { MP_ORDER_TITLE, MP_ORDER_ARTIST, MP_ORDER_ALBUM }; @@ -478,9 +514,9 @@ parse_overlay_config(struct overlay_params *params, //increase hud width if io read and write if (!params->width) { if ((params->enabled[OVERLAY_PARAM_ENABLED_io_read] || params->enabled[OVERLAY_PARAM_ENABLED_io_write])) { - params->width = 13 * params->font_size; + params->width = 13 * params->font_size * params->font_scale; } else { - params->width = params->font_size * 11.7; + params->width = params->font_size * params->font_scale * 11.7; } } diff --git a/src/overlay_params.h b/src/overlay_params.h index 05a6181b..84ebe3b0 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -51,6 +51,12 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_file) \ OVERLAY_PARAM_CUSTOM(font_file) \ + OVERLAY_PARAM_CUSTOM(font_file_text) \ + OVERLAY_PARAM_CUSTOM(font_glyph_ranges) \ + OVERLAY_PARAM_CUSTOM(font_size) \ + OVERLAY_PARAM_CUSTOM(font_size_text) \ + OVERLAY_PARAM_CUSTOM(font_scale) \ + OVERLAY_PARAM_CUSTOM(font_scale_media_player) \ OVERLAY_PARAM_CUSTOM(position) \ OVERLAY_PARAM_CUSTOM(width) \ OVERLAY_PARAM_CUSTOM(height) \ @@ -59,8 +65,6 @@ typedef unsigned long KeySym; OVERLAY_PARAM_CUSTOM(fps_limit) \ OVERLAY_PARAM_CUSTOM(vsync) \ OVERLAY_PARAM_CUSTOM(gl_vsync) \ - OVERLAY_PARAM_CUSTOM(font_size) \ - OVERLAY_PARAM_CUSTOM(font_scale_media_player) \ OVERLAY_PARAM_CUSTOM(toggle_hud) \ OVERLAY_PARAM_CUSTOM(toggle_logging) \ OVERLAY_PARAM_CUSTOM(reload_cfg) \ @@ -111,6 +115,18 @@ enum media_player_order { MP_ORDER_ALBUM, }; +enum font_glyph_ranges { + FG_KOREAN = (1u << 0), + FG_CHINESE_FULL = (1u << 1), + FG_CHINESE_SIMPLIFIED = (1u << 2), + FG_JAPANESE = (1u << 3), + FG_CYRILLIC = (1u << 4), + FG_THAI = (1u << 5), + FG_VIETNAMESE = (1u << 6), + FG_LATIN_EXT_A = (1u << 7), + FG_LATIN_EXT_B = (1u << 8), +}; + enum overlay_param_enabled { #define OVERLAY_PARAM_BOOL(name) OVERLAY_PARAM_ENABLED_##name, #define OVERLAY_PARAM_CUSTOM(name) @@ -139,20 +155,24 @@ struct overlay_params { unsigned cpu_color, gpu_color, vram_color, ram_color, engine_color, io_color, frametime_color, background_color, text_color; unsigned media_player_color; unsigned tableCols; - float font_size; + float font_size, font_scale; + float font_size_text; float font_scale_media_player; float background_alpha, alpha; std::vector toggle_hud; std::vector toggle_logging; std::vector reload_cfg; std::vector upload_log; - std::string time_format, output_file, font_file; + std::string time_format, output_file; std::string pci_dev; std::string media_player_name; std::string cpu_text, gpu_text; unsigned log_interval; std::vector media_player_order; + std::string font_file, font_file_text; + uint32_t font_glyph_ranges; + std::string config_file_path; std::unordered_map options; int permit_upload;