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/display.h>
|
||||
#include "meta-plugin-manager.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef struct _MetaCompScreen MetaCompScreen;
|
||||
@ -41,6 +42,10 @@ struct _MetaCompScreen
|
||||
GHashTable *windows_by_xid;
|
||||
Window output;
|
||||
|
||||
/* Used for unredirecting fullscreen windows */
|
||||
guint disable_unredirect_count;
|
||||
MetaWindowActor *unredirected_window;
|
||||
|
||||
/* Before we create the output window */
|
||||
XserverRegion pending_input_region;
|
||||
|
||||
|
@ -598,6 +598,38 @@ meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||
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
|
||||
meta_compositor_add_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
@ -618,12 +650,25 @@ meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = NULL;
|
||||
MetaScreen *screen;
|
||||
MetaCompScreen *info;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_remove_window\n");
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1097,6 +1142,33 @@ static void
|
||||
pre_paint_windows (MetaCompScreen *info)
|
||||
{
|
||||
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)
|
||||
meta_window_actor_pre_paint (l->data);
|
||||
@ -1200,6 +1272,37 @@ meta_get_overlay_window (MetaScreen *screen)
|
||||
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
|
||||
|
||||
static void
|
||||
|
@ -26,10 +26,18 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
|
||||
|
||||
void meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
XDamageNotifyEvent *event);
|
||||
|
||||
void meta_window_actor_pre_paint (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);
|
||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||
|
@ -114,6 +114,8 @@ struct _MetaWindowActorPrivate
|
||||
guint no_shadow : 1;
|
||||
|
||||
guint no_more_x_calls : 1;
|
||||
|
||||
guint unredirected : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -575,7 +577,7 @@ meta_window_actor_get_shadow_params (MetaWindowActor *self,
|
||||
params);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *bounds)
|
||||
{
|
||||
@ -1210,6 +1212,62 @@ meta_window_actor_detach (MetaWindowActor *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
|
||||
meta_window_actor_destroy (MetaWindowActor *self)
|
||||
{
|
||||
@ -1945,6 +2003,10 @@ meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
|
||||
priv->received_damage = TRUE;
|
||||
|
||||
/* Drop damage event for unredirected windows */
|
||||
if (self->priv->unredirected)
|
||||
return;
|
||||
|
||||
if (is_frozen (self))
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (priv->received_damage)
|
||||
if (priv->received_damage && !self->unredirected)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XDamageSubtract (xdisplay, priv->damage, None, None);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-background-actor-private.h"
|
||||
@ -104,10 +105,19 @@ static void
|
||||
meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
cairo_region_t *visible_region;
|
||||
cairo_region_t *unredirected_window_region = NULL;
|
||||
ClutterActor *stage;
|
||||
cairo_rectangle_int_t visible_rect;
|
||||
cairo_rectangle_int_t visible_rect, unredirected_rect;
|
||||
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),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* 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);
|
||||
|
||||
if (unredirected_window_region)
|
||||
cairo_region_subtract (visible_region, unredirected_window_region);
|
||||
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
|
||||
@ -164,6 +177,9 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user