The open source OpenXR runtime
at main 180 lines 4.5 kB view raw
1// Copyright 2020-2022, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief C++ program part for the SDL test. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup sdl_test 8 */ 9 10#include "ogl/ogl_api.h" 11 12#include "util/u_misc.h" 13 14#include "sdl_internal.hpp" 15 16#include <cstdio> 17 18void 19sdl_create_window(struct sdl_program *sp) 20{ 21 if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { 22 assert(false); 23 } 24 25 char title[1024]; 26 snprintf(title, sizeof(title), "Monado! ☃"); 27 28 int x = SDL_WINDOWPOS_UNDEFINED; 29 int y = SDL_WINDOWPOS_UNDEFINED; 30 int w = 1920; 31 int h = 1080; 32 33 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); 34 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); 35 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); 36 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 37 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5); 38 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 39 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); 40 SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); 41 42 int window_flags = 0; 43 window_flags |= SDL_WINDOW_SHOWN; 44 window_flags |= SDL_WINDOW_OPENGL; 45 window_flags |= SDL_WINDOW_RESIZABLE; 46 window_flags |= SDL_WINDOW_ALLOW_HIGHDPI; 47#if 0 48 window_flags |= SDL_WINDOW_MAXIMIZED; 49#endif 50 51 52 sp->win = SDL_CreateWindow(title, x, y, w, h, window_flags); 53 54 if (sp->win == NULL) { 55 assert(false); 56 } 57 58 sp->ctx = SDL_GL_CreateContext(sp->win); 59 if (sp->ctx == NULL) { 60 assert(false); 61 } 62 63 // Make the context current in this thread for loading OpenGL. 64 sdl_make_current(sp); 65 SDL_GL_SetSwapInterval(1); // Enable vsync 66 67 // Setup OpenGL bindings. 68 bool err = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress) == 0; 69 if (err) { 70 assert(false); 71 } 72 73 // We are going to render on a different thread, make sure to unbind it. 74 sdl_make_uncurrent(sp); 75} 76 77extern "C" struct sdl_program * 78sdl_program_plus_create() 79{ 80 sdl_program_plus &spp = *new sdl_program_plus(); 81 spp.spp = &spp; 82 83 os_mutex_init(&spp.current_mutex); 84 85 // Initial state. 86 spp.log_level = U_LOGGING_INFO; 87 spp.state.head.pose = XRT_POSE_IDENTITY; 88 89 // Create the window, init before sub components. 90 sdl_create_window(&spp); 91 92 // Init sub components. 93 sdl_instance_init(&spp); 94 sdl_system_init(&spp); 95 sdl_device_init(&spp); 96 sdl_system_devices_init(&spp); 97 sdl_compositor_init(&spp); // Needs the window. 98 99 return &spp; 100} 101 102extern "C" void 103sdl_program_plus_render(struct sdl_program_plus *spp_ptr) 104{ 105 auto &spp = *spp_ptr; 106 107 // Make context current 108 sdl_make_current(&spp); 109 110 // Flush the events. 111 SDL_Event e = {0}; 112 while (SDL_PollEvent(&e)) { 113 // Nothing for now. 114 } 115 116 if (spp.c.base.layer_accum.layer_count == 0) { 117 glClearColor(0.2f, 0.2f, 0.2f, 0.0f); 118 glClear(GL_COLOR_BUFFER_BIT); 119 } else if (spp.c.base.layer_accum.layers[0].data.type == XRT_LAYER_PROJECTION || 120 spp.c.base.layer_accum.layers[0].data.type == XRT_LAYER_PROJECTION_DEPTH) { 121 122 auto &l = spp.c.base.layer_accum.layers[0]; 123 auto &ssc = *(sdl_swapchain *)l.sc_array[0]; 124 GLuint tex = ssc.textures[l.data.proj.v[0].sub.image_index]; 125 126 glClearColor(0.2f, 0.0f, 0.0f, 0.0f); 127 glClear(GL_COLOR_BUFFER_BIT); 128 129 GLuint fbo = 0; 130 glGenFramebuffers(1, &fbo); 131 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); 132 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 133 CHECK_GL(); 134 135 glFramebufferTexture2D( // 136 GL_READ_FRAMEBUFFER, // GLenum target 137 GL_COLOR_ATTACHMENT0, // GLenum attachment 138 GL_TEXTURE_2D, // GLenum textarget 139 tex, // GLuint texture 140 0); // GLint level 141 CHECK_GL(); 142 143 int w, h; 144 SDL_GetWindowSize(spp.win, &w, &h); 145 glBlitFramebuffer( // 146 0, // GLint srcX0 147 0, // GLint srcY0 148 ssc.w, // GLint srcX1 149 ssc.h, // GLint srcY1 150 0, // GLint dstX0 151 0, // GLint dstY0 152 w, // GLint dstX1 153 h, // GLint dstY1 154 GL_COLOR_BUFFER_BIT, // GLbitfield mask 155 GL_NEAREST); // GLenum filter 156 CHECK_GL(); 157 158 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); 159 CHECK_GL(); 160 161 glDeleteFramebuffers(1, &fbo); 162 } else { 163 glClearColor(1.0f, 0.0f, 1.0f, 0.0f); 164 glClear(GL_COLOR_BUFFER_BIT); 165 } 166 167 // Display what we rendered. 168 SDL_GL_SwapWindow(spp.win); 169 170 // Will be used when creating swapchains, unbind it. 171 sdl_make_uncurrent(&spp); 172} 173 174extern "C" void 175sdl_program_plus_destroy(struct sdl_program_plus *spp) 176{ 177 os_mutex_destroy(&spp->current_mutex); 178 179 delete spp; 180}