linuxOS_AP06/buildroot/package/weston/0076-backend-drm-Support-displaying-on-custom-plane.patch
2025-06-03 12:28:32 +08:00

245 lines
8.1 KiB
Diff

From 8dac648cab34e384919a306508d122f8623ecd8e Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Thu, 4 Jan 2024 10:50:02 +0800
Subject: [PATCH 76/95] backend-drm: Support displaying on custom plane
Tested on RK3588 EVB with:
1/ gst-launch-1.0 videotestsrc ! kmssink force-modesetting=1
2/ Set custom plane-id in weston.ini:
[output]
name=DSI-1
plane-id=159
3/ echo "output:DSI-1:rect=<0,0,600,1000>" > /tmp/.weston_drm.conf
4/ Launch weston and check /sys/kernel/debug/dri/0/summary
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
libweston/backend-drm/drm-internal.h | 1 +
libweston/backend-drm/drm.c | 74 +++++++++++++++++++++++++++-
libweston/backend-drm/kms.c | 36 +++++++++++---
3 files changed, 102 insertions(+), 9 deletions(-)
diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h
index 9fe1afe..65e2a44 100644
--- a/libweston/backend-drm/drm-internal.h
+++ b/libweston/backend-drm/drm-internal.h
@@ -611,6 +611,7 @@ struct drm_output {
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;
+ unsigned int custom_plane;
/* The last state submitted to the kernel for this CRTC. */
struct drm_output_state *state_cur;
diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c
index 462b5c0..ca0fd28 100644
--- a/libweston/backend-drm/drm.c
+++ b/libweston/backend-drm/drm.c
@@ -483,6 +483,9 @@ drm_output_get_disable_state(struct drm_pending_state *pending_state,
static int
drm_output_apply_mode(struct drm_output *output);
+static unsigned int
+drm_waitvblank_pipe(struct drm_crtc *crtc);
+
/**
* Mark a drm_output_state (the output's last state) as complete. This handles
* any post-completion actions such as updating the repaint timer, disabling the
@@ -500,13 +503,37 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
if (output->pageflip_timer)
wl_event_source_timer_update(output->pageflip_timer, 0);
+ if (!sec && !usec) {
+ drmVBlank vbl = {
+ .request.type = DRM_VBLANK_RELATIVE,
+ .request.sequence = 0,
+ .request.signal = 0,
+ };
+ int ret;
+
+ /* Try to get current msc and timestamp via instant query */
+ vbl.request.type |= drm_waitvblank_pipe(output->crtc);
+ ret = drmWaitVBlank(device->drm.fd, &vbl);
+
+ /* Error ret or zero timestamp means failure to get valid timestamp */
+ if ((ret == 0) &&
+ (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
+ ts.tv_sec = vbl.reply.tval_sec;
+ ts.tv_nsec = vbl.reply.tval_usec * 1000;
+ sec = ts.tv_sec;
+ usec = ts.tv_nsec / 1000;
+
+ drm_output_update_msc(output, vbl.reply.sequence);
+ }
+ }
+
wl_list_for_each(ps, &output->state_cur->plane_list, link)
ps->complete = true;
drm_output_state_free(output->state_last);
output->state_last = NULL;
- if (output->fb_dummy) {
+ if (output->fb_dummy && !output->custom_plane) {
drm_fb_unref(output->fb_dummy);
output->fb_dummy = NULL;
}
@@ -550,7 +577,7 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
ts.tv_sec = sec;
ts.tv_nsec = usec * 1000;
- if (output->state_cur->dpms != WESTON_DPMS_OFF)
+ if (output->state_cur->dpms != WESTON_DPMS_OFF && (sec || usec))
weston_output_finish_frame(&output->base, &ts, flags);
else
weston_output_finish_frame(&output->base, NULL,
@@ -1679,6 +1706,15 @@ retry:
struct weston_output *base;
bool found_elsewhere = false;
+ if (type == WDRM_PLANE_TYPE_PRIMARY && output->custom_plane) {
+ if (output->custom_plane != plane->plane_id)
+ continue;
+
+ /* Pretend to be primary plane */
+ output->crtc->primary_plane_id = output->custom_plane;
+ plane->type = WDRM_PLANE_TYPE_PRIMARY;
+ }
+
if (plane->type != type)
continue;
if (!drm_plane_is_available(plane, output))
@@ -1809,6 +1845,9 @@ create_sprites(struct drm_device *device, drmModeRes *resources)
assert(drm_crtc);
drm_crtc->cursor_plane_id = drm_plane->plane_id;
} else if (drm_plane->type == WDRM_PLANE_TYPE_OVERLAY) {
+ if (device->sprites_are_broken)
+ continue;
+
weston_compositor_stack_plane(b->compositor,
&drm_plane->base,
NULL);
@@ -2558,6 +2597,22 @@ drm_output_init_planes(struct drm_output *output)
{
struct drm_backend *b = output->backend;
struct drm_device *device = output->device;
+ struct weston_config_section *section;
+ struct weston_head *head;
+
+ wl_list_for_each(head, &output->base.head_list, output_link) {
+ section = head->section;
+ if (section) {
+ weston_config_section_get_uint(section, "plane-id",
+ &output->custom_plane,
+ 0);
+ break;
+ }
+ }
+
+ if (output->custom_plane)
+ weston_log("Using custom plane: %d for output %s\n",
+ output->custom_plane, output->base.name);
output->scanout_plane =
drm_output_find_special_plane(device, output,
@@ -2572,6 +2627,13 @@ drm_output_init_planes(struct drm_output *output)
&output->scanout_plane->base,
&output->base.primary_plane);
+ if (output->custom_plane) {
+ device->atomic_modeset = false;
+ device->cursors_are_broken = true;
+ device->sprites_are_broken = true;
+ return 0;
+ }
+
/* Failing to find a cursor plane is not fatal, as we'll fall back
* to software cursor. */
output->cursor_plane =
@@ -2722,6 +2784,14 @@ drm_output_detach_crtc(struct drm_output *output)
crtc->output = NULL;
output->crtc = NULL;
+ if (output->custom_plane && !output->fb_dummy) {
+ if (output->scanout_plane)
+ drmModeSetPlane(crtc->device->drm.fd,
+ output->scanout_plane->plane_id,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ return;
+ }
+
/* HACK: Do it here rather than in the kms.c for drm-master config */
drmModeSetCrtc(crtc->device->drm.fd,
crtc->crtc_id, 0, 0, 0, NULL, 0, NULL);
diff --git a/libweston/backend-drm/kms.c b/libweston/backend-drm/kms.c
index 6f730aa..2bd5da4 100644
--- a/libweston/backend-drm/kms.c
+++ b/libweston/backend-drm/kms.c
@@ -890,6 +890,12 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
struct timespec now;
int ret = 0;
bool scaling;
+ bool mode_valid;
+ drmModeCrtc *drm_crtc;
+
+ drm_crtc = drmModeGetCrtc(device->drm.fd, output->crtc->crtc_id);
+ mode_valid = drm_crtc->mode_valid;
+ drmModeFreeCrtc(drm_crtc);
wl_list_for_each(head, &output->base.head_list, base.output_link) {
if (!drm_head_is_connected(head)) {
@@ -922,11 +928,20 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
strerror(errno));
}
- ret = drmModeSetCrtc(device->drm.fd, crtc->crtc_id, 0, 0, 0,
- NULL, 0, NULL);
- if (ret)
- weston_log("drmModeSetCrtc failed disabling: %s\n",
- strerror(errno));
+ if (!output->custom_plane || output->fb_dummy) {
+ ret = drmModeSetCrtc(device->drm.fd, crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ if (ret)
+ weston_log("drmModeSetCrtc failed disabling: %s\n",
+ strerror(errno));
+ } else {
+ ret = drmModeSetPlane(device->drm.fd,
+ output->scanout_plane->plane_id,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ if (ret)
+ weston_log("drmModeSetPlane failed disabling: %s\n",
+ strerror(errno));
+ }
drm_output_assign_state(state, DRM_STATE_APPLY_SYNC);
weston_compositor_read_presentation_clock(output->base.compositor, &now);
@@ -947,8 +962,8 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
mode = to_drm_mode(output->base.current_mode);
- if (output->state_invalid ||
- !scanout_plane->state_cur->fb) {
+ if ((!output->custom_plane || !mode_valid) &&
+ (output->state_invalid || !scanout_plane->state_cur->fb)) {
int fb_id = scanout_state->fb->fb_id;
if (scanout_state->dest_x || scanout_state->dest_y ||
@@ -1015,6 +1030,13 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
crtc->crtc_id, scanout_state->plane->plane_id,
pinfo ? pinfo->drm_format_name : "UNKNOWN");
+ if (output->custom_plane) {
+ drm_output_assign_state(state, DRM_STATE_APPLY_SYNC);
+ output->state_invalid = false;
+ drm_output_update_complete(output, 0, 0, 0);
+ return 0;
+ }
+
if (drmModePageFlip(device->drm.fd, crtc->crtc_id,
scanout_state->fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
--
2.20.1