From 0584fc81a2960c47426560fa52bab675b10527b5 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Fri, 28 Jul 2017 15:25:25 -0500 Subject: [PATCH] ecore_drm2: Add a fallback method for vblank waiting We can't depend on vblank waits being implemented by the driver, but we can count on page flips functioning, so add a fallback that does a page flip and waits for it. --- src/lib/ecore_drm2/ecore_drm2_outputs.c | 49 +++++++++++++++++++++++++ src/lib/ecore_drm2/ecore_drm2_private.h | 2 + 2 files changed, 51 insertions(+) diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index fba4be0c8d..85504a0d6d 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1583,6 +1583,49 @@ ecore_drm2_output_subpixel_get(const Ecore_Drm2_Output *output) return output->subpixel; } +static void +_blank_fallback_handler(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec, unsigned int usec, void *data EINA_UNUSED) +{ + Ecore_Drm2_Output *output; + + output = data; + output->fallback_usec = usec; + output->fallback_sec = sec; +} +static int +_blanktime_fallback(Ecore_Drm2_Output *output, int sequence, long *sec, long *usec) +{ + drmEventContext ctx; + int ret; + + /* Too lazy to loop for > 1, and don't want to block for < 1 */ + if (sequence != 1) return -1; + + /* If we got here with a flip waiting to complete we can do nothing. */ + if (output->pending.fb) return -1; + + if (!output->current.fb) return -1; + + memset(&ctx, 0, sizeof(ctx)); + ctx.version = 2; + ctx.page_flip_handler = _blank_fallback_handler; + ctx.vblank_handler = NULL; + + ret = sym_drmModePageFlip(output->current.fb->fd, output->crtc_id, + output->current.fb->id, DRM_MODE_PAGE_FLIP_EVENT, + output); + if (ret < 0) return -1; + do + { + ret = sym_drmHandleEvent(output->current.fb->fd, &ctx); + } while (ret != 0 && errno == EAGAIN); + if (ret < 0) return -1; + + *sec = output->fallback_sec; + *usec = output->fallback_usec; + return 0; +} + EAPI Eina_Bool ecore_drm2_output_blanktime_get(Ecore_Drm2_Output *output, int sequence, long *sec, long *usec) { @@ -1597,6 +1640,12 @@ ecore_drm2_output_blanktime_get(Ecore_Drm2_Output *output, int sequence, long *s v.request.type = DRM_VBLANK_RELATIVE; v.request.sequence = sequence; ret = sym_drmWaitVBlank(output->fd, &v); + if (ret) + { + ret = _blanktime_fallback(output, sequence, sec, usec); + if (ret) return EINA_FALSE; + return EINA_TRUE; + } if (ret) return EINA_FALSE; if (v.reply.tval_sec < 0) return EINA_FALSE; if (v.reply.tval_usec < 0) return EINA_FALSE; diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index c8c2bf66c2..a85cb0c2d5 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -209,6 +209,8 @@ struct _Ecore_Drm2_Output int pipe; int x, y, w, h, pw, ph; + long fallback_sec, fallback_usec; + uint32_t subpixel; uint32_t crtc_id, conn_id, conn_type; uint32_t scale;