monado/src/xrt/targets/sdl_test/sdl_internal.h
2022-09-15 14:06:20 +01:00

411 lines
7.7 KiB
C

// Copyright 2020-2022, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief Internal header for SDL XR system.
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup sdl_test
*/
#include "xrt/xrt_system.h"
#include "xrt/xrt_device.h"
#include "xrt/xrt_instance.h"
#include "xrt/xrt_tracking.h"
#include "xrt/xrt_compositor.h"
#include "util/u_pacing.h"
#include "util/u_logging.h"
#include "util/comp_base.h"
#include "util/comp_swapchain.h"
#include "SDL2/SDL.h"
#include "ogl/ogl_api.h"
#ifdef __cplusplus
extern "C" {
#endif
struct sdl_program;
/*!
* Sub-class of @ref comp_swapchain, used to do OpenGL rendering.
*
* @ingroup sdl_test
*/
struct sdl_swapchain
{
struct comp_swapchain base;
//! Pointer back to main program.
struct sdl_program *sp;
//! Cached width and height.
int w, h;
//! Number of textures in base.base.base.image_count.
GLuint textures[XRT_MAX_SWAPCHAIN_IMAGES];
//! Same number of images as textures.
GLuint memory[XRT_MAX_SWAPCHAIN_IMAGES];
};
/*!
* State to emulate state transitions correctly.
*
* @ingroup sdl_test
*/
enum sdl_comp_state
{
SDL_COMP_STATE_UNINITIALIZED = 0,
SDL_COMP_STATE_READY = 1,
SDL_COMP_STATE_PREPARED = 2,
SDL_COMP_STATE_VISIBLE = 3,
SDL_COMP_STATE_FOCUSED = 4,
};
/*!
* Tracking frame state.
*
* @ingroup sdl_test
*/
struct sdl_comp_frame
{
int64_t id;
uint64_t predicted_display_time_ns;
uint64_t desired_present_time_ns;
uint64_t present_slop_ns;
};
/*!
* Split out for convinecne.
*
* @ingroup sdl_test
*/
struct sdl_compositor
{
//! Base native compositor.
struct comp_base base;
//! Pacing helper to drive us forward.
struct u_pacing_compositor *upc;
struct
{
//! Frame interval that we are using.
uint64_t frame_interval_ns;
} settings;
// Kept here for convenience.
struct xrt_system_compositor_info sys_info;
//! State for generating the correct set of events.
enum sdl_comp_state state;
//! @todo Insert your own required members here
struct
{
struct sdl_comp_frame waited;
struct sdl_comp_frame rendering;
} frame;
};
struct sdl_program_plus;
/*!
* C base class for the SDL program.
*
* @ingroup sdl_test
*/
struct sdl_program
{
//! Base class for devices.
struct xrt_device xdev_base;
//! Instance base.
struct xrt_instance xinst_base;
//! System devices base.
struct xrt_system_devices xsysd_base;
//! SDL compositor struct.
struct sdl_compositor c;
//! Created system compositor.
struct xrt_system_compositor *xsysc;
//! Inputs exposed by the SDL device.
struct xrt_input inputs[1];
//! HMD parts exposed by the SDL device to become a HMD.
struct xrt_hmd_parts hmd;
//! Tracking origin that the device is located in.
struct xrt_tracking_origin origin;
//! The current log level.
enum u_logging_level log_level;
struct
{
struct
{
//! The pose of the head, only used for view space.
struct xrt_pose pose;
} head;
struct
{
//! Pose of each individual eye.
struct xrt_pose pose;
//! Fov of each individual eye.
struct xrt_fov fov;
} left, right;
} state;
//! The main window.
SDL_Window *win;
//! Main OpenGL context.
SDL_GLContext ctx;
//! Protects the OpenGL context.
struct os_mutex current_mutex;
//! Pointer back to the C++ part of the program.
struct sdl_program_plus *spp;
};
static inline struct sdl_program *
from_xinst(struct xrt_instance *xinst)
{
return container_of(xinst, struct sdl_program, xinst_base);
}
static inline struct sdl_program *
from_xsysd(struct xrt_system_devices *xsysd)
{
return container_of(xsysd, struct sdl_program, xsysd_base);
}
static inline struct sdl_program *
from_xdev(struct xrt_device *xdev)
{
return container_of(xdev, struct sdl_program, xdev_base);
}
static inline struct sdl_program *
from_comp(struct xrt_compositor *xc)
{
return container_of(xc, struct sdl_program, c.base.base);
}
/*!
* Spew level logging.
*
* @relates sdl_program
* @ingroup sdl_test
*/
#define SP_TRACE(sp, ...) U_LOG_IFL_T(sp->log_level, __VA_ARGS__);
/*!
* Debug level logging.
*
* @relates sdl_program
*/
#define SP_DEBUG(sp, ...) U_LOG_IFL_D(sp->log_level, __VA_ARGS__);
/*!
* Info level logging.
*
* @relates sdl_program
* @ingroup sdl_test
*/
#define SP_INFO(sp, ...) U_LOG_IFL_I(sp->log_level, __VA_ARGS__);
/*!
* Warn level logging.
*
* @relates sdl_program
* @ingroup sdl_test
*/
#define SP_WARN(sp, ...) U_LOG_IFL_W(sp->log_level, __VA_ARGS__);
/*!
* Error level logging.
*
* @relates sdl_program
* @ingroup sdl_test
*/
#define SP_ERROR(sp, ...) U_LOG_IFL_E(sp->log_level, __VA_ARGS__);
/*!
* Check for OpenGL errors, context needs to be current.
*
* @ingroup sdl_test
*/
#define CHECK_GL() \
do { \
GLint err = glGetError(); \
if (err != 0) { \
U_LOG_RAW("%s:%u: error: 0x%04x", __func__, __LINE__, err); \
} \
} while (false)
/*!
* Makes the OpenGL context current in this thread, takes lock.
*
* @ingroup sdl_test
*/
static inline void
sdl_make_current(struct sdl_program *sp)
{
os_mutex_lock(&sp->current_mutex);
SDL_GL_MakeCurrent(sp->win, sp->ctx);
}
/*!
* Unmakes the any OpenGL context current in this thread, releases the lock.
*
* @ingroup sdl_test
*/
static inline void
sdl_make_uncurrent(struct sdl_program *sp)
{
SDL_GL_MakeCurrent(NULL, NULL);
os_mutex_unlock(&sp->current_mutex);
}
/*
*
* sdl_device.c
*
*/
/*!
* Init the @ref xrt_device sub struct.
*
* In sdl_device.c
*
* @ingroup sdl_test
*/
void
sdl_device_init(struct sdl_program *sp);
/*
*
* sdl_swapchain.c
*
*/
/*!
* Implementation of @ref xrt_compositor::create_swapchain.
*
* @ingroup sdl_test
*/
xrt_result_t
sdl_swapchain_create(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_swapchain **out_xsc);
/*!
* Implementation of @ref xrt_compositor::import_swapchain.
*
* @ingroup sdl_test
*/
xrt_result_t
sdl_swapchain_import(struct xrt_compositor *xc,
const struct xrt_swapchain_create_info *info,
struct xrt_image_native *native_images,
uint32_t native_image_count,
struct xrt_swapchain **out_xsc);
/*
*
* sdl_compositor.c
*
*/
/*!
* Initializes the compositor part of the SDL program.
*
* @ingroup sdl_test
*/
void
sdl_compositor_init(struct sdl_program *sp);
/*!
* Creates the system compositor that wraps the native compositor.
*
* @ingroup sdl_test
*/
xrt_result_t
sdl_compositor_create_system(struct sdl_program *sp, struct xrt_system_compositor **out_xsysc);
/*
*
* sdl_instance.c
*
*/
/*!
* Init the @ref xrt_system_devices sub struct.
*
* @ingroup sdl_test
*/
void
sdl_system_devices_init(struct sdl_program *sp);
/*!
* Init the @ref xrt_instance sub struct.
*
* @ingroup sdl_test
*/
void
sdl_instance_init(struct sdl_program *sp);
/*
*
* sdl_program.cpp
*
*/
/*!
* Create the SDL program.
*
* @ingroup sdl_test
*/
struct sdl_program *
sdl_program_plus_create();
/*!
* Render a frame, called by the compositor when layers have been committed.
*
* @ingroup sdl_test
*/
void
sdl_program_plus_render(struct sdl_program_plus *spp);
/*!
* Destroy the SDL program.
*
* @ingroup sdl_test
*/
void
sdl_program_plus_destroy(struct sdl_program_plus *spp);
#ifdef __cplusplus
}
#endif