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;
crtc->applied = true;
}
- *slot = NULL;
+ pipe->base.back = NULL;
pipe->base.front = &fb->base;
fb->flipid = 0;
++pipe->counter;
* 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;
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;
}
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);
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);
}
}
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);
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);
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,
};
/*