mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-02-02 20:08:29 +00:00
c/multi: Add new multi-client helper
This commit is contained in:
parent
efdba1602f
commit
086bef8545
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2020, Collabora, Ltd.
|
||||
# Copyright 2019-2021, Collabora, Ltd.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
spirv_shaders(SHADER_HEADERS
|
||||
|
@ -38,6 +38,14 @@ set(MAIN_SOURCE_FILES
|
|||
render/comp_resources.c
|
||||
)
|
||||
|
||||
set(MULTI_SOURCE_FILES
|
||||
multi/comp_multi_compositor.c
|
||||
multi/comp_multi_interface.h
|
||||
multi/comp_multi_private.h
|
||||
multi/comp_multi_system.c
|
||||
)
|
||||
|
||||
|
||||
###
|
||||
# Client library
|
||||
#
|
||||
|
@ -96,6 +104,8 @@ endif()
|
|||
if(XRT_HAVE_OPENGL AND XRT_HAVE_XLIB)
|
||||
target_link_libraries(comp_client PRIVATE OpenGL::GLX)
|
||||
endif()
|
||||
|
||||
|
||||
##
|
||||
# Main library
|
||||
#
|
||||
|
@ -192,3 +202,17 @@ if(XRT_FEATURE_COMPOSITOR_MAIN)
|
|||
|
||||
add_subdirectory(shaders)
|
||||
endif()
|
||||
|
||||
|
||||
###
|
||||
# Multi client compositor library
|
||||
#
|
||||
|
||||
add_library(comp_multi STATIC ${MULTI_SOURCE_FILES})
|
||||
target_link_libraries(comp_multi PUBLIC xrt-interfaces PRIVATE aux_util aux_os)
|
||||
target_include_directories(comp_multi PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
|
||||
if(XRT_FEATURE_COMPOSITOR_MAIN)
|
||||
target_link_libraries(comp_main PRIVATE comp_multi)
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright 2019-2020, Collabora, Ltd.
|
||||
# Copyright 2019-2021, Collabora, Ltd.
|
||||
# SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
subdir('shaders')
|
||||
|
@ -28,6 +28,10 @@ compositor_srcs = [
|
|||
'main/comp_window.h',
|
||||
'main/comp_layer_renderer.c',
|
||||
'main/comp_layer.c',
|
||||
'multi/comp_multi_compositor.c',
|
||||
'multi/comp_multi_interface.h',
|
||||
'multi/comp_multi_private.h',
|
||||
'multi/comp_multi_system.c',
|
||||
'render/comp_buffer.c',
|
||||
'render/comp_render.h',
|
||||
'render/comp_rendering.c',
|
||||
|
|
563
src/xrt/compositor/multi/comp_multi_compositor.c
Normal file
563
src/xrt/compositor/multi/comp_multi_compositor.c
Normal file
|
@ -0,0 +1,563 @@
|
|||
// Copyright 2019-2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Multi client wrapper compositor.
|
||||
* @author Pete Black <pblack@collabora.com>
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
|
||||
#include "xrt/xrt_gfx_native.h"
|
||||
|
||||
#include "os/os_time.h"
|
||||
|
||||
#include "util/u_var.h"
|
||||
#include "util/u_misc.h"
|
||||
#include "util/u_time.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_handles.h"
|
||||
#include "util/u_trace_marker.h"
|
||||
#include "util/u_distortion_mesh.h"
|
||||
|
||||
#include "multi/comp_multi_private.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef XRT_GRAPHICS_SYNC_HANDLE_IS_FD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Slot management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
slot_clear(struct multi_layer_slot *slot)
|
||||
{
|
||||
for (size_t i = 0; i < slot->num_layers; i++) {
|
||||
for (size_t k = 0; k < ARRAY_SIZE(slot->layers[i].xscs); k++) {
|
||||
xrt_swapchain_reference(&slot->layers[i].xscs[k], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
U_ZERO(slot);
|
||||
}
|
||||
|
||||
static void
|
||||
slot_move_and_clear(struct multi_layer_slot *dst, struct multi_layer_slot *src)
|
||||
{
|
||||
slot_clear(dst);
|
||||
|
||||
// All references are kept.
|
||||
*dst = *src;
|
||||
|
||||
U_ZERO(src);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Event management functions.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
multi_compositor_push_event(struct multi_compositor *mc, const union xrt_compositor_event *xce)
|
||||
{
|
||||
struct multi_event *me = U_TYPED_CALLOC(struct multi_event);
|
||||
me->xce = *xce;
|
||||
|
||||
os_mutex_lock(&mc->event.mutex);
|
||||
|
||||
// Find the last slot.
|
||||
struct multi_event **slot = &mc->event.next;
|
||||
while (*slot != NULL) {
|
||||
slot = &(*slot)->next;
|
||||
}
|
||||
|
||||
*slot = me;
|
||||
|
||||
os_mutex_unlock(&mc->event.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
pop_event(struct multi_compositor *mc, union xrt_compositor_event *out_xce)
|
||||
{
|
||||
out_xce->type = XRT_COMPOSITOR_EVENT_NONE;
|
||||
|
||||
os_mutex_lock(&mc->event.mutex);
|
||||
|
||||
if (mc->event.next != NULL) {
|
||||
struct multi_event *me = mc->event.next;
|
||||
|
||||
*out_xce = me->xce;
|
||||
mc->event.next = me->next;
|
||||
free(me);
|
||||
}
|
||||
|
||||
os_mutex_unlock(&mc->event.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
drain_events(struct multi_compositor *mc)
|
||||
{
|
||||
union xrt_compositor_event xce;
|
||||
do {
|
||||
pop_event(mc, &xce);
|
||||
} while (xce.type != XRT_COMPOSITOR_EVENT_NONE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Compositor functions.
|
||||
*
|
||||
*/
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_create_swapchain(struct xrt_compositor *xc,
|
||||
const struct xrt_swapchain_create_info *info,
|
||||
struct xrt_swapchain **out_xsc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
return xrt_comp_create_swapchain(&mc->msc->xcn->base, info, out_xsc);
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_import_swapchain(struct xrt_compositor *xc,
|
||||
const struct xrt_swapchain_create_info *info,
|
||||
struct xrt_image_native *native_images,
|
||||
uint32_t num_images,
|
||||
struct xrt_swapchain **out_xsc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
return xrt_comp_import_swapchain(&mc->msc->xcn->base, info, native_images, num_images, out_xsc);
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_import_fence(struct xrt_compositor *xc,
|
||||
xrt_graphics_sync_handle_t handle,
|
||||
struct xrt_compositor_fence **out_xcf)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
return xrt_comp_import_fence(&mc->msc->xcn->base, handle, out_xcf);
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_begin_session(struct xrt_compositor *xc, enum xrt_view_type type)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)mc;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_end_session(struct xrt_compositor *xc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)mc;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_predict_frame(struct xrt_compositor *xc,
|
||||
int64_t *out_frame_id,
|
||||
uint64_t *out_wake_time_ns,
|
||||
uint64_t *out_predicted_gpu_time_ns,
|
||||
uint64_t *out_predicted_display_time_ns,
|
||||
uint64_t *out_predicted_display_period_ns)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
uint64_t min_display_period = 0;
|
||||
|
||||
u_rt_helper_predict( //
|
||||
&mc->urth, //
|
||||
out_frame_id, //
|
||||
out_predicted_display_time_ns, //
|
||||
out_wake_time_ns, //
|
||||
out_predicted_display_period_ns, //
|
||||
&min_display_period); //
|
||||
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_mark_frame(struct xrt_compositor *xc,
|
||||
int64_t frame_id,
|
||||
enum xrt_compositor_frame_point point,
|
||||
uint64_t when_ns)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
switch (point) {
|
||||
case XRT_COMPOSITOR_FRAME_POINT_WOKE:
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
u_rt_helper_mark_wait_woke(&mc->urth, frame_id);
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
break;
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_wait_frame(struct xrt_compositor *xc,
|
||||
int64_t *out_frame_id,
|
||||
uint64_t *predicted_display_time,
|
||||
uint64_t *predicted_display_period)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)mc;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_begin_frame(struct xrt_compositor *xc, int64_t frame_id)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
u_rt_helper_mark_begin(&mc->urth, frame_id);
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_discard_frame(struct xrt_compositor *xc, int64_t frame_id)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
u_rt_helper_mark_discarded(&mc->urth, frame_id);
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_begin(struct xrt_compositor *xc,
|
||||
int64_t frame_id,
|
||||
uint64_t display_time_ns,
|
||||
enum xrt_blend_mode env_blend_mode)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
assert(mc->progress.num_layers == 0);
|
||||
U_ZERO(&mc->progress);
|
||||
|
||||
mc->progress.display_time_ns = display_time_ns;
|
||||
mc->progress.env_blend_mode = env_blend_mode;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_stereo_projection(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *l_xsc,
|
||||
struct xrt_swapchain *r_xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)mc;
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], l_xsc);
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[1], r_xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_stereo_projection_depth(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *l_xsc,
|
||||
struct xrt_swapchain *r_xsc,
|
||||
struct xrt_swapchain *l_d_xsc,
|
||||
struct xrt_swapchain *r_d_xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], l_xsc);
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[1], r_xsc);
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[2], l_d_xsc);
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[3], r_d_xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_quad(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_cube(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_cylinder(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_equirect1(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_equirect2(struct xrt_compositor *xc,
|
||||
struct xrt_device *xdev,
|
||||
struct xrt_swapchain *xsc,
|
||||
const struct xrt_layer_data *data)
|
||||
{
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
size_t index = mc->progress.num_layers++;
|
||||
mc->progress.layers[index].xdev = xdev;
|
||||
xrt_swapchain_reference(&mc->progress.layers[index].xscs[0], xsc);
|
||||
mc->progress.layers[index].data = *data;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_layer_commit(struct xrt_compositor *xc, int64_t frame_id, xrt_graphics_sync_handle_t sync_handle)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
struct xrt_compositor_fence *xcf = NULL;
|
||||
|
||||
do {
|
||||
if (!xrt_graphics_sync_handle_is_valid(sync_handle)) {
|
||||
break;
|
||||
}
|
||||
|
||||
xrt_result_t xret = xrt_comp_import_fence( //
|
||||
&mc->msc->xcn->base, //
|
||||
sync_handle, //
|
||||
&xcf); //
|
||||
/*!
|
||||
* If import_fence succeeded, we have transferred ownership to
|
||||
* the compositor no need to do anything more. If the call
|
||||
* failed we need to close the handle.
|
||||
*/
|
||||
if (xret == XRT_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
u_graphics_sync_unref(&sync_handle);
|
||||
} while (false); // Goto without the labels.
|
||||
|
||||
if (xcf != NULL) {
|
||||
xrt_compositor_fence_wait(xcf, UINT64_MAX);
|
||||
xrt_compositor_fence_destroy(&xcf);
|
||||
}
|
||||
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
slot_move_and_clear(&mc->delivered, &mc->progress);
|
||||
|
||||
u_rt_helper_mark_delivered(&mc->urth, frame_id);
|
||||
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
multi_compositor_poll_events(struct xrt_compositor *xc, union xrt_compositor_event *out_xce)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
pop_event(mc, out_xce);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
multi_compositor_destroy(struct xrt_compositor *xc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
|
||||
os_mutex_lock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
// Remove it from the list of clients.
|
||||
for (size_t i = 0; i < MULTI_MAX_CLIENTS; i++) {
|
||||
if (mc->msc->clients[i] == mc) {
|
||||
mc->msc->clients[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
os_mutex_unlock(&mc->msc->list_and_timing_lock);
|
||||
|
||||
drain_events(mc);
|
||||
|
||||
// We are now off the rendering list, clear slots for any swapchains.
|
||||
slot_clear(&mc->progress);
|
||||
slot_clear(&mc->delivered);
|
||||
|
||||
free(mc);
|
||||
}
|
||||
|
||||
xrt_result_t
|
||||
multi_compositor_create(struct multi_system_compositor *msc,
|
||||
const struct xrt_session_info *xsi,
|
||||
struct xrt_compositor_native **out_xcn)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct multi_compositor *mc = U_TYPED_CALLOC(struct multi_compositor);
|
||||
|
||||
mc->base.base.create_swapchain = multi_compositor_create_swapchain;
|
||||
mc->base.base.import_swapchain = multi_compositor_import_swapchain;
|
||||
mc->base.base.import_fence = multi_compositor_import_fence;
|
||||
mc->base.base.begin_session = multi_compositor_begin_session;
|
||||
mc->base.base.end_session = multi_compositor_end_session;
|
||||
mc->base.base.predict_frame = multi_compositor_predict_frame;
|
||||
mc->base.base.mark_frame = multi_compositor_mark_frame;
|
||||
mc->base.base.wait_frame = multi_compositor_wait_frame;
|
||||
mc->base.base.begin_frame = multi_compositor_begin_frame;
|
||||
mc->base.base.discard_frame = multi_compositor_discard_frame;
|
||||
mc->base.base.layer_begin = multi_compositor_layer_begin;
|
||||
mc->base.base.layer_stereo_projection = multi_compositor_layer_stereo_projection;
|
||||
mc->base.base.layer_stereo_projection_depth = multi_compositor_layer_stereo_projection_depth;
|
||||
mc->base.base.layer_quad = multi_compositor_layer_quad;
|
||||
mc->base.base.layer_cube = multi_compositor_layer_cube;
|
||||
mc->base.base.layer_cylinder = multi_compositor_layer_cylinder;
|
||||
mc->base.base.layer_equirect1 = multi_compositor_layer_equirect1;
|
||||
mc->base.base.layer_equirect2 = multi_compositor_layer_equirect2;
|
||||
mc->base.base.layer_commit = multi_compositor_layer_commit;
|
||||
mc->base.base.destroy = multi_compositor_destroy;
|
||||
mc->base.base.poll_events = multi_compositor_poll_events;
|
||||
mc->msc = msc;
|
||||
mc->xsi = *xsi;
|
||||
|
||||
// Passthrough our formats from the native compositor to the client.
|
||||
mc->base.base.info = msc->xcn->base.info;
|
||||
|
||||
// This is safe to do without a lock since we are not on the list yet.
|
||||
u_rt_helper_init(&mc->urth);
|
||||
u_rt_helper_client_clear(&mc->urth);
|
||||
|
||||
os_mutex_lock(&msc->list_and_timing_lock);
|
||||
|
||||
// Meh if we have to many clients just ignore it.
|
||||
for (size_t i = 0; i < MULTI_MAX_CLIENTS; i++) {
|
||||
if (mc->msc->clients[i] != NULL) {
|
||||
continue;
|
||||
}
|
||||
mc->msc->clients[i] = mc;
|
||||
break;
|
||||
}
|
||||
|
||||
u_rt_helper_new_sample( //
|
||||
&mc->urth, //
|
||||
msc->last_timings.predicted_display_time_ns, //
|
||||
msc->last_timings.predicted_display_period_ns, //
|
||||
msc->last_timings.diff_ns); //
|
||||
|
||||
os_mutex_unlock(&msc->list_and_timing_lock);
|
||||
|
||||
*out_xcn = &mc->base;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
28
src/xrt/compositor/multi/comp_multi_interface.h
Normal file
28
src/xrt/compositor/multi/comp_multi_interface.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Interface for the multi-client layer code.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup comp_main
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_compositor.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
xrt_result_t
|
||||
comp_multi_create_system_compositor(struct xrt_compositor_native *xcn,
|
||||
const struct xrt_system_compositor_info *xsci,
|
||||
struct xrt_system_compositor **out_xsysc);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
204
src/xrt/compositor/multi/comp_multi_private.h
Normal file
204
src/xrt/compositor/multi/comp_multi_private.h
Normal file
|
@ -0,0 +1,204 @@
|
|||
// Copyright 2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Multi-client compositor internal structs.
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xrt/xrt_compiler.h"
|
||||
#include "xrt/xrt_defines.h"
|
||||
#include "xrt/xrt_compositor.h"
|
||||
|
||||
#include "os/os_time.h"
|
||||
#include "os/os_threading.h"
|
||||
|
||||
#include "util/u_timing_render.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define MULTI_MAX_CLIENTS 64
|
||||
#define MULTI_MAX_LAYERS 16
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Native compositor.
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Data for a single composition layer.
|
||||
*
|
||||
* Similar in function to @ref comp_layer
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
struct multi_layer_entry
|
||||
{
|
||||
/*!
|
||||
* Device to get pose from.
|
||||
*/
|
||||
struct xrt_device *xdev;
|
||||
|
||||
/*!
|
||||
* Pointers to swapchains.
|
||||
*
|
||||
* How many are actually used depends on the value of @p data.type
|
||||
*/
|
||||
struct xrt_swapchain *xscs[4];
|
||||
|
||||
/*!
|
||||
* All basic (trivially-serializable) data associated with a layer,
|
||||
* aside from which swapchain(s) are used.
|
||||
*/
|
||||
struct xrt_layer_data data;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Render state for a single client, including all layers.
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
struct multi_layer_slot
|
||||
{
|
||||
uint64_t display_time_ns; //!< When should this be shown, @see XrFrameEndInfo::displayTime.
|
||||
enum xrt_blend_mode env_blend_mode;
|
||||
uint32_t num_layers;
|
||||
struct multi_layer_entry layers[MULTI_MAX_LAYERS];
|
||||
};
|
||||
|
||||
/*!
|
||||
* Render state for a single client, including all layers.
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
struct multi_event
|
||||
{
|
||||
struct multi_event *next;
|
||||
union xrt_compositor_event xce;
|
||||
};
|
||||
|
||||
/*!
|
||||
* A single compositor.
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
struct multi_compositor
|
||||
{
|
||||
struct xrt_compositor_native base;
|
||||
|
||||
// Client info.
|
||||
struct xrt_session_info xsi;
|
||||
|
||||
//! Owning system compositor.
|
||||
struct multi_system_compositor *msc;
|
||||
|
||||
struct
|
||||
{
|
||||
struct os_mutex mutex;
|
||||
struct multi_event *next;
|
||||
} event;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool visible;
|
||||
bool focused;
|
||||
} sent;
|
||||
struct
|
||||
{
|
||||
bool visible;
|
||||
bool focused;
|
||||
} current;
|
||||
|
||||
int64_t z_order;
|
||||
} state;
|
||||
|
||||
//! Currently being transferred or waited on.
|
||||
struct multi_layer_slot progress;
|
||||
|
||||
//! Fully ready to be used.
|
||||
struct multi_layer_slot delivered;
|
||||
|
||||
struct u_rt_helper urth;
|
||||
};
|
||||
|
||||
static inline struct multi_compositor *
|
||||
multi_compositor(struct xrt_compositor *xc)
|
||||
{
|
||||
return (struct multi_compositor *)xc;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Create a multi client wrapper compositor.
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
xrt_result_t
|
||||
multi_compositor_create(struct multi_system_compositor *msc,
|
||||
const struct xrt_session_info *xsi,
|
||||
struct xrt_compositor_native **out_xcn);
|
||||
|
||||
/*!
|
||||
* Push a event to be delivered to the client.
|
||||
*
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
void
|
||||
multi_compositor_push_event(struct multi_compositor *mc, const union xrt_compositor_event *xce);
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* System compositor.
|
||||
*
|
||||
*/
|
||||
|
||||
struct multi_system_compositor
|
||||
{
|
||||
struct xrt_system_compositor base;
|
||||
|
||||
//! Extra functions to handle multi client.
|
||||
struct xrt_multi_compositor_control xmcc;
|
||||
|
||||
//! Real native compositor.
|
||||
struct xrt_compositor_native *xcn;
|
||||
|
||||
//! Render loop thread.
|
||||
struct os_thread_helper oth;
|
||||
|
||||
/*!
|
||||
* This mutex protects the list of client compositor
|
||||
* and the rendering timings on it.
|
||||
*/
|
||||
struct os_mutex list_and_timing_lock;
|
||||
|
||||
struct
|
||||
{
|
||||
uint64_t predicted_display_time_ns;
|
||||
uint64_t predicted_display_period_ns;
|
||||
uint64_t diff_ns;
|
||||
} last_timings;
|
||||
|
||||
struct multi_compositor *clients[MULTI_MAX_CLIENTS];
|
||||
};
|
||||
|
||||
static inline struct multi_system_compositor *
|
||||
multi_system_compositor(struct xrt_system_compositor *xsc)
|
||||
{
|
||||
return (struct multi_system_compositor *)xsc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
463
src/xrt/compositor/multi/comp_multi_system.c
Normal file
463
src/xrt/compositor/multi/comp_multi_system.c
Normal file
|
@ -0,0 +1,463 @@
|
|||
// Copyright 2019-2021, Collabora, Ltd.
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
/*!
|
||||
* @file
|
||||
* @brief Multi client wrapper compositor.
|
||||
* @author Pete Black <pblack@collabora.com>
|
||||
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||
* @ingroup comp_multi
|
||||
*/
|
||||
|
||||
#include "xrt/xrt_gfx_native.h"
|
||||
|
||||
#include "os/os_time.h"
|
||||
|
||||
#include "util/u_var.h"
|
||||
#include "util/u_misc.h"
|
||||
#include "util/u_time.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "util/u_trace_marker.h"
|
||||
#include "util/u_distortion_mesh.h"
|
||||
|
||||
#include "multi/comp_multi_private.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef XRT_GRAPHICS_SYNC_HANDLE_IS_FD
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Render thread.
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
do_projection_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = layer->xdev;
|
||||
struct xrt_swapchain *l_xcs = layer->xscs[0];
|
||||
struct xrt_swapchain *r_xcs = layer->xscs[1];
|
||||
|
||||
if (l_xcs == NULL || r_xcs == NULL) {
|
||||
U_LOG_E("Invalid swap chain for projection layer #%u!", i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xdev == NULL) {
|
||||
U_LOG_E("Invalid xdev for projection layer #%u!", i);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cast away
|
||||
struct xrt_layer_data *data = (struct xrt_layer_data *)&layer->data;
|
||||
|
||||
xrt_comp_layer_stereo_projection(xc, xdev, l_xcs, r_xcs, data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_projection_layer_depth(struct xrt_compositor *xc,
|
||||
struct multi_compositor *mc,
|
||||
struct multi_layer_entry *layer,
|
||||
uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = layer->xdev;
|
||||
struct xrt_swapchain *l_xcs = layer->xscs[0];
|
||||
struct xrt_swapchain *r_xcs = layer->xscs[1];
|
||||
struct xrt_swapchain *l_d_xcs = layer->xscs[2];
|
||||
struct xrt_swapchain *r_d_xcs = layer->xscs[2];
|
||||
|
||||
if (l_xcs == NULL || r_xcs == NULL || l_d_xcs == NULL || r_d_xcs == NULL) {
|
||||
U_LOG_E("Invalid swap chain for projection layer #%u!", i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xdev == NULL) {
|
||||
U_LOG_E("Invalid xdev for projection layer #%u!", i);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cast away
|
||||
struct xrt_layer_data *data = (struct xrt_layer_data *)&layer->data;
|
||||
|
||||
xrt_comp_layer_stereo_projection_depth(xc, xdev, l_xcs, r_xcs, l_d_xcs, r_d_xcs, data);
|
||||
}
|
||||
|
||||
static bool
|
||||
do_single(struct xrt_compositor *xc,
|
||||
struct multi_compositor *mc,
|
||||
struct multi_layer_entry *layer,
|
||||
uint32_t i,
|
||||
const char *name,
|
||||
struct xrt_device **out_xdev,
|
||||
struct xrt_swapchain **out_xcs,
|
||||
struct xrt_layer_data **out_data)
|
||||
{
|
||||
struct xrt_device *xdev = layer->xdev;
|
||||
struct xrt_swapchain *xcs = layer->xscs[0];
|
||||
|
||||
if (xcs == NULL) {
|
||||
U_LOG_E("Invalid swapchain for layer #%u '%s'!", i, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xdev == NULL) {
|
||||
U_LOG_E("Invalid xdev for layer #%u '%s'!", i, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cast away
|
||||
struct xrt_layer_data *data = (struct xrt_layer_data *)&layer->data;
|
||||
|
||||
*out_xdev = xdev;
|
||||
*out_xcs = xcs;
|
||||
*out_data = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
do_quad_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = NULL;
|
||||
struct xrt_swapchain *xcs = NULL;
|
||||
struct xrt_layer_data *data = NULL;
|
||||
|
||||
if (!do_single(xc, mc, layer, i, "quad", &xdev, &xcs, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xrt_comp_layer_quad(xc, xdev, xcs, data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_cube_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = NULL;
|
||||
struct xrt_swapchain *xcs = NULL;
|
||||
struct xrt_layer_data *data = NULL;
|
||||
|
||||
if (!do_single(xc, mc, layer, i, "cube", &xdev, &xcs, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xrt_comp_layer_cube(xc, xdev, xcs, data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_cylinder_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = NULL;
|
||||
struct xrt_swapchain *xcs = NULL;
|
||||
struct xrt_layer_data *data = NULL;
|
||||
|
||||
if (!do_single(xc, mc, layer, i, "cylinder", &xdev, &xcs, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xrt_comp_layer_cylinder(xc, xdev, xcs, data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_equirect1_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = NULL;
|
||||
struct xrt_swapchain *xcs = NULL;
|
||||
struct xrt_layer_data *data = NULL;
|
||||
|
||||
if (!do_single(xc, mc, layer, i, "equirect1", &xdev, &xcs, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xrt_comp_layer_equirect1(xc, xdev, xcs, data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_equirect2_layer(struct xrt_compositor *xc, struct multi_compositor *mc, struct multi_layer_entry *layer, uint32_t i)
|
||||
{
|
||||
struct xrt_device *xdev = NULL;
|
||||
struct xrt_swapchain *xcs = NULL;
|
||||
struct xrt_layer_data *data = NULL;
|
||||
|
||||
if (!do_single(xc, mc, layer, i, "equirect2", &xdev, &xcs, &data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
xrt_comp_layer_equirect2(xc, xdev, xcs, data);
|
||||
}
|
||||
|
||||
static int
|
||||
overlay_sort_func(const void *a, const void *b)
|
||||
{
|
||||
struct multi_compositor *mc_a = *(struct multi_compositor **)a;
|
||||
struct multi_compositor *mc_b = *(struct multi_compositor **)b;
|
||||
|
||||
if (mc_a->state.z_order < mc_b->state.z_order) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mc_a->state.z_order > mc_b->state.z_order) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
transfer_layers_locked(struct multi_system_compositor *msc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct xrt_compositor *xc = &msc->xcn->base;
|
||||
|
||||
struct multi_compositor *array[MULTI_MAX_CLIENTS] = {0};
|
||||
|
||||
size_t count = 0;
|
||||
for (size_t k = 0; k < ARRAY_SIZE(array); k++) {
|
||||
if (msc->clients[k] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
array[count++] = msc->clients[k];
|
||||
}
|
||||
|
||||
// Sort the stack array
|
||||
qsort(array, count, sizeof(struct multi_compositor *), overlay_sort_func);
|
||||
|
||||
for (size_t k = 0; k < count; k++) {
|
||||
struct multi_compositor *mc = array[k];
|
||||
|
||||
if (mc == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mc->delivered.num_layers; i++) {
|
||||
struct multi_layer_entry *layer = &mc->delivered.layers[i];
|
||||
|
||||
switch (layer->data.type) {
|
||||
case XRT_LAYER_STEREO_PROJECTION: do_projection_layer(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_STEREO_PROJECTION_DEPTH: do_projection_layer_depth(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_QUAD: do_quad_layer(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_CUBE: do_cube_layer(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_CYLINDER: do_cylinder_layer(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_EQUIRECT1: do_equirect1_layer(xc, mc, layer, i); break;
|
||||
case XRT_LAYER_EQUIRECT2: do_equirect2_layer(xc, mc, layer, i); break;
|
||||
default: U_LOG_E("Unhandled layer type '%i'!", layer->data.type); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_timings(struct multi_system_compositor *msc,
|
||||
uint64_t predicted_display_time_ns,
|
||||
uint64_t predicted_display_period_ns,
|
||||
uint64_t diff_ns)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
os_mutex_lock(&msc->list_and_timing_lock);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(msc->clients); i++) {
|
||||
struct multi_compositor *mc = msc->clients[i];
|
||||
if (mc == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
u_rt_helper_new_sample( //
|
||||
&mc->urth, //
|
||||
predicted_display_time_ns, //
|
||||
predicted_display_period_ns, //
|
||||
diff_ns); //
|
||||
}
|
||||
|
||||
msc->last_timings.predicted_display_time_ns = predicted_display_time_ns;
|
||||
msc->last_timings.predicted_display_period_ns = predicted_display_period_ns;
|
||||
msc->last_timings.diff_ns = diff_ns;
|
||||
|
||||
os_mutex_unlock(&msc->list_and_timing_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
multi_main_loop(struct multi_system_compositor *msc)
|
||||
{
|
||||
COMP_TRACE_MARKER();
|
||||
|
||||
struct xrt_compositor *xc = &msc->xcn->base;
|
||||
|
||||
//! @todo Don't make this a hack.
|
||||
enum xrt_view_type view_type = XRT_VIEW_TYPE_STEREO;
|
||||
|
||||
xrt_comp_begin_session(xc, view_type);
|
||||
|
||||
os_thread_helper_lock(&msc->oth);
|
||||
while (os_thread_helper_is_running_locked(&msc->oth)) {
|
||||
os_thread_helper_unlock(&msc->oth);
|
||||
|
||||
int64_t frame_id;
|
||||
uint64_t predicted_display_time_ns;
|
||||
uint64_t predicted_display_period_ns;
|
||||
|
||||
xrt_comp_wait_frame(xc, &frame_id, &predicted_display_time_ns, &predicted_display_period_ns);
|
||||
|
||||
uint64_t now_ns = os_monotonic_get_ns();
|
||||
uint64_t diff_ns = predicted_display_time_ns - now_ns;
|
||||
|
||||
broadcast_timings(msc, predicted_display_time_ns, predicted_display_period_ns, diff_ns);
|
||||
|
||||
// Make sure that the clients doesn't go away.
|
||||
os_mutex_lock(&msc->list_and_timing_lock);
|
||||
|
||||
xrt_comp_begin_frame(xc, frame_id);
|
||||
xrt_comp_layer_begin(xc, frame_id, 0, 0);
|
||||
|
||||
transfer_layers_locked(msc);
|
||||
|
||||
xrt_comp_layer_commit(xc, frame_id, XRT_GRAPHICS_SYNC_HANDLE_INVALID);
|
||||
|
||||
os_mutex_unlock(&msc->list_and_timing_lock);
|
||||
|
||||
// Re-lock the thread for check in while statement.
|
||||
os_thread_helper_lock(&msc->oth);
|
||||
}
|
||||
|
||||
xrt_comp_end_session(xc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
thread_func(void *ptr)
|
||||
{
|
||||
return (void *)(intptr_t)multi_main_loop((struct multi_system_compositor *)ptr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* System multi compositor functions.
|
||||
*
|
||||
*/
|
||||
|
||||
static xrt_result_t
|
||||
system_compositor_set_state(struct xrt_system_compositor *xsc, struct xrt_compositor *xc, bool visible, bool focused)
|
||||
{
|
||||
struct multi_system_compositor *msc = multi_system_compositor(xsc);
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)msc;
|
||||
|
||||
//! @todo Locking?
|
||||
if (mc->state.sent.visible != visible || mc->state.sent.focused != focused) {
|
||||
mc->state.sent.visible = visible;
|
||||
mc->state.sent.focused = focused;
|
||||
|
||||
union xrt_compositor_event xce = {0};
|
||||
xce.type = XRT_COMPOSITOR_EVENT_STATE_CHANGE;
|
||||
xce.state.visible = visible;
|
||||
xce.state.focused = focused;
|
||||
|
||||
multi_compositor_push_event(mc, &xce);
|
||||
}
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
system_compositor_set_z_order(struct xrt_system_compositor *xsc, struct xrt_compositor *xc, int64_t z_order)
|
||||
{
|
||||
struct multi_system_compositor *msc = multi_system_compositor(xsc);
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)msc;
|
||||
|
||||
//! @todo Locking?
|
||||
mc->state.z_order = z_order;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
static xrt_result_t
|
||||
system_compositor_set_main_app_visibility(struct xrt_system_compositor *xsc, struct xrt_compositor *xc, bool visible)
|
||||
{
|
||||
struct multi_system_compositor *msc = multi_system_compositor(xsc);
|
||||
struct multi_compositor *mc = multi_compositor(xc);
|
||||
(void)msc;
|
||||
|
||||
union xrt_compositor_event xce = {0};
|
||||
xce.type = XRT_COMPOSITOR_EVENT_OVERLAY_CHANGE;
|
||||
xce.overlay.visible = visible;
|
||||
|
||||
multi_compositor_push_event(mc, &xce);
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* System compositor functions.
|
||||
*
|
||||
*/
|
||||
|
||||
static xrt_result_t
|
||||
system_compositor_create_native_compositor(struct xrt_system_compositor *xsc,
|
||||
const struct xrt_session_info *xsi,
|
||||
struct xrt_compositor_native **out_xcn)
|
||||
{
|
||||
struct multi_system_compositor *msc = multi_system_compositor(xsc);
|
||||
|
||||
return multi_compositor_create(msc, xsi, out_xcn);
|
||||
}
|
||||
|
||||
static void
|
||||
system_compositor_destroy(struct xrt_system_compositor *xsc)
|
||||
{
|
||||
struct multi_system_compositor *msc = multi_system_compositor(xsc);
|
||||
|
||||
// Stop the render thread first.
|
||||
os_thread_helper_stop(&msc->oth);
|
||||
|
||||
xrt_comp_native_destroy(&msc->xcn);
|
||||
|
||||
free(msc);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* 'Exported' functions.
|
||||
*
|
||||
*/
|
||||
|
||||
xrt_result_t
|
||||
comp_multi_create_system_compositor(struct xrt_compositor_native *xcn,
|
||||
const struct xrt_system_compositor_info *xsci,
|
||||
struct xrt_system_compositor **out_xsysc)
|
||||
{
|
||||
struct multi_system_compositor *msc = U_TYPED_CALLOC(struct multi_system_compositor);
|
||||
msc->base.create_native_compositor = system_compositor_create_native_compositor;
|
||||
msc->base.destroy = system_compositor_destroy;
|
||||
msc->xmcc.set_state = system_compositor_set_state;
|
||||
msc->xmcc.set_z_order = system_compositor_set_z_order;
|
||||
msc->xmcc.set_main_app_visibility = system_compositor_set_main_app_visibility;
|
||||
msc->base.xmcc = &msc->xmcc;
|
||||
msc->base.info = *xsci;
|
||||
msc->xcn = xcn;
|
||||
|
||||
int ret = os_thread_helper_init(&msc->oth);
|
||||
if (ret < 0) {
|
||||
return XRT_ERROR_THREADING_INIT_FAILURE;
|
||||
}
|
||||
|
||||
os_thread_helper_start(&msc->oth, thread_func, msc);
|
||||
|
||||
*out_xsysc = &msc->base;
|
||||
|
||||
return XRT_SUCCESS;
|
||||
}
|
Loading…
Reference in a new issue