From 15743d822b2ab0d142c513100fec59ddf6db2e9d Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 13 Sep 2023 14:04:18 +0100 Subject: [PATCH] st/gui: Refactor a few OpenGL drawing code into helper --- src/xrt/state_trackers/gui/CMakeLists.txt | 2 + src/xrt/state_trackers/gui/gui_ogl.c | 96 +++++++++++++++++++ src/xrt/state_trackers/gui/gui_ogl.h | 39 ++++++++ .../state_trackers/gui/gui_scene_calibrate.c | 16 ++-- .../state_trackers/gui/gui_window_record.c | 65 +++---------- 5 files changed, 159 insertions(+), 59 deletions(-) create mode 100644 src/xrt/state_trackers/gui/gui_ogl.c create mode 100644 src/xrt/state_trackers/gui/gui_ogl.h diff --git a/src/xrt/state_trackers/gui/CMakeLists.txt b/src/xrt/state_trackers/gui/CMakeLists.txt index 7c2202c50..29764b109 100644 --- a/src/xrt/state_trackers/gui/CMakeLists.txt +++ b/src/xrt/state_trackers/gui/CMakeLists.txt @@ -8,6 +8,8 @@ add_library( st_gui STATIC gui_common.h gui_imgui.h + gui_ogl.c + gui_ogl.h gui_ogl_sink.c gui_prober.c gui_scene.cpp diff --git a/src/xrt/state_trackers/gui/gui_ogl.c b/src/xrt/state_trackers/gui/gui_ogl.c new file mode 100644 index 000000000..00ca7e62b --- /dev/null +++ b/src/xrt/state_trackers/gui/gui_ogl.c @@ -0,0 +1,96 @@ +// Copyright 2019-2023, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief OpenGL helper functions for drawing GUI elements. + * @author Jakob Bornecrantz + * @author Moses Turner + * @ingroup gui + */ + +#include "math/m_api.h" + +#include "gui_ogl.h" +#include "gui_imgui.h" + + +/* + * + * Helpers. + * + */ + +static void +get_uvs(ImVec2 *uv0, ImVec2 *uv1, bool rotate_180, bool flip_y) +{ + // Flip direction of y (x) if we are rotating. + float u0 = rotate_180 ? 1.f : 0.f; + float u1 = rotate_180 ? 0.f : 1.f; + + // Flip direction of v (y) if either flip_y or rotate_180 is true. + float v0 = (rotate_180 ^ flip_y) ? 1.f : 0.f; + float v1 = (rotate_180 ^ flip_y) ? 0.f : 1.f; + + // Note: We can't easily do 90 or 270-degree rotations: https://github.com/ocornut/imgui/issues/3267 + *uv0 = (ImVec2){u0, v0}; + *uv1 = (ImVec2){u1, v1}; +} + + +/* + * + * 'Exported' functions. + * + */ + +void +gui_ogl_draw_image(uint32_t width, uint32_t height, uint32_t tex_id, float scale, bool rotate_180, bool flip_y) +{ + ImVec2 uv0, uv1; + get_uvs(&uv0, &uv1, rotate_180, flip_y); + + // Need to go via ints to get integer steps. + int w = (float)width * scale; + int h = (float)height * scale; + + ImVec2 size = {(float)w, (float)h}; + ImVec4 white = {1, 1, 1, 1}; + ImVec4 black = {0, 0, 0, 1}; + ImTextureID id = (ImTextureID)(intptr_t)tex_id; + + igImageBg(id, size, uv0, uv1, white, white, black); +} + +void +gui_ogl_draw_background(uint32_t width, uint32_t height, uint32_t tex_id, bool rotate_180, bool flip_y) +{ + ImVec2 uv0, uv1; + get_uvs(&uv0, &uv1, rotate_180, flip_y); + + const ImU32 white = 0xffffffff; + ImTextureID id = (ImTextureID)(intptr_t)tex_id; + + ImGuiIO *io = igGetIO(); + + float in_w = (float)width; + float in_h = (float)height; + float out_w = io->DisplaySize.x; + float out_h = io->DisplaySize.y; + + float scale_w = (float)out_w / in_w; // 128 / 1280 = 0.1 + float scale_h = (float)out_h / in_h; // 128 / 800 = 0.16 + + float scale = MIN(scale_w, scale_h); // 0.1 + + float inside_w = in_w * scale; + float inside_h = in_h * scale; + + float translate_x = (out_w - inside_w) / 2; // Should be 0 for 1280x800 + float translate_y = (out_h - inside_h) / 2; // Should be (1280 - 800) / 2 = 240 + + ImVec2 p_min = {translate_x, translate_y}; + ImVec2 p_max = {translate_x + inside_w, translate_y + inside_h}; + + ImDrawList *bg = igGetBackgroundDrawList(); + ImDrawList_AddImage(bg, id, p_min, p_max, uv0, uv1, white); +} diff --git a/src/xrt/state_trackers/gui/gui_ogl.h b/src/xrt/state_trackers/gui/gui_ogl.h new file mode 100644 index 000000000..bec699cc2 --- /dev/null +++ b/src/xrt/state_trackers/gui/gui_ogl.h @@ -0,0 +1,39 @@ +// Copyright 2019-2023, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief OpenGL helper functions for drawing GUI elements. + * @author Jakob Bornecrantz + * @ingroup gui + */ + +#pragma once + +#include "xrt/xrt_compiler.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * Draw the given textures as igImage, scale of 1.0f == 100%. + * + * @ingroup gui + */ +void +gui_ogl_draw_image(uint32_t width, uint32_t height, uint32_t tex_id, float scale, bool rotate_180, bool flip_y); + + +/*! + * Draw the given texture to the background of the current OS window. + * + * @ingroup gui + */ +void +gui_ogl_draw_background(uint32_t width, uint32_t height, uint32_t tex_id, bool rotate_180, bool flip_y); + + +#ifdef __cplusplus +} +#endif diff --git a/src/xrt/state_trackers/gui/gui_scene_calibrate.c b/src/xrt/state_trackers/gui/gui_scene_calibrate.c index 22c43f5f5..8af12fc23 100644 --- a/src/xrt/state_trackers/gui/gui_scene_calibrate.c +++ b/src/xrt/state_trackers/gui/gui_scene_calibrate.c @@ -27,6 +27,7 @@ #include "gui_common.h" #include "gui_imgui.h" +#include "gui_ogl.h" #include @@ -134,15 +135,14 @@ draw_texture(struct gui_ogl_texture *tex, bool header) gui_ogl_sink_update(tex); - int w = tex->w / (tex->half ? 2 : 1); - int h = tex->h / (tex->half ? 2 : 1); + gui_ogl_draw_image( // + (uint32_t)tex->w, // width + (uint32_t)tex->h, // height + tex->id, // tex_id + tex->half ? 0.5f : 1.0f, // scale + false, // rotate_180 + false); // flip_y - ImVec2 size = {(float)w, (float)h}; - ImVec2 uv0 = {0, 0}; - ImVec2 uv1 = {1, 1}; - ImVec4 white = {1, 1, 1, 1}; - ImTextureID id = (ImTextureID)(intptr_t)tex->id; - igImage(id, size, uv0, uv1, white, white); igText("Sequence %u", (uint32_t)tex->seq); char temp[512]; diff --git a/src/xrt/state_trackers/gui/gui_window_record.c b/src/xrt/state_trackers/gui/gui_window_record.c index 225516bdd..ad8464cfb 100644 --- a/src/xrt/state_trackers/gui/gui_window_record.c +++ b/src/xrt/state_trackers/gui/gui_window_record.c @@ -34,6 +34,7 @@ #include "gstreamer/gst_pipeline.h" #endif +#include "gui_ogl.h" #include "gui_imgui.h" #include "gui_common.h" #include "gui_window_record.h" @@ -313,42 +314,12 @@ gui_window_record_to_background(struct gui_record_window *rw, struct gui_program gui_ogl_sink_update(tex); - ImVec2 uv0 = {0, 0}; - ImVec2 uv1 = {1, 1}; - - // Note: We can't easily do 90 or 270-degree rotations: https://github.com/ocornut/imgui/issues/3267 - if (rw->texture.rotate_180) { - uv0 = (ImVec2){1, 1}; - uv1 = (ImVec2){0, 0}; - } - - const ImU32 white = 0xffffffff; - ImTextureID id = (ImTextureID)(intptr_t)tex->id; - - ImGuiIO *io = igGetIO(); - - // Shamelessly stolen from hg_model.cpp - float in_w = tex->w; - float in_h = tex->h; - float out_w = io->DisplaySize.x; - float out_h = io->DisplaySize.y; - - float scale_w = (float)out_w / in_w; // 128 / 1280 = 0.1 - float scale_h = (float)out_h / in_h; // 128 / 800 = 0.16 - - float scale = MIN(scale_w, scale_h); // 0.1 - - float inside_w = in_w * scale; - float inside_h = in_h * scale; - - float translate_x = (out_w - inside_w) / 2; // Should be 0 for 1280x800 - float translate_y = (out_h - inside_h) / 2; // Should be (1280 - 800) / 2 = 240 - - ImVec2 p_min = {translate_x, translate_y}; - ImVec2 p_max = {translate_x + inside_w, translate_y + inside_h}; - - ImDrawList *bg = igGetBackgroundDrawList(); - ImDrawList_AddImage(bg, id, p_min, p_max, uv0, uv1, white); + gui_ogl_draw_background( // + (uint32_t)tex->w, // width + (uint32_t)tex->h, // height + tex->id, // tex_id + rw->texture.rotate_180, // rotate_180 + false); // flip_y } void @@ -363,22 +334,14 @@ gui_window_record_render(struct gui_record_window *rw, struct gui_program *p) struct gui_ogl_texture *tex = rw->texture.ogl; - int w = tex->w * rw->texture.scale / 100.0f; - int h = tex->h * rw->texture.scale / 100.0f; + gui_ogl_draw_image( // + (uint32_t)tex->w, // width + (uint32_t)tex->h, // height + tex->id, // tex_id + rw->texture.scale / 100.0f, // scale + rw->texture.rotate_180, // rotate_180 + false); // flip_y - ImVec2 size = {(float)w, (float)h}; - ImVec2 uv0 = {0, 0}; - ImVec2 uv1 = {1, 1}; - - // Note: We can't easily do 90 or 270-degree rotations: https://github.com/ocornut/imgui/issues/3267 - if (rw->texture.rotate_180) { - uv0 = (ImVec2){1, 1}; - uv1 = (ImVec2){0, 0}; - } - - ImVec4 white = {1, 1, 1, 1}; - ImTextureID id = (ImTextureID)(intptr_t)tex->id; - igImage(id, size, uv0, uv1, white, white); #ifdef XRT_HAVE_GST draw_gst(rw);