From 8cd317233509cffc29cbdedcfe7d3512d5f1cfff Mon Sep 17 00:00:00 2001 From: jackun Date: Thu, 2 Apr 2020 01:30:47 +0300 Subject: [PATCH] [OpenGL] Separate GLX out from shareable code so wayland sessions can just use EGL, hopefully --- src/gl/imgui_hud.cpp | 86 +++--- src/gl/imgui_hud.h | 16 +- src/gl/imgui_hud_shared.cpp | 31 ++ src/gl/imgui_hud_shared.h | 15 + src/gl/imgui_impl_opengl3.cpp | 533 +++++++++++++++++----------------- src/gl/imgui_impl_opengl3.h | 31 +- src/gl/inject_glx.cpp | 41 +-- src/keybinds.h | 2 + src/loaders/loader_x11.cpp | 4 +- src/loaders/loader_x11.h | 4 +- src/meson.build | 88 +++++- src/overlay_params.cpp | 13 +- 12 files changed, 503 insertions(+), 361 deletions(-) create mode 100644 src/gl/imgui_hud_shared.cpp create mode 100644 src/gl/imgui_hud_shared.h diff --git a/src/gl/imgui_hud.cpp b/src/gl/imgui_hud.cpp index 1f116e02..19ef3584 100644 --- a/src/gl/imgui_hud.cpp +++ b/src/gl/imgui_hud.cpp @@ -1,17 +1,17 @@ #include #include #include -#include -#include "GL/gl3w.h" -#include -#include "imgui_impl_opengl3.h" #include "font_default.h" -#include "overlay.h" #include "cpu.h" #include "file_utils.h" -#include "notify.h" +#include "imgui_hud_shared.h" +#include "imgui_hud.h" -using namespace MangoHud; +#ifdef IMGUI_GLX +#include "GL/gl3w.h" +#endif + +namespace MangoHud { namespace GL { struct GLVec { @@ -43,34 +43,12 @@ struct state { }; static GLVec last_vp {}, last_sb {}; -static ImVec2 window_size; static swapchain_stats sw_stats {}; static state state; -static notify_thread notifier; -static bool cfg_inited = false; -static bool inited = false; static uint32_t vendorID; static std::string deviceName; -overlay_params params {}; - -// seems to quit by itself though -static std::unique_ptr> - stop_it(¬ifier, [](notify_thread *n){ stop_notifier(*n); }); - -void imgui_init() -{ - if (cfg_inited) - return; - parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); - notifier.params = ¶ms; - start_notifier(notifier); - window_size = ImVec2(params.width, params.height); - init_system_info(); - cfg_inited = true; - init_cpu_stats(params); -} -void imgui_create(void *ctx) +static void imgui_create(void *ctx) { if (inited) return; @@ -80,7 +58,6 @@ void imgui_create(void *ctx) return; imgui_init(); - gl3wInit(); std::cerr << "GL version: " << glGetString(GL_VERSION) << std::endl; glGetIntegerv(GL_MAJOR_VERSION, &sw_stats.version_gl.major); @@ -113,7 +90,7 @@ void imgui_create(void *ctx) ImGui::GetIO().IniFilename = NULL; ImGui::GetIO().DisplaySize = ImVec2(last_vp[2], last_vp[3]); - ImGui_ImplOpenGL3_Init(); + VARIANT(ImGui_ImplOpenGL3_Init)(); // Make a dummy GL call (we don't actually need the result) // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. @@ -141,7 +118,34 @@ void imgui_create(void *ctx) ImGui::SetCurrentContext(saved_ctx); } -void imgui_shutdown() +#ifdef IMGUI_GLX +void VARIANT(imgui_create)(void *ctx) +{ + if (inited) + return; + + if (!ctx) + return; + + gl3wInit(); + imgui_create(ctx); +} +#endif + +#ifdef IMGUI_EGL +void VARIANT(imgui_create)(void *ctx) +{ + if (inited) + return; + + if (!ctx) + return; + + imgui_create(ctx); +} +#endif + +void VARIANT(imgui_shutdown)() { #ifndef NDEBUG std::cerr << __func__ << std::endl; @@ -149,26 +153,26 @@ void imgui_shutdown() if (state.imgui_ctx) { ImGui::SetCurrentContext(state.imgui_ctx); - ImGui_ImplOpenGL3_Shutdown(); + VARIANT(ImGui_ImplOpenGL3_Shutdown)(); ImGui::DestroyContext(state.imgui_ctx); state.imgui_ctx = nullptr; } inited = false; } -void imgui_set_context(void *ctx) +void VARIANT(imgui_set_context)(void *ctx) { if (!ctx) { - imgui_shutdown(); + VARIANT(imgui_shutdown)(); return; } #ifndef NDEBUG std::cerr << __func__ << ": " << ctx << std::endl; #endif - imgui_create(ctx); + VARIANT(imgui_create)(ctx); } -void imgui_render(unsigned int width, unsigned int height) +void VARIANT(imgui_render)(unsigned int width, unsigned int height) { if (!state.imgui_ctx) return; @@ -180,7 +184,7 @@ void imgui_render(unsigned int width, unsigned int height) ImGui::SetCurrentContext(state.imgui_ctx); ImGui::GetIO().DisplaySize = ImVec2(width, height); - ImGui_ImplOpenGL3_NewFrame(); + VARIANT(ImGui_ImplOpenGL3_NewFrame)(); ImGui::NewFrame(); { std::lock_guard lk(notifier.mutex); @@ -190,6 +194,8 @@ void imgui_render(unsigned int width, unsigned int height) ImGui::PopStyleVar(3); ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + VARIANT(ImGui_ImplOpenGL3_RenderDrawData)(ImGui::GetDrawData()); ImGui::SetCurrentContext(saved_ctx); } + +}} // namespaces diff --git a/src/gl/imgui_hud.h b/src/gl/imgui_hud.h index 79a18226..60712f5e 100644 --- a/src/gl/imgui_hud.h +++ b/src/gl/imgui_hud.h @@ -1,7 +1,13 @@ #pragma once -void imgui_init(); -void imgui_create(void *ctx); -void imgui_shutdown(); -void imgui_set_context(void *ctx); -void imgui_render(unsigned int width, unsigned int height); +#include "imgui_impl_opengl3.h" + +namespace MangoHud { namespace GL { + +void VARIANT(imgui_init)(); +void VARIANT(imgui_create)(void *ctx); +void VARIANT(imgui_shutdown)(); +void VARIANT(imgui_set_context)(void *ctx); +void VARIANT(imgui_render)(unsigned int width, unsigned int height); + +}} // namespace diff --git a/src/gl/imgui_hud_shared.cpp b/src/gl/imgui_hud_shared.cpp new file mode 100644 index 00000000..12544797 --- /dev/null +++ b/src/gl/imgui_hud_shared.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include "imgui_hud_shared.h" + +namespace MangoHud { namespace GL { + +notify_thread notifier; +static bool cfg_inited = false; +ImVec2 window_size; +bool inited = false; +overlay_params params {}; + +// seems to quit by itself though +static std::unique_ptr> + stop_it(¬ifier, [](notify_thread *n){ stop_notifier(*n); }); + +void imgui_init() +{ + if (cfg_inited) + return; + parse_overlay_config(¶ms, getenv("MANGOHUD_CONFIG")); + notifier.params = ¶ms; + start_notifier(notifier); + window_size = ImVec2(params.width, params.height); + init_system_info(); + cfg_inited = true; + init_cpu_stats(params); +} + +}} // namespaces diff --git a/src/gl/imgui_hud_shared.h b/src/gl/imgui_hud_shared.h new file mode 100644 index 00000000..499404e9 --- /dev/null +++ b/src/gl/imgui_hud_shared.h @@ -0,0 +1,15 @@ +#pragma once +#include +#include "overlay.h" +#include "notify.h" + +namespace MangoHud { namespace GL { + +extern notify_thread notifier; +extern ImVec2 window_size; +extern bool inited; +extern overlay_params params; + +void imgui_init(); + +}} // namespaces diff --git a/src/gl/imgui_impl_opengl3.cpp b/src/gl/imgui_impl_opengl3.cpp index cfd502ce..290f59c1 100644 --- a/src/gl/imgui_impl_opengl3.cpp +++ b/src/gl/imgui_impl_opengl3.cpp @@ -63,19 +63,25 @@ // ES 3.0 300 "#version 300 es" = WebGL 2.0 //---------------------------------------- -#include "imgui.h" +#include #include "imgui_impl_opengl3.h" #include #include // intptr_t +#ifdef IMGUI_GLX #include +#endif + +#ifdef IMGUI_GLX + #define GL_CLIP_ORIGIN 0x935C #define GL_NEGATIVE_ONE_TO_ONE 0x935E #define GL_ZERO_TO_ONE 0x935F #define GL_CLIP_DEPTH_MODE 0x935D void* get_glx_proc_address(const char* name); -void (*glClipControl)(int origin, int depth); +void (*glClipControl)(int origin, int depth) = nullptr; +#endif namespace MangoHud { @@ -96,263 +102,7 @@ static int g_AttribLocationVtxPos = 0, g_AttribLocationVtxUV = 0, g_Att static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; // Functions -bool ImGui_ImplOpenGL3_Init(const char* glsl_version) -{ - glClipControl = reinterpret_cast (get_glx_proc_address("glClipControl")); - - // Query for GL version -#if !defined(IMGUI_IMPL_OPENGL_ES2) - - glsl_version = "#version 130"; - GLint major = -1, minor = -1; - glGetIntegerv(GL_MAJOR_VERSION, &major); - glGetIntegerv(GL_MINOR_VERSION, &minor); - g_GlVersion = major * 1000 + minor; - printf("Version: %d.%d\n", major, minor); - if (major >= 4 && minor >= 1) - glsl_version = "#version 410"; - else if (major > 3 || (major == 3 && minor >= 2)) - glsl_version = "#version 150"; - -#else - g_GlVersion = 2000; // GLES 2 -#endif - - // Setup back-end capabilities flags - ImGuiIO& io = ImGui::GetIO(); - io.BackendRendererName = "imgui_impl_opengl3"; -#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET - if (g_GlVersion >= 3200) - io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. -#endif - - // Store GLSL version string so we can refer to it later in case we recreate shaders. - // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. - if (glsl_version == NULL) - glsl_version = "#version 130"; - - IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); - strcpy(g_GlslVersionString, glsl_version); - strcat(g_GlslVersionString, "\n"); - - // Make a dummy GL call (we don't actually need the result) - // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. - // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. - GLint current_texture; - glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); - - return true; -} - -void ImGui_ImplOpenGL3_Shutdown() -{ - ImGui_ImplOpenGL3_DestroyDeviceObjects(); -} - -void ImGui_ImplOpenGL3_NewFrame() -{ - if (!g_ShaderHandle) - ImGui_ImplOpenGL3_CreateDeviceObjects(); -} - -static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) -{ - // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -#endif - - // Setup viewport, orthographic projection matrix - // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. - glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); - float L = draw_data->DisplayPos.x; - float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; - float T = draw_data->DisplayPos.y; - float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; - const float ortho_projection[4][4] = - { - { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, - { 0.0f, 0.0f, -1.0f, 0.0f }, - { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, - }; - glUseProgram(g_ShaderHandle); - glUniform1i(g_AttribLocationTex, 0); - glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. -#endif - - (void)vertex_array_object; -#ifndef IMGUI_IMPL_OPENGL_ES2 - glBindVertexArray(vertex_array_object); -#endif - - // Bind vertex/index buffers and setup attributes for ImDrawVert - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); - glEnableVertexAttribArray(g_AttribLocationVtxPos); - glEnableVertexAttribArray(g_AttribLocationVtxUV); - glEnableVertexAttribArray(g_AttribLocationVtxColor); - glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); -} - -// OpenGL3 Render function. -// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) -// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -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) - return; - - // Backup GL state - GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); - glActiveTexture(GL_TEXTURE0); - GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); -#ifdef GL_SAMPLER_BINDING - GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); -#endif - GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); -#ifndef IMGUI_IMPL_OPENGL_ES2 - GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object); -#endif -#ifdef GL_POLYGON_MODE - GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); -#endif - GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); - GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); - GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); - GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); - GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); - GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); - GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); - GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); - GLboolean last_enable_blend = glIsEnabled(GL_BLEND); - GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); - GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); - GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - bool clip_origin_lower_left = true; -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) - GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) - GLenum last_clip_depth_mode = 0; glGetIntegerv(GL_CLIP_DEPTH_MODE, (GLint*)&last_clip_depth_mode); - if (last_clip_origin == GL_UPPER_LEFT) { - clip_origin_lower_left = false; - if (glClipControl) - glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); - } -#endif - - // Setup desired GL state - // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) - // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. - GLuint vertex_array_object = 0; -#ifndef IMGUI_IMPL_OPENGL_ES2 - glGenVertexArrays(1, &vertex_array_object); -#endif - ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); - - // Will project scissor/clipping rectangles into framebuffer space - ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports - ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) - - // Render command lists - for (int n = 0; n < draw_data->CmdListsCount; n++) - { - const ImDrawList* cmd_list = draw_data->CmdLists[n]; - - // Upload vertex/index buffers - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); - - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) - { - const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; - if (pcmd->UserCallback != NULL) - { - // User callback, registered via ImDrawList::AddCallback() - // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) - if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) - ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); - else - pcmd->UserCallback(cmd_list, pcmd); - } - else - { - // Project scissor/clipping rectangles into framebuffer space - ImVec4 clip_rect; - clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; - clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; - clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; - clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; - - if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) - { - // Apply scissor/clipping rectangle - //if (clip_origin_lower_left) - glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); - //else - // glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) - - // Bind texture, Draw - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); -#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET - if (g_GlVersion >= 3200) - glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); - else -#endif - glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); - } - } - } - } - - // Destroy the temporary VAO -#ifndef IMGUI_IMPL_OPENGL_ES2 - glDeleteVertexArrays(1, &vertex_array_object); -#endif - - // Restore modified GL state - glUseProgram(last_program); - glBindTexture(GL_TEXTURE_2D, last_texture); -#ifdef GL_SAMPLER_BINDING - glBindSampler(0, last_sampler); -#endif - glActiveTexture(last_active_texture); -#ifndef IMGUI_IMPL_OPENGL_ES2 - glBindVertexArray(last_vertex_array_object); -#endif - glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); - glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); - glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); - if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); - if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); - if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); - if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); -#ifdef GL_POLYGON_MODE - glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); -#endif - glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); - glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); - -#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) - if (!clip_origin_lower_left && glClipControl) - glClipControl(last_clip_origin, last_clip_depth_mode); -#endif -} - -bool ImGui_ImplOpenGL3_CreateFontsTexture() +static bool ImGui_ImplOpenGL3_CreateFontsTexture() { // Build texture atlas ImGuiIO& io = ImGui::GetIO(); @@ -381,7 +131,7 @@ bool ImGui_ImplOpenGL3_CreateFontsTexture() return true; } -void ImGui_ImplOpenGL3_DestroyFontsTexture() +static void ImGui_ImplOpenGL3_DestroyFontsTexture() { if (g_FontTexture) { @@ -428,7 +178,7 @@ static bool CheckProgram(GLuint handle, const char* desc) return (GLboolean)status == GL_TRUE; } -bool ImGui_ImplOpenGL3_CreateDeviceObjects() +static bool ImGui_ImplOpenGL3_CreateDeviceObjects() { // Backup GL state GLint last_texture, last_array_buffer; @@ -612,7 +362,7 @@ bool ImGui_ImplOpenGL3_CreateDeviceObjects() return true; } -void ImGui_ImplOpenGL3_DestroyDeviceObjects() +static void ImGui_ImplOpenGL3_DestroyDeviceObjects() { #ifndef NDEBUG printf("%s\n", __func__); @@ -627,4 +377,263 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects() ImGui_ImplOpenGL3_DestroyFontsTexture(); } + +bool VARIANT(ImGui_ImplOpenGL3_Init)(const char* glsl_version) +{ +#ifdef IMGUI_GLX + glClipControl = reinterpret_cast (get_glx_proc_address("glClipControl")); +#endif + + // Query for GL version +#if !defined(IMGUI_IMPL_OPENGL_ES2) + + glsl_version = "#version 130"; + GLint major = -1, minor = -1; + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); + g_GlVersion = major * 1000 + minor; + printf("Version: %d.%d\n", major, minor); + if (major >= 4 && minor >= 1) + glsl_version = "#version 410"; + else if (major > 3 || (major == 3 && minor >= 2)) + glsl_version = "#version 150"; + +#else + g_GlVersion = 2000; // GLES 2 +#endif + + // Setup back-end capabilities flags + ImGuiIO& io = ImGui::GetIO(); + io.BackendRendererName = "imgui_impl_opengl3"; +#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET + if (g_GlVersion >= 3200) + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. +#endif + + // Store GLSL version string so we can refer to it later in case we recreate shaders. + // Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure. + if (glsl_version == NULL) + glsl_version = "#version 130"; + + IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString)); + strcpy(g_GlslVersionString, glsl_version); + strcat(g_GlslVersionString, "\n"); + + // Make a dummy GL call (we don't actually need the result) + // IF YOU GET A CRASH HERE: it probably means that you haven't initialized the OpenGL function loader used by this code. + // Desktop OpenGL 3/4 need a function loader. See the IMGUI_IMPL_OPENGL_LOADER_xxx explanation above. + GLint current_texture; + glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); + + return true; +} + +void VARIANT(ImGui_ImplOpenGL3_Shutdown)() +{ + ImGui_ImplOpenGL3_DestroyDeviceObjects(); +} + +void VARIANT(ImGui_ImplOpenGL3_NewFrame)() +{ + if (!g_ShaderHandle) + ImGui_ImplOpenGL3_CreateDeviceObjects(); +} + +static void VARIANT(ImGui_ImplOpenGL3_SetupRenderState)(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) +{ + // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); +#ifdef GL_POLYGON_MODE + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif + + // Setup viewport, orthographic projection matrix + // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. + glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height); + float L = draw_data->DisplayPos.x; + float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; + float T = draw_data->DisplayPos.y; + float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; + const float ortho_projection[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, -1.0f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, + }; + glUseProgram(g_ShaderHandle); + glUniform1i(g_AttribLocationTex, 0); + glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); +#ifdef GL_SAMPLER_BINDING + glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. +#endif + + (void)vertex_array_object; +#ifndef IMGUI_IMPL_OPENGL_ES2 + glBindVertexArray(vertex_array_object); +#endif + + // Bind vertex/index buffers and setup attributes for ImDrawVert + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle); + glEnableVertexAttribArray(g_AttribLocationVtxPos); + glEnableVertexAttribArray(g_AttribLocationVtxUV); + glEnableVertexAttribArray(g_AttribLocationVtxColor); + glVertexAttribPointer(g_AttribLocationVtxPos, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationVtxUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); +} + +// OpenGL3 Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. +void VARIANT(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) + return; + + // Backup GL state + GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture); + glActiveTexture(GL_TEXTURE0); + GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); +#ifdef GL_SAMPLER_BINDING + GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler); +#endif + GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); +#ifndef IMGUI_IMPL_OPENGL_ES2 + GLint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array_object); +#endif +#ifdef GL_POLYGON_MODE + GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); +#endif + GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); + GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb); + GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb); + GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha); + GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha); + GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb); + GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha); + GLboolean last_enable_blend = glIsEnabled(GL_BLEND); + GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); + GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); + GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + bool clip_origin_lower_left = true; +#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) + GLenum last_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&last_clip_origin); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) + GLenum last_clip_depth_mode = 0; glGetIntegerv(GL_CLIP_DEPTH_MODE, (GLint*)&last_clip_depth_mode); + if (last_clip_origin == GL_UPPER_LEFT) { + clip_origin_lower_left = false; + if (glClipControl) + glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE); + } +#endif + + // Setup desired GL state + // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts) + // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound. + GLuint vertex_array_object = 0; +#ifndef IMGUI_IMPL_OPENGL_ES2 + glGenVertexArrays(1, &vertex_array_object); +#endif + VARIANT(ImGui_ImplOpenGL3_SetupRenderState)(draw_data, fb_width, fb_height, vertex_array_object); + + // Will project scissor/clipping rectangles into framebuffer space + ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports + ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) + + // Render command lists + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + + // Upload vertex/index buffers + glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); + + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback != NULL) + { + // User callback, registered via ImDrawList::AddCallback() + // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) + if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) + VARIANT(ImGui_ImplOpenGL3_SetupRenderState)(draw_data, fb_width, fb_height, vertex_array_object); + else + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + // Project scissor/clipping rectangles into framebuffer space + ImVec4 clip_rect; + clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; + clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; + clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; + clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; + + if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) + { + // Apply scissor/clipping rectangle + //if (clip_origin_lower_left) + glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); + //else + // glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) + + // Bind texture, Draw + glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); +#if IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET + if (g_GlVersion >= 3200) + glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset); + else +#endif + glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))); + } + } + } + } + + // Destroy the temporary VAO +#ifndef IMGUI_IMPL_OPENGL_ES2 + glDeleteVertexArrays(1, &vertex_array_object); +#endif + + // Restore modified GL state + glUseProgram(last_program); + glBindTexture(GL_TEXTURE_2D, last_texture); +#ifdef GL_SAMPLER_BINDING + glBindSampler(0, last_sampler); +#endif + glActiveTexture(last_active_texture); +#ifndef IMGUI_IMPL_OPENGL_ES2 + glBindVertexArray(last_vertex_array_object); +#endif + glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer); + glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha); + glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha); + if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); + if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); + if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); +#ifdef GL_POLYGON_MODE + glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); +#endif + glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); + glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); + +#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) + if (!clip_origin_lower_left && glClipControl) + glClipControl(last_clip_origin, last_clip_depth_mode); +#endif +} + } diff --git a/src/gl/imgui_impl_opengl3.h b/src/gl/imgui_impl_opengl3.h index 97044aa4..33747764 100644 --- a/src/gl/imgui_impl_opengl3.h +++ b/src/gl/imgui_impl_opengl3.h @@ -25,16 +25,31 @@ namespace MangoHud { +#if defined(IMGUI_GLX) && defined(IMGUI_EGL) +#error Both IMGUI_GLX and IMGUI_EGL can not be defined at the same time! +#elif !defined(IMGUI_GLX) && !defined(IMGUI_EGL) +#error Define IMGUI_GLX or IMGUI_EGL! +#endif + +#undef VARIANT +#ifdef IMGUI_GLX +#define VARIANT(x) x##_GLX +#endif + +#ifdef IMGUI_EGL +#define VARIANT(x) x##_EGL +#endif + // Backend API -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = nullptr); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data); +IMGUI_IMPL_API bool VARIANT(ImGui_ImplOpenGL3_Init)(const char* glsl_version = nullptr); +IMGUI_IMPL_API void VARIANT(ImGui_ImplOpenGL3_Shutdown)(); +IMGUI_IMPL_API void VARIANT(ImGui_ImplOpenGL3_NewFrame)(); +IMGUI_IMPL_API void VARIANT(ImGui_ImplOpenGL3_RenderDrawData)(ImDrawData* draw_data); // (Optional) Called by Init/NewFrame/Shutdown -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); -IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); -IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); +//IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateFontsTexture(); +//IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyFontsTexture(); +//IMGUI_IMPL_API bool ImGui_ImplOpenGL3_CreateDeviceObjects(); +//IMGUI_IMPL_API void ImGui_ImplOpenGL3_DestroyDeviceObjects(); } diff --git a/src/gl/inject_glx.cpp b/src/gl/inject_glx.cpp index 31de9bcb..914cabb3 100644 --- a/src/gl/inject_glx.cpp +++ b/src/gl/inject_glx.cpp @@ -4,21 +4,24 @@ #include #include "real_dlsym.h" #include "loaders/loader_glx.h" -#include "imgui_hud.h" +#include "loaders/loader_x11.h" #include "mesa/util/macros.h" #include "mesa/util/os_time.h" -#include "overlay.h" #include #include +#include "imgui_hud_shared.h" +#include "imgui_hud.h" + +using namespace MangoHud::GL; + #define EXPORT_C_(type) extern "C" __attribute__((__visibility__("default"))) type EXPORT_C_(void *) glXGetProcAddress(const unsigned char* procName); EXPORT_C_(void *) glXGetProcAddressARB(const unsigned char* procName); static glx_loader glx; -extern overlay_params params; void* get_proc_address(const char* name) { void (*func)() = (void (*)())real_dlsym( RTLD_NEXT, name ); @@ -47,30 +50,6 @@ void* get_glx_proc_address(const char* name) { return func; } -Status XGetGeometry( - Display *display, - Drawable d, - Window *root, - int *x, - int *y, - unsigned int *width, - unsigned int *height, - unsigned int *border_width, - unsigned int *depth -) -{ - static decltype(&::XGetGeometry) pfnXGetGeometry = nullptr; - if (!pfnXGetGeometry) { - void *handle = real_dlopen("libX11.so.6", RTLD_LAZY); - if (!handle) - std::cerr << "MANGOHUD: couldn't find libX11.so.6" << std::endl; - pfnXGetGeometry = reinterpret_cast( - real_dlsym(handle, "XGetGeometry")); - } - - return pfnXGetGeometry(display, d, root, x, y, width, height, border_width, depth); -} - EXPORT_C_(void *) glXCreateContext(void *dpy, void *vis, void *shareList, int direct) { glx.Load(); @@ -89,7 +68,7 @@ EXPORT_C_(bool) glXMakeCurrent(void* dpy, void* drawable, void* ctx) { bool ret = glx.MakeCurrent(dpy, drawable, ctx); if (ret) - imgui_set_context(ctx); + VARIANT(imgui_set_context)(ctx); if (params.gl_vsync >= -1) { if (glx.SwapIntervalEXT) @@ -105,7 +84,7 @@ EXPORT_C_(bool) glXMakeCurrent(void* dpy, void* drawable, void* ctx) { EXPORT_C_(void) glXSwapBuffers(void* dpy, void* drawable) { glx.Load(); - imgui_create(glx.GetCurrentContext()); + VARIANT(imgui_create)(glx.GetCurrentContext()); unsigned int width, height; //glx.QueryDrawable(dpy, drawable, 0x801D /*GLX_WIDTH*/, &width); @@ -114,7 +93,7 @@ EXPORT_C_(void) glXSwapBuffers(void* dpy, void* drawable) { // glXQueryDrawable is buggy, use XGetGeometry instead Window unused_window; int unused; - XGetGeometry((Display*)dpy, (Window)drawable, &unused_window, + g_x11->XGetGeometry((Display*)dpy, (Window)drawable, &unused_window, &unused, &unused, &width, &height, (unsigned int*) &unused, (unsigned int*) &unused); @@ -123,7 +102,7 @@ EXPORT_C_(void) glXSwapBuffers(void* dpy, void* drawable) { width = vp[2]; height = vp[3];*/ - imgui_render(width, height); + VARIANT(imgui_render)(width, height); glx.SwapBuffers(dpy, drawable); if (fps_limit_stats.targetFrameTime > 0){ fps_limit_stats.frameStart = os_time_get_nano(); diff --git a/src/keybinds.h b/src/keybinds.h index 30abd254..406bffee 100644 --- a/src/keybinds.h +++ b/src/keybinds.h @@ -10,6 +10,7 @@ double elapsedF2, elapsedF12, elapsedReloadCfg; uint64_t last_f2_press, last_f12_press, reload_cfg_press; pthread_t f2; +#ifdef HAVE_X11 bool key_is_pressed(KeySym ks) { if (!init_x11()) @@ -21,3 +22,4 @@ bool key_is_pressed(KeySym ks) { bool isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7))); return isPressed; } +#endif \ No newline at end of file diff --git a/src/loaders/loader_x11.cpp b/src/loaders/loader_x11.cpp index 082a7b50..a9bf52e6 100644 --- a/src/loaders/loader_x11.cpp +++ b/src/loaders/loader_x11.cpp @@ -1,4 +1,5 @@ #include "loader_x11.h" +#include "real_dlsym.h" libx11_loader::libx11_loader() : loaded_(false) { } @@ -12,7 +13,7 @@ bool libx11_loader::Load(const std::string& library_name) { return false; } - library_ = dlopen(library_name.c_str(), RTLD_LAZY); + library_ = real_dlopen(library_name.c_str(), RTLD_LAZY); if (!library_) return false; @@ -80,6 +81,7 @@ void libx11_loader::CleanUp(bool unload) { XCloseDisplay = NULL; XQueryKeymap = NULL; XKeysymToKeycode = NULL; + XStringToKeysym = NULL; XGetGeometry = NULL; } diff --git a/src/loaders/loader_x11.h b/src/loaders/loader_x11.h index 05a36a99..4b502428 100644 --- a/src/loaders/loader_x11.h +++ b/src/loaders/loader_x11.h @@ -25,8 +25,8 @@ class libx11_loader { private: void CleanUp(bool unload); - void* library_; - bool loaded_; + void* library_ = nullptr; + bool loaded_ = false; // Disallow copy constructor and assignment operator. libx11_loader(const libx11_loader&); diff --git a/src/meson.build b/src/meson.build index 7cfb252a..2f1704c4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -56,11 +56,15 @@ vklayer_files = files( ) opengl_files = files( - 'gl/imgui_hud.cpp', - 'gl/imgui_impl_opengl3.cpp', - 'gl/gl3w/GL/gl3w.c', + 'gl/imgui_hud_shared.cpp', ) +pre_args += '-DHOOK_DLSYM' +inc_opengl = include_directories('gl/gl3w') + +glimgui_glx_dep = null_dep +glimgui_egl_dep = null_dep + if get_option('with_x11').enabled() and \ get_option('with_xnvctrl').enabled() pre_args += '-DHAVE_XNVCTRL' @@ -72,16 +76,80 @@ endif if get_option('with_x11').enabled() pre_args += '-DHAVE_X11' - opengl_files += files( - 'gl/inject_glx.cpp', - 'loaders/loader_glx.cpp', + + vklayer_files += files( 'loaders/loader_x11.cpp', 'shared_x11.cpp', ) + + opengl_files += files( + 'loaders/loader_glx.cpp', + ) + + # build with GLX functions + glimgui_glx = static_library( + 'glimgui_glx', + files( + 'gl/inject_glx.cpp', + 'gl/imgui_impl_opengl3.cpp', + 'gl/imgui_hud.cpp', + 'gl/gl3w/GL/gl3w.c', + ), + pic : true, + c_args : [ + pre_args, + c_vis_args, + no_override_init_args, + '-DIMGUI_GLX', + ], + cpp_args : [ + pre_args, + cpp_vis_args, + '-DIMGUI_GLX', + ], + dependencies : [ + libimgui_core_dep, + ], + include_directories : [inc_common, inc_opengl], + ) + + glimgui_glx_dep = declare_dependency( + link_with : glimgui_glx, + ) endif -pre_args += '-DHOOK_DLSYM' -inc_opengl = include_directories('gl/gl3w') +if false +#if get_option('with_wayland').enabled() + # build with EGL functions + glimgui_egl = static_library( + 'glimgui_egl', + files( + 'gl/imgui_impl_opengl3.cpp', + 'gl/imgui_hud.cpp', + ), + pic : true, + c_args : [ + pre_args, + c_vis_args, + no_override_init_args, + '-DIMGUI_EGL', + ], + cpp_args : [ + pre_args, + cpp_vis_args, + '-DIMGUI_EGL', + ], + dependencies : [ + libimgui_core_dep, + ], + include_directories : [inc_common, inc_opengl], + ) + + glimgui_egl_dep = declare_dependency( + link_with : glimgui_egl, + ) + +endif vklayer_mesa_overlay = shared_library( 'MangoHud', @@ -104,7 +172,9 @@ vklayer_mesa_overlay = shared_library( ], dependencies : [ vulkan_wsi_deps, - libimgui_core_dep, + libimgui_core_dep, + glimgui_glx_dep, + glimgui_egl_dep, dep_dl, dep_pthread, dep_vulkan], diff --git a/src/overlay_params.cpp b/src/overlay_params.cpp index ad3c63b9..8ee9c75d 100644 --- a/src/overlay_params.cpp +++ b/src/overlay_params.cpp @@ -113,6 +113,10 @@ parse_reload_cfg(const char *str) return g_x11->XStringToKeysym(str); return 0; } +#else +#define parse_toggle_hud(x) 0 +#define parse_toggle_logging(x) 0 +#define parse_reload_cfg(x) 0 #endif static uint32_t @@ -342,9 +346,6 @@ parse_overlay_config(struct overlay_params *params, params->width = 280; params->height = 140; params->control = -1; - params->toggle_hud = XK_F12; - params->toggle_logging = XK_F2; - params->reload_cfg = XK_F4; params->fps_limit = 0; params->vsync = -1; params->gl_vsync = -2; @@ -364,6 +365,12 @@ parse_overlay_config(struct overlay_params *params, params->background_color = strtol("020202", NULL, 16); params->text_color = strtol("ffffff", NULL, 16); +#ifdef HAVE_X11 + params->toggle_hud = XK_F12; + params->toggle_logging = XK_F2; + params->reload_cfg = XK_F4; +#endif + // first pass with env var if (env) parse_overlay_env(params, env);