From 177623674d0b696bc4f1dc5a7fa26ebbfce60fa5 Mon Sep 17 00:00:00 2001 From: bjornstahl Date: Sat, 16 Sep 2023 03:54:04 +0200 Subject: [PATCH] (shmif) merge compatible stepframes, preroll fdfix With the clockreq changes from b3364d the chance for a buildup on a stalled client is substantially higher. While realtime performance is to be asked of someone explicitly asking for vblank feedback, it is not always in their control. To help congestion then, add stepframe to the list of valid candidates. This also fixes a subtle thing to take note of and monitor for. Normally fd- transfer events aren't necessary during preroll, with a notable exception being DEVICEHINT for specifically routing a GPU, though that has not yet been used. While re-using shmif for other purposes, it was discovered that the first descriptor transfer during a preroll could be dropped, never to find the descriptor. Whether this is posix-madness that will come back to bite us or not is to be seen, but change the behaviour to retry when an expected descriptor does not arrive - instead of returning an event with a bad descriptor field. --- src/shmif/arcan_shmif_control.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/shmif/arcan_shmif_control.c b/src/shmif/arcan_shmif_control.c index f875315d4..75e58e228 100644 --- a/src/shmif/arcan_shmif_control.c +++ b/src/shmif/arcan_shmif_control.c @@ -558,6 +558,25 @@ static bool calc_dirty( return true; } +static bool scan_stepframe_event( + struct arcan_evctx*c, struct arcan_event* old, int id) +{ + if (old->tgt.ioevs[1].iv != id) + return false; + uint8_t cur = *c->front; + +/* conservative merge on STEPFRAME so far is results from VBLANK polling only */ + while (cur != *c->back){ + struct arcan_event* ev = &c->eventbuf[cur]; + if (ev->category == EVENT_TARGET && + ev->tgt.kind == TARGET_COMMAND_STEPFRAME && + ev->tgt.ioevs[1].iv == id) + return true; + cur = (cur + 1) % c->eventbuf_sz; + } + return false; +} + static bool scan_disp_event(struct arcan_evctx* c, struct arcan_event* old) { uint8_t cur = *c->front; @@ -801,8 +820,10 @@ static int process_events(struct arcan_shmif_cont* c, */ checkfd: do { - if (-1 == priv->pev.fd) + errno = 0; + if (-1 == priv->pev.fd){ priv->pev.fd = arcan_fetchhandle(c->epipe, blocking); + } if (priv->pev.gotev){ if (blocking){ @@ -820,7 +841,7 @@ static int process_events(struct arcan_shmif_cont* c, else if (blocking){ debug_print(STATUS, c, "failure on blocking fd-wait: %s, %s", strerror(errno), arcan_shmif_eventstr(&priv->pev.ev, NULL, 0)); - if (errno == EAGAIN) + if (!errno || errno == EAGAIN) continue; } @@ -865,6 +886,11 @@ static int process_events(struct arcan_shmif_cont* c, goto reset; break; + case TARGET_COMMAND_STEPFRAME: + if (scan_stepframe_event(ctx, dst, 2) || scan_stepframe_event(ctx, dst, 3)) + goto reset; + break; + /* automatic pause switches to pause_ev, which only supports subset */ case TARGET_COMMAND_PAUSE: if ((priv->flags & SHMIF_MANUAL_PAUSE) == 0){