main shrub/neuswc / libswc / compositor.c
   1/* swc: libswc/compositor.c
   2 *
   3 * Copyright (c) 2013-2020 Michael Forney
   4 *
   5 * Based in part upon compositor.c from weston, which is:
   6 *
   7 *     Copyright © 2010-2011 Intel Corporation
   8 *     Copyright © 2008-2011 Kristian Høgsberg
   9 *     Copyright © 2012 Collabora, Ltd.
  10 *
  11 * Permission is hereby granted, free of charge, to any person obtaining a copy
  12 * of this software and associated documentation files (the "Software"), to deal
  13 * in the Software without restriction, including without limitation the rights
  14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15 * copies of the Software, and to permit persons to whom the Software is
  16 * furnished to do so, subject to the following conditions:
  17 *
  18 * The above copyright notice and this permission notice shall be included in
  19 * all copies or substantial portions of the Software.
  20 *
  21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  27 * SOFTWARE.
  28 */
  29
  30#include "compositor.h"
  31#include "backend.h"
  32#include "data_device_manager.h"
  33#include "decor.h"
  34#ifdef ENABLE_DRM
  35#include "drm.h"
  36#endif
  37#include "event.h"
  38#include "internal.h"
  39#include "launch.h"
  40#include "output.h"
  41#include "pointer.h"
  42#include "region.h"
  43#include "screen.h"
  44#include "seat.h"
  45#include "shm.h"
  46#include "subsurface.h"
  47#include "surface.h"
  48#include "swc.h"
  49#include "util.h"
  50#include "view.h"
  51#include "window.h"
  52
  53#include <assert.h>
  54#include <errno.h>
  55#include <limits.h>
  56#include <stdio.h>
  57#include <stdlib.h>
  58#ifdef ENABLE_DRM
  59#include <wld/drm.h>
  60#endif
  61#include <wld/wld.h>
  62#include <xkbcommon/xkbcommon-keysyms.h>
  63
  64#define DEFAULT_BG 0xff000000u
  65
  66static inline int32_t
  67clamp_i32(int64_t v)
  68{
  69	if (v > INT32_MAX) {
  70		return INT32_MAX;
  71	}
  72	if (v < INT32_MIN) {
  73		return INT32_MIN;
  74	}
  75	return (int32_t)v;
  76}
  77
  78static inline uint32_t
  79span_u32(int32_t a, int32_t b)
  80{
  81	int64_t d = (int64_t)b - (int64_t)a;
  82
  83	if (d <= 0) {
  84		return 0;
  85	}
  86	if (d > UINT32_MAX) {
  87		return UINT32_MAX;
  88	}
  89	return (uint32_t)d;
  90}
  91
  92struct target {
  93	struct wld_surface *surface;
  94	struct wld_buffer *next_buffer, *current_buffer;
  95	struct view *view;
  96	struct view_handler view_handler;
  97	uint32_t mask;
  98
  99	struct wl_listener screen_destroy_listener;
 100};
 101
 102static bool
 103handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t x,
 104              wl_fixed_t y);
 105static bool
 106handle_button(struct pointer_handler *handler, uint32_t time,
 107              struct button *button, uint32_t state);
 108static void
 109perform_update(void *data);
 110
 111static struct pointer_handler pointer_handler = {
 112    .motion = handle_motion,
 113    .button = handle_button,
 114};
 115
 116static struct {
 117	struct wl_list views;
 118	pixman_region32_t damage, opaque;
 119	struct wl_listener swc_listener;
 120
 121	/* A mask of screens that have been repainted but are waiting on a page
 122	 * flip. */
 123	uint32_t pending_flips;
 124
 125	/* A mask of screens that are scheduled to be repainted on the next idle. */
 126	uint32_t scheduled_updates;
 127
 128	bool updating;
 129	struct wl_global *global;
 130	bool initialized;
 131
 132	/* zoom level (1.0 = normal, >1 = zoomed in, <1 = zoomed out) */
 133	float zoom;
 134	struct wld_buffer *zoom_buffer;
 135} compositor;
 136
 137static struct {
 138	bool active;
 139	int32_t x, y;
 140	uint32_t width, height;
 141	uint32_t color;
 142	uint32_t border_width;
 143} overlay;
 144
 145struct swc_compositor swc_compositor = {
 146    .pointer_handler = &pointer_handler,
 147};
 148
 149static void
 150handle_screen_destroy(struct wl_listener *listener, void *data)
 151{
 152	struct target *target =
 153	    wl_container_of(listener, target, screen_destroy_listener);
 154
 155	wld_destroy_surface(target->surface);
 156	free(target);
 157}
 158
 159static struct target *
 160target_get(struct screen *screen)
 161{
 162	struct wl_listener *listener =
 163	    wl_signal_get(&screen->destroy_signal, &handle_screen_destroy);
 164	struct target *target;
 165
 166	return listener ? wl_container_of(listener, target, screen_destroy_listener)
 167	                : NULL;
 168}
 169
 170static void
 171handle_screen_frame(struct view_handler *handler, uint32_t time)
 172{
 173	struct target *target = wl_container_of(handler, target, view_handler);
 174	struct compositor_view *view;
 175
 176	compositor.pending_flips &= ~target->mask;
 177
 178	wl_list_for_each(view, &compositor.views, link)
 179	{
 180		if (view->visible && view->base.screens & target->mask) {
 181			view_frame(&view->base, time);
 182		}
 183	}
 184
 185	if (target->current_buffer) {
 186		wld_surface_release(target->surface, target->current_buffer);
 187	}
 188
 189	target->current_buffer = target->next_buffer;
 190
 191	/* If we had scheduled updates that couldn't run because we were waiting on
 192	 * a page flip, run them now. If the compositor is currently updating, then
 193	 * the frame finished immediately, and we can be sure that there are no
 194	 * pending updates. */
 195	if (compositor.scheduled_updates && !compositor.updating) {
 196		perform_update(NULL);
 197	}
 198}
 199
 200static const struct view_handler_impl screen_view_handler = {
 201    .frame = handle_screen_frame,
 202};
 203
 204static int
 205target_swap_buffers(struct target *target)
 206{
 207	target->next_buffer = wld_surface_take(target->surface);
 208	return view_attach(target->view, target->next_buffer);
 209}
 210
 211static struct target *
 212target_new(struct screen *screen)
 213{
 214	struct target *target;
 215	struct swc_rectangle *geom = &screen->base.geometry;
 216
 217	if (!(target = malloc(sizeof(*target)))) {
 218		goto error0;
 219	}
 220
 221	target->surface =
 222	    wld_create_surface(swc.backend->context, geom->width, geom->height,
 223	                       WLD_FORMAT_XRGB8888,
 224#ifdef ENABLE_DRM
 225	                       WLD_DRM_FLAG_SCANOUT
 226#else
 227	                       WLD_FLAG_MAP
 228#endif
 229	    );
 230
 231	if (!target->surface) {
 232		goto error1;
 233	}
 234
 235	target->view = &screen->planes.primary.view;
 236	target->view_handler.impl = &screen_view_handler;
 237	wl_list_insert(&target->view->handlers, &target->view_handler.link);
 238	target->current_buffer = NULL;
 239	target->mask = screen_mask(screen);
 240
 241	target->screen_destroy_listener.notify = &handle_screen_destroy;
 242	wl_signal_add(&screen->destroy_signal, &target->screen_destroy_listener);
 243
 244	return target;
 245
 246error1:
 247	free(target);
 248error0:
 249	return NULL;
 250}
 251
 252/* Rendering {{{ */
 253
 254/* check the client's window buffer is opaque */
 255static bool
 256view_buffer_is_opaque(struct compositor_view *view)
 257{
 258	const struct swc_rectangle *geom = &view->base.geometry;
 259	struct wld_buffer *buffer = view->base.buffer;
 260	uint32_t x1, y1, width, height;
 261
 262	if (view->buffer_opaque_valid) {
 263		return view->buffer_opaque;
 264	}
 265
 266	view->buffer_opaque_valid = true;
 267	view->buffer_opaque = false;
 268	if (!buffer || buffer->format != WLD_FORMAT_ARGB8888) {
 269		return false;
 270	}
 271
 272	if (view->window) {
 273		if (view->buffer_offset_x < 0 || view->buffer_offset_y < 0) {
 274			return false;
 275		}
 276		x1 = (uint32_t)view->buffer_offset_x;
 277		y1 = (uint32_t)view->buffer_offset_y;
 278		width = geom->width;
 279		height = geom->height;
 280	} else {
 281		x1 = 0;
 282		y1 = 0;
 283		width = buffer->width;
 284		height = buffer->height;
 285	}
 286
 287	if (x1 > buffer->width || y1 > buffer->height ||
 288	    width > buffer->width - x1 || height > buffer->height - y1 ||
 289	    !wld_map(buffer)) {
 290		return false;
 291	}
 292
 293	view->buffer_opaque = true;
 294	for (uint32_t y = 0; y < height && view->buffer_opaque; ++y) {
 295		const uint8_t *row = (const uint8_t *)buffer->map +
 296		                     (size_t)(y1 + y) * buffer->pitch +
 297		                     (size_t)x1 * 4;
 298
 299		for (uint32_t x = 0; x < width; ++x) {
 300			uint32_t pixel;
 301
 302			memcpy(&pixel, row + (size_t)x * 4, sizeof(pixel));
 303			if ((pixel >> 24) != 0xff) {
 304				view->buffer_opaque = false;
 305				break;
 306			}
 307		}
 308	}
 309	wld_unmap(buffer);
 310
 311	return view->buffer_opaque;
 312}
 313
 314static void
 315repaint_view(struct target *target, struct compositor_view *view,
 316             pixman_region32_t *damage)
 317{
 318	pixman_region32_t geom_region, buffer_region, border_region, view_damage,
 319	    buffer_damage, border_damage;
 320	const struct swc_rectangle *geom = &view->base.geometry,
 321	                           *target_geom = &target->view->geometry;
 322	int32_t buf_x, buf_y;
 323	uint32_t buf_w, buf_h;
 324	int64_t total_border;
 325
 326	if (!view->base.buffer) {
 327		return;
 328	}
 329
 330	buf_w = view->base.buffer->width;
 331	buf_h = view->base.buffer->height;
 332	buf_x = geom->x - view->buffer_offset_x;
 333	buf_y = geom->y - view->buffer_offset_y;
 334
 335	total_border =
 336	    (int64_t)view->border.outwidth + (int64_t)view->border.inwidth;
 337	pixman_region32_init_rect(&geom_region, geom->x, geom->y, geom->width,
 338	                          geom->height);
 339	if (view->window) {
 340		pixman_region32_init_rect(&buffer_region, geom->x, geom->y, geom->width,
 341		                          geom->height);
 342	} else {
 343		pixman_region32_init_rect(&buffer_region, buf_x, buf_y, buf_w, buf_h);
 344	}
 345	pixman_region32_init_rect(&border_region,
 346	                          geom->x - (int32_t)total_border,
 347	                          geom->y - (int32_t)total_border,
 348	                          geom->width + (uint32_t)(2 * total_border),
 349	                          geom->height + (uint32_t)(2 * total_border));
 350	pixman_region32_subtract(&border_region, &border_region, &geom_region);
 351	pixman_region32_init_with_extents(&view_damage, &view->extents);
 352	pixman_region32_init(&buffer_damage);
 353	pixman_region32_init(&border_damage);
 354
 355	pixman_region32_intersect(&view_damage, &view_damage, damage);
 356	pixman_region32_subtract(&view_damage, &view_damage, &view->clip);
 357	pixman_region32_intersect(&border_damage, &view_damage, &border_region);
 358	pixman_region32_intersect(&buffer_damage, &view_damage, &buffer_region);
 359
 360	if (pixman_region32_not_empty(&buffer_damage)) {
 361		pixman_region32_translate(&buffer_damage,
 362		                          -geom->x + view->buffer_offset_x,
 363		                          -geom->y + view->buffer_offset_y);
 364		if (view->buffer->format == WLD_FORMAT_ARGB8888) {
 365			pixman_region32_t opaque_damage, blend_damage;
 366
 367			/* keep pixels that we know are opaque on the accelerated path; only
 368			 * pixels which might have alpha need blending. */
 369			pixman_region32_init(&opaque_damage);
 370			pixman_region32_intersect(&opaque_damage, &buffer_damage,
 371			                          &view->surface->state.opaque);
 372			pixman_region32_init(&blend_damage);
 373			pixman_region32_subtract(&blend_damage, &buffer_damage,
 374			                         &opaque_damage);
 375
 376			if (!pixman_region32_not_empty(&blend_damage) ||
 377			    view_buffer_is_opaque(view)) {
 378				wld_copy_region(swc.backend->renderer, view->buffer,
 379				                buf_x - target_geom->x,
 380				                buf_y - target_geom->y, &buffer_damage);
 381			} else {
 382				wld_copy_region(swc.backend->renderer, view->buffer,
 383				                buf_x - target_geom->x,
 384				                buf_y - target_geom->y, &opaque_damage);
 385				wld_blend_region(swc.backend->renderer, view->buffer,
 386				                 buf_x - target_geom->x,
 387				                 buf_y - target_geom->y, &blend_damage);
 388			}
 389
 390			pixman_region32_fini(&blend_damage);
 391			pixman_region32_fini(&opaque_damage);
 392		} else {
 393			wld_copy_region(swc.backend->renderer, view->buffer,
 394			                buf_x - target_geom->x, buf_y - target_geom->y,
 395			                &buffer_damage);
 396		}
 397	}
 398
 399	pixman_region32_fini(&view_damage);
 400	pixman_region32_fini(&buffer_damage);
 401
 402	pixman_region32_t in_rect;
 403	pixman_region32_init_rect(&in_rect,
 404	                          geom->x - view->border.inwidth,
 405	                          geom->y - view->border.inwidth,
 406	                          geom->width + (2 * view->border.inwidth),
 407	                          geom->height + (2 * view->border.inwidth));
 408
 409	pixman_region32_t out_border;
 410	pixman_region32_init(&out_border);
 411	pixman_region32_subtract(&out_border, &border_damage, &in_rect);
 412
 413	pixman_region32_t in_border;
 414	pixman_region32_init(&in_border);
 415	pixman_region32_subtract(&in_border, &in_rect, &geom_region);
 416	pixman_region32_intersect(&in_border, &in_border, &border_damage);
 417
 418	pixman_region32_fini(&geom_region);
 419	pixman_region32_fini(&buffer_region);
 420	pixman_region32_fini(&border_region);
 421
 422	/* Draw border */
 423	if (view->border.outwidth > 0 && pixman_region32_not_empty(&out_border)) {
 424		pixman_region32_translate(&out_border, -target_geom->x,
 425		                          -target_geom->y);
 426		wld_fill_region(swc.backend->renderer, view->border.outcolor, &out_border);
 427	}
 428
 429	if (view->border.inwidth > 0 && pixman_region32_not_empty(&in_border)) {
 430		pixman_region32_translate(&in_border, -target_geom->x, -target_geom->y);
 431		wld_fill_region(swc.backend->renderer, view->border.incolor, &in_border);
 432	}
 433
 434	pixman_region32_fini(&border_damage);
 435	pixman_region32_fini(&in_rect);
 436	pixman_region32_fini(&out_border);
 437	pixman_region32_fini(&in_border);
 438
 439	if ((view->decor.top || view->decor.right || view->decor.bottom ||
 440	     view->decor.left)) {
 441		decor_repaint(swc.backend->renderer, target_geom, view, damage);
 442	}
 443}
 444
 445static void
 446draw_overlays(struct wld_renderer *renderer, const struct swc_rectangle *target_geom)
 447{
 448	int32_t tx = (int32_t)target_geom->width;
 449	int32_t ty = (int32_t)target_geom->height;
 450
 451/* draw box as 4 rectangles with wld */
 452#define CLAMP_LOW(v, lo) ((v) < (lo) ? (lo) : (v))
 453#define CLAMP_HIGH(v, hi) ((v) > (hi) ? (hi) : (v))
 454#define DRAW_CLIPPED(rx, ry, rw, rh, clr)                                     \
 455	do {                                                                       \
 456		int32_t _x1 = CLAMP_LOW((rx), 0);                                      \
 457		int32_t _y1 = CLAMP_LOW((ry), 0);                                      \
 458		int32_t _x2 = CLAMP_HIGH((rx) + (int32_t)(rw), tx);                    \
 459		int32_t _y2 = CLAMP_HIGH((ry) + (int32_t)(rh), ty);                    \
 460		if (_x2 > _x1 && _y2 > _y1)                                            \
 461			wld_fill_rectangle(renderer, (clr), _x1, _y1,                      \
 462			                   (uint32_t)(_x2 - _x1), (uint32_t)(_y2 - _y1)); \
 463	} while (0)
 464
 465	if (overlay.active && overlay.border_width > 0) {
 466		int32_t x = overlay.x - target_geom->x;
 467		int32_t y = overlay.y - target_geom->y;
 468		uint32_t w = overlay.width, h = overlay.height,
 469		         bw = overlay.border_width;
 470
 471		if (w > 0 && h > 0) {
 472			if (bw > w) {
 473				bw = w;
 474			}
 475			if (bw > h) {
 476				bw = h;
 477			}
 478
 479			DRAW_CLIPPED(x, y, (int32_t)w, (int32_t)bw, overlay.color);
 480			DRAW_CLIPPED(x, y + (int32_t)h - (int32_t)bw, (int32_t)w,
 481			             (int32_t)bw, overlay.color);
 482			DRAW_CLIPPED(x, y, (int32_t)bw, (int32_t)h, overlay.color);
 483			DRAW_CLIPPED(x + (int32_t)w - (int32_t)bw, y, (int32_t)bw,
 484			             (int32_t)h, overlay.color);
 485		}
 486	}
 487
 488#undef DRAW_CLIPPED
 489#undef CLAMP_HIGH
 490#undef CLAMP_LOW
 491}
 492
 493static void
 494renderer_repaint(struct target *target, pixman_region32_t *damage,
 495                 pixman_region32_t *base_damage, struct wl_list *views,
 496                 struct screen *screen)
 497{
 498	struct compositor_view *view;
 499	const struct swc_rectangle *target_geom = &target->view->geometry;
 500
 501	DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n",
 502	      target->view->geometry.x, target->view->geometry.y,
 503	      target->view->geometry.width, target->view->geometry.height);
 504
 505	wld_set_target_surface(swc.backend->renderer, target->surface);
 506
 507	if (pixman_region32_not_empty(base_damage)) {
 508		pixman_region32_translate(base_damage, -target->view->geometry.x,
 509		                          -target->view->geometry.y);
 510		wld_fill_region(swc.backend->renderer, DEFAULT_BG,
 511		                base_damage);
 512	}
 513
 514	wl_list_for_each_reverse(view, views, link)
 515	{
 516		if (view->visible && view->base.screens & target->mask) {
 517			repaint_view(target, view, damage);
 518		}
 519	}
 520
 521	draw_overlays(swc.backend->renderer, target_geom);
 522
 523	wld_flush(swc.backend->renderer);
 524}
 525
 526static int
 527renderer_attach(struct compositor_view *view, struct wld_buffer *client_buffer)
 528{
 529	struct wld_buffer *buffer;
 530	uint32_t proxy_width, proxy_height;
 531	bool was_proxy = view->buffer != view->base.buffer;
 532	bool needs_proxy =
 533	    client_buffer && !(wld_capabilities(swc.backend->renderer, client_buffer) &
 534	                       WLD_CAPABILITY_READ);
 535	bool proxy_incompatible =
 536	    view->buffer && client_buffer &&
 537	    (view->buffer->format != client_buffer->format ||
 538	     view->buffer->width < client_buffer->width ||
 539	     view->buffer->height < client_buffer->height);
 540
 541	if (client_buffer) {
 542		/* Create a proxy buffer if necessary (for example a hardware buffer
 543		 * backing a SHM buffer). */
 544		if (needs_proxy) {
 545			if (!was_proxy || proxy_incompatible) {
 546				DEBUG("Creating a proxy buffer\n");
 547				proxy_width = client_buffer->width;
 548				proxy_height = client_buffer->height;
 549				if (proxy_width <= UINT32_MAX - 255) {
 550					proxy_width = (proxy_width + 255) & ~255U;
 551				}
 552				if (proxy_height <= UINT32_MAX - 255) {
 553					proxy_height = (proxy_height + 255) & ~255U;
 554				}
 555				buffer = wld_create_buffer(
 556				    swc.backend->context, proxy_width, proxy_height,
 557				    client_buffer->format, WLD_FLAG_MAP);
 558
 559				if (!buffer) {
 560					return -ENOMEM;
 561				}
 562			} else {
 563				/* Otherwise we can keep the original proxy buffer. */
 564				buffer = view->buffer;
 565			}
 566		} else {
 567			buffer = client_buffer;
 568		}
 569	} else {
 570		buffer = NULL;
 571	}
 572
 573	/* If we no longer need a proxy buffer, or the original buffer is of a
 574	 * different size, destroy the old proxy image. */
 575	if (view->buffer &&
 576	    ((!needs_proxy && was_proxy) ||
 577	     (needs_proxy && was_proxy && proxy_incompatible))) {
 578		wld_buffer_unreference(view->buffer);
 579	}
 580
 581	view->buffer = buffer;
 582	view->buffer_opaque_valid = false;
 583
 584	return 0;
 585}
 586
 587static void
 588renderer_flush_view(struct compositor_view *view)
 589{
 590	if (view->buffer == view->base.buffer) {
 591		return;
 592	}
 593
 594	wld_set_target_buffer(swc.shm->renderer, view->buffer);
 595	wld_copy_region(swc.shm->renderer, view->base.buffer, 0, 0,
 596	                &view->surface->state.damage);
 597	wld_flush(swc.shm->renderer);
 598}
 599
 600/* }}} */
 601
 602/* Surface Views {{{ */
 603
 604/**
 605 * Adds the region below a view to the compositor's damaged region.
 606 */
 607static void
 608damage_below_view(struct compositor_view *view)
 609{
 610	pixman_region32_t damage_below;
 611
 612	pixman_region32_init_with_extents(&damage_below, &view->extents);
 613	pixman_region32_union(&compositor.damage, &compositor.damage,
 614	                      &damage_below);
 615	pixman_region32_fini(&damage_below);
 616}
 617
 618/**
 619 * Completely damages the surface and its border.
 620 */
 621static void
 622damage_view(struct compositor_view *view)
 623{
 624	damage_below_view(view);
 625	view->border.damaged_border1 = true;
 626	view->border.damaged_border2 = true;
 627}
 628
 629static void
 630update_extents(struct compositor_view *view)
 631{
 632	int64_t total_border =
 633	    (int64_t)view->border.outwidth + (int64_t)view->border.inwidth;
 634	int64_t geom_x = view->base.geometry.x;
 635	int64_t geom_y = view->base.geometry.y;
 636	int64_t geom_w = view->base.geometry.width;
 637	int64_t geom_h = view->base.geometry.height;
 638
 639	int64_t border_x1 = geom_x - total_border;
 640	int64_t border_y1 = geom_y - total_border;
 641	int64_t border_x2 = geom_x + geom_w + total_border;
 642	int64_t border_y2 = geom_y + geom_h + total_border;
 643	int64_t decor_x1 = geom_x - (int64_t)view->decor.left;
 644	int64_t decor_y1 = geom_y - (int64_t)view->decor.top;
 645	int64_t decor_x2 = geom_x + geom_w + (int64_t)view->decor.right;
 646	int64_t decor_y2 = geom_y + geom_h + (int64_t)view->decor.bottom;
 647
 648	int64_t buffer_x1 = geom_x - view->buffer_offset_x;
 649	int64_t buffer_y1 = geom_y - view->buffer_offset_y;
 650	int64_t buffer_x2 =
 651	    buffer_x1 +
 652	    (view->base.buffer ? view->base.buffer->width : (uint32_t)geom_w);
 653	int64_t buffer_y2 =
 654	    buffer_y1 +
 655	    (view->base.buffer ? view->base.buffer->height : (uint32_t)geom_h);
 656
 657	view->extents.x1 = clamp_i32(MIN(MIN(border_x1, decor_x1), buffer_x1));
 658	view->extents.y1 = clamp_i32(MIN(MIN(border_y1, decor_y1), buffer_y1));
 659	view->extents.x2 = clamp_i32(MAX(MAX(border_x2, decor_x2), buffer_x2));
 660	view->extents.y2 = clamp_i32(MAX(MAX(border_y2, decor_y2), buffer_y2));
 661
 662	if (view->extents.x2 < view->extents.x1) {
 663		view->extents.x2 = view->extents.x1;
 664	}
 665	if (view->extents.y2 < view->extents.y1) {
 666		view->extents.y2 = view->extents.y1;
 667	}
 668
 669	/* Damage border. */
 670	view->border.damaged_border1 = true;
 671	view->border.damaged_border2 = true;
 672	view->decor.damaged = true;
 673}
 674
 675static void
 676schedule_updates(uint32_t screens)
 677{
 678	if (compositor.scheduled_updates == 0) {
 679		wl_event_loop_add_idle(swc.event_loop, &perform_update, NULL);
 680	}
 681
 682	if (screens == -1) {
 683		struct screen *screen;
 684
 685		screens = 0;
 686		wl_list_for_each(screen, &swc.screens, link) screens |=
 687		    screen_mask(screen);
 688	}
 689
 690	/* when zoomed, force full screen damage since actual area differs from
 691	 * world coords */
 692	if (compositor.zoom != 1.0f) {
 693		struct screen *screen;
 694		wl_list_for_each(screen, &swc.screens, link)
 695		{
 696			pixman_region32_union_rect(
 697			    &compositor.damage, &compositor.damage, screen->base.geometry.x,
 698			    screen->base.geometry.y, screen->base.geometry.width,
 699			    screen->base.geometry.height);
 700			screens |= screen_mask(screen);
 701		}
 702	}
 703
 704	compositor.scheduled_updates |= screens;
 705}
 706
 707void
 708compositor_damage_all(void)
 709{
 710	struct screen *screen;
 711
 712	if (!compositor.initialized) {
 713		return;
 714	}
 715
 716	wl_list_for_each(screen, &swc.screens, link)
 717	{
 718		pixman_region32_union_rect(
 719		    &compositor.damage, &compositor.damage, screen->base.geometry.x,
 720		    screen->base.geometry.y, screen->base.geometry.width,
 721		    screen->base.geometry.height);
 722	}
 723
 724	schedule_updates(-1);
 725}
 726
 727static void
 728overlay_damage_region(int32_t x, int32_t y, uint32_t width, uint32_t height,
 729                      uint32_t border_width)
 730{
 731	(void)border_width;
 732	pixman_region32_union_rect(&compositor.damage, &compositor.damage, x, y,
 733	                           width, height);
 734}
 735
 736EXPORT void
 737swc_overlay_set_box(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
 738                    uint32_t color, uint32_t border_width)
 739{
 740	int32_t x = x1 < x2 ? x1 : x2;
 741	int32_t y = y1 < y2 ? y1 : y2;
 742	uint32_t width = (uint32_t)abs(x2 - x1);
 743	uint32_t height = (uint32_t)abs(y2 - y1);
 744
 745	if (border_width == 0) {
 746		border_width = 1;
 747	}
 748
 749	if (overlay.active) {
 750		overlay_damage_region(overlay.x, overlay.y, overlay.width,
 751		                      overlay.height, overlay.border_width);
 752	}
 753
 754	overlay.active = true;
 755	overlay.x = x;
 756	overlay.y = y;
 757	overlay.width = width;
 758	overlay.height = height;
 759	overlay.color = color;
 760	overlay.border_width = border_width;
 761
 762	overlay_damage_region(overlay.x, overlay.y, overlay.width, overlay.height,
 763	                      overlay.border_width);
 764	schedule_updates(-1);
 765}
 766
 767EXPORT void
 768swc_overlay_clear(void)
 769{
 770	if (!overlay.active) {
 771		return;
 772	}
 773
 774	overlay_damage_region(overlay.x, overlay.y, overlay.width, overlay.height,
 775	                      overlay.border_width);
 776	overlay.active = false;
 777	schedule_updates(-1);
 778}
 779
 780EXPORT void
 781swc_set_zoom(float level)
 782{
 783	if (level < 0.1f) {
 784		level = 0.1f;
 785	}
 786	if (level > 10.0f) {
 787		level = 10.0f;
 788	}
 789
 790	if (compositor.zoom != level) {
 791		compositor.zoom = level;
 792		if (level == 1.0f) {
 793			if (compositor.zoom_buffer) {
 794				wld_buffer_unreference(compositor.zoom_buffer);
 795				compositor.zoom_buffer = NULL;
 796			}
 797		}
 798		/* damage entire screen to force full repaint */
 799		schedule_updates(-1);
 800	}
 801}
 802
 803EXPORT float
 804swc_get_zoom(void)
 805{
 806	return compositor.zoom;
 807}
 808
 809static pixman_format_code_t
 810wld_to_pixman_format(enum wld_format format)
 811{
 812	switch (format) {
 813	case WLD_FORMAT_XRGB8888:
 814		return PIXMAN_x8r8g8b8;
 815	case WLD_FORMAT_ARGB8888:
 816		return PIXMAN_a8r8g8b8;
 817	default:
 818		return PIXMAN_x8r8g8b8;
 819	}
 820}
 821
 822static struct wld_buffer *
 823zoom_buffer_for_screen(struct screen *screen)
 824{
 825	uint32_t width = screen->base.geometry.width;
 826	uint32_t height = screen->base.geometry.height;
 827
 828	if (compositor.zoom_buffer &&
 829	    (compositor.zoom_buffer->width != width ||
 830	     compositor.zoom_buffer->height != height ||
 831	     compositor.zoom_buffer->format != WLD_FORMAT_ARGB8888)) {
 832		wld_buffer_unreference(compositor.zoom_buffer);
 833		compositor.zoom_buffer = NULL;
 834	}
 835
 836	if (!compositor.zoom_buffer) {
 837		compositor.zoom_buffer =
 838		    wld_create_buffer(swc.shm->context, width, height,
 839		                      WLD_FORMAT_ARGB8888, WLD_FLAG_MAP);
 840		if (!compositor.zoom_buffer) {
 841			return NULL;
 842		}
 843	}
 844
 845	wld_buffer_reference(compositor.zoom_buffer);
 846	return compositor.zoom_buffer;
 847}
 848
 849/* render zoomed view to shm      wallpaper unscaled, windows scaled */
 850static struct wld_buffer *
 851render_zoomed_to_shm(struct screen *screen, float zoom)
 852{
 853	uint32_t width = screen->base.geometry.width;
 854	uint32_t height = screen->base.geometry.height;
 855	int32_t screen_x = screen->base.geometry.x;
 856	int32_t screen_y = screen->base.geometry.y;
 857	int32_t cx = screen_x + width / 2;
 858	int32_t cy = screen_y + height / 2;
 859	struct compositor_view *view;
 860	struct wld_buffer *buffer = zoom_buffer_for_screen(screen);
 861	if (!buffer) {
 862		return NULL;
 863	}
 864
 865	if (!wld_set_target_buffer(swc.shm->renderer, buffer)) {
 866		wld_buffer_unreference(buffer);
 867		return NULL;
 868	}
 869
 870	pixman_region32_t full;
 871	pixman_region32_init_rect(&full, 0, 0, width, height);
 872	wld_fill_region(swc.shm->renderer, DEFAULT_BG, &full);
 873	pixman_region32_fini(&full);
 874	wld_flush(swc.shm->renderer);
 875
 876	if (!wld_map(buffer)) {
 877		wld_buffer_unreference(buffer);
 878		return NULL;
 879	}
 880
 881	pixman_image_t *dst_img = pixman_image_create_bits(
 882	    wld_to_pixman_format(buffer->format), buffer->width, buffer->height,
 883	    buffer->map, buffer->pitch);
 884
 885	if (!dst_img) {
 886		wld_unmap(buffer);
 887		wld_buffer_unreference(buffer);
 888		return NULL;
 889	}
 890
 891	/* render each view with scaling */
 892	wl_list_for_each_reverse(view, &compositor.views, link)
 893	{
 894		struct wld_buffer *src = view->buffer;
 895		const struct swc_rectangle *geom = &view->base.geometry;
 896
 897		if (!src) {
 898			continue;
 899		}
 900
 901		if (!(wld_capabilities(swc.shm->renderer, src) & WLD_CAPABILITY_READ)) {
 902			src = view->base.buffer;
 903		}
 904		if (!src) {
 905			continue;
 906		}
 907
 908		/* maths     zoom position and size */
 909		float zoomed_x, zoomed_y, zoomed_w, zoomed_h;
 910		float border_out, border_in, total_border;
 911
 912		if (view->always_top) {
 913			zoomed_x = geom->x - screen_x;
 914			zoomed_y = geom->y - screen_y;
 915			zoomed_w = geom->width;
 916			zoomed_h = geom->height;
 917
 918			border_out = view->border.outwidth;
 919			border_in = view->border.inwidth;
 920		} else {
 921			zoomed_x = (geom->x - cx) * zoom + width / 2.0f;
 922			zoomed_y = (geom->y - cy) * zoom + height / 2.0f;
 923			zoomed_w = geom->width * zoom;
 924			zoomed_h = geom->height * zoom;
 925
 926			border_out = view->border.outwidth * zoom;
 927			border_in = view->border.inwidth * zoom;
 928		}
 929
 930		total_border = border_out + border_in;
 931
 932		if (zoomed_x + zoomed_w + total_border < 0 ||
 933		    zoomed_x - total_border >= (int32_t)width ||
 934		    zoomed_y + zoomed_h + total_border < 0 ||
 935		    zoomed_y - total_border >= (int32_t)height) {
 936			continue;
 937		}
 938
 939		if (view->border.outwidth > 0 && border_out >= 1) {
 940			int32_t bx = (int32_t)(zoomed_x - total_border);
 941			int32_t by = (int32_t)(zoomed_y - total_border);
 942			int32_t bw = (int32_t)(zoomed_w + 2 * total_border);
 943			int32_t bh = (int32_t)(zoomed_h + 2 * total_border);
 944			int32_t bo = (int32_t)border_out;
 945
 946			pixman_color_t color = {
 947			    .red = ((view->border.outcolor >> 16) & 0xff) * 257,
 948			    .green = ((view->border.outcolor >> 8) & 0xff) * 257,
 949			    .blue = (view->border.outcolor & 0xff) * 257,
 950			    .alpha = 0xffff};
 951			pixman_image_t *fill = pixman_image_create_solid_fill(&color);
 952			if (fill) {
 953				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 954				                         0, 0, 0, bx, by, bw, bo);
 955				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 956				                         0, 0, 0, bx, by + bh - bo, bw, bo);
 957				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 958				                         0, 0, 0, bx, by + bo, bo, bh - 2 * bo);
 959				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 960				                         0, 0, 0, bx + bw - bo, by + bo, bo,
 961				                         bh - 2 * bo);
 962				pixman_image_unref(fill);
 963			}
 964		}
 965
 966		if (view->border.inwidth > 0 && border_in >= 1) {
 967			int32_t bx = (int32_t)(zoomed_x - border_in);
 968			int32_t by = (int32_t)(zoomed_y - border_in);
 969			int32_t bw = (int32_t)(zoomed_w + 2 * border_in);
 970			int32_t bh = (int32_t)(zoomed_h + 2 * border_in);
 971			int32_t bi = (int32_t)border_in;
 972
 973			pixman_color_t color = {
 974			    .red = ((view->border.incolor >> 16) & 0xff) * 257,
 975			    .green = ((view->border.incolor >> 8) & 0xff) * 257,
 976			    .blue = (view->border.incolor & 0xff) * 257,
 977			    .alpha = 0xffff};
 978			pixman_image_t *fill = pixman_image_create_solid_fill(&color);
 979			if (fill) {
 980				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 981				                         0, 0, 0, bx, by, bw, bi);
 982				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 983				                         0, 0, 0, bx, by + bh - bi, bw, bi);
 984				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 985				                         0, 0, 0, bx, by + bi, bi, bh - 2 * bi);
 986				pixman_image_composite32(PIXMAN_OP_OVER, fill, NULL, dst_img, 0,
 987				                         0, 0, 0, bx + bw - bi, by + bi, bi,
 988				                         bh - 2 * bi);
 989				pixman_image_unref(fill);
 990			}
 991		}
 992
 993		if (!wld_map(src)) {
 994			continue;
 995		}
 996
 997		pixman_image_t *src_img = pixman_image_create_bits(
 998		    wld_to_pixman_format(src->format), src->width, src->height,
 999		    src->map, src->pitch);
1000
1001		if (src_img) {
1002			if (!view->always_top) {
1003				pixman_transform_t transform;
1004				pixman_transform_init_identity(&transform);
1005				pixman_fixed_t scale = pixman_double_to_fixed(1.0 / zoom);
1006				pixman_transform_scale(&transform, NULL, scale, scale);
1007				pixman_image_set_transform(src_img, &transform);
1008				pixman_image_set_filter(src_img, PIXMAN_FILTER_BILINEAR, NULL,
1009				                        0);
1010			}
1011
1012			pixman_image_composite32(PIXMAN_OP_OVER, src_img, NULL, dst_img, 0,
1013			                         0, 0, 0, (int32_t)zoomed_x,
1014			                         (int32_t)zoomed_y, (int32_t)(zoomed_w + 1),
1015			                         (int32_t)(zoomed_h + 1));
1016
1017			pixman_image_unref(src_img);
1018		}
1019
1020		wld_unmap(src);
1021	}
1022
1023	pixman_image_unref(dst_img);
1024	wld_unmap(buffer);
1025
1026	return buffer;
1027}
1028
1029static bool
1030update(struct view *base)
1031{
1032	struct compositor_view *view = (void *)base;
1033
1034	if (!swc.active || !view->visible) {
1035		return false;
1036	}
1037
1038	schedule_updates(view->base.screens);
1039
1040	return true;
1041}
1042
1043static int
1044attach(struct view *base, struct wld_buffer *buffer)
1045{
1046	struct compositor_view *view = (void *)base;
1047	struct surface *surface = view->surface;
1048	pixman_box32_t old_extents;
1049	pixman_region32_t old, new, both;
1050	uint32_t new_width = buffer ? buffer->width : 0;
1051	uint32_t new_height = buffer ? buffer->height : 0;
1052	int ret;
1053
1054	if ((ret = renderer_attach(view, buffer)) < 0) {
1055		return ret;
1056	}
1057
1058	/* Schedule updates on the screens the view was previously
1059	 * visible on. */
1060	update(&view->base);
1061
1062	view->buffer_offset_x = 0;
1063	view->buffer_offset_y = 0;
1064	if (surface && surface->has_window_geometry && buffer) {
1065		if (surface->window_width > 0 && surface->window_height > 0) {
1066			new_width = (uint32_t)surface->window_width;
1067			new_height = (uint32_t)surface->window_height;
1068			view->buffer_offset_x = surface->window_x;
1069			view->buffer_offset_y = surface->window_y;
1070		}
1071	}
1072
1073	if (view_set_size(&view->base, new_width, new_height)) {
1074		/* The view was resized. */
1075		old_extents = view->extents;
1076		update_extents(view);
1077
1078		if (view->visible) {
1079			/* Damage the region that was newly uncovered or covered. */
1080			pixman_region32_init_with_extents(&old, &old_extents);
1081			pixman_region32_init_with_extents(&new, &view->extents);
1082			pixman_region32_init(&both);
1083			pixman_region32_intersect(&both, &old, &new);
1084			pixman_region32_union(&new, &old, &new);
1085			pixman_region32_subtract(&new, &new, &both);
1086			pixman_region32_union(&compositor.damage, &compositor.damage, &new);
1087			pixman_region32_fini(&old);
1088			pixman_region32_fini(&new);
1089			pixman_region32_fini(&both);
1090
1091			view_update_screens(&view->base);
1092			update(&view->base);
1093		}
1094	}
1095
1096	return 0;
1097}
1098
1099static bool
1100move(struct view *base, int32_t x, int32_t y)
1101{
1102	struct compositor_view *view = (void *)base;
1103
1104	if (view->visible) {
1105		damage_below_view(view);
1106		update(&view->base);
1107	}
1108
1109	if (view_set_position(&view->base, x, y)) {
1110		update_extents(view);
1111
1112		if (view->visible) {
1113			/* Assume worst-case no clipping until we draw the next frame (in
1114			 * case the surface gets moved again before that). */
1115			pixman_region32_clear(&view->clip);
1116
1117			view_update_screens(&view->base);
1118			damage_below_view(view);
1119			update(&view->base);
1120		}
1121	}
1122
1123	return true;
1124}
1125
1126static const struct view_impl view_impl = {
1127    .update = update,
1128    .attach = attach,
1129    .move = move,
1130};
1131
1132static void
1133restack_view_for_layer(struct compositor_view *view, bool raise)
1134{
1135	struct compositor_view *other;
1136	struct wl_list *insert_after = &compositor.views;
1137	bool found_same = false;
1138
1139	wl_list_for_each(other, &compositor.views, link)
1140	{
1141		if (other == view) {
1142			continue;
1143		}
1144
1145		if (other->stack_layer > view->stack_layer) {
1146			insert_after = &other->link;
1147			continue;
1148		}
1149
1150		if (other->stack_layer == view->stack_layer) {
1151			found_same = true;
1152			if (raise) {
1153				insert_after = other->link.prev;
1154			} else {
1155				insert_after = &other->link;
1156			}
1157			break;
1158		}
1159
1160		insert_after = other->link.prev;
1161		break;
1162	}
1163
1164	if (!found_same && !raise && insert_after == &compositor.views) {
1165		insert_after = compositor.views.prev;
1166		if (insert_after == &view->link) {
1167			insert_after = insert_after->prev;
1168		}
1169	}
1170
1171	if (insert_after == &view->link) {
1172		insert_after = insert_after->prev;
1173	}
1174
1175	wl_list_remove(&view->link);
1176	wl_list_insert(insert_after, &view->link);
1177}
1178
1179static struct compositor_view *
1180view_at(int32_t x, int32_t y)
1181{
1182	struct compositor_view *view;
1183	struct swc_rectangle *geom;
1184	struct swc_rectangle buffer_geom;
1185
1186	wl_list_for_each(view, &compositor.views, link)
1187	{
1188		if (!view->visible) {
1189			continue;
1190		}
1191
1192		geom = &view->base.geometry;
1193		if (view->window) {
1194			if (!rectangle_contains_point(geom, x, y)) {
1195				continue;
1196			}
1197		} else if (view->base.buffer) {
1198			buffer_geom.x = geom->x - view->buffer_offset_x;
1199			buffer_geom.y = geom->y - view->buffer_offset_y;
1200			buffer_geom.width = view->base.buffer->width;
1201			buffer_geom.height = view->base.buffer->height;
1202			if (!rectangle_contains_point(&buffer_geom, x, y)) {
1203				continue;
1204			}
1205		} else if (!rectangle_contains_point(geom, x, y)) {
1206			continue;
1207		}
1208
1209		if (pixman_region32_contains_point(&view->surface->state.input,
1210		                                   x - geom->x + view->buffer_offset_x,
1211		                                   y - geom->y + view->buffer_offset_y,
1212		                                   NULL)) {
1213			return view;
1214		}
1215	}
1216
1217	return NULL;
1218}
1219
1220static struct compositor_view *
1221window_view(struct compositor_view *view)
1222{
1223	while (view && !view->window && view->parent && view->parent != view) {
1224		view = view->parent;
1225	}
1226	return (view && view->window) ? view : NULL;
1227}
1228
1229void
1230raise_window(struct compositor_view *view)
1231{
1232	struct compositor_view *other, *top_window;
1233	struct wl_list *insert_after;
1234	uint32_t screens;
1235
1236	view = window_view(view);
1237	if (!view || !view->visible) {
1238		return;
1239	}
1240
1241	top_window = NULL;
1242	insert_after = &compositor.views;
1243	wl_list_for_each(other, &compositor.views, link)
1244	{
1245		if (other == view) {
1246			continue;
1247		}
1248
1249		if (!other->visible) {
1250			continue;
1251		}
1252
1253		if (other->stack_layer > STACK_LAYER_NORMAL ||
1254		    other->always_top) {
1255			insert_after = &other->link;
1256			continue;
1257		}
1258
1259		if (other->stack_layer < STACK_LAYER_NORMAL) {
1260			break;
1261		}
1262
1263		if (other->window) {
1264			top_window = other;
1265			break;
1266		}
1267		insert_after = &other->link;
1268	}
1269
1270	if (view == top_window) {
1271		return;
1272	}
1273
1274	screens = view->base.screens;
1275
1276	wl_list_remove(&view->link);
1277	wl_list_insert(insert_after, &view->link);
1278
1279	view->border.damaged_border1 = true;
1280	pixman_region32_union_rect(&compositor.damage, &compositor.damage,
1281	                           view->extents.x1, view->extents.y1,
1282	                           span_u32(view->extents.x1, view->extents.x2),
1283	                           span_u32(view->extents.y1, view->extents.y2));
1284	schedule_updates(screens);
1285}
1286
1287void
1288raise_window_top(struct compositor_view *view)
1289{
1290	view->stack_layer = STACK_LAYER_OVERLAY;
1291	restack_view_for_layer(view, true);
1292	damage_view(view);
1293	schedule_updates(view->base.screens);
1294}
1295
1296void
1297compositor_view_set_stack_layer(struct compositor_view *view, uint32_t layer,
1298	                            bool raise)
1299{
1300	if (view->stack_layer == layer) {
1301		if (raise) {
1302			restack_view_for_layer(view, true);
1303			damage_view(view);
1304			schedule_updates(view->base.screens);
1305		}
1306		return;
1307	}
1308
1309	damage_view(view);
1310	view->stack_layer = layer;
1311	restack_view_for_layer(view, raise);
1312	damage_view(view);
1313	schedule_updates(view->base.screens);
1314}
1315
1316EXPORT struct swc_window *
1317swc_window_at(int32_t x, int32_t y)
1318{
1319	struct compositor_view *view = window_view(view_at(x, y));
1320
1321	return view ? &view->window->base : NULL;
1322}
1323
1324static struct compositor_view *
1325view_for_window(struct swc_window *base)
1326{
1327	struct window *window;
1328
1329	if (!base) {
1330		return NULL;
1331	}
1332
1333	window = (struct window *)base;
1334	return window->view;
1335}
1336
1337static struct compositor_view *
1338prev_window_view(struct compositor_view *view)
1339{
1340	struct wl_list *link;
1341	struct compositor_view *other;
1342
1343	for (link = view->link.prev; link != &compositor.views; link = link->prev) {
1344		other = wl_container_of(link, other, link);
1345
1346		if (other->visible && other->window) {
1347			return other;
1348		}
1349	}
1350
1351	return NULL;
1352}
1353
1354static struct compositor_view *
1355next_window_view(struct compositor_view *view)
1356{
1357	struct wl_list *link;
1358	struct compositor_view *other;
1359
1360	for (link = view->link.next; link != &compositor.views; link = link->next) {
1361		other = wl_container_of(link, other, link);
1362
1363		if (other->visible && other->window) {
1364			return other;
1365		}
1366	}
1367
1368	return NULL;
1369}
1370
1371static void
1372damage_views(struct compositor_view *a, struct compositor_view *b)
1373{
1374	uint32_t screens = a->base.screens | (b ? b->base.screens : 0);
1375
1376	a->border.damaged_border1 = true;
1377	a->border.damaged_border2 = true;
1378	pixman_region32_union_rect(&compositor.damage, &compositor.damage,
1379	                           a->extents.x1, a->extents.y1,
1380	                           span_u32(a->extents.x1, a->extents.x2),
1381	                           span_u32(a->extents.y1, a->extents.y2));
1382
1383	if (b) {
1384		b->border.damaged_border1 = true;
1385		b->border.damaged_border2 = true;
1386		pixman_region32_union_rect(&compositor.damage, &compositor.damage,
1387		                           b->extents.x1, b->extents.y1,
1388		                           span_u32(b->extents.x1, b->extents.x2),
1389		                           span_u32(b->extents.y1, b->extents.y2));
1390	}
1391
1392	schedule_updates(screens);
1393}
1394
1395EXPORT void
1396swc_window_stack(struct swc_window *window, int32_t direction)
1397{
1398	struct compositor_view *view = view_for_window(window);
1399	struct compositor_view *other = NULL;
1400
1401	if (!view || !view->visible || direction == 0) {
1402		return;
1403	}
1404
1405	if (direction < 0) {
1406		other = prev_window_view(view);
1407		if (!other) {
1408			return;
1409		}
1410		wl_list_remove(&view->link);
1411		wl_list_insert(other->link.prev, &view->link);
1412	} else {
1413		other = next_window_view(view);
1414		if (!other) {
1415			return;
1416		}
1417		wl_list_remove(&view->link);
1418		wl_list_insert(&other->link, &view->link);
1419	}
1420
1421	damage_views(view, other);
1422}
1423
1424struct compositor_view *
1425compositor_create_view(struct surface *surface)
1426{
1427	struct compositor_view *view;
1428
1429	view = malloc(sizeof(*view));
1430
1431	if (!view) {
1432		return NULL;
1433	}
1434
1435	view_initialize(&view->base, &view_impl);
1436	view->surface = surface;
1437	view->buffer = NULL;
1438	view->buffer_opaque_valid = false;
1439	view->buffer_opaque = false;
1440	view->window = NULL;
1441	view->parent = NULL;
1442	view->buffer_offset_x = 0;
1443	view->buffer_offset_y = 0;
1444	view->visible = false;
1445	view->always_top = false;
1446	view->stack_layer = STACK_LAYER_NORMAL;
1447	view->extents.x1 = 0;
1448	view->extents.y1 = 0;
1449	view->extents.x2 = 0;
1450	view->extents.y2 = 0;
1451	view->border.outwidth = 0;
1452	view->border.outcolor = 0x000000;
1453	view->border.damaged_border1 = false;
1454	view->border.inwidth = 0;
1455	view->border.incolor = 0x000000;
1456	view->border.damaged_border2 = false;
1457	view->decor.color = 0x000000;
1458	view->decor.top = 0;
1459	view->decor.right = 0;
1460	view->decor.bottom = 0;
1461	view->decor.left = 0;
1462	decor_view_initialize(view);
1463	view->decor.damaged = false;
1464	pixman_region32_init(&view->clip);
1465	wl_signal_init(&view->destroy_signal);
1466	surface_set_view(surface, &view->base);
1467	wl_list_insert(&compositor.views, &view->link);
1468
1469	return view;
1470}
1471
1472void
1473compositor_view_destroy(struct compositor_view *view)
1474{
1475	wl_signal_emit(&view->destroy_signal, NULL);
1476	compositor_view_hide(view);
1477	surface_set_view(view->surface, NULL);
1478	view_finalize(&view->base);
1479	decor_view_finalize(view);
1480	pixman_region32_fini(&view->clip);
1481	wl_list_remove(&view->link);
1482	free(view);
1483}
1484
1485struct compositor_view *
1486compositor_view(struct view *view)
1487{
1488	return view->impl == &view_impl ? (struct compositor_view *)view : NULL;
1489}
1490
1491void
1492compositor_view_set_parent(struct compositor_view *view,
1493                           struct compositor_view *parent)
1494{
1495	view->parent = parent;
1496
1497	if (!parent) {
1498		return;
1499	}
1500
1501	if (parent->visible) {
1502		compositor_view_show(view);
1503	} else {
1504		compositor_view_hide(view);
1505	}
1506}
1507
1508void
1509compositor_view_restack(struct compositor_view *view,
1510                        struct compositor_view *sibling, bool above)
1511{
1512	if (!view || !sibling || view == sibling) {
1513		return;
1514	}
1515
1516	if (above) {
1517		if (view->link.next == &sibling->link) {
1518			return;
1519		}
1520		wl_list_remove(&view->link);
1521		wl_list_insert(sibling->link.prev, &view->link);
1522	} else {
1523		if (view->link.prev == &sibling->link) {
1524			return;
1525		}
1526		wl_list_remove(&view->link);
1527		wl_list_insert(&sibling->link, &view->link);
1528	}
1529
1530	damage_views(view, sibling);
1531}
1532
1533void
1534compositor_view_show(struct compositor_view *view)
1535{
1536	struct compositor_view *other;
1537	struct subsurface *subsurface;
1538
1539	if (view->visible) {
1540		return;
1541	}
1542
1543	subsurface = view->surface ? view->surface->subsurface : NULL;
1544	if (subsurface) {
1545		if (!subsurface->added || !view->surface->state.buffer) {
1546			return;
1547		}
1548	}
1549
1550	view->visible = true;
1551	view_update_screens(&view->base);
1552
1553	if (view->window) {
1554		raise_window(view);
1555	}
1556
1557	/* Assume worst-case no clipping until we draw the next frame (in case the
1558	 * surface gets moved before that. */
1559	pixman_region32_clear(&view->clip);
1560	damage_view(view);
1561	update(&view->base);
1562
1563	wl_list_for_each(other, &compositor.views, link)
1564	{
1565		if (other->parent == view) {
1566			compositor_view_show(other);
1567		}
1568	}
1569}
1570
1571void
1572compositor_view_hide(struct compositor_view *view)
1573{
1574	struct compositor_view *other;
1575
1576	if (!view->visible) {
1577		return;
1578	}
1579
1580	/* Update all the screens the view was on. */
1581	update(&view->base);
1582	damage_below_view(view);
1583
1584	view_set_screens(&view->base, 0);
1585	view->visible = false;
1586
1587	wl_list_for_each(other, &compositor.views, link)
1588	{
1589		if (other->parent == view) {
1590			compositor_view_hide(other);
1591		}
1592	}
1593}
1594
1595void
1596compositor_view_set_border_width(struct compositor_view *view,
1597                                 uint32_t outwidth, uint32_t inwidth)
1598{
1599	if (view->border.outwidth == outwidth && view->border.inwidth == inwidth) {
1600		return;
1601	}
1602
1603	view->border.outwidth = outwidth;
1604	view->border.damaged_border1 = true;
1605
1606	view->border.inwidth = inwidth;
1607	view->border.damaged_border2 = true;
1608
1609	/* XXX: Damage above surface for transparent surfaces? */
1610
1611	update_extents(view);
1612	update(&view->base);
1613}
1614
1615void
1616compositor_view_set_border_color(struct compositor_view *view,
1617                                 uint32_t outcolor, uint32_t incolor)
1618{
1619	if (view->border.outcolor == outcolor && view->border.incolor == incolor) {
1620		return;
1621	}
1622
1623	view->border.outcolor = outcolor;
1624	view->border.damaged_border1 = true;
1625
1626	view->border.incolor = incolor;
1627	view->border.damaged_border2 = true;
1628
1629	/* XXX: Damage above surface for transparent surfaces? */
1630
1631	update(&view->base);
1632}
1633
1634void
1635compositor_view_set_decor(struct compositor_view *view,
1636                            const struct swc_decor *decor)
1637{
1638	/* decor_view_set() could shrink or remove the decoration, so wedamage the old
1639	 * extents before they are replaced */
1640	if (view->visible) {
1641		damage_below_view(view);
1642	}
1643
1644	decor_view_set(view, decor);
1645	update_extents(view);
1646	update(&view->base);
1647}
1648
1649void
1650compositor_view_damage_decor(struct compositor_view *view)
1651{
1652	if (!view->decor.top && !view->decor.right && !view->decor.bottom &&
1653	    !view->decor.left) {
1654		return;
1655	}
1656
1657	decor_view_damage(view);
1658	update(&view->base);
1659}
1660
1661/* }}} */
1662
1663static void
1664calculate_damage(void)
1665{
1666	struct compositor_view *view;
1667	struct swc_rectangle *geom;
1668	pixman_region32_t surface_opaque, *surface_damage;
1669
1670	pixman_region32_clear(&compositor.opaque);
1671	pixman_region32_init(&surface_opaque);
1672
1673	/* Go through views top-down to calculate clipping regions. */
1674	wl_list_for_each(view, &compositor.views, link)
1675	{
1676		if (!view->visible) {
1677			continue;
1678		}
1679
1680		geom = &view->base.geometry;
1681		pixman_region32_t view_region;
1682
1683		pixman_region32_init_rect(&view_region, geom->x, geom->y, geom->width,
1684		                          geom->height);
1685
1686		/* Clip the surface by the opaque region covering it. */
1687		pixman_region32_copy(&view->clip, &compositor.opaque);
1688
1689		/* Translate the opaque region to global coordinates. */
1690		pixman_region32_copy(&surface_opaque, &view->surface->state.opaque);
1691		pixman_region32_translate(&surface_opaque,
1692		                          geom->x - view->buffer_offset_x,
1693		                          geom->y - view->buffer_offset_y);
1694		pixman_region32_intersect(&surface_opaque, &surface_opaque,
1695		                          &view_region);
1696
1697		/* Add the surface's opaque region to the accumulated opaque region. */
1698		pixman_region32_union(&compositor.opaque, &compositor.opaque,
1699		                      &surface_opaque);
1700
1701		surface_damage = &view->surface->state.damage;
1702
1703		if (pixman_region32_not_empty(surface_damage)) {
1704			view->buffer_opaque_valid = false;
1705			renderer_flush_view(view);
1706
1707			/* Translate surface damage to global coordinates. */
1708			pixman_region32_translate(surface_damage,
1709			                          geom->x - view->buffer_offset_x,
1710			                          geom->y - view->buffer_offset_y);
1711
1712			/* Add the surface damage to the compositor damage. */
1713			pixman_region32_union(&compositor.damage, &compositor.damage,
1714			                      surface_damage);
1715			pixman_region32_clear(surface_damage);
1716		}
1717
1718		/* redraw entire thingy if border or decor changed */
1719		if (view->border.damaged_border1 || view->border.damaged_border2 ||
1720		    view->decor.damaged) {
1721			pixman_region32_t border_region;
1722
1723			pixman_region32_init_with_extents(&border_region, &view->extents);
1724
1725			pixman_region32_subtract(&border_region, &border_region,
1726			                         &view_region);
1727
1728			pixman_region32_union(&compositor.damage, &compositor.damage,
1729			                      &border_region);
1730
1731			pixman_region32_fini(&border_region);
1732
1733			view->border.damaged_border1 = false;
1734			view->border.damaged_border2 = false;
1735			view->decor.damaged = false;
1736		}
1737
1738		pixman_region32_fini(&view_region);
1739	}
1740
1741	pixman_region32_fini(&surface_opaque);
1742}
1743
1744static void
1745update_screen(struct screen *screen)
1746{
1747	struct target *target;
1748	const struct swc_rectangle *geom = &screen->base.geometry;
1749	pixman_region32_t damage, *total_damage;
1750
1751	if (!(compositor.scheduled_updates & screen_mask(screen))) {
1752		return;
1753	}
1754
1755	if (!(target = target_get(screen))) {
1756		return;
1757	}
1758
1759	pixman_region32_init(&damage);
1760	pixman_region32_intersect_rect(&damage, &compositor.damage, geom->x,
1761	                               geom->y, geom->width, geom->height);
1762	pixman_region32_translate(&damage, -geom->x, -geom->y);
1763	total_damage = wld_surface_damage(target->surface, &damage);
1764
1765	/* Don't repaint the screen if it is waiting for a page flip. */
1766	if (compositor.pending_flips & screen_mask(screen)) {
1767		pixman_region32_fini(&damage);
1768		return;
1769	}
1770
1771	/* check if zoom */
1772	if (compositor.zoom != 1.0f) {
1773		pixman_region32_fini(&damage);
1774
1775		struct wld_buffer *zoomed =
1776		    render_zoomed_to_shm(screen, compositor.zoom);
1777		if (!zoomed) {
1778			return;
1779		}
1780
1781		pixman_region32_t full;
1782		pixman_region32_init_rect(&full, 0, 0, geom->width, geom->height);
1783		wld_set_target_surface(swc.backend->renderer, target->surface);
1784		wld_copy_region(swc.backend->renderer, zoomed, 0, 0, &full);
1785		wld_flush(swc.backend->renderer);
1786		pixman_region32_fini(&full);
1787
1788		wld_buffer_unreference(zoomed);
1789	} else {
1790		pixman_region32_t base_damage;
1791		pixman_region32_copy(&damage, total_damage);
1792		pixman_region32_translate(&damage, geom->x, geom->y);
1793		pixman_region32_init(&base_damage);
1794		pixman_region32_subtract(&base_damage, &damage, &compositor.opaque);
1795		renderer_repaint(target, &damage, &base_damage, &compositor.views,
1796		                 screen);
1797		pixman_region32_fini(&damage);
1798		pixman_region32_fini(&base_damage);
1799	}
1800
1801	switch (target_swap_buffers(target)) {
1802	case -EACCES:
1803		/* If we get an EACCES, it is because this session is being deactivated,
1804		 * but we haven't yet received the deactivate signal from swc-launch. */
1805		swc_deactivate();
1806		break;
1807	case 0:
1808		compositor.pending_flips |= screen_mask(screen);
1809		break;
1810	}
1811}
1812
1813static void
1814perform_update(void *data)
1815{
1816	struct screen *screen;
1817	uint32_t updates = compositor.scheduled_updates & ~compositor.pending_flips;
1818
1819	if (!swc.active || !updates) {
1820		return;
1821	}
1822
1823	DEBUG("Performing update\n");
1824
1825	compositor.updating = true;
1826	calculate_damage();
1827
1828	wl_list_for_each(screen, &swc.screens, link) update_screen(screen);
1829
1830	/* XXX: Should assert that all damage was covered by some output */
1831	pixman_region32_clear(&compositor.damage);
1832	compositor.scheduled_updates &= ~updates;
1833	compositor.updating = false;
1834}
1835
1836bool
1837handle_motion(struct pointer_handler *handler, uint32_t time, wl_fixed_t fx,
1838              wl_fixed_t fy)
1839{
1840	int32_t x = wl_fixed_to_int(fx), y = wl_fixed_to_int(fy);
1841
1842	/* If buttons are pressed, don't change pointer focus. */
1843	if (swc.seat->pointer->buttons.size > 0) {
1844		return false;
1845	}
1846
1847	struct compositor_view *view = view_at(x, y);
1848
1849	pointer_set_focus(swc.seat->pointer, view);
1850
1851	return false;
1852}
1853
1854static bool
1855handle_button(struct pointer_handler *handler, uint32_t time,
1856              struct button *button, uint32_t state)
1857{
1858	(void)handler;
1859	(void)time;
1860	(void)button;
1861
1862	if (state != WL_POINTER_BUTTON_STATE_PRESSED) {
1863		return false;
1864	}
1865
1866	int32_t x = wl_fixed_to_int(swc.seat->pointer->x);
1867	int32_t y = wl_fixed_to_int(swc.seat->pointer->y);
1868	struct compositor_view *view = view_at(x, y);
1869
1870	pointer_set_focus(swc.seat->pointer, view);
1871	raise_window(view);
1872
1873	return false;
1874}
1875
1876static void
1877handle_terminate(void *data, uint32_t time, uint32_t value, uint32_t state)
1878{
1879	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1880		wl_display_terminate(swc.display);
1881	}
1882}
1883
1884static void
1885handle_switch_vt(void *data, uint32_t time, uint32_t value, uint32_t state)
1886{
1887	uint8_t vt = value - XKB_KEY_XF86Switch_VT_1 + 1;
1888
1889	if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1890		launch_activate_vt(vt);
1891	}
1892}
1893
1894static void
1895handle_swc_event(struct wl_listener *listener, void *data)
1896{
1897	struct event *event = data;
1898
1899	switch (event->type) {
1900	case SWC_EVENT_ACTIVATED:
1901		schedule_updates(-1);
1902		break;
1903	case SWC_EVENT_DEACTIVATED:
1904		compositor.scheduled_updates = 0;
1905		break;
1906	}
1907}
1908
1909static void
1910create_surface(struct wl_client *client, struct wl_resource *resource,
1911               uint32_t id)
1912{
1913	struct surface *surface;
1914
1915	/* Initialize surface. */
1916	surface = surface_new(client, wl_resource_get_version(resource), id);
1917
1918	if (!surface) {
1919		wl_resource_post_no_memory(resource);
1920		return;
1921	}
1922
1923	wl_signal_emit(&swc_compositor.signal.new_surface, surface);
1924}
1925
1926static void
1927create_region(struct wl_client *client, struct wl_resource *resource,
1928              uint32_t id)
1929{
1930	if (!region_new(client, wl_resource_get_version(resource), id)) {
1931		wl_resource_post_no_memory(resource);
1932	}
1933}
1934
1935static const struct wl_compositor_interface compositor_impl = {
1936    .create_surface = create_surface,
1937    .create_region = create_region,
1938};
1939
1940static void
1941bind_compositor(struct wl_client *client, void *data, uint32_t version,
1942                uint32_t id)
1943{
1944	struct wl_resource *resource;
1945
1946	resource =
1947	    wl_resource_create(client, &wl_compositor_interface, version, id);
1948	if (!resource) {
1949		wl_client_post_no_memory(client);
1950		return;
1951	}
1952	wl_resource_set_implementation(resource, &compositor_impl, NULL, NULL);
1953}
1954
1955bool
1956compositor_initialize(void)
1957{
1958	struct screen *screen;
1959	uint32_t keysym;
1960
1961	compositor.global = wl_global_create(swc.display, &wl_compositor_interface,
1962	                                     4, NULL, &bind_compositor);
1963
1964	if (!compositor.global) {
1965		return false;
1966	}
1967
1968	compositor.scheduled_updates = 0;
1969	compositor.pending_flips = 0;
1970	compositor.updating = false;
1971	compositor.zoom = 1.0f;
1972	compositor.zoom_buffer = NULL;
1973	if (!decor_initialize()) {
1974		return false;
1975	}
1976	pixman_region32_init(&compositor.damage);
1977	pixman_region32_init(&compositor.opaque);
1978	wl_list_init(&compositor.views);
1979	wl_signal_init(&swc_compositor.signal.new_surface);
1980	compositor.swc_listener.notify = &handle_swc_event;
1981	wl_signal_add(&swc.event_signal, &compositor.swc_listener);
1982
1983	wl_list_for_each(screen, &swc.screens, link) target_new(screen);
1984	if (swc.active) {
1985		schedule_updates(-1);
1986	}
1987
1988	swc_add_binding(SWC_BINDING_KEY, SWC_MOD_CTRL | SWC_MOD_ALT,
1989	                XKB_KEY_BackSpace, &handle_terminate, NULL);
1990
1991	for (keysym = XKB_KEY_XF86Switch_VT_1; keysym <= XKB_KEY_XF86Switch_VT_12;
1992	     ++keysym) {
1993		swc_add_binding(SWC_BINDING_KEY, SWC_MOD_ANY, keysym, &handle_switch_vt,
1994		                NULL);
1995	}
1996
1997	compositor.initialized = true;
1998
1999	return true;
2000}
2001
2002void
2003compositor_finalize(void)
2004{
2005	compositor.initialized = false;
2006
2007	if (compositor.zoom_buffer) {
2008		wld_buffer_unreference(compositor.zoom_buffer);
2009		compositor.zoom_buffer = NULL;
2010	}
2011	decor_finalize();
2012	pixman_region32_fini(&compositor.damage);
2013	pixman_region32_fini(&compositor.opaque);
2014	wl_global_destroy(compositor.global);
2015}
2016
2017struct wld_buffer *
2018compositor_get_buffer(struct screen *screen)
2019{
2020	struct target *target = target_get(screen);
2021	if (!target) {
2022		return NULL;
2023	}
2024	return target->current_buffer;
2025}
2026
2027struct wld_buffer *
2028compositor_render_to_shm(struct screen *screen)
2029{
2030	if (compositor.zoom != 1.0f) {
2031		return render_zoomed_to_shm(screen, compositor.zoom);
2032	}
2033
2034	uint32_t width = screen->base.geometry.width;
2035	uint32_t height = screen->base.geometry.height;
2036	struct wld_buffer *buffer;
2037	struct compositor_view *view;
2038	pixman_region32_t region;
2039	pixman_region32_t damage;
2040	uint32_t caps;
2041
2042	/* create shm buf */
2043	buffer = wld_create_buffer(swc.shm->context, width, height,
2044	                           WLD_FORMAT_ARGB8888, WLD_FLAG_MAP);
2045	if (!buffer) {
2046		return NULL;
2047	}
2048
2049	caps = wld_capabilities(swc.shm->renderer, buffer);
2050	if (!(caps & WLD_CAPABILITY_WRITE) ||
2051	    !wld_set_target_buffer(swc.shm->renderer, buffer)) {
2052		wld_buffer_unreference(buffer);
2053		return NULL;
2054	}
2055
2056	/* set region */
2057	pixman_region32_init_rect(&region, 0, 0, width, height);
2058	pixman_region32_init_rect(&damage, screen->base.geometry.x,
2059	                          screen->base.geometry.y, width, height);
2060
2061	/* background */
2062	wld_fill_region(swc.shm->renderer, DEFAULT_BG, &region);
2063
2064	wl_list_for_each_reverse(view, &compositor.views, link)
2065	{
2066		struct wld_buffer *src = view->buffer;
2067
2068		if (!view->visible) {
2069			continue;
2070		}
2071
2072		if (src &&
2073		    !(wld_capabilities(swc.shm->renderer, src) & WLD_CAPABILITY_READ)) {
2074			src = view->base.buffer;
2075		}
2076
2077		if (src &&
2078		    (wld_capabilities(swc.shm->renderer, src) & WLD_CAPABILITY_READ)) {
2079			const struct swc_rectangle *geom = &view->base.geometry;
2080			int32_t src_x = view->window ? view->buffer_offset_x : 0;
2081			int32_t src_y = view->window ? view->buffer_offset_y : 0;
2082			int32_t dst_x = geom->x - src_x - screen->base.geometry.x;
2083			int32_t dst_y = geom->y - src_y - screen->base.geometry.y;
2084			pixman_region32_t source_region;
2085
2086			pixman_region32_init_rect(&source_region, src_x, src_y, geom->width,
2087			                          geom->height);
2088			pixman_region32_intersect_rect(&source_region, &source_region, 0, 0,
2089			                               src->width, src->height);
2090			if (src->format == WLD_FORMAT_ARGB8888) {
2091				wld_blend_region(swc.shm->renderer, src, dst_x, dst_y,
2092				                 &source_region);
2093			} else {
2094				wld_copy_region(swc.shm->renderer, src, dst_x, dst_y,
2095				                &source_region);
2096			}
2097			pixman_region32_fini(&source_region);
2098		}
2099
2100		if ((view->border.outwidth > 0 || view->border.inwidth > 0) &&
2101		    view->base.buffer) {
2102			pixman_region32_t view_region, view_damage, border_damage;
2103			const struct swc_rectangle *geom = &view->base.geometry;
2104			const struct swc_rectangle *target_geom = &screen->base.geometry;
2105
2106			pixman_region32_init_rect(&view_region, geom->x, geom->y,
2107			                          geom->width, geom->height);
2108			pixman_region32_init_with_extents(&view_damage, &view->extents);
2109			pixman_region32_init(&border_damage);
2110
2111			pixman_region32_intersect(&view_damage, &view_damage, &damage);
2112			pixman_region32_subtract(&view_damage, &view_damage, &view->clip);
2113			pixman_region32_subtract(&border_damage, &view_damage,
2114			                         &view_region);
2115
2116			pixman_region32_t in_rect;
2117			pixman_region32_init_rect(&in_rect,
2118			                          geom->x - view->border.inwidth,
2119			                          geom->y - view->border.inwidth,
2120			                          geom->width + (2 * view->border.inwidth),
2121			                          geom->height +
2122			                              (2 * view->border.inwidth));
2123
2124			pixman_region32_t out_border;
2125			pixman_region32_init(&out_border);
2126			pixman_region32_subtract(&out_border, &border_damage, &in_rect);
2127
2128			pixman_region32_t in_border;
2129			pixman_region32_init(&in_border);
2130			pixman_region32_subtract(&in_border, &in_rect, &view_region);
2131			pixman_region32_intersect(&in_border, &in_border, &border_damage);
2132
2133			if (view->border.outwidth > 0 &&
2134			    pixman_region32_not_empty(&out_border)) {
2135				pixman_region32_translate(&out_border, -target_geom->x,
2136				                          -target_geom->y);
2137				wld_fill_region(swc.shm->renderer, view->border.outcolor,
2138				                &out_border);
2139			}
2140
2141			if (view->border.inwidth > 0 &&
2142			    pixman_region32_not_empty(&in_border)) {
2143				pixman_region32_translate(&in_border, -target_geom->x,
2144				                          -target_geom->y);
2145				wld_fill_region(swc.shm->renderer, view->border.incolor,
2146				                &in_border);
2147			}
2148
2149			pixman_region32_fini(&border_damage);
2150			pixman_region32_fini(&view_region);
2151			pixman_region32_fini(&view_damage);
2152			pixman_region32_fini(&in_rect);
2153			pixman_region32_fini(&out_border);
2154			pixman_region32_fini(&in_border);
2155		}
2156
2157		if (view->decor.top || view->decor.right || view->decor.bottom ||
2158		    view->decor.left) {
2159			const struct swc_rectangle *target_geom = &screen->base.geometry;
2160			decor_repaint(swc.shm->renderer, target_geom, view, &damage);
2161		}
2162	}
2163
2164	draw_overlays(swc.shm->renderer, &screen->base.geometry);
2165
2166	wld_flush(swc.shm->renderer);
2167	pixman_region32_fini(&region);
2168	pixman_region32_fini(&damage);
2169
2170	return buffer;
2171}