[PATCH weston v3 09/14] weston: Port X11 backend to new output handling API
Armin Krezović
krezovic.armin at gmail.com
Fri Sep 30 12:11:10 UTC 2016
This is a complete port of the X11 backend that
uses recently added output handling API for output
configuration.
- Output can be configured at runtime by passing the
necessary configuration parameters, which can be
filled in manually, obtained from the configuration
file or obtained from the command line using
previously added functionality. It is required that
the scale and transform values are set using the
previously added functionality.
- Output can be created at runtime using the output
API. The output creation only creates a pending
output, which needs to be configured the same way as
mentioned above.
Same as before, a single output is created at runtime
using the default configuration or a configuration
parsed from the command line. The output-count
functionality is also preserved, which means more than
one output can be created initially, and more outputs can
be added at runtime using the output API.
v2:
- Fix wet_configure_windowed_output_from_config() usage.
- Call x11_output_disable() explicitly from
x11_output_destroy().
v3:
- Remove unneeded free().
- Disallow calling x11_output_configure more than once.
- Remove unneeded checks for output->name == NULL as that
has been disallowed.
- Use weston_compositor_add_pending_output().
- Bump weston_x11_backend_config version to 2.
Reviewed-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Signed-off-by: Armin Krezović <krezovic.armin at gmail.com>
---
compositor/main.c | 151 +++++++++-------------
libweston/compositor-x11.c | 312 +++++++++++++++++++++++++--------------------
libweston/compositor-x11.h | 13 +-
3 files changed, 235 insertions(+), 241 deletions(-)
diff --git a/compositor/main.c b/compositor/main.c
index d19b3f0..fca9778 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -1426,48 +1426,43 @@ out:
return ret;
}
-static int
-weston_x11_backend_config_append_output_config(struct weston_x11_backend_config *config,
- struct weston_x11_backend_output_config *output_config) {
- struct weston_x11_backend_output_config *new_outputs;
-
- new_outputs = realloc(config->outputs, (config->num_outputs+1) *
- sizeof(struct weston_x11_backend_output_config));
- if (new_outputs == NULL)
- return -1;
-
- config->outputs = new_outputs;
- config->outputs[config->num_outputs].width = output_config->width;
- config->outputs[config->num_outputs].height = output_config->height;
- config->outputs[config->num_outputs].transform = output_config->transform;
- config->outputs[config->num_outputs].scale = output_config->scale;
- config->outputs[config->num_outputs].name = strdup(output_config->name);
- config->num_outputs++;
+static void
+x11_backend_output_configure(struct wl_listener *listener, void *data)
+{
+ struct weston_output *output = data;
+ struct wet_output_config defaults = {
+ .width = 1024,
+ .height = 600,
+ .scale = 1,
+ .transform = WL_OUTPUT_TRANSFORM_NORMAL
+ };
- return 0;
+ if (wet_configure_windowed_output_from_config(output, &defaults) < 0)
+ weston_log("Cannot configure output \"%s\".\n", output->name);
}
static int
load_x11_backend(struct weston_compositor *c,
int *argc, char **argv, struct weston_config *wc)
{
- struct weston_x11_backend_output_config default_output;
+ char *default_output;
+ const struct weston_windowed_output_api *api;
struct weston_x11_backend_config config = {{ 0, }};
struct weston_config_section *section;
int ret = 0;
- int option_width = 0;
- int option_height = 0;
- int option_scale = 0;
int option_count = 1;
int output_count = 0;
char const *section_name;
int i;
- uint32_t j;
+
+ struct wet_output_config *parsed_options = wet_init_parsed_options(c);
+ if (!parsed_options)
+ return -1;
const struct weston_option options[] = {
- { WESTON_OPTION_INTEGER, "width", 0, &option_width },
- { WESTON_OPTION_INTEGER, "height", 0, &option_height },
- { WESTON_OPTION_INTEGER, "scale", 0, &option_scale },
+ { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
+ { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
+ { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
{ WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
{ WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
{ WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
@@ -1476,94 +1471,66 @@ load_x11_backend(struct weston_compositor *c,
parse_options(options, ARRAY_LENGTH(options), argc, argv);
+ config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
+ config.base.struct_size = sizeof(struct weston_x11_backend_config);
+
+ /* load the actual backend and configure it */
+ ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
+ &config.base);
+
+ if (ret < 0)
+ return ret;
+
+ wet_set_pending_output_handler(c, x11_backend_output_configure);
+
+ api = weston_windowed_output_get_api(c);
+
+ if (!api) {
+ weston_log("Cannot use weston_windowed_output_api.\n");
+ return -1;
+ }
+
section = NULL;
while (weston_config_next_section(wc, §ion, §ion_name)) {
- struct weston_x11_backend_output_config current_output = { 0, };
- char *t;
- char *mode;
+ char *output_name;
+
+ if (output_count >= option_count)
+ break;
if (strcmp(section_name, "output") != 0) {
continue;
}
- weston_config_section_get_string(section, "name", ¤t_output.name, NULL);
- if (current_output.name == NULL || current_output.name[0] != 'X') {
- free(current_output.name);
+ weston_config_section_get_string(section, "name", &output_name, NULL);
+ if (output_name == NULL || output_name[0] != 'X') {
+ free(output_name);
continue;
}
- weston_config_section_get_string(section, "mode", &mode, "1024x600");
- if (sscanf(mode, "%dx%d", ¤t_output.width,
- ¤t_output.height) != 2) {
- weston_log("Invalid mode \"%s\" for output %s\n",
- mode, current_output.name);
- current_output.width = 1024;
- current_output.height = 600;
- }
- free(mode);
- if (current_output.width < 1)
- current_output.width = 1024;
- if (current_output.height < 1)
- current_output.height = 600;
- if (option_width)
- current_output.width = option_width;
- if (option_height)
- current_output.height = option_height;
-
- weston_config_section_get_int(section, "scale", ¤t_output.scale, 1);
- if (option_scale)
- current_output.scale = option_scale;
-
- weston_config_section_get_string(section,
- "transform", &t, "normal");
- if (weston_parse_transform(t, ¤t_output.transform) < 0)
- weston_log("Invalid transform \"%s\" for output %s\n",
- t, current_output.name);
- free(t);
-
- if (weston_x11_backend_config_append_output_config(&config, ¤t_output) < 0) {
- ret = -1;
- goto out;
+ if (api->output_create(c, output_name) < 0) {
+ free(output_name);
+ return -1;
}
+ free(output_name);
output_count++;
- if (output_count >= option_count)
- break;
}
- default_output.name = NULL;
- default_output.width = option_width ? option_width : 1024;
- default_output.height = option_height ? option_height : 600;
- default_output.scale = option_scale ? option_scale : 1;
- default_output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ default_output = NULL;
for (i = output_count; i < option_count; i++) {
- if (asprintf(&default_output.name, "screen%d", i) < 0) {
- ret = -1;
- goto out;
+ if (asprintf(&default_output, "screen%d", i) < 0) {
+ return -1;
}
- if (weston_x11_backend_config_append_output_config(&config, &default_output) < 0) {
- ret = -1;
- free(default_output.name);
- goto out;
+ if (api->output_create(c, default_output) < 0) {
+ free(default_output);
+ return -1;
}
- free(default_output.name);
+ free(default_output);
}
- config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
- config.base.struct_size = sizeof(struct weston_x11_backend_config);
-
- /* load the actual backend and configure it */
- ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
- &config.base);
-
-out:
- for (j = 0; j < config.num_outputs; ++j)
- free(config.outputs[j].name);
- free(config.outputs);
-
- return ret;
+ return 0;
}
static void
diff --git a/libweston/compositor-x11.c b/libweston/compositor-x11.c
index 3e0d20f..86241c6 100644
--- a/libweston/compositor-x11.c
+++ b/libweston/compositor-x11.c
@@ -59,6 +59,7 @@
#include "pixman-renderer.h"
#include "presentation-time-server-protocol.h"
#include "linux-dmabuf.h"
+#include "windowed-output-api.h"
#define DEFAULT_AXIS_STEP_DISTANCE 10
@@ -75,6 +76,8 @@ struct x11_backend {
struct xkb_keymap *xkb_keymap;
unsigned int has_xkb;
uint8_t xkb_event_base;
+ int fullscreen;
+ int no_input;
int use_pixman;
int has_net_wm_state_fullscreen;
@@ -516,30 +519,6 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
}
static void
-x11_output_destroy(struct weston_output *output_base)
-{
- struct x11_output *output = to_x11_output(output_base);
- struct x11_backend *backend =
- to_x11_backend(output->base.compositor);
-
- wl_event_source_remove(output->finish_frame_timer);
-
- if (backend->use_pixman) {
- pixman_renderer_output_destroy(output_base);
- x11_output_deinit_shm(backend, output);
- } else
- gl_renderer->output_destroy(output_base);
-
- xcb_destroy_window(backend->conn, output->window);
-
- xcb_flush(backend->conn);
-
- weston_output_destroy(&output->base);
-
- free(output);
-}
-
-static void
x11_output_set_wm_protocols(struct x11_backend *b,
struct x11_output *output)
{
@@ -789,20 +768,54 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
return 0;
}
-static struct x11_output *
-x11_backend_create_output(struct x11_backend *b, int x, int y,
- int width, int height, int fullscreen,
- int no_input, char *configured_name,
- uint32_t transform, int32_t scale)
+static int
+x11_output_disable(struct weston_output *base)
+{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *backend = to_x11_backend(base->compositor);
+
+ if (!output->base.enabled)
+ return 0;
+
+ wl_event_source_remove(output->finish_frame_timer);
+
+ if (backend->use_pixman) {
+ pixman_renderer_output_destroy(&output->base);
+ x11_output_deinit_shm(backend, output);
+ } else {
+ gl_renderer->output_destroy(&output->base);
+ }
+
+ xcb_destroy_window(backend->conn, output->window);
+ xcb_flush(backend->conn);
+
+ return 0;
+}
+
+static void
+x11_output_destroy(struct weston_output *base)
+{
+ struct x11_output *output = to_x11_output(base);
+
+ x11_output_disable(&output->base);
+ weston_output_destroy(&output->base);
+
+ free(output);
+}
+
+static int
+x11_output_enable(struct weston_output *base)
{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *b = to_x11_backend(base->compositor);
+
static const char name[] = "Weston Compositor";
static const char class[] = "weston-1\0Weston Compositor";
char *title = NULL;
- struct x11_output *output;
xcb_screen_t *screen;
struct wm_normal_hints normal_hints;
struct wl_event_loop *loop;
- int output_width, output_height, width_mm, height_mm;
+
int ret;
uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
xcb_atom_t atom_list[1];
@@ -812,10 +825,7 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
0
};
- output_width = width * scale;
- output_height = height * scale;
-
- if (!no_input)
+ if (!b->no_input)
values[0] |=
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_KEY_RELEASE |
@@ -827,22 +837,6 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
XCB_EVENT_MASK_KEYMAP_STATE |
XCB_EVENT_MASK_FOCUS_CHANGE;
- output = zalloc(sizeof *output);
- if (output == NULL) {
- perror("zalloc");
- return NULL;
- }
-
- output->mode.flags =
- WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
-
- output->mode.width = output_width;
- output->mode.height = output_height;
- output->mode.refresh = 60000;
- output->scale = scale;
- wl_list_init(&output->base.mode_list);
- wl_list_insert(&output->base.mode_list, &output->mode.link);
-
values[1] = b->null_cursor;
output->window = xcb_generate_id(b->conn);
screen = x11_compositor_get_default_screen(b);
@@ -851,13 +845,14 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
output->window,
screen->root,
0, 0,
- output_width, output_height,
+ output->base.current_mode->width,
+ output->base.current_mode->height,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual,
mask, values);
- if (fullscreen) {
+ if (b->fullscreen) {
atom_list[0] = b->atom.net_wm_state_fullscreen;
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE,
output->window,
@@ -869,10 +864,10 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
memset(&normal_hints, 0, sizeof normal_hints);
normal_hints.flags =
WM_NORMAL_HINTS_MAX_SIZE | WM_NORMAL_HINTS_MIN_SIZE;
- normal_hints.min_width = output_width;
- normal_hints.min_height = output_height;
- normal_hints.max_width = output_width;
- normal_hints.max_height = output_height;
+ normal_hints.min_width = output->base.current_mode->width;
+ normal_hints.min_height = output->base.current_mode->height;
+ normal_hints.max_width = output->base.current_mode->width;
+ normal_hints.max_height = output->base.current_mode->height;
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE, output->window,
b->atom.wm_normal_hints,
b->atom.wm_size_hints, 32,
@@ -881,8 +876,8 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
}
/* Set window name. Don't bother with non-EWMH WMs. */
- if (configured_name) {
- if (asprintf(&title, "%s - %s", name, configured_name) < 0)
+ if (output->base.name) {
+ if (asprintf(&title, "%s - %s", name, output->base.name) < 0)
title = NULL;
} else {
title = strdup(name);
@@ -894,9 +889,7 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
strlen(title), title);
free(title);
} else {
- xcb_destroy_window(b->conn, output->window);
- free(output);
- return NULL;
+ goto err;
}
xcb_change_property(b->conn, XCB_PROP_MODE_REPLACE, output->window,
@@ -909,44 +902,20 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
xcb_map_window(b->conn, output->window);
- if (fullscreen)
+ if (b->fullscreen)
x11_output_wait_for_map(b, output);
- output->base.start_repaint_loop = x11_output_start_repaint_loop;
- if (b->use_pixman)
- output->base.repaint = x11_output_repaint_shm;
- else
- output->base.repaint = x11_output_repaint_gl;
- output->base.destroy = x11_output_destroy;
- output->base.assign_planes = NULL;
- output->base.set_backlight = NULL;
- output->base.set_dpms = NULL;
- output->base.switch_mode = NULL;
- output->base.current_mode = &output->mode;
- output->base.make = "weston-X11";
- output->base.model = "none";
-
- if (configured_name)
- output->base.name = strdup(configured_name);
-
- width_mm = width * b->screen->width_in_millimeters /
- b->screen->width_in_pixels;
- height_mm = height * b->screen->height_in_millimeters /
- b->screen->height_in_pixels;
- weston_output_init(&output->base, b->compositor,
- x, y, width_mm, height_mm, transform, scale);
-
if (b->use_pixman) {
if (x11_output_init_shm(b, output,
- output->mode.width,
- output->mode.height) < 0) {
+ output->base.current_mode->width,
+ output->base.current_mode->height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
- return NULL;
+ goto err;
}
if (pixman_renderer_output_create(&output->base) < 0) {
weston_log("Failed to create pixman renderer for output\n");
x11_output_deinit_shm(b, output);
- return NULL;
+ goto err;
}
} else {
/* eglCreatePlatformWindowSurfaceEXT takes a Window*
@@ -960,19 +929,112 @@ x11_backend_create_output(struct x11_backend *b, int x, int y,
NULL,
0);
if (ret < 0)
- return NULL;
+ goto err;
}
loop = wl_display_get_event_loop(b->compositor->wl_display);
output->finish_frame_timer =
wl_event_loop_add_timer(loop, finish_frame_handler, output);
- weston_compositor_add_output(b->compositor, &output->base);
-
weston_log("x11 output %dx%d, window id %d\n",
- width, height, output->window);
+ output->base.current_mode->width,
+ output->base.current_mode->height,
+ output->window);
+
+ return 0;
- return output;
+err:
+ xcb_destroy_window(b->conn, output->window);
+ xcb_flush(b->conn);
+
+ return -1;
+}
+
+static int
+x11_output_set_size(struct weston_output *base, int width, int height)
+{
+ struct x11_output *output = to_x11_output(base);
+ struct x11_backend *b = to_x11_backend(base->compositor);
+ int output_width, output_height;
+
+ /* We can only be called once. */
+ assert(!output->base.current_mode);
+
+ /* Make sure we have scale set. */
+ assert(output->base.scale);
+
+ if (width < 1) {
+ weston_log("Invalid width \"%d\" for output %s\n",
+ width, output->base.name);
+ return -1;
+ }
+
+ if (height < 1) {
+ weston_log("Invalid height \"%d\" for output %s\n",
+ height, output->base.name);
+ return -1;
+ }
+
+ output_width = width * output->base.scale;
+ output_height = height * output->base.scale;
+
+ output->mode.flags =
+ WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
+
+ output->mode.width = output_width;
+ output->mode.height = output_height;
+ output->mode.refresh = 60000;
+ output->scale = output->base.scale;
+ wl_list_init(&output->base.mode_list);
+ wl_list_insert(&output->base.mode_list, &output->mode.link);
+
+ output->base.current_mode = &output->mode;
+ output->base.make = "weston-X11";
+ output->base.model = "none";
+
+ output->base.mm_width = width * b->screen->width_in_millimeters /
+ b->screen->width_in_pixels;
+ output->base.mm_height = height * b->screen->height_in_millimeters /
+ b->screen->height_in_pixels;
+
+ if (b->use_pixman)
+ output->base.repaint = x11_output_repaint_shm;
+ else
+ output->base.repaint = x11_output_repaint_gl;
+
+ output->base.start_repaint_loop = x11_output_start_repaint_loop;
+ output->base.assign_planes = NULL;
+ output->base.set_backlight = NULL;
+ output->base.set_dpms = NULL;
+ output->base.switch_mode = NULL;
+
+ return 0;
+}
+
+static int
+x11_output_create(struct weston_compositor *compositor,
+ const char *name)
+{
+ struct x11_output *output;
+
+ /* name can't be NULL. */
+ assert(name);
+
+ output = zalloc(sizeof *output);
+ if (output == NULL) {
+ perror("zalloc");
+ return -1;
+ }
+
+ output->base.name = strdup(name);
+ output->base.destroy = x11_output_destroy;
+ output->base.disable = x11_output_disable;
+ output->base.enable = x11_output_enable;
+
+ weston_output_init_pending(&output->base, compositor);
+ weston_compositor_add_pending_output(&output->base, compositor);
+
+ return 0;
}
static struct x11_output *
@@ -1588,21 +1650,27 @@ init_gl_renderer(struct x11_backend *b)
return ret;
}
+static const struct weston_windowed_output_api api = {
+ x11_output_set_size,
+ x11_output_create,
+};
+
static struct x11_backend *
x11_backend_create(struct weston_compositor *compositor,
struct weston_x11_backend_config *config)
{
struct x11_backend *b;
- struct x11_output *output;
struct wl_event_loop *loop;
- int x = 0;
- unsigned i;
+ int ret;
b = zalloc(sizeof *b);
if (b == NULL)
return NULL;
b->compositor = compositor;
+ b->fullscreen = config->fullscreen;
+ b->no_input = config->no_input;
+
if (weston_compositor_set_presentation_clock_software(compositor) < 0)
goto err_free;
@@ -1648,44 +1716,6 @@ x11_backend_create(struct weston_compositor *compositor,
goto err_renderer;
}
- for (i = 0; i < config->num_outputs; ++i) {
- struct weston_x11_backend_output_config *output_iterator =
- &config->outputs[i];
-
- if (output_iterator->name == NULL) {
- continue;
- }
-
- if (output_iterator->width < 1) {
- weston_log("Invalid width \"%d\" for output %s\n",
- output_iterator->width, output_iterator->name);
- goto err_x11_input;
- }
-
- if (output_iterator->height < 1) {
- weston_log("Invalid height \"%d\" for output %s\n",
- output_iterator->height, output_iterator->name);
- goto err_x11_input;
- }
-
- output = x11_backend_create_output(b,
- x,
- 0,
- output_iterator->width,
- output_iterator->height,
- config->fullscreen,
- config->no_input,
- output_iterator->name,
- output_iterator->transform,
- output_iterator->scale);
- if (output == NULL) {
- weston_log("Failed to create configured x11 output\n");
- goto err_x11_input;
- }
-
- x = pixman_region32_extents(&output->base.region)->x2;
- }
-
loop = wl_display_get_event_loop(compositor->wl_display);
b->xcb_source =
wl_event_loop_add_fd(loop,
@@ -1702,6 +1732,14 @@ x11_backend_create(struct weston_compositor *compositor,
compositor->backend = &b->base;
+ ret = weston_plugin_api_register(compositor, WESTON_WINDOWED_OUTPUT_API_NAME,
+ &api, sizeof(api));
+
+ if (ret < 0) {
+ weston_log("Failed to register output API.\n");
+ goto err_x11_input;
+ }
+
return b;
err_x11_input:
diff --git a/libweston/compositor-x11.h b/libweston/compositor-x11.h
index 6a17f96..8989fc2 100644
--- a/libweston/compositor-x11.h
+++ b/libweston/compositor-x11.h
@@ -34,15 +34,7 @@ extern "C" {
#include "compositor.h"
-#define WESTON_X11_BACKEND_CONFIG_VERSION 1
-
-struct weston_x11_backend_output_config {
- int width;
- int height;
- char *name;
- uint32_t transform;
- int32_t scale;
-};
+#define WESTON_X11_BACKEND_CONFIG_VERSION 2
struct weston_x11_backend_config {
struct weston_backend_config base;
@@ -52,9 +44,6 @@ struct weston_x11_backend_config {
/** Whether to use the pixman renderer instead of the OpenGL ES renderer. */
bool use_pixman;
-
- uint32_t num_outputs;
- struct weston_x11_backend_output_config *outputs;
};
#ifdef __cplusplus
--
2.10.0
More information about the wayland-devel
mailing list