From f08163fd7225b5b116862600e79129e5159b886f Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 8 Jul 2021 11:45:54 +1000 Subject: [PATCH] [client] imgui: added imgui to the client and OpenGL/EGL renderers --- client/CMakeLists.txt | 7 +++++- client/include/app.h | 2 ++ client/include/egl_dynprocs.h | 3 +++ client/renderers/EGL/CMakeLists.txt | 8 ++++++- client/renderers/EGL/egl.c | 31 +++++++++++++++++++++++++- client/renderers/OpenGL/CMakeLists.txt | 7 +++++- client/renderers/OpenGL/opengl.c | 18 +++++++++++++++ client/src/app.c | 10 +++++++++ client/src/main.c | 19 ++++++++++++++++ doc/build.rst | 1 + 10 files changed, 102 insertions(+), 4 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 4e2d66e5..698a5ef9 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -project(looking-glass-client C) +project(looking-glass-client C CXX) list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/") @@ -127,12 +127,16 @@ set(SOURCES add_subdirectory("${PROJECT_TOP}/common" "${CMAKE_BINARY_DIR}/common" ) add_subdirectory("${PROJECT_TOP}/repos/LGMP/lgmp" "${CMAKE_BINARY_DIR}/LGMP" ) add_subdirectory("${PROJECT_TOP}/repos/PureSpice" "${CMAKE_BINARY_DIR}/PureSpice") +add_subdirectory("${PROJECT_TOP}/repos/cimgui" "${CMAKE_BINARY_DIR}/cimgui" ) add_subdirectory(displayservers) add_subdirectory(renderers) add_subdirectory(fonts) add_executable(looking-glass-client ${SOURCES}) + +target_compile_definitions(looking-glass-client PRIVATE CIMGUI_DEFINE_ENUMS_AND_STRUCTS=1) + target_link_libraries(looking-glass-client ${EXE_FLAGS} lg_common @@ -141,6 +145,7 @@ target_link_libraries(looking-glass-client purespice renderers fonts + cimgui ) install(TARGETS looking-glass-client diff --git a/client/include/app.h b/client/include/app.h index 26a99de1..0bc7b50a 100644 --- a/client/include/app.h +++ b/client/include/app.h @@ -78,6 +78,8 @@ void app_glSetSwapInterval(int interval); void app_glSwapBuffers(void); #endif +bool app_renderImGui(void); + void app_clipboardRelease(void); void app_clipboardNotifyTypes(const LG_ClipboardData types[], int count); void app_clipboardNotifySize(const LG_ClipboardData type, size_t size); diff --git a/client/include/egl_dynprocs.h b/client/include/egl_dynprocs.h index 78c7369c..ef57fe36 100644 --- a/client/include/egl_dynprocs.h +++ b/client/include/egl_dynprocs.h @@ -25,6 +25,9 @@ #include #include +// if GLEW is included, GLeglImageOES was not defined +typedef void * GLeglImageOES; + typedef EGLDisplay (*eglGetPlatformDisplayEXT_t)(EGLenum platform, void *native_display, const EGLint *attrib_list); typedef void (*eglSwapBuffersWithDamageKHR_t)(EGLDisplay dpy, diff --git a/client/renderers/EGL/CMakeLists.txt b/client/renderers/EGL/CMakeLists.txt index 824e1e7b..c2c9cdce 100644 --- a/client/renderers/EGL/CMakeLists.txt +++ b/client/renderers/EGL/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -project(renderer_EGL LANGUAGES C) +project(renderer_EGL LANGUAGES C CXX) find_package(PkgConfig) pkg_check_modules(RENDERER_EGL_PKGCONFIG REQUIRED @@ -54,13 +54,19 @@ add_library(renderer_EGL STATIC alert.c ${EGL_SHADER_OBJS} "${EGL_SHADER_INCS}/desktop_rgb.def.h" + ${PROJECT_TOP}/repos/cimgui/imgui/backends/imgui_impl_opengl3.cpp ) +target_compile_definitions(renderer_EGL PRIVATE CIMGUI_DEFINE_ENUMS_AND_STRUCTS=1) + target_link_libraries(renderer_EGL ${RENDERER_EGL_PKGCONFIG_LIBRARIES} ${RENDERER_EGL_OPT_PKGCONFIG_LIBRARIES} lg_common fonts + + cimgui + GLEW ) target_include_directories(renderer_EGL diff --git a/client/renderers/EGL/egl.c b/client/renderers/EGL/egl.c index f2d72392..20a28ff7 100644 --- a/client/renderers/EGL/egl.c +++ b/client/renderers/EGL/egl.c @@ -25,11 +25,16 @@ #include "common/sysinfo.h" #include "common/time.h" #include "common/locking.h" +#include "app.h" #include "util.h" #include "dynamic/fonts.h" +#include #include +#include "cimgui.h" +#include "generator/output/cimgui_impl.h" + #include #include #include @@ -72,6 +77,7 @@ struct Inst EGL_Splash * splash; // the splash screen EGL_Alert * alert; // the alert display EGL_Help * help; // the help display + bool imgui; // if imgui was initialized LG_RendererFormat format; bool formatValid; @@ -279,6 +285,9 @@ void egl_deinitialize(void * opaque) { struct Inst * this = (struct Inst *)opaque; + if (this->imgui) + ImGui_ImplOpenGL3_Shutdown(); + if (this->font) { if (this->fontObj) @@ -288,7 +297,6 @@ void egl_deinitialize(void * opaque) this->font->destroy(this->helpFontObj); } - egl_desktop_free(&this->desktop); egl_cursor_free (&this->cursor); egl_fps_free (&this->fps ); @@ -766,6 +774,20 @@ bool egl_render_startup(void * opaque) return false; } + // glew is needed for imgui + if (!glewInit()) + { + DEBUG_ERROR("GLEW failed to initialize"); + return false; + } + + if (!ImGui_ImplOpenGL3_Init("#version 100")) + { + DEBUG_ERROR("Failed to initialize ImGui"); + return false; + } + + this->imgui = true; return true; } @@ -866,6 +888,13 @@ bool egl_render(void * opaque, LG_RendererRotate rotate) egl_fps_render(this->fps, this->screenScaleX, this->screenScaleY); egl_help_render(this->help, this->screenScaleX, this->screenScaleY); + + if (app_renderImGui()) + { + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData()); + } + app_eglSwapBuffers(this->display, this->surface, damage, damageIdx); return true; } diff --git a/client/renderers/OpenGL/CMakeLists.txt b/client/renderers/OpenGL/CMakeLists.txt index 8eb03315..b537fd22 100644 --- a/client/renderers/OpenGL/CMakeLists.txt +++ b/client/renderers/OpenGL/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.0) -project(renderer_Opengl LANGUAGES C) +project(renderer_Opengl LANGUAGES C CXX) find_package(PkgConfig) pkg_check_modules(RENDERER_OPENGL_PKGCONFIG REQUIRED @@ -8,12 +8,17 @@ pkg_check_modules(RENDERER_OPENGL_PKGCONFIG REQUIRED add_library(renderer_OpenGL STATIC opengl.c + ${PROJECT_TOP}/repos/cimgui/imgui/backends/imgui_impl_opengl2.cpp ) +target_compile_definitions(renderer_OpenGL PRIVATE CIMGUI_DEFINE_ENUMS_AND_STRUCTS=1) + target_link_libraries(renderer_OpenGL ${RENDERER_OPENGL_PKGCONFIG_LIBRARIES} lg_common fonts + + cimgui ) target_include_directories(renderer_OpenGL diff --git a/client/renderers/OpenGL/opengl.c b/client/renderers/OpenGL/opengl.c index bfa9ff2e..81fa2ed0 100644 --- a/client/renderers/OpenGL/opengl.c +++ b/client/renderers/OpenGL/opengl.c @@ -29,6 +29,9 @@ #include #include +#include "cimgui.h" +#include "generator/output/cimgui_impl.h" + #include "common/debug.h" #include "common/option.h" #include "common/framebuffer.h" @@ -272,6 +275,8 @@ void opengl_deinitialize(void * opaque) if (this->renderStarted) { + ImGui_ImplOpenGL2_Shutdown(); + glDeleteLists(this->texList , BUFFER_COUNT); glDeleteLists(this->mouseList, 1); glDeleteLists(this->fpsList , 1); @@ -581,6 +586,13 @@ bool opengl_render_startup(void * opaque) this->hasTextures = true; app_glSetSwapInterval(this->opt.vsync ? 1 : 0); + + if (!ImGui_ImplOpenGL2_Init()) + { + DEBUG_ERROR("Failed to initialize ImGui"); + return false; + } + this->renderStarted = true; return true; } @@ -690,6 +702,12 @@ bool opengl_render(void * opaque, LG_RendererRotate rotate) break; } + if (app_renderImGui()) + { + ImGui_ImplOpenGL2_NewFrame(); + ImGui_ImplOpenGL2_RenderDrawData(igGetDrawData()); + } + if (this->opt.preventBuffer) { app_glSwapBuffers(); diff --git a/client/src/app.c b/client/src/app.c index c1a9261b..3ccdbd1d 100644 --- a/client/src/app.c +++ b/client/src/app.c @@ -31,6 +31,8 @@ #include "common/debug.h" #include "common/stringutils.h" +#include "cimgui.h" + #include #include #include @@ -617,3 +619,11 @@ void app_showFPS(bool showFPS) g_state.lgr->on_show_fps(g_state.lgrData, showFPS); } + +bool app_renderImGui(void) +{ + igNewFrame(); + igShowDemoWindow(NULL); + igRender(); + return true; +} diff --git a/client/src/main.c b/client/src/main.c index 734110cf..097a9d61 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -56,6 +56,8 @@ #include "ll.h" #include "egl_dynprocs.h" +#include "cimgui.h" + // forwards static int cursorThread(void * unused); static int renderThread(void * unused); @@ -97,12 +99,21 @@ static void lgInit(void) static int renderThread(void * unused) { + /* setup imgui */ + igCreateContext(NULL); + ImGuiIO * io = igGetIO(); + unsigned char *text_pixels = NULL; + int text_w, text_h; + ImFontAtlas_GetTexDataAsRGBA32(io->Fonts, &text_pixels, + &text_w, &text_h, NULL); + if (!g_state.lgr->render_startup(g_state.lgrData)) { g_state.state = APP_STATE_SHUTDOWN; /* unblock threads waiting on the condition */ lgSignalEvent(e_startup); + igDestroyContext(NULL); return 1; } @@ -128,6 +139,13 @@ static int renderThread(void * unused) int resize = atomic_load(&g_state.lgrResize); if (resize) { + const ImVec2 displaySize = + { + .x = g_state.windowW, + .y = g_state.windowH + }; + io->DisplaySize = displaySize; + if (g_state.lgr) g_state.lgr->on_resize(g_state.lgrData, g_state.windowW, g_state.windowH, g_state.windowScale, g_state.dstRect, g_params.winRotate); @@ -193,6 +211,7 @@ static int renderThread(void * unused) g_state.lgr = NULL; LG_LOCK_FREE(g_state.lgrLock); + igDestroyContext(NULL); return 0; } diff --git a/doc/build.rst b/doc/build.rst index d5ca67e2..61e4acd5 100644 --- a/doc/build.rst +++ b/doc/build.rst @@ -57,6 +57,7 @@ Required Dependencies - fonts-freefont-ttf - libegl-dev - libgl-dev +- libglew-dev - libfontconfig1-dev - libgmp-dev - libspice-protocol-dev