t/gui: Refactor out SDL2 code

This commit is contained in:
Jakob Bornecrantz 2019-10-09 16:22:34 +01:00
parent 473047962f
commit 420f25c7f7
14 changed files with 181 additions and 222 deletions

View file

@ -15,9 +15,7 @@ include_directories(
set(SOURCE_FILES
gui_common.h
gui_imgui.c
gui_imgui.h
gui_main.c
gui_ogl.c
gui_prober.c
gui_scene.cpp
@ -26,6 +24,9 @@ set(SOURCE_FILES
gui_scene_main_menu.c
gui_scene_video.c
gui_sdl2.c
gui_sdl2_imgui.c
gui_sdl2_main.c
gui_sdl2_prober.c
../../../external/glad/gl.h
../../../external/glad/gl.c
../../../external/imgui/cimgui.cpp

View file

@ -9,8 +9,8 @@
#pragma once
#include "xrt/xrt_frame.h"
#include <SDL2/SDL.h>
#include "xrt/xrt_compiler.h"
/*!
* @defgroup gui GUI Config Interface
@ -19,44 +19,32 @@
* @brief Small GUI interface to configure Monado based on SDL2.
*/
#ifdef __cplusplus
extern "C" {
#endif
#define NUM_XDEVS 8
struct xrt_device;
struct xrt_prober;
struct xrt_fs;
struct xrt_frame_sink;
struct xrt_frame_context;
struct time_state;
struct gui_scene_manager;
/*!
* Common struct holding state for the GUI interface.
* A gui program.
*
* @ingroup gui
*/
struct program
struct gui_program
{
SDL_Window *win;
SDL_GLContext ctx;
bool stopped;
bool initialized;
struct gui_scene_manager *gsm;
struct
{
SDL_Surface *sf;
uint8_t *buffer;
size_t stride;
uint32_t width;
uint32_t height;
bool own_buffer;
} blit;
struct time_state *timekeeping;
struct xrt_device *xdevs[NUM_XDEVS];
struct xrt_prober *xp;
@ -70,8 +58,8 @@ struct program
*/
struct gui_scene
{
void (*render)(struct gui_scene *, struct program *);
void (*destroy)(struct gui_scene *, struct program *);
void (*render)(struct gui_scene *, struct gui_program *);
void (*destroy)(struct gui_scene *, struct gui_program *);
};
/*!
@ -91,58 +79,13 @@ struct gui_ogl_texture
void *ptr;
};
/*!
* Init SDL2, create and show a window and bring up any other structs needed.
*
* @ingroup gui
*/
int
gui_sdl2_init(struct program *p);
/*!
* Loop until user request quit and show Imgui interface.
*
* @ingroup gui
*/
void
gui_imgui_loop(struct program *p);
/*!
* Loop until quit signal has been received.
*
* @ingroup gui
*/
void
gui_sdl2_loop(struct program *p);
/*!
* Display a 24bit RGB image on the screen.
*
* @ingroup gui
*/
void
gui_sdl2_display_R8G8B8(struct program *p,
bool resize,
uint32_t width,
uint32_t height,
size_t stride,
void *data);
/*!
* Destroy all SDL things and quit SDL.
*
* @ingroup gui
*/
void
gui_sdl2_quit(struct program *p);
/*!
* Initialize the prober and open all devices found.
*
* @ingroup gui
*/
int
gui_prober_init(struct program *p);
gui_prober_init(struct gui_program *p);
/*!
* Create devices.
@ -150,7 +93,7 @@ gui_prober_init(struct program *p);
* @ingroup gui
*/
int
gui_prober_select(struct program *p);
gui_prober_select(struct gui_program *p);
/*!
* Update all devices.
@ -158,7 +101,7 @@ gui_prober_select(struct program *p);
* @ingroup gui
*/
void
gui_prober_update(struct program *p);
gui_prober_update(struct gui_program *p);
/*!
* Destroy all opened devices and destroy the prober.
@ -166,7 +109,7 @@ gui_prober_update(struct program *p);
* @ingroup gui
*/
void
gui_prober_teardown(struct program *p);
gui_prober_teardown(struct gui_program *p);
/*!
* Create a sink that will turn frames into OpenGL textures, since the frame
@ -195,7 +138,7 @@ gui_ogl_sink_update(struct gui_ogl_texture *);
* @ingroup gui
*/
void
gui_scene_push_front(struct program *p, struct gui_scene *me);
gui_scene_push_front(struct gui_program *p, struct gui_scene *me);
/*!
* Put a scene on the delete list, also removes it from any other list.
@ -203,7 +146,7 @@ gui_scene_push_front(struct program *p, struct gui_scene *me);
* @ingroup gui
*/
void
gui_scene_delete_me(struct program *p, struct gui_scene *me);
gui_scene_delete_me(struct gui_program *p, struct gui_scene *me);
/*!
* Render the scenes.
@ -211,7 +154,7 @@ gui_scene_delete_me(struct program *p, struct gui_scene *me);
* @ingroup gui
*/
void
gui_scene_manager_render(struct program *p);
gui_scene_manager_render(struct gui_program *p);
/*!
* Initialize the scene manager.
@ -219,7 +162,7 @@ gui_scene_manager_render(struct program *p);
* @ingroup gui
*/
void
gui_scene_manager_init(struct program *p);
gui_scene_manager_init(struct gui_program *p);
/*!
* Destroy the scene manager.
@ -227,7 +170,7 @@ gui_scene_manager_init(struct program *p);
* @ingroup gui
*/
void
gui_scene_manager_destroy(struct program *p);
gui_scene_manager_destroy(struct gui_program *p);
/*
@ -242,7 +185,7 @@ gui_scene_manager_destroy(struct program *p);
* @ingroup gui
*/
void
gui_scene_main_menu(struct program *p);
gui_scene_main_menu(struct gui_program *p);
/*!
* Shows a UI that lets you select a video device and mode for calibration.
@ -250,7 +193,7 @@ gui_scene_main_menu(struct program *p);
* @ingroup gui
*/
void
gui_scene_select_video_calibrate(struct program *p);
gui_scene_select_video_calibrate(struct gui_program *p);
/*!
* Shows a UI that lets you select a video device and mode for testing.
@ -258,7 +201,7 @@ gui_scene_select_video_calibrate(struct program *p);
* @ingroup gui
*/
void
gui_scene_select_video_test(struct program *p);
gui_scene_select_video_test(struct gui_program *p);
/*!
* Regular debug UI.
@ -266,7 +209,7 @@ gui_scene_select_video_test(struct program *p);
* @ingroup gui
*/
void
gui_scene_debug(struct program *p);
gui_scene_debug(struct gui_program *p);
/*!
* Given the frameserver runs some debug code on it.
@ -274,7 +217,7 @@ gui_scene_debug(struct program *p);
* @ingroup gui
*/
void
gui_scene_debug_video(struct program *p,
gui_scene_debug_video(struct gui_program *p,
struct xrt_frame_context *xfctx,
struct xrt_fs *xfs,
size_t mode);
@ -285,7 +228,7 @@ gui_scene_debug_video(struct program *p,
* @ingroup gui
*/
void
gui_scene_calibrate(struct program *p,
gui_scene_calibrate(struct gui_program *p,
struct xrt_frame_context *xfctx,
struct xrt_fs *xfs,
size_t mode);

View file

@ -18,7 +18,7 @@
*/
static int
do_exit(struct program *p, int ret)
do_exit(struct gui_program *p, int ret)
{
gui_prober_teardown(p);
return ret;
@ -32,7 +32,7 @@ do_exit(struct program *p, int ret)
*/
int
gui_prober_init(struct program *p)
gui_prober_init(struct gui_program *p)
{
int ret = 0;
@ -54,7 +54,7 @@ gui_prober_init(struct program *p)
}
int
gui_prober_select(struct program *p)
gui_prober_select(struct gui_program *p)
{
int ret;
@ -68,7 +68,7 @@ gui_prober_select(struct program *p)
}
void
gui_prober_update(struct program *p)
gui_prober_update(struct gui_program *p)
{
// We haven't been initialized
if (p->timekeeping == NULL) {
@ -87,7 +87,7 @@ gui_prober_update(struct program *p)
}
void
gui_prober_teardown(struct program *p)
gui_prober_teardown(struct gui_program *p)
{
for (size_t i = 0; i < NUM_XDEVS; i++) {
if (p->xdevs[i] == NULL) {
@ -105,9 +105,3 @@ gui_prober_teardown(struct program *p)
xrt_prober_destroy(&p->xp);
}
int
xrt_prober_create(struct xrt_prober **out_xp)
{
return xrt_prober_create_with_lists(out_xp, &target_lists);
}

View file

@ -21,7 +21,7 @@ public:
};
extern "C" void
gui_scene_push_front(struct program *p, struct gui_scene *me)
gui_scene_push_front(struct gui_program *p, struct gui_scene *me)
{
auto &gsm = *p->gsm;
@ -42,7 +42,7 @@ gui_scene_push_front(struct program *p, struct gui_scene *me)
}
extern "C" void
gui_scene_delete_me(struct program *p, struct gui_scene *me)
gui_scene_delete_me(struct gui_program *p, struct gui_scene *me)
{
auto &gsm = *p->gsm;
@ -61,7 +61,7 @@ gui_scene_delete_me(struct program *p, struct gui_scene *me)
}
extern "C" void
gui_scene_manager_render(struct program *p)
gui_scene_manager_render(struct gui_program *p)
{
auto &gsm = *p->gsm;
auto copy = gsm.scenes;
@ -83,13 +83,13 @@ gui_scene_manager_render(struct program *p)
}
extern "C" void
gui_scene_manager_init(struct program *p)
gui_scene_manager_init(struct gui_program *p)
{
p->gsm = new gui_scene_manager;
}
extern "C" void
gui_scene_manager_destroy(struct program *p)
gui_scene_manager_destroy(struct gui_program *p)
{
delete p->gsm;
p->gsm = NULL;

View file

@ -76,7 +76,7 @@ draw_texture(struct gui_ogl_texture *tex, bool header)
}
static void
scene_render_video(struct gui_scene *scene, struct program *p)
scene_render_video(struct gui_scene *scene, struct gui_program *p)
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
@ -100,7 +100,7 @@ scene_render_video(struct gui_scene *scene, struct program *p)
}
static void
scene_render_select(struct gui_scene *scene, struct program *p)
scene_render_select(struct gui_scene *scene, struct gui_program *p)
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
@ -151,7 +151,7 @@ scene_render_select(struct gui_scene *scene, struct program *p)
}
static void
scene_destroy(struct gui_scene *scene, struct program *p)
scene_destroy(struct gui_scene *scene, struct gui_program *p)
{
struct calibration_scene *cs = (struct calibration_scene *)scene;
@ -171,7 +171,7 @@ scene_destroy(struct gui_scene *scene, struct program *p)
*/
void
gui_scene_calibrate(struct program *p,
gui_scene_calibrate(struct gui_program *p,
struct xrt_frame_context *xfctx,
struct xrt_fs *xfs,
size_t mode)

View file

@ -56,12 +56,12 @@ conv_rgb_u8_to_f32(struct xrt_colour_rgb_u8 *from,
struct draw_state
{
struct program *p;
struct gui_program *p;
bool hidden;
};
static void
on_sink_var(const char *name, void *ptr, struct program *p)
on_sink_var(const char *name, void *ptr, struct gui_program *p)
{
for (size_t i = 0; i < ARRAY_SIZE(p->texs); i++) {
struct gui_ogl_texture *tex = p->texs[i];
@ -184,7 +184,7 @@ on_root_exit(const char *name, void *priv)
}
static void
scene_render(struct gui_scene *scene, struct program *p)
scene_render(struct gui_scene *scene, struct gui_program *p)
{
struct debug_scene *ds = (struct debug_scene *)scene;
(void)ds;
@ -194,7 +194,7 @@ scene_render(struct gui_scene *scene, struct program *p)
}
static void
scene_destroy(struct gui_scene *scene, struct program *p)
scene_destroy(struct gui_scene *scene, struct gui_program *p)
{
struct debug_scene *ds = (struct debug_scene *)scene;
@ -220,7 +220,7 @@ on_root_enter_sink(const char *name, void *priv)
static void
on_elem_sink(const char *name, enum u_var_kind kind, void *ptr, void *priv)
{
struct program *p = (struct program *)priv;
struct gui_program *p = (struct gui_program *)priv;
if (kind != U_VAR_KIND_SINK) {
return;
@ -256,7 +256,7 @@ on_root_exit_sink(const char *name, void *priv)
*/
void
gui_scene_debug_video(struct program *p,
gui_scene_debug_video(struct gui_program *p,
struct xrt_frame_context *xfctx,
struct xrt_fs *xfs,
size_t mode)
@ -297,7 +297,7 @@ gui_scene_debug_video(struct program *p,
}
void
gui_scene_debug(struct program *p)
gui_scene_debug(struct gui_program *p)
{
struct debug_scene *ds = U_TYPED_CALLOC(struct debug_scene);

View file

@ -21,7 +21,7 @@ struct main_menu
};
static void
scene_render(struct gui_scene *scene, struct program *p)
scene_render(struct gui_scene *scene, struct gui_program *p)
{
igBegin("Main Menu", NULL, 0);
@ -50,7 +50,7 @@ scene_render(struct gui_scene *scene, struct program *p)
}
static void
scene_destroy(struct gui_scene *scene, struct program *p)
scene_destroy(struct gui_scene *scene, struct gui_program *p)
{
free(scene);
}
@ -63,7 +63,7 @@ scene_destroy(struct gui_scene *scene, struct program *p)
*/
void
gui_scene_main_menu(struct program *p)
gui_scene_main_menu(struct gui_program *p)
{
struct main_menu *mm = U_TYPED_CALLOC(struct main_menu);

View file

@ -73,7 +73,7 @@ render_mode(struct xrt_fs_mode *mode)
}
static void
scene_render(struct gui_scene *scene, struct program *p)
scene_render(struct gui_scene *scene, struct gui_program *p)
{
struct video_select *vs = (struct video_select *)scene;
@ -118,7 +118,7 @@ scene_render(struct gui_scene *scene, struct program *p)
}
static void
scene_destroy(struct gui_scene *scene, struct program *p)
scene_destroy(struct gui_scene *scene, struct gui_program *p)
{
struct video_select *vs = (struct video_select *)scene;
@ -144,7 +144,7 @@ scene_destroy(struct gui_scene *scene, struct program *p)
*/
void
gui_scene_select_video_test(struct program *p)
gui_scene_select_video_test(struct gui_program *p)
{
struct video_select *vs = U_TYPED_CALLOC(struct video_select);
@ -156,7 +156,7 @@ gui_scene_select_video_test(struct program *p)
}
void
gui_scene_select_video_calibrate(struct program *p)
gui_scene_select_video_calibrate(struct gui_program *p)
{
struct video_select *vs = U_TYPED_CALLOC(struct video_select);

View file

@ -7,7 +7,7 @@
* @ingroup gui
*/
#include "gui_common.h"
#include "gui_sdl2.h"
#include "glad/gl.h"
@ -17,37 +17,11 @@
*
*/
XRT_MAYBE_UNUSED static void
create_blit_info(struct program *p, uint32_t width, uint32_t height)
{
if (p->blit.sf != NULL) {
SDL_FreeSurface(p->blit.sf);
p->blit.sf = NULL;
if (p->blit.own_buffer) {
free(p->blit.buffer);
}
p->blit.buffer = NULL;
}
size_t stride = width * 4;
size_t size = stride * height;
p->blit.width = width;
p->blit.height = height;
p->blit.stride = stride;
p->blit.own_buffer = true;
p->blit.buffer = malloc(size);
p->blit.sf =
SDL_CreateRGBSurfaceFrom(p->blit.buffer, width, height, 32, stride,
0x0000FF, 0x00FF00, 0xFF0000, 0);
}
static void
sdl2_handle_keydown(struct program *p, const SDL_Event *e)
sdl2_handle_keydown(struct sdl2_program *p, const SDL_Event *e)
{
switch (e->key.keysym.sym) {
case SDLK_ESCAPE: p->stopped = true; break;
case SDLK_ESCAPE: p->base.stopped = true; break;
default: break;
}
@ -62,43 +36,10 @@ sdl2_handle_keydown(struct program *p, const SDL_Event *e)
*/
void
gui_sdl2_display_R8G8B8(struct program *p,
bool resize,
uint32_t width,
uint32_t height,
size_t stride,
void *data)
{
if (p->blit.buffer != data || p->blit.width != width ||
p->blit.height != height || p->blit.sf == NULL) {
if (resize) {
SDL_SetWindowSize(p->win, width, height);
}
p->blit.sf =
SDL_CreateRGBSurfaceFrom(data, width, height, 24, stride,
0x0000FF, 0x00FF00, 0xFF0000, 0);
p->blit.width = width;
p->blit.height = height;
p->blit.stride = stride;
p->blit.buffer = data;
p->blit.own_buffer = false;
}
SDL_Surface *win_sf = SDL_GetWindowSurface(p->win);
if (SDL_BlitSurface(p->blit.sf, NULL, win_sf, NULL) == 0) {
SDL_UpdateWindowSurface(p->win);
}
}
void
gui_sdl2_loop(struct program *p)
gui_sdl2_loop(struct sdl2_program *p)
{
SDL_Event event;
while (!p->stopped) {
while (!p->base.stopped) {
if (SDL_WaitEvent(&event) == 0) {
return;
}
@ -116,11 +57,12 @@ gui_sdl2_loop(struct program *p)
}
int
gui_sdl2_init(struct program *p)
gui_sdl2_init(struct sdl2_program *p)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
return -1;
}
p->sdl_initialized = true;
const char *title = "Monado! ☺";
int x = SDL_WINDOWPOS_UNDEFINED;
@ -146,7 +88,7 @@ gui_sdl2_init(struct program *p)
window_flags |= SDL_WINDOW_MAXIMIZED;
#endif
p->initialized = true;
p->win = SDL_CreateWindow(title, x, y, w, h, window_flags);
if (p->win == NULL) {
@ -171,22 +113,8 @@ gui_sdl2_init(struct program *p)
}
void
gui_sdl2_quit(struct program *p)
gui_sdl2_quit(struct sdl2_program *p)
{
if (!p->initialized) {
return;
}
if (p->blit.sf != NULL) {
SDL_FreeSurface(p->blit.sf);
p->blit.sf = NULL;
if (p->blit.own_buffer) {
free(p->blit.buffer);
}
p->blit.buffer = NULL;
}
if (p->ctx != NULL) {
SDL_GL_DeleteContext(p->ctx);
p->ctx = NULL;
@ -198,5 +126,5 @@ gui_sdl2_quit(struct program *p)
}
SDL_Quit();
p->initialized = false;
p->sdl_initialized = false;
}

View file

@ -0,0 +1,78 @@
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Common file for the Monado SDL2 based GUI program.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup gui
*/
#pragma once
#include "gui_common.h"
#include <SDL2/SDL.h>
/*!
* @defgroup gui GUI Config Interface
* @ingroup xrt
*
* @brief Small GUI interface to configure Monado based on SDL2.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Common struct holding state for the GUI interface.
*
* @ingroup gui
*/
struct sdl2_program
{
struct gui_program base;
bool sdl_initialized;
SDL_Window *win;
SDL_GLContext ctx;
};
/*!
* Init SDL2, create and show a window and bring up any other structs needed.
*
* @ingroup gui
*/
int
gui_sdl2_init(struct sdl2_program *p);
/*!
* Loop until user request quit and show Imgui interface.
*
* @ingroup gui
*/
void
gui_sdl2_imgui_loop(struct sdl2_program *p);
/*!
* Loop until quit signal has been received.
*
* @ingroup gui
*/
void
gui_sdl2_loop(struct sdl2_program *p);
/*!
* Destroy all SDL things and quit SDL.
*
* @ingroup gui
*/
void
gui_sdl2_quit(struct sdl2_program *p);
#ifdef __cplusplus
}
#endif

View file

@ -13,9 +13,7 @@
#include "util/u_sink.h"
#include "util/u_format.h"
#include "xrt/xrt_prober.h"
#include "gui_common.h"
#include "gui_sdl2.h"
#include "gui_imgui.h"
@ -44,7 +42,7 @@ struct gui_imgui
*/
void
gui_imgui_loop(struct program *p)
gui_sdl2_imgui_loop(struct sdl2_program *p)
{
// Need to call this before any other Imgui call.
igCreateContext(NULL);
@ -67,22 +65,22 @@ gui_imgui_loop(struct program *p)
u_var_add_root(&gui, "GUI Control", false);
u_var_add_rgb_f32(&gui, &gui.clear, "Clear Colour");
u_var_add_bool(&gui, &gui.show_demo_window, "Demo Window");
u_var_add_bool(&gui, &p->stopped, "Exit");
u_var_add_bool(&gui, &p->base.stopped, "Exit");
while (!p->stopped) {
while (!p->base.stopped) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
igImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT) {
p->stopped = true;
p->base.stopped = true;
}
if (event.type == SDL_WINDOWEVENT &&
event.window.event == SDL_WINDOWEVENT_CLOSE &&
event.window.windowID == SDL_GetWindowID(p->win)) {
p->stopped = true;
p->base.stopped = true;
}
}
@ -94,7 +92,7 @@ gui_imgui_loop(struct program *p)
igNewFrame();
// Render the scene into it.
gui_scene_manager_render(p);
gui_scene_manager_render(&p->base);
// Handle this here.
if (gui.show_demo_window) {
@ -114,7 +112,7 @@ gui_imgui_loop(struct program *p)
SDL_GL_SwapWindow(p->win);
gui_prober_update(p);
gui_prober_update(&p->base);
}
// Cleanup

View file

@ -8,13 +8,13 @@
*/
#include "util/u_var.h"
#include "gui_common.h"
#include "gui_sdl2.h"
int
main(int argc, char **argv)
{
struct program p = {0};
struct sdl2_program p = {0};
int ret;
// Need to do this as early as possible.
@ -27,28 +27,28 @@ main(int argc, char **argv)
}
// To manage the scenes.
gui_scene_manager_init(&p);
gui_scene_manager_init(&p.base);
// Start all of the devices.
gui_prober_init(&p);
gui_prober_init(&p.base);
// First scene to start with.
if (argc >= 2 && strcmp("debug", argv[1]) == 0) {
gui_scene_debug(&p);
gui_scene_debug(&p.base);
} else if (argc >= 2 && strcmp("calibrate", argv[1]) == 0) {
gui_scene_select_video_calibrate(&p);
gui_scene_select_video_calibrate(&p.base);
} else {
gui_scene_main_menu(&p);
gui_scene_main_menu(&p.base);
}
// Main loop.
gui_imgui_loop(&p);
gui_sdl2_imgui_loop(&p);
// Clean up after us.
gui_prober_teardown(&p);
gui_prober_teardown(&p.base);
// All scenes should be destroyed by now.
gui_scene_manager_destroy(&p);
gui_scene_manager_destroy(&p.base);
// Final close.
gui_sdl2_quit(&p);

View file

@ -0,0 +1,16 @@
// Copyright 2019, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Enable the use of the prober in the gui application.
* @author Jakob Bornecrantz <jakob@collabora.com>
*/
#include "target_lists.h"
int
xrt_prober_create(struct xrt_prober **out_xp)
{
return xrt_prober_create_with_lists(out_xp, &target_lists);
}

View file

@ -17,17 +17,18 @@ gui = executable(
'monado-gui',
files(
'gui_common.h',
'gui_imgui.c',
'gui_imgui.h',
'gui_main.c',
'gui_ogl.c',
'gui_prober.c',
'gui_scene_calibrate.c',
'gui_scene.cpp',
'gui_scene_calibrate.c',
'gui_scene_debug.c',
'gui_scene_main_menu.c',
'gui_scene_video.c',
'gui_sdl2.c',
'gui_sdl2_imgui.c',
'gui_sdl2_main.c',
'gui_sdl2_prober.c',
'../../../external/glad/gl.h',
'../../../external/glad/gl.c',
'../../../external/imgui/cimgui.cpp',