Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Images component, background image component #642

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
| `arch` | Show if the application is 32- or 64-bit |
| `autostart_log=` | Starts the log after X seconds from mangohud init |
| `background_alpha` | Set the opacity of the background `0.0`-`1.0` |
| `background_image` | Display a background image from argument path on the whole screen (eventually transparent) |
| `battery_color` | Change the battery text color |
| `battery_icon` | Display battery icon instead of percent |
| `battery_watt` | Display wattage for the battery option |
Expand Down Expand Up @@ -379,6 +380,8 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
| `horizontal_stretch` | Stretches the background to the screens width in `horizontal` mode |
| `hud_compact` | Display compact version of MangoHud |
| `hud_no_margin` | Remove margins around MangoHud |
| `image` | Display an image from argument path |
| `image_max_width` | Maximize the image by a max number of pixel for the width |
| `io_read`<br> `io_write` | Show non-cached IO read/write, in MiB/s |
| `log_duration` | Set amount of time the logging will run for (in seconds) |
| `log_interval` | Change the default log interval in milliseconds. Default is `0` |
Expand Down
7 changes: 7 additions & 0 deletions data/MangoHud.conf
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,13 @@ frame_timing
### Display output of Bash command in next column
# exec=

### Display a background image from argument path on the whole screen (eventually transparent)
# background_image=
### Display an image from argument path
# image=
### Maximize the image by a max number of pixel for the width
# image_max_width=

### Display media player metadata
# media_player
## for example spotify
Expand Down
25 changes: 14 additions & 11 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ else
dep_rt = null_dep
endif

if get_option('use_vulkan')
# Commented code can be used if mangohud start using latest SDK Vulkan-Headers
# Allowing user to build mangohud using system Vulkan-Headers
#if not dependency('VulkanHeaders').found()
Expand All @@ -177,17 +178,19 @@ endif
# vk_api_xml = files('/usr/share/vulkan/registry/vk.xml')
#endif



vk_enum_to_str = custom_target(
'vk_enum_to_str',
input : ['bin/gen_enum_to_str.py', vk_api_xml],
output : ['vk_enum_to_str.c', 'vk_enum_to_str.h'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
'--outdir', meson.current_build_dir()
],
)
vk_enum_to_str = custom_target(
'vk_enum_to_str',
input : ['bin/gen_enum_to_str.py', vk_api_xml],
output : ['vk_enum_to_str.c', 'vk_enum_to_str.h'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
'--outdir', meson.current_build_dir()
],
)
else
dep_vulkan = null_dep
vk_enum_to_str = []
endif

imgui_options = [
'default_library=static',
Expand Down
1 change: 1 addition & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ option('with_nvml', type : 'combo', value : 'enabled', choices: ['enabled', 'sys
option('with_xnvctrl', type : 'feature', value : 'enabled', description: 'Enable XNVCtrl support')
option('with_x11', type : 'feature', value : 'enabled')
option('with_wayland', type : 'feature', value : 'enabled')
option('use_vulkan', type : 'boolean', value : true)
option('with_dbus', type : 'feature', value : 'enabled')
option('loglevel', type: 'combo', choices : ['trace', 'debug', 'info', 'warn', 'err', 'critical', 'off'], value : 'info', description: 'Max log level in non-debug build')
option('mangoapp', type: 'boolean', value : false)
Expand Down
12 changes: 6 additions & 6 deletions src/gl/gl_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
ImGuiIO& io = ImGui::GetIO();
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsAlpha8(&pixels, &width, &height);
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);

GLint last_texture, last_unpack_buffer;

Expand All @@ -128,7 +128,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture()
if (g_IsGLES || g_GlVersion >= 200)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

// Store our identifier
io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontTexture);
Expand Down Expand Up @@ -259,7 +259,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"varying vec4 Frag_Color;\n"
"void main()\n"
"{\n"
" gl_FragColor = Frag_Color * vec4(1, 1, 1, texture2D(Texture, Frag_UV.st).r);\n"
" gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
"}\n";

const GLchar* fragment_shader_glsl_130 =
Expand All @@ -269,7 +269,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).r);\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";

const GLchar* fragment_shader_glsl_300_es =
Expand All @@ -280,7 +280,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"layout (location = 0) out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).r);\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";

const GLchar* fragment_shader_glsl_410_core =
Expand All @@ -290,7 +290,7 @@ static bool ImGui_ImplOpenGL3_CreateDeviceObjects()
"layout (location = 0) out vec4 Out_Color;\n"
"void main()\n"
"{\n"
" Out_Color = Frag_Color * vec4(1, 1, 1, texture(Texture, Frag_UV.st).r);\n"
" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
"}\n";

SPDLOG_DEBUG("glsl_version: {}", glsl_version);
Expand Down
5 changes: 5 additions & 0 deletions src/gl/inject_egl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <chrono>
#include <iomanip>
#include <spdlog/spdlog.h>
#include <glad/glad.h>
#include "real_dlsym.h"
#include "mesa/util/macros.h"
#include "mesa/util/os_time.h"
Expand All @@ -25,6 +26,10 @@ static void* get_egl_proc_address(const char* name) {
SPDLOG_ERROR("Failed to open " MANGOHUD_ARCH " libEGL.so.1: {}", dlerror());
} else {
pfn_eglGetProcAddress = reinterpret_cast<decltype(pfn_eglGetProcAddress)>(real_dlsym(handle, "eglGetProcAddress"));

if(gladLoadGLES2Loader((GLADloadproc)pfn_eglGetProcAddress) == 0) {
pfn_eglGetProcAddress = nullptr;
}
}
}

Expand Down
84 changes: 81 additions & 3 deletions src/hud_elements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#endif
#include "amdgpu.h"
#include "fps_metrics.h"
#include "load_textures.h"

#define CHAR_CELSIUS "\xe2\x84\x83"
#define CHAR_FAHRENHEIT "\xe2\x84\x89"
Expand Down Expand Up @@ -680,6 +681,7 @@ void HudElements::engine_version(){
ImguiNextColumnFirstItem();
ImGui::PushFont(HUDElements.sw_stats->font1);
if (HUDElements.is_vulkan) {
#ifdef HAVE_VULKAN
if ((HUDElements.sw_stats->engine == EngineTypes::DXVK || HUDElements.sw_stats->engine == EngineTypes::VKD3D)){
HUDElements.TextColored(HUDElements.colors.engine,
"%s/%d.%d.%d", HUDElements.sw_stats->engineVersion.c_str(),
Expand All @@ -693,6 +695,7 @@ void HudElements::engine_version(){
HUDElements.sw_stats->version_vk.minor,
HUDElements.sw_stats->version_vk.patch);
}
#endif
} else {
HUDElements.TextColored(HUDElements.colors.engine,
"%d.%d%s", HUDElements.sw_stats->version_gl.major, HUDElements.sw_stats->version_gl.minor,
Expand Down Expand Up @@ -922,6 +925,80 @@ void HudElements::custom_text_center(){
}
}

void HudElements::image(){
const std::string& value = HUDElements.ordered_functions[HUDElements.place].value;
nadenislamarre marked this conversation as resolved.
Show resolved Hide resolved

// load the image if needed
if (HUDElements.image_infos.loaded == false) {
unsigned maxwidth = HUDElements.params->width;
if (HUDElements.params->image_max_width != 0 && HUDElements.params->image_max_width < maxwidth) {
maxwidth = HUDElements.params->image_max_width;
}

HUDElements.image_infos.loaded = true;
if (HUDElements.is_vulkan) {
#ifdef HAVE_VULKAN
if ((HUDElements.image_infos.texture = add_texture(HUDElements.sw_stats, value, &(HUDElements.image_infos.width), &(HUDElements.image_infos.height), maxwidth)))
HUDElements.image_infos.valid = true;
#endif
} else {
#ifndef HAVE_VULKAN
HUDElements.image_infos.valid = GL_LoadTextureFromFile(value.c_str(),
reinterpret_cast<unsigned int*>(&(HUDElements.image_infos.texture)),
&(HUDElements.image_infos.width),
&(HUDElements.image_infos.height),
maxwidth);
#endif
}

if (HUDElements.image_infos.valid)
SPDLOG_INFO("Image {} loaded ({}x{})", value, HUDElements.image_infos.width, HUDElements.image_infos.height);
else
SPDLOG_WARN("Failed to load image: {}", value);
}

// render the image
if (HUDElements.image_infos.valid) {
ImGui::TableNextRow(); ImGui::TableNextColumn();
ImGui::Image(HUDElements.image_infos.texture, ImVec2(HUDElements.image_infos.width, HUDElements.image_infos.height));
}
}

void HudElements::background_image(){
const std::string& value = HUDElements.params->background_image;

// load the image if needed
if (HUDElements.background_image_infos.loaded == false) {
HUDElements.background_image_infos.loaded = true;
if (HUDElements.is_vulkan) {
#ifdef HAVE_VULKAN
if ((HUDElements.background_image_infos.texture = add_texture(HUDElements.sw_stats, value, &(HUDElements.background_image_infos.width), &(HUDElements.background_image_infos.height), 0)))
HUDElements.background_image_infos.valid = true;
#endif
} else {
#ifndef HAVE_VULKAN
HUDElements.background_image_infos.valid = GL_LoadTextureFromFile(value.c_str(),
reinterpret_cast<unsigned int*>(&(HUDElements.background_image_infos.texture)),
&(HUDElements.background_image_infos.width),
&(HUDElements.background_image_infos.height),
0);
#endif
}

if (HUDElements.background_image_infos.valid)
SPDLOG_INFO("Image {} loaded ({}x{})", value, HUDElements.background_image_infos.width, HUDElements.background_image_infos.height);
else
SPDLOG_WARN("Failed to load image: {}", value);
}

// render the image
if (HUDElements.background_image_infos.valid) {
ImGui::GetBackgroundDrawList()->AddImage(HUDElements.background_image_infos.texture,
ImVec2(0, 0),
ImVec2(HUDElements.background_image_infos.width, HUDElements.background_image_infos.height));
}
}

void HudElements::custom_text(){
ImguiNextColumnFirstItem();
ImGui::PushFont(HUDElements.sw_stats->font1);
Expand Down Expand Up @@ -1089,7 +1166,7 @@ void HudElements::gamescope_frame_timing(){
HUDElements.gamescope_debug_app.end());
auto max = std::max_element(HUDElements.gamescope_debug_app.begin(),
HUDElements.gamescope_debug_app.end());

ImGui::PushFont(HUDElements.sw_stats->font1);
ImGui::Dummy(ImVec2(0.0f, real_font_size.y));
HUDElements.TextColored(HUDElements.colors.engine, "%s", "App");
Expand Down Expand Up @@ -1522,8 +1599,9 @@ void HudElements::sort_elements(const std::pair<std::string, std::string>& optio
{"refresh_rate", {refresh_rate}},
{"winesync", {winesync}},
{"present_mode", {present_mode}},
{"network", {network}}

{"network", {network}},
{"background_image", {background_image}},
{"image", {image}},
nadenislamarre marked this conversation as resolved.
Show resolved Hide resolved
};

auto check_param = display_params.find(param);
Expand Down
22 changes: 22 additions & 0 deletions src/hud_elements.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,29 @@ struct Function {
std::string value;
};

struct image_infos {
std::string path;
int width;
int height;
bool loaded;
bool valid;
ImTextureID texture;

image_infos() {
loaded = false;
valid = false;
}

~image_infos() {
}
};


struct overlay_params;
class HudElements{
public:
struct image_infos image_infos;
struct image_infos background_image_infos;
struct swapchain_stats *sw_stats;
struct overlay_params *params;
struct exec_entry {
Expand Down Expand Up @@ -83,6 +103,8 @@ class HudElements{
static void show_fps_limit();
static void custom_text_center();
static void custom_text();
static void image();
static void background_image();
static void vkbasalt();
static void gamemode();
static void graphs();
Expand Down
64 changes: 64 additions & 0 deletions src/load_textures.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "load_textures.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize2.h"

bool GL_LoadTextureFromFile(const char* filename, GLuint* out_texture, int* out_width, int* out_height, int maxwidth)
{
(void)stbir__support_zero;
// load the image
int image_width = 0;
int image_height = 0;
int channels;
auto image_data = stbi_load(filename, &image_width, &image_height, &channels, STBI_rgb_alpha);
if (!image_data)
return false;

// reduce the image
float ratio = 1;
if (image_width > maxwidth && maxwidth != 0) {
ratio = maxwidth / static_cast<float>(image_width);
}

int image_width_resized = image_width * ratio;
int image_height_resized = image_height * ratio;

if (ratio != 1)
{
unsigned char* image_data_resized = (unsigned char*)stbi__malloc(image_width_resized * image_height_resized * 4);
if (!image_data_resized) {
stbi_image_free(image_data);
return false;
}
stbir_resize_uint8_linear(image_data, image_width, image_height, 0,
image_data_resized, image_width_resized, image_height_resized, 0,
STBIR_RGBA);
stbi_image_free(image_data);
image_data = image_data_resized;
}

// Create a OpenGL texture identifier
GLuint image_texture;
glGenTextures(1, &image_texture);
glBindTexture(GL_TEXTURE_2D, image_texture);

// Setup filtering parameters for display
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same

// Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width_resized, image_height_resized, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
stbi_image_free(image_data);

*out_texture = image_texture;
*out_width = image_width_resized;
*out_height = image_height_resized;

return true;
}
4 changes: 4 additions & 0 deletions src/load_textures.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once
#include <glad/glad.h>

bool GL_LoadTextureFromFile(const char* filename, GLuint* out_texture, int* out_width, int* out_height, int maxwidth);
Loading
Loading