shaped-texture: Disable mipmapping during animation
This avoids overwhelming the GPU with trying to update mipmaps at a high rate. Because doing so could easily cause a reduction in the compositor frame rate and thus actually reduce visual quality. In the case of a window that is constantly animating in the overview, this reduces mutter's render time by around 20%-30%.
This commit is contained in:
parent
d2a8cdfd7c
commit
c9c3283540
@ -38,6 +38,20 @@
|
||||
|
||||
#include "meta-cullable.h"
|
||||
|
||||
/* MAX_MIPMAPPING_FPS needs to be as small as possible for the best GPU
|
||||
* performance, but higher than the refresh rate of commonly slow updating
|
||||
* windows like top or a blinking cursor, so that such windows do get
|
||||
* mipmapped.
|
||||
*/
|
||||
#define MAX_MIPMAPPING_FPS 5
|
||||
#define MIN_MIPMAP_AGE_USEC (G_USEC_PER_SEC / MAX_MIPMAPPING_FPS)
|
||||
|
||||
/* MIN_FAST_UPDATES_BEFORE_UNMIPMAP allows windows to update themselves
|
||||
* occasionally without causing mipmapping to be disabled, so long as such
|
||||
* an update takes fewer update_area calls than:
|
||||
*/
|
||||
#define MIN_FAST_UPDATES_BEFORE_UNMIPMAP 20
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
@ -95,6 +109,11 @@ struct _MetaShapedTexturePrivate
|
||||
guint tex_width, tex_height;
|
||||
guint fallback_width, fallback_height;
|
||||
|
||||
gint64 prev_invalidation, last_invalidation;
|
||||
guint fast_updates;
|
||||
guint remipmap_timeout_id;
|
||||
gint64 earliest_remipmap;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
@ -191,6 +210,12 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->remipmap_timeout_id)
|
||||
{
|
||||
g_source_remove (priv->remipmap_timeout_id);
|
||||
priv->remipmap_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
@ -372,6 +397,21 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_is_idle_and_not_mipmapped (gpointer user_data)
|
||||
{
|
||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (user_data);
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if ((g_get_monotonic_time () - priv->earliest_remipmap) < 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
priv->remipmap_timeout_id = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
@ -381,9 +421,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
guchar opacity;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglTexture *paint_tex;
|
||||
CoglTexture *paint_tex = NULL;
|
||||
ClutterActorBox alloc;
|
||||
CoglPipelineFilter filter;
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
@ -406,13 +447,34 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
if (priv->create_mipmaps && priv->last_invalidation)
|
||||
{
|
||||
gint64 age = now - priv->last_invalidation;
|
||||
|
||||
if (age >= MIN_MIPMAP_AGE_USEC ||
|
||||
priv->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
}
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
{
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
{
|
||||
/* Minus 1000 to ensure we don't fail the age test in timeout */
|
||||
priv->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
|
||||
|
||||
if (!priv->remipmap_timeout_id)
|
||||
priv->remipmap_timeout_id =
|
||||
g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000,
|
||||
texture_is_idle_and_not_mipmapped,
|
||||
stex);
|
||||
}
|
||||
}
|
||||
|
||||
tex_width = priv->tex_width;
|
||||
tex_height = priv->tex_height;
|
||||
@ -758,6 +820,20 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
|
||||
priv->prev_invalidation = priv->last_invalidation;
|
||||
priv->last_invalidation = g_get_monotonic_time ();
|
||||
|
||||
if (priv->prev_invalidation)
|
||||
{
|
||||
gint64 interval = priv->last_invalidation - priv->prev_invalidation;
|
||||
gboolean fast_update = interval < MIN_MIPMAP_AGE_USEC;
|
||||
|
||||
if (!fast_update)
|
||||
priv->fast_updates = 0;
|
||||
else if (priv->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
||||
priv->fast_updates++;
|
||||
}
|
||||
|
||||
unobscured_region = effective_unobscured_region (stex);
|
||||
if (unobscured_region)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user