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.
This commit is contained in:
Ray Strode 2019-01-12 12:38:01 -05:00
parent 53d63ea72b
commit 45c5f557bd
3 changed files with 55 additions and 0 deletions

View File

@ -34,6 +34,7 @@
#include "meta-crtc-kms.h" #include "meta-crtc-kms.h"
#include "meta-gpu-kms.h" #include "meta-gpu-kms.h"
#include "meta-output-kms.h" #include "meta-output-kms.h"
#include "wayland/meta-wayland-outputs.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -415,9 +416,15 @@ void
meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms) meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
{ {
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
ClutterBackend *clutter_backend = clutter_get_default_backend ();
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
meta_monitor_manager_kms_connect_uevent_handler (manager_kms); meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
handle_hotplug_event (manager); handle_hotplug_event (manager);
if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ());
} }
static gboolean static gboolean

View File

@ -452,6 +452,53 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
return new_table; 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 static void
on_monitors_changed (MetaMonitorManager *monitors, on_monitors_changed (MetaMonitorManager *monitors,
MetaWaylandCompositor *compositor) MetaWaylandCompositor *compositor)

View File

@ -47,5 +47,6 @@ struct _MetaWaylandOutput
}; };
void meta_wayland_outputs_init (MetaWaylandCompositor *compositor); void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);
void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor);
#endif /* META_WAYLAND_OUTPUTS_H */ #endif /* META_WAYLAND_OUTPUTS_H */