Unredirect fullscreen windows
Some apps that do a lot of rendering on the screen like games, mostly run in fullscreen where there is no need for them to be redirected doing so does add an overhead; while performance is critical for those apps. This can be disabled / enabled at runtime using meta_enable_unredirect_for_screen / meta_disable_unredirect_for_screen https://bugzilla.gnome.org/show_bug.cgi?id=597014
This commit is contained in:
parent
05fee9beea
commit
d3831729a0
@ -8,6 +8,7 @@
|
|||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
#include <meta/display.h>
|
#include <meta/display.h>
|
||||||
#include "meta-plugin-manager.h"
|
#include "meta-plugin-manager.h"
|
||||||
|
#include "meta-window-actor-private.h"
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
typedef struct _MetaCompScreen MetaCompScreen;
|
typedef struct _MetaCompScreen MetaCompScreen;
|
||||||
@ -41,6 +42,10 @@ struct _MetaCompScreen
|
|||||||
GHashTable *windows_by_xid;
|
GHashTable *windows_by_xid;
|
||||||
Window output;
|
Window output;
|
||||||
|
|
||||||
|
/* Used for unredirecting fullscreen windows */
|
||||||
|
guint disable_unredirect_count;
|
||||||
|
MetaWindowActor *unredirected_window;
|
||||||
|
|
||||||
/* Before we create the output window */
|
/* Before we create the output window */
|
||||||
XserverRegion pending_input_region;
|
XserverRegion pending_input_region;
|
||||||
|
|
||||||
|
@ -598,6 +598,38 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
|||||||
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shapes the cow so that the given window is exposed,
|
||||||
|
* when xwin is None it clears the shape again
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
meta_shape_cow_for_window (MetaScreen *screen,
|
||||||
|
Window xwin)
|
||||||
|
{
|
||||||
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
|
Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));
|
||||||
|
|
||||||
|
if (xwin == None)
|
||||||
|
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XserverRegion output_region;
|
||||||
|
XRectangle screen_rect;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
meta_screen_get_size (screen, &width, &height);
|
||||||
|
screen_rect.x = 0;
|
||||||
|
screen_rect.y = 0;
|
||||||
|
screen_rect.width = width;
|
||||||
|
screen_rect.height = height;
|
||||||
|
|
||||||
|
output_region = XFixesCreateRegionFromWindow (xdisplay, xwin, WindowRegionBounding);
|
||||||
|
XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
|
||||||
|
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region);
|
||||||
|
XFixesDestroyRegion (xdisplay, output_region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_compositor_add_window (MetaCompositor *compositor,
|
meta_compositor_add_window (MetaCompositor *compositor,
|
||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
@ -618,12 +650,25 @@ meta_compositor_remove_window (MetaCompositor *compositor,
|
|||||||
MetaWindow *window)
|
MetaWindow *window)
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor = NULL;
|
MetaWindowActor *window_actor = NULL;
|
||||||
|
MetaScreen *screen;
|
||||||
|
MetaCompScreen *info;
|
||||||
|
|
||||||
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
||||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||||
if (!window_actor)
|
if (!window_actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
screen = meta_window_get_screen (window);
|
||||||
|
info = meta_screen_get_compositor_data (screen);
|
||||||
|
|
||||||
|
if (window_actor == info->unredirected_window)
|
||||||
|
{
|
||||||
|
meta_window_actor_set_redirected (window_actor, TRUE);
|
||||||
|
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
|
||||||
|
None);
|
||||||
|
info->unredirected_window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
meta_window_actor_destroy (window_actor);
|
meta_window_actor_destroy (window_actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1097,6 +1142,33 @@ static void
|
|||||||
pre_paint_windows (MetaCompScreen *info)
|
pre_paint_windows (MetaCompScreen *info)
|
||||||
{
|
{
|
||||||
GList *l;
|
GList *l;
|
||||||
|
MetaWindowActor *top_window;
|
||||||
|
MetaWindowActor *expected_unredirected_window = NULL;
|
||||||
|
|
||||||
|
top_window = g_list_last (info->windows)->data;
|
||||||
|
|
||||||
|
if (meta_window_actor_should_unredirect (top_window) &&
|
||||||
|
info->disable_unredirect_count == 0)
|
||||||
|
expected_unredirected_window = top_window;
|
||||||
|
|
||||||
|
if (info->unredirected_window != expected_unredirected_window)
|
||||||
|
{
|
||||||
|
if (info->unredirected_window != NULL)
|
||||||
|
{
|
||||||
|
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
|
||||||
|
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
|
||||||
|
None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expected_unredirected_window != NULL)
|
||||||
|
{
|
||||||
|
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
|
||||||
|
meta_window_actor_get_x_window (top_window));
|
||||||
|
meta_window_actor_set_redirected (top_window, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
info->unredirected_window = expected_unredirected_window;
|
||||||
|
}
|
||||||
|
|
||||||
for (l = info->windows; l; l = l->next)
|
for (l = info->windows; l; l = l->next)
|
||||||
meta_window_actor_pre_paint (l->data);
|
meta_window_actor_pre_paint (l->data);
|
||||||
@ -1200,6 +1272,37 @@ meta_get_overlay_window (MetaScreen *screen)
|
|||||||
return info->output;
|
return info->output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_disable_unredirect_for_screen:
|
||||||
|
* @screen: a #MetaScreen
|
||||||
|
*
|
||||||
|
* Disables unredirection, can be usefull in situations where having
|
||||||
|
* unredirected windows is undesireable like when recording a video.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_disable_unredirect_for_screen (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
|
if (info != NULL)
|
||||||
|
info->disable_unredirect_count = info->disable_unredirect_count + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_enable_unredirect_for_screen:
|
||||||
|
* @screen: a #MetaScreen
|
||||||
|
*
|
||||||
|
* Enables unredirection which reduces the overhead for apps like games.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_enable_unredirect_for_screen (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||||
|
if (info != NULL)
|
||||||
|
info->disable_unredirect_count = MAX(0, info->disable_unredirect_count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
#define FLASH_TIME_MS 50
|
#define FLASH_TIME_MS 50
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -26,10 +26,18 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
|
|||||||
|
|
||||||
void meta_window_actor_process_damage (MetaWindowActor *self,
|
void meta_window_actor_process_damage (MetaWindowActor *self,
|
||||||
XDamageNotifyEvent *event);
|
XDamageNotifyEvent *event);
|
||||||
|
|
||||||
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
void meta_window_actor_pre_paint (MetaWindowActor *self);
|
||||||
|
|
||||||
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
||||||
|
|
||||||
|
void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state);
|
||||||
|
|
||||||
|
gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
|
||||||
|
|
||||||
|
void meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||||
|
cairo_rectangle_int_t *bounds);
|
||||||
|
|
||||||
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
||||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||||
|
@ -114,6 +114,8 @@ struct _MetaWindowActorPrivate
|
|||||||
guint no_shadow : 1;
|
guint no_shadow : 1;
|
||||||
|
|
||||||
guint no_more_x_calls : 1;
|
guint no_more_x_calls : 1;
|
||||||
|
|
||||||
|
guint unredirected : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -575,7 +577,7 @@ meta_window_actor_get_shadow_params (MetaWindowActor *self,
|
|||||||
params);
|
params);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||||
cairo_rectangle_int_t *bounds)
|
cairo_rectangle_int_t *bounds)
|
||||||
{
|
{
|
||||||
@ -1210,6 +1212,62 @@ meta_window_actor_detach (MetaWindowActor *self)
|
|||||||
meta_window_actor_queue_create_pixmap (self);
|
meta_window_actor_queue_create_pixmap (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||||
|
{
|
||||||
|
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
|
||||||
|
MetaScreen *screen = meta_window_get_screen (metaWindow);
|
||||||
|
|
||||||
|
if (meta_window_is_override_redirect (metaWindow))
|
||||||
|
{
|
||||||
|
int screen_width, screen_height;
|
||||||
|
MetaRectangle window_rect;
|
||||||
|
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)
|
||||||
|
return TRUE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int num_monitors = meta_screen_get_n_monitors (screen);
|
||||||
|
int i;
|
||||||
|
MetaRectangle monitor_rect;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
|
||||||
|
{
|
||||||
|
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
|
||||||
|
|
||||||
|
Display *xdisplay = meta_display_get_xdisplay (meta_window_get_display (metaWindow));
|
||||||
|
Window xwin = meta_window_actor_get_x_window (self);
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
{
|
||||||
|
XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
|
||||||
|
meta_window_actor_queue_create_pixmap (self);
|
||||||
|
self->priv->unredirected = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
|
||||||
|
self->priv->unredirected = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_window_actor_destroy (MetaWindowActor *self)
|
meta_window_actor_destroy (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
@ -1945,6 +2003,10 @@ meta_window_actor_process_damage (MetaWindowActor *self,
|
|||||||
|
|
||||||
priv->received_damage = TRUE;
|
priv->received_damage = TRUE;
|
||||||
|
|
||||||
|
/* Drop damage event for unredirected windows */
|
||||||
|
if (self->priv->unredirected)
|
||||||
|
return;
|
||||||
|
|
||||||
if (is_frozen (self))
|
if (is_frozen (self))
|
||||||
{
|
{
|
||||||
/* The window is frozen due to an effect in progress: we ignore damage
|
/* The window is frozen due to an effect in progress: we ignore damage
|
||||||
@ -2226,7 +2288,7 @@ meta_window_actor_pre_paint (MetaWindowActor *self)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->received_damage)
|
if (priv->received_damage && !self->unredirected)
|
||||||
{
|
{
|
||||||
meta_error_trap_push (display);
|
meta_error_trap_push (display);
|
||||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||||
|
|
||||||
|
#include "compositor-private.h"
|
||||||
#include "meta-window-actor-private.h"
|
#include "meta-window-actor-private.h"
|
||||||
#include "meta-window-group.h"
|
#include "meta-window-group.h"
|
||||||
#include "meta-background-actor-private.h"
|
#include "meta-background-actor-private.h"
|
||||||
@ -104,10 +105,19 @@ static void
|
|||||||
meta_window_group_paint (ClutterActor *actor)
|
meta_window_group_paint (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
cairo_region_t *visible_region;
|
cairo_region_t *visible_region;
|
||||||
|
cairo_region_t *unredirected_window_region = NULL;
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
cairo_rectangle_int_t visible_rect;
|
cairo_rectangle_int_t visible_rect, unredirected_rect;
|
||||||
GList *children, *l;
|
GList *children, *l;
|
||||||
|
|
||||||
|
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||||
|
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||||
|
if (info->unredirected_window != NULL)
|
||||||
|
{
|
||||||
|
meta_window_actor_get_shape_bounds (META_WINDOW_ACTOR (info->unredirected_window), &unredirected_rect);
|
||||||
|
unredirected_window_region = cairo_region_create_rectangle (&unredirected_rect);
|
||||||
|
}
|
||||||
|
|
||||||
/* We walk the list from top to bottom (opposite of painting order),
|
/* We walk the list from top to bottom (opposite of painting order),
|
||||||
* and subtract the opaque area of each window out of the visible
|
* and subtract the opaque area of each window out of the visible
|
||||||
* region that we pass to the windows below.
|
* region that we pass to the windows below.
|
||||||
@ -127,6 +137,9 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
visible_region = cairo_region_create_rectangle (&visible_rect);
|
visible_region = cairo_region_create_rectangle (&visible_rect);
|
||||||
|
|
||||||
|
if (unredirected_window_region)
|
||||||
|
cairo_region_subtract (visible_region, unredirected_window_region);
|
||||||
|
|
||||||
for (l = children; l; l = l->next)
|
for (l = children; l; l = l->next)
|
||||||
{
|
{
|
||||||
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||||
@ -164,6 +177,9 @@ meta_window_group_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
cairo_region_destroy (visible_region);
|
cairo_region_destroy (visible_region);
|
||||||
|
|
||||||
|
if (unredirected_window_region)
|
||||||
|
cairo_region_destroy (unredirected_window_region);
|
||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
||||||
|
|
||||||
/* Now that we are done painting, unset the visible regions (they will
|
/* Now that we are done painting, unset the visible regions (they will
|
||||||
|
@ -39,6 +39,9 @@ Window meta_get_overlay_window (MetaScreen *screen);
|
|||||||
GList *meta_get_window_actors (MetaScreen *screen);
|
GList *meta_get_window_actors (MetaScreen *screen);
|
||||||
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
|
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
|
||||||
|
|
||||||
|
void meta_disable_unredirect_for_screen (MetaScreen *screen);
|
||||||
|
void meta_enable_unredirect_for_screen (MetaScreen *screen);
|
||||||
|
|
||||||
ClutterActor *meta_get_background_actor_for_screen (MetaScreen *screen);
|
ClutterActor *meta_get_background_actor_for_screen (MetaScreen *screen);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user