The open source OpenXR runtime
0
fork

Configure Feed

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

t/gui: Add OpenGL sink code

authored by

Jakob Bornecrantz and committed by
Jakob Bornecrantz
c4741127 968952aa

+216 -1
+1
src/xrt/targets/gui/CMakeLists.txt
··· 16 16 set(SOURCE_FILES 17 17 gui_common.h 18 18 gui_main.c 19 + gui_ogl.c 19 20 gui_prober.c 20 21 gui_sdl2.c 21 22 ../../../external/glad/gl.h
+39 -1
src/xrt/targets/gui/gui_common.h
··· 9 9 10 10 #pragma once 11 11 12 - #include "xrt/xrt_defines.h" 12 + #include "xrt/xrt_frame.h" 13 13 #include <SDL2/SDL.h> 14 14 15 15 /*! ··· 55 55 struct time_state *timekeeping; 56 56 struct xrt_device *xdevs[NUM_XDEVS]; 57 57 struct xrt_prober *xp; 58 + 59 + struct gui_ogl_texture *texs[256]; 60 + }; 61 + 62 + /*! 63 + * A OpenGL texture. 64 + * 65 + * @ingroup gui 66 + */ 67 + struct gui_ogl_texture 68 + { 69 + uint64_t seq; 70 + uint64_t dropped; 71 + const char *name; 72 + uint32_t w, h; 73 + uint32_t id; 74 + bool half; 58 75 }; 59 76 60 77 /*! ··· 117 134 */ 118 135 void 119 136 gui_prober_teardown(struct program *p); 137 + 138 + /*! 139 + * Create a sink that will turn frames into OpenGL textures, since the frame 140 + * can come from another thread @ref gui_ogl_sink_update needs to be called. 141 + * 142 + * Destruction is handled by the frame context. 143 + * 144 + * @ingroup gui 145 + */ 146 + struct gui_ogl_texture * 147 + gui_ogl_sink_create(const char *name, 148 + struct xrt_frame_context *xfctx, 149 + struct xrt_frame_sink **out_sink); 150 + 151 + /*! 152 + * Update the texture to the latest received frame. 153 + * 154 + * @ingroup gui 155 + */ 156 + void 157 + gui_ogl_sink_update(struct gui_ogl_texture *); 120 158 121 159 122 160 #ifdef __cplusplus
+176
src/xrt/targets/gui/gui_ogl.c
··· 1 + // Copyright 2019, Collabora, Ltd. 2 + // SPDX-License-Identifier: BSL-1.0 3 + /*! 4 + * @file 5 + * @brief OpenGL functions to drive the gui. 6 + * @author Jakob Bornecrantz <jakob@collabora.com> 7 + * @ingroup gui 8 + */ 9 + 10 + #include "xrt/xrt_frame.h" 11 + #include "util/u_misc.h" 12 + 13 + #include "gui_common.h" 14 + #include "glad/gl.h" 15 + 16 + #include <pthread.h> 17 + 18 + 19 + struct gui_ogl_sink 20 + { 21 + struct gui_ogl_texture tex; 22 + 23 + struct xrt_frame_sink sink; 24 + struct xrt_frame_node node; 25 + 26 + struct xrt_frame *frame; 27 + 28 + pthread_mutex_t mutex; 29 + 30 + bool running; 31 + }; 32 + 33 + static void 34 + push_frame(struct xrt_frame_sink *xs, struct xrt_frame *xf) 35 + { 36 + struct gui_ogl_sink *s = container_of(xs, struct gui_ogl_sink, sink); 37 + 38 + // The fields are protected. 39 + pthread_mutex_lock(&s->mutex); 40 + 41 + // If we are in the process of shutting down, don't take the reference. 42 + if (s->running) { 43 + xrt_frame_reference(&s->frame, xf); 44 + } 45 + 46 + // Done 47 + pthread_mutex_unlock(&s->mutex); 48 + } 49 + 50 + static void 51 + break_apart(struct xrt_frame_node *node) 52 + { 53 + struct gui_ogl_sink *s = container_of(node, struct gui_ogl_sink, node); 54 + 55 + // Stop receiving any more reference. 56 + pthread_mutex_lock(&s->mutex); 57 + s->running = false; 58 + pthread_mutex_unlock(&s->mutex); 59 + } 60 + 61 + static void 62 + destroy(struct xrt_frame_node *node) 63 + { 64 + struct gui_ogl_sink *s = container_of(node, struct gui_ogl_sink, node); 65 + 66 + glDeleteTextures(1, &s->tex.id); 67 + 68 + pthread_mutex_destroy(&s->mutex); 69 + 70 + free(s); 71 + } 72 + 73 + static void 74 + update_r8g8b8(struct gui_ogl_sink *s, GLint w, GLint h, uint8_t *data) 75 + { 76 + glBindTexture(GL_TEXTURE_2D, s->tex.id); 77 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, 78 + GL_UNSIGNED_BYTE, data); 79 + glBindTexture(GL_TEXTURE_2D, 0); 80 + } 81 + 82 + static void 83 + update_l8(struct gui_ogl_sink *s, GLint w, GLint h, uint8_t *data) 84 + { 85 + glBindTexture(GL_TEXTURE_2D, s->tex.id); 86 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, w, h, 0, GL_RED, 87 + GL_UNSIGNED_BYTE, data); 88 + GLint swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_ONE}; 89 + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); 90 + glBindTexture(GL_TEXTURE_2D, 0); 91 + } 92 + 93 + void 94 + gui_ogl_sink_update(struct gui_ogl_texture *tex) 95 + { 96 + struct gui_ogl_sink *s = container_of(tex, struct gui_ogl_sink, tex); 97 + (void)s; 98 + 99 + // Take the frame no need to adjust reference. 100 + pthread_mutex_lock(&s->mutex); 101 + struct xrt_frame *frame = s->frame; 102 + s->frame = NULL; 103 + pthread_mutex_unlock(&s->mutex); 104 + 105 + if (frame == NULL) { 106 + return; 107 + } 108 + 109 + GLint w, h; 110 + uint8_t *data; 111 + 112 + w = frame->width; 113 + h = frame->height; 114 + 115 + if (tex->w != (uint32_t)w || tex->h != (uint32_t)h) { 116 + tex->w = w; 117 + tex->h = h; 118 + 119 + // Automatically set the half scaling. 120 + if (tex->w >= 1024 || tex->h >= 1024) { 121 + tex->half = true; 122 + } 123 + } 124 + 125 + tex->seq = frame->source_sequence; 126 + data = frame->data; 127 + 128 + switch (frame->format) { 129 + case XRT_FORMAT_R8G8B8: update_r8g8b8(s, w, h, data); break; 130 + case XRT_FORMAT_L8: update_l8(s, w, h, data); break; 131 + default: break; 132 + } 133 + 134 + xrt_frame_reference(&frame, NULL); 135 + } 136 + 137 + struct gui_ogl_texture * 138 + gui_ogl_sink_create(const char *name, 139 + struct xrt_frame_context *xfctx, 140 + struct xrt_frame_sink **out_sink) 141 + { 142 + struct gui_ogl_sink *s = U_TYPED_CALLOC(struct gui_ogl_sink); 143 + int ret = 0; 144 + 145 + s->sink.push_frame = push_frame; 146 + s->node.break_apart = break_apart; 147 + s->node.destroy = destroy; 148 + s->tex.name = name; 149 + s->tex.w = 256; 150 + s->tex.h = 256; 151 + s->running = true; 152 + 153 + ret = pthread_mutex_init(&s->mutex, NULL); 154 + if (ret != 0) { 155 + free(s); 156 + return NULL; 157 + } 158 + 159 + // Temporary texture 160 + glGenTextures(1, &s->tex.id); 161 + glBindTexture(GL_TEXTURE_2D, s->tex.id); 162 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 163 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 164 + GLint w = 1; 165 + GLint h = 1; 166 + struct xrt_colour_rgb_u8 pink = {255, 0, 255}; 167 + 168 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGB, 169 + GL_UNSIGNED_BYTE, &pink.r); 170 + 171 + glBindTexture(GL_TEXTURE_2D, 0); 172 + 173 + *out_sink = &s->sink; 174 + 175 + return &s->tex; 176 + }