monado/src/xrt/targets/sdl_test/sdl_program.cpp

179 lines
4.4 KiB
C++
Raw Normal View History

2022-06-01 19:16:18 +00:00
// Copyright 2020-2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief C++ program part for the SDL test.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup sdl_test
*/
#include "ogl/ogl_api.h"
#include "util/u_misc.h"
#include "sdl_internal.hpp"
void
sdl_create_window(struct sdl_program *sp)
{
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
assert(false);
}
char title[1024];
snprintf(title, sizeof(title), "Monado! ☃");
int x = SDL_WINDOWPOS_UNDEFINED;
int y = SDL_WINDOWPOS_UNDEFINED;
int w = 1920;
int h = 1080;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
int window_flags = 0;
window_flags |= SDL_WINDOW_SHOWN;
window_flags |= SDL_WINDOW_OPENGL;
window_flags |= SDL_WINDOW_RESIZABLE;
window_flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#if 0
window_flags |= SDL_WINDOW_MAXIMIZED;
#endif
sp->win = SDL_CreateWindow(title, x, y, w, h, window_flags);
if (sp->win == NULL) {
assert(false);
}
sp->ctx = SDL_GL_CreateContext(sp->win);
if (sp->ctx == NULL) {
assert(false);
}
// Make the context current in this thread for loading OpenGL.
sdl_make_current(sp);
SDL_GL_SetSwapInterval(1); // Enable vsync
// Setup OpenGL bindings.
bool err = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress) == 0;
if (err) {
assert(false);
}
// We are going to render on a different thread, make sure to unbind it.
sdl_make_uncurrent(sp);
}
extern "C" struct sdl_program *
sdl_program_plus_create()
{
sdl_program_plus &spp = *new sdl_program_plus();
spp.spp = &spp;
os_mutex_init(&spp.current_mutex);
// Initial state.
spp.log_level = U_LOGGING_INFO;
spp.state.head.pose = XRT_POSE_IDENTITY;
// Create the window, init before sub components.
sdl_create_window(&spp);
// Init sub components.
sdl_instance_init(&spp);
sdl_system_devices_init(&spp);
sdl_device_init(&spp);
sdl_compositor_init(&spp); // Needs the window.
return &spp;
}
extern "C" void
sdl_program_plus_render(struct sdl_program_plus *spp_ptr)
{
auto &spp = *spp_ptr;
// Make context current
sdl_make_current(&spp);
// Flush the events.
SDL_Event e = {0};
while (SDL_PollEvent(&e)) {
// Nothing for now.
}
if (spp.c.base.slot.layer_count == 0) {
glClearColor(0.2f, 0.2f, 0.2f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
} else if (spp.c.base.slot.layers[0].data.type == XRT_LAYER_STEREO_PROJECTION ||
spp.c.base.slot.layers[0].data.type == XRT_LAYER_STEREO_PROJECTION_DEPTH) {
auto &l = spp.c.base.slot.layers[0];
auto &ssc = *(sdl_swapchain *)l.sc_array[0];
GLuint tex = ssc.textures[l.data.stereo.l.sub.image_index];
glClearColor(0.2f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
GLuint fbo = 0;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
CHECK_GL();
glFramebufferTexture2D( //
GL_READ_FRAMEBUFFER, // GLenum target
GL_COLOR_ATTACHMENT0, // GLenum attachment
GL_TEXTURE_2D, // GLenum textarget
tex, // GLuint texture
0); // GLint level
CHECK_GL();
int w, h;
SDL_GetWindowSize(spp.win, &w, &h);
glBlitFramebuffer( //
0, // GLint srcX0
0, // GLint srcY0
ssc.w, // GLint srcX1
ssc.h, // GLint srcY1
0, // GLint dstX0
0, // GLint dstY0
w, // GLint dstX1
h, // GLint dstY1
GL_COLOR_BUFFER_BIT, // GLbitfield mask
GL_NEAREST); // GLenum filter
CHECK_GL();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
CHECK_GL();
glDeleteFramebuffers(1, &fbo);
} else {
glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
// Display what we rendered.
SDL_GL_SwapWindow(spp.win);
// Will be used when creating swapchains, unbind it.
sdl_make_uncurrent(&spp);
}
extern "C" void
sdl_program_plus_destroy(struct sdl_program_plus *spp)
{
os_mutex_destroy(&spp->current_mutex);
delete spp;
}