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
This commit is contained in:
Adel Gadllah 2013-02-02 19:50:01 +01:00
parent 867e10dbcc
commit 90f2a3ae4c

View File

@ -119,6 +119,10 @@ struct _MetaWindowActorPrivate
guint no_more_x_calls : 1; guint no_more_x_calls : 1;
guint unredirected : 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 enum
@ -1158,48 +1162,59 @@ gboolean
meta_window_actor_should_unredirect (MetaWindowActor *self) meta_window_actor_should_unredirect (MetaWindowActor *self)
{ {
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
MetaScreen *screen = meta_window_get_screen (metaWindow);
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
int screen_width, screen_height;
MetaRectangle window_rect, monitor_rect; gboolean occupies_full_monitors = FALSE;
int num_monitors = meta_screen_get_n_monitors (screen);
int i;
if (meta_window_requested_dont_bypass_compositor (metaWindow)) if (meta_window_requested_dont_bypass_compositor (metaWindow))
return FALSE; return FALSE;
if (!meta_window_is_override_redirect (metaWindow) &&
!meta_window_requested_bypass_compositor (metaWindow))
return FALSE;
if (priv->opacity != 0xff) if (priv->opacity != 0xff)
return FALSE; return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
return FALSE;
if (metaWindow->has_shape) if (metaWindow->has_shape)
return FALSE; return FALSE;
if (meta_window_requested_bypass_compositor (metaWindow) && if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
meta_window_is_fullscreen (metaWindow)) return FALSE;
return TRUE;
meta_screen_get_size (screen, &screen_width, &screen_height); if (meta_window_is_fullscreen (metaWindow))
meta_window_get_outer_rect (metaWindow, &window_rect); occupies_full_monitors = TRUE;
else if (meta_window_is_override_redirect (metaWindow))
if (window_rect.x == 0 && window_rect.y == 0 &&
window_rect.width == screen_width && window_rect.height == screen_height)
return TRUE;
for (i = 0; i < num_monitors; i++)
{ {
meta_screen_get_monitor_geometry (screen , i, &monitor_rect); MetaScreen *screen = meta_window_get_screen (metaWindow);
if (monitor_rect.x == window_rect.x && monitor_rect.y == window_rect.y && MetaRectangle window_rect, monitor_rect;
monitor_rect.width == window_rect.width && monitor_rect.height == window_rect.height)
return TRUE; 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))
return TRUE;
if (meta_window_is_override_redirect (metaWindow))
return TRUE;
if (priv->does_full_damage)
return TRUE;
return FALSE; return FALSE;
} }
@ -1883,11 +1898,29 @@ meta_window_actor_process_damage (MetaWindowActor *self,
XDamageNotifyEvent *event) XDamageNotifyEvent *event)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
priv->received_damage = TRUE; 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 */ /* Drop damage event for unredirected windows */
if (self->priv->unredirected) if (priv->unredirected)
return; return;
if (is_frozen (self)) if (is_frozen (self))