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
1 changed files with 82 additions and 6 deletions
|
@ -38,6 +38,20 @@
|
||||||
|
|
||||||
#include "meta-cullable.h"
|
#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_dispose (GObject *object);
|
||||||
|
|
||||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||||
|
@ -95,6 +109,11 @@ struct _MetaShapedTexturePrivate
|
||||||
guint tex_width, tex_height;
|
guint tex_width, tex_height;
|
||||||
guint fallback_width, fallback_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;
|
guint create_mipmaps : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -191,6 +210,12 @@ meta_shaped_texture_dispose (GObject *object)
|
||||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||||
MetaShapedTexturePrivate *priv = self->priv;
|
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)
|
if (priv->paint_tower)
|
||||||
meta_texture_tower_free (priv->paint_tower);
|
meta_texture_tower_free (priv->paint_tower);
|
||||||
priv->paint_tower = NULL;
|
priv->paint_tower = NULL;
|
||||||
|
@ -372,6 +397,21 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||||
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
|
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
|
static void
|
||||||
meta_shaped_texture_paint (ClutterActor *actor)
|
meta_shaped_texture_paint (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
|
@ -381,9 +421,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||||
guchar opacity;
|
guchar opacity;
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
CoglFramebuffer *fb;
|
CoglFramebuffer *fb;
|
||||||
CoglTexture *paint_tex;
|
CoglTexture *paint_tex = NULL;
|
||||||
ClutterActorBox alloc;
|
ClutterActorBox alloc;
|
||||||
CoglPipelineFilter filter;
|
CoglPipelineFilter filter;
|
||||||
|
gint64 now = g_get_monotonic_time ();
|
||||||
|
|
||||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||||
return;
|
return;
|
||||||
|
@ -406,14 +447,35 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||||
* support for TFP textures will result in fallbacks to XGetImage.
|
* support for TFP textures will result in fallbacks to XGetImage.
|
||||||
*/
|
*/
|
||||||
if (priv->create_mipmaps)
|
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);
|
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||||
else
|
}
|
||||||
|
|
||||||
|
if (paint_tex == NULL)
|
||||||
|
{
|
||||||
paint_tex = COGL_TEXTURE (priv->texture);
|
paint_tex = COGL_TEXTURE (priv->texture);
|
||||||
|
|
||||||
if (paint_tex == NULL)
|
if (paint_tex == NULL)
|
||||||
return;
|
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_width = priv->tex_width;
|
||||||
tex_height = priv->tex_height;
|
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);
|
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);
|
unobscured_region = effective_unobscured_region (stex);
|
||||||
if (unobscured_region)
|
if (unobscured_region)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue