blob: 9cd80d66dd9486a46e93c6dc9e27ae9834725db1 [file] [log] [blame]
Daniel Stonedd1bc502019-06-17 12:13:46 +01001/*
2 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
4 * Copyright © 2017, 2018 Collabora, Ltd.
5 * Copyright © 2017, 2018 General Electric Company
6 * Copyright (c) 2018 DisplayLink (UK) Ltd.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30#include "config.h"
31
32#include <errno.h>
33#include <stdint.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include <string.h>
37#include <fcntl.h>
38#include <unistd.h>
39#include <linux/input.h>
40#include <linux/vt.h>
41#include <assert.h>
42#include <sys/mman.h>
43#include <time.h>
44
45
46#include <xf86drm.h>
47#include <xf86drmMode.h>
Daniel Stonedd1bc502019-06-17 12:13:46 +010048
Stefan Agnerccf24072019-07-09 22:02:00 +020049#ifdef BUILD_DRM_GBM
Daniel Stonedd1bc502019-06-17 12:13:46 +010050#include <gbm.h>
Stefan Agnerccf24072019-07-09 22:02:00 +020051#endif
Daniel Stonedd1bc502019-06-17 12:13:46 +010052#include <libudev.h>
53
54#include <libweston/libweston.h>
55#include <libweston/backend-drm.h>
Marius Vladc901e892019-06-21 22:49:18 +030056#include <libweston/weston-log.h>
Daniel Stonedd1bc502019-06-17 12:13:46 +010057#include "shared/helpers.h"
Pekka Paalanen4b301fe2021-02-04 17:39:45 +020058#include "shared/weston-drm-fourcc.h"
Daniel Stonedd1bc502019-06-17 12:13:46 +010059#include "libinput-seat.h"
Marius Vlade41c1bf2019-07-16 23:11:25 +030060#include "backend.h"
Marius Vlada72e3712019-07-10 13:46:39 +030061#include "libweston-internal.h"
Daniel Stonedd1bc502019-06-17 12:13:46 +010062
Daniel Stonedd1bc502019-06-17 12:13:46 +010063#ifndef GBM_BO_USE_CURSOR
64#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
65#endif
66
67#ifndef GBM_BO_USE_LINEAR
68#define GBM_BO_USE_LINEAR (1 << 4)
69#endif
70
Marius Vladcdd6fa22019-08-29 20:42:00 +030071#ifndef DRM_PLANE_ZPOS_INVALID_PLANE
72#define DRM_PLANE_ZPOS_INVALID_PLANE 0xffffffffffffffffULL
73#endif
74
Daniel Stonedd1bc502019-06-17 12:13:46 +010075/**
76 * A small wrapper to print information into the 'drm-backend' debug scope.
77 *
78 * The following conventions are used to print variables:
79 *
80 * - fixed uint32_t values, including Weston object IDs such as weston_output
81 * IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats:
82 * "%lu (0x%lx)" (unsigned long) value, (unsigned long) value
83 *
84 * - fixed uint64_t values, such as DRM property values (including object IDs
85 * when used as a value):
86 * "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value
87 *
88 * - non-fixed-width signed int:
89 * "%d" value
90 *
91 * - non-fixed-width unsigned int:
92 * "%u (0x%x)" value, value
93 *
94 * - non-fixed-width unsigned long:
95 * "%lu (0x%lx)" value, value
96 *
97 * Either the integer or hexadecimal forms may be omitted if it is known that
98 * one representation is not useful (e.g. width/height in hex are rarely what
99 * you want).
100 *
101 * This is to avoid implicit widening or narrowing when we use fixed-size
102 * types: uint32_t can be resolved by either unsigned int or unsigned long
103 * on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t
104 * being unsigned long long on a 32-bit system and unsigned long on a 64-bit
105 * system. To avoid confusing side effects, we explicitly cast to the widest
106 * possible type and use a matching format specifier.
107 */
108#define drm_debug(b, ...) \
109 weston_log_scope_printf((b)->debug, __VA_ARGS__)
110
111#define MAX_CLONED_CONNECTORS 4
112
Stefan Agner723c6a12019-12-09 13:06:36 +0100113
Daniel Stonedd1bc502019-06-17 12:13:46 +0100114/**
Daniel Stonedd1bc502019-06-17 12:13:46 +0100115 * Represents the values of an enum-type KMS property
116 */
117struct drm_property_enum_info {
118 const char *name; /**< name as string (static, not freed) */
119 bool valid; /**< true if value is supported; ignore if false */
120 uint64_t value; /**< raw value */
121};
122
123/**
124 * Holds information on a DRM property, including its ID and the enum
125 * values it holds.
126 *
127 * DRM properties are allocated dynamically, and maintained as DRM objects
128 * within the normal object ID space; they thus do not have a stable ID
129 * to refer to. This includes enum values, which must be referred to by
130 * integer values, but these are not stable.
131 *
132 * drm_property_info allows a cache to be maintained where Weston can use
133 * enum values internally to refer to properties, with the mapping to DRM
134 * ID values being maintained internally.
135 */
136struct drm_property_info {
137 const char *name; /**< name as string (static, not freed) */
138 uint32_t prop_id; /**< KMS property object ID */
Marius Vlad1accffe2019-11-01 12:00:09 +0200139 uint32_t flags;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100140 unsigned int num_enum_values; /**< number of enum values */
141 struct drm_property_enum_info *enum_values; /**< array of enum values */
Marius Vlad1accffe2019-11-01 12:00:09 +0200142 unsigned int num_range_values;
143 uint64_t range_values[2];
Daniel Stonedd1bc502019-06-17 12:13:46 +0100144};
145
146/**
147 * List of properties attached to DRM planes
148 */
149enum wdrm_plane_property {
150 WDRM_PLANE_TYPE = 0,
151 WDRM_PLANE_SRC_X,
152 WDRM_PLANE_SRC_Y,
153 WDRM_PLANE_SRC_W,
154 WDRM_PLANE_SRC_H,
155 WDRM_PLANE_CRTC_X,
156 WDRM_PLANE_CRTC_Y,
157 WDRM_PLANE_CRTC_W,
158 WDRM_PLANE_CRTC_H,
159 WDRM_PLANE_FB_ID,
160 WDRM_PLANE_CRTC_ID,
161 WDRM_PLANE_IN_FORMATS,
162 WDRM_PLANE_IN_FENCE_FD,
163 WDRM_PLANE_FB_DAMAGE_CLIPS,
Marius Vladcdd6fa22019-08-29 20:42:00 +0300164 WDRM_PLANE_ZPOS,
Daniel Stonedd1bc502019-06-17 12:13:46 +0100165 WDRM_PLANE__COUNT
166};
167
168/**
169 * Possible values for the WDRM_PLANE_TYPE property.
170 */
171enum wdrm_plane_type {
172 WDRM_PLANE_TYPE_PRIMARY = 0,
173 WDRM_PLANE_TYPE_CURSOR,
174 WDRM_PLANE_TYPE_OVERLAY,
175 WDRM_PLANE_TYPE__COUNT
176};
177
178/**
179 * List of properties attached to a DRM connector
180 */
181enum wdrm_connector_property {
182 WDRM_CONNECTOR_EDID = 0,
183 WDRM_CONNECTOR_DPMS,
184 WDRM_CONNECTOR_CRTC_ID,
185 WDRM_CONNECTOR_NON_DESKTOP,
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530186 WDRM_CONNECTOR_CONTENT_PROTECTION,
187 WDRM_CONNECTOR_HDCP_CONTENT_TYPE,
Lucas Stach72e7a1e2019-11-25 23:31:57 +0000188 WDRM_CONNECTOR_PANEL_ORIENTATION,
Daniel Stonedd1bc502019-06-17 12:13:46 +0100189 WDRM_CONNECTOR__COUNT
190};
191
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530192enum wdrm_content_protection_state {
193 WDRM_CONTENT_PROTECTION_UNDESIRED = 0,
194 WDRM_CONTENT_PROTECTION_DESIRED,
195 WDRM_CONTENT_PROTECTION_ENABLED,
196 WDRM_CONTENT_PROTECTION__COUNT
197};
198
199enum wdrm_hdcp_content_type {
200 WDRM_HDCP_CONTENT_TYPE0 = 0,
201 WDRM_HDCP_CONTENT_TYPE1,
202 WDRM_HDCP_CONTENT_TYPE__COUNT
203};
204
Daniel Stonedd1bc502019-06-17 12:13:46 +0100205enum wdrm_dpms_state {
206 WDRM_DPMS_STATE_OFF = 0,
207 WDRM_DPMS_STATE_ON,
208 WDRM_DPMS_STATE_STANDBY, /* unused */
209 WDRM_DPMS_STATE_SUSPEND, /* unused */
210 WDRM_DPMS_STATE__COUNT
211};
212
Lucas Stach72e7a1e2019-11-25 23:31:57 +0000213enum wdrm_panel_orientation {
214 WDRM_PANEL_ORIENTATION_NORMAL = 0,
215 WDRM_PANEL_ORIENTATION_UPSIDE_DOWN,
216 WDRM_PANEL_ORIENTATION_LEFT_SIDE_UP,
217 WDRM_PANEL_ORIENTATION_RIGHT_SIDE_UP,
218 WDRM_PANEL_ORIENTATION__COUNT
219};
220
Daniel Stonedd1bc502019-06-17 12:13:46 +0100221/**
222 * List of properties attached to DRM CRTCs
223 */
224enum wdrm_crtc_property {
225 WDRM_CRTC_MODE_ID = 0,
226 WDRM_CRTC_ACTIVE,
227 WDRM_CRTC__COUNT
228};
229
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300230/**
231 * Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
232 */
233enum try_view_on_plane_failure_reasons {
234 FAILURE_REASONS_NONE = 0,
235 FAILURE_REASONS_FORCE_RENDERER = (1 << 0),
236 FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = (1 << 1),
237 FAILURE_REASONS_DMABUF_MODIFIER_INVALID = (1 << 2),
238 FAILURE_REASONS_ADD_FB_FAILED = (1 << 3),
239};
240
Leandro Ribeiro54293022021-10-12 14:48:36 -0300241/**
242 * We use this to keep track of actions we need to do with the dma-buf feedback
243 * in order to keep it up-to-date with the info we get from the DRM-backend.
244 */
245enum actions_needed_dmabuf_feedback {
246 ACTION_NEEDED_NONE = 0,
247 ACTION_NEEDED_ADD_SCANOUT_TRANCHE = (1 << 0),
248 ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
249};
250
Daniel Stonedd1bc502019-06-17 12:13:46 +0100251struct drm_backend {
252 struct weston_backend base;
253 struct weston_compositor *compositor;
254
255 struct udev *udev;
256 struct wl_event_source *drm_source;
257
258 struct udev_monitor *udev_monitor;
259 struct wl_event_source *udev_drm_source;
260
261 struct {
262 int id;
263 int fd;
264 char *filename;
265 dev_t devnum;
266 } drm;
267 struct gbm_device *gbm;
268 struct wl_listener session_listener;
269 uint32_t gbm_format;
270
271 /* we need these parameters in order to not fail drmModeAddFB2()
272 * due to out of bounds dimensions, and then mistakenly set
273 * sprites_are_broken:
274 */
275 int min_width, max_width;
276 int min_height, max_height;
277
278 struct wl_list plane_list;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100279
280 void *repaint_data;
281
282 bool state_invalid;
283
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300284 /* drm_crtc::link */
285 struct wl_list crtc_list;
286
Leandro Ribeiro96bef052020-09-09 15:23:49 -0300287 /* drm_writeback::link */
288 struct wl_list writeback_connector_list;
289
Emmanuel Gil Peyrot1b3ad092019-12-09 02:50:55 +0100290 bool sprites_are_broken;
291 bool cursors_are_broken;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100292
Daniel Stonedd1bc502019-06-17 12:13:46 +0100293 bool atomic_modeset;
294
295 bool use_pixman;
296 bool use_pixman_shadow;
297
298 struct udev_input input;
299
300 int32_t cursor_width;
301 int32_t cursor_height;
302
303 uint32_t pageflip_timeout;
304
305 bool shutting_down;
306
307 bool aspect_ratio_supported;
308
309 bool fb_modifiers;
310
311 struct weston_log_scope *debug;
312};
313
314struct drm_mode {
315 struct weston_mode base;
316 drmModeModeInfo mode_info;
317 uint32_t blob_id;
318};
319
320enum drm_fb_type {
321 BUFFER_INVALID = 0, /**< never used */
322 BUFFER_CLIENT, /**< directly sourced from client */
323 BUFFER_DMABUF, /**< imported from linux_dmabuf client */
324 BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
325 BUFFER_GBM_SURFACE, /**< internal EGL rendering */
326 BUFFER_CURSOR, /**< internal cursor buffer */
327};
328
329struct drm_fb {
330 enum drm_fb_type type;
331
332 int refcnt;
333
334 uint32_t fb_id, size;
335 uint32_t handles[4];
336 uint32_t strides[4];
337 uint32_t offsets[4];
338 int num_planes;
339 const struct pixel_format_info *format;
340 uint64_t modifier;
341 int width, height;
342 int fd;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100343
344 /* Used by gbm fbs */
345 struct gbm_bo *bo;
346 struct gbm_surface *gbm_surface;
347
348 /* Used by dumb fbs */
349 void *map;
350};
351
352struct drm_edid {
353 char eisa_id[13];
354 char monitor_name[13];
355 char pnp_id[5];
356 char serial_number[13];
357};
358
359/**
360 * Pending state holds one or more drm_output_state structures, collected from
361 * performing repaint. This pending state is transient, and only lives between
362 * beginning a repaint group and flushing the results: after flush, each
363 * output state will complete and be retired separately.
364 */
365struct drm_pending_state {
366 struct drm_backend *backend;
367 struct wl_list output_list;
368};
369
370/*
371 * Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
372 * plus >= 1 each of encoder/connector/plane. Since everything but the planes
373 * is currently statically assigned per-output, we mainly use this to track
374 * plane state.
375 *
376 * pending_state is set when the output state is owned by a pending_state,
377 * i.e. when it is being constructed and has not yet been applied. When the
378 * output state has been applied, the owning pending_state is freed.
379 */
380struct drm_output_state {
381 struct drm_pending_state *pending_state;
382 struct drm_output *output;
383 struct wl_list link;
384 enum dpms_enum dpms;
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530385 enum weston_hdcp_protection protection;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100386 struct wl_list plane_list;
387};
388
389/**
Marius Vlad2538aac2019-10-14 11:05:30 +0300390 * An instance of this class is created each time we believe we have a plane
Maxime Roussin-Bélanger35e34502020-12-17 17:08:56 -0500391 * suitable to be used by a view as a direct scan-out. The list is initialized
Marius Vlad2538aac2019-10-14 11:05:30 +0300392 * and populated locally.
393 */
394struct drm_plane_zpos {
395 struct drm_plane *plane;
396 struct wl_list link; /**< :candidate_plane_zpos_list */
397};
398
399/**
Daniel Stonedd1bc502019-06-17 12:13:46 +0100400 * Plane state holds the dynamic state for a plane: where it is positioned,
401 * and which buffer it is currently displaying.
402 *
403 * The plane state is owned by an output state, except when setting an initial
404 * state. See drm_output_state for notes on state object lifetime.
405 */
406struct drm_plane_state {
407 struct drm_plane *plane;
408 struct drm_output *output;
409 struct drm_output_state *output_state;
410
411 struct drm_fb *fb;
Daniel Stone2ecc38b2021-11-18 15:33:17 +0000412 struct {
413 struct weston_buffer_reference buffer;
414 struct weston_buffer_release_reference release;
415 } fb_ref;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100416
417 struct weston_view *ev; /**< maintained for drm_assign_planes only */
418
419 int32_t src_x, src_y;
420 uint32_t src_w, src_h;
421 int32_t dest_x, dest_y;
422 uint32_t dest_w, dest_h;
423
Marius Vladcdd6fa22019-08-29 20:42:00 +0300424 uint64_t zpos;
425
Daniel Stonedd1bc502019-06-17 12:13:46 +0100426 bool complete;
427
428 /* We don't own the fd, so we shouldn't close it */
429 int in_fence_fd;
430
Scott Anderson15c603c2020-06-02 17:39:43 +1200431 uint32_t damage_blob_id; /* damage to kernel */
Daniel Stonedd1bc502019-06-17 12:13:46 +0100432
433 struct wl_list link; /* drm_output_state::plane_list */
434};
435
436/**
437 * A plane represents one buffer, positioned within a CRTC, and stacked
438 * relative to other planes on the same CRTC.
439 *
440 * Each CRTC has a 'primary plane', which use used to display the classic
441 * framebuffer contents, as accessed through the legacy drmModeSetCrtc
442 * call (which combines setting the CRTC's actual physical mode, and the
443 * properties of the primary plane).
444 *
445 * The cursor plane also has its own alternate legacy API.
446 *
447 * Other planes are used opportunistically to display content we do not
448 * wish to blit into the primary plane. These non-primary/cursor planes
449 * are referred to as 'sprites'.
450 */
451struct drm_plane {
452 struct weston_plane base;
453
454 struct drm_backend *backend;
455
456 enum wdrm_plane_type type;
457
458 uint32_t possible_crtcs;
459 uint32_t plane_id;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100460
461 struct drm_property_info props[WDRM_PLANE__COUNT];
462
463 /* The last state submitted to the kernel for this plane. */
464 struct drm_plane_state *state_cur;
465
Marius Vladcdd6fa22019-08-29 20:42:00 +0300466 uint64_t zpos_min;
467 uint64_t zpos_max;
468
Daniel Stonedd1bc502019-06-17 12:13:46 +0100469 struct wl_list link;
470
Scott Anderson74663092021-02-01 15:46:33 -0300471 struct weston_drm_format_array formats;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100472};
473
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300474struct drm_connector {
475 struct drm_backend *backend;
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300476
477 drmModeConnector *conn;
478 uint32_t connector_id;
479
Leandro Ribeiro702fbf72020-08-18 17:35:05 -0300480 drmModeObjectProperties *props_drm;
481
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300482 /* Holds the properties for the connector */
483 struct drm_property_info props[WDRM_CONNECTOR__COUNT];
484};
485
Leandro Ribeiro96bef052020-09-09 15:23:49 -0300486struct drm_writeback {
487 /* drm_backend::writeback_connector_list */
488 struct wl_list link;
489
490 struct drm_backend *backend;
491 struct drm_connector connector;
492};
493
Daniel Stonedd1bc502019-06-17 12:13:46 +0100494struct drm_head {
495 struct weston_head base;
496 struct drm_backend *backend;
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300497 struct drm_connector connector;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100498
Daniel Stonedd1bc502019-06-17 12:13:46 +0100499 struct drm_edid edid;
500
Daniel Stonedd1bc502019-06-17 12:13:46 +0100501 struct backlight *backlight;
502
503 drmModeModeInfo inherited_mode; /**< Original mode on the connector */
504 uint32_t inherited_crtc_id; /**< Original CRTC assignment */
505};
506
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300507struct drm_crtc {
508 /* drm_backend::crtc_list */
509 struct wl_list link;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100510 struct drm_backend *backend;
511
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300512 /* The output driven by the CRTC */
513 struct drm_output *output;
514
Daniel Stonedd1bc502019-06-17 12:13:46 +0100515 uint32_t crtc_id; /* object ID to pass to DRM functions */
516 int pipe; /* index of CRTC in resource array / bitmasks */
517
518 /* Holds the properties for the CRTC */
519 struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300520};
521
522struct drm_output {
523 struct weston_output base;
524 struct drm_backend *backend;
525 struct drm_crtc *crtc;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100526
Emmanuel Gil Peyrot1b3ad092019-12-09 02:50:55 +0100527 bool page_flip_pending;
528 bool atomic_complete_pending;
529 bool destroy_pending;
530 bool disable_pending;
531 bool dpms_off_pending;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100532
Stefan Agner974390a2019-07-08 00:42:05 +0200533 uint32_t gbm_cursor_handle[2];
Daniel Stonedd1bc502019-06-17 12:13:46 +0100534 struct drm_fb *gbm_cursor_fb[2];
535 struct drm_plane *cursor_plane;
536 struct weston_view *cursor_view;
Alexandros Frantzis10937fe2021-06-14 13:09:44 +0300537 struct wl_listener cursor_view_destroy_listener;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100538 int current_cursor;
539
540 struct gbm_surface *gbm_surface;
541 uint32_t gbm_format;
542 uint32_t gbm_bo_flags;
543
544 /* Plane being displayed directly on the CRTC */
545 struct drm_plane *scanout_plane;
546
547 /* The last state submitted to the kernel for this CRTC. */
548 struct drm_output_state *state_cur;
549 /* The previously-submitted state, where the hardware has not
550 * yet acknowledged completion of state_cur. */
551 struct drm_output_state *state_last;
552
553 struct drm_fb *dumb[2];
554 pixman_image_t *image[2];
555 int current_image;
556 pixman_region32_t previous_damage;
557
558 struct vaapi_recorder *recorder;
559 struct wl_listener recorder_frame_listener;
560
561 struct wl_event_source *pageflip_timer;
562
563 bool virtual;
564
565 submit_frame_cb virtual_submit_frame;
566};
567
568static inline struct drm_head *
569to_drm_head(struct weston_head *base)
570{
571 return container_of(base, struct drm_head, base);
572}
573
574static inline struct drm_output *
575to_drm_output(struct weston_output *base)
576{
577 return container_of(base, struct drm_output, base);
578}
579
580static inline struct drm_backend *
581to_drm_backend(struct weston_compositor *base)
582{
583 return container_of(base->backend, struct drm_backend, base);
584}
585
586static inline struct drm_mode *
587to_drm_mode(struct weston_mode *base)
588{
589 return container_of(base, struct drm_mode, base);
590}
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100591
Marius Vlad3dea57a2019-09-27 20:45:41 +0300592static inline const char *
593drm_output_get_plane_type_name(struct drm_plane *p)
594{
595 switch (p->type) {
596 case WDRM_PLANE_TYPE_PRIMARY:
597 return "primary";
598 case WDRM_PLANE_TYPE_CURSOR:
599 return "cursor";
600 case WDRM_PLANE_TYPE_OVERLAY:
601 return "overlay";
602 default:
603 assert(0);
604 break;
605 }
606}
607
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300608struct drm_crtc *
609drm_crtc_find(struct drm_backend *b, uint32_t crtc_id);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100610
611struct drm_head *
612drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id);
613
Daniel Stone7580b3c2019-06-18 11:16:53 +0100614static inline bool
615drm_view_transform_supported(struct weston_view *ev, struct weston_output *output)
616{
617 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
618
619 /* This will incorrectly disallow cases where the combination of
620 * buffer and view transformations match the output transform.
621 * Fixing this requires a full analysis of the transformation
622 * chain. */
623 if (ev->transform.enabled &&
624 ev->transform.matrix.type >= WESTON_MATRIX_TRANSFORM_ROTATE)
625 return false;
626
627 if (viewport->buffer.transform != output->transform)
628 return false;
629
630 return true;
631}
632
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100633int
634drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode);
635
636struct drm_mode *
637drm_output_choose_mode(struct drm_output *output,
638 struct weston_mode *target_mode);
639void
Leandro Ribeiro702fbf72020-08-18 17:35:05 -0300640update_head_from_connector(struct drm_head *head);
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100641
642void
643drm_mode_list_destroy(struct drm_backend *backend, struct wl_list *mode_list);
644
645void
646drm_output_print_modes(struct drm_output *output);
647
648int
649drm_output_set_mode(struct weston_output *base,
650 enum weston_drm_backend_output_mode mode,
651 const char *modeline);
652
Daniel Stone4c2fc702019-06-18 11:12:07 +0100653void
654drm_property_info_populate(struct drm_backend *b,
655 const struct drm_property_info *src,
656 struct drm_property_info *info,
657 unsigned int num_infos,
658 drmModeObjectProperties *props);
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100659uint64_t
660drm_property_get_value(struct drm_property_info *info,
661 const drmModeObjectProperties *props,
662 uint64_t def);
Marius Vlad1accffe2019-11-01 12:00:09 +0200663uint64_t *
664drm_property_get_range_values(struct drm_property_info *info,
665 const drmModeObjectProperties *props);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100666int
667drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane,
Stefan Agner465ab2c2020-06-17 23:36:44 +0200668 const drmModeObjectProperties *props,
669 const bool use_modifiers);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100670void
671drm_property_info_free(struct drm_property_info *info, int num_props);
672
673extern struct drm_property_enum_info plane_type_enums[];
674extern const struct drm_property_info plane_props[];
675extern struct drm_property_enum_info dpms_state_enums[];
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530676extern struct drm_property_enum_info content_protection_enums[];
677extern struct drm_property_enum_info hdcp_content_type_enums[];
Daniel Stone4c2fc702019-06-18 11:12:07 +0100678extern const struct drm_property_info connector_props[];
679extern const struct drm_property_info crtc_props[];
680
681int
682init_kms_caps(struct drm_backend *b);
683
684int
685drm_pending_state_test(struct drm_pending_state *pending_state);
686int
687drm_pending_state_apply(struct drm_pending_state *pending_state);
688int
689drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
690
691void
692drm_output_set_gamma(struct weston_output *output_base,
693 uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
694
695void
696drm_output_update_msc(struct drm_output *output, unsigned int seq);
697void
698drm_output_update_complete(struct drm_output *output, uint32_t flags,
699 unsigned int sec, unsigned int usec);
700int
701on_drm_input(int fd, uint32_t mask, void *data);
702
Daniel Stone7580b3c2019-06-18 11:16:53 +0100703struct drm_fb *
704drm_fb_ref(struct drm_fb *fb);
705void
706drm_fb_unref(struct drm_fb *fb);
707
708struct drm_fb *
709drm_fb_create_dumb(struct drm_backend *b, int width, int height,
710 uint32_t format);
711struct drm_fb *
712drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
713 bool is_opaque, enum drm_fb_type type);
Daniel Stone6b466f22019-06-18 11:30:54 +0100714
Alexandros Frantzis10937fe2021-06-14 13:09:44 +0300715void
716drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev);
717
Stefan Agnerccf24072019-07-09 22:02:00 +0200718#ifdef BUILD_DRM_GBM
719extern struct drm_fb *
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300720drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev,
721 uint32_t *try_view_on_plane_failure_reasons);
Marius Vlad81bada52019-11-11 00:27:17 +0200722extern bool
723drm_can_scanout_dmabuf(struct weston_compositor *ec,
724 struct linux_dmabuf_buffer *dmabuf);
Stefan Agnerccf24072019-07-09 22:02:00 +0200725#else
726static inline struct drm_fb *
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300727drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev,
728 uint32_t *try_view_on_plane_failure_reasons)
Stefan Agnerccf24072019-07-09 22:02:00 +0200729{
730 return NULL;
731}
Marius Vlad81bada52019-11-11 00:27:17 +0200732static inline bool
733drm_can_scanout_dmabuf(struct weston_compositor *ec,
734 struct linux_dmabuf_buffer *dmabuf)
735{
736 return false;
737}
Stefan Agnerccf24072019-07-09 22:02:00 +0200738#endif
Daniel Stone6b466f22019-06-18 11:30:54 +0100739
740struct drm_pending_state *
741drm_pending_state_alloc(struct drm_backend *backend);
742void
743drm_pending_state_free(struct drm_pending_state *pending_state);
744struct drm_output_state *
745drm_pending_state_get_output(struct drm_pending_state *pending_state,
746 struct drm_output *output);
747
748
749/**
750 * Mode for drm_output_state_duplicate.
751 */
752enum drm_output_state_duplicate_mode {
753 DRM_OUTPUT_STATE_CLEAR_PLANES, /**< reset all planes to off */
754 DRM_OUTPUT_STATE_PRESERVE_PLANES, /**< preserve plane state */
755};
756
757struct drm_output_state *
758drm_output_state_alloc(struct drm_output *output,
759 struct drm_pending_state *pending_state);
760struct drm_output_state *
761drm_output_state_duplicate(struct drm_output_state *src,
762 struct drm_pending_state *pending_state,
763 enum drm_output_state_duplicate_mode plane_mode);
764void
765drm_output_state_free(struct drm_output_state *state);
766struct drm_plane_state *
767drm_output_state_get_plane(struct drm_output_state *state_output,
768 struct drm_plane *plane);
769struct drm_plane_state *
770drm_output_state_get_existing_plane(struct drm_output_state *state_output,
771 struct drm_plane *plane);
772
773
774
775struct drm_plane_state *
776drm_plane_state_alloc(struct drm_output_state *state_output,
777 struct drm_plane *plane);
778struct drm_plane_state *
779drm_plane_state_duplicate(struct drm_output_state *state_output,
780 struct drm_plane_state *src);
781void
782drm_plane_state_free(struct drm_plane_state *state, bool force);
783void
784drm_plane_state_put_back(struct drm_plane_state *state);
785bool
786drm_plane_state_coords_for_view(struct drm_plane_state *state,
Marius Vlad2538aac2019-10-14 11:05:30 +0300787 struct weston_view *ev, uint64_t zpos);
Alexandros Frantzis99751342020-05-18 15:22:49 +0300788void
789drm_plane_reset_state(struct drm_plane *plane);
Daniel Stonee404b722019-06-22 18:40:31 +0100790
791void
792drm_assign_planes(struct weston_output *output_base, void *repaint_data);
793
794bool
795drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
Stefan Agner3654c672019-07-09 00:50:30 +0200796
797void
798drm_output_render(struct drm_output_state *state, pixman_region32_t *damage);
799
800int
801parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format);
802
803extern struct gl_renderer_interface *gl_renderer;
804
805#ifdef BUILD_DRM_VIRTUAL
806extern int
807drm_backend_init_virtual_output_api(struct weston_compositor *compositor);
808#else
809inline static int
810drm_backend_init_virtual_output_api(struct weston_compositor *compositor)
811{
812 return 0;
813}
814#endif
815
Stefan Agnerccf24072019-07-09 22:02:00 +0200816#ifdef BUILD_DRM_GBM
817int
818init_egl(struct drm_backend *b);
819
Stefan Agner3654c672019-07-09 00:50:30 +0200820int
821drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
Stefan Agnerccf24072019-07-09 22:02:00 +0200822
Stefan Agner3654c672019-07-09 00:50:30 +0200823void
824drm_output_fini_egl(struct drm_output *output);
825
Stefan Agnerccf24072019-07-09 22:02:00 +0200826struct drm_fb *
827drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
828
829void
830renderer_switch_binding(struct weston_keyboard *keyboard,
831 const struct timespec *time, uint32_t key, void *data);
832#else
833inline static int
834init_egl(struct drm_backend *b)
835{
836 weston_log("Compiled without GBM/EGL support\n");
837 return -1;
838}
839
840inline static int
841drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
842{
843 return -1;
844}
845
846inline static void
847drm_output_fini_egl(struct drm_output *output)
848{
849}
850
851inline static struct drm_fb *
852drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
853{
854 return NULL;
855}
856
857inline static void
858renderer_switch_binding(struct weston_keyboard *keyboard,
859 const struct timespec *time, uint32_t key, void *data)
860{
861 weston_log("Compiled without GBM/EGL support\n");
862}
863#endif