compositor-drm.c 203 KB
Newer Older
1
/*
2 3
 * Copyright © 2008-2011 Kristian Høgsberg
 * Copyright © 2011 Intel Corporation
4 5
 * Copyright © 2017, 2018 Collabora, Ltd.
 * Copyright © 2017, 2018 General Electric Company
6
 *
7 8 9 10 11 12 13
 * 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:
14
 *
15 16 17 18 19 20 21 22 23 24 25 26
 * The above copyright notice and this permission notice (including the
 * next paragraph) 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.
27 28
 */

29
#include "config.h"
30

31
#include <errno.h>
32
#include <stdint.h>
33
#include <stdlib.h>
34
#include <ctype.h>
35 36 37
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
38
#include <linux/input.h>
39
#include <linux/vt.h>
40
#include <assert.h>
41
#include <sys/mman.h>
42
#include <dlfcn.h>
43
#include <time.h>
44

45 46
#include <xf86drm.h>
#include <xf86drmMode.h>
47
#include <drm_fourcc.h>
48

49
#include <gbm.h>
50
#include <libudev.h>
51

52 53
#include "compositor.h"
#include "compositor-drm.h"
54
#include "weston-debug.h"
55
#include "shared/helpers.h"
56
#include "shared/timespec-util.h"
57
#include "gl-renderer.h"
58
#include "weston-egl-ext.h"
59
#include "pixman-renderer.h"
60
#include "pixel-formats.h"
61
#include "libbacklight.h"
62
#include "libinput-seat.h"
63
#include "launcher-util.h"
64
#include "vaapi-recorder.h"
65
#include "presentation-time-server-protocol.h"
66
#include "linux-dmabuf.h"
67
#include "linux-dmabuf-unstable-v1-server-protocol.h"
68

69 70 71 72
#ifndef DRM_CLIENT_CAP_ASPECT_RATIO
#define DRM_CLIENT_CAP_ASPECT_RATIO	4
#endif

73 74 75 76
#ifndef GBM_BO_USE_CURSOR
#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
#endif

77 78 79 80
#ifndef GBM_BO_USE_LINEAR
#define GBM_BO_USE_LINEAR (1 << 4)
#endif

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
/**
 * A small wrapper to print information into the 'drm-backend' debug scope.
 *
 * The following conventions are used to print variables:
 *
 *  - fixed uint32_t values, including Weston object IDs such as weston_output
 *    IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats:
 *      "%lu (0x%lx)" (unsigned long) value, (unsigned long) value
 *
 *  - fixed uint64_t values, such as DRM property values (including object IDs
 *    when used as a value):
 *      "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value
 *
 *  - non-fixed-width signed int:
 *      "%d" value
 *
 *  - non-fixed-width unsigned int:
 *      "%u (0x%x)" value, value
 *
 *  - non-fixed-width unsigned long:
 *      "%lu (0x%lx)" value, value
 *
 * Either the integer or hexadecimal forms may be omitted if it is known that
 * one representation is not useful (e.g. width/height in hex are rarely what
 * you want).
 *
 * This is to avoid implicit widening or narrowing when we use fixed-size
 * types: uint32_t can be resolved by either unsigned int or unsigned long
 * on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t
 * being unsigned long long on a 32-bit system and unsigned long on a 64-bit
 * system. To avoid confusing side effects, we explicitly cast to the widest
 * possible type and use a matching format specifier.
 */
#define drm_debug(b, ...) \
	weston_debug_scope_printf((b)->debug, __VA_ARGS__)

117
#define MAX_CLONED_CONNECTORS 4
118

119 120 121 122 123 124 125 126 127
/**
 * aspect ratio info taken from the drmModeModeInfo flag bits 19-22,
 * which should be used to fill the aspect ratio field in weston_mode.
 */
#define DRM_MODE_FLAG_PIC_AR_BITS_POS	19
#ifndef DRM_MODE_FLAG_PIC_AR_MASK
#define DRM_MODE_FLAG_PIC_AR_MASK (0xF << DRM_MODE_FLAG_PIC_AR_BITS_POS)
#endif

128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/**
 * Represents the values of an enum-type KMS property
 */
struct drm_property_enum_info {
	const char *name; /**< name as string (static, not freed) */
	bool valid; /**< true if value is supported; ignore if false */
	uint64_t value; /**< raw value */
};

/**
 * Holds information on a DRM property, including its ID and the enum
 * values it holds.
 *
 * DRM properties are allocated dynamically, and maintained as DRM objects
 * within the normal object ID space; they thus do not have a stable ID
 * to refer to. This includes enum values, which must be referred to by
 * integer values, but these are not stable.
 *
 * drm_property_info allows a cache to be maintained where Weston can use
 * enum values internally to refer to properties, with the mapping to DRM
 * ID values being maintained internally.
 */
struct drm_property_info {
	const char *name; /**< name as string (static, not freed) */
	uint32_t prop_id; /**< KMS property object ID */
	unsigned int num_enum_values; /**< number of enum values */
	struct drm_property_enum_info *enum_values; /**< array of enum values */
};

157 158 159 160 161
/**
 * List of properties attached to DRM planes
 */
enum wdrm_plane_property {
	WDRM_PLANE_TYPE = 0,
162 163 164 165 166 167 168 169 170 171
	WDRM_PLANE_SRC_X,
	WDRM_PLANE_SRC_Y,
	WDRM_PLANE_SRC_W,
	WDRM_PLANE_SRC_H,
	WDRM_PLANE_CRTC_X,
	WDRM_PLANE_CRTC_Y,
	WDRM_PLANE_CRTC_W,
	WDRM_PLANE_CRTC_H,
	WDRM_PLANE_FB_ID,
	WDRM_PLANE_CRTC_ID,
172
	WDRM_PLANE_IN_FORMATS,
173 174 175 176 177 178 179 180 181 182 183 184 185
	WDRM_PLANE__COUNT
};

/**
 * Possible values for the WDRM_PLANE_TYPE property.
 */
enum wdrm_plane_type {
	WDRM_PLANE_TYPE_PRIMARY = 0,
	WDRM_PLANE_TYPE_CURSOR,
	WDRM_PLANE_TYPE_OVERLAY,
	WDRM_PLANE_TYPE__COUNT
};

186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
static struct drm_property_enum_info plane_type_enums[] = {
	[WDRM_PLANE_TYPE_PRIMARY] = {
		.name = "Primary",
	},
	[WDRM_PLANE_TYPE_OVERLAY] = {
		.name = "Overlay",
	},
	[WDRM_PLANE_TYPE_CURSOR] = {
		.name = "Cursor",
	},
};

static const struct drm_property_info plane_props[] = {
	[WDRM_PLANE_TYPE] = {
		.name = "type",
		.enum_values = plane_type_enums,
		.num_enum_values = WDRM_PLANE_TYPE__COUNT,
	},
	[WDRM_PLANE_SRC_X] = { .name = "SRC_X", },
	[WDRM_PLANE_SRC_Y] = { .name = "SRC_Y", },
	[WDRM_PLANE_SRC_W] = { .name = "SRC_W", },
	[WDRM_PLANE_SRC_H] = { .name = "SRC_H", },
	[WDRM_PLANE_CRTC_X] = { .name = "CRTC_X", },
	[WDRM_PLANE_CRTC_Y] = { .name = "CRTC_Y", },
	[WDRM_PLANE_CRTC_W] = { .name = "CRTC_W", },
	[WDRM_PLANE_CRTC_H] = { .name = "CRTC_H", },
	[WDRM_PLANE_FB_ID] = { .name = "FB_ID", },
	[WDRM_PLANE_CRTC_ID] = { .name = "CRTC_ID", },
214
	[WDRM_PLANE_IN_FORMATS] = { .name = "IN_FORMATS" },
215 216
};

217 218 219 220 221 222
/**
 * List of properties attached to a DRM connector
 */
enum wdrm_connector_property {
	WDRM_CONNECTOR_EDID = 0,
	WDRM_CONNECTOR_DPMS,
223
	WDRM_CONNECTOR_CRTC_ID,
224
	WDRM_CONNECTOR_NON_DESKTOP,
225 226 227
	WDRM_CONNECTOR__COUNT
};

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
enum wdrm_dpms_state {
	WDRM_DPMS_STATE_OFF = 0,
	WDRM_DPMS_STATE_ON,
	WDRM_DPMS_STATE_STANDBY, /* unused */
	WDRM_DPMS_STATE_SUSPEND, /* unused */
	WDRM_DPMS_STATE__COUNT
};

static struct drm_property_enum_info dpms_state_enums[] = {
	[WDRM_DPMS_STATE_OFF] = {
		.name = "Off",
	},
	[WDRM_DPMS_STATE_ON] = {
		.name = "On",
	},
	[WDRM_DPMS_STATE_STANDBY] = {
		.name = "Standby",
	},
	[WDRM_DPMS_STATE_SUSPEND] = {
		.name = "Suspend",
	},
};

251 252
static const struct drm_property_info connector_props[] = {
	[WDRM_CONNECTOR_EDID] = { .name = "EDID" },
253 254 255 256 257
	[WDRM_CONNECTOR_DPMS] = {
		.name = "DPMS",
		.enum_values = dpms_state_enums,
		.num_enum_values = WDRM_DPMS_STATE__COUNT,
	},
258
	[WDRM_CONNECTOR_CRTC_ID] = { .name = "CRTC_ID", },
259
	[WDRM_CONNECTOR_NON_DESKTOP] = { .name = "non-desktop", },
260 261
};

262 263 264 265 266 267 268 269 270
/**
 * List of properties attached to DRM CRTCs
 */
enum wdrm_crtc_property {
	WDRM_CRTC_MODE_ID = 0,
	WDRM_CRTC_ACTIVE,
	WDRM_CRTC__COUNT
};

271 272 273 274 275
static const struct drm_property_info crtc_props[] = {
	[WDRM_CRTC_MODE_ID] = { .name = "MODE_ID", },
	[WDRM_CRTC_ACTIVE] = { .name = "ACTIVE", },
};

276 277 278 279 280 281 282 283 284 285 286 287 288 289
/**
 * Mode for drm_output_state_duplicate.
 */
enum drm_output_state_duplicate_mode {
	DRM_OUTPUT_STATE_CLEAR_PLANES, /**< reset all planes to off */
	DRM_OUTPUT_STATE_PRESERVE_PLANES, /**< preserve plane state */
};

/**
 * Mode for drm_pending_state_apply and co.
 */
enum drm_state_apply_mode {
	DRM_STATE_APPLY_SYNC, /**< state fully processed */
	DRM_STATE_APPLY_ASYNC, /**< state pending event delivery */
290
	DRM_STATE_TEST_ONLY, /**< test if the state can be applied */
291 292
};

293 294 295
struct drm_backend {
	struct weston_backend base;
	struct weston_compositor *compositor;
296 297 298 299

	struct udev *udev;
	struct wl_event_source *drm_source;

300 301 302
	struct udev_monitor *udev_monitor;
	struct wl_event_source *udev_drm_source;

303
	struct {
304
		int id;
305
		int fd;
306
		char *filename;
307
	} drm;
308
	struct gbm_device *gbm;
309
	struct wl_listener session_listener;
310
	uint32_t gbm_format;
311

312 313 314 315
	/* we need these parameters in order to not fail drmModeAddFB2()
	 * due to out of bounds dimensions, and then mistakenly set
	 * sprites_are_broken:
	 */
316 317
	int min_width, max_width;
	int min_height, max_height;
318

319
	struct wl_list plane_list;
320
	int sprites_are_broken;
321
	int sprites_hidden;
322

323 324
	void *repaint_data;

325 326
	bool state_invalid;

327
	/* CRTC IDs not used by any enabled output. */
328 329
	struct wl_array unused_crtcs;

330 331
	int cursors_are_broken;

332
	bool universal_planes;
333
	bool atomic_modeset;
334

335
	int use_pixman;
336
	bool use_pixman_shadow;
337

338
	struct udev_input input;
339

340 341
	int32_t cursor_width;
	int32_t cursor_height;
342

343
	uint32_t pageflip_timeout;
344 345

	bool shutting_down;
346 347

	bool aspect_ratio_supported;
348 349

	struct weston_debug_scope *debug;
350 351
};

352
struct drm_mode {
353
	struct weston_mode base;
354
	drmModeModeInfo mode_info;
355
	uint32_t blob_id;
356 357
};

358 359 360
enum drm_fb_type {
	BUFFER_INVALID = 0, /**< never used */
	BUFFER_CLIENT, /**< directly sourced from client */
361
	BUFFER_DMABUF, /**< imported from linux_dmabuf client */
362 363
	BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
	BUFFER_GBM_SURFACE, /**< internal EGL rendering */
364
	BUFFER_CURSOR, /**< internal cursor buffer */
365 366
};

367
struct drm_fb {
368 369
	enum drm_fb_type type;

370 371
	int refcnt;

372 373 374 375
	uint32_t fb_id, size;
	uint32_t handles[4];
	uint32_t strides[4];
	uint32_t offsets[4];
376
	int num_planes;
377
	const struct pixel_format_info *format;
378
	uint64_t modifier;
379
	int width, height;
380
	int fd;
381
	struct weston_buffer_reference buffer_ref;
382 383 384

	/* Used by gbm fbs */
	struct gbm_bo *bo;
385
	struct gbm_surface *gbm_surface;
386 387 388

	/* Used by dumb fbs */
	void *map;
389 390
};

391 392 393 394 395 396 397
struct drm_edid {
	char eisa_id[13];
	char monitor_name[13];
	char pnp_id[5];
	char serial_number[13];
};

398 399 400 401 402 403 404 405
/**
 * Pending state holds one or more drm_output_state structures, collected from
 * performing repaint. This pending state is transient, and only lives between
 * beginning a repaint group and flushing the results: after flush, each
 * output state will complete and be retired separately.
 */
struct drm_pending_state {
	struct drm_backend *backend;
406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
	struct wl_list output_list;
};

/*
 * Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
 * plus >= 1 each of encoder/connector/plane. Since everything but the planes
 * is currently statically assigned per-output, we mainly use this to track
 * plane state.
 *
 * pending_state is set when the output state is owned by a pending_state,
 * i.e. when it is being constructed and has not yet been applied. When the
 * output state has been applied, the owning pending_state is freed.
 */
struct drm_output_state {
	struct drm_pending_state *pending_state;
	struct drm_output *output;
	struct wl_list link;
423
	enum dpms_enum dpms;
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
	struct wl_list plane_list;
};

/**
 * Plane state holds the dynamic state for a plane: where it is positioned,
 * and which buffer it is currently displaying.
 *
 * The plane state is owned by an output state, except when setting an initial
 * state. See drm_output_state for notes on state object lifetime.
 */
struct drm_plane_state {
	struct drm_plane *plane;
	struct drm_output *output;
	struct drm_output_state *output_state;

	struct drm_fb *fb;

441 442
	struct weston_view *ev; /**< maintained for drm_assign_planes only */

443 444 445 446 447 448 449 450
	int32_t src_x, src_y;
	uint32_t src_w, src_h;
	int32_t dest_x, dest_y;
	uint32_t dest_w, dest_h;

	bool complete;

	struct wl_list link; /* drm_output_state::plane_list */
451 452
};

453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
/**
 * A plane represents one buffer, positioned within a CRTC, and stacked
 * relative to other planes on the same CRTC.
 *
 * Each CRTC has a 'primary plane', which use used to display the classic
 * framebuffer contents, as accessed through the legacy drmModeSetCrtc
 * call (which combines setting the CRTC's actual physical mode, and the
 * properties of the primary plane).
 *
 * The cursor plane also has its own alternate legacy API.
 *
 * Other planes are used opportunistically to display content we do not
 * wish to blit into the primary plane. These non-primary/cursor planes
 * are referred to as 'sprites'.
 */
struct drm_plane {
	struct weston_plane base;

	struct drm_backend *backend;

473 474
	enum wdrm_plane_type type;

475 476 477 478
	uint32_t possible_crtcs;
	uint32_t plane_id;
	uint32_t count_formats;

479 480
	struct drm_property_info props[WDRM_PLANE__COUNT];

481 482
	/* The last state submitted to the kernel for this plane. */
	struct drm_plane_state *state_cur;
483

484
	struct wl_list link;
485

486 487 488 489 490
	struct {
		uint32_t format;
		uint32_t count_modifiers;
		uint64_t *modifiers;
	} formats[];
491 492
};

493 494 495 496
struct drm_head {
	struct weston_head base;
	struct drm_backend *backend;

497 498 499 500 501 502 503
	drmModeConnector *connector;
	uint32_t connector_id;
	struct drm_edid edid;

	/* Holds the properties for the connector */
	struct drm_property_info props_conn[WDRM_CONNECTOR__COUNT];

504
	struct backlight *backlight;
505 506

	drmModeModeInfo inherited_mode;	/**< Original mode on the connector */
507
	uint32_t inherited_crtc_id;	/**< Original CRTC assignment */
508 509
};

510
struct drm_output {
511
	struct weston_output base;
512
	struct drm_backend *backend;
513

514 515
	uint32_t crtc_id; /* object ID to pass to DRM functions */
	int pipe; /* index of CRTC in resource array / bitmasks */
516

517 518
	/* Holds the properties for the CRTC */
	struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
519

520 521
	int vblank_pending;
	int page_flip_pending;
522
	int atomic_complete_pending;
523
	int destroy_pending;
524
	int disable_pending;
525
	int dpms_off_pending;
526

527
	struct drm_fb *gbm_cursor_fb[2];
528
	struct drm_plane *cursor_plane;
529
	struct weston_view *cursor_view;
530
	int current_cursor;
531 532 533

	struct gbm_surface *gbm_surface;
	uint32_t gbm_format;
534
	uint32_t gbm_bo_flags;
535

536 537
	/* Plane being displayed directly on the CRTC */
	struct drm_plane *scanout_plane;
538

539 540 541 542 543 544
	/* The last state submitted to the kernel for this CRTC. */
	struct drm_output_state *state_cur;
	/* The previously-submitted state, where the hardware has not
	 * yet acknowledged completion of state_cur. */
	struct drm_output_state *state_last;

545 546 547 548
	struct drm_fb *dumb[2];
	pixman_image_t *image[2];
	int current_image;
	pixman_region32_t previous_damage;
549 550 551

	struct vaapi_recorder *recorder;
	struct wl_listener recorder_frame_listener;
552 553

	struct wl_event_source *pageflip_timer;
554 555 556 557

	bool virtual;

	submit_frame_cb virtual_submit_frame;
558 559
};

560 561 562 563 564 565 566 567
static const char *const aspect_ratio_as_string[] = {
	[WESTON_MODE_PIC_AR_NONE] = "",
	[WESTON_MODE_PIC_AR_4_3] = " 4:3",
	[WESTON_MODE_PIC_AR_16_9] = " 16:9",
	[WESTON_MODE_PIC_AR_64_27] = " 64:27",
	[WESTON_MODE_PIC_AR_256_135] = " 256:135",
};

568 569
static struct gl_renderer_interface *gl_renderer;

570
static const char default_seat[] = "seat0";
571

572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
static void
wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
{
	uint32_t *pos, *end;

	end = (uint32_t *) ((char *) array->data + array->size);

	wl_array_for_each(pos, array) {
		if (*pos != elm)
			continue;

		array->size -= sizeof(*pos);
		if (pos + 1 == end)
			break;

		memmove(pos, pos + 1, (char *) end -  (char *) (pos + 1));
		break;
	}
}

592 593 594 595 596 597
static inline struct drm_head *
to_drm_head(struct weston_head *base)
{
	return container_of(base, struct drm_head, base);
}

598 599 600 601 602 603 604 605 606 607 608 609
static inline struct drm_output *
to_drm_output(struct weston_output *base)
{
	return container_of(base, struct drm_output, base);
}

static inline struct drm_backend *
to_drm_backend(struct weston_compositor *base)
{
	return container_of(base->backend, struct drm_backend, base);
}

610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
static int
pageflip_timeout(void *data) {
	/*
	 * Our timer just went off, that means we're not receiving drm
	 * page flip events anymore for that output. Let's gracefully exit
	 * weston with a return value so devs can debug what's going on.
	 */
	struct drm_output *output = data;
	struct weston_compositor *compositor = output->base.compositor;

	weston_log("Pageflip timeout reached on output %s, your "
	           "driver is probably buggy!  Exiting.\n",
		   output->base.name);
	weston_compositor_exit_with_code(compositor, EXIT_FAILURE);

	return 0;
}

/* Creates the pageflip timer. Note that it isn't armed by default */
static int
drm_output_pageflip_timer_create(struct drm_output *output)
{
	struct wl_event_loop *loop = NULL;
	struct weston_compositor *ec = output->base.compositor;

	loop = wl_display_get_event_loop(ec->wl_display);
	assert(loop);
	output->pageflip_timer = wl_event_loop_add_timer(loop,
	                                                 pageflip_timeout,
	                                                 output);

	if (output->pageflip_timer == NULL) {
		weston_log("creating drm pageflip timer failed: %m\n");
		return -1;
	}

	return 0;
}

649 650 651 652 653 654
static inline struct drm_mode *
to_drm_mode(struct weston_mode *base)
{
	return container_of(base, struct drm_mode, base);
}

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
/**
 * Get the current value of a KMS property
 *
 * Given a drmModeObjectGetProperties return, as well as the drm_property_info
 * for the target property, return the current value of that property,
 * with an optional default. If the property is a KMS enum type, the return
 * value will be translated into the appropriate internal enum.
 *
 * If the property is not present, the default value will be returned.
 *
 * @param info Internal structure for property to look up
 * @param props Raw KMS properties for the target object
 * @param def Value to return if property is not found
 */
static uint64_t
drm_property_get_value(struct drm_property_info *info,
671
		       const drmModeObjectProperties *props,
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
		       uint64_t def)
{
	unsigned int i;

	if (info->prop_id == 0)
		return def;

	for (i = 0; i < props->count_props; i++) {
		unsigned int j;

		if (props->props[i] != info->prop_id)
			continue;

		/* Simple (non-enum) types can return the value directly */
		if (info->num_enum_values == 0)
			return props->prop_values[i];

		/* Map from raw value to enum value */
		for (j = 0; j < info->num_enum_values; j++) {
			if (!info->enum_values[j].valid)
				continue;
			if (info->enum_values[j].value != props->prop_values[i])
				continue;

			return j;
		}

		/* We don't have a mapping for this enum; return default. */
		break;
	}

	return def;
}

/**
 * Cache DRM property values
 *
 * Update a per-object array of drm_property_info structures, given the
 * DRM properties of the object.
 *
 * Call this every time an object newly appears (note that only connectors
 * can be hotplugged), the first time it is seen, or when its status changes
 * in a way which invalidates the potential property values (currently, the
 * only case for this is connector hotplug).
 *
 * This updates the property IDs and enum values within the drm_property_info
 * array.
 *
 * DRM property enum values are dynamic at runtime; the user must query the
 * property to find out the desired runtime value for a requested string
 * name. Using the 'type' field on planes as an example, there is no single
 * hardcoded constant for primary plane types; instead, the property must be
 * queried at runtime to find the value associated with the string "Primary".
 *
 * This helper queries and caches the enum values, to allow us to use a set
 * of compile-time-constant enums portably across various implementations.
 * The values given in enum_names are searched for, and stored in the
 * same-indexed field of the map array.
 *
 * @param b DRM backend object
 * @param src DRM property info array to source from
 * @param info DRM property info array to copy into
 * @param num_infos Number of entries in the source array
 * @param props DRM object properties for the object
 */
static void
drm_property_info_populate(struct drm_backend *b,
		           const struct drm_property_info *src,
			   struct drm_property_info *info,
			   unsigned int num_infos,
			   drmModeObjectProperties *props)
{
	drmModePropertyRes *prop;
	unsigned i, j;

	for (i = 0; i < num_infos; i++) {
		unsigned int j;

		info[i].name = src[i].name;
		info[i].prop_id = 0;
		info[i].num_enum_values = src[i].num_enum_values;

		if (src[i].num_enum_values == 0)
			continue;

		info[i].enum_values =
			malloc(src[i].num_enum_values *
			       sizeof(*info[i].enum_values));
		assert(info[i].enum_values);
		for (j = 0; j < info[i].num_enum_values; j++) {
			info[i].enum_values[j].name = src[i].enum_values[j].name;
			info[i].enum_values[j].valid = false;
		}
	}

	for (i = 0; i < props->count_props; i++) {
		unsigned int k;

		prop = drmModeGetProperty(b->drm.fd, props->props[i]);
		if (!prop)
			continue;

		for (j = 0; j < num_infos; j++) {
			if (!strcmp(prop->name, info[j].name))
				break;
		}

		/* We don't know/care about this property. */
		if (j == num_infos) {
#ifdef DEBUG
			weston_log("DRM debug: unrecognized property %u '%s'\n",
				   prop->prop_id, prop->name);
#endif
			drmModeFreeProperty(prop);
			continue;
		}

		if (info[j].num_enum_values == 0 &&
		    (prop->flags & DRM_MODE_PROP_ENUM)) {
			weston_log("DRM: expected property %s to not be an"
			           " enum, but it is; ignoring\n", prop->name);
			drmModeFreeProperty(prop);
			continue;
		}

		info[j].prop_id = props->props[i];

		if (info[j].num_enum_values == 0) {
			drmModeFreeProperty(prop);
			continue;
		}

		if (!(prop->flags & DRM_MODE_PROP_ENUM)) {
			weston_log("DRM: expected property %s to be an enum,"
				   " but it is not; ignoring\n", prop->name);
			drmModeFreeProperty(prop);
			info[j].prop_id = 0;
			continue;
		}

		for (k = 0; k < info[j].num_enum_values; k++) {
			int l;

			for (l = 0; l < prop->count_enums; l++) {
				if (!strcmp(prop->enums[l].name,
					    info[j].enum_values[k].name))
					break;
			}

			if (l == prop->count_enums)
				continue;

			info[j].enum_values[k].valid = true;
			info[j].enum_values[k].value = prop->enums[l].value;
		}

		drmModeFreeProperty(prop);
	}

#ifdef DEBUG
	for (i = 0; i < num_infos; i++) {
		if (info[i].prop_id == 0)
			weston_log("DRM warning: property '%s' missing\n",
				   info[i].name);
	}
#endif
}

/**
 * Free DRM property information
 *
843 844 845
 * Frees all memory associated with a DRM property info array and zeroes
 * it out, leaving it usable for a further drm_property_info_update() or
 * drm_property_info_free().
846 847 848 849 850 851 852 853 854 855 856
 *
 * @param info DRM property info array
 * @param num_props Number of entries in array to free
 */
static void
drm_property_info_free(struct drm_property_info *info, int num_props)
{
	int i;

	for (i = 0; i < num_props; i++)
		free(info[i].enum_values);
857 858

	memset(info, 0, sizeof(*info) * num_props);
859 860
}

861
static void
862
drm_output_set_cursor(struct drm_output_state *output_state);
863

864 865 866
static void
drm_output_update_msc(struct drm_output *output, unsigned int seq);

867 868 869
static void
drm_output_destroy(struct weston_output *output_base);

870 871 872
static void
drm_virtual_output_destroy(struct weston_output *output_base);

873 874 875 876 877 878
/**
 * Returns true if the plane can be used on the given output for its current
 * repaint cycle.
 */
static bool
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output)
879
{
880 881
	assert(plane->state_cur);

882 883 884
	if (output->virtual)
		return false;

885 886 887 888 889 890 891 892 893 894
	/* The plane still has a request not yet completed by the kernel. */
	if (!plane->state_cur->complete)
		return false;

	/* The plane is still active on another output. */
	if (plane->state_cur->output && plane->state_cur->output != output)
		return false;

	/* Check whether the plane can be used with this CRTC; possible_crtcs
	 * is a bitmask of CRTC indices (pipe), rather than CRTC object ID. */
895
	return !!(plane->possible_crtcs & (1 << output->pipe));
896 897
}

898 899 900 901 902 903 904 905 906 907 908 909 910
static struct drm_output *
drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id)
{
	struct drm_output *output;

	wl_list_for_each(output, &b->compositor->output_list, base.link) {
		if (output->crtc_id == crtc_id)
			return output;
	}

	return NULL;
}

911 912 913 914 915 916 917 918 919
static struct drm_head *
drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id)
{
	struct weston_head *base;
	struct drm_head *head;

	wl_list_for_each(base,
			 &backend->compositor->head_list, compositor_link) {
		head = to_drm_head(base);
920
		if (head->connector_id == connector_id)
921 922 923 924 925 926
			return head;
	}

	return NULL;
}

927
static void
928
drm_fb_destroy(struct drm_fb *fb)
929
{
930
	if (fb->fb_id != 0)
931
		drmModeRmFB(fb->fd, fb->fb_id);
932
	weston_buffer_reference(&fb->buffer_ref, NULL);
933 934 935 936 937 938 939 940 941 942 943 944 945 946
	free(fb);
}

static void
drm_fb_destroy_dumb(struct drm_fb *fb)
{
	struct drm_mode_destroy_dumb destroy_arg;

	assert(fb->type == BUFFER_PIXMAN_DUMB);

	if (fb->map && fb->size > 0)
		munmap(fb->map, fb->size);

	memset(&destroy_arg, 0, sizeof(destroy_arg));
947
	destroy_arg.handle = fb->handles[0];
948 949 950 951 952 953 954 955 956
	drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);

	drm_fb_destroy(fb);
}

static void
drm_fb_destroy_gbm(struct gbm_bo *bo, void *data)
{
	struct drm_fb *fb = data;
957

958 959
	assert(fb->type == BUFFER_GBM_SURFACE || fb->type == BUFFER_CLIENT ||
	       fb->type == BUFFER_CURSOR);
960
	drm_fb_destroy(fb);
961 962
}

963 964 965
static int
drm_fb_addfb(struct drm_fb *fb)
{
966 967 968
	int ret = -EINVAL;
#ifdef HAVE_DRM_ADDFB2_MODIFIERS
	uint64_t mods[4] = { };
969
	size_t i;
970 971 972 973 974 975 976 977
#endif

	/* If we have a modifier set, we must only use the WithModifiers
	 * entrypoint; we cannot import it through legacy ioctls. */
	if (fb->modifier != DRM_FORMAT_MOD_INVALID) {
		/* KMS demands that if a modifier is set, it must be the same
		 * for all planes. */
#ifdef HAVE_DRM_ADDFB2_MODIFIERS
978
		for (i = 0; i < ARRAY_LENGTH(mods) && fb->handles[i]; i++)
979 980 981 982 983 984 985 986 987
			mods[i] = fb->modifier;
		ret = drmModeAddFB2WithModifiers(fb->fd, fb->width, fb->height,
						 fb->format->format,
						 fb->handles, fb->strides,
						 fb->offsets, mods, &fb->fb_id,
						 DRM_MODE_FB_MODIFIERS);
#endif
		return ret;
	}
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009

	ret = drmModeAddFB2(fb->fd, fb->width, fb->height, fb->format->format,
			    fb->handles, fb->strides, fb->offsets, &fb->fb_id,
			    0);
	if (ret == 0)
		return 0;

	/* Legacy AddFB can't always infer the format from depth/bpp alone, so
	 * check if our format is one of the lucky ones. */
	if (!fb->format->depth || !fb->format->bpp)
		return ret;

	/* Cannot fall back to AddFB for multi-planar formats either. */
	if (fb->handles[1] || fb->handles[2] || fb->handles[3])
		return ret;

	ret = drmModeAddFB(fb->fd, fb->width, fb->height,
			   fb->format->depth, fb->format->bpp,
			   fb->strides[0], fb->handles[0], &fb->fb_id);
	return ret;
}

1010
static struct drm_fb *
1011
drm_fb_create_dumb(struct drm_backend *b, int width, int height,
1012
		   uint32_t format)
1013 1014 1015 1016 1017 1018 1019 1020
{
	struct drm_fb *fb;
	int ret;

	struct drm_mode_create_dumb create_arg;
	struct drm_mode_destroy_dumb destroy_arg;
	struct drm_mode_map_dumb map_arg;

1021
	fb = zalloc(sizeof *fb);
1022 1023
	if (!fb)
		return NULL;
1024 1025
	fb->refcnt = 1;

1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
	fb->format = pixel_format_get_info(format);
	if (!fb->format) {
		weston_log("failed to look up format 0x%lx\n",
			   (unsigned long) format);
		goto err_fb;
	}

	if (!fb->format->depth || !fb->format->bpp) {
		weston_log("format 0x%lx is not compatible with dumb buffers\n",
			   (unsigned long) format);
		goto err_fb;
1037 1038
	}

1039
	memset(&create_arg, 0, sizeof create_arg);
1040
	create_arg.bpp = fb->format->bpp;
1041 1042 1043
	create_arg.width = width;
	create_arg.height = height;

1044
	ret = drmIoctl(b->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
1045 1046 1047
	if (ret)
		goto err_fb;

1048
	fb->type = BUFFER_PIXMAN_DUMB;
1049
	fb->modifier = DRM_FORMAT_MOD_INVALID;
1050 1051
	fb->handles[0] = create_arg.handle;
	fb->strides[0] = create_arg.pitch;
1052
	fb->num_planes = 1;
1053
	fb->size = create_arg.size;
1054 1055
	fb->width = width;
	fb->height = height;
1056
	fb->fd = b->drm.fd;
1057

1058 1059
	if (drm_fb_addfb(fb) != 0) {
		weston_log("failed to create kms fb: %m\n");
1060
		goto err_bo;
1061
	}
1062

1063
	memset(&map_arg, 0, sizeof map_arg);
1064
	map_arg.handle = fb->handles[0];
1065
	ret = drmIoctl(fb->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
1066 1067 1068
	if (ret)
		goto err_add_fb;

1069
	fb->map = mmap(NULL, fb->size, PROT_WRITE,
1070
		       MAP_SHARED, b->drm.fd, map_arg.offset);
1071 1072 1073 1074 1075 1076
	if (fb->map == MAP_FAILED)
		goto err_add_fb;

	return fb;

err_add_fb:
1077
	drmModeRmFB(b->drm.fd, fb->fb_id);
1078 1079 1080
err_bo:
	memset(&destroy_arg, 0, sizeof(destroy_arg));
	destroy_arg.handle = create_arg.handle;
1081
	drmIoctl(b->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
1082 1083 1084 1085 1086
err_fb:
	free(fb);
	return NULL;
}

1087 1088 1089 1090 1091 1092 1093
static struct drm_fb *
drm_fb_ref(struct drm_fb *fb)
{
	fb->refcnt++;
	return fb;
}

1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
static void
drm_fb_destroy_dmabuf(struct drm_fb *fb)
{
	/* We deliberately do not close the GEM handles here; GBM manages
	 * their lifetime through the BO. */
	if (fb->bo)
		gbm_bo_destroy(fb->bo);
	drm_fb_destroy(fb);
}

static struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
		       struct drm_backend *backend, bool is_opaque)
{
#ifdef HAVE_GBM_FD_IMPORT
	struct drm_fb *fb;
	struct gbm_import_fd_data import_legacy = {
		.width = dmabuf->attributes.width,
		.height = dmabuf->attributes.height,
		.format = dmabuf->attributes.format,
		.stride = dmabuf->attributes.stride[0],
		.fd = dmabuf->attributes.fd[0],
	};
	struct gbm_import_fd_modifier_data import_mod = {
		.width = dmabuf->attributes.width,
		.height = dmabuf->attributes.height,
		.format = dmabuf->attributes.format,
		.num_fds = dmabuf->attributes.n_planes,
		.modifier = dmabuf->attributes.modifier[0],
	};
	int i;

	/* XXX: TODO:
	 *
	 * Currently the buffer is rejected if any dmabuf attribute
	 * flag is set.  This keeps us from passing an inverted /
	 * interlaced / bottom-first buffer (or any other type that may
	 * be added in the future) through to an overlay.  Ultimately,
	 * these types of buffers should be handled through buffer
	 * transforms and not as spot-checks requiring specific
	 * knowledge. */
	if (dmabuf->attributes.flags)
		return NULL;

	fb = zalloc(sizeof *fb);
	if (fb == NULL)
		return NULL;

	fb->refcnt = 1;
	fb->type = BUFFER_DMABUF;

	static_assert(ARRAY_LENGTH(import_mod.fds) ==
		      ARRAY_LENGTH(dmabuf->attributes.fd),
		      "GBM and linux_dmabuf FD size must match");
	static_assert(sizeof(import_mod.fds) == sizeof(dmabuf->attributes.fd),
		      "GBM and linux_dmabuf FD size must match");
	memcpy(import_mod.fds, dmabuf->attributes.fd, sizeof(import_mod.fds));

	static_assert(ARRAY_LENGTH(import_mod.strides) ==
		      ARRAY_LENGTH(dmabuf->attributes.stride),
		      "GBM and linux_dmabuf stride size must match");
	static_assert(sizeof(import_mod.strides) ==
		      sizeof(dmabuf->attributes.stride),
		      "GBM and linux_dmabuf stride size must match");
	memcpy(import_mod.strides, dmabuf->attributes.stride,
	       sizeof(import_mod.strides));

	static_assert(ARRAY_LENGTH(import_mod.offsets) ==
		      ARRAY_LENGTH(dmabuf->attributes.offset),
		      "GBM and linux_dmabuf offset size must match");
	static_assert(sizeof(import_mod.offsets) ==
		      sizeof(dmabuf->attributes.offset),
		      "GBM and linux_dmabuf offset size must match");
	memcpy(import_mod.offsets, dmabuf->attributes.offset,
	       sizeof(import_mod.offsets));

	/* The legacy FD-import path does not allow us to supply modifiers,
	 * multiple planes, or buffer offsets. */
	if (dmabuf->attributes.modifier[0] != DRM_FORMAT_MOD_INVALID ||
	    import_mod.num_fds > 1 ||
	    import_mod.offsets[0] > 0) {
		fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
				       &import_mod,
				       GBM_BO_USE_SCANOUT);
	} else {
		fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD,
				       &import_legacy,
				       GBM_BO_USE_SCANOUT);
	}

	if (!fb->bo)
		goto err_free;

	fb->width = dmabuf->attributes.width;
	fb->height = dmabuf->attributes.height;
	fb->modifier = dmabuf->attributes.modifier[0];
	fb->size = 0;
	fb->fd = backend->drm.fd;

	static_assert(ARRAY_LENGTH(fb->strides) ==
		      ARRAY_LENGTH(dmabuf->attributes.stride),
		      "drm_fb and dmabuf stride size must match");
	static_assert(sizeof(fb->strides) == sizeof(dmabuf->attributes.stride),
		      "drm_fb and dmabuf stride size must match");
	memcpy(fb->strides, dmabuf->attributes.stride, sizeof(fb->strides));
	static_assert(ARRAY_LENGTH(fb->offsets) ==
		      ARRAY_LENGTH(dmabuf->attributes.offset),
		      "drm_fb and dmabuf offset size must match");
	static_assert(sizeof(fb->offsets) == sizeof(dmabuf->attributes.offset),
		      "drm_fb and dmabuf offset size must match");
	memcpy(fb->offsets, dmabuf->attributes.offset, sizeof(fb->offsets));

	fb->format = pixel_format_get_info(dmabuf->attributes.format);
	if (!fb->format) {
		weston_log("couldn't look up format info for 0x%lx\n",
			   (unsigned long) dmabuf->attributes.format);
		goto err_free;
	}

	if (is_opaque)
		fb->format = pixel_format_get_opaque_substitute(fb->format);

	if (backend->min_width > fb->width ||
	    fb->width > backend->max_width ||
	    backend->min_height > fb->height ||
	    fb->height > backend->max_height) {
		weston_log("bo geometry out of bounds\n");
		goto err_free;
	}

1224
	fb->num_planes = dmabuf->attributes.n_planes;
1225 1226 1227 1228 1229 1230
	for (i = 0; i < dmabuf->attributes.n_planes; i++) {
		fb->handles[i] = gbm_bo_get_handle_for_plane(fb->bo, i).u32;
		if (!fb->handles[i])
			goto err_free;
	}

1231
	if (drm_fb_addfb(fb) != 0)
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
		goto err_free;

	return fb;

err_free:
	drm_fb_destroy_dmabuf(fb);
#endif
	return NULL;
}

1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272
static void
drm_fb_setup_gbm_modifier(struct gbm_bo *bo, struct drm_backend *backend,
			  struct drm_fb *fb)
{
#ifdef HAVE_GBM_MODIFIERS
	uint64_t cap;
	int ret, i;

	ret = drmGetCap(backend->drm.fd, DRM_CAP_ADDFB2_MODIFIERS, &cap);
	if (ret != 0 || cap != 1)
		goto no_gbm_modifiers;

	fb->modifier = gbm_bo_get_modifier(bo);
	fb->num_planes = gbm_bo_get_plane_count(bo);
	for (i = 0; i < fb->num_planes; i++) {
		fb->strides[i] = gbm_bo_get_stride_for_plane(bo, i);
		fb->handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
		fb->offsets[i] = gbm_bo_get_offset(bo, i);
	}

	return;

no_gbm_modifiers:
#endif

	fb->num_planes = 1;
	fb->strides[0] = gbm_bo_get_stride(bo);
	fb->handles[0] = gbm_bo_get_handle(bo).u32;
	fb->modifier = DRM_FORMAT_MOD_INVALID;
}

1273
static struct drm_fb *
1274
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
1275
		   bool is_opaque, enum drm_fb_type type)
1276 1277 1278
{
	struct drm_fb *fb = gbm_bo_get_user_data(bo);

1279 1280
	if (fb) {
		assert(fb->type == type);
1281
		return drm_fb_ref(fb);
1282
	}
1283

1284 1285
	fb = zalloc(sizeof *fb);
	if (fb == NULL)
1286
		return NULL;
1287

1288
	fb->type = type;
1289
	fb->refcnt = 1;
1290
	fb->bo = bo;
1291
	fb->fd = backend->drm.fd;
1292

1293 1294
	fb->width = gbm_bo_get_width(bo);
	fb->height = gbm_bo_get_height(bo);
1295 1296 1297
	fb->format = pixel_format_get_info(gbm_bo_get_format(bo));
	fb->size = 0;

1298 1299
	if (!fb->format) {
		weston_log("couldn't look up format 0x%lx\n",
1300
			   (unsigned long) gbm_bo_get_format(bo));
1301 1302 1303
		goto err_free;
	}

1304 1305
	drm_fb_setup_gbm_modifier(bo, backend, fb);

1306 1307 1308 1309 1310
	/* We can scanout an ARGB buffer if the surface's opaque region covers
	 * the whole output, but we have to use XRGB as the KMS format code. */
	if (is_opaque)
		fb->format = pixel_format_get_opaque_substitute(fb->format);

1311 1312 1313 1314
	if (backend->min_width > fb->width ||
	    fb->width > backend->max_width ||
	    backend->min_height > fb->height ||
	    fb->height > backend->max_height) {
1315 1316 1317 1318
		weston_log("bo geometry out of bounds\n");
		goto err_free;
	}

1319
	if (drm_fb_addfb(fb) != 0) {
1320 1321
		if (type == BUFFER_GBM_SURFACE)
			weston_log("failed to create kms fb: %m\n");
1322
		goto err_free;
1323 1324
	}

1325
	gbm_bo_set_user_data(bo, fb, drm_fb_destroy_gbm);
1326 1327

	return fb;
1328 1329 1330 1331

err_free:
	free(fb);
	return NULL;
1332 1333
}

1334
static void
1335
drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
1336
{
1337
	assert(fb->buffer_ref.buffer == NULL);
1338
	assert(fb->type == BUFFER_CLIENT || fb->type == BUFFER_DMABUF);
1339
	weston_buffer_reference(&fb->buffer_ref, buffer);
1340 1341
}

1342
static void
1343
drm_fb_unref(struct drm_fb *fb)
1344 1345 1346 1347
{
	if (!fb)
		return;

1348 1349 1350 1351
	assert(fb->refcnt > 0);
	if (--fb->refcnt > 0)
		return;

1352 1353
	switch (fb->type) {
	case BUFFER_PIXMAN_DUMB:
1354
		drm_fb_destroy_dumb(fb);
1355
		break;
1356
	case BUFFER_CURSOR:
1357 1358 1359 1360
	case BUFFER_CLIENT:
		gbm_bo_destroy(fb->bo);
		break;
	case BUFFER_GBM_SURFACE:
1361
		gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
1362
		break;
1363 1364 1365
	case BUFFER_DMABUF:
		drm_fb_destroy_dmabuf(fb);
		break;
1366 1367 1368
	default:
		assert(NULL);
		break;
1369 1370 1371
	}
}

1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
/**
 * Allocate a new, empty, plane state.
 */
static struct drm_plane_state *
drm_plane_state_alloc(struct drm_output_state *state_output,
		      struct drm_plane *plane)
{
	struct drm_plane_state *state = zalloc(sizeof(*state));

	assert(state);
	state->output_state = state_output;
	state->plane = plane;

	/* Here we only add the plane state to the desired link, and not
	 * set the member. Having an output pointer set means that the
	 * plane will be displayed on the output; this won't be the case
	 * when we go to disable a plane. In this case, it must be part of
	 * the commit (and thus the output state), but the member must be
	 * NULL, as it will not be on any output when the state takes
	 * effect.
	 */
	if (state_output)
		wl_list_insert(&state_output->plane_list, &state->link);
	else
		wl_list_init(&state->link);

	return state;
}

/**
 * Free an existing plane state. As a special case, the state will not
 * normally be freed if it is the current state; see drm_plane_set_state.
 */
static void
drm_plane_state_free(struct drm_plane_state *state, bool force)
{
	if (!state)
		return;

	wl_list_remove(&state->link);
	wl_list_init(&state->link);
	state->output_state = NULL;

	if (force || state != state->plane->state_cur) {
		drm_fb_unref(state->fb);
		free(state);
	}
}

/**
 * Duplicate an existing plane state into a new plane state, storing it within
 * the given output state. If the output state already contains a plane state
 * for the drm_plane referenced by 'src', that plane state is freed first.
 */
static struct drm_plane_state *
drm_plane_state_duplicate(struct drm_output_state *state_output,
			  struct drm_plane_state *src)
{
	struct drm_plane_state *dst = malloc(sizeof(*dst));
	struct drm_plane_state *old, *tmp;

	assert(src);
	assert(dst);
	*dst = *src;
	wl_list_init(&dst->link);

	wl_list_for_each_safe(old, tmp, &state_output->plane_list, link) {
		/* Duplicating a plane state into the same output state, so
		 * it can replace itself with an identical copy of itself,
		 * makes no sense. */
		assert(old != src);
		if (old->plane == dst->plane)
			drm_plane_state_free(old, false);
	}

	wl_list_insert(&state_output->plane_list, &dst->link);
	if (src->fb)
		dst->fb = drm_fb_ref(src->fb);
	dst->output_state = state_output;
	dst->complete = false;

	return dst;
}

/**
 * Remove a plane state from an output state; if the plane was previously
 * enabled, then replace it with a disabling state. This ensures that the
 * output state was untouched from it was before the plane state was
 * modified by the caller of this function.
 *
 * This is required as drm_output_state_get_plane may either allocate a
 * new plane state, in which case this function will just perform a matching
 * drm_plane_state_free, or it may instead repurpose an existing disabling
 * state (if the plane was previously active), in which case this function
 * will reset it.
 */
static void
drm_plane_state_put_back(struct drm_plane_state *state)
{
	struct drm_output_state *state_output;
	struct drm_plane *plane;

	if (!state)
		return;

	state_output = state->output_state;
	plane = state->plane;
	drm_plane_state_free(state, false);

	/* Plane was previously disabled; no need to keep this temporary
	 * state around. */
	if (!plane->state_cur->fb)
		return;

	(void) drm_plane_state_alloc(state_output, plane);
}

1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
static bool
drm_view_transform_supported(struct weston_view *ev, struct weston_output *output)
{
	struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;

	/* This will incorrectly disallow cases where the combination of
	 * buffer and view transformations match the output transform.
	 * Fixing this requires a full analysis of the transformation
	 * chain. */
	if (ev->transform.enabled &&
	    ev->transform.matrix.type >= WESTON_MATRIX_TRANSFORM_ROTATE)
		return false;

	if (viewport->buffer.transform != output->transform)
		return false;

	return true;
}

1508 1509 1510 1511
/**
 * Given a weston_view, fill the drm_plane_state's co-ordinates to display on
 * a given plane.
 */
1512
static bool
1513 1514 1515 1516
drm_plane_state_coords_for_view(struct drm_plane_state *state,
				struct weston_view *ev)
{
	struct drm_output *output = state->output;
1517
	struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
1518 1519
	pixman_region32_t dest_rect, src_rect;
	pixman_box32_t *box, tbox;
1520
	float sxf1, syf1, sxf2, syf2;
1521

1522 1523 1524
	if (!drm_view_transform_supported(ev, &output->base))
		return false;

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554
	/* Update the base weston_plane co-ordinates. */
	box = pixman_region32_extents(&ev->transform.boundingbox);
	state->plane->base.x = box->x1;
	state->plane->base.y = box->y1;

	/* First calculate the destination co-ordinates by taking the
	 * area of the view which is visible on this output, performing any
	 * transforms to account for output rotation and scale as necessary. */
	pixman_region32_init(&dest_rect);
	pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
				  &output->base.region);
	pixman_region32_translate(&dest_rect, -output->base.x, -output->base.y);
	box = pixman_region32_extents(&dest_rect);
	tbox = weston_transformed_rect(output->base.width,
				       output->base.height,
				       output->base.transform,
				       output->base.current_scale,
				       *box);
	state->dest_x = tbox.x1;
	state->dest_y = tbox.y1;
	state->dest_w = tbox.x2 - tbox.x1;
	state->dest_h = tbox.y2 - tbox.y1;
	pixman_region32_fini(&dest_rect);

	/* Now calculate the source rectangle, by finding the extents of the
	 * view, and working backwards to source co-ordinates. */
	pixman_region32_init(&src_rect);
	pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
				  &output->base.region);
	box = pixman_region32_extents(&src_rect);
1555 1556 1557 1558 1559
	weston_view_from_global_float(ev, box->x1, box->y1, &sxf1, &syf1);
	weston_surface_to_buffer_float(ev->surface, sxf1, syf1, &sxf1, &syf1);
	weston_view_from_global_float(ev, box->x2, box->y2, &sxf2, &syf2);
	weston_surface_to_buffer_float(ev->surface, sxf2, syf2, &sxf2, &syf2);
	pixman_region32_fini(&src_rect);
1560

1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578
	/* Buffer transforms may mean that x2 is to the left of x1, and/or that
	 * y2 is above y1. */
	if (sxf2 < sxf1) {
		double tmp = sxf1;
		sxf1 = sxf2;
		sxf2 = tmp;
	}
	if (syf2 < syf1) {
		double tmp = syf1;
		syf1 = syf2;
		syf2 = tmp;
	}

	/* Shift from S23.8 wl_fixed to U16.16 KMS fixed-point encoding. */
	state->src_x = wl_fixed_from_double(sxf1) << 8;
	state->src_y = wl_fixed_from_double(syf1) << 8;
	state->src_w = wl_fixed_from_double(sxf2 - sxf1) << 8;
	state->src_h = wl_fixed_from_double(syf2 - syf1) << 8;
1579 1580 1581 1582 1583 1584

	/* Clamp our source co-ordinates to surface bounds; it's possible
	 * for intermediate translations to give us slightly incorrect
	 * co-ordinates if we have, for example, multiple zooming
	 * transformations. View bounding boxes are also explicitly rounded
	 * greedily. */
1585 1586 1587 1588 1589 1590 1591 1592
	if (state->src_x < 0)
		state->src_x = 0;
	if (state->src_y < 0)
		state->src_y = 0;
	if (state->src_w > (uint32_t) ((buffer->width << 16) - state->src_x))
		state->src_w = (buffer->width << 16) - state->src_x;
	if (state->src_h > (uint32_t) ((buffer->height << 16) - state->src_y))
		state->src_h = (buffer->height << 16) - state->src_y;
1593 1594

	return true;
1595 1596
}

1597 1598 1599 1600 1601 1602
static struct drm_fb *
drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev)
{
	struct drm_output *output = state->output;
	struct drm_backend *b = to_drm_backend(output->base.compositor);
	struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
1603
	bool is_opaque = weston_view_is_opaque(ev, &ev->transform.boundingbox);
1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
	struct linux_dmabuf_buffer *dmabuf;
	struct drm_fb *fb;

	if (ev->alpha != 1.0f)
		return NULL;

	if (!drm_view_transform_supported(ev, &output->base))
		return NULL;

	if (!buffer)
		return NULL;

	if (wl_shm_buffer_get(buffer->resource))
		return NULL;

1619
	/* GBM is used for dmabuf import as well as from client wl_buffer. */
1620 1621 1622 1623 1624
	if (!b->gbm)
		return NULL;

	dmabuf = linux_dmabuf_buffer_get(buffer->resource);
	if (dmabuf) {
1625 1626
		fb = drm_fb_get_from_dmabuf(dmabuf, b, is_opaque);
		if (!fb)
1627 1628
			return NULL;
	} else {
1629 1630
		struct gbm_bo *bo;

1631 1632
		bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
				   buffer->resource, GBM_BO_USE_SCANOUT);
1633 1634
		if (!bo)
			return NULL;
1635

1636 1637 1638 1639 1640
		fb = drm_fb_get_from_bo(bo, b, is_opaque, BUFFER_CLIENT);
		if (!fb) {
			gbm_bo_destroy(bo);
			return NULL;
		}
1641 1642 1643 1644 1645 1646
	}

	drm_fb_set_buffer(fb, buffer);
	return fb;
}

1647
/**
1648
 * Return a plane state from a drm_output_state.
1649 1650
 */
static struct drm_plane_state *
1651 1652
drm_output_state_get_existing_plane(struct drm_output_state *state_output,
				    struct drm_plane *plane)
1653 1654 1655 1656 1657 1658 1659 1660
{
	struct drm_plane_state *ps;

	wl_list_for_each(ps, &state_output->plane_list, link) {
		if (ps->plane == plane)
			return ps;
	}

1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
	return NULL;
}

/**
 * Return a plane state from a drm_output_state, either existing or
 * freshly allocated.
 */
static struct drm_plane_state *
drm_output_state_get_plane(struct drm_output_state *state_output,
			   struct drm_plane *plane)
{
	struct drm_plane_state *ps;

	ps = drm_output_state_get_existing_plane(state_output, plane);
	if (ps)
		return ps;

1678 1679 1680
	return drm_plane_state_alloc(state_output, plane);
}

1681 1682 1683 1684 1685 1686 1687
/**
 * Allocate a new, empty drm_output_state. This should not generally be used
 * in the repaint cycle; see drm_output_state_duplicate.
 */
static struct drm_output_state *
drm_output_state_alloc(struct drm_output *output,
		       struct drm_pending_state *pending_state)
1688
{
1689 1690 1691 1692
	struct drm_output_state *state = zalloc(sizeof(*state));

	assert(state);
	state->output = output;
1693
	state->dpms = WESTON_DPMS_OFF;
1694 1695 1696 1697 1698 1699
	state->pending_state = pending_state;
	if (pending_state)
		wl_list_insert(&pending_state->output_list, &state->link);
	else
		wl_list_init(&state->link);

1700 1701
	wl_list_init(&state->plane_list);

1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718
	return state;
}

/**
 * Duplicate an existing drm_output_state into a new one. This is generally
 * used during the repaint cycle, to capture the existing state of an output
 * and modify it to create a new state to be used.
 *
 * The mode determines whether the output will be reset to an a blank state,
 * or an exact mirror of the current state.
 */
static struct drm_output_state *
drm_output_state_duplicate(struct drm_output_state *src,
			   struct drm_pending_state *pending_state,
			   enum drm_output_state_duplicate_mode plane_mode)
{
	struct drm_output_state *dst = malloc(sizeof(*dst));
1719
	struct drm_plane_state *ps;
1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733

	assert(dst);

	/* Copy the whole structure, then individually modify the
	 * pending_state, as well as the list link into our pending
	 * state. */
	*dst = *src;

	dst->pending_state = pending_state;
	if (pending_state)
		wl_list_insert(&pending_state->output_list, &dst->link);
	else
		wl_list_init(&dst->link);

1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
	wl_list_init(&dst->plane_list);

	wl_list_for_each(ps, &src->plane_list, link) {
		/* Don't carry planes which are now disabled; these should be
		 * free for other outputs to reuse. */
		if (!ps->output)
			continue;

		if (plane_mode == DRM_OUTPUT_STATE_CLEAR_PLANES)
			(void) drm_plane_state_alloc(dst, ps->plane);
		else
			(void) drm_plane_state_duplicate(dst, ps);
	}

1748 1749 1750 1751 1752 1753 1754 1755 1756
	return dst;
}

/**
 * Free an unused drm_output_state.
 */
static void
drm_output_state_free(struct drm_output_state *state)
{
1757 1758
	struct drm_plane_state *ps, *next;

1759 1760 1761
	if (!state)
		return;

1762 1763 1764
	wl_list_for_each_safe(ps, next, &state->plane_list, link)
		drm_plane_state_free(ps, false);

1765
	wl_list_remove(&state->link);
1766

1767
	free(state);
1768 1769
}

1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
/**
 * Get output state to disable output
 *
 * Returns a pointer to an output_state object which can be used to disable
 * an output (e.g. DPMS off).
 *
 * @param pending_state The pending state object owning this update
 * @param output The output to disable
 * @returns A drm_output_state to disable the output
 */
static struct drm_output_state *
drm_output_get_disable_state(struct drm_pending_state *pending_state,
			     struct drm_output *output)
{
	struct drm_output_state *output_state;

	output_state = drm_output_state_duplicate(output->state_cur,
						  pending_state,
						  DRM_OUTPUT_STATE_CLEAR_PLANES);
	output_state->dpms = WESTON_DPMS_OFF;

	return output_state;
}

1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812