1
0
Fork 0
mutter-performance-pkgbuild/mr1877.patch
Sung Mingi e25757d0e9
Sync to gnome-42 & Re-enable !1877 by default
* Also update both !1441 and !1877.

Signed-off-by: Sung Mingi <FiestaLake@protonmail.com>
2022-04-13 17:39:19 +09:00

1117 lines
40 KiB
Diff

Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
Source: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1877
Editor: Sung Mingi <FiestaLake@protonmail.com>
Commit: 463d746d30f66925657fea8711acd6cfa5ab01d7
Last Updated: 04/13/22 (Mutter 42.0+r45+g9d0f612de-2)
---
By avoiding StScrollViewFade we avoid offscreening and therefore
avoid painting everything twice to get it on screen. So this almost
halves the render time of the icon grid.
---
diff --git a/src/compositor/clutter-utils.c b/src/compositor/clutter-utils.c
index 86d788562e383c38961de1b385bb7bbf16424d28..3c7165f1ef1bb70f2fab58adb4d09716ef816e35 100644
--- a/src/compositor/clutter-utils.c
+++ b/src/compositor/clutter-utils.c
@@ -69,8 +69,7 @@ gboolean
meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
float widthf,
float heightf,
- int *x_origin,
- int *y_origin)
+ MetaTransforms *trans)
{
int width, height;
int v0x, v0y, v1x, v1y, v2x, v2y, v3x, v3y;
@@ -90,6 +89,14 @@ meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
x = v0x >> 8;
y = v0y >> 8;
+ if (trans)
+ {
+ trans->x_origin = x;
+ trans->y_origin = y;
+ trans->x_scale = (v1x - v0x) / (float) width;
+ trans->y_scale = (v2y - v0y) / (float) height;
+ }
+
/* At integral coordinates? */
if (x * 256 != v0x || y * 256 != v0y)
return FALSE;
@@ -103,11 +110,6 @@ meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
v3x != v1x || v3y != v2y)
return FALSE;
- if (x_origin)
- *x_origin = x;
- if (y_origin)
- *y_origin = y;
-
return TRUE;
}
@@ -137,8 +139,7 @@ meta_actor_painting_untransformed (CoglFramebuffer *fb,
int paint_height,
int sample_width,
int sample_height,
- int *x_origin,
- int *y_origin)
+ MetaTransforms *trans)
{
graphene_matrix_t modelview, projection, modelview_projection;
graphene_point3d_t vertices[4];
@@ -183,6 +184,6 @@ meta_actor_painting_untransformed (CoglFramebuffer *fb,
return meta_actor_vertices_are_untransformed (vertices,
sample_width, sample_height,
- x_origin, y_origin);
+ trans);
}
diff --git a/src/compositor/clutter-utils.h b/src/compositor/clutter-utils.h
index 8ed0e2a4d127d037a0371d01d1d7dbd349adc161..039e61a61998dba8acff584017daf258fe763f18 100644
--- a/src/compositor/clutter-utils.h
+++ b/src/compositor/clutter-utils.h
@@ -23,18 +23,21 @@
#include "clutter/clutter.h"
+typedef struct {
+ int x_origin, y_origin;
+ float x_scale, y_scale;
+} MetaTransforms;
+
gboolean meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
float widthf,
float heightf,
- int *x_origin,
- int *y_origin);
+ MetaTransforms *trans);
gboolean meta_actor_painting_untransformed (CoglFramebuffer *fb,
int paint_width,
int paint_height,
int sample_widthf,
int sample_heightf,
- int *x_origin,
- int *y_origin);
+ MetaTransforms *trans);
#endif /* __META_CLUTTER_UTILS_H__ */
diff --git a/src/compositor/meta-background-content.c b/src/compositor/meta-background-content.c
index 49f5885ca70d1a69ee81be4139f448fcb7c70dce..93de521d05bb7a334fbccfc872d220a43ca7d7da 100644
--- a/src/compositor/meta-background-content.c
+++ b/src/compositor/meta-background-content.c
@@ -561,7 +561,7 @@ setup_pipeline (MetaBackgroundContent *self,
actor_pixel_rect->height,
self->texture_width,
self->texture_height,
- NULL, NULL))
+ NULL))
{
min_filter = COGL_PIPELINE_FILTER_NEAREST;
mag_filter = COGL_PIPELINE_FILTER_NEAREST;
diff --git a/src/compositor/meta-cullable.c b/src/compositor/meta-cullable.c
index 6f38c5e47c8f8e219bd195fc2da274c97ba298ec..e306c56e287752ab9e09ec3958e205de3a4d47a9 100644
--- a/src/compositor/meta-cullable.c
+++ b/src/compositor/meta-cullable.c
@@ -175,7 +175,7 @@ meta_cullable_default_is_untransformed (MetaCullable *cullable)
clutter_actor_get_abs_allocation_vertices (CLUTTER_ACTOR (cullable), verts);
return meta_actor_vertices_are_untransformed (verts, width, height,
- NULL, NULL);
+ NULL);
}
static void
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 34fec6852ad8dd348934e16474e97265a7f390d8..222095587a3f258721e69d647459c8af85fd4946 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -41,7 +41,6 @@
#include "cogl/cogl.h"
#include "compositor/clutter-utils.h"
-#include "compositor/meta-texture-tower.h"
#include "compositor/region-utils.h"
#include "core/boxes-private.h"
#include "meta/meta-shaped-texture.h"
@@ -82,8 +81,6 @@ struct _MetaShapedTexture
{
GObject parent;
- MetaTextureTower *paint_tower;
-
CoglTexture *texture;
CoglTexture *mask_texture;
CoglSnippet *snippet;
@@ -96,6 +93,11 @@ struct _MetaShapedTexture
CoglPipeline *unblended_pipeline;
CoglPipeline *unblended_tower_pipeline;
+ CoglTexture *mipmap_texture;
+ gboolean mipmap_texture_out_of_date;
+ CoglFramebuffer *mipmap_fb;
+ CoglPipeline *mipmap_pipeline;
+
gboolean is_y_inverted;
/* The region containing only fully opaque pixels */
@@ -154,8 +156,6 @@ invalidate_size (MetaShapedTexture *stex)
static void
meta_shaped_texture_init (MetaShapedTexture *stex)
{
- stex->paint_tower = meta_texture_tower_new ();
-
stex->buffer_scale = 1;
stex->texture = NULL;
stex->mask_texture = NULL;
@@ -252,6 +252,13 @@ meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
g_clear_pointer (&stex->unblended_tower_pipeline, cogl_object_unref);
}
+static void
+free_mipmaps (MetaShapedTexture *stex)
+{
+ g_clear_object (&stex->mipmap_fb);
+ cogl_clear_object (&stex->mipmap_texture);
+}
+
static void
meta_shaped_texture_dispose (GObject *object)
{
@@ -259,9 +266,8 @@ meta_shaped_texture_dispose (GObject *object)
g_clear_handle_id (&stex->remipmap_timeout_id, g_source_remove);
- if (stex->paint_tower)
- meta_texture_tower_free (stex->paint_tower);
- stex->paint_tower = NULL;
+ free_mipmaps (stex);
+ cogl_clear_object (&stex->mipmap_pipeline);
g_clear_pointer (&stex->texture, cogl_object_unref);
@@ -618,13 +624,7 @@ set_cogl_texture (MetaShapedTexture *stex,
update_size (stex);
}
- /* NB: We don't queue a redraw of the actor here because we don't
- * know how much of the buffer has changed with respect to the
- * previous buffer. We only queue a redraw in response to surface
- * damage. */
-
- if (stex->create_mipmaps)
- meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
+ stex->mipmap_texture_out_of_date = TRUE;
}
static gboolean
@@ -652,11 +652,14 @@ flip_ints (int *x,
*y = tmp;
}
+static CoglTexture *
+select_texture_for_paint (MetaShapedTexture *stex,
+ ClutterPaintContext *paint_context);
+
static void
do_paint_content (MetaShapedTexture *stex,
ClutterPaintNode *root_node,
ClutterPaintContext *paint_context,
- CoglTexture *paint_tex,
ClutterActorBox *alloc,
uint8_t opacity)
{
@@ -665,7 +668,9 @@ do_paint_content (MetaShapedTexture *stex,
gboolean use_opaque_region;
cairo_region_t *blended_tex_region;
CoglContext *ctx;
- CoglPipelineFilter filter;
+ CoglPipelineFilter min_filter, mag_filter;
+ MetaTransforms transforms;
+ CoglTexture *paint_tex = stex->texture;
CoglFramebuffer *framebuffer;
int sample_width, sample_height;
gboolean debug_paint_opaque_region;
@@ -712,10 +717,33 @@ do_paint_content (MetaShapedTexture *stex,
if (meta_actor_painting_untransformed (framebuffer,
dst_width, dst_height,
sample_width, sample_height,
- NULL, NULL))
- filter = COGL_PIPELINE_FILTER_NEAREST;
+ &transforms))
+ {
+ min_filter = COGL_PIPELINE_FILTER_NEAREST;
+ mag_filter = COGL_PIPELINE_FILTER_NEAREST;
+
+ /* Back to normal desktop viewing. Save some memory */
+ free_mipmaps (stex);
+ }
else
- filter = COGL_PIPELINE_FILTER_LINEAR;
+ {
+ min_filter = COGL_PIPELINE_FILTER_LINEAR;
+ mag_filter = COGL_PIPELINE_FILTER_LINEAR;
+
+ /* If we're painting a texture below half its native resolution
+ * then mipmapping is required to avoid aliasing. If it's above
+ * half then sticking with COGL_PIPELINE_FILTER_LINEAR will look
+ * and perform better.
+ */
+ if (stex->create_mipmaps &&
+ transforms.x_scale < 0.5 &&
+ transforms.y_scale < 0.5)
+ {
+ paint_tex = select_texture_for_paint (stex, paint_context);
+ if (paint_tex == stex->mipmap_texture)
+ min_filter = COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST;
+ }
+ }
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
@@ -777,7 +805,7 @@ do_paint_content (MetaShapedTexture *stex,
opaque_pipeline = get_unblended_pipeline (stex, ctx, paint_tex);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
- cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
+ cogl_pipeline_set_layer_filters (opaque_pipeline, 0, min_filter, mag_filter);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
@@ -825,11 +853,11 @@ do_paint_content (MetaShapedTexture *stex,
{
blended_pipeline = get_masked_pipeline (stex, ctx, paint_tex);
cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture);
- cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
+ cogl_pipeline_set_layer_filters (blended_pipeline, 1, min_filter, mag_filter);
}
cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex);
- cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter);
+ cogl_pipeline_set_layer_filters (blended_pipeline, 0, min_filter, mag_filter);
CoglColor color;
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
@@ -894,6 +922,94 @@ do_paint_content (MetaShapedTexture *stex,
g_clear_pointer (&blended_tex_region, cairo_region_destroy);
}
+static void
+ensure_mipmap_texture (MetaShapedTexture *stex)
+{
+ CoglContext *ctx =
+ clutter_backend_get_cogl_context (clutter_get_default_backend ());
+ int width, height;
+
+ /* Let's avoid spending any texture memory copying the base level texture
+ * because we'll never need that one and it would have used most of the
+ * memory;
+ * S(0) = W x H
+ * S(n) = S(n-1) / 4
+ * sum to infinity of S(n) = 4/3 * S(0)
+ * So subtracting S(0) means even infinite mipmap levels only need one third
+ * of the original texture's memory. Finite levels need less.
+ *
+ * The fact that mipmap level 0 of stex->mipmap_texture is half the
+ * resolution of stex->texture makes no visual difference, so long as you're
+ * never trying to view a level of detail higher than half. If you need that
+ * then just use stex->texture instead of stex->mipmap_texture, which is
+ * faster anyway.
+ */
+ width = cogl_texture_get_width (stex->texture) / 2;
+ height = cogl_texture_get_height (stex->texture) / 2;
+
+ if (!width || !height)
+ {
+ free_mipmaps (stex);
+ return;
+ }
+
+ if (!stex->mipmap_texture ||
+ cogl_texture_get_width (stex->mipmap_texture) != width ||
+ cogl_texture_get_height (stex->mipmap_texture) != height)
+ {
+ CoglOffscreen *offscreen;
+ CoglTexture2D *tex2d;
+
+ free_mipmaps (stex);
+
+ tex2d = cogl_texture_2d_new_with_size (ctx, width, height);
+ if (!tex2d)
+ return;
+
+ stex->mipmap_texture = COGL_TEXTURE (tex2d);
+
+ offscreen = cogl_offscreen_new_with_texture (stex->mipmap_texture);
+ if (!offscreen)
+ {
+ free_mipmaps (stex);
+ return;
+ }
+
+ stex->mipmap_fb = COGL_FRAMEBUFFER (offscreen);
+
+ if (!cogl_framebuffer_allocate (stex->mipmap_fb, NULL))
+ {
+ free_mipmaps (stex);
+ return;
+ }
+
+ cogl_framebuffer_orthographic (stex->mipmap_fb,
+ 0, 0, width, height, -1.0, 1.0);
+
+ stex->mipmap_texture_out_of_date = TRUE;
+ }
+
+ if (stex->mipmap_texture_out_of_date)
+ {
+ if (!stex->mipmap_pipeline)
+ {
+ stex->mipmap_pipeline = cogl_pipeline_new (ctx);
+ cogl_pipeline_set_blend (stex->mipmap_pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL);
+ cogl_pipeline_set_layer_filters (stex->mipmap_pipeline, 0,
+ COGL_PIPELINE_FILTER_LINEAR,
+ COGL_PIPELINE_FILTER_LINEAR);
+ }
+
+ cogl_pipeline_set_layer_texture (stex->mipmap_pipeline, 0, stex->texture);
+ cogl_framebuffer_draw_textured_rectangle (stex->mipmap_fb,
+ stex->mipmap_pipeline,
+ 0, 0, width, height,
+ 0.0, 0.0, 1.0, 1.0);
+
+ stex->mipmap_texture_out_of_date = FALSE;
+ }
+}
+
static CoglTexture *
select_texture_for_paint (MetaShapedTexture *stex,
ClutterPaintContext *paint_context)
@@ -913,8 +1029,8 @@ select_texture_for_paint (MetaShapedTexture *stex,
if (age >= MIN_MIPMAP_AGE_USEC ||
stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
{
- texture = meta_texture_tower_get_paint_texture (stex->paint_tower,
- paint_context);
+ ensure_mipmap_texture (stex);
+ texture = stex->mipmap_texture;
}
}
@@ -946,7 +1062,6 @@ meta_shaped_texture_paint_content (ClutterContent *content,
{
MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
ClutterActorBox alloc;
- CoglTexture *paint_tex = NULL;
uint8_t opacity;
if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
@@ -967,14 +1082,13 @@ meta_shaped_texture_paint_content (ClutterContent *content,
* Setting the texture quality to high without SGIS_generate_mipmap
* support for TFP textures will result in fallbacks to XGetImage.
*/
- paint_tex = select_texture_for_paint (stex, paint_context);
- if (!paint_tex)
+ if (stex->texture == NULL)
return;
opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_content_box (actor, &alloc);
- do_paint_content (stex, root_node, paint_context, paint_tex, &alloc, opacity);
+ do_paint_content (stex, root_node, paint_context, &alloc, opacity);
}
static gboolean
@@ -1012,10 +1126,10 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
if (create_mipmaps != stex->create_mipmaps)
{
- CoglTexture *base_texture;
stex->create_mipmaps = create_mipmaps;
- base_texture = create_mipmaps ? stex->texture : NULL;
- meta_texture_tower_set_base_texture (stex->paint_tower, base_texture);
+
+ if (!stex->create_mipmaps)
+ free_mipmaps (stex);
}
}
@@ -1144,12 +1258,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
clip);
}
- meta_texture_tower_update_area (stex->paint_tower,
- x,
- y,
- width,
- height);
-
+ stex->mipmap_texture_out_of_date = TRUE;
stex->prev_invalidation = stex->last_invalidation;
stex->last_invalidation = g_get_monotonic_time ();
@@ -1214,8 +1323,6 @@ meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
g_clear_pointer (&stex->snippet, cogl_object_unref);
if (snippet)
stex->snippet = cogl_object_ref (snippet);
-
- meta_texture_tower_set_snippet (stex->paint_tower, snippet);
}
/**
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index c2bf6696a2092882215da37ef865ddaeb79bf5e4..fcd94b86d3a3e3e0df6923095196a9ee3c4a5e6c 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -331,7 +331,7 @@ meta_surface_actor_is_untransformed (MetaCullable *cullable)
return meta_actor_vertices_are_untransformed (verts,
width * geometry_scale,
height * geometry_scale,
- NULL, NULL);
+ NULL);
}
static void
diff --git a/src/compositor/meta-texture-tower.c b/src/compositor/meta-texture-tower.c
deleted file mode 100644
index 510e85f7968eb09edaace5479a0ac9d43f4d9728..0000000000000000000000000000000000000000
--- a/src/compositor/meta-texture-tower.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * MetaTextureTower
- *
- * Mipmap emulation by creation of scaled down images
- *
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <string.h>
-
-#include "compositor/meta-texture-tower.h"
-
-#ifndef M_LOG2E
-#define M_LOG2E 1.4426950408889634074
-#endif
-
-#define MAX_TEXTURE_LEVELS 12
-
-/* If the texture format in memory doesn't match this, then Mesa
- * will do the conversion, so things will still work, but it might
- * be slow depending on how efficient Mesa is. These should be the
- * native formats unless the display is 16bpp. If conversions
- * here are a bottleneck, investigate whether we are converting when
- * storing window data *into* the texture before adding extra code
- * to handle multiple texture formats.
- */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
-#else
-#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
-#endif
-
-typedef struct
-{
- guint16 x1;
- guint16 y1;
- guint16 x2;
- guint16 y2;
-} Box;
-
-struct _MetaTextureTower
-{
- int n_levels;
- CoglTexture *textures[MAX_TEXTURE_LEVELS];
- CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
- Box invalid[MAX_TEXTURE_LEVELS];
- CoglPipeline *pipeline_template;
- CoglSnippet *snippet;
-};
-
-/**
- * meta_texture_tower_new:
- *
- * Creates a new texture tower. The base texture has to be set with
- * meta_texture_tower_set_base_texture() before use.
- *
- * Return value: the new texture tower. Free with meta_texture_tower_free()
- */
-MetaTextureTower *
-meta_texture_tower_new (void)
-{
- MetaTextureTower *tower;
-
- tower = g_new0 (MetaTextureTower, 1);
-
- return tower;
-}
-
-/**
- * meta_texture_tower_free:
- * @tower: a #MetaTextureTower
- *
- * Frees a texture tower created with meta_texture_tower_new().
- */
-void
-meta_texture_tower_free (MetaTextureTower *tower)
-{
- g_return_if_fail (tower != NULL);
-
- if (tower->pipeline_template != NULL)
- cogl_object_unref (tower->pipeline_template);
-
- meta_texture_tower_set_base_texture (tower, NULL);
- cogl_clear_object (&tower->snippet);
-
- g_free (tower);
-}
-
-/**
- * meta_texture_tower_set_base_texture:
- * @tower: a #MetaTextureTower
- * @texture: the new texture used as a base for scaled down versions
- *
- * Sets the base texture that is the scaled texture that the
- * scaled textures of the tower are derived from. The texture itself
- * will be used as level 0 of the tower and will be referenced until
- * unset or until the tower is freed.
- */
-void
-meta_texture_tower_set_base_texture (MetaTextureTower *tower,
- CoglTexture *texture)
-{
- int i;
-
- g_return_if_fail (tower != NULL);
-
- if (texture == tower->textures[0])
- return;
-
- if (tower->textures[0] != NULL)
- {
- for (i = 1; i < tower->n_levels; i++)
- {
- cogl_clear_object (&tower->textures[i]);
- g_clear_object (&tower->fbos[i]);
- }
-
- cogl_object_unref (tower->textures[0]);
- }
-
- tower->textures[0] = texture;
-
- if (tower->textures[0] != NULL)
- {
- int width, height;
-
- cogl_object_ref (tower->textures[0]);
-
- width = cogl_texture_get_width (tower->textures[0]);
- height = cogl_texture_get_height (tower->textures[0]);
-
- tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
- tower->n_levels = MIN (tower->n_levels, MAX_TEXTURE_LEVELS);
-
- meta_texture_tower_update_area (tower, 0, 0, width, height);
- }
- else
- {
- tower->n_levels = 0;
- }
-}
-
-/**
- * meta_texture_tower_update_area:
- * @tower: a #MetaTextureTower
- * @x: X coordinate of upper left of rectangle that changed
- * @y: Y coordinate of upper left of rectangle that changed
- * @width: width of rectangle that changed
- * @height: height rectangle that changed
- *
- * Mark a region of the base texture as having changed; the next
- * time a scaled down version of the base texture is retrieved,
- * the appropriate area of the scaled down texture will be updated.
- */
-void
-meta_texture_tower_update_area (MetaTextureTower *tower,
- int x,
- int y,
- int width,
- int height)
-{
- int texture_width, texture_height;
- Box invalid;
- int i;
-
- g_return_if_fail (tower != NULL);
-
- if (tower->textures[0] == NULL)
- return;
-
- texture_width = cogl_texture_get_width (tower->textures[0]);
- texture_height = cogl_texture_get_height (tower->textures[0]);
-
- invalid.x1 = x;
- invalid.y1 = y;
- invalid.x2 = x + width;
- invalid.y2 = y + height;
-
- for (i = 1; i < tower->n_levels; i++)
- {
- texture_width = MAX (1, texture_width / 2);
- texture_height = MAX (1, texture_height / 2);
-
- invalid.x1 = invalid.x1 / 2;
- invalid.y1 = invalid.y1 / 2;
- invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
- invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
-
- if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
- tower->invalid[i].y1 == tower->invalid[i].y2)
- {
- tower->invalid[i] = invalid;
- }
- else
- {
- tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
- tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
- tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
- tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
- }
- }
-}
-
-void
-meta_texture_tower_set_snippet (MetaTextureTower *tower,
- CoglSnippet *snippet)
-{
- int i;
-
- if (tower->snippet == snippet)
- return;
-
- g_clear_pointer (&tower->snippet, cogl_object_unref);
-
- if (snippet)
- tower->snippet = cogl_object_ref (snippet);
-
- for (i = 1; i < tower->n_levels; i++)
- {
- cogl_clear_object (&tower->textures[i]);
- g_clear_object (&tower->fbos[i]);
- }
- cogl_clear_object (&tower->pipeline_template);
-}
-
-/* It generally looks worse if we scale up a window texture by even a
- * small amount than if we scale it down using bilinear filtering, so
- * we always pick the *larger* adjacent level. */
-#define LOD_BIAS (-0.49)
-
-/* This determines the appropriate level of detail to use when drawing the
- * texture, in a way that corresponds to what the GL specification does
- * when mip-mapping. This is probably fancier and slower than what we need,
- * but we do the computation only once each time we paint a window, and
- * its easier to just use the equations from the specification than to
- * come up with something simpler.
- *
- * If window is being painted at an angle from the viewer, then we have to
- * pick a point in the texture; we use the middle of the texture (which is
- * why the width/height are passed in.) This is not the normal case for
- * Meta.
- */
-static int
-get_paint_level (ClutterPaintContext *paint_context,
- int width,
- int height)
-{
- CoglFramebuffer *framebuffer;
- graphene_matrix_t projection, modelview, pm;
- float xx, xy, xw;
- float yx, yy, yw;
- float wx, wy, ww;
- float v[4];
- double viewport_width, viewport_height;
- double u0, v0;
- double xc, yc, wc;
- double dxdu_, dxdv_, dydu_, dydv_;
- double det_, det_sq;
- double rho_sq;
- double lambda;
-
- /* See
- * http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
- * Section 3.8.9, p. 1.6.2. Here we have
- *
- * u(x,y) = x_o;
- * v(x,y) = y_o;
- *
- * Since we are mapping 1:1 from object coordinates into pixel
- * texture coordinates, the clip coordinates are:
- *
- * (x_c) (x_o) (u)
- * (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
- * (z_c) (z_o) (0)
- * (w_c) (w_o) (1)
- */
-
- framebuffer = clutter_paint_context_get_framebuffer (paint_context);
- cogl_framebuffer_get_projection_matrix (framebuffer, &projection);
- cogl_framebuffer_get_modelview_matrix (framebuffer, &modelview);
-
- graphene_matrix_multiply (&modelview, &projection, &pm);
-
- xx = graphene_matrix_get_value (&pm, 0, 0);
- xy = graphene_matrix_get_value (&pm, 0, 1);
- xw = graphene_matrix_get_value (&pm, 0, 3);
- yx = graphene_matrix_get_value (&pm, 1, 0);
- yy = graphene_matrix_get_value (&pm, 1, 1);
- yw = graphene_matrix_get_value (&pm, 1, 3);
- wx = graphene_matrix_get_value (&pm, 3, 0);
- wy = graphene_matrix_get_value (&pm, 3, 1);
- ww = graphene_matrix_get_value (&pm, 3, 3);
-
- cogl_framebuffer_get_viewport4fv (framebuffer, v);
- viewport_width = v[2];
- viewport_height = v[3];
-
- u0 = width / 2.;
- v0 = height / 2.;
-
- xc = xx * u0 + yx * v0 + wx;
- yc = xy * u0 + yy * v0 + wy;
- wc = xw * u0 + yw * v0 + ww;
-
- /* We'll simplify the equations below for a bit of micro-optimization.
- * The commented out code is the unsimplified version.
-
- // Partial derivates of window coordinates:
- //
- // x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
- // y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
- //
- // with respect to u, v, using
- // d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
-
- dxdu = 0.5 * viewport_width * (xx - xw * (xc/wc)) / wc;
- dxdv = 0.5 * viewport_width * (yx - yw * (xc/wc)) / wc;
- dydu = 0.5 * viewport_height * (xy - xw * (yc/wc)) / wc;
- dydv = 0.5 * viewport_height * (yy - yw * (yc/wc)) / wc;
-
- // Compute the inverse partials as the matrix inverse
- det = dxdu * dydv - dxdv * dydu;
-
- dudx = dydv / det;
- dudy = - dxdv / det;
- dvdx = - dydu / det;
- dvdy = dvdu / det;
-
- // Scale factor; maximum of the distance in texels for a change of 1 pixel
- // in the X direction or 1 pixel in the Y direction
- rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
-
- // Level of detail
- lambda = log2 (rho) + LOD_BIAS;
- */
-
- /* dxdu * wc, etc */
- dxdu_ = 0.5 * viewport_width * (xx - xw * (xc/wc));
- dxdv_ = 0.5 * viewport_width * (yx - yw * (xc/wc));
- dydu_ = 0.5 * viewport_height * (xy - xw * (yc/wc));
- dydv_ = 0.5 * viewport_height * (yy - yw * (yc/wc));
-
- /* det * wc^2 */
- det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
- det_sq = det_ * det_;
- if (det_sq == 0.0)
- return -1;
-
- /* (rho * det * wc)^2 */
- rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
- lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
-
-#if 0
- g_print ("%g %g %g\n", 0.5 * viewport_width * xx / ww, 0.5 * viewport_height * yy / ww, lambda);
-#endif
-
- if (lambda <= 0.)
- return 0;
- else
- return (int)(0.5 + lambda);
-}
-
-static void
-texture_tower_create_texture (MetaTextureTower *tower,
- int level,
- int width,
- int height)
-{
- CoglContext *ctx =
- clutter_backend_get_cogl_context (clutter_get_default_backend ());
-
- tower->textures[level] =
- COGL_TEXTURE (cogl_texture_2d_new_with_size (ctx, width, height));
-
- tower->invalid[level].x1 = 0;
- tower->invalid[level].y1 = 0;
- tower->invalid[level].x2 = width;
- tower->invalid[level].y2 = height;
-}
-
-static void
-texture_tower_revalidate (MetaTextureTower *tower,
- int level)
-{
- CoglTexture *source_texture = tower->textures[level - 1];
- int source_texture_width = cogl_texture_get_width (source_texture);
- int source_texture_height = cogl_texture_get_height (source_texture);
- CoglTexture *dest_texture = tower->textures[level];
- int dest_texture_width = cogl_texture_get_width (dest_texture);
- int dest_texture_height = cogl_texture_get_height (dest_texture);
- Box *invalid = &tower->invalid[level];
- CoglFramebuffer *fb;
- GError *catch_error = NULL;
- CoglPipeline *pipeline;
-
- if (tower->fbos[level] == NULL)
- tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
-
- fb = COGL_FRAMEBUFFER (tower->fbos[level]);
-
- if (!cogl_framebuffer_allocate (fb, &catch_error))
- {
- g_error_free (catch_error);
- return;
- }
-
- cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
-
- if (!tower->pipeline_template)
- {
- CoglContext *ctx =
- clutter_backend_get_cogl_context (clutter_get_default_backend ());
- tower->pipeline_template = cogl_pipeline_new (ctx);
- cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
- }
-
- pipeline = cogl_pipeline_copy (tower->pipeline_template);
- cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
-
- if (tower->snippet && level == 1)
- cogl_pipeline_add_layer_snippet (pipeline, 0, tower->snippet);
-
- cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
- invalid->x1, invalid->y1,
- invalid->x2, invalid->y2,
- (2. * invalid->x1) / source_texture_width,
- (2. * invalid->y1) / source_texture_height,
- (2. * invalid->x2) / source_texture_width,
- (2. * invalid->y2) / source_texture_height);
-
- cogl_object_unref (pipeline);
-
- tower->invalid[level].x1 = tower->invalid[level].x2 = 0;
- tower->invalid[level].y1 = tower->invalid[level].y2 = 0;
-}
-
-/**
- * meta_texture_tower_get_paint_texture:
- * @tower: a #MetaTextureTower
- * @paint_context: a #ClutterPaintContext
- *
- * Gets the texture from the tower that best matches the current
- * rendering scale. (On the assumption here the texture is going to
- * be rendered with vertex coordinates that correspond to its
- * size in pixels, so a 200x200 texture will be rendered on the
- * rectangle (0, 0, 200, 200).
- *
- * Return value: the COGL texture handle to use for painting, or
- * %NULL if no base texture has yet been set.
- */
-CoglTexture *
-meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
- ClutterPaintContext *paint_context)
-{
- int texture_width, texture_height;
- int level;
-
- g_return_val_if_fail (tower != NULL, NULL);
-
- if (tower->textures[0] == NULL)
- return NULL;
-
- texture_width = cogl_texture_get_width (tower->textures[0]);
- texture_height = cogl_texture_get_height (tower->textures[0]);
-
- level = get_paint_level (paint_context, texture_width, texture_height);
- if (level < 0) /* singular paint matrix, scaled to nothing */
- return NULL;
- level = MIN (level, tower->n_levels - 1);
-
- if (tower->textures[level] == NULL ||
- (tower->invalid[level].x2 != tower->invalid[level].x1 &&
- tower->invalid[level].y2 != tower->invalid[level].y1))
- {
- int i;
-
- for (i = 1; i <= level; i++)
- {
- /* Use "floor" convention here to be consistent with the NPOT texture extension */
- texture_width = MAX (1, texture_width / 2);
- texture_height = MAX (1, texture_height / 2);
-
- if (tower->textures[i] == NULL)
- texture_tower_create_texture (tower, i, texture_width, texture_height);
- }
-
- for (i = 1; i <= level; i++)
- {
- if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
- tower->invalid[level].y2 != tower->invalid[level].y1)
- texture_tower_revalidate (tower, i);
- }
- }
-
- return tower->textures[level];
-}
diff --git a/src/compositor/meta-texture-tower.h b/src/compositor/meta-texture-tower.h
deleted file mode 100644
index 5522dfbb16ac9b207e979065413ac3c06f1ac974..0000000000000000000000000000000000000000
--- a/src/compositor/meta-texture-tower.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/*
- * MetaTextureTower
- *
- * Mipmap emulation by creation of scaled down images
- *
- * Copyright (C) 2009 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __META_TEXTURE_TOWER_H__
-#define __META_TEXTURE_TOWER_H__
-
-#include "clutter/clutter.h"
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:MetaTextureTower
- * @short_description: mipmap emulation by creation of scaled down images
- *
- * A #MetaTextureTower is used to get good looking scaled down images when
- * we can't use the GL drivers mipmap support. There are two separate reasons
- *
- * - Some cards (including radeon cards <= r5xx) only support
- * TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
- * are defined not to support mipmapping.
- * - Even when NPOT textures are available, the combination of NPOT
- * textures, texture_from_pixmap, and mipmapping doesn't typically
- * work, since the X server doesn't allocate pixmaps in the right
- * layout for mipmapping.
- *
- * So, what we do is create the "mipmap" levels ourselves by successive
- * power-of-two scaledowns, and when rendering pick the single texture
- * that best matches the scale we are rendering at. (Since we aren't
- * typically using perspective transforms, we'll frequently have a single
- * scale for the entire texture.)
- */
-
-typedef struct _MetaTextureTower MetaTextureTower;
-
-MetaTextureTower *meta_texture_tower_new (void);
-void meta_texture_tower_free (MetaTextureTower *tower);
-void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
- CoglTexture *texture);
-void meta_texture_tower_update_area (MetaTextureTower *tower,
- int x,
- int y,
- int width,
- int height);
-CoglTexture *meta_texture_tower_get_paint_texture (MetaTextureTower *tower,
- ClutterPaintContext *paint_context);
-
-void meta_texture_tower_set_snippet (MetaTextureTower *tower,
- CoglSnippet *snippet);
-
-G_END_DECLS
-
-#endif /* __META_TEXTURE_TOWER_H__ */
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index 16ff2db097e17210d319d1dadcf00a6a55ef3cc1..c6af609aea50f38b444f8e0436fa1008322fadce 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -92,6 +92,7 @@ meta_window_group_paint (ClutterActor *actor,
{
CoglFramebuffer *fb;
ClutterStageView *view;
+ MetaTransforms trans;
fb = clutter_paint_context_get_framebuffer (paint_context);
view = clutter_paint_context_get_stage_view (paint_context);
@@ -102,13 +103,15 @@ meta_window_group_paint (ClutterActor *actor,
screen_height,
screen_width,
screen_height,
- &paint_x_origin,
- &paint_y_origin) ||
+ &trans) ||
!meta_cullable_is_untransformed (META_CULLABLE (actor)))
{
parent_actor_class->paint (actor, paint_context);
return;
}
+
+ paint_x_origin = trans.x_origin;
+ paint_y_origin = trans.y_origin;
}
else
{
diff --git a/src/meson.build b/src/meson.build
index 7b456f524fb5e16904b6f2c27b7e88a8ec7b0506..4ebe351b04145dfa590d4b0e8b52e5ceedb05361 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -345,8 +345,6 @@ mutter_sources = [
'compositor/meta-surface-actor-x11.h',
'compositor/meta-sync-ring.c',
'compositor/meta-sync-ring.h',
- 'compositor/meta-texture-tower.c',
- 'compositor/meta-texture-tower.h',
'compositor/meta-window-actor.c',
'compositor/meta-window-actor-private.h',
'compositor/meta-window-actor-x11.c',