From aa1055134da5f5f4f25a5781b43305b7de79fd99 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 21 Feb 2023 10:21:37 +0100 Subject: [PATCH] backend/drm: handle output layer damage --- backend/drm/atomic.c | 9 +++----- backend/drm/libliftoff.c | 46 ++++++++++++++++++++++++++++--------- include/backend/drm/iface.h | 2 +- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index 4c95a3bba..7c5fc0bad 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -144,15 +144,12 @@ bool create_gamma_lut_blob(struct wlr_drm_backend *drm, } bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm, - struct wlr_drm_fb *fb, const pixman_region32_t *damage, uint32_t *blob_id) { + int width, int height, const pixman_region32_t *damage, uint32_t *blob_id) { if (!pixman_region32_not_empty(damage)) { *blob_id = 0; return true; } - int width = fb->wlr_buf->width; - int height = fb->wlr_buf->height; - pixman_region32_t clipped; pixman_region32_init(&clipped); pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height); @@ -298,8 +295,8 @@ static bool atomic_crtc_commit(struct wlr_drm_connector *conn, uint32_t fb_damage_clips = 0; if ((state->base->committed & WLR_OUTPUT_STATE_DAMAGE) && crtc->primary->props.fb_damage_clips != 0) { - create_fb_damage_clips_blob(drm, state->primary_fb, - &state->base->damage, &fb_damage_clips); + create_fb_damage_clips_blob(drm, state->primary_fb->wlr_buf->width, + state->primary_fb->wlr_buf->height, &state->base->damage, &fb_damage_clips); } bool prev_vrr_enabled = diff --git a/backend/drm/libliftoff.c b/backend/drm/libliftoff.c index 7b2983bc7..5b828e173 100644 --- a/backend/drm/libliftoff.c +++ b/backend/drm/libliftoff.c @@ -179,7 +179,8 @@ static uint64_t to_fp16(double v) { } static bool set_layer_props(struct wlr_drm_backend *drm, - const struct wlr_output_layer_state *state, uint64_t zpos) { + const struct wlr_output_layer_state *state, uint64_t zpos, + struct wl_array *fb_damage_clips_arr) { struct wlr_drm_layer *layer = get_drm_layer(drm, state->layer); uint32_t width = 0, height = 0; @@ -219,6 +220,17 @@ static bool set_layer_props(struct wlr_drm_backend *drm, uint64_t src_w = to_fp16(src_box.width); uint64_t src_h = to_fp16(src_box.height); + uint32_t fb_damage_clips = 0; + if (state->damage != NULL) { + uint32_t *ptr = wl_array_add(fb_damage_clips_arr, sizeof(fb_damage_clips)); + if (ptr == NULL) { + return false; + } + create_fb_damage_clips_blob(drm, width, height, + state->damage, &fb_damage_clips); + *ptr = fb_damage_clips; + } + return liftoff_layer_set_property(layer->liftoff, "zpos", zpos) == 0 && liftoff_layer_set_property(layer->liftoff, "CRTC_X", crtc_x) == 0 && @@ -228,7 +240,8 @@ static bool set_layer_props(struct wlr_drm_backend *drm, liftoff_layer_set_property(layer->liftoff, "SRC_X", src_x) == 0 && liftoff_layer_set_property(layer->liftoff, "SRC_Y", src_y) == 0 && liftoff_layer_set_property(layer->liftoff, "SRC_W", src_w) == 0 && - liftoff_layer_set_property(layer->liftoff, "SRC_H", src_h) == 0; + liftoff_layer_set_property(layer->liftoff, "SRC_H", src_h) == 0 && + liftoff_layer_set_property(layer->liftoff, "FB_DAMAGE_CLIPS", fb_damage_clips) == 0; } static bool devid_from_fd(int fd, dev_t *devid) { @@ -327,11 +340,19 @@ static bool crtc_commit(struct wlr_drm_connector *conn, } } - uint32_t fb_damage_clips = 0; + struct wl_array fb_damage_clips_arr = {0}; + + uint32_t primary_fb_damage_clips = 0; if ((state->base->committed & WLR_OUTPUT_STATE_DAMAGE) && crtc->primary->props.fb_damage_clips != 0) { - create_fb_damage_clips_blob(drm, state->primary_fb, - &state->base->damage, &fb_damage_clips); + uint32_t *ptr = wl_array_add(&fb_damage_clips_arr, sizeof(primary_fb_damage_clips)); + if (ptr == NULL) { + return false; + } + create_fb_damage_clips_blob(drm, state->primary_fb->wlr_buf->width, + state->primary_fb->wlr_buf->height, &state->base->damage, + &primary_fb_damage_clips); + *ptr = primary_fb_damage_clips; } bool prev_vrr_enabled = @@ -387,14 +408,15 @@ static bool crtc_commit(struct wlr_drm_connector *conn, set_plane_props(crtc->primary, crtc->primary->liftoff_layer, state->primary_fb, 0, 0, 0) && set_plane_props(crtc->primary, crtc->liftoff_composition_layer, state->primary_fb, 0, 0, 0); liftoff_layer_set_property(crtc->primary->liftoff_layer, - "FB_DAMAGE_CLIPS", fb_damage_clips); + "FB_DAMAGE_CLIPS", primary_fb_damage_clips); liftoff_layer_set_property(crtc->liftoff_composition_layer, - "FB_DAMAGE_CLIPS", fb_damage_clips); + "FB_DAMAGE_CLIPS", primary_fb_damage_clips); if (state->base->committed & WLR_OUTPUT_STATE_LAYERS) { for (size_t i = 0; i < state->base->layers_len; i++) { const struct wlr_output_layer_state *layer_state = &state->base->layers[i]; - ok = ok && set_layer_props(drm, layer_state, i + 1); + ok = ok && set_layer_props(drm, layer_state, i + 1, + &fb_damage_clips_arr); } } @@ -472,9 +494,11 @@ out: rollback_blob(drm, &crtc->gamma_lut, gamma_lut); } - if (fb_damage_clips != 0 && - drmModeDestroyPropertyBlob(drm->fd, fb_damage_clips) != 0) { - wlr_log_errno(WLR_ERROR, "Failed to destroy FB_DAMAGE_CLIPS property blob"); + uint32_t *fb_damage_clips_ptr; + wl_array_for_each(fb_damage_clips_ptr, &fb_damage_clips_arr) { + if (drmModeDestroyPropertyBlob(drm->fd, *fb_damage_clips_ptr) != 0) { + wlr_log_errno(WLR_ERROR, "Failed to destroy FB_DAMAGE_CLIPS property blob"); + } } return ok; diff --git a/include/backend/drm/iface.h b/include/backend/drm/iface.h index f06acf9a8..9916f3831 100644 --- a/include/backend/drm/iface.h +++ b/include/backend/drm/iface.h @@ -36,6 +36,6 @@ bool create_mode_blob(struct wlr_drm_backend *drm, bool create_gamma_lut_blob(struct wlr_drm_backend *drm, size_t size, const uint16_t *lut, uint32_t *blob_id); bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm, - struct wlr_drm_fb *fb, const pixman_region32_t *damage, uint32_t *blob_id); + int width, int height, const pixman_region32_t *damage, uint32_t *blob_id); #endif