[mutter/wip/texture-purge-on-nvidia: 5/6] wayland: force X clients to redraw on resume



commit 5fa848f3496d1674801b4368a865ac1b8f97c69d
Author: Ray Strode <rstrode redhat com>
Date:   Sat Jan 12 12:38:01 2019 -0500

    wayland: force X clients to redraw on resume
    
    On nvidia, the textures backing Xwayland client window contents get
    corrupted on suspend.  Xwayland currently doesn't handle this situation
    itself.
    
    For now, in order to work around this issue, send an empty output
    change event to Xwayland.  This will cause it to force Expose events
    to get sent to all clients and get them to redraw.

 src/backends/native/meta-monitor-manager-kms.c |  3 ++
 src/wayland/meta-wayland-outputs.c             | 47 ++++++++++++++++++++++++++
 src/wayland/meta-wayland-outputs.h             |  1 +
 3 files changed, 51 insertions(+)
---
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 5a7178753..c90c8405f 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -34,6 +34,7 @@
 #include "meta-crtc-kms.h"
 #include "meta-gpu-kms.h"
 #include "meta-output-kms.h"
+#include "wayland/meta-wayland-outputs.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -447,6 +448,8 @@ meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
 
   meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
   handle_hotplug_event (manager);
+
+  meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ());
 }
 
 static gboolean
diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c
index 1f99a163d..450f5e484 100644
--- a/src/wayland/meta-wayland-outputs.c
+++ b/src/wayland/meta-wayland-outputs.c
@@ -452,6 +452,53 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
   return new_table;
 }
 
+void
+meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor)
+{
+  MetaMonitorManager *monitor_manager;
+  GList *logical_monitors, *l;
+
+  monitor_manager = meta_monitor_manager_get ();
+
+  logical_monitors =
+    meta_monitor_manager_get_logical_monitors (monitor_manager);
+
+  for (l = logical_monitors; l; l = l->next)
+    {
+      MetaLogicalMonitor *logical_monitor = l->data;
+      MetaWaylandOutput *wayland_output;
+      GList *iter;
+
+      if (logical_monitor->winsys_id == 0)
+        continue;
+
+      wayland_output =
+        g_hash_table_lookup (compositor->outputs,
+                             GSIZE_TO_POINTER (logical_monitor->winsys_id));
+
+      if (wayland_output == NULL)
+        continue;
+
+      /* Just output a "changes done" event for one of the outputs, with no actual changes.
+       * xwayland takes this as a cue to send expose events to all X clients.
+       */
+      for (iter = wayland_output->resources; iter; iter = iter->next)
+        {
+          struct wl_resource *resource = iter->data;
+          if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
+            wl_output_send_done (resource);
+        }
+
+      for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
+        {
+          struct wl_resource *xdg_output = iter->data;
+          zxdg_output_v1_send_done (xdg_output);
+        }
+
+      break;
+    }
+}
+
 static void
 on_monitors_changed (MetaMonitorManager    *monitors,
                      MetaWaylandCompositor *compositor)
diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h
index e6b60d5fa..d8c648174 100644
--- a/src/wayland/meta-wayland-outputs.h
+++ b/src/wayland/meta-wayland-outputs.h
@@ -47,5 +47,6 @@ struct _MetaWaylandOutput
 };
 
 void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);
+void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor);
 
 #endif /* META_WAYLAND_OUTPUTS_H */


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