gpu-kms: poll() on KMS fd on EAGAIN

When drmHandleEvent() returns an error and errno is set to EAGAIN,
instead of ending up in a busy loop, poll() the fd until there is
anything to read.

https://bugzilla.gnome.org/show_bug.cgi?id=785381
This commit is contained in:
Jonas Ådahl 2017-07-24 10:50:49 +08:00
parent 8b23dd915f
commit 406359bba1
3 changed files with 44 additions and 8 deletions

View File

@ -25,6 +25,7 @@
#include <drm.h>
#include <errno.h>
#include <poll.h>
#include <string.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@ -80,7 +81,7 @@ kms_event_dispatch (GSource *source,
{
MetaKmsSource *kms_source = (MetaKmsSource *) source;
meta_gpu_kms_wait_for_flip (kms_source->gpu_kms);
meta_gpu_kms_wait_for_flip (kms_source->gpu_kms, NULL);
return G_SOURCE_CONTINUE;
}
@ -256,18 +257,52 @@ page_flip_handler (int fd,
invoke_flip_closure (flip_closure);
}
void
meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms)
gboolean
meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
GError **error)
{
drmEventContext evctx;
if (gpu_kms->page_flips_not_supported)
return;
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Page flips not supported");
return FALSE;
}
memset (&evctx, 0, sizeof evctx);
evctx.version = DRM_EVENT_CONTEXT_VERSION;
evctx.page_flip_handler = page_flip_handler;
drmHandleEvent (gpu_kms->fd, &evctx);
while (TRUE)
{
if (drmHandleEvent (gpu_kms->fd, &evctx) != 0)
{
struct pollfd pfd;
int ret;
if (errno != EAGAIN)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
strerror (errno));
return FALSE;
}
pfd.fd = gpu_kms->fd;
pfd.events = POLL_IN | POLL_ERR;
do
{
ret = poll (&pfd, 1, -1);
}
while (ret == -1 && errno == EINTR);
}
else
{
break;
}
}
return TRUE;
}
void

View File

@ -62,7 +62,8 @@ gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
GClosure *flip_closure,
gboolean *fb_in_use);
void meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms);
gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
GError **error);
int meta_gpu_kms_get_fd (MetaGpuKms *gpu_kms);

View File

@ -944,7 +944,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
* animation earlier due to the animation being driven by some other monitor.
*/
while (onscreen_native->pending_flips)
meta_gpu_kms_wait_for_flip (gpu_kms);
meta_gpu_kms_wait_for_flip (gpu_kms, NULL);
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
rectangles,
@ -1658,7 +1658,7 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
* to swap the current buffer.
*/
while (onscreen_native->gbm.next_fb_id != 0)
meta_gpu_kms_wait_for_flip (gpu_kms);
meta_gpu_kms_wait_for_flip (gpu_kms, NULL);
/* Need to drop the GBM surface and create a new one */