Skip to content
Commits on Source (10)
......@@ -88,6 +88,8 @@ struct wet_layoutput;
struct wet_head_tracker {
struct wl_listener head_destroy_listener;
struct wl_listener resized_listener;
struct wet_compositor *wet;
};
/** User data for each weston_output */
......@@ -151,6 +153,7 @@ struct wet_compositor {
bool use_color_manager;
bool drm_backend_loaded;
struct wl_listener screenshot_auth;
struct wl_listener output_created_listener;
enum require_outputs require_outputs;
};
......@@ -774,7 +777,7 @@ usage(int error_code)
" --external-listener-fd=FD\tUse socket as listener connection\n"
" --address=ADDR\tThe address to bind\n"
" --port=PORT\t\tThe port to listen on\n"
" --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
" --no-resizeable\tThe RDP peers will be forced to the size of the desktop\n"
" --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
" --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
" --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
......@@ -1681,6 +1684,135 @@ allow_content_protection(struct weston_output *output,
weston_output_allow_protection(output, allow_hdcp);
}
static int
wet_config_find_output_mirror(struct weston_output *output,
struct wet_compositor *wet,
char **mirror_key_value,
char **mirror_output_name,
struct weston_config_section **section)
{
const char *section_name;
int ret = 0;
while (weston_config_next_section(wet->config, section, &section_name)) {
char *output_name = NULL;
char *mirror_of_key = NULL;
/* ignore sections we're not interested in */
if (strcmp(section_name, "output"))
continue;
weston_config_section_get_string(*section, "mirror-of",
&mirror_of_key, NULL);
/* ignore outputs which do not have the mirror of key */
if (!mirror_of_key)
continue;
*mirror_key_value = mirror_of_key;
weston_config_section_get_string(*section, "name",
&output_name, NULL);
if (output_name) {
*mirror_output_name = output_name;
goto out;
}
free(output_name);
}
ret = -1;
out:
return ret;
}
static struct weston_head *
wet_head_find_by_name(struct wet_compositor *wet, const char *name)
{
struct weston_head *it = NULL;
struct weston_head *head_found = NULL;
while ((it = weston_compositor_iterate_heads(wet->compositor, it))) {
if (!strcmp(it->name, name)) {
head_found = it;
break;
}
}
return head_found;
}
static struct wet_backend *
wet_get_backend_from_head(struct wet_compositor *wet, struct weston_head *head)
{
struct wet_backend *b = NULL;
wl_list_for_each(b, &wet->backend_list, compositor_link)
if (b->backend == head->backend)
return b;
return NULL;
}
static struct weston_head *
wet_config_find_head_to_mirror(struct weston_output *output,
struct wet_compositor *wet)
{
struct weston_head *head = NULL;
struct weston_config_section *section = NULL;
do {
char *mof_name = NULL;
char *remote_output_name = NULL;
/* do we have a mirror-of key at all? */
if (wet_config_find_output_mirror(output, wet, &mof_name,
&remote_output_name,
&section))
break;
assert(mof_name);
/* do we have a matching output between signal event and the
* output to mirror ? */
if (strcmp(mof_name, output->name)) {
free(mof_name);
free(remote_output_name);
continue;
}
/* grab the output name of this 'remote_output_name' */
head = wet_head_find_by_name(wet, remote_output_name);
free(mof_name);
free(remote_output_name);
} while (!head);
return head;
}
static bool
wet_config_head_has_mirror_of_entry(struct wet_compositor *wet, char *head_name)
{
struct weston_config_section *section;
section = weston_config_get_section(wet->config, "output", "name", head_name);
if (section) {
char *mirror_of_key;
weston_config_section_get_string(section, "mirror-of",
&mirror_of_key, NULL);
if (mirror_of_key) {
free(mirror_of_key);
return true;
}
}
return false;
}
static void
parse_simple_mode(struct weston_output *output,
struct weston_config_section *section, int *width,
......@@ -1775,6 +1907,9 @@ static void
wet_head_tracker_destroy(struct wet_head_tracker *track)
{
wl_list_remove(&track->head_destroy_listener.link);
if (track->resized_listener.notify)
wl_list_remove(&track->resized_listener.link);
free(track);
}
......@@ -1869,11 +2004,26 @@ weston_output_lazy_align(struct weston_output *output)
static void
simple_head_enable(struct wet_compositor *wet, struct wet_backend *wb,
struct weston_head *head)
struct weston_head *head, struct weston_head *head_to_mirror,
wet_head_additional_setup wet_head_pre_enable,
wet_head_additional_setup wet_head_post_enable)
{
struct weston_output *output;
enum weston_compositor_backend backend_type;
int ret = 0;
backend_type = weston_get_backend_type(head->backend);
/* remote type of outputs: RDP/VNC/PipeWire that mirror out
* a native one will be handled automatically with the help
* of compositor outputs signals */
if ((backend_type == WESTON_BACKEND_RDP ||
backend_type == WESTON_BACKEND_VNC ||
backend_type == WESTON_BACKEND_PIPEWIRE) &&
wet_config_head_has_mirror_of_entry(wet, head->name) &&
!head_to_mirror)
return;
output = weston_compositor_create_output(wet->compositor, head,
head->name);
if (!output) {
......@@ -1884,7 +2034,10 @@ simple_head_enable(struct wet_compositor *wet, struct wet_backend *wb,
return;
}
weston_output_lazy_align(output);
if (wet_head_pre_enable && head_to_mirror)
wet_head_pre_enable(head, head_to_mirror);
else
weston_output_lazy_align(output);
if (wb->simple_output_configure)
ret = wb->simple_output_configure(output);
......@@ -1906,6 +2059,9 @@ simple_head_enable(struct wet_compositor *wet, struct wet_backend *wb,
return;
}
if (wet_head_post_enable && head)
wet_head_post_enable(head, head_to_mirror);
wet_head_tracker_create(wet, head);
/* The weston_compositor will track and destroy the output on exit. */
......@@ -1958,7 +2114,7 @@ simple_heads_changed(struct wl_listener *listener, void *arg)
non_desktop = weston_head_is_non_desktop(head);
if (connected && !enabled && !non_desktop) {
simple_head_enable(wet, wb, head);
simple_head_enable(wet, wb, head, NULL, NULL, NULL);
} else if (!connected && enabled) {
simple_head_disable(head);
} else if (enabled && changed) {
......@@ -2271,8 +2427,8 @@ drm_backend_output_configure(struct weston_output *output,
/* Find the output section to use for configuring the output with the
* named head. If an output section with the given name contains
* a "same-as" key, ignore all other settings in the output section and
* instead find an output section named by the "same-as". Do this
* a "clone-of" key, ignore all other settings in the output section and
* instead find an output section named by the "clone-of". Do this
* recursively.
*/
static struct weston_config_section *
......@@ -2280,33 +2436,33 @@ drm_config_find_controlling_output_section(struct weston_config *config,
const char *head_name)
{
struct weston_config_section *section;
char *same_as;
char *clone_of;
int depth = 0;
same_as = strdup(head_name);
clone_of = strdup(head_name);
do {
section = weston_config_get_section(config, "output",
"name", same_as);
"name", clone_of);
if (!section && depth > 0)
weston_log("Configuration error: "
"output section referred to with "
"'same-as=%s' not found.\n", same_as);
"'clone-of=%s' not found.\n", clone_of);
free(same_as);
free(clone_of);
if (!section)
return NULL;
if (++depth > 10) {
weston_log("Configuration error: "
"'same-as' nested too deep for output '%s'.\n",
"'clone-of' nested too deep for output '%s'.\n",
head_name);
return NULL;
}
weston_config_section_get_string(section, "same-as",
&same_as, NULL);
} while (same_as);
weston_config_section_get_string(section, "clone-of",
&clone_of, NULL);
} while (clone_of);
return section;
}
......@@ -2352,14 +2508,139 @@ static void
wet_output_handle_destroy(struct wl_listener *listener, void *data)
{
struct wet_output *output;
struct wet_compositor *wet;
struct weston_head *head = NULL;
output = wl_container_of(listener, output, output_destroy_listener);
assert(output->output == data);
wet = output->layoutput->compositor;
head = wet_config_find_head_to_mirror(output->output, wet);
if (head && !wet->compositor->shutting_down) {
simple_head_disable(head);
}
output->output = NULL;
wl_list_remove(&output->output_destroy_listener.link);
}
static void
wet_output_overlap_pre_enable(struct weston_head *head,
struct weston_head *head_to_mirror)
{
head->output->mirror_of = head_to_mirror->output;
weston_output_set_position(head->output, head_to_mirror->output->pos);
}
static void
wet_output_compute_output_from_mirror(struct weston_output *output,
struct weston_output *mirror,
struct weston_mode *mode,
int *scale)
{
mode->width = output->native_mode_copy.width /
mirror->current_scale;
mode->height = output->native_mode_copy.height /
mirror->current_scale;
mode->refresh = output->native_mode_copy.refresh;
*scale = output->current_scale;
}
/*
* "A" is being a mirror-of output "B" then:
*
* - "A" defaults to scale=1, but the [output] section may define another
* scale, or the remote backend may provide the scale from the client.
* - The resolution of "A" is determined from the desktop area of "B" and the
* output scale of "A".
*/
static void
wet_output_overlap_post_enable(struct weston_head *head,
struct weston_head *head_to_mirror)
{
struct weston_mode mode;
int scale = 1;
wet_output_compute_output_from_mirror(head_to_mirror->output,
head->output, &mode, &scale);
weston_log("Setting modeline to output '%s' to %dx%d, scale: %d\n",
head->name, mode.width, mode.height, scale);
weston_output_mode_set_native(head->output, &mode, scale);
}
static void
simple_heads_output_sharing_resize(struct wl_listener *listener, void *data)
{
struct weston_head *head = data;
struct weston_head *head_to_mirror = NULL;
struct weston_output *output;
struct wet_head_tracker *head_track =
container_of(listener, struct wet_head_tracker, resized_listener);
struct wet_compositor *wet = head_track->wet;
struct weston_mode mode;
int scale = 1;
output = weston_head_get_output(head);
head_to_mirror = wet_config_find_head_to_mirror(output, wet);
if (!head_to_mirror)
return;
weston_output_set_position(head_to_mirror->output, output->pos);
wet_output_compute_output_from_mirror(head->output,
head_to_mirror->output,
&mode, &scale);
weston_output_mode_set_native(head_to_mirror->output, &mode, scale);
}
static void
wet_output_handle_create(struct wl_listener *listener, void *data)
{
struct wet_compositor *wet =
container_of(listener, struct wet_compositor, output_created_listener);
struct weston_output *output = data;
struct weston_head *head = NULL;
struct weston_head *head_to_mirror =
weston_output_get_first_head(output);
struct wet_head_tracker *head_track;
struct wet_backend *wb;
/* just ignore events from other remote backends */
switch (weston_get_backend_type(output->backend)) {
case WESTON_BACKEND_RDP:
case WESTON_BACKEND_VNC:
case WESTON_BACKEND_PIPEWIRE:
return;
default:
break;
}
head = wet_config_find_head_to_mirror(output, wet);
if (!head)
return;
wb = wet_get_backend_from_head(wet, head);
assert(wb);
simple_head_enable(wet, wb, head, head_to_mirror,
wet_output_overlap_pre_enable,
wet_output_overlap_post_enable);
weston_head_reset_device_changed(head);
head_track = wet_head_tracker_from_head(head);
head_track->wet = wet;
head_track->resized_listener.notify = simple_heads_output_sharing_resize;
wl_signal_add(&wet->compositor->output_resized_signal,
&head_track->resized_listener);
}
static struct wet_output *
wet_layoutput_create_output_with_head(struct wet_layoutput *lo,
const char *name,
......@@ -3301,7 +3582,7 @@ pipewire_backend_output_configure(struct weston_output *output)
weston_config_section_get_string(section, "gbm-format", &gbm_format, NULL);
weston_output_set_scale(output, 1);
wet_output_set_scale(output, section, 1, 0);
weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
api->set_gbm_format(output, gbm_format);
......@@ -3379,7 +3660,7 @@ weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
config->server_key = NULL;
config->env_socket = 0;
config->external_listener_fd = -1;
config->no_clients_resize = 0;
config->resizeable = true;
config->force_no_compression = 0;
config->remotefx_codec = true;
config->refresh_rate = RDP_DEFAULT_FREQ;
......@@ -3398,6 +3679,7 @@ rdp_backend_output_configure(struct weston_output *output)
struct weston_head *head = NULL;
int scale = 1;
struct weston_mode new_mode = {};
struct weston_config_section *section = NULL;
head = weston_output_get_first_head(output);
if (!head) {
......@@ -3405,6 +3687,9 @@ rdp_backend_output_configure(struct weston_output *output)
return -1;
}
section = weston_config_get_section(wet_get_config(output->compositor),
"output", "name", output->name);
api->head_get_monitor(head, &config);
width = config.width;
......@@ -3426,9 +3711,14 @@ rdp_backend_output_configure(struct weston_output *output)
new_mode.width = width;
new_mode.height = height;
if (output->mirror_of) {
api->disable_output_resize(output);
weston_log("Use of mirror_of disables resizing for output %s\n", output->name);
}
api->output_set_mode(output, &new_mode);
weston_output_set_scale(output, scale);
wet_output_set_scale(output, section, scale, 0);
weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
weston_log("rdp_backend_output_configure.. Done\n");
......@@ -3446,6 +3736,7 @@ load_rdp_backend(struct weston_compositor *c,
struct wet_backend *wb;
bool no_remotefx_codec = false;
struct wet_output_config *parsed_options = wet_init_parsed_options(c);
bool no_resizeable = false;
if (!parsed_options)
return -1;
......@@ -3459,7 +3750,7 @@ load_rdp_backend(struct weston_compositor *c,
{ WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
{ WESTON_OPTION_STRING, "address", 0, &config.bind_address },
{ WESTON_OPTION_INTEGER, "port", 0, &config.port },
{ WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
{ WESTON_OPTION_BOOLEAN, "no-resizeable", false, &no_resizeable },
{ WESTON_OPTION_STRING, "rdp4-key", 0, &config.rdp_key },
{ WESTON_OPTION_STRING, "rdp-tls-cert", 0, &config.server_cert },
{ WESTON_OPTION_STRING, "rdp-tls-key", 0, &config.server_key },
......@@ -3470,6 +3761,7 @@ load_rdp_backend(struct weston_compositor *c,
parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
config.remotefx_codec = !no_remotefx_codec;
config.resizeable = !no_resizeable;
config.renderer = renderer;
section = weston_config_get_section(wc, "rdp", NULL, NULL);
......@@ -3527,7 +3819,13 @@ vnc_backend_output_configure(struct weston_output *output)
weston_config_section_get_bool(section, "resizeable", &resizeable, true);
weston_output_set_scale(output, 1);
if (output->mirror_of && resizeable) {
resizeable = false;
weston_log("Use of mirror_of disables resizing for output %s\n", output->name);
}
wet_output_set_scale(output, section, 1, 0);
weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
if (api->output_set_size(output, width, height, resizeable) < 0) {
......@@ -3936,6 +4234,15 @@ load_backends(struct weston_compositor *ec, const char *backends,
return 0;
}
static void
wet_handle_mirror_outputs(struct wet_compositor *wet)
{
wet->output_created_listener.notify = wet_output_handle_create;
wl_signal_add(&wet->compositor->output_created_signal,
&wet->output_created_listener);
}
static char *
copy_command_line(int argc, char * const argv[])
{
......@@ -4350,6 +4657,8 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
if (weston_compositor_backends_loaded(wet.compositor) < 0)
goto out;
wet_handle_mirror_outputs(&wet);
if (test_data && !check_compositor_capabilities(wet.compositor,
test_data->test_quirks.required_capabilities)) {
ret = WET_MAIN_RET_MISSING_CAPS;
......@@ -4484,6 +4793,8 @@ out:
if (wet_xwl)
wet_xwayland_destroy(wet.compositor, wet_xwl);
if (wet.output_created_listener.notify)
wl_list_remove(&wet.output_created_listener.link);
weston_compositor_destroy(wet.compositor);
wet_compositor_destroy_layout(&wet);
weston_log_scope_destroy(protocol_scope);
......
......@@ -50,3 +50,6 @@ int
wet_output_set_colorimetry_mode(struct weston_output *output,
struct weston_config_section *section,
bool have_color_manager);
typedef void (*wet_head_additional_setup)(struct weston_head *head,
struct weston_head *head_to_mirror);
......@@ -53,6 +53,9 @@ struct weston_rdp_output_api {
/** Set mode for an output */
void (*output_set_mode)(struct weston_output *base,
struct weston_mode *mode);
/** disable output resize */
void (*disable_output_resize)(struct weston_output *output);
};
static inline const struct weston_rdp_output_api *
......@@ -81,7 +84,7 @@ struct weston_rdp_backend_config {
char *server_cert;
char *server_key;
int env_socket;
int no_clients_resize;
bool resizeable;
int force_no_compression;
bool remotefx_codec;
int external_listener_fd;
......
......@@ -624,6 +624,15 @@ struct weston_output {
struct weston_mode *native_mode;
struct weston_mode *current_mode;
struct weston_mode *original_mode;
/* FIXME: keep a local copy for native_mode */
struct {
uint32_t flags;
enum weston_mode_aspect_ratio aspect_ratio;
int32_t width;
int32_t height;
uint32_t refresh;
} native_mode_copy;
struct wl_list mode_list;
struct wl_list head_list; /**< List of driven weston_heads */
......@@ -696,6 +705,12 @@ struct weston_output {
*/
void (*detach_head)(struct weston_output *output,
struct weston_head *head);
/**
* When set, this output is a mirror-of another output. See
* mirror-of key in [output] section.
*/
struct weston_output *mirror_of;
};
enum weston_pointer_motion_mask {
......@@ -2202,6 +2217,8 @@ void
weston_output_schedule_repaint_reset(struct weston_output *output);
void
weston_output_schedule_repaint_restart(struct weston_output *output);
enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend);
void
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
void
......@@ -2809,6 +2826,14 @@ weston_compositor_add_screenshot_authority(struct weston_compositor *compositor,
int
weston_compositor_backends_loaded(struct weston_compositor *compositor);
void
weston_output_set_position(struct weston_output *output,
struct weston_coord_global pos);
int
weston_output_mode_set_native(struct weston_output *output,
struct weston_mode *mode,
int32_t scale);
#ifdef __cplusplus
}
#endif
......
......@@ -328,6 +328,15 @@ finish_frame_handler(void *data)
return 1;
}
static void
rdp_output_disable_resize(struct weston_output *base)
{
struct rdp_output *rdpOutput = container_of(base, struct rdp_output, base);
struct rdp_backend *b = rdpOutput->backend;
b->resizeable = false;
}
static void
rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
{
......@@ -1091,7 +1100,7 @@ xf_peer_activate(freerdp_peer* client)
* We still need the xf_peer_adjust_monitor_layout() call to make sure
* we've set up scaling appropriately.
*/
if (b->no_clients_resize) {
if (!b->resizeable) {
struct weston_mode *mode = output->base.current_mode;
if (mode->width != (int)settings->DesktopWidth ||
......@@ -1620,7 +1629,7 @@ xf_peer_adjust_monitor_layout(freerdp_peer *client)
fallback = true;
}
if (b->no_clients_resize)
if (!b->resizeable)
fallback = true;
if (settings->MonitorCount > RDP_MAX_MONITOR) {
......@@ -1658,7 +1667,7 @@ xf_peer_adjust_monitor_layout(freerdp_peer *client)
monitors[0].attributes.deviceScaleFactor = settings->DeviceScaleFactor;
monitors[0].orig_screen = 0;
if (b->no_clients_resize) {
if (!b->resizeable) {
/* If we're not allowing clients to resize us, set these
* to 0 so the front end knows it needs to make something
* up.
......@@ -1726,7 +1735,7 @@ rdp_peer_init(freerdp_peer *client, struct rdp_backend *b)
client->PostConnect = xf_peer_post_connect;
client->Activate = xf_peer_activate;
if (!b->no_clients_resize) {
if (b->resizeable) {
settings->SupportMonitorLayoutPdu = TRUE;
client->AdjustMonitorsLayout = xf_peer_adjust_monitor_layout;
}
......@@ -1805,6 +1814,7 @@ rdp_incoming_peer(freerdp_listener *instance, freerdp_peer *client)
static const struct weston_rdp_output_api api = {
rdp_head_get_monitor,
rdp_output_set_mode,
rdp_output_disable_resize,
};
static const uint32_t rdp_formats[] = {
......@@ -1830,7 +1840,7 @@ rdp_backend_create(struct weston_compositor *compositor,
b->base.destroy = rdp_destroy;
b->base.create_output = rdp_output_create;
b->rdp_key = config->rdp_key ? strdup(config->rdp_key) : NULL;
b->no_clients_resize = config->no_clients_resize;
b->resizeable = config->resizeable;
b->force_no_compression = config->force_no_compression;
b->remotefx_codec = config->remotefx_codec;
b->audio_in_setup = config->audio_in_setup;
......@@ -2003,7 +2013,7 @@ config_init_to_defaults(struct weston_rdp_backend_config *config)
config->server_cert = NULL;
config->server_key = NULL;
config->env_socket = 0;
config->no_clients_resize = 0;
config->resizeable = true;
config->force_no_compression = 0;
config->remotefx_codec = true;
config->external_listener_fd = -1;
......
......@@ -86,7 +86,7 @@ struct rdp_backend {
char *server_key;
char *rdp_key;
int tls_enabled;
int no_clients_resize;
int resizeable;
int force_no_compression;
bool remotefx_codec;
int external_listener_fd;
......
......@@ -129,6 +129,11 @@ struct weston_backend {
*/
bool (*can_scanout_dmabuf)(struct weston_backend *backend,
struct linux_dmabuf_buffer *buffer);
/** Identifies a particular backend_type from one
* defined in weston_compositor_backend.
*/
enum weston_compositor_backend backend_type;
};
/* weston_head */
......
......@@ -555,6 +555,12 @@ weston_output_mode_set_native(struct weston_output *output,
output->native_mode = mode;
output->native_scale = scale;
output->native_mode_copy.width = mode->width;
output->native_mode_copy.height = mode->height;
output->native_mode_copy.flags = mode->flags;
output->native_mode_copy.aspect_ratio = mode->aspect_ratio;
output->native_mode_copy.refresh = mode->refresh;
weston_mode_switch_finish(output, mode_changed, scale_changed);
if (mode_changed || scale_changed) {
......@@ -7241,10 +7247,6 @@ weston_head_get_destroy_listener(struct weston_head *head,
return wl_signal_get(&head->destroy_signal, notify);
}
static void
weston_output_set_position(struct weston_output *output,
struct weston_coord_global pos);
/* Move other outputs when one is resized so the space remains contiguous. */
static void
weston_compositor_reflow_outputs(struct weston_compositor *compositor,
......@@ -7339,7 +7341,7 @@ weston_output_init_geometry(struct weston_output *output,
/**
* \ingroup output
*/
static void
WL_EXPORT void
weston_output_set_position(struct weston_output *output,
struct weston_coord_global pos)
{
......@@ -10189,6 +10191,7 @@ weston_compositor_load_backend(struct weston_compositor *compositor,
return NULL;
b = wl_container_of(compositor->backend_list.next, b, link);
b->backend_type = backend;
/* Return the last loaded backend. */
return b;
......@@ -10456,3 +10459,21 @@ weston_output_finish_frame_from_timer(struct weston_output *output)
weston_output_finish_frame(output, &ts, 0);
}
/** Retrieve the backend type of as described in enum
* weston_compositor_backend.
*
* Note that the backend must be loaded, with weston_compositor_load_backend
*
* \param backend weston_backend in question
* \returns a type of enum weston_compositor_backend
*
* \sa weston_compositor_load_backend
*
*/
WL_EXPORT enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend)
{
assert(backend);
return backend->backend_type;
}
......@@ -149,7 +149,7 @@ Set the DRM KMS framebuffer format for this specific output. If not set,
If using the Pixman-renderer, use shadow framebuffers. Defaults to
.BR true .
.TP
\fBsame-as\fR=\fIname\fR
\fBclone-of\fR=\fIname\fR
Make this output (connector) a clone of another. The argument
.IR name " is the "
.BR name " value of another output section. The
......
.\" shorthand for double quote that works everywhere.
.ds q \N'34'
.TH weston.ini 5 "2019-03-26" "Weston @version@"
.TH weston.ini 5 "2024-08-07" "Weston @version@"
.\"---------------------------------------------------------------------
.SH NAME
weston.ini \- configuration file for
......@@ -651,6 +651,20 @@ Sets the basic output color characteristics by loading the parameters from the
section with the key
.BI "name=" name
\&. If an ICC profile is also set, the ICC profile takes precedence.
.TP 7
.BI "mirror-of=" ouput_name
Makes the remote output overlap (mirror) the native output identified by the
mirror-of value. This is useful for sharing or mirroring a native DRM output.
The output mirroring the DRM native one, will inherit the same video modeline
as the DRM native one, including the refresh rate and scale of the native
output. Note that depending on the remote backend, automatic output resize
will be disabled when mirroring is in effect. Mirroring a DRM native
output to another DRM native output is yet not supported, being intended
only for remote outputs.
NOTE: The native outputs created by the DRM backend using the 'clone-of'
are for cloning the outputs, and not sharing or mirroring. See also
.BR weston-drm(7).
.\"---------------------------------------------------------------------
.SH "INPUT-METHOD SECTION"
.TP 7
......