The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

t/gui: Add SDL2 based GUI target

authored by

Jakob Bornecrantz and committed by
Jakob Bornecrantz
44d58037 d48b3385

+403
+14
CMakeLists.txt
··· 29 29 find_package(OpenCV COMPONENTS core calib3d highgui imgproc imgcodecs features2d video) 30 30 find_package(Libusb1) 31 31 find_package(JPEG) 32 + find_package(SDL2) 32 33 33 34 # @TODO Turn into a find_package LIBUVC file. 34 35 pkg_check_modules(LIBUVC libuvc) ··· 59 60 cmake_dependent_option(BUILD_WITH_FFMPEG "Enable ffmpeg testing video driver" ON "FFMPEG_FOUND" OFF) 60 61 cmake_dependent_option(BUILD_WITH_HIDAPI "Enable HIDAPI-based driver(s) (OSVR HDK, PSVR)" ON "HIDAPI_FOUND" OFF) 61 62 cmake_dependent_option(BUILD_WITH_OPENHMD "Enable OpenHMD driver" ON "OPENHMD_FOUND" OFF) 63 + cmake_dependent_option(BUILD_WITH_SDL2 "Enable SDL2 based test application" ON "SDL2_FOUND" OFF) 62 64 63 65 64 66 ### ··· 99 101 100 102 if(BUILD_WITH_FFMPEG) 101 103 add_definitions(-DXRT_HAVE_FFMPEG) 104 + endif() 105 + 106 + if(BUILD_WITH_SDL2) 107 + add_definitions(-DXRT_HAVE_SDL2) 108 + 109 + # Arch work around 110 + if(NOT DEFINED SDL2_LIBRARIES) 111 + set(SDL2_LIBRARIES SDL2::SDL2) 112 + endif() 113 + 114 + # SDL2 based gui 115 + set(BUILD_TARGET_GUI TRUE) 102 116 endif() 103 117 104 118 if(BUILD_WITH_OPENHMD)
+4
src/xrt/targets/CMakeLists.txt
··· 56 56 add_subdirectory(common) 57 57 add_subdirectory(openxr) 58 58 add_subdirectory(cli) 59 + 60 + if(BUILD_TARGET_GUI) 61 + add_subdirectory(gui) 62 + endif()
+62
src/xrt/targets/gui/CMakeLists.txt
··· 1 + # Copyright 2019, Collabora, Ltd. 2 + # SPDX-License-Identifier: BSL-1.0 3 + 4 + ###### 5 + # Create a small SDL2 based GUI for Monado. 6 + 7 + include_directories( 8 + ${CMAKE_CURRENT_SOURCE_DIR}/../../targets/common 9 + ${CMAKE_CURRENT_SOURCE_DIR}/../../auxiliary 10 + ${CMAKE_CURRENT_SOURCE_DIR}/../../include 11 + ${CMAKE_CURRENT_SOURCE_DIR}/../../drivers 12 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../external 13 + ${SDL2_INCLUDE_DIRS} 14 + ) 15 + 16 + set(SOURCE_FILES 17 + gui_common.h 18 + gui_main.c 19 + gui_sdl2.c 20 + ../../../external/glad/gl.h 21 + ../../../external/glad/gl.c 22 + ) 23 + 24 + add_executable(gui 25 + ${SOURCE_FILES} 26 + $<TARGET_OBJECTS:aux_os> 27 + $<TARGET_OBJECTS:aux_util> 28 + $<TARGET_OBJECTS:aux_math> 29 + $<TARGET_OBJECTS:st_prober> 30 + $<TARGET_OBJECTS:target_lists> 31 + ) 32 + 33 + set_target_properties(gui PROPERTIES 34 + OUTPUT_NAME monado-gui 35 + PREFIX "" 36 + ) 37 + 38 + target_link_libraries(gui PRIVATE 39 + ${LIBUSB_LIBRARIES} 40 + ${LIBUVC_LIBRARIES} 41 + ${UDEV_LIBRARIES} 42 + ${SDL2_LIBRARIES} 43 + ) 44 + 45 + if(BUILD_TRACKING) 46 + target_link_libraries(gui PRIVATE 47 + $<TARGET_OBJECTS:aux_tracking> 48 + ${OpenCV_LIBRARIES} 49 + ) 50 + endif() 51 + 52 + if(DRIVER_OBJECTS) 53 + target_sources(gui PRIVATE ${DRIVER_OBJECTS}) 54 + endif() 55 + 56 + if(BUILD_WITH_JPEG) 57 + target_link_libraries(gui PRIVATE ${JPEG_LIBRARIES}) 58 + endif() 59 + 60 + if(DRIVER_LIBRARIES) 61 + target_link_libraries(gui PRIVATE ${DRIVER_LIBRARIES}) 62 + endif()
+91
src/xrt/targets/gui/gui_common.h
··· 1 + // Copyright 2019, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Common file for the Monado GUI program. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup gui 8 + */ 9 + 10 + #pragma once 11 + 12 + #include "xrt/xrt_defines.h" 13 + #include <SDL2/SDL.h> 14 + 15 + /*! 16 + * @defgroup gui GUI Config Interface 17 + * @ingroup xrt 18 + * 19 + * @brief Small GUI interface to configure Monado based on SDL2. 20 + */ 21 + 22 + 23 + #ifdef __cplusplus 24 + extern "C" { 25 + #endif 26 + 27 + /*! 28 + * Common struct holding state for the GUI interface. 29 + * 30 + * @ingroup gui 31 + */ 32 + struct program 33 + { 34 + SDL_Window *win; 35 + SDL_GLContext ctx; 36 + 37 + bool stopped; 38 + bool initialized; 39 + 40 + struct 41 + { 42 + SDL_Surface *sf; 43 + uint8_t *buffer; 44 + size_t stride; 45 + uint32_t width; 46 + uint32_t height; 47 + bool own_buffer; 48 + } blit; 49 + }; 50 + 51 + /*! 52 + * Init SDL2, create and show a window and bring up any other structs needed. 53 + * 54 + * @ingroup gui 55 + */ 56 + int 57 + gui_sdl2_init(struct program *p); 58 + 59 + /*! 60 + * Loop until quit signal has been received. 61 + * 62 + * @ingroup gui 63 + */ 64 + void 65 + gui_sdl2_loop(struct program *p); 66 + 67 + /*! 68 + * Display a 24bit RGB image on the screen. 69 + * 70 + * @ingroup gui 71 + */ 72 + void 73 + gui_sdl2_display_R8G8B8(struct program *p, 74 + bool resize, 75 + uint32_t width, 76 + uint32_t height, 77 + size_t stride, 78 + void *data); 79 + 80 + /*! 81 + * Destroy all SDL things and quit SDL. 82 + * 83 + * @ingroup gui 84 + */ 85 + void 86 + gui_sdl2_quit(struct program *p); 87 + 88 + 89 + #ifdef __cplusplus 90 + } 91 + #endif
+30
src/xrt/targets/gui/gui_main.c
··· 1 + // Copyright 2019, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief Main entrypoint for the Monado GUI program. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup gui 8 + */ 9 + 10 + #include "gui_common.h" 11 + 12 + 13 + int 14 + main(int argc, char **argv) 15 + { 16 + struct program p = {0}; 17 + int ret; 18 + 19 + ret = gui_sdl2_init(&p); 20 + if (ret != 0) { 21 + gui_sdl2_quit(&p); 22 + return ret; 23 + } 24 + 25 + gui_sdl2_loop(&p); 26 + 27 + gui_sdl2_quit(&p); 28 + 29 + return 0; 30 + }
+202
src/xrt/targets/gui/gui_sdl2.c
··· 1 + // Copyright 2019, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief SDL2 functions to drive the GUI. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup gui 8 + */ 9 + 10 + #include "gui_common.h" 11 + #include "glad/gl.h" 12 + 13 + 14 + /* 15 + * 16 + * Internal static functions 17 + * 18 + */ 19 + 20 + XRT_MAYBE_UNUSED static void 21 + create_blit_info(struct program *p, uint32_t width, uint32_t height) 22 + { 23 + if (p->blit.sf != NULL) { 24 + SDL_FreeSurface(p->blit.sf); 25 + p->blit.sf = NULL; 26 + 27 + if (p->blit.own_buffer) { 28 + free(p->blit.buffer); 29 + } 30 + p->blit.buffer = NULL; 31 + } 32 + 33 + size_t stride = width * 4; 34 + size_t size = stride * height; 35 + p->blit.width = width; 36 + p->blit.height = height; 37 + p->blit.stride = stride; 38 + p->blit.own_buffer = true; 39 + 40 + p->blit.buffer = malloc(size); 41 + p->blit.sf = 42 + SDL_CreateRGBSurfaceFrom(p->blit.buffer, width, height, 32, stride, 43 + 0x0000FF, 0x00FF00, 0xFF0000, 0); 44 + } 45 + 46 + static void 47 + sdl2_handle_keydown(struct program *p, const SDL_Event *e) 48 + { 49 + switch (e->key.keysym.sym) { 50 + case SDLK_ESCAPE: p->stopped = true; break; 51 + default: break; 52 + } 53 + 54 + return; 55 + } 56 + 57 + 58 + /* 59 + * 60 + * "Exported" functions. 61 + * 62 + */ 63 + 64 + void 65 + gui_sdl2_display_R8G8B8(struct program *p, 66 + bool resize, 67 + uint32_t width, 68 + uint32_t height, 69 + size_t stride, 70 + void *data) 71 + { 72 + if (p->blit.buffer != data || p->blit.width != width || 73 + p->blit.height != height || p->blit.sf == NULL) { 74 + 75 + if (resize) { 76 + SDL_SetWindowSize(p->win, width, height); 77 + } 78 + 79 + p->blit.sf = 80 + SDL_CreateRGBSurfaceFrom(data, width, height, 24, stride, 81 + 0x0000FF, 0x00FF00, 0xFF0000, 0); 82 + 83 + p->blit.width = width; 84 + p->blit.height = height; 85 + p->blit.stride = stride; 86 + p->blit.buffer = data; 87 + p->blit.own_buffer = false; 88 + } 89 + 90 + SDL_Surface *win_sf = SDL_GetWindowSurface(p->win); 91 + 92 + if (SDL_BlitSurface(p->blit.sf, NULL, win_sf, NULL) == 0) { 93 + SDL_UpdateWindowSurface(p->win); 94 + } 95 + } 96 + 97 + void 98 + gui_sdl2_loop(struct program *p) 99 + { 100 + SDL_Event event; 101 + while (!p->stopped) { 102 + if (SDL_WaitEvent(&event) == 0) { 103 + return; 104 + } 105 + 106 + if (event.type == SDL_QUIT) { 107 + return; 108 + } 109 + 110 + if (event.type == SDL_KEYDOWN) { 111 + sdl2_handle_keydown(p, &event); 112 + } 113 + } 114 + 115 + return; 116 + } 117 + 118 + int 119 + gui_sdl2_init(struct program *p) 120 + { 121 + if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { 122 + return -1; 123 + } 124 + 125 + const char *title = "Monado! ☺"; 126 + int x = SDL_WINDOWPOS_UNDEFINED; 127 + int y = SDL_WINDOWPOS_UNDEFINED; 128 + int w = 1920; 129 + int h = 1080; 130 + 131 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); 132 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 133 + SDL_GL_CONTEXT_PROFILE_CORE); 134 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); 135 + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); 136 + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 137 + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 138 + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 139 + 140 + SDL_WindowFlags window_flags = 0; 141 + window_flags |= SDL_WINDOW_SHOWN; 142 + window_flags |= SDL_WINDOW_OPENGL; 143 + window_flags |= SDL_WINDOW_RESIZABLE; 144 + window_flags |= SDL_WINDOW_ALLOW_HIGHDPI; 145 + #if 0 146 + window_flags |= SDL_WINDOW_MAXIMIZED; 147 + #endif 148 + 149 + p->initialized = true; 150 + p->win = SDL_CreateWindow(title, x, y, w, h, window_flags); 151 + 152 + if (p->win == NULL) { 153 + return -1; 154 + } 155 + 156 + p->ctx = SDL_GL_CreateContext(p->win); 157 + if (p->ctx == NULL) { 158 + return -1; 159 + } 160 + 161 + SDL_GL_MakeCurrent(p->win, p->ctx); 162 + SDL_GL_SetSwapInterval(1); // Enable vsync 163 + 164 + // Setup OpenGL bindings. 165 + bool err = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress) == 0; 166 + if (err) { 167 + return -1; 168 + } 169 + 170 + return 0; 171 + } 172 + 173 + void 174 + gui_sdl2_quit(struct program *p) 175 + { 176 + if (!p->initialized) { 177 + return; 178 + } 179 + 180 + if (p->blit.sf != NULL) { 181 + SDL_FreeSurface(p->blit.sf); 182 + p->blit.sf = NULL; 183 + 184 + if (p->blit.own_buffer) { 185 + free(p->blit.buffer); 186 + } 187 + p->blit.buffer = NULL; 188 + } 189 + 190 + if (p->ctx != NULL) { 191 + SDL_GL_DeleteContext(p->ctx); 192 + p->ctx = NULL; 193 + } 194 + 195 + if (p->win != NULL) { 196 + SDL_DestroyWindow(p->win); 197 + p->win = NULL; 198 + } 199 + 200 + SDL_Quit(); 201 + p->initialized = false; 202 + }