[mutter] mutter-window-actor: Improve unredirect heuristic



commit 90f2a3ae4ca205f7cbbc2daeba2ab7cfa5ed1613
Author: Adel Gadllah <adel gadllah gmail com>
Date:   Sat Feb 2 19:50:01 2013 +0100

    mutter-window-actor: Improve unredirect heuristic
    
    Currently we only unredirect monitor sized override redirect windows.
    This was supposed to catch fullscreen opengl games and improve
    their performance.
    
    Newer games like fullscreen webgl games and SDL2 using games (like L4D) as well as wine based games do not use override redirect windows so we need a better
    heuristic to catch them.
    
    GLX windows always damage the whole window when calling glxSwapBuffers and
    never damage sub regions. So we can use that to detect them.
    
    The new heuristic unredirects windows fullscreen windows that have damaged the
    whole window more then 100 times in a row.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=683786

 src/compositor/meta-window-actor.c |   81 +++++++++++++++++++++++++-----------
 1 files changed, 57 insertions(+), 24 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 8963f39..4d68c80 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -119,6 +119,10 @@ struct _MetaWindowActorPrivate
   guint             no_more_x_calls        : 1;
 
   guint             unredirected           : 1;
+
+  /* This is used to detect fullscreen windows that need to be unredirected */
+  guint             full_damage_frames_count;
+  guint             does_full_damage  : 1;
 };
 
 enum
@@ -1158,47 +1162,58 @@ gboolean
 meta_window_actor_should_unredirect (MetaWindowActor *self)
 {
   MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
-  MetaScreen *screen = meta_window_get_screen (metaWindow);
   MetaWindowActorPrivate *priv = self->priv;
-  int screen_width, screen_height;
-  MetaRectangle window_rect, monitor_rect;
-  int num_monitors = meta_screen_get_n_monitors (screen);
-  int i;
+
+  gboolean occupies_full_monitors = FALSE;
 
   if (meta_window_requested_dont_bypass_compositor (metaWindow))
     return FALSE;
 
-  if (!meta_window_is_override_redirect (metaWindow) &&
-      !meta_window_requested_bypass_compositor (metaWindow))
+  if (priv->opacity != 0xff)
     return FALSE;
 
-  if (priv->opacity != 0xff)
+  if (metaWindow->has_shape)
     return FALSE;
 
   if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
     return FALSE;
 
-  if (metaWindow->has_shape)
+  if (meta_window_is_fullscreen (metaWindow))
+    occupies_full_monitors = TRUE;
+  else if (meta_window_is_override_redirect (metaWindow))
+    {
+      MetaScreen *screen = meta_window_get_screen (metaWindow);
+      MetaRectangle window_rect, monitor_rect;
+
+      int num_monitors = meta_screen_get_n_monitors (screen);
+      int screen_width, screen_height, i;
+
+      meta_screen_get_size (screen, &screen_width, &screen_height);
+
+      if (window_rect.x == 0 && window_rect.y == 0 &&
+          window_rect.width == screen_width && window_rect.height == screen_height)
+        occupies_full_monitors = TRUE;
+
+      for (i = 0; i < num_monitors; i++)
+        {
+          meta_screen_get_monitor_geometry (screen , i, &monitor_rect);
+          if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y &&
+              monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height)
+            occupies_full_monitors = TRUE;
+        }
+    }
+
+  if (!occupies_full_monitors)
     return FALSE;
 
-  if (meta_window_requested_bypass_compositor (metaWindow) &&
-      meta_window_is_fullscreen (metaWindow))
+  if (meta_window_requested_bypass_compositor (metaWindow))
     return TRUE;
 
-  meta_screen_get_size (screen, &screen_width, &screen_height);
-  meta_window_get_outer_rect (metaWindow, &window_rect);
-
-  if (window_rect.x == 0 && window_rect.y == 0 &&
-      window_rect.width == screen_width && window_rect.height == screen_height)
+  if (meta_window_is_override_redirect (metaWindow))
     return TRUE;
 
-  for (i = 0; i < num_monitors; i++)
-    {
-      meta_screen_get_monitor_geometry (screen , i, &monitor_rect);
-      if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y &&
-          monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height)
-        return TRUE;
-    }
+  if (priv->does_full_damage)
+    return TRUE;
 
   return FALSE;
 }
@@ -1883,11 +1898,29 @@ meta_window_actor_process_damage (MetaWindowActor    *self,
                                   XDamageNotifyEvent *event)
 {
   MetaWindowActorPrivate *priv = self->priv;
+  MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
 
   priv->received_damage = TRUE;
 
+  if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
+    {
+      MetaRectangle window_rect;
+      meta_window_get_outer_rect (priv->window, &window_rect);
+
+      if (window_rect.x == event->area.x &&
+          window_rect.y == event->area.y &&
+          window_rect.width == event->area.width &&
+          window_rect.height == event->area.height)
+        priv->full_damage_frames_count++;
+      else
+        priv->full_damage_frames_count = 0;
+
+      if (priv->full_damage_frames_count >= 100)
+        priv->does_full_damage = TRUE;
+    }
+
   /* Drop damage event for unredirected windows */
-  if (self->priv->unredirected)
+  if (priv->unredirected)
     return;
 
   if (is_frozen (self))



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