backend/drm: move atomic cursor code into pageflip code

It makes sense to construct as much atomic state as possible in the same
place, so it doesn't get lost if we "reset" it.
This commit is contained in:
Scott Anderson 2020-02-12 21:25:40 +13:00 committed by Simon Ser
parent be90062c51
commit 52281cb8ba
4 changed files with 66 additions and 65 deletions

View file

@ -69,10 +69,27 @@ static void atomic_add(struct atomic *atom, uint32_t id, uint32_t prop, uint64_t
} }
} }
static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane, static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
uint32_t crtc_id, uint32_t fb_id, bool set_crtc_xy) {
uint32_t id = plane->id; uint32_t id = plane->id;
const union wlr_drm_plane_props *props = &plane->props; const union wlr_drm_plane_props *props = &plane->props;
atomic_add(atom, id, props->fb_id, 0);
atomic_add(atom, id, props->crtc_id, 0);
}
static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
struct wlr_drm_plane *plane, uint32_t crtc_id, int32_t x, int32_t y) {
uint32_t id = plane->id;
const union wlr_drm_plane_props *props = &plane->props;
struct wlr_drm_fb *fb = plane_get_next_fb(plane);
struct gbm_bo *bo = drm_fb_acquire(fb, drm, &plane->mgpu_surf);
if (!bo) {
goto error;
}
uint32_t fb_id = get_fb_for_bo(bo, drm->addfb2_modifiers);
if (!fb_id) {
goto error;
}
// The src_* properties are in 16.16 fixed point // The src_* properties are in 16.16 fixed point
atomic_add(atom, id, props->src_x, 0); atomic_add(atom, id, props->src_x, 0);
@ -83,16 +100,19 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_plane *plane,
atomic_add(atom, id, props->crtc_h, plane->surf.height); atomic_add(atom, id, props->crtc_h, plane->surf.height);
atomic_add(atom, id, props->fb_id, fb_id); atomic_add(atom, id, props->fb_id, fb_id);
atomic_add(atom, id, props->crtc_id, crtc_id); atomic_add(atom, id, props->crtc_id, crtc_id);
if (set_crtc_xy) { atomic_add(atom, id, props->crtc_x, (uint64_t)x);
atomic_add(atom, id, props->crtc_x, 0); atomic_add(atom, id, props->crtc_y, (uint64_t)y);
atomic_add(atom, id, props->crtc_y, 0);
} return;
error:
atom->failed = true;
} }
static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm, static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, struct wlr_drm_connector *conn, drmModeModeInfo *mode) {
struct wlr_drm_crtc *crtc, struct wlr_drm_crtc *crtc = conn->crtc;
uint32_t fb_id, drmModeModeInfo *mode) {
if (mode != NULL) { if (mode != NULL) {
if (crtc->mode_id != 0) { if (crtc->mode_id != 0) {
drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id); drmModeDestroyPropertyBlob(drm->fd, crtc->mode_id);
@ -121,14 +141,29 @@ static bool atomic_crtc_pageflip(struct wlr_drm_backend *drm,
} }
atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id); atomic_add(&atom, crtc->id, crtc->props.mode_id, crtc->mode_id);
atomic_add(&atom, crtc->id, crtc->props.active, 1); atomic_add(&atom, crtc->id, crtc->props.active, 1);
set_plane_props(&atom, crtc->primary, crtc->id, fb_id, true); set_plane_props(&atom, drm, crtc->primary, crtc->id, 0, 0);
if (crtc->cursor) {
if (crtc->cursor->cursor_enabled) {
set_plane_props(&atom, drm, crtc->cursor, crtc->id,
conn->cursor_x, conn->cursor_y);
} else {
plane_disable(&atom, crtc->cursor);
}
}
if (!atomic_end(drm->fd, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : 0, &atom)) { if (!atomic_end(drm->fd, mode ? DRM_MODE_ATOMIC_ALLOW_MODESET : 0, &atom)) {
drmModeAtomicSetCursor(atom.req, 0); drmModeAtomicSetCursor(atom.req, 0);
return false; return false;
} }
return atomic_commit(drm->fd, &atom, conn, flags, mode); if (!atomic_commit(drm->fd, &atom, conn, flags, mode)) {
return false;
}
if (crtc->cursor) {
drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb);
}
return true;
} }
static bool atomic_conn_enable(struct wlr_drm_backend *drm, static bool atomic_conn_enable(struct wlr_drm_backend *drm,
@ -154,52 +189,16 @@ static bool atomic_conn_enable(struct wlr_drm_backend *drm,
static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm, static bool atomic_crtc_set_cursor(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, struct gbm_bo *bo) { struct wlr_drm_crtc *crtc, struct gbm_bo *bo) {
if (!crtc || !crtc->cursor) { /* Cursor updates happen when we pageflip */
return true; return true;
} }
struct wlr_drm_plane *plane = crtc->cursor;
// We can't use atomic operations on fake planes
if (plane->id == 0) {
return legacy_crtc_set_cursor(drm, crtc, bo);
}
struct atomic atom;
atomic_begin(crtc, &atom);
if (bo) {
uint32_t fb_id =
get_fb_for_bo(bo, drm->addfb2_modifiers);
set_plane_props(&atom, plane, crtc->id, fb_id, false);
} else {
atomic_add(&atom, plane->id, plane->props.fb_id, 0);
atomic_add(&atom, plane->id, plane->props.crtc_id, 0);
}
return atomic_end(drm->fd, &atom);
}
static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm, static bool atomic_crtc_move_cursor(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, int x, int y) { struct wlr_drm_crtc *crtc, int x, int y) {
if (!crtc || !crtc->cursor) { /* Cursor updates happen when we pageflip */
return true; return true;
} }
struct wlr_drm_plane *plane = crtc->cursor;
// We can't use atomic operations on fake planes
if (plane->id == 0) {
return legacy_crtc_move_cursor(drm, crtc, x, y);
}
struct atomic atom;
atomic_begin(crtc, &atom);
atomic_add(&atom, plane->id, plane->props.crtc_x, x);
atomic_add(&atom, plane->id, plane->props.crtc_y, y);
return atomic_end(drm->fd, &atom);
}
static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm, static bool atomic_crtc_set_gamma(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, size_t size, struct wlr_drm_crtc *crtc, size_t size,
uint16_t *r, uint16_t *g, uint16_t *b) { uint16_t *r, uint16_t *g, uint16_t *b) {

View file

@ -338,9 +338,6 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn,
struct wlr_drm_mode *mode) { struct wlr_drm_mode *mode) {
struct wlr_drm_backend *drm = get_drm_backend_from_backend(conn->output.backend); struct wlr_drm_backend *drm = get_drm_backend_from_backend(conn->output.backend);
struct wlr_drm_crtc *crtc = conn->crtc; struct wlr_drm_crtc *crtc = conn->crtc;
struct wlr_drm_plane *plane = crtc->primary;
struct gbm_bo *bo;
uint32_t fb_id;
drmModeModeInfo *drm_mode = mode ? &mode->drm_mode : NULL; drmModeModeInfo *drm_mode = mode ? &mode->drm_mode : NULL;
if (conn->pageflip_pending) { if (conn->pageflip_pending) {
@ -348,13 +345,7 @@ static bool drm_crtc_page_flip(struct wlr_drm_connector *conn,
return false; return false;
} }
bo = drm_fb_acquire(&plane->queued_fb, drm, &plane->mgpu_surf); if (!drm->iface->crtc_pageflip(drm, conn, drm_mode)) {
if (!bo) {
return false;
}
fb_id = get_fb_for_bo(bo, drm->addfb2_modifiers);
if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, drm_mode)) {
return false; return false;
} }

View file

@ -7,8 +7,19 @@
#include "backend/drm/util.h" #include "backend/drm/util.h"
static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm, static bool legacy_crtc_pageflip(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, struct wlr_drm_connector *conn, drmModeModeInfo *mode) {
uint32_t fb_id, drmModeModeInfo *mode) { struct wlr_drm_crtc *crtc = conn->crtc;
struct wlr_drm_fb *fb = plane_get_next_fb(crtc->primary);
struct gbm_bo *bo = drm_fb_acquire(fb, drm, &crtc->primary->mgpu_surf);
if (!bo) {
return false;
}
uint32_t fb_id = get_fb_for_bo(bo, drm->addfb2_modifiers);
if (!fb_id) {
return false;
}
if (mode) { if (mode) {
if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0, if (drmModeSetCrtc(drm->fd, crtc->id, fb_id, 0, 0,
&conn->id, 1, mode)) { &conn->id, 1, mode)) {
@ -60,6 +71,7 @@ bool legacy_crtc_set_cursor(struct wlr_drm_backend *drm,
return false; return false;
} }
drm_fb_move(&crtc->cursor->queued_fb, &crtc->cursor->pending_fb);
return true; return true;
} }

View file

@ -18,8 +18,7 @@ struct wlr_drm_interface {
struct wlr_drm_connector *conn, bool enable); struct wlr_drm_connector *conn, bool enable);
// Pageflip on crtc. If mode is non-NULL perform a full modeset using it. // Pageflip on crtc. If mode is non-NULL perform a full modeset using it.
bool (*crtc_pageflip)(struct wlr_drm_backend *drm, bool (*crtc_pageflip)(struct wlr_drm_backend *drm,
struct wlr_drm_connector *conn, struct wlr_drm_crtc *crtc, struct wlr_drm_connector *conn, drmModeModeInfo *mode);
uint32_t fb_id, drmModeModeInfo *mode);
// Enable the cursor buffer on crtc. Set bo to NULL to disable // Enable the cursor buffer on crtc. Set bo to NULL to disable
bool (*crtc_set_cursor)(struct wlr_drm_backend *drm, bool (*crtc_set_cursor)(struct wlr_drm_backend *drm,
struct wlr_drm_crtc *crtc, struct gbm_bo *bo); struct wlr_drm_crtc *crtc, struct gbm_bo *bo);