This commit makes the wayland backend search through the config for
[output] sections with names starting with "WL" and create outputs
accordingly.  Outputs created due to the config file support mode, scale,
and transform parameters.  It also listens for the --output-count
command-line option.

This brings the wayland backend almost up to par, in terms of functionality
with the X11 backend.

Signed-off-by: Jason Ekstrand <ja...@jlekstrand.net>
---
 man/weston.ini.man       |   4 +-
 src/compositor-wayland.c | 234 +++++++++++++++++++++++++++++++++++++----------
 src/compositor.c         |   1 +
 3 files changed, 188 insertions(+), 51 deletions(-)

diff --git a/man/weston.ini.man b/man/weston.ini.man
index d252419..ecb7ebb 100644
--- a/man/weston.ini.man
+++ b/man/weston.ini.man
@@ -236,7 +236,8 @@ currently only recognized by the drm and x11 backends.
 .TP 7
 .BI "name=" name
 sets a name for the output (string). The backend uses the name to
-identify the output. All X11 output names start with a letter X. The available
+identify the output. All X11 output names start with a letter X.  All
+Wayland output names start with the letters WL.  The available
 output names for DRM backend are listed in the
 .B "weston-launch(1)"
 output.
@@ -247,6 +248,7 @@ Examples of usage:
 .BR "LVDS1    " "DRM backend, Laptop internal panel no.1"
 .BR "VGA1     " "DRM backend, VGA connector no.1"
 .BR "X1       " "X11 backend, X window no.1"
+.BR "WL1      " "Wayland backend, Wayland window no.1"
 .fi
 .RE
 .RS
diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index c8268fd..78f9eb1 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -42,6 +42,15 @@
 #include "../shared/os-compatibility.h"
 #include "../shared/cairo-util.h"
 
+#define WINDOW_TITLE "Weston Compositor"
+
+struct wayland_backend_options {
+       int width, height;
+       char *display_name;
+       int use_pixman;
+       int count;
+};
+
 struct wayland_compositor {
        struct weston_compositor base;
 
@@ -100,6 +109,7 @@ struct wayland_output {
        } shm;
 
        struct weston_mode mode;
+       uint32_t scale;
 };
 
 struct wayland_shm_buffer {
@@ -202,8 +212,8 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
                width = frame_width(output->frame);
                height = frame_height(output->frame);
        } else {
-               width = output->mode.width;
-               height = output->mode.height;
+               width = output->base.current_mode->width;
+               height = output->base.current_mode->height;
        }
 
        stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
@@ -457,13 +467,18 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
        int32_t ix, iy, iwidth, iheight, fwidth, fheight;
        int i, n;
 
+       pixman_region32_init(&damage);
+       weston_transformed_region(sb->output->base.width,
+                                 sb->output->base.height,
+                                 sb->output->base.transform,
+                                 sb->output->base.current_scale,
+                                 &sb->damage, &damage);
+
        if (sb->output->frame) {
                frame_interior(sb->output->frame, &ix, &iy, &iwidth, &iheight);
                fwidth = frame_width(sb->output->frame);
                fheight = frame_height(sb->output->frame);
 
-               pixman_region32_init(&damage);
-               pixman_region32_copy(&damage, &sb->damage);
                pixman_region32_translate(&damage, ix, iy);
 
                if (sb->frame_damaged) {
@@ -478,11 +493,9 @@ wayland_shm_buffer_attach(struct wayland_shm_buffer *sb)
                                                   0, iy + iheight,
                                                   fwidth, fheight - (iy + 
iheight));
                }
-               rects = pixman_region32_rectangles(&damage, &n);
-       } else {
-               rects = pixman_region32_rectangles(&sb->damage, &n);
        }
 
+       rects = pixman_region32_rectangles(&damage, &n);
        wl_surface_attach(sb->output->parent.surface, sb->buffer, 0, 0);
        for (i = 0; i < n; ++i)
                wl_surface_damage(sb->output->parent.surface, rects[i].x1,
@@ -576,8 +589,8 @@ wayland_output_init_gl_renderer(struct wayland_output 
*output)
                fwidth = frame_width(output->frame);
                fheight = frame_height(output->frame);
        } else {
-               fwidth = output->base.width;
-               fheight = output->base.height;
+               fwidth = output->base.current_mode->width;
+               fheight = output->base.current_mode->height;
        }
 
        output->gl.egl_window =
@@ -605,45 +618,50 @@ wayland_output_init_pixman_renderer(struct wayland_output 
*output)
        return pixman_renderer_output_create(&output->base);
 }
 
-static int
-wayland_compositor_create_output(struct wayland_compositor *c,
-                                int width, int height)
+static struct wayland_output *
+wayland_output_create(struct wayland_compositor *c, int x, int y,
+                     int width, int height, const char *name,
+                     uint32_t transform, int32_t scale)
 {
        struct wayland_output *output;
        int32_t fx, fy, fwidth, fheight;
+       int output_width, output_height;
        struct wl_region *region;
 
        output = zalloc(sizeof *output);
        if (output == NULL)
-               return -1;
+               return NULL;
 
+       output_width = width * scale;
+       output_height = height * scale;
+       
        output->mode.flags =
                WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
-       output->mode.width = width;
-       output->mode.height = height;
-       output->mode.refresh = 60;
+       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);
 
+       weston_log("Creating %dx%d wayland output at (%d, %d)\n",
+                  width, height, x, y);
+
        output->base.current_mode = &output->mode;
-       weston_output_init(&output->base, &c->base, 0, 0, width, height,
-                          WL_OUTPUT_TRANSFORM_NORMAL, 1);
+       weston_output_init(&output->base, &c->base, x, y, width, height,
+                          transform, scale);
 
        output->base.make = "waywayland";
        output->base.model = "none";
 
-       weston_output_move(&output->base, 0, 0);
-
        wl_list_init(&output->shm.buffers);
        wl_list_init(&output->shm.free_buffers);
 
        if (!c->theme)
                c->theme = theme_create();
        output->frame = frame_create(c->theme, width, height,
-                                    FRAME_BUTTON_CLOSE, "Weston");
-       frame_resize_inside(output->frame, width, height);
-
-       weston_log("Creating %dx%d wayland output\n", width, height);
+                                    FRAME_BUTTON_CLOSE, name);
+       frame_resize_inside(output->frame, output_width, output_height);
 
        output->parent.surface =
                wl_compositor_create_surface(c->parent.compositor);
@@ -688,13 +706,85 @@ wayland_compositor_create_output(struct 
wayland_compositor *c,
 
        wl_list_insert(c->base.output_list.prev, &output->base.link);
 
-       return 0;
+       return output;
 
 cleanup_output:
        /* FIXME: cleanup weston_output */
        free(output);
 
-       return -1;
+       return NULL;
+}
+
+static struct wayland_output *
+wayland_output_create_for_config(struct wayland_compositor *c,
+                                struct wayland_backend_options *options,
+                                struct weston_config_section *config_section,
+                                int32_t x, int32_t y)
+{
+       struct wayland_output *output;
+       char *mode, *t, *name, *str;
+       int width, height, scale;
+       uint32_t transform;
+       unsigned int i, slen;
+
+       static const struct { const char *name; uint32_t token; } 
transform_names[] = {
+               { "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
+               { "90",         WL_OUTPUT_TRANSFORM_90 },
+               { "180",        WL_OUTPUT_TRANSFORM_180 },
+               { "270",        WL_OUTPUT_TRANSFORM_270 },
+               { "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
+               { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
+               { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
+               { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
+       };
+
+       weston_config_section_get_string(config_section, "name", &name, NULL);
+       if (name) {
+               slen = strlen(name);
+               slen += strlen(WINDOW_TITLE " - ");
+               str = malloc(slen + 1);
+               if (str)
+                       snprintf(str, slen + 1, WINDOW_TITLE " - %s", name);
+               free(name);
+               name = str;
+       }
+       if (!name)
+               name = WINDOW_TITLE;
+
+       weston_config_section_get_string(config_section,
+                                        "mode", &mode, "1024x600");
+       if (sscanf(mode, "%dx%d", &width, &height) != 2) {
+               weston_log("Invalid mode \"%s\" for output %s\n",
+                          mode, name);
+               width = 1024;
+               height = 640;
+       }
+       free(mode);
+
+       if (options->width)
+               width = options->width;
+       if (options->height)
+               height = options->height;
+
+       weston_config_section_get_int(config_section, "scale", &scale, 1);
+
+       weston_config_section_get_string(config_section,
+                                        "transform", &t, "normal");
+       transform = WL_OUTPUT_TRANSFORM_NORMAL;
+       for (i = 0; i < ARRAY_LENGTH(transform_names); i++) {
+               if (strcmp(transform_names[i].name, t) == 0) {
+                       transform = transform_names[i].token;
+                       break;
+               }
+       }
+       if (i >= ARRAY_LENGTH(transform_names))
+               weston_log("Invalid transform \"%s\" for output %s\n", t, name);
+       free(t);
+
+       output = wayland_output_create(c, x, y, width, height, name, transform, 
scale);
+       free(name);
+
+       return output;
 }
 
 static void
@@ -817,6 +907,7 @@ input_handle_pointer_enter(void *data, struct wl_pointer 
*pointer,
 
        x += wl_fixed_from_int(input->output->base.x);
        y += wl_fixed_from_int(input->output->base.y);
+       weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
 
        if (location == THEME_LOCATION_CLIENT_AREA) {
                input->focus = 1;
@@ -872,6 +963,7 @@ input_handle_motion(void *data, struct wl_pointer *pointer,
 
        x += wl_fixed_from_int(input->output->base.x);
        y += wl_fixed_from_int(input->output->base.y);
+       weston_output_transform_coordinate(&input->output->base, x, y, &x, &y);
 
        if (input->focus && location != THEME_LOCATION_CLIENT_AREA) {
                input_set_cursor(input);
@@ -1251,14 +1343,19 @@ create_cursor(struct wayland_compositor *c, struct 
weston_config *config)
 }
 
 static struct weston_compositor *
-wayland_compositor_create(struct wl_display *display, int use_pixman,
-                         int width, int height, const char *display_name,
+wayland_compositor_create(struct wl_display *display,
+                         struct wayland_backend_options *options,
                          int *argc, char *argv[],
                          struct weston_config *config)
 {
        struct wayland_compositor *c;
+       struct wayland_output *wo;
        struct wl_event_loop *loop;
-       int fd;
+       struct weston_config_section *section;
+       struct weston_output *output;
+       char *name;
+       const char *section_name;
+       int fd, x, count, width, height;
 
        c = zalloc(sizeof *c);
        if (c == NULL)
@@ -1268,7 +1365,7 @@ wayland_compositor_create(struct wl_display *display, int 
use_pixman,
                                   config) < 0)
                goto err_free;
 
-       c->parent.wl_display = wl_display_connect(display_name);
+       c->parent.wl_display = wl_display_connect(options->display_name);
 
        if (c->parent.wl_display == NULL) {
                weston_log("failed to create display: %m\n");
@@ -1284,13 +1381,16 @@ wayland_compositor_create(struct wl_display *display, 
int use_pixman,
 
        c->base.wl_display = display;
 
-       gl_renderer = weston_load_module("gl-renderer.so",
-                                        "gl_renderer_interface");
-       if (!gl_renderer)
-               goto err_display;
+       c->use_pixman = options->use_pixman;
 
-       c->use_pixman = use_pixman;
-       if (!use_pixman) {
+       if (!c->use_pixman) {
+               gl_renderer = weston_load_module("gl-renderer.so",
+                                                "gl_renderer_interface");
+               if (!gl_renderer)
+                       c->use_pixman = 1;
+       }
+
+       if (!c->use_pixman) {
                if (gl_renderer->create(&c->base, c->parent.wl_display,
                                gl_renderer->alpha_attribs,
                                NULL) < 0) {
@@ -1310,9 +1410,39 @@ wayland_compositor_create(struct wl_display *display, 
int use_pixman,
        c->base.destroy = wayland_destroy;
        c->base.restore = wayland_restore;
 
-       /* requires border fields */
-       if (wayland_compositor_create_output(c, width, height) < 0)
-               goto err_gl;
+       section = NULL;
+       x = 0;
+       count = 0;
+       while (weston_config_next_section(config, &section, &section_name)) {
+               if (!section_name || strcmp(section_name, "output") != 0)
+                       continue;
+               weston_config_section_get_string(section, "name", &name, NULL);
+               if (name == NULL)
+                       continue;
+
+               if (name[0] != 'W' || name[1] != 'L') {
+                       free(name);
+                       continue;
+               }
+               free(name);
+
+               wo = wayland_output_create_for_config(c, options, section, x, 
0);
+               if (!wo)
+                       goto err_outputs;
+               x += wo->base.width;
+               ++count;
+       }
+
+
+       width = options->width > 0 ? options->width : 1024;
+       height = options->height > 0 ? options->height : 640;
+       while (count < options->count) {
+               if (!wayland_output_create(c, x, 0, width, height,
+                                          WINDOW_TITLE, 0, 1))
+                       goto err_outputs;
+               x += width;
+               ++count;
+       }
 
        loop = wl_display_get_event_loop(c->base.wl_display);
 
@@ -1321,13 +1451,15 @@ wayland_compositor_create(struct wl_display *display, 
int use_pixman,
                wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
                                     wayland_compositor_handle_event, c);
        if (c->parent.wl_source == NULL)
-               goto err_gl;
+               goto err_outputs;
 
        wl_event_source_check(c->parent.wl_source);
 
        return &c->base;
+err_outputs:
+       wl_list_for_each(output, &c->base.output_list, link)
+               wayland_output_destroy(output);
 
-err_gl:
        c->base.renderer->destroy(&c->base);
 err_display:
        wl_display_disconnect(c->parent.wl_display);
@@ -1342,20 +1474,22 @@ WL_EXPORT struct weston_compositor *
 backend_init(struct wl_display *display, int *argc, char *argv[],
             struct weston_config *config)
 {
-       int width = 1024, height = 640;
-       char *display_name = NULL;
-       int use_pixman = 0;
+       struct wayland_backend_options options;
+       memset(&options, 0, sizeof options);
 
        const struct weston_option wayland_options[] = {
-               { WESTON_OPTION_INTEGER, "width", 0, &width },
-               { WESTON_OPTION_INTEGER, "height", 0, &height },
-               { WESTON_OPTION_STRING, "display", 0, &display_name },
-               { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
+               { WESTON_OPTION_INTEGER, "width", 0, &options.width },
+               { WESTON_OPTION_INTEGER, "height", 0, &options.height },
+               { WESTON_OPTION_STRING, "display", 0, &options.display_name },
+               { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &options.use_pixman },
+               { WESTON_OPTION_INTEGER, "output-count", 0, &options.count },
        };
 
+       options.count = 1;
+
        parse_options(wayland_options,
                      ARRAY_LENGTH(wayland_options), argc, argv);
 
-       return wayland_compositor_create(display, use_pixman, width, height,
-                                        display_name, argc, argv, config);
+       return wayland_compositor_create(display, &options,
+                                        argc, argv, config);
 }
diff --git a/src/compositor.c b/src/compositor.c
index 7b1d352..c9bd0ce 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3709,6 +3709,7 @@ usage(int error_code)
                "  --width=WIDTH\t\tWidth of Wayland surface\n"
                "  --height=HEIGHT\tHeight of Wayland surface\n"
                "  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+               "  --output-count=COUNT\tCreate multiple outputs\n"
                "  --display=DISPLAY\tWayland display to connect to\n\n");
 
 #if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
-- 
1.8.3.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to