mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-25 16:11:45 +00:00
416 lines
9.7 KiB
C
416 lines
9.7 KiB
C
// Copyright 2020, Collabora, Ltd.
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
/*!
|
|
* @file
|
|
* @brief Abstracted compositor rendering target.
|
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
|
* @ingroup comp_main
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "xrt/xrt_compiler.h"
|
|
#include "xrt/xrt_defines.h"
|
|
|
|
#include "vk/vk_helpers.h"
|
|
|
|
#include "util/u_trace_marker.h"
|
|
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/*!
|
|
* For marking timepoints on a frame's lifetime, not a async event.
|
|
*/
|
|
enum comp_target_timing_point
|
|
{
|
|
COMP_TARGET_TIMING_POINT_WAKE_UP, //<! Woke up after sleeping in wait frame.
|
|
COMP_TARGET_TIMING_POINT_BEGIN, //<! Began CPU side work for GPU.
|
|
COMP_TARGET_TIMING_POINT_SUBMIT, //<! Submitted work to the GPU.
|
|
};
|
|
|
|
/*!
|
|
* If the target should use the display timing information.
|
|
*/
|
|
enum comp_target_display_timing_usage
|
|
{
|
|
COMP_TARGET_FORCE_FAKE_DISPLAY_TIMING = 0,
|
|
COMP_TARGET_USE_DISPLAY_IF_AVAILABLE = 1,
|
|
};
|
|
|
|
/*!
|
|
* Image and view pair for @ref comp_target.
|
|
*
|
|
* @ingroup comp_main
|
|
*/
|
|
struct comp_target_image
|
|
{
|
|
VkImage handle;
|
|
VkImageView view;
|
|
};
|
|
|
|
/*!
|
|
* A target is essentially a swapchain, but it is such a overloaded term so
|
|
* we are differencating swapchains that the compositor provides to clients and
|
|
* swapchains that the compositor renders by naming the latter to target.
|
|
*
|
|
* @ingroup comp_main
|
|
*/
|
|
struct comp_target
|
|
{
|
|
//! Owning compositor.
|
|
struct comp_compositor *c;
|
|
|
|
//! Name of the backing system.
|
|
const char *name;
|
|
|
|
//! Current dimensions of the target.
|
|
uint32_t width, height;
|
|
|
|
//! The format that the renderpass targeting this target should use.
|
|
VkFormat format;
|
|
|
|
//! Number of images that this target has.
|
|
uint32_t num_images;
|
|
//! Array of images and image views for rendering.
|
|
struct comp_target_image *images;
|
|
|
|
//! Transformation of the current surface, required for pre-rotation
|
|
VkSurfaceTransformFlagBitsKHR surface_transform;
|
|
|
|
|
|
/*
|
|
*
|
|
* Vulkan functions.
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* Do any initialization that is required to happen before Vulkan has
|
|
* been loaded.
|
|
*/
|
|
bool (*init_pre_vulkan)(struct comp_target *ct);
|
|
|
|
/*!
|
|
* Do any initialization that requires Vulkan to be loaded, you need to
|
|
* call @ref create_images after calling this function.
|
|
*/
|
|
bool (*init_post_vulkan)(struct comp_target *ct, uint32_t preferred_width, uint32_t preferred_height);
|
|
|
|
/*!
|
|
* Create or recreate the image(s) of the target, for swapchain based
|
|
* targets this will (re)create the swapchain.
|
|
*/
|
|
void (*create_images)(struct comp_target *ct,
|
|
uint32_t preferred_width,
|
|
uint32_t preferred_height,
|
|
VkFormat preferred_color_format,
|
|
VkColorSpaceKHR preferred_color_space,
|
|
VkPresentModeKHR present_mode);
|
|
|
|
/*!
|
|
* Acquire the next image for rendering.
|
|
*/
|
|
VkResult (*acquire)(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index);
|
|
|
|
/*!
|
|
* Present the image at index to the screen.
|
|
*/
|
|
VkResult (*present)(struct comp_target *ct,
|
|
VkQueue queue,
|
|
uint32_t index,
|
|
VkSemaphore semaphore,
|
|
uint64_t desired_present_time_ns,
|
|
uint64_t present_slop_ns);
|
|
|
|
/*!
|
|
* Flush any WSI state before rendering.
|
|
*/
|
|
void (*flush)(struct comp_target *ct);
|
|
|
|
|
|
/*
|
|
*
|
|
* Timing functions.
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* Predict when the next frame should be started and when it will be
|
|
* turned into photons by the hardware.
|
|
*/
|
|
void (*calc_frame_timings)(struct comp_target *ct,
|
|
int64_t *out_frame_id,
|
|
uint64_t *out_wake_up_time_ns,
|
|
uint64_t *out_desired_present_time_ns,
|
|
uint64_t *out_present_slop_ns,
|
|
uint64_t *out_predicted_display_time_ns);
|
|
|
|
/*!
|
|
* The compositor tells the target a timing information about a single
|
|
* timing point on the frames lifecycle.
|
|
*/
|
|
void (*mark_timing_point)(struct comp_target *ct,
|
|
enum comp_target_timing_point point,
|
|
int64_t frame_id,
|
|
uint64_t when_ns);
|
|
|
|
/*!
|
|
* Update timing information for this target, this function should be
|
|
* lightweight and is called multiple times during a frame to make sure
|
|
* that we get the timing data as soon as possible.
|
|
*/
|
|
VkResult (*update_timings)(struct comp_target *ct);
|
|
|
|
|
|
/*
|
|
*
|
|
* Misc functions.
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* If the target can show a title (like a window) set the title.
|
|
*/
|
|
void (*set_title)(struct comp_target *ct, const char *title);
|
|
|
|
/*!
|
|
* Destroys this target.
|
|
*/
|
|
void (*destroy)(struct comp_target *ct);
|
|
};
|
|
|
|
/*!
|
|
* @copydoc comp_target::init_pre_vulkan
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline bool
|
|
comp_target_init_pre_vulkan(struct comp_target *ct)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
return ct->init_pre_vulkan(ct);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::init_post_vulkan
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline bool
|
|
comp_target_init_post_vulkan(struct comp_target *ct, uint32_t preferred_width, uint32_t preferred_height)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
return ct->init_post_vulkan(ct, preferred_width, preferred_height);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::create_images
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_create_images(struct comp_target *ct,
|
|
uint32_t preferred_width,
|
|
uint32_t preferred_height,
|
|
VkFormat preferred_color_format,
|
|
VkColorSpaceKHR preferred_color_space,
|
|
VkPresentModeKHR present_mode)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->create_images( //
|
|
ct, //
|
|
preferred_width, //
|
|
preferred_height, //
|
|
preferred_color_format, //
|
|
preferred_color_space, //
|
|
present_mode); //
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::acquire
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline VkResult
|
|
comp_target_acquire(struct comp_target *ct, VkSemaphore semaphore, uint32_t *out_index)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
return ct->acquire(ct, semaphore, out_index);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::present
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline VkResult
|
|
comp_target_present(struct comp_target *ct,
|
|
VkQueue queue,
|
|
uint32_t index,
|
|
VkSemaphore semaphore,
|
|
uint64_t desired_present_time_ns,
|
|
uint64_t present_slop_ns)
|
|
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
return ct->present( //
|
|
ct, //
|
|
queue, //
|
|
index, //
|
|
semaphore, //
|
|
desired_present_time_ns, //
|
|
present_slop_ns); //
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::flush
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_flush(struct comp_target *ct)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->flush(ct);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::calc_frame_timings
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_calc_frame_timings(struct comp_target *ct,
|
|
int64_t *out_frame_id,
|
|
uint64_t *out_wake_up_time_ns,
|
|
uint64_t *out_desired_present_time_ns,
|
|
uint64_t *out_present_slop_ns,
|
|
uint64_t *out_predicted_display_time_ns)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->calc_frame_timings( //
|
|
ct, //
|
|
out_frame_id, //
|
|
out_wake_up_time_ns, //
|
|
out_desired_present_time_ns, //
|
|
out_present_slop_ns, //
|
|
out_predicted_display_time_ns); //
|
|
}
|
|
|
|
/*!
|
|
* Quick helper for marking wake up.
|
|
* @copydoc comp_target::mark_timing_point
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_mark_wake_up(struct comp_target *ct, int64_t frame_id, uint64_t when_woke_ns)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->mark_timing_point(ct, COMP_TARGET_TIMING_POINT_WAKE_UP, frame_id, when_woke_ns);
|
|
}
|
|
|
|
/*!
|
|
* Quick helper for marking begin.
|
|
* @copydoc comp_target::mark_timing_point
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_mark_begin(struct comp_target *ct, int64_t frame_id, uint64_t when_began_ns)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->mark_timing_point(ct, COMP_TARGET_TIMING_POINT_BEGIN, frame_id, when_began_ns);
|
|
}
|
|
|
|
/*!
|
|
* Quick helper for marking submit.
|
|
* @copydoc comp_target::mark_timing_point
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_mark_submit(struct comp_target *ct, int64_t frame_id, uint64_t when_submitted_ns)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->mark_timing_point(ct, COMP_TARGET_TIMING_POINT_SUBMIT, frame_id, when_submitted_ns);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::update_timings
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline VkResult
|
|
comp_target_update_timings(struct comp_target *ct)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
return ct->update_timings(ct);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::set_title
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_set_title(struct comp_target *ct, const char *title)
|
|
{
|
|
COMP_TRACE_MARKER();
|
|
|
|
ct->set_title(ct, title);
|
|
}
|
|
|
|
/*!
|
|
* @copydoc comp_target::destroy
|
|
*
|
|
* Helper for calling through the function pointer: does a null check and sets
|
|
* ct_ptr to null if freed.
|
|
*
|
|
* @public @memberof comp_target
|
|
* @ingroup comp_main
|
|
*/
|
|
static inline void
|
|
comp_target_destroy(struct comp_target **ct_ptr)
|
|
{
|
|
struct comp_target *ct = *ct_ptr;
|
|
if (ct == NULL) {
|
|
return;
|
|
}
|
|
|
|
ct->destroy(ct);
|
|
*ct_ptr = NULL;
|
|
}
|
|
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|