From 46a1bc2d225a42829f1e278f4432b2d8af3e0725 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 7 Jan 2017 13:16:06 +0900 Subject: [PATCH] ecore_drm2 - work with broken kernels that EBUSY on drm page flip so thelatest rpi kernels available e.g. in raspbian contain no fixes for this yet so thatmeans basically ALL users would be affected, so best to have a small workaround in ecore_drm2 to try the page flip a few times until it works. this actually works. i try a usleep for 100 then try again. up to 500 times max then give up. actual numbers show that betwee 1 to about 60 tries gets the flip to happen when these glitches happen. log an error when this happens so we know it's happening and a workaround is kicking in. technically this would be much nicer if swapping had a dedicated thread that could stall in this case and keep trying, but the odd times it happens (seems to happen on average maybe once every 30 seconds) it wouldnt stall the mainloop or rendering and JUSt stall a dedicated swapper thread. this requires a lot mor work to implement though and we'd have to then ensure swaps ARe async with the swap result coming back as an event etc... so a lot more work. this at least makes rendering on the rpi stable and i can dig into other issues like libproxy throws exceptions and causes a whole process abort() as a result, or the latest mesa pkgs have totally broken partial gl rnedering with all non-rendered areas being black (it used to work though... until i updated). @fix --- src/lib/ecore_drm2/ecore_drm2_fb.c | 37 +++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c index 6648d67aab..6b4a1b731a 100644 --- a/src/lib/ecore_drm2/ecore_drm2_fb.c +++ b/src/lib/ecore_drm2/ecore_drm2_fb.c @@ -393,6 +393,9 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) else #endif { + Eina_Bool repeat; + int count = 0; + if ((!output->current) || (output->current->stride != fb->stride)) { @@ -419,9 +422,37 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) */ } - ret = - sym_drmModePageFlip(fb->fd, output->crtc_id, fb->id, - DRM_MODE_PAGE_FLIP_EVENT, output->user_data); + do + { + repeat = EINA_FALSE; + ret = sym_drmModePageFlip(fb->fd, output->crtc_id, fb->id, + DRM_MODE_PAGE_FLIP_EVENT, + output->user_data); + /* Some drivers (RPI - looking at you) are broken and produce + * flip events before they are ready for another flip, so be + * a little robust in the face of badness and try a few times + * until we can flip or we give up (100 tries with a yield + * between each try). We can't expect everyone to run the + * latest bleeding edge kernel IF a workaround is possible + * in userspace, so do this. */ + if ((ret < 0) && (errno == EBUSY)) + { + repeat = EINA_TRUE; + if (count == 0) + ERR("Pageflip fail - EBUSY from drmModePageFlip..."); + count++; + if (count > 500) + { + ERR("Pageflip EBUSY for %i tries - give up", count); + break; + } + usleep(100); + } + } + while (repeat); + if ((ret == 0) && (count > 0)) + ERR("Pageflip finally succeeded after %i tries due to EBUSY", count); + if ((ret < 0) && (errno != EBUSY)) { DBG("Pageflip Failed for Crtc %u on Connector %u: %m",