swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit 0dc0ed350e20a22189a4f31e7dba2ee5dd52167c
parent 4d255239247338b6f112cb599d115abd58c2464d
Author: Michael Forney <mforney@mforney.org>
Date:   Thu, 16 Jan 2014 19:52:26 -0800

Implement screens

Diffstat:
Mlibswc/compositor.c | 113+++++++++++++++++++++++++++++++------------------------------------------------
Mlibswc/compositor.h | 6++----
Mlibswc/drm.c | 57+++++++++++++++++----------------------------------------
Mlibswc/drm.h | 2+-
Mlibswc/internal.h | 3+++
Mlibswc/local.mk | 3++-
Mlibswc/output.c | 63+++++++++++++++++++++++++++++++++++++--------------------------
Mlibswc/output.h | 22+++++++---------------
Mlibswc/plane.c | 14++++++++------
Alibswc/screen.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/screen.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlibswc/surface.c | 2+-
Mlibswc/surface.h | 2+-
Mlibswc/swc.c | 45++++++++++++++++++++++++++++-----------------
Mlibswc/swc.h | 21+++++++++++++++++----
15 files changed, 318 insertions(+), 185 deletions(-)

diff --git a/libswc/compositor.c b/libswc/compositor.c @@ -7,6 +7,7 @@ #include "output.h" #include "pointer.h" #include "region.h" +#include "screen.h" #include "seat.h" #include "surface.h" #include "util.h" @@ -195,50 +196,51 @@ static void update_extents(struct swc_surface * surface) view->border.damaged = true; } -static void update_outputs(struct swc_surface * surface) +static void update_screens(struct swc_surface * surface) { struct view * view = (void *) surface->view; - struct swc_compositor * compositor = view->compositor; - uint32_t old_outputs = surface->outputs, new_outputs = 0, - entered_outputs, left_outputs, changed_outputs; + uint32_t old_screens = surface->screens, new_screens = 0, + entered_screens, left_screens, changed_screens; + struct swc_screen_internal * screen; struct swc_output * output; struct wl_client * client; struct wl_resource * resource; if (view->mapped) { - wl_list_for_each(output, &compositor->outputs, link) + wl_list_for_each(screen, &swc.screens, link) { - if (swc_rectangle_overlap(&output->geometry, &surface->geometry)) - new_outputs |= SWC_OUTPUT_MASK(output); + if (swc_rectangle_overlap(&screen->base.geometry, &surface->geometry)) + new_screens |= swc_screen_mask(screen); } } - if (new_outputs == old_outputs) + if (new_screens == old_screens) return; - entered_outputs = new_outputs & ~old_outputs; - left_outputs = old_outputs & ~new_outputs; - changed_outputs = old_outputs ^ new_outputs; + entered_screens = new_screens & ~old_screens; + left_screens = old_screens & ~new_screens; + changed_screens = old_screens ^ new_screens; - wl_list_for_each(output, &compositor->outputs, link) + wl_list_for_each(screen, &swc.screens, link) { - if (!(changed_outputs & SWC_OUTPUT_MASK(output))) + if (!(changed_screens & swc_screen_mask(screen))) continue; + output = CONTAINER_OF(screen->outputs.next, typeof(*output), link); client = wl_resource_get_client(surface->resource); resource = wl_resource_find_for_client(&output->resources, client); if (resource) { - if (entered_outputs & SWC_OUTPUT_MASK(output)) + if (entered_screens & swc_screen_mask(screen)) wl_surface_send_enter(surface->resource, resource); - else if (left_outputs & SWC_OUTPUT_MASK(output)) + else if (left_screens & swc_screen_mask(screen)) wl_surface_send_leave(surface->resource, resource); } } - surface->outputs = new_outputs; + surface->screens = new_screens; } static void update(struct swc_view * view); @@ -258,7 +260,7 @@ static void handle_surface_event(struct wl_listener * listener, void * data) update_extents(surface); update(&view->base); - update_outputs(surface); + update_screens(surface); break; } @@ -284,16 +286,15 @@ static void attach(struct swc_view * base, struct swc_buffer * buffer) static void update(struct swc_view * base) { struct view * view = (void *) base; - struct swc_compositor * compositor = view->compositor; - struct swc_output * output; + struct swc_screen_internal * screen; if (!view->mapped) return; - wl_list_for_each(output, &compositor->outputs, link) + wl_list_for_each(screen, &swc.screens, link) { - if (view->surface->outputs & SWC_OUTPUT_MASK(output)) - swc_compositor_schedule_update(compositor, output); + if (view->surface->screens & swc_screen_mask(screen)) + swc_compositor_schedule_update(view->compositor, screen); } } @@ -321,7 +322,7 @@ static void move(struct swc_view * base, int32_t x, int32_t y) damage_below_surface(surface); update(&view->base); - update_outputs(surface); + update_screens(surface); update(&view->base); } } @@ -382,7 +383,7 @@ void swc_compositor_surface_show(struct swc_surface * surface) pixman_region32_clear(&view->clip); damage_surface(surface); - update_outputs(surface); + update_screens(surface); update(&view->base); wl_list_insert(&compositor->surfaces, &surface->link); } @@ -403,7 +404,7 @@ void swc_compositor_surface_hide(struct swc_surface * surface) view->mapped = false; damage_below_surface(surface); - update_outputs(surface); + update_screens(surface); wl_list_remove(&surface->link); } @@ -509,10 +510,12 @@ static void calculate_damage(struct swc_compositor * compositor) pixman_region32_fini(&surface_opaque); } -static void repaint_output(struct swc_compositor * compositor, - struct swc_output * output, +static void repaint_screen(struct swc_compositor * compositor, + struct swc_screen_internal * screen, pixman_region32_t * damage) { + struct swc_output * output + = CONTAINER_OF(screen->outputs.next, typeof(*output), link); pixman_region32_t base_damage; struct render_target target; @@ -520,10 +523,8 @@ static void repaint_output(struct swc_compositor * compositor, pixman_region32_subtract(&base_damage, damage, &compositor->opaque); target.buffer = swc_plane_get_buffer(&output->framebuffer_plane); - target.geometry.x = output->framebuffer_plane.output->geometry.x - + output->framebuffer_plane.x; - target.geometry.y = output->framebuffer_plane.output->geometry.y - + output->framebuffer_plane.y; + target.geometry.x = screen->base.geometry.x + output->framebuffer_plane.x; + target.geometry.y = screen->base.geometry.y + output->framebuffer_plane.y; target.geometry.width = target.buffer->width; target.geometry.height = target.buffer->height; @@ -539,12 +540,13 @@ static void repaint_output(struct swc_compositor * compositor, static void update_output_damage(struct swc_output * output, pixman_region32_t * damage) { + struct swc_rectangle * geometry = &output->screen->base.geometry; + pixman_region32_union (&output->current_damage, &output->current_damage, damage); pixman_region32_intersect_rect (&output->current_damage, &output->current_damage, - output->geometry.x, output->geometry.y, - output->geometry.width, output->geometry.height); + geometry->x, geometry->y, geometry->width, geometry->height); } static void flush_output_damage(struct swc_output * output, @@ -564,6 +566,7 @@ static void flush_output_damage(struct swc_output * output, static void perform_update(void * data) { struct swc_compositor * compositor = data; + struct swc_screen_internal * screen; struct swc_output * output; pixman_region32_t damage; uint32_t updates = compositor->scheduled_updates @@ -577,19 +580,20 @@ static void perform_update(void * data) calculate_damage(compositor); pixman_region32_init(&damage); - wl_list_for_each(output, &compositor->outputs, link) + wl_list_for_each(screen, &swc.screens, link) { - if (!(compositor->scheduled_updates & SWC_OUTPUT_MASK(output))) + if (!(compositor->scheduled_updates & swc_screen_mask(screen))) continue; + output = CONTAINER_OF(screen->outputs.next, typeof(*output), link); update_output_damage(output, &compositor->damage); /* Don't repaint the output if it is waiting for a page flip. */ - if (compositor->pending_flips & SWC_OUTPUT_MASK(output)) + if (compositor->pending_flips & swc_screen_mask(screen)) continue; flush_output_damage(output, &damage); - repaint_output(compositor, output, &damage); + repaint_screen(compositor, screen, &damage); } pixman_region32_fini(&damage); @@ -725,7 +729,6 @@ bool swc_compositor_initialize(struct swc_compositor * compositor, struct wl_display * display, struct wl_event_loop * event_loop) { - struct wl_list * outputs; uint32_t keysym; compositor->display = display; @@ -739,20 +742,6 @@ bool swc_compositor_initialize(struct swc_compositor * compositor, wl_signal_add(&swc.drm->event_signal, &compositor->drm_listener); - outputs = swc_drm_create_outputs(); - - if (outputs) - { - wl_list_init(&compositor->outputs); - wl_list_insert_list(&compositor->outputs, outputs); - free(outputs); - } - else - { - printf("could not create outputs\n"); - return false; - } - pixman_region32_init(&compositor->damage); pixman_region32_init(&compositor->opaque); wl_list_init(&compositor->surfaces); @@ -774,38 +763,24 @@ bool swc_compositor_initialize(struct swc_compositor * compositor, void swc_compositor_finish(struct swc_compositor * compositor) { - struct swc_output * output, * tmp; - - wl_list_for_each_safe(output, tmp, &compositor->outputs, link) - { - swc_output_finish(output); - free(output); - } } void swc_compositor_add_globals(struct swc_compositor * compositor, struct wl_display * display) { - struct swc_output * output; - wl_global_create(display, &wl_compositor_interface, 3, compositor, &bind_compositor); - - wl_list_for_each(output, &compositor->outputs, link) - { - swc_output_add_globals(output, display); - } } void swc_compositor_schedule_update(struct swc_compositor * compositor, - struct swc_output * output) + struct swc_screen_internal * screen) { bool update_scheduled = compositor->scheduled_updates != 0; - if (compositor->scheduled_updates & SWC_OUTPUT_MASK(output)) + if (compositor->scheduled_updates & swc_screen_mask(screen)) return; - compositor->scheduled_updates |= SWC_OUTPUT_MASK(output); + compositor->scheduled_updates |= swc_screen_mask(screen); if (!update_scheduled) { diff --git a/libswc/compositor.h b/libswc/compositor.h @@ -5,13 +5,11 @@ #include <wayland-server.h> -struct swc_output; +struct swc_screen_internal; struct swc_compositor { struct wl_display * display; - - struct wl_list outputs; struct wl_list surfaces; /* Internal state related to repainting the screen. */ @@ -44,7 +42,7 @@ void swc_compositor_add_globals(struct swc_compositor * compositor, struct wl_display * display); void swc_compositor_schedule_update(struct swc_compositor * compositor, - struct swc_output * output); + struct swc_screen_internal * screen); bool swc_compositor_add_surface(struct swc_compositor * compositor, struct swc_surface * surface); diff --git a/libswc/drm.c b/libswc/drm.c @@ -25,6 +25,7 @@ #include "event.h" #include "internal.h" #include "output.h" +#include "screen.h" #include "wayland_buffer.h" #include <stdio.h> @@ -47,7 +48,7 @@ static struct uint32_t id; char * path; - uint32_t taken_output_ids; + uint32_t taken_ids; struct wl_global * global; struct wl_event_source * event_source; @@ -248,7 +249,7 @@ static bool find_available_crtc(drmModeRes * resources, static bool find_available_id(uint32_t * id) { - uint32_t index = __builtin_ffsl(~drm.taken_output_ids); + uint32_t index = __builtin_ffsl(~drm.taken_ids); if (index == 0) return false; @@ -335,7 +336,7 @@ bool swc_drm_initialize(const char * seat_name) goto error0; } - drm.taken_output_ids = 0; + drm.taken_ids = 0; drm.path = strdup(udev_device_get_devnode(drm_device)); udev_device_unref(drm_device); swc.drm->fd = swc_launch_open_device(drm.path, O_RDWR | O_CLOEXEC); @@ -402,25 +403,19 @@ void swc_drm_finalize() close(swc.drm->fd); } -struct wl_list * swc_drm_create_outputs() +bool swc_drm_create_screens(struct wl_list * screens) { drmModeRes * resources; drmModeConnector * connector; drmModeCrtc * crtc; uint32_t index; - uint32_t x = 0; struct swc_output * output; - struct wl_list * outputs; uint32_t taken_crtcs = 0; - outputs = malloc(sizeof(struct wl_list)); - wl_list_init(outputs); - - resources = drmModeGetResources(swc.drm->fd); - if (!resources) + if (!(resources = drmModeGetResources(swc.drm->fd))) { printf("couldn't get DRM resources\n"); - goto error; + return false; } printf("crtc count: %u\n", resources->count_crtcs); @@ -444,7 +439,8 @@ struct wl_list * swc_drm_create_outputs() drmModeFreeEncoder(encoder); } - for (index = 0; index < resources->count_connectors; ++index) + for (index = 0; index < resources->count_connectors; + ++index, drmModeFreeConnector(connector)) { connector = drmModeGetConnector(swc.drm->fd, resources->connectors[index]); @@ -472,41 +468,22 @@ struct wl_list * swc_drm_create_outputs() break; } - output = malloc(sizeof(struct swc_output)); - - output->geometry.x = x; - output->geometry.y = 0; - - if (!swc_output_initialize(output, id, - resources->crtcs[crtc_index], connector)) - { - drmModeFreeConnector(connector); - free(output); + if (!(output = swc_output_new(resources->crtcs[crtc_index], connector))) continue; - } + + output->screen = swc_screen_new(resources->crtcs[crtc_index], + output); + output->screen->id = id; taken_crtcs |= 1 << crtc_index; - drm.taken_output_ids |= 1 << id; + drm.taken_ids |= 1 << id; - wl_list_insert(outputs, &output->link); - x += output->geometry.width; + wl_list_insert(screens, &output->screen->link); } - - drmModeFreeConnector(connector); } drmModeFreeResources(resources); - if (wl_list_empty(outputs)) - { - printf("couldn't find any outputs\n"); - goto error; - } - - return outputs; - - error: - free(outputs); - return NULL; + return true; } diff --git a/libswc/drm.h b/libswc/drm.h @@ -27,7 +27,7 @@ struct swc_drm bool swc_drm_initialize(const char * seat); void swc_drm_finalize(); -struct wl_list * swc_drm_create_outputs(); +bool swc_drm_create_screens(struct wl_list * screens); #endif diff --git a/libswc/internal.h b/libswc/internal.h @@ -24,6 +24,8 @@ #ifndef SWC_INTERNAL_H #define SWC_INTERNAL_H +#include <wayland-util.h> + struct swc { struct wl_display * display; @@ -34,6 +36,7 @@ struct swc const struct swc_seat_global * const seat; const struct swc_bindings_global * const bindings; + struct wl_list screens; struct swc_compositor * compositor; struct swc_shm * const shm; struct swc_drm * const drm; diff --git a/libswc/local.mk b/libswc/local.mk @@ -59,7 +59,8 @@ SWC_SOURCES += \ libswc/window.c \ libswc/shell.c \ libswc/shell_surface.c \ - libswc/bindings.c + libswc/bindings.c \ + libswc/screen.c ifeq ($(ENABLE_XWAYLAND),1) $(dir)_CFLAGS += -DENABLE_XWAYLAND diff --git a/libswc/output.c b/libswc/output.c @@ -2,6 +2,7 @@ #include "drm.h" #include "internal.h" #include "mode.h" +#include "screen.h" #include "util.h" #include <stdio.h> @@ -14,6 +15,7 @@ static void bind_output(struct wl_client * client, void * data, uint32_t version, uint32_t id) { struct swc_output * output = data; + struct swc_screen_internal * screen = output->screen; struct swc_mode * mode; struct wl_resource * resource; uint32_t flags; @@ -26,9 +28,10 @@ static void bind_output(struct wl_client * client, void * data, &swc_remove_resource); wl_list_insert(&output->resources, wl_resource_get_link(resource)); - wl_output_send_geometry(resource, output->geometry.x, output->geometry.y, - output->physical_width, output->physical_height, 0, "unknown", - "unknown", WL_OUTPUT_TRANSFORM_NORMAL); + wl_output_send_geometry + (resource, screen->base.geometry.x, screen->base.geometry.y, + output->physical_width, output->physical_height, 0, "unknown", + "unknown", WL_OUTPUT_TRANSFORM_NORMAL); wl_array_for_each(mode, &output->modes) { @@ -46,18 +49,29 @@ static void bind_output(struct wl_client * client, void * data, wl_output_send_done(resource); } -bool swc_output_initialize(struct swc_output * output, - uint32_t id, uint32_t crtc_id, - drmModeConnector * connector) +struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector) { + struct swc_output * output; drmModeEncoder * encoder; drmModeCrtc * current_crtc; struct swc_mode * modes; uint32_t index; - printf("initializing output with id: %u\n", id); + if (!(output = malloc(sizeof *output))) + { + ERROR("Failed to allocated output\n"); + goto error0; + } + + output->global = wl_global_create(swc.display, &wl_output_interface, 2, + output, &bind_output); + + if (!output->global) + { + ERROR("Failed to create output global\n"); + goto error1; + } - output->id = id; output->physical_width = connector->mmWidth; output->physical_height = connector->mmHeight; @@ -66,8 +80,8 @@ bool swc_output_initialize(struct swc_output * output, pixman_region32_init(&output->current_damage); pixman_region32_init(&output->previous_damage); - output->crtc_id = crtc_id; - output->connector_id = connector->connector_id; + output->crtc = crtc_id; + output->connector = connector->connector_id; /* Determine the current CRTC of this output. */ encoder = drmModeGetEncoder(swc.drm->fd, connector->encoder_id); @@ -90,9 +104,6 @@ bool swc_output_initialize(struct swc_output * output, if (output->preferred_mode) output->current_mode = output->preferred_mode; - output->geometry.width = output->current_mode->width; - output->geometry.height = output->current_mode->height; - output->original_state.crtc = current_crtc; /* Create output planes */ @@ -100,22 +111,26 @@ bool swc_output_initialize(struct swc_output * output, &swc_framebuffer_plane, output)) { printf("failed to initialize framebuffer plane\n"); - goto error_base; + goto error2; } if (!swc_plane_initialize(&output->cursor_plane, &swc_cursor_plane, output)) { printf("failed to initialize cursor plane\n"); - goto error_base; + goto error2; } - return true; + return output; - error_base: - return false; + error2: + wl_global_destroy(output->global); + error1: + free(output); + error0: + return NULL; } -void swc_output_finish(struct swc_output * output) +void swc_output_destroy(struct swc_output * output) { struct swc_mode * mode; drmModeCrtc * crtc = output->original_state.crtc; @@ -125,13 +140,9 @@ void swc_output_finish(struct swc_output * output) wl_array_release(&output->modes); drmModeSetCrtc(swc.drm->fd, crtc->crtc_id, crtc->buffer_id, crtc->x, - crtc->y, &output->connector_id, 1, &crtc->mode); + crtc->y, &output->connector, 1, &crtc->mode); drmModeFreeCrtc(crtc); -} - -void swc_output_add_globals(struct swc_output * output, - struct wl_display * display) -{ - wl_global_create(display, &wl_output_interface, 2, output, &bind_output); + wl_global_destroy(output->global); + free(output); } diff --git a/libswc/output.h b/libswc/output.h @@ -8,16 +8,13 @@ #include <wayland-util.h> #include <xf86drmMode.h> -#define SWC_OUTPUT_MASK(output) (1 << (output)->id) - struct wl_display; struct swc_output { - uint32_t id; + struct swc_screen_internal * screen; - /* The geometry of this output */ - struct swc_rectangle geometry; + /* The physical dimensions (in mm) of this output */ uint32_t physical_width, physical_height; struct wl_array modes; @@ -29,26 +26,21 @@ struct swc_output pixman_region32_t current_damage, previous_damage; - /* The CRTC and connector we are using to drive this output */ - uint32_t crtc_id; - uint32_t connector_id; + /* The DRM connector corresponding to this output */ + uint32_t crtc, connector; struct { drmModeCrtc * crtc; } original_state; + struct wl_global * global; struct wl_list resources; struct wl_list link; }; -bool swc_output_initialize(struct swc_output * output, uint32_t id, uint32_t crtc_id, - drmModeConnector * connector); - -void swc_output_finish(struct swc_output * output); - -void swc_output_add_globals(struct swc_output * output, - struct wl_display * display); +struct swc_output * swc_output_new(uint32_t crtc_id, drmModeConnector * connector); +void swc_output_destroy(struct swc_output * output); #endif diff --git a/libswc/plane.c b/libswc/plane.c @@ -26,6 +26,7 @@ #include "internal.h" #include "mode.h" #include "output.h" +#include "screen.h" #include <stdlib.h> #include <stdio.h> @@ -43,8 +44,8 @@ static bool framebuffer_initialize(struct swc_plane * plane) { struct framebuffer * fb = swc_double_buffer_front(&plane->double_buffer); - return drmModeSetCrtc(swc.drm->fd, plane->output->crtc_id, - fb->id, 0, 0, &plane->output->connector_id, 1, + return drmModeSetCrtc(swc.drm->fd, plane->output->crtc, + fb->id, 0, 0, &plane->output->connector, 1, &plane->output->current_mode->info) == 0; } @@ -59,7 +60,8 @@ static void * framebuffer_create_buffer(struct swc_plane * plane) goto error0; buffer = wld_create_buffer(swc.drm->context, - output->geometry.width, output->geometry.height, + output->screen->base.geometry.width, + output->screen->base.geometry.height, WLD_FORMAT_XRGB8888); if (!buffer) @@ -109,7 +111,7 @@ static bool framebuffer_flip(struct swc_plane * plane) struct swc_output * output = plane->output; struct framebuffer * fb = swc_double_buffer_back(&plane->double_buffer); - return drmModePageFlip(swc.drm->fd, output->crtc_id, fb->id, + return drmModePageFlip(swc.drm->fd, output->crtc, fb->id, DRM_MODE_PAGE_FLIP_EVENT, output) == 0; } @@ -149,13 +151,13 @@ static bool cursor_flip(struct swc_plane * plane) union wld_object object; wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object); - return drmModeSetCursor(swc.drm->fd, plane->output->crtc_id, + return drmModeSetCursor(swc.drm->fd, plane->output->crtc, object.u32, 64, 64) == 0; } static bool cursor_move(struct swc_plane * plane, int32_t x, int32_t y) { - return drmModeMoveCursor(swc.drm->fd, plane->output->crtc_id, x, y) == 0; + return drmModeMoveCursor(swc.drm->fd, plane->output->crtc, x, y) == 0; } const struct swc_plane_interface swc_cursor_plane = { diff --git a/libswc/screen.c b/libswc/screen.c @@ -0,0 +1,94 @@ +/* swc: libswc/screen.c + * + * Copyright (c) 2013, 2014 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "screen.h" +#include "drm.h" +#include "internal.h" +#include "mode.h" +#include "output.h" + +#include <stdlib.h> +#include <sys/param.h> + +#define INTERNAL(screen) ((struct swc_screen_internal *) (screen)) + +bool swc_screens_initialize() +{ + wl_list_init(&swc.screens); + + if (!swc_drm_create_screens(&swc.screens)) + return false; + + if (wl_list_empty(&swc.screens)) + return false; + + return true; +} + +void swc_screens_finalize() +{ + struct swc_screen_internal * screen, * tmp; + + wl_list_for_each_safe(screen, tmp, &swc.screens, link) + free(screen); +} + +struct swc_screen_internal * swc_screen_new(uint32_t crtc, + struct swc_output * output) +{ + struct swc_screen_internal * screen; + int32_t x = 0; + + /* Simple heuristic for initial screen positioning. */ + wl_list_for_each(screen, &swc.screens, link) + x = MAX(x, screen->base.geometry.x + screen->base.geometry.width); + + if (!(screen = malloc(sizeof *screen))) + goto error0; + + screen->base.geometry.x = x; + screen->base.geometry.y = 0; + screen->base.geometry.width = output->preferred_mode->width; + screen->base.geometry.height = output->preferred_mode->height; + screen->base.usable_geometry = screen->base.geometry; + wl_signal_init(&screen->base.event_signal); + wl_list_init(&screen->outputs); + wl_list_insert(&INTERNAL(screen)->outputs, &output->link); + + swc.manager->new_screen(&screen->base); + + return screen; + + error0: + return NULL; +} + +void swc_screen_destroy(struct swc_screen_internal * screen) +{ + struct swc_output * output, * next; + + wl_list_for_each_safe(output, next, &screen->outputs, link) + swc_output_destroy(output); + free(screen); +} + diff --git a/libswc/screen.h b/libswc/screen.h @@ -0,0 +1,56 @@ +/* swc: libswc/screen.h + * + * Copyright (c) 2013, 2014 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SWC_SCREEN_H +#define SWC_SCREEN_H + +#include "swc.h" + +#include <wayland-util.h> + +struct swc_output; + +struct swc_screen_internal +{ + struct swc_screen base; + + uint8_t id; + + struct wl_list outputs; + struct wl_list modifiers; + struct wl_list link; +}; + +bool swc_screens_initialize(); +void swc_screens_finalize(); + +struct swc_screen_internal * swc_screen_new(uint32_t crtc, + struct swc_output * output); +void swc_screen_destroy(struct swc_screen_internal * screen); +static inline uint32_t swc_screen_mask(struct swc_screen_internal * screen) +{ + return 1 << screen->id; +} + +#endif + diff --git a/libswc/surface.c b/libswc/surface.c @@ -383,7 +383,7 @@ struct swc_surface * swc_surface_new(struct wl_client * client, return NULL; /* Initialize the surface. */ - surface->outputs = 0; + surface->screens = 0; surface->geometry.x = 0; surface->geometry.y = 0; surface->geometry.width = 0; diff --git a/libswc/surface.h b/libswc/surface.h @@ -90,7 +90,7 @@ struct swc_surface struct wl_listener view_listener; void * view_state; - uint32_t outputs; + uint32_t screens; struct swc_rectangle geometry; struct wl_signal event_signal; diff --git a/libswc/swc.c b/libswc/swc.c @@ -28,11 +28,12 @@ #include "drm.h" #include "internal.h" #include "keyboard.h" -#include "output.h" #include "pointer.h" +#include "screen.h" #include "seat.h" #include "shell.h" #include "shm.h" +#include "util.h" #include "window.h" #ifdef ENABLE_XWAYLAND # include "xserver.h" @@ -57,7 +58,8 @@ struct swc swc = { static void setup_compositor() { pixman_region32_t pointer_region; - struct swc_output * output; + struct swc_screen_internal * screen; + struct swc_rectangle * geometry; wl_list_insert(&swc.seat->keyboard->handlers, &swc.bindings->keyboard_handler->link); @@ -68,12 +70,12 @@ static void setup_compositor() /* Calculate pointer region */ pixman_region32_init(&pointer_region); - wl_list_for_each(output, &compositor.outputs, link) + wl_list_for_each(screen, &swc.screens, link) { + geometry = &screen->base.geometry; pixman_region32_union_rect(&pointer_region, &pointer_region, - output->geometry.x, output->geometry.y, - output->geometry.width, - output->geometry.height); + geometry->x, geometry->y, + geometry->width, geometry->height); } swc_pointer_set_region(swc.seat->pointer, &pointer_region); @@ -108,10 +110,16 @@ bool swc_initialize(struct wl_display * display, goto error2; } + if (!swc_screens_initialize()) + { + ERROR("Could not initialize screens\n"); + goto error3; + } + if (!swc_compositor_initialize(&compositor, display, swc.event_loop)) { ERROR("Could not initialize compositor\n"); - goto error3; + goto error4; } swc_compositor_add_globals(&compositor, display); @@ -119,32 +127,32 @@ bool swc_initialize(struct wl_display * display, if (!swc_data_device_manager_initialize()) { ERROR("Could not initialize data device manager\n"); - goto error4; + goto error5; } if (!swc_seat_initialize()) { ERROR("Could not initialize seat\n"); - goto error5; + goto error6; } if (!swc_bindings_initialize()) { ERROR("Could not initialize bindings\n"); - goto error6; + goto error7; } if (!swc_shell_initialize()) { ERROR("Could not initialize shell\n"); - goto error7; + goto error8; } #ifdef ENABLE_XWAYLAND if (!swc_xserver_initialize()) { ERROR("Could not initialize xwayland\n"); - goto error8; + goto error9; } #endif @@ -152,16 +160,18 @@ bool swc_initialize(struct wl_display * display, return true; - error8: + error9: swc_shell_finalize(); - error7: + error8: swc_bindings_finalize(); - error6: + error7: swc_seat_finalize(); - error5: + error6: swc_data_device_manager_finalize(); - error4: + error5: swc_compositor_finish(&compositor); + error4: + swc_screens_finalize(); error3: swc_shm_finalize(); error2: @@ -183,6 +193,7 @@ void swc_finalize() swc_seat_finalize(); swc_data_device_manager_finalize(); swc_compositor_finish(&compositor); + swc_screens_finalize(); swc_shm_finalize(); swc_drm_finalize(); udev_unref(swc.udev); diff --git a/libswc/swc.h b/libswc/swc.h @@ -134,12 +134,25 @@ void swc_window_set_border(struct swc_window * window, enum { /** - * Sent when either the total_geometry or usable_geometry of the screen has + * Sent when the screen is about to be destroyed. + * + * After this event is sent, the screen is not longer valid. + */ + SWC_SCREEN_DESTROYED, + + /** + * Sent when the total area of the screen is changed. + */ + SWC_SCREEN_GEOMETRY_CHANGED, + + /** + * Sent when the geometry of the screen available for laying out windows is * changed. * - * The data member of this event points to the rectangle which changed. + * Display servers should respond to this event by making sure all visible + * windows are within this area. */ - SWC_SCREEN_GEOMETRY_CHANGED + SWC_SCREEN_USABLE_GEOMETRY_CHANGED }; struct swc_screen @@ -149,7 +162,7 @@ struct swc_screen /** * The total area of the screen. */ - struct swc_rectangle total_geometry; + struct swc_rectangle geometry; /** * The area of the screen available for placing windows.