mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
terminal/drm: provide pipe->target() callback
Instead of looking for available back-buffers on each operation, set it to NULL and wait for the next frame request. It will call back into the pipe to request the back-buffer via ->target(), where we can do the same and look for an available backbuffer. This simplifies the code and avoids double lookups if we run short of buffers.
This commit is contained in:
parent
6a15ce2b3e
commit
aec3f44651
@ -1095,19 +1095,19 @@ static void grdrm_crtc_expose(grdrm_crtc *crtc) {
|
||||
grdev_pipe_ready(&crtc->pipe->base, true);
|
||||
}
|
||||
|
||||
static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb **slot) {
|
||||
static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb *basefb) {
|
||||
struct drm_mode_crtc set_crtc = { .crtc_id = crtc->object.id };
|
||||
grdrm_card *card = crtc->object.card;
|
||||
grdrm_pipe *pipe = crtc->pipe;
|
||||
grdrm_fb *fb = fb_from_base(*slot);
|
||||
size_t i;
|
||||
grdrm_fb *fb;
|
||||
int r;
|
||||
|
||||
assert(crtc);
|
||||
assert(slot);
|
||||
assert(*slot);
|
||||
assert(basefb);
|
||||
assert(pipe);
|
||||
|
||||
fb = fb_from_base(basefb);
|
||||
|
||||
set_crtc.set_connectors_ptr = PTR_TO_UINT64(crtc->set.connectors);
|
||||
set_crtc.count_connectors = crtc->set.n_connectors;
|
||||
set_crtc.fb_id = fb->id;
|
||||
@ -1132,7 +1132,7 @@ static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb **slot) {
|
||||
crtc->applied = true;
|
||||
}
|
||||
|
||||
*slot = NULL;
|
||||
pipe->base.back = NULL;
|
||||
pipe->base.front = &fb->base;
|
||||
fb->flipid = 0;
|
||||
++pipe->counter;
|
||||
@ -1144,40 +1144,25 @@ static void grdrm_crtc_commit_deep(grdrm_crtc *crtc, grdev_fb **slot) {
|
||||
* To avoid duplicating that everywhere, we schedule our own
|
||||
* timer and raise a fake FRAME event when it fires. */
|
||||
grdev_pipe_schedule(&pipe->base, 1);
|
||||
|
||||
if (!pipe->base.back) {
|
||||
for (i = 0; i < pipe->base.max_fbs; ++i) {
|
||||
if (!pipe->base.fbs[i])
|
||||
continue;
|
||||
|
||||
fb = fb_from_base(pipe->base.fbs[i]);
|
||||
if (&fb->base == pipe->base.front)
|
||||
continue;
|
||||
|
||||
fb->flipid = 0;
|
||||
pipe->base.back = &fb->base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb **slot) {
|
||||
static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb *basefb) {
|
||||
struct drm_mode_crtc_page_flip page_flip = { .crtc_id = crtc->object.id };
|
||||
grdrm_card *card = crtc->object.card;
|
||||
grdrm_pipe *pipe = crtc->pipe;
|
||||
grdrm_fb *fb = fb_from_base(*slot);
|
||||
grdrm_fb *fb;
|
||||
uint32_t cnt;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
assert(crtc);
|
||||
assert(slot);
|
||||
assert(*slot);
|
||||
assert(basefb);
|
||||
assert(pipe);
|
||||
|
||||
if (!crtc->applied && !grdrm_modes_compatible(&crtc->kern.mode, &crtc->set.mode))
|
||||
return 0;
|
||||
|
||||
fb = fb_from_base(basefb);
|
||||
|
||||
cnt = ++pipe->counter ? : ++pipe->counter;
|
||||
page_flip.fb_id = fb->id;
|
||||
page_flip.flags = DRM_MODE_PAGE_FLIP_EVENT;
|
||||
@ -1209,29 +1194,13 @@ static int grdrm_crtc_commit_flip(grdrm_crtc *crtc, grdev_fb **slot) {
|
||||
pipe->base.flip = false;
|
||||
pipe->counter = cnt;
|
||||
fb->flipid = cnt;
|
||||
*slot = NULL;
|
||||
pipe->base.back = NULL;
|
||||
|
||||
/* Raise fake FRAME event if it takes longer than 2
|
||||
* frames to receive the pageflip event. We assume the
|
||||
* queue ran over or some other error happened. */
|
||||
grdev_pipe_schedule(&pipe->base, 2);
|
||||
|
||||
if (!pipe->base.back) {
|
||||
for (i = 0; i < pipe->base.max_fbs; ++i) {
|
||||
if (!pipe->base.fbs[i])
|
||||
continue;
|
||||
|
||||
fb = fb_from_base(pipe->base.fbs[i]);
|
||||
if (&fb->base == pipe->base.front)
|
||||
continue;
|
||||
if (fb->flipid)
|
||||
continue;
|
||||
|
||||
pipe->base.back = &fb->base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1239,7 +1208,7 @@ static void grdrm_crtc_commit(grdrm_crtc *crtc) {
|
||||
struct drm_mode_crtc set_crtc = { .crtc_id = crtc->object.id };
|
||||
grdrm_card *card = crtc->object.card;
|
||||
grdrm_pipe *pipe;
|
||||
grdev_fb **slot;
|
||||
grdev_fb *fb;
|
||||
int r;
|
||||
|
||||
assert(crtc);
|
||||
@ -1280,19 +1249,19 @@ static void grdrm_crtc_commit(grdrm_crtc *crtc) {
|
||||
assert(crtc->set.n_connectors > 0);
|
||||
|
||||
if (pipe->base.flip)
|
||||
slot = &pipe->base.back;
|
||||
fb = pipe->base.back;
|
||||
else if (!crtc->applied)
|
||||
slot = &pipe->base.front;
|
||||
fb = pipe->base.front;
|
||||
else
|
||||
return;
|
||||
|
||||
if (!*slot)
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
r = grdrm_crtc_commit_flip(crtc, slot);
|
||||
r = grdrm_crtc_commit_flip(crtc, fb);
|
||||
if (r == 0) {
|
||||
/* in case we couldn't page-flip, perform deep modeset */
|
||||
grdrm_crtc_commit_deep(crtc, slot);
|
||||
grdrm_crtc_commit_deep(crtc, fb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1335,7 +1304,6 @@ static void grdrm_crtc_restore(grdrm_crtc *crtc) {
|
||||
static void grdrm_crtc_flip_complete(grdrm_crtc *crtc, uint32_t counter, struct drm_event_vblank *event) {
|
||||
bool flipped = false;
|
||||
grdrm_pipe *pipe;
|
||||
grdrm_fb *back = NULL;
|
||||
size_t i;
|
||||
|
||||
assert(crtc);
|
||||
@ -1366,15 +1334,9 @@ static void grdrm_crtc_flip_complete(grdrm_crtc *crtc, uint32_t counter, struct
|
||||
flipped = true;
|
||||
} else if (counter - fb->flipid < UINT16_MAX) {
|
||||
fb->flipid = 0;
|
||||
back = fb;
|
||||
} else if (fb->flipid == 0) {
|
||||
back = fb;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pipe->base.back && back)
|
||||
pipe->base.back = &back->base;
|
||||
|
||||
if (flipped) {
|
||||
crtc->pipe->base.flipping = false;
|
||||
grdev_pipe_frame(&pipe->base);
|
||||
@ -1561,8 +1523,32 @@ static void grdrm_pipe_free(grdev_pipe *basepipe) {
|
||||
free(pipe);
|
||||
}
|
||||
|
||||
static grdev_fb *grdrm_pipe_target(grdev_pipe *basepipe) {
|
||||
grdrm_fb *fb;
|
||||
size_t i;
|
||||
|
||||
if (!basepipe->back) {
|
||||
for (i = 0; i < basepipe->max_fbs; ++i) {
|
||||
if (!basepipe->fbs[i])
|
||||
continue;
|
||||
|
||||
fb = fb_from_base(basepipe->fbs[i]);
|
||||
if (&fb->base == basepipe->front)
|
||||
continue;
|
||||
if (basepipe->flipping && fb->flipid)
|
||||
continue;
|
||||
|
||||
basepipe->back = &fb->base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return basepipe->back;
|
||||
}
|
||||
|
||||
static const grdev_pipe_vtable grdrm_pipe_vtable = {
|
||||
.free = grdrm_pipe_free,
|
||||
.target = grdrm_pipe_target,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -382,6 +382,8 @@ const grdev_display_target *grdev_display_next_target(grdev_display *display, co
|
||||
if (!(fb = pipe->back)) {
|
||||
if (!pipe->vtable->target || !(fb = pipe->vtable->target(pipe)))
|
||||
continue;
|
||||
|
||||
assert(fb == pipe->back);
|
||||
}
|
||||
|
||||
/* if back-buffer is up-to-date, schedule flip */
|
||||
|
Loading…
Reference in New Issue
Block a user