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
This commit is contained in:
Carsten Haitzler 2017-01-07 13:16:06 +09:00
parent 78bd2ea6f5
commit 46a1bc2d22
1 changed files with 34 additions and 3 deletions

View File

@ -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",