mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-21 06:01:43 +00:00
c/util: Enable swapchain to be sub-classed
This commit is contained in:
parent
d578203a8e
commit
06ee685e9a
|
@ -89,14 +89,18 @@ swapchain_release_image(struct xrt_swapchain *xsc, uint32_t index)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct comp_swapchain *
|
static struct comp_swapchain *
|
||||||
alloc_and_set_funcs(struct vk_bundle *vk, struct comp_swapchain_gc *cscgc, uint32_t image_count)
|
set_common_fields(struct comp_swapchain *sc,
|
||||||
|
comp_swapchain_destroy_func_t destroy_func,
|
||||||
|
struct vk_bundle *vk,
|
||||||
|
struct comp_swapchain_gc *cscgc,
|
||||||
|
uint32_t image_count)
|
||||||
{
|
{
|
||||||
struct comp_swapchain *sc = U_TYPED_CALLOC(struct comp_swapchain);
|
|
||||||
sc->base.base.destroy = swapchain_destroy;
|
sc->base.base.destroy = swapchain_destroy;
|
||||||
sc->base.base.acquire_image = swapchain_acquire_image;
|
sc->base.base.acquire_image = swapchain_acquire_image;
|
||||||
sc->base.base.wait_image = swapchain_wait_image;
|
sc->base.base.wait_image = swapchain_wait_image;
|
||||||
sc->base.base.release_image = swapchain_release_image;
|
sc->base.base.release_image = swapchain_release_image;
|
||||||
sc->base.base.image_count = image_count;
|
sc->base.base.image_count = image_count;
|
||||||
|
sc->real_destroy = destroy_func;
|
||||||
sc->vk = vk;
|
sc->vk = vk;
|
||||||
sc->gc = cscgc;
|
sc->gc = cscgc;
|
||||||
|
|
||||||
|
@ -257,9 +261,143 @@ image_cleanup(struct vk_bundle *vk, struct comp_swapchain_image *image)
|
||||||
D(Sampler, image->repeat_sampler);
|
D(Sampler, image->repeat_sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Swapchain destruct is delayed until it is safe to destroy them, this function
|
||||||
|
* does the actual destruction and is called from @ref
|
||||||
|
* comp_swapchain_garbage_collect.
|
||||||
|
*
|
||||||
|
* @ingroup comp_util
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
really_destroy(struct comp_swapchain *sc)
|
||||||
|
{
|
||||||
|
// Re-use close function.
|
||||||
|
comp_swapchain_teardown(sc);
|
||||||
|
|
||||||
|
free(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* 'Exported' functions.
|
* 'Exported' parent-class functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
comp_swapchain_create_init(struct comp_swapchain *sc,
|
||||||
|
comp_swapchain_destroy_func_t destroy_func,
|
||||||
|
struct vk_bundle *vk,
|
||||||
|
struct comp_swapchain_gc *cscgc,
|
||||||
|
const struct xrt_swapchain_create_info *info,
|
||||||
|
const struct xrt_swapchain_create_properties *xsccp)
|
||||||
|
{
|
||||||
|
VkResult ret;
|
||||||
|
|
||||||
|
VK_DEBUG(vk, "CREATE %p %dx%d %s (%ld)", (void *)sc, //
|
||||||
|
info->width, info->height, //
|
||||||
|
vk_format_string(info->format), info->format);
|
||||||
|
|
||||||
|
if ((info->create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT) != 0) {
|
||||||
|
VK_WARN(vk,
|
||||||
|
"Swapchain info is valid but this compositor doesn't support creating protected content "
|
||||||
|
"swapchains!");
|
||||||
|
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_common_fields(sc, destroy_func, vk, cscgc, xsccp->image_count);
|
||||||
|
|
||||||
|
// Use the image helper to allocate the images.
|
||||||
|
ret = vk_ic_allocate(vk, info, xsccp->image_count, &sc->vkic);
|
||||||
|
if (ret == VK_ERROR_FEATURE_NOT_PRESENT) {
|
||||||
|
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
|
||||||
|
} else if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
|
||||||
|
return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED;
|
||||||
|
} else if (ret != VK_SUCCESS) {
|
||||||
|
return XRT_ERROR_VULKAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrt_graphics_buffer_handle_t handles[ARRAY_SIZE(sc->vkic.images)];
|
||||||
|
|
||||||
|
vk_ic_get_handles(vk, &sc->vkic, ARRAY_SIZE(handles), handles);
|
||||||
|
for (uint32_t i = 0; i < sc->vkic.image_count; i++) {
|
||||||
|
sc->base.images[i].handle = handles[i];
|
||||||
|
sc->base.images[i].size = sc->vkic.images[i].size;
|
||||||
|
sc->base.images[i].use_dedicated_allocation = sc->vkic.images[i].use_dedicated_allocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_post_create_vulkan_setup(vk, info, sc);
|
||||||
|
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrt_result_t
|
||||||
|
comp_swapchain_import_init(struct comp_swapchain *sc,
|
||||||
|
comp_swapchain_destroy_func_t destroy_func,
|
||||||
|
struct vk_bundle *vk,
|
||||||
|
struct comp_swapchain_gc *cscgc,
|
||||||
|
const struct xrt_swapchain_create_info *info,
|
||||||
|
struct xrt_image_native *native_images,
|
||||||
|
uint32_t native_image_count)
|
||||||
|
{
|
||||||
|
VkResult ret;
|
||||||
|
|
||||||
|
VK_DEBUG(vk, "IMPORT %p %dx%d %s (%ld)", (void *)sc, //
|
||||||
|
info->width, info->height, //
|
||||||
|
vk_format_string(info->format), info->format);
|
||||||
|
|
||||||
|
set_common_fields(sc, destroy_func, vk, cscgc, native_image_count);
|
||||||
|
|
||||||
|
// Use the image helper to get the images.
|
||||||
|
ret = vk_ic_from_natives(vk, info, native_images, native_image_count, &sc->vkic);
|
||||||
|
if (ret != VK_SUCCESS) {
|
||||||
|
return XRT_ERROR_VULKAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_post_create_vulkan_setup(vk, info, sc);
|
||||||
|
|
||||||
|
return XRT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
comp_swapchain_teardown(struct comp_swapchain *sc)
|
||||||
|
{
|
||||||
|
struct vk_bundle *vk = sc->vk;
|
||||||
|
|
||||||
|
VK_TRACE(vk, "REALLY DESTROY");
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sc->base.base.image_count; i++) {
|
||||||
|
image_cleanup(vk, &sc->images[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sc->base.base.image_count; i++) {
|
||||||
|
u_graphics_buffer_unref(&sc->base.images[i].handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
vk_ic_destroy(vk, &sc->vkic);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 'Exported' garbage collection functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
comp_swapchain_garbage_collect(struct comp_swapchain_gc *cscgc)
|
||||||
|
{
|
||||||
|
struct comp_swapchain *sc;
|
||||||
|
|
||||||
|
while ((sc = u_threading_stack_pop(&cscgc->destroy_swapchains))) {
|
||||||
|
sc->real_destroy(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 'Exported' default implementation.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -286,50 +424,25 @@ comp_swapchain_create(struct vk_bundle *vk,
|
||||||
const struct xrt_swapchain_create_properties *xsccp,
|
const struct xrt_swapchain_create_properties *xsccp,
|
||||||
struct xrt_swapchain **out_xsc)
|
struct xrt_swapchain **out_xsc)
|
||||||
{
|
{
|
||||||
VkResult ret;
|
struct comp_swapchain *sc = U_TYPED_CALLOC(struct comp_swapchain);
|
||||||
|
xrt_result_t xret;
|
||||||
|
|
||||||
if ((info->create & XRT_SWAPCHAIN_CREATE_PROTECTED_CONTENT) != 0) {
|
xret = comp_swapchain_create_init( //
|
||||||
VK_WARN(vk,
|
sc, //
|
||||||
"Swapchain info is valid but this compositor doesn't support creating protected content "
|
really_destroy, //
|
||||||
"swapchains!");
|
vk, //
|
||||||
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
|
cscgc, //
|
||||||
}
|
info, //
|
||||||
|
xsccp); //
|
||||||
struct comp_swapchain *sc = alloc_and_set_funcs(vk, cscgc, xsccp->image_count);
|
if (xret != XRT_SUCCESS) {
|
||||||
|
|
||||||
VK_DEBUG(vk, "CREATE %p %dx%d %s (%ld)", (void *)sc, //
|
|
||||||
info->width, info->height, //
|
|
||||||
vk_format_string(info->format), info->format);
|
|
||||||
|
|
||||||
// Use the image helper to allocate the images.
|
|
||||||
ret = vk_ic_allocate(vk, info, xsccp->image_count, &sc->vkic);
|
|
||||||
if (ret == VK_ERROR_FEATURE_NOT_PRESENT) {
|
|
||||||
free(sc);
|
free(sc);
|
||||||
return XRT_ERROR_SWAPCHAIN_FLAG_VALID_BUT_UNSUPPORTED;
|
return xret;
|
||||||
} else if (ret == VK_ERROR_FORMAT_NOT_SUPPORTED) {
|
|
||||||
free(sc);
|
|
||||||
return XRT_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED;
|
|
||||||
}
|
}
|
||||||
if (ret != VK_SUCCESS) {
|
|
||||||
free(sc);
|
|
||||||
return XRT_ERROR_VULKAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
xrt_graphics_buffer_handle_t handles[ARRAY_SIZE(sc->vkic.images)];
|
|
||||||
|
|
||||||
vk_ic_get_handles(vk, &sc->vkic, ARRAY_SIZE(handles), handles);
|
|
||||||
for (uint32_t i = 0; i < sc->vkic.image_count; i++) {
|
|
||||||
sc->base.images[i].handle = handles[i];
|
|
||||||
sc->base.images[i].size = sc->vkic.images[i].size;
|
|
||||||
sc->base.images[i].use_dedicated_allocation = sc->vkic.images[i].use_dedicated_allocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_post_create_vulkan_setup(vk, info, sc);
|
|
||||||
|
|
||||||
// Correctly setup refcounts.
|
// Correctly setup refcounts.
|
||||||
xrt_swapchain_reference(out_xsc, &sc->base.base);
|
xrt_swapchain_reference(out_xsc, &sc->base.base);
|
||||||
|
|
||||||
return XRT_SUCCESS;
|
return xret;
|
||||||
}
|
}
|
||||||
|
|
||||||
xrt_result_t
|
xrt_result_t
|
||||||
|
@ -337,64 +450,27 @@ comp_swapchain_import(struct vk_bundle *vk,
|
||||||
struct comp_swapchain_gc *cscgc,
|
struct comp_swapchain_gc *cscgc,
|
||||||
const struct xrt_swapchain_create_info *info,
|
const struct xrt_swapchain_create_info *info,
|
||||||
struct xrt_image_native *native_images,
|
struct xrt_image_native *native_images,
|
||||||
uint32_t images_count,
|
uint32_t native_image_count,
|
||||||
struct xrt_swapchain **out_xsc)
|
struct xrt_swapchain **out_xsc)
|
||||||
{
|
{
|
||||||
VkResult ret;
|
struct comp_swapchain *sc = U_TYPED_CALLOC(struct comp_swapchain);
|
||||||
|
xrt_result_t xret;
|
||||||
|
|
||||||
struct comp_swapchain *sc = alloc_and_set_funcs(vk, cscgc, images_count);
|
xret = comp_swapchain_import_init( //
|
||||||
|
sc, //
|
||||||
VK_DEBUG(vk, "IMPORT %p %dx%d %s (%ld)", (void *)sc, //
|
really_destroy, //
|
||||||
info->width, info->height, //
|
vk, //
|
||||||
vk_format_string(info->format), info->format);
|
cscgc, //
|
||||||
|
info, //
|
||||||
// Use the image helper to get the images.
|
native_images, //
|
||||||
ret = vk_ic_from_natives(vk, info, native_images, images_count, &sc->vkic);
|
native_image_count); //
|
||||||
if (ret != VK_SUCCESS) {
|
if (xret != XRT_SUCCESS) {
|
||||||
return XRT_ERROR_VULKAN;
|
free(sc);
|
||||||
|
return xret;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_post_create_vulkan_setup(vk, info, sc);
|
|
||||||
|
|
||||||
// Correctly setup refcounts.
|
// Correctly setup refcounts.
|
||||||
xrt_swapchain_reference(out_xsc, &sc->base.base);
|
xrt_swapchain_reference(out_xsc, &sc->base.base);
|
||||||
|
|
||||||
return XRT_SUCCESS;
|
return xret;
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* Swapchain destruct is delayed until it is safe to destroy them, this function
|
|
||||||
* does the actual destruction and is called from @ref
|
|
||||||
* comp_swapchain_garbage_collect.
|
|
||||||
*
|
|
||||||
* @ingroup comp_util
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
comp_swapchain_really_destroy(struct comp_swapchain *sc)
|
|
||||||
{
|
|
||||||
struct vk_bundle *vk = sc->vk;
|
|
||||||
|
|
||||||
VK_TRACE(vk, "REALLY DESTROY");
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sc->base.base.image_count; i++) {
|
|
||||||
image_cleanup(vk, &sc->images[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sc->base.base.image_count; i++) {
|
|
||||||
u_graphics_buffer_unref(&sc->base.images[i].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
vk_ic_destroy(vk, &sc->vkic);
|
|
||||||
|
|
||||||
free(sc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
comp_swapchain_garbage_collect(struct comp_swapchain_gc *cscgc)
|
|
||||||
{
|
|
||||||
struct comp_swapchain *sc;
|
|
||||||
|
|
||||||
while ((sc = u_threading_stack_pop(&cscgc->destroy_swapchains))) {
|
|
||||||
comp_swapchain_really_destroy(sc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,16 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct comp_swapchain;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Callback for implementing own destroy function, should call
|
||||||
|
* @ref comp_swapchain_teardown and is responsible for memory.
|
||||||
|
*
|
||||||
|
* @ingroup comp_util
|
||||||
|
*/
|
||||||
|
typedef void (*comp_swapchain_destroy_func_t)(struct comp_swapchain *sc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* A garbage collector that collects swapchains to be safely destroyed.
|
* A garbage collector that collects swapchains to be safely destroyed.
|
||||||
*
|
*
|
||||||
|
@ -81,6 +91,9 @@ struct comp_swapchain
|
||||||
* image, this should probably be made even smarter.
|
* image, this should probably be made even smarter.
|
||||||
*/
|
*/
|
||||||
struct u_index_fifo fifo;
|
struct u_index_fifo fifo;
|
||||||
|
|
||||||
|
//! Virtual real destroy function.
|
||||||
|
comp_swapchain_destroy_func_t real_destroy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,6 +116,52 @@ comp_swapchain(struct xrt_swapchain *xsc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* 'Exported' parent-class functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Helper to init a comp_swachain struct as if it was a create operation,
|
||||||
|
* useful for wrapping comp_swapchain within another struct. Ref-count is
|
||||||
|
* set to zero so the caller need to init it correctly.
|
||||||
|
*
|
||||||
|
* @ingroup comp_util
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
comp_swapchain_create_init(struct comp_swapchain *sc,
|
||||||
|
comp_swapchain_destroy_func_t destroy_func,
|
||||||
|
struct vk_bundle *vk,
|
||||||
|
struct comp_swapchain_gc *cscgc,
|
||||||
|
const struct xrt_swapchain_create_info *info,
|
||||||
|
const struct xrt_swapchain_create_properties *xsccp);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Helper to init a comp_swachain struct as if it was a import operation,
|
||||||
|
* useful for wrapping comp_swapchain within another struct. Ref-count is
|
||||||
|
* set to zero so the caller need to init it correctly.
|
||||||
|
*
|
||||||
|
* @ingroup comp_util
|
||||||
|
*/
|
||||||
|
xrt_result_t
|
||||||
|
comp_swapchain_import_init(struct comp_swapchain *sc,
|
||||||
|
comp_swapchain_destroy_func_t destroy_func,
|
||||||
|
struct vk_bundle *vk,
|
||||||
|
struct comp_swapchain_gc *cscgc,
|
||||||
|
const struct xrt_swapchain_create_info *info,
|
||||||
|
struct xrt_image_native *native_images,
|
||||||
|
uint32_t native_image_count);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* De-inits a comp_swapchain, usable for classes sub-classing comp_swapchain.
|
||||||
|
*
|
||||||
|
* @ingroup comp_util
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
comp_swapchain_teardown(struct comp_swapchain *sc);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* 'Exported' garbage collection functions.
|
* 'Exported' garbage collection functions.
|
||||||
|
|
Loading…
Reference in a new issue