diff --git a/compositor/config-helpers.c b/compositor/config-helpers.c
index a012e7236..3d5c66cdf 100644
--- a/compositor/config-helpers.c
+++ b/compositor/config-helpers.c
@@ -62,3 +62,32 @@ get_backend_from_string(const char *name,
return false;
}
+
+struct {
+ char *name;
+ enum weston_renderer_type renderer;
+} renderer_name_map[] = {
+ { "auto", WESTON_RENDERER_AUTO },
+ { "gl", WESTON_RENDERER_GL },
+ { "noop", WESTON_RENDERER_NOOP },
+ { "pixman", WESTON_RENDERER_PIXMAN },
+};
+
+bool
+get_renderer_from_string(const char *name,
+ enum weston_renderer_type *renderer)
+{
+ size_t i;
+
+ if (!name)
+ name = "auto";
+
+ for (i = 0; i < ARRAY_LENGTH(renderer_name_map); i++) {
+ if (strcmp(name, renderer_name_map[i].name) == 0) {
+ *renderer = renderer_name_map[i].renderer;
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/compositor/main.c b/compositor/main.c
index 8e5c904ce..9e9670bdf 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -670,6 +670,13 @@ usage(int error_code)
#if defined(BUILD_X11_COMPOSITOR)
"\t\t\t\tx11\n"
#endif
+ " --renderer=NAME\tRenderer to use, one of\n"
+ "\t\t\t\tauto\tAutomatic selection of one of the below renderers\n"
+#if defined(ENABLE_EGL)
+ "\t\t\t\tgl\tOpenGL ES\n"
+#endif
+ "\t\t\t\tnoop\tNo-op renderer for testing only\n"
+ "\t\t\t\tpixman\tPixman software renderer\n"
" --shell=NAME\tShell to load, defaults to desktop\n"
" -S, --socket=NAME\tName of socket to listen on\n"
" -i, --idle-time=SECS\tIdle time in seconds\n"
@@ -695,7 +702,7 @@ usage(int error_code)
"Options for drm:\n\n"
" --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
" --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
- " --use-pixman\t\tUse the pixman (CPU) renderer\n"
+ " --use-pixman\t\tUse the pixman (CPU) renderer (deprecated alias for --renderer=pixman)\n"
" --current-mode\tPrefer current KMS mode over EDID preferred mode\n"
" --continue-without-input\tAllow the compositor to start without input devices\n\n");
#endif
@@ -708,8 +715,8 @@ usage(int error_code)
" --scale=SCALE\t\tScale factor of output\n"
" --transform=TR\tThe output transformation, TR is one of:\n"
"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
- " --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n"
- " --use-gl\t\tUse the GL renderer (default: no rendering)\n"
+ " --use-pixman\t\tUse the pixman (CPU) renderer (deprecated alias for --renderer=pixman)\n"
+ " --use-gl\t\tUse the GL renderer (deprecated alias for --renderer=gl)\n"
" --no-outputs\t\tDo not create any virtual outputs\n"
"\n");
#endif
@@ -748,7 +755,7 @@ usage(int error_code)
" --height=HEIGHT\tHeight of Wayland surface\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
- " --use-pixman\t\tUse the pixman (CPU) renderer\n"
+ " --use-pixman\t\tUse the pixman (CPU) renderer (deprecated alias for --renderer=pixman)\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --sprawl\t\tCreate one fullscreen output for every parent output\n"
" --display=DISPLAY\tWayland display to connect to\n\n");
@@ -761,7 +768,7 @@ usage(int error_code)
" --height=HEIGHT\tHeight of X window\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
- " --use-pixman\t\tUse the pixman (CPU) renderer\n"
+ " --use-pixman\t\tUse the pixman (CPU) renderer (deprecated alias for --renderer=pixman)\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --no-input\t\tDont create input devices\n\n");
#endif
@@ -2885,8 +2892,8 @@ load_pipewire(struct weston_compositor *c, struct weston_config *wc)
}
static int
-load_drm_backend(struct weston_compositor *c,
- int *argc, char **argv, struct weston_config *wc)
+load_drm_backend(struct weston_compositor *c, int *argc, char **argv,
+ struct weston_config *wc, enum weston_renderer_type renderer)
{
struct weston_drm_backend_config config = {{ 0, }};
struct weston_config_section *section;
@@ -2912,10 +2919,14 @@ load_drm_backend(struct weston_compositor *c,
parse_options(options, ARRAY_LENGTH(options), argc, argv);
- if (force_pixman)
+ if (force_pixman && renderer != WESTON_RENDERER_AUTO) {
+ weston_log("error: conflicting renderer specification\n");
+ return -1;
+ } else if (force_pixman) {
config.renderer = WESTON_RENDERER_PIXMAN;
- else
- config.renderer = WESTON_RENDERER_AUTO;
+ } else {
+ config.renderer = renderer;
+ }
section = weston_config_get_section(wc, "core", NULL, NULL);
weston_config_section_get_string(section,
@@ -2976,7 +2987,8 @@ headless_backend_output_configure(struct weston_output *output)
static int
load_headless_backend(struct weston_compositor *c,
- int *argc, char **argv, struct weston_config *wc)
+ int *argc, char **argv, struct weston_config *wc,
+ enum weston_renderer_type renderer)
{
const struct weston_windowed_output_api *api;
struct weston_headless_backend_config config = {{ 0, }};
@@ -3011,7 +3023,8 @@ load_headless_backend(struct weston_compositor *c,
parse_options(options, ARRAY_LENGTH(options), argc, argv);
- if (force_pixman && force_gl) {
+ if ((force_pixman && force_gl) ||
+ (renderer != WESTON_RENDERER_AUTO && (force_pixman || force_gl))) {
weston_log("Conflicting renderer specifications\n");
return -1;
} else if (force_pixman) {
@@ -3019,7 +3032,7 @@ load_headless_backend(struct weston_compositor *c,
} else if (force_gl) {
config.renderer = WESTON_RENDERER_GL;
} else {
- config.renderer = WESTON_RENDERER_AUTO;
+ config.renderer = renderer;
}
if (transform) {
@@ -3113,7 +3126,8 @@ weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
static int
load_rdp_backend(struct weston_compositor *c,
- int *argc, char *argv[], struct weston_config *wc)
+ int *argc, char *argv[], struct weston_config *wc,
+ enum weston_renderer_type renderer)
{
struct weston_rdp_backend_config config = {{ 0, }};
struct weston_config_section *section;
@@ -3143,6 +3157,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.renderer = renderer;
wet_set_simple_head_configurator(c, rdp_backend_output_configure);
section = weston_config_get_section(wc, "rdp", NULL, NULL);
@@ -3216,7 +3231,8 @@ weston_vnc_backend_config_init(struct weston_vnc_backend_config *config)
static int
load_vnc_backend(struct weston_compositor *c,
- int *argc, char *argv[], struct weston_config *wc)
+ int *argc, char *argv[], struct weston_config *wc,
+ enum weston_renderer_type renderer)
{
struct weston_vnc_backend_config config = {{ 0, }};
struct weston_config_section *section;
@@ -3239,6 +3255,8 @@ load_vnc_backend(struct weston_compositor *c,
parse_options(vnc_options, ARRAY_LENGTH(vnc_options), argc, argv);
+ config.renderer = renderer;
+
wet_set_simple_head_configurator(c, vnc_backend_output_configure);
section = weston_config_get_section(wc, "vnc", NULL, NULL);
weston_config_section_get_int(section, "refresh-rate",
@@ -3270,7 +3288,8 @@ x11_backend_output_configure(struct weston_output *output)
static int
load_x11_backend(struct weston_compositor *c,
- int *argc, char **argv, struct weston_config *wc)
+ int *argc, char **argv, struct weston_config *wc,
+ enum weston_renderer_type renderer)
{
char *default_output;
const struct weston_windowed_output_api *api;
@@ -3306,10 +3325,14 @@ load_x11_backend(struct weston_compositor *c,
config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
config.base.struct_size = sizeof(struct weston_x11_backend_config);
- if (force_pixman)
+ if (force_pixman && renderer != WESTON_RENDERER_AUTO) {
+ weston_log("error: conflicting renderer specification\n");
+ return -1;
+ } else if (force_pixman) {
config.renderer = WESTON_RENDERER_PIXMAN;
- else
+ } else {
config.renderer = WESTON_RENDERER_AUTO;
+ }
wet_set_simple_head_configurator(c, x11_backend_output_configure);
@@ -3385,7 +3408,8 @@ wayland_backend_output_configure(struct weston_output *output)
static int
load_wayland_backend(struct weston_compositor *c,
- int *argc, char **argv, struct weston_config *wc)
+ int *argc, char **argv, struct weston_config *wc,
+ enum weston_renderer_type renderer)
{
struct weston_wayland_backend_config config = {{ 0, }};
struct weston_config_section *section;
@@ -3431,10 +3455,14 @@ load_wayland_backend(struct weston_compositor *c,
config.base.struct_size = sizeof(struct weston_wayland_backend_config);
config.base.struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION;
- if (force_pixman)
+ if (force_pixman && renderer != WESTON_RENDERER_AUTO) {
+ weston_log("error: conflicting renderer specification\n");
+ return -1;
+ } else if (force_pixman) {
config.renderer = WESTON_RENDERER_PIXMAN;
- else
- config.renderer = WESTON_RENDERER_AUTO;
+ } else {
+ config.renderer = renderer;
+ }
/* load the actual wayland backend and configure it */
ret = weston_compositor_load_backend(c, WESTON_BACKEND_WAYLAND,
@@ -3506,28 +3534,41 @@ load_wayland_backend(struct weston_compositor *c,
static int
load_backend(struct weston_compositor *compositor, const char *name,
- int *argc, char **argv, struct weston_config *config)
+ int *argc, char **argv, struct weston_config *config,
+ const char *renderer_name)
{
enum weston_compositor_backend backend;
+ enum weston_renderer_type renderer;
if (!get_backend_from_string(name, &backend)) {
weston_log("Error: unknown backend \"%s\"\n", name);
return -1;
}
+ if (!get_renderer_from_string(renderer_name, &renderer)) {
+ weston_log("Error: unknown renderer \"%s\"\n", renderer_name);
+ return -1;
+ }
+
switch (backend) {
case WESTON_BACKEND_DRM:
- return load_drm_backend(compositor, argc, argv, config);
+ return load_drm_backend(compositor, argc, argv, config,
+ renderer);
case WESTON_BACKEND_HEADLESS:
- return load_headless_backend(compositor, argc, argv, config);
+ return load_headless_backend(compositor, argc, argv, config,
+ renderer);
case WESTON_BACKEND_RDP:
- return load_rdp_backend(compositor, argc, argv, config);
+ return load_rdp_backend(compositor, argc, argv, config,
+ renderer);
case WESTON_BACKEND_VNC:
- return load_vnc_backend(compositor, argc, argv, config);
+ return load_vnc_backend(compositor, argc, argv, config,
+ renderer);
case WESTON_BACKEND_WAYLAND:
- return load_wayland_backend(compositor, argc, argv, config);
+ return load_wayland_backend(compositor, argc, argv, config,
+ renderer);
case WESTON_BACKEND_X11:
- return load_x11_backend(compositor, argc, argv, config);
+ return load_x11_backend(compositor, argc, argv, config,
+ renderer);
default:
unreachable("unknown backend type in load_backend()");
}
@@ -3670,6 +3711,7 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
struct wl_event_loop *loop;
int i, fd;
char *backend = NULL;
+ char *renderer = NULL;
char *shell = NULL;
bool xwayland = false;
char *modules = NULL;
@@ -3703,6 +3745,7 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
const struct weston_option core_options[] = {
{ WESTON_OPTION_STRING, "backend", 'B', &backend },
+ { WESTON_OPTION_STRING, "renderer", 0, &renderer },
{ WESTON_OPTION_STRING, "shell", 0, &shell },
{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
@@ -3837,6 +3880,11 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
raise(SIGSTOP);
}
+ if (!renderer) {
+ weston_config_section_get_string(section, "renderer",
+ &renderer, NULL);
+ }
+
if (!backend) {
weston_config_section_get_string(section, "backend", &backend,
NULL);
@@ -3876,7 +3924,8 @@ wet_main(int argc, char *argv[], const struct weston_testsuite_data *test_data)
weston_config_section_get_bool(section, "require-input",
&wet.compositor->require_input, true);
- if (load_backend(wet.compositor, backend, &argc, argv, config) < 0) {
+ if (load_backend(wet.compositor, backend, &argc, argv, config,
+ renderer) < 0) {
weston_log("fatal: failed to create compositor backend\n");
goto out;
}
diff --git a/compositor/weston-private.h b/compositor/weston-private.h
index 6d6bda4a4..066d07cf7 100644
--- a/compositor/weston-private.h
+++ b/compositor/weston-private.h
@@ -32,6 +32,10 @@ bool
get_backend_from_string(const char *name,
enum weston_compositor_backend *backend);
+bool
+get_renderer_from_string(const char *name,
+ enum weston_renderer_type *renderer);
+
int
wet_output_set_color_characteristics(struct weston_output *output,
struct weston_config *wc,
diff --git a/doc/sphinx/toc/running-weston.rst b/doc/sphinx/toc/running-weston.rst
index 7ea3ed00a..9822b2fe9 100644
--- a/doc/sphinx/toc/running-weston.rst
+++ b/doc/sphinx/toc/running-weston.rst
@@ -34,15 +34,12 @@ stitching them together is performed by a *renderer*. By doing so, it is
compositing all surfaces into a single image, which is being handed out to a
back-end, and finally, displayed on the screen.
-libweston has a CPU-based type of renderer by making use of the
-`Pixman `_ library, but also one that can make
-use of the GPU to do that, which uses `OpenGL ES `_
-and it is simply called the GL-renderer.
-
-Most of the back-ends provide a command line option to disable the GL-renderer,
-and use the CPU for doing that. That happens by appending to the command line
-``--use-pixman`` when running Weston. One might use the CPU-based renderer
-to exclude any other potential issues with the GL-renderer.
+libweston provides two useful renderers. One uses
+`OpenGL ES `_, which will often be accelerated
+by your GPU when suitable drivers are installed. The other uses the
+`Pixman `_ library which is entirely CPU (software)
+rendered. You can select between these with the ``--renderer=gl`` and
+``--renderer=pixman`` arguments when starting Weston.
Additional set-up steps
-----------------------
diff --git a/man/weston.ini.man b/man/weston.ini.man
index 4f1141e13..483208576 100644
--- a/man/weston.ini.man
+++ b/man/weston.ini.man
@@ -188,7 +188,25 @@ directory are:
.fi
.RE
.TP 7
+.BI "renderer=" auto
+Selects a renderer to use for internal composition when required, or
+.BI auto
+to select the most appropriate renderer. Available renderers are:
+.PP
+.RS 10
+.nf
+.BR auto
+.BR gl
+.BR noop
+.BR pixman
+.fi
+.RE
+Not all backends support all renderers.
+.TP 7
.BI "use-pixman=" true
+Deprecated in favour of the
+.BI "renderer="
+option.
Enables pixman-based rendering for all outputs on backends that support it.
Boolean, defaults to
.BR false .
diff --git a/man/weston.man b/man/weston.man
index 7c7bf9145..3de1c8a9d 100644
--- a/man/weston.man
+++ b/man/weston.man
@@ -185,6 +185,10 @@ Do not read
for the compositor. Avoids e.g. loading compositor modules via the
configuration file, which is useful for unit tests.
.TP
+\fB\-\-renderer\fR=\fIrenderer\fR
+Select which renderer to use for Weston's internal composition. Defaults to
+automatic selection.
+.TP
\fB\-\-shell\fR=\fIshell\fR
Select which shell to load to provide Weston's user interface. See
.BR ENVIRONMENT "."
@@ -236,7 +240,9 @@ Give all outputs a scale factor of
.I N.
.TP
.B \-\-use\-pixman
-Use the pixman renderer. By default, weston will try to use EGL and
+Deprecated in favour of the
+.BI \-\-renderer
+option. Use the pixman renderer. By default weston will try to use EGL and
GLES2 for rendering and will fall back to the pixman-based renderer for
software compositing if EGL cannot be used. Passing this option will force
weston to use the pixman renderer.
@@ -262,7 +268,9 @@ Give all outputs a scale factor of
.I N.
.TP
.B \-\-use\-pixman
-Use the pixman renderer. By default weston will try to use EGL and
+Deprecated in favour of the
+.BI \-\-renderer
+option. Use the pixman renderer. By default weston will try to use EGL and
GLES2 for rendering. Passing this option will make weston use the
pixman library for software compsiting.
.
diff --git a/tests/weston-test-fixture-compositor.c b/tests/weston-test-fixture-compositor.c
index 6a6a05cba..ab606515e 100644
--- a/tests/weston-test-fixture-compositor.c
+++ b/tests/weston-test-fixture-compositor.c
@@ -218,30 +218,15 @@ backend_to_str(enum weston_compositor_backend b)
}
static const char *
-renderer_to_arg(enum weston_compositor_backend b, enum renderer_type r)
+renderer_to_str(enum renderer_type t)
{
- static const char * const headless_names[] = {
- [RENDERER_NOOP] = NULL,
- [RENDERER_PIXMAN] = "--use-pixman",
- [RENDERER_GL] = "--use-gl",
+ static const char * const names[] = {
+ [RENDERER_NOOP] = "noop",
+ [RENDERER_PIXMAN] = "pixman",
+ [RENDERER_GL] = "gl",
};
- static const char * const drm_names[] = {
- [RENDERER_PIXMAN] = "--use-pixman",
- [RENDERER_GL] = NULL,
- };
-
- switch (b) {
- case WESTON_BACKEND_HEADLESS:
- assert(r >= RENDERER_NOOP && r <= RENDERER_GL);
- return headless_names[r];
- case WESTON_BACKEND_DRM:
- assert(r >= RENDERER_PIXMAN && r <= RENDERER_GL);
- return drm_names[r];
- default:
- assert(0 && "renderer_to_str() does not know the backend");
- }
-
- return NULL;
+ assert(t >= 0 && t <= ARRAY_LENGTH(names));
+ return names[t];
}
static const char *
@@ -291,7 +276,7 @@ execute_compositor(const struct compositor_setup *setup,
struct weston_testsuite_data test_data;
struct prog_args args;
char *tmp;
- const char *ctmp, *drm_device;
+ const char *drm_device;
int lock_fd = -1;
int ret = RESULT_OK;
@@ -367,9 +352,8 @@ execute_compositor(const struct compositor_setup *setup,
prog_args_take(&args, strdup("--no-config"));
}
- ctmp = renderer_to_arg(setup->backend, setup->renderer);
- if (ctmp)
- prog_args_take(&args, strdup(ctmp));
+ str_printf(&tmp, "--renderer=%s", renderer_to_str(setup->renderer));
+ prog_args_take(&args, strdup(tmp));
str_printf(&tmp, "--shell=%s", shell_to_str(setup->shell));
prog_args_take(&args, tmp);