blob: d4747b2f8bb6de98ac49d94e2b7d3ac847f36d3b [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
limin.tian85cd2462024-08-12 08:04:12 +000075#ifndef DEFAULT_OSD_PLANE_ZPOS
76#define DEFAULT_OSD_PLANE_ZPOS 65
77#endif
78
Daniel Stonedd1bc502019-06-17 12:13:46 +010079/**
80 * A small wrapper to print information into the 'drm-backend' debug scope.
81 *
82 * The following conventions are used to print variables:
83 *
84 * - fixed uint32_t values, including Weston object IDs such as weston_output
85 * IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats:
86 * "%lu (0x%lx)" (unsigned long) value, (unsigned long) value
87 *
88 * - fixed uint64_t values, such as DRM property values (including object IDs
89 * when used as a value):
90 * "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value
91 *
92 * - non-fixed-width signed int:
93 * "%d" value
94 *
95 * - non-fixed-width unsigned int:
96 * "%u (0x%x)" value, value
97 *
98 * - non-fixed-width unsigned long:
99 * "%lu (0x%lx)" value, value
100 *
101 * Either the integer or hexadecimal forms may be omitted if it is known that
102 * one representation is not useful (e.g. width/height in hex are rarely what
103 * you want).
104 *
105 * This is to avoid implicit widening or narrowing when we use fixed-size
106 * types: uint32_t can be resolved by either unsigned int or unsigned long
107 * on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t
108 * being unsigned long long on a 32-bit system and unsigned long on a 64-bit
109 * system. To avoid confusing side effects, we explicitly cast to the widest
110 * possible type and use a matching format specifier.
111 */
112#define drm_debug(b, ...) \
113 weston_log_scope_printf((b)->debug, __VA_ARGS__)
114
115#define MAX_CLONED_CONNECTORS 4
116
Stefan Agner723c6a12019-12-09 13:06:36 +0100117
Daniel Stonedd1bc502019-06-17 12:13:46 +0100118/**
Daniel Stonedd1bc502019-06-17 12:13:46 +0100119 * Represents the values of an enum-type KMS property
120 */
121struct drm_property_enum_info {
122 const char *name; /**< name as string (static, not freed) */
123 bool valid; /**< true if value is supported; ignore if false */
124 uint64_t value; /**< raw value */
125};
126
127/**
128 * Holds information on a DRM property, including its ID and the enum
129 * values it holds.
130 *
131 * DRM properties are allocated dynamically, and maintained as DRM objects
132 * within the normal object ID space; they thus do not have a stable ID
133 * to refer to. This includes enum values, which must be referred to by
134 * integer values, but these are not stable.
135 *
136 * drm_property_info allows a cache to be maintained where Weston can use
137 * enum values internally to refer to properties, with the mapping to DRM
138 * ID values being maintained internally.
139 */
140struct drm_property_info {
141 const char *name; /**< name as string (static, not freed) */
142 uint32_t prop_id; /**< KMS property object ID */
Marius Vlad1accffe2019-11-01 12:00:09 +0200143 uint32_t flags;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100144 unsigned int num_enum_values; /**< number of enum values */
145 struct drm_property_enum_info *enum_values; /**< array of enum values */
Marius Vlad1accffe2019-11-01 12:00:09 +0200146 unsigned int num_range_values;
147 uint64_t range_values[2];
Daniel Stonedd1bc502019-06-17 12:13:46 +0100148};
149
150/**
151 * List of properties attached to DRM planes
152 */
153enum wdrm_plane_property {
154 WDRM_PLANE_TYPE = 0,
155 WDRM_PLANE_SRC_X,
156 WDRM_PLANE_SRC_Y,
157 WDRM_PLANE_SRC_W,
158 WDRM_PLANE_SRC_H,
159 WDRM_PLANE_CRTC_X,
160 WDRM_PLANE_CRTC_Y,
161 WDRM_PLANE_CRTC_W,
162 WDRM_PLANE_CRTC_H,
163 WDRM_PLANE_FB_ID,
164 WDRM_PLANE_CRTC_ID,
165 WDRM_PLANE_IN_FORMATS,
166 WDRM_PLANE_IN_FENCE_FD,
167 WDRM_PLANE_FB_DAMAGE_CLIPS,
Marius Vladcdd6fa22019-08-29 20:42:00 +0300168 WDRM_PLANE_ZPOS,
chen.wang1f06854b2024-09-26 11:26:04 +0000169 WDRM_PLANE_VIDEO_ROTATION,
leng.fanga0f20922024-10-11 17:23:59 +0800170 WDRM_PLANE_ALPHA,
Daniel Stonedd1bc502019-06-17 12:13:46 +0100171 WDRM_PLANE__COUNT
172};
173
174/**
175 * Possible values for the WDRM_PLANE_TYPE property.
176 */
177enum wdrm_plane_type {
178 WDRM_PLANE_TYPE_PRIMARY = 0,
179 WDRM_PLANE_TYPE_CURSOR,
180 WDRM_PLANE_TYPE_OVERLAY,
181 WDRM_PLANE_TYPE__COUNT
182};
183
184/**
185 * List of properties attached to a DRM connector
186 */
187enum wdrm_connector_property {
188 WDRM_CONNECTOR_EDID = 0,
189 WDRM_CONNECTOR_DPMS,
190 WDRM_CONNECTOR_CRTC_ID,
191 WDRM_CONNECTOR_NON_DESKTOP,
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530192 WDRM_CONNECTOR_CONTENT_PROTECTION,
193 WDRM_CONNECTOR_HDCP_CONTENT_TYPE,
Lucas Stach72e7a1e2019-11-25 23:31:57 +0000194 WDRM_CONNECTOR_PANEL_ORIENTATION,
Daniel Stonedd1bc502019-06-17 12:13:46 +0100195 WDRM_CONNECTOR__COUNT
196};
197
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530198enum wdrm_content_protection_state {
199 WDRM_CONTENT_PROTECTION_UNDESIRED = 0,
200 WDRM_CONTENT_PROTECTION_DESIRED,
201 WDRM_CONTENT_PROTECTION_ENABLED,
202 WDRM_CONTENT_PROTECTION__COUNT
203};
204
205enum wdrm_hdcp_content_type {
206 WDRM_HDCP_CONTENT_TYPE0 = 0,
207 WDRM_HDCP_CONTENT_TYPE1,
208 WDRM_HDCP_CONTENT_TYPE__COUNT
209};
210
Daniel Stonedd1bc502019-06-17 12:13:46 +0100211enum wdrm_dpms_state {
212 WDRM_DPMS_STATE_OFF = 0,
213 WDRM_DPMS_STATE_ON,
214 WDRM_DPMS_STATE_STANDBY, /* unused */
215 WDRM_DPMS_STATE_SUSPEND, /* unused */
216 WDRM_DPMS_STATE__COUNT
217};
218
Lucas Stach72e7a1e2019-11-25 23:31:57 +0000219enum wdrm_panel_orientation {
220 WDRM_PANEL_ORIENTATION_NORMAL = 0,
221 WDRM_PANEL_ORIENTATION_UPSIDE_DOWN,
222 WDRM_PANEL_ORIENTATION_LEFT_SIDE_UP,
223 WDRM_PANEL_ORIENTATION_RIGHT_SIDE_UP,
224 WDRM_PANEL_ORIENTATION__COUNT
225};
226
Daniel Stonedd1bc502019-06-17 12:13:46 +0100227/**
228 * List of properties attached to DRM CRTCs
229 */
230enum wdrm_crtc_property {
231 WDRM_CRTC_MODE_ID = 0,
232 WDRM_CRTC_ACTIVE,
233 WDRM_CRTC__COUNT
234};
235
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300236/**
237 * Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
238 */
239enum try_view_on_plane_failure_reasons {
240 FAILURE_REASONS_NONE = 0,
241 FAILURE_REASONS_FORCE_RENDERER = (1 << 0),
242 FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = (1 << 1),
243 FAILURE_REASONS_DMABUF_MODIFIER_INVALID = (1 << 2),
244 FAILURE_REASONS_ADD_FB_FAILED = (1 << 3),
245};
246
Leandro Ribeiro54293022021-10-12 14:48:36 -0300247/**
248 * We use this to keep track of actions we need to do with the dma-buf feedback
249 * in order to keep it up-to-date with the info we get from the DRM-backend.
250 */
251enum actions_needed_dmabuf_feedback {
252 ACTION_NEEDED_NONE = 0,
253 ACTION_NEEDED_ADD_SCANOUT_TRANCHE = (1 << 0),
254 ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
255};
256
Daniel Stonedd1bc502019-06-17 12:13:46 +0100257struct drm_backend {
258 struct weston_backend base;
259 struct weston_compositor *compositor;
260
261 struct udev *udev;
262 struct wl_event_source *drm_source;
263
264 struct udev_monitor *udev_monitor;
265 struct wl_event_source *udev_drm_source;
266
267 struct {
268 int id;
269 int fd;
270 char *filename;
271 dev_t devnum;
272 } drm;
273 struct gbm_device *gbm;
274 struct wl_listener session_listener;
275 uint32_t gbm_format;
276
277 /* we need these parameters in order to not fail drmModeAddFB2()
278 * due to out of bounds dimensions, and then mistakenly set
279 * sprites_are_broken:
280 */
281 int min_width, max_width;
282 int min_height, max_height;
283
284 struct wl_list plane_list;
Daniel Stone57d609a2021-11-16 18:56:09 +0000285 uint32_t next_plane_idx;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100286
287 void *repaint_data;
288
289 bool state_invalid;
290
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300291 /* drm_crtc::link */
292 struct wl_list crtc_list;
293
Leandro Ribeiro96bef052020-09-09 15:23:49 -0300294 /* drm_writeback::link */
295 struct wl_list writeback_connector_list;
296
Emmanuel Gil Peyrot1b3ad092019-12-09 02:50:55 +0100297 bool sprites_are_broken;
298 bool cursors_are_broken;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100299
Daniel Stonedd1bc502019-06-17 12:13:46 +0100300 bool atomic_modeset;
301
302 bool use_pixman;
303 bool use_pixman_shadow;
304
305 struct udev_input input;
306
307 int32_t cursor_width;
308 int32_t cursor_height;
309
310 uint32_t pageflip_timeout;
311
312 bool shutting_down;
313
314 bool aspect_ratio_supported;
315
316 bool fb_modifiers;
317
318 struct weston_log_scope *debug;
leng.fang32af9fc2024-06-13 11:22:15 +0800319
320#ifdef MESON_DRM_FIX_UI_SIZE
321 /** Set the logic window size
322 * the current_mode 's w/h will not equal real display mode size any more
323 * after enable fixed ui size. */
324 struct weston_size fixed_ui_size;
325#endif
leng.fang32af9fc2024-06-13 11:22:15 +0800326 int vdin_detect_fd;
leng.fang32af9fc2024-06-13 11:22:15 +0800327 bool allow_modeset;
leng.fang9cf09e22024-07-17 20:01:11 +0800328 int display_enable;
limin.tianaaaff782024-12-20 09:49:25 +0000329 int hdmitx_hdcppwr;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100330};
331
332struct drm_mode {
333 struct weston_mode base;
334 drmModeModeInfo mode_info;
335 uint32_t blob_id;
336};
337
338enum drm_fb_type {
339 BUFFER_INVALID = 0, /**< never used */
340 BUFFER_CLIENT, /**< directly sourced from client */
341 BUFFER_DMABUF, /**< imported from linux_dmabuf client */
342 BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
343 BUFFER_GBM_SURFACE, /**< internal EGL rendering */
344 BUFFER_CURSOR, /**< internal cursor buffer */
345};
346
347struct drm_fb {
348 enum drm_fb_type type;
349
350 int refcnt;
351
352 uint32_t fb_id, size;
353 uint32_t handles[4];
354 uint32_t strides[4];
355 uint32_t offsets[4];
356 int num_planes;
357 const struct pixel_format_info *format;
358 uint64_t modifier;
359 int width, height;
360 int fd;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100361
Daniel Stone57d609a2021-11-16 18:56:09 +0000362 uint32_t plane_mask;
363
Daniel Stonedd1bc502019-06-17 12:13:46 +0100364 /* Used by gbm fbs */
365 struct gbm_bo *bo;
366 struct gbm_surface *gbm_surface;
367
368 /* Used by dumb fbs */
369 void *map;
leng.fang32af9fc2024-06-13 11:22:15 +0800370 struct drm_plane *plane;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100371};
372
Daniel Stone7d27df42021-11-18 16:01:03 +0000373struct drm_buffer_fb {
374 struct drm_fb *fb;
375 enum try_view_on_plane_failure_reasons failure_reasons;
376 struct wl_listener buffer_destroy_listener;
377};
378
Daniel Stonedd1bc502019-06-17 12:13:46 +0100379struct drm_edid {
380 char eisa_id[13];
381 char monitor_name[13];
382 char pnp_id[5];
383 char serial_number[13];
384};
385
386/**
387 * Pending state holds one or more drm_output_state structures, collected from
388 * performing repaint. This pending state is transient, and only lives between
389 * beginning a repaint group and flushing the results: after flush, each
390 * output state will complete and be retired separately.
391 */
392struct drm_pending_state {
393 struct drm_backend *backend;
394 struct wl_list output_list;
395};
396
397/*
398 * Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
399 * plus >= 1 each of encoder/connector/plane. Since everything but the planes
400 * is currently statically assigned per-output, we mainly use this to track
401 * plane state.
402 *
403 * pending_state is set when the output state is owned by a pending_state,
404 * i.e. when it is being constructed and has not yet been applied. When the
405 * output state has been applied, the owning pending_state is freed.
406 */
407struct drm_output_state {
408 struct drm_pending_state *pending_state;
409 struct drm_output *output;
410 struct wl_list link;
411 enum dpms_enum dpms;
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530412 enum weston_hdcp_protection protection;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100413 struct wl_list plane_list;
414};
415
416/**
Marius Vlad2538aac2019-10-14 11:05:30 +0300417 * An instance of this class is created each time we believe we have a plane
Maxime Roussin-Bélanger35e34502020-12-17 17:08:56 -0500418 * suitable to be used by a view as a direct scan-out. The list is initialized
Marius Vlad2538aac2019-10-14 11:05:30 +0300419 * and populated locally.
420 */
421struct drm_plane_zpos {
422 struct drm_plane *plane;
423 struct wl_list link; /**< :candidate_plane_zpos_list */
424};
425
426/**
Daniel Stonedd1bc502019-06-17 12:13:46 +0100427 * Plane state holds the dynamic state for a plane: where it is positioned,
428 * and which buffer it is currently displaying.
429 *
430 * The plane state is owned by an output state, except when setting an initial
431 * state. See drm_output_state for notes on state object lifetime.
432 */
433struct drm_plane_state {
434 struct drm_plane *plane;
435 struct drm_output *output;
436 struct drm_output_state *output_state;
437
438 struct drm_fb *fb;
Daniel Stone2ecc38b2021-11-18 15:33:17 +0000439 struct {
440 struct weston_buffer_reference buffer;
441 struct weston_buffer_release_reference release;
442 } fb_ref;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100443
444 struct weston_view *ev; /**< maintained for drm_assign_planes only */
445
446 int32_t src_x, src_y;
447 uint32_t src_w, src_h;
448 int32_t dest_x, dest_y;
449 uint32_t dest_w, dest_h;
450
Marius Vladcdd6fa22019-08-29 20:42:00 +0300451 uint64_t zpos;
chen.wang1fdc0f562024-09-04 07:57:16 +0000452 uint64_t video_zpos;
Marius Vladcdd6fa22019-08-29 20:42:00 +0300453
Daniel Stonedd1bc502019-06-17 12:13:46 +0100454 bool complete;
455
456 /* We don't own the fd, so we shouldn't close it */
457 int in_fence_fd;
458
Scott Anderson15c603c2020-06-02 17:39:43 +1200459 uint32_t damage_blob_id; /* damage to kernel */
Daniel Stonedd1bc502019-06-17 12:13:46 +0100460
461 struct wl_list link; /* drm_output_state::plane_list */
chen.wang1f06854b2024-09-26 11:26:04 +0000462 uint32_t video_transform;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100463};
464
465/**
466 * A plane represents one buffer, positioned within a CRTC, and stacked
467 * relative to other planes on the same CRTC.
468 *
469 * Each CRTC has a 'primary plane', which use used to display the classic
470 * framebuffer contents, as accessed through the legacy drmModeSetCrtc
471 * call (which combines setting the CRTC's actual physical mode, and the
472 * properties of the primary plane).
473 *
474 * The cursor plane also has its own alternate legacy API.
475 *
476 * Other planes are used opportunistically to display content we do not
477 * wish to blit into the primary plane. These non-primary/cursor planes
478 * are referred to as 'sprites'.
479 */
480struct drm_plane {
481 struct weston_plane base;
482
483 struct drm_backend *backend;
484
485 enum wdrm_plane_type type;
486
487 uint32_t possible_crtcs;
488 uint32_t plane_id;
Daniel Stone57d609a2021-11-16 18:56:09 +0000489 uint32_t plane_idx;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100490
491 struct drm_property_info props[WDRM_PLANE__COUNT];
492
493 /* The last state submitted to the kernel for this plane. */
494 struct drm_plane_state *state_cur;
495
Marius Vladcdd6fa22019-08-29 20:42:00 +0300496 uint64_t zpos_min;
497 uint64_t zpos_max;
498
Daniel Stonedd1bc502019-06-17 12:13:46 +0100499 struct wl_list link;
500
leng.fang32af9fc2024-06-13 11:22:15 +0800501 bool is_video_plane;
502 int video_plane;
503 bool keep_last_frame;
504 uint32_t last_fb_id;
505 struct drm_crtc *crtc;
506
Scott Anderson74663092021-02-01 15:46:33 -0300507 struct weston_drm_format_array formats;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100508};
509
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300510struct drm_connector {
511 struct drm_backend *backend;
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300512
513 drmModeConnector *conn;
514 uint32_t connector_id;
515
Leandro Ribeiro702fbf72020-08-18 17:35:05 -0300516 drmModeObjectProperties *props_drm;
517
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300518 /* Holds the properties for the connector */
519 struct drm_property_info props[WDRM_CONNECTOR__COUNT];
520};
521
Leandro Ribeiro96bef052020-09-09 15:23:49 -0300522struct drm_writeback {
523 /* drm_backend::writeback_connector_list */
524 struct wl_list link;
525
526 struct drm_backend *backend;
527 struct drm_connector connector;
528};
529
Daniel Stonedd1bc502019-06-17 12:13:46 +0100530struct drm_head {
531 struct weston_head base;
532 struct drm_backend *backend;
Leandro Ribeiroe6369902020-06-17 11:09:47 -0300533 struct drm_connector connector;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100534
Daniel Stonedd1bc502019-06-17 12:13:46 +0100535 struct drm_edid edid;
536
Daniel Stonedd1bc502019-06-17 12:13:46 +0100537 struct backlight *backlight;
538
539 drmModeModeInfo inherited_mode; /**< Original mode on the connector */
540 uint32_t inherited_crtc_id; /**< Original CRTC assignment */
541};
542
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300543struct drm_crtc {
544 /* drm_backend::crtc_list */
545 struct wl_list link;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100546 struct drm_backend *backend;
547
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300548 /* The output driven by the CRTC */
549 struct drm_output *output;
550
Daniel Stonedd1bc502019-06-17 12:13:46 +0100551 uint32_t crtc_id; /* object ID to pass to DRM functions */
552 int pipe; /* index of CRTC in resource array / bitmasks */
553
554 /* Holds the properties for the CRTC */
555 struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
leng.fang32af9fc2024-06-13 11:22:15 +0800556 bool output_change;
557 struct drm_output *disable_output;
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300558};
559
560struct drm_output {
561 struct weston_output base;
562 struct drm_backend *backend;
563 struct drm_crtc *crtc;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100564
Emmanuel Gil Peyrot1b3ad092019-12-09 02:50:55 +0100565 bool page_flip_pending;
566 bool atomic_complete_pending;
567 bool destroy_pending;
568 bool disable_pending;
569 bool dpms_off_pending;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100570
Stefan Agner974390a2019-07-08 00:42:05 +0200571 uint32_t gbm_cursor_handle[2];
Daniel Stonedd1bc502019-06-17 12:13:46 +0100572 struct drm_fb *gbm_cursor_fb[2];
573 struct drm_plane *cursor_plane;
574 struct weston_view *cursor_view;
Alexandros Frantzis10937fe2021-06-14 13:09:44 +0300575 struct wl_listener cursor_view_destroy_listener;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100576 int current_cursor;
577
578 struct gbm_surface *gbm_surface;
579 uint32_t gbm_format;
580 uint32_t gbm_bo_flags;
581
582 /* Plane being displayed directly on the CRTC */
583 struct drm_plane *scanout_plane;
584
585 /* The last state submitted to the kernel for this CRTC. */
586 struct drm_output_state *state_cur;
587 /* The previously-submitted state, where the hardware has not
588 * yet acknowledged completion of state_cur. */
589 struct drm_output_state *state_last;
590
591 struct drm_fb *dumb[2];
592 pixman_image_t *image[2];
593 int current_image;
594 pixman_region32_t previous_damage;
595
596 struct vaapi_recorder *recorder;
597 struct wl_listener recorder_frame_listener;
598
599 struct wl_event_source *pageflip_timer;
600
601 bool virtual;
leng.fang32af9fc2024-06-13 11:22:15 +0800602 int video_plane_count;
Daniel Stonedd1bc502019-06-17 12:13:46 +0100603
604 submit_frame_cb virtual_submit_frame;
leng.fang32af9fc2024-06-13 11:22:15 +0800605
606#ifdef MESON_DRM_FIX_UI_SIZE
607 bool current_mode_need_restore;
608
609 /* the real display mode size will saved out of the current mode */
610 struct weston_size display_size;
611#endif
612
Daniel Stonedd1bc502019-06-17 12:13:46 +0100613};
614
615static inline struct drm_head *
616to_drm_head(struct weston_head *base)
617{
618 return container_of(base, struct drm_head, base);
619}
620
621static inline struct drm_output *
622to_drm_output(struct weston_output *base)
623{
624 return container_of(base, struct drm_output, base);
625}
626
627static inline struct drm_backend *
628to_drm_backend(struct weston_compositor *base)
629{
630 return container_of(base->backend, struct drm_backend, base);
631}
632
leng.fang32af9fc2024-06-13 11:22:15 +0800633static inline struct drm_plane *
634to_drm_plane(struct weston_plane *base)
635{
636 return container_of(base, struct drm_plane, base);
637}
638
Daniel Stonedd1bc502019-06-17 12:13:46 +0100639static inline struct drm_mode *
640to_drm_mode(struct weston_mode *base)
641{
642 return container_of(base, struct drm_mode, base);
643}
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100644
Marius Vlad3dea57a2019-09-27 20:45:41 +0300645static inline const char *
646drm_output_get_plane_type_name(struct drm_plane *p)
647{
648 switch (p->type) {
649 case WDRM_PLANE_TYPE_PRIMARY:
650 return "primary";
651 case WDRM_PLANE_TYPE_CURSOR:
652 return "cursor";
653 case WDRM_PLANE_TYPE_OVERLAY:
654 return "overlay";
655 default:
656 assert(0);
657 break;
658 }
659}
660
Leandro Ribeirob00d1a22020-08-13 14:12:28 -0300661struct drm_crtc *
662drm_crtc_find(struct drm_backend *b, uint32_t crtc_id);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100663
664struct drm_head *
665drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id);
666
Daniel Stone7580b3c2019-06-18 11:16:53 +0100667static inline bool
668drm_view_transform_supported(struct weston_view *ev, struct weston_output *output)
669{
670 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
671
672 /* This will incorrectly disallow cases where the combination of
673 * buffer and view transformations match the output transform.
674 * Fixing this requires a full analysis of the transformation
675 * chain. */
chen.wang1f06854b2024-09-26 11:26:04 +0000676 if (ev->surface->is_video_surface) {
677 weston_log("\n %s %d video surface return true\n", __FUNCTION__,__LINE__);
678 return true;
679 }
Daniel Stone7580b3c2019-06-18 11:16:53 +0100680 if (ev->transform.enabled &&
681 ev->transform.matrix.type >= WESTON_MATRIX_TRANSFORM_ROTATE)
682 return false;
683
684 if (viewport->buffer.transform != output->transform)
685 return false;
686
687 return true;
688}
leng.fang32af9fc2024-06-13 11:22:15 +0800689struct weston_plane *
690drm_get_weston_plane(struct drm_backend *backend, struct drm_plane* drm_plane);
Daniel Stone7580b3c2019-06-18 11:16:53 +0100691
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100692int
693drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode);
694
695struct drm_mode *
696drm_output_choose_mode(struct drm_output *output,
697 struct weston_mode *target_mode);
698void
Leandro Ribeiro702fbf72020-08-18 17:35:05 -0300699update_head_from_connector(struct drm_head *head);
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100700
701void
702drm_mode_list_destroy(struct drm_backend *backend, struct wl_list *mode_list);
703
704void
705drm_output_print_modes(struct drm_output *output);
706
707int
708drm_output_set_mode(struct weston_output *base,
709 enum weston_drm_backend_output_mode mode,
710 const char *modeline);
711
Daniel Stone4c2fc702019-06-18 11:12:07 +0100712void
713drm_property_info_populate(struct drm_backend *b,
714 const struct drm_property_info *src,
715 struct drm_property_info *info,
716 unsigned int num_infos,
717 drmModeObjectProperties *props);
Daniel Stonefbe6c1d2019-06-17 16:04:26 +0100718uint64_t
719drm_property_get_value(struct drm_property_info *info,
720 const drmModeObjectProperties *props,
721 uint64_t def);
Marius Vlad1accffe2019-11-01 12:00:09 +0200722uint64_t *
723drm_property_get_range_values(struct drm_property_info *info,
724 const drmModeObjectProperties *props);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100725int
726drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane,
Stefan Agner465ab2c2020-06-17 23:36:44 +0200727 const drmModeObjectProperties *props,
728 const bool use_modifiers);
Daniel Stone4c2fc702019-06-18 11:12:07 +0100729void
730drm_property_info_free(struct drm_property_info *info, int num_props);
731
732extern struct drm_property_enum_info plane_type_enums[];
733extern const struct drm_property_info plane_props[];
734extern struct drm_property_enum_info dpms_state_enums[];
Ankit Nautiyala344fe32019-05-14 18:36:08 +0530735extern struct drm_property_enum_info content_protection_enums[];
736extern struct drm_property_enum_info hdcp_content_type_enums[];
Daniel Stone4c2fc702019-06-18 11:12:07 +0100737extern const struct drm_property_info connector_props[];
738extern const struct drm_property_info crtc_props[];
739
740int
741init_kms_caps(struct drm_backend *b);
742
743int
744drm_pending_state_test(struct drm_pending_state *pending_state);
745int
746drm_pending_state_apply(struct drm_pending_state *pending_state);
747int
748drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
749
750void
751drm_output_set_gamma(struct weston_output *output_base,
752 uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
753
754void
755drm_output_update_msc(struct drm_output *output, unsigned int seq);
756void
757drm_output_update_complete(struct drm_output *output, uint32_t flags,
758 unsigned int sec, unsigned int usec);
759int
760on_drm_input(int fd, uint32_t mask, void *data);
761
Daniel Stone7580b3c2019-06-18 11:16:53 +0100762struct drm_fb *
763drm_fb_ref(struct drm_fb *fb);
764void
765drm_fb_unref(struct drm_fb *fb);
766
767struct drm_fb *
768drm_fb_create_dumb(struct drm_backend *b, int width, int height,
769 uint32_t format);
770struct drm_fb *
771drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend,
772 bool is_opaque, enum drm_fb_type type);
Daniel Stone6b466f22019-06-18 11:30:54 +0100773
Alexandros Frantzis10937fe2021-06-14 13:09:44 +0300774void
775drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev);
776
Stefan Agnerccf24072019-07-09 22:02:00 +0200777#ifdef BUILD_DRM_GBM
778extern struct drm_fb *
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300779drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev,
780 uint32_t *try_view_on_plane_failure_reasons);
Marius Vlad81bada52019-11-11 00:27:17 +0200781extern bool
782drm_can_scanout_dmabuf(struct weston_compositor *ec,
783 struct linux_dmabuf_buffer *dmabuf);
Stefan Agnerccf24072019-07-09 22:02:00 +0200784#else
785static inline struct drm_fb *
Leandro Ribeiro0a7034c2021-09-13 14:52:53 -0300786drm_fb_get_from_view(struct drm_output_state *state, struct weston_view *ev,
787 uint32_t *try_view_on_plane_failure_reasons)
Stefan Agnerccf24072019-07-09 22:02:00 +0200788{
789 return NULL;
790}
Marius Vlad81bada52019-11-11 00:27:17 +0200791static inline bool
792drm_can_scanout_dmabuf(struct weston_compositor *ec,
793 struct linux_dmabuf_buffer *dmabuf)
794{
795 return false;
796}
Stefan Agnerccf24072019-07-09 22:02:00 +0200797#endif
Daniel Stone6b466f22019-06-18 11:30:54 +0100798
799struct drm_pending_state *
800drm_pending_state_alloc(struct drm_backend *backend);
801void
802drm_pending_state_free(struct drm_pending_state *pending_state);
803struct drm_output_state *
804drm_pending_state_get_output(struct drm_pending_state *pending_state,
805 struct drm_output *output);
806
807
808/**
809 * Mode for drm_output_state_duplicate.
810 */
811enum drm_output_state_duplicate_mode {
812 DRM_OUTPUT_STATE_CLEAR_PLANES, /**< reset all planes to off */
813 DRM_OUTPUT_STATE_PRESERVE_PLANES, /**< preserve plane state */
814};
815
816struct drm_output_state *
817drm_output_state_alloc(struct drm_output *output,
818 struct drm_pending_state *pending_state);
819struct drm_output_state *
820drm_output_state_duplicate(struct drm_output_state *src,
821 struct drm_pending_state *pending_state,
822 enum drm_output_state_duplicate_mode plane_mode);
823void
824drm_output_state_free(struct drm_output_state *state);
825struct drm_plane_state *
826drm_output_state_get_plane(struct drm_output_state *state_output,
827 struct drm_plane *plane);
828struct drm_plane_state *
829drm_output_state_get_existing_plane(struct drm_output_state *state_output,
830 struct drm_plane *plane);
831
832
833
834struct drm_plane_state *
835drm_plane_state_alloc(struct drm_output_state *state_output,
836 struct drm_plane *plane);
837struct drm_plane_state *
838drm_plane_state_duplicate(struct drm_output_state *state_output,
839 struct drm_plane_state *src);
840void
841drm_plane_state_free(struct drm_plane_state *state, bool force);
842void
843drm_plane_state_put_back(struct drm_plane_state *state);
844bool
845drm_plane_state_coords_for_view(struct drm_plane_state *state,
Marius Vlad2538aac2019-10-14 11:05:30 +0300846 struct weston_view *ev, uint64_t zpos);
Alexandros Frantzis99751342020-05-18 15:22:49 +0300847void
848drm_plane_reset_state(struct drm_plane *plane);
Daniel Stonee404b722019-06-22 18:40:31 +0100849
850void
851drm_assign_planes(struct weston_output *output_base, void *repaint_data);
852
853bool
854drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
Stefan Agner3654c672019-07-09 00:50:30 +0200855
856void
857drm_output_render(struct drm_output_state *state, pixman_region32_t *damage);
858
859int
860parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format);
861
862extern struct gl_renderer_interface *gl_renderer;
863
864#ifdef BUILD_DRM_VIRTUAL
865extern int
866drm_backend_init_virtual_output_api(struct weston_compositor *compositor);
867#else
868inline static int
869drm_backend_init_virtual_output_api(struct weston_compositor *compositor)
870{
871 return 0;
872}
873#endif
874
Stefan Agnerccf24072019-07-09 22:02:00 +0200875#ifdef BUILD_DRM_GBM
876int
877init_egl(struct drm_backend *b);
878
Stefan Agner3654c672019-07-09 00:50:30 +0200879int
880drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
Stefan Agnerccf24072019-07-09 22:02:00 +0200881
Stefan Agner3654c672019-07-09 00:50:30 +0200882void
883drm_output_fini_egl(struct drm_output *output);
884
Stefan Agnerccf24072019-07-09 22:02:00 +0200885struct drm_fb *
886drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
887
888void
889renderer_switch_binding(struct weston_keyboard *keyboard,
890 const struct timespec *time, uint32_t key, void *data);
891#else
892inline static int
893init_egl(struct drm_backend *b)
894{
895 weston_log("Compiled without GBM/EGL support\n");
896 return -1;
897}
898
899inline static int
900drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
901{
902 return -1;
903}
904
905inline static void
906drm_output_fini_egl(struct drm_output *output)
907{
908}
909
910inline static struct drm_fb *
911drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
912{
913 return NULL;
914}
915
916inline static void
917renderer_switch_binding(struct weston_keyboard *keyboard,
918 const struct timespec *time, uint32_t key, void *data)
919{
920 weston_log("Compiled without GBM/EGL support\n");
921}
922#endif