mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-29 05:40:12 -04:00
Support direct scanout with src crop and dst boxes
Enable scene-tree direct scanout of a single buffer with various options for scaling and source crop. This is intended to support direct scanout for fullscreen video with/without scaling, letterboxing/pillarboxing (e.g. 4:3 content on a 16:9 display), and source crop (e.g. when 1920x1088 planes are used for 1920x1080 video). This works by explicitly specifying the source crop and destination box for the primary buffer in the output state. DRM atomic and libliftoff backends will turn this into a crop and scale of the plane (assuming the hardware supports that). For the Wayland/X11/DRM-legacy backends I just reject this so scanout will be disabled. The previous behaviour is preserved if buffer_src_box and buffer_dst_box are unset: the buffer is displayed at native size at the top-left of the output with no crop. The change to `struct wlr_output_state` makes this a binary breaking change (but this works transparently for scene-tree compositors like labwc after a recompile).
This commit is contained in:
parent
47fb00f66d
commit
c87ab6465d
10 changed files with 230 additions and 59 deletions
|
|
@ -4,12 +4,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/iface.h"
|
||||
#include "config.h"
|
||||
#include "types/wlr_output.h"
|
||||
|
||||
static void log_handler(enum liftoff_log_priority priority, const char *fmt, va_list args) {
|
||||
enum wlr_log_importance importance = WLR_SILENT;
|
||||
|
|
@ -149,25 +151,23 @@ static bool add_prop(drmModeAtomicReq *req, uint32_t obj,
|
|||
}
|
||||
|
||||
static bool set_plane_props(struct wlr_drm_plane *plane,
|
||||
struct liftoff_layer *layer, struct wlr_drm_fb *fb, int32_t x, int32_t y, uint64_t zpos) {
|
||||
struct liftoff_layer *layer, struct wlr_drm_fb *fb, uint64_t zpos,
|
||||
const struct wlr_box *dst_box, const struct wlr_fbox *src_box) {
|
||||
if (fb == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to acquire FB for plane %"PRIu32, plane->id);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t width = fb->wlr_buf->width;
|
||||
uint32_t height = fb->wlr_buf->height;
|
||||
|
||||
// The SRC_* properties are in 16.16 fixed point
|
||||
// The src_* properties are in 16.16 fixed point
|
||||
return liftoff_layer_set_property(layer, "zpos", zpos) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_X", 0) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_Y", 0) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_W", (uint64_t)width << 16) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_H", (uint64_t)height << 16) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_X", (uint64_t)x) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_Y", (uint64_t)y) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_W", width) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_H", height) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_X", src_box->x * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_Y", src_box->y * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_W", src_box->width * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_H", src_box->height * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_X", dst_box->x) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_Y", dst_box->y) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_W", dst_box->width) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_H", dst_box->height) == 0 &&
|
||||
liftoff_layer_set_property(layer, "FB_ID", fb->id) == 0;
|
||||
}
|
||||
|
||||
|
|
@ -331,9 +331,17 @@ static bool add_connector(drmModeAtomicReq *req,
|
|||
if (crtc->props.vrr_enabled != 0) {
|
||||
ok = ok && add_prop(req, crtc->id, crtc->props.vrr_enabled, state->vrr_enabled);
|
||||
}
|
||||
struct wlr_fbox src_box;
|
||||
struct wlr_box dst_box;
|
||||
output_state_get_buffer_src_box(state->base, &src_box);
|
||||
output_state_get_buffer_dst_box(state->base, &dst_box);
|
||||
|
||||
ok = ok &&
|
||||
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);
|
||||
set_plane_props(crtc->primary, crtc->primary->liftoff_layer,
|
||||
state->primary_fb, 0, &dst_box, &src_box);
|
||||
ok = ok &&
|
||||
set_plane_props(crtc->primary, crtc->liftoff_composition_layer,
|
||||
state->primary_fb, 0, &dst_box, &src_box);
|
||||
liftoff_layer_set_property(crtc->primary->liftoff_layer,
|
||||
"FB_DAMAGE_CLIPS", state->fb_damage_clips);
|
||||
liftoff_layer_set_property(crtc->liftoff_composition_layer,
|
||||
|
|
@ -360,9 +368,19 @@ static bool add_connector(drmModeAtomicReq *req,
|
|||
|
||||
if (crtc->cursor) {
|
||||
if (drm_connector_is_cursor_visible(conn)) {
|
||||
struct wlr_fbox cursor_src = {
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
struct wlr_box cursor_dst = {
|
||||
.x = conn->cursor_x,
|
||||
.y = conn->cursor_y,
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
ok = ok && set_plane_props(crtc->cursor, crtc->cursor->liftoff_layer,
|
||||
state->cursor_fb, conn->cursor_x, conn->cursor_y,
|
||||
wl_list_length(&crtc->layers) + 1);
|
||||
state->cursor_fb, wl_list_length(&crtc->layers) + 1,
|
||||
&cursor_dst, &cursor_src);
|
||||
} else {
|
||||
ok = ok && disable_plane(crtc->cursor);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue