[mutter] gpu-kms: poll() on KMS fd on EAGAIN



commit 406359bba154e60aab2a14666eb5e183c1c0e1cf
Author: Jonas Ådahl <jadahl gmail com>
Date:   Mon Jul 24 10:50:49 2017 +0800

    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

 src/backends/native/meta-gpu-kms.c         |   45 ++++++++++++++++++++++++---
 src/backends/native/meta-gpu-kms.h         |    3 +-
 src/backends/native/meta-renderer-native.c |    4 +-
 3 files changed, 44 insertions(+), 8 deletions(-)
---
diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c
index 775ed34..0b70c38 100644
--- a/src/backends/native/meta-gpu-kms.c
+++ b/src/backends/native/meta-gpu-kms.c
@@ -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
diff --git a/src/backends/native/meta-gpu-kms.h b/src/backends/native/meta-gpu-kms.h
index 001fc95..6c7d5a3 100644
--- a/src/backends/native/meta-gpu-kms.h
+++ b/src/backends/native/meta-gpu-kms.h
@@ -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);
 
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 4fdaeb4..8a54e9b 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -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 */
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]