---
compositor/main.c | 52 ++++++++++++++++--
libweston/compositor-rdp.c | 130 +++++++++++++++++++++++++++++++--------------
libweston/compositor-rdp.h | 24 ++++++++-
3 files changed, 160 insertions(+), 46 deletions(-)
diff --git a/compositor/main.c b/compositor/main.c
index b26760c..a72c2f9 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -1284,13 +1284,46 @@ load_headless_backend(struct weston_compositor *c,
}
static void
+rdp_backend_output_configure(struct wl_listener *listener, void *data)
+{
+ struct weston_output *output = data;
+ struct wet_compositor *compositor =
to_wet_compositor(output->compositor);
+ struct wet_output_config *parsed_options = compositor->parsed_options;
+ const struct weston_rdp_output_api *api =
weston_rdp_output_get_api(output->compositor);
+ int width = 640;
+ int height = 480;
+
+ assert(parsed_options);
+
+ if (!api) {
+ weston_log("Cannot use weston_rdp_output_api.\n");
+ return;
+ }
+
+ if (parsed_options->width)
+ width = parsed_options->width;
+
+ if (parsed_options->height)
+ height = parsed_options->height;
+
+ weston_output_set_scale(output, 1);
+ weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
+
+ if (api->output_set_size(output, width, height) < 0) {
+ weston_log("Cannot configure output \"%s\" using
weston_rdp_output_api.\n",
+ output->name);
+ return;
+ }
+
+ weston_output_enable(output);
+}
+
+static void
weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
{
config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
config->base.struct_size = sizeof(struct weston_rdp_backend_config);
- config->width = 640;
- config->height = 480;
config->bind_address = NULL;
config->port = 3389;
config->rdp_key = NULL;
@@ -1307,12 +1340,16 @@ load_rdp_backend(struct weston_compositor *c,
struct weston_rdp_backend_config config = {{ 0, }};
int ret = 0;
+ struct wet_output_config *parsed_options = wet_init_parsed_options(c);
+ if (!parsed_options)
+ return -1;
+
weston_rdp_backend_config_init(&config);
const struct weston_option rdp_options[] = {
{ WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
- { WESTON_OPTION_INTEGER, "width", 0, &config.width },
- { WESTON_OPTION_INTEGER, "height", 0, &config.height },
+ { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
+ { 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 },
@@ -1326,10 +1363,17 @@ load_rdp_backend(struct weston_compositor *c,
ret = weston_compositor_load_backend(c, WESTON_BACKEND_RDP,
&config.base);
+ if (ret < 0)
+ goto out;
+
+ wet_set_pending_output_handler(c, rdp_backend_output_configure);
+
+out:
free(config.bind_address);
free(config.rdp_key);
free(config.server_cert);
free(config.server_key);
+
return ret;
}
diff --git a/libweston/compositor-rdp.c b/libweston/compositor-rdp.c
index 11f5f05..ffa2fdf 100644
--- a/libweston/compositor-rdp.c
+++ b/libweston/compositor-rdp.c
@@ -371,15 +371,6 @@ rdp_output_repaint(struct weston_output *output_base,
pixman_region32_t *damage)
return 0;
}
-static void
-rdp_output_destroy(struct weston_output *output_base)
-{
- struct rdp_output *output = to_rdp_output(output_base);
-
- wl_event_source_remove(output->finish_frame_timer);
- free(output);
-}
-
static int
finish_frame_handler(void *data)
{
@@ -471,17 +462,13 @@ rdp_switch_mode(struct weston_output *output, struct
weston_mode *target_mode)
}
static int
-rdp_backend_create_output(struct rdp_backend *b, int width, int height)
+rdp_output_configure(struct weston_output *base,
+ int width, int height)
{
- struct rdp_output *output;
- struct wl_event_loop *loop;
+ struct rdp_output *output = to_rdp_output(base);
struct weston_mode *currentMode;
struct weston_mode initMode;
- output = zalloc(sizeof *output);
- if (output == NULL)
- return -1;
-
wl_list_init(&output->peers);
wl_list_init(&output->base.mode_list);
@@ -492,48 +479,100 @@ rdp_backend_create_output(struct rdp_backend *b, int
width, int height)
currentMode = ensure_matching_mode(&output->base, &initMode);
if (!currentMode)
- goto out_free_output;
+ return -1;
output->base.current_mode = output->base.native_mode = currentMode;
- weston_output_init(&output->base, b->compositor, 0, 0, width, height,
- WL_OUTPUT_TRANSFORM_NORMAL, 1);
output->base.make = "weston";
output->base.model = "rdp";
+ output->base.mm_width = width;
+ output->base.mm_height = height;
+
+ output->base.start_repaint_loop = rdp_output_start_repaint_loop;
+ output->base.repaint = rdp_output_repaint;
+ output->base.assign_planes = NULL;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+ output->base.switch_mode = rdp_switch_mode;
+
+ return 0;
+}
+
+static int
+rdp_output_enable(struct weston_output *base)
+{
+ struct rdp_output *output = to_rdp_output(base);
+ struct rdp_backend *b = to_rdp_backend(base->compositor);
+ struct wl_event_loop *loop;
+
output->shadow_surface = pixman_image_create_bits(PIXMAN_x8r8g8b8,
- width, height,
+ output->base.mm_width, output->base.mm_height,
NULL,
- width * 4);
+ output->base.mm_width * 4);
if (output->shadow_surface == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
- goto out_output;
+ return -1;
}
- if (pixman_renderer_output_create(&output->base) < 0)
- goto out_shadow_surface;
+ if (pixman_renderer_output_create(&output->base) < 0) {
+ pixman_image_unref(output->shadow_surface);
+ return -1;
+ }
loop = wl_display_get_event_loop(b->compositor->wl_display);
output->finish_frame_timer = wl_event_loop_add_timer(loop,
finish_frame_handler, output);
- output->base.start_repaint_loop = rdp_output_start_repaint_loop;
- output->base.repaint = rdp_output_repaint;
- output->base.destroy = rdp_output_destroy;
- output->base.assign_planes = NULL;
- output->base.set_backlight = NULL;
- output->base.set_dpms = NULL;
- output->base.switch_mode = rdp_switch_mode;
b->output = output;
- weston_compositor_add_output(b->compositor, &output->base);
return 0;
+}
+
+static int
+rdp_output_disable(struct weston_output *base)
+{
+ struct rdp_output *output = to_rdp_output(base);
+ struct rdp_backend *b = to_rdp_backend(base->compositor);
+
+ if (!output->base.enabled)
+ return 0;
-out_shadow_surface:
pixman_image_unref(output->shadow_surface);
-out_output:
+ pixman_renderer_output_destroy(&output->base);
+
+ wl_event_source_remove(output->finish_frame_timer);
+ b->output = NULL;
+
+ return 0;
+}
+
+static void
+rdp_output_destroy(struct weston_output *base)
+{
+ struct rdp_output *output = to_rdp_output(base);
+
+ rdp_output_disable(&output->base);
weston_output_destroy(&output->base);
-out_free_output:
+
free(output);
- return -1;
+}
+
+static int
+rdp_backend_create_output(struct weston_compositor *compositor)
+{
+ struct rdp_output *output;
+
+ output = zalloc(sizeof *output);
+ if (output == NULL)
+ return -1;
+
+ output->base.name = NULL;
+ output->base.destroy = rdp_output_destroy;
+ output->base.disable = rdp_output_disable;
+ output->base.enable = rdp_output_enable;
+
+ weston_output_init_pending(&output->base, compositor);
+
+ return 0;
}
static void
@@ -1216,6 +1255,10 @@ rdp_incoming_peer(freerdp_listener *instance,
freerdp_peer *client)
FREERDP_CB_RETURN(TRUE);
}
+static const struct weston_rdp_output_api api = {
+ rdp_output_configure,
+};
+
static struct rdp_backend *
rdp_backend_create(struct weston_compositor *compositor,
struct weston_rdp_backend_config *config)
@@ -1223,7 +1266,7 @@ rdp_backend_create(struct weston_compositor *compositor,
struct rdp_backend *b;
char *fd_str;
char *fd_tail;
- int fd;
+ int fd, ret;
b = zalloc(sizeof *b);
if (b == NULL)
@@ -1251,7 +1294,7 @@ rdp_backend_create(struct weston_compositor *compositor,
if (pixman_renderer_init(compositor) < 0)
goto err_compositor;
- if (rdp_backend_create_output(b, config->width, config->height) < 0)
+ if (rdp_backend_create_output(compositor) < 0)
goto err_compositor;
compositor->capabilities |= WESTON_CAP_ARBITRARY_MODES;
@@ -1282,6 +1325,15 @@ rdp_backend_create(struct weston_compositor *compositor,
}
compositor->backend = &b->base;
+
+ ret = weston_plugin_api_register(compositor, WESTON_RDP_OUTPUT_API_NAME,
+ &api, sizeof(api));
+
+ if (ret < 0) {
+ weston_log("Failed to register output API.\n");
+ goto err_output;
+ }
+
return b;
err_listener:
@@ -1301,8 +1353,6 @@ err_free_strings:
static void
config_init_to_defaults(struct weston_rdp_backend_config *config)
{
- config->width = 640;
- config->height = 480;
config->bind_address = NULL;
config->port = 3389;
config->rdp_key = NULL;
diff --git a/libweston/compositor-rdp.h b/libweston/compositor-rdp.h
index dfa1759..44bea3d 100644
--- a/libweston/compositor-rdp.h
+++ b/libweston/compositor-rdp.h
@@ -31,13 +31,33 @@ extern "C" {
#endif
#include "compositor.h"
+#include "plugin-registry.h"
+
+#define WESTON_RDP_OUTPUT_API_NAME "weston_rdp_output_api_v1"
+
+struct weston_rdp_output_api {
+ /** Initialize a RDP output with specified width and height.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+ int (*output_set_size)(struct weston_output *output,
+ int width, int height);
+};
+
+static inline const struct weston_rdp_output_api *
+weston_rdp_output_get_api(struct weston_compositor *compositor)
+{
+ const void *api;
+ api = weston_plugin_api_get(compositor, WESTON_RDP_OUTPUT_API_NAME,
+ sizeof(struct weston_rdp_output_api));
+
+ return (const struct weston_rdp_output_api *)api;
+}
#define WESTON_RDP_BACKEND_CONFIG_VERSION 1
struct weston_rdp_backend_config {
struct weston_backend_config base;
- int width;
- int height;
char *bind_address;
int port;
char *rdp_key;