shaped-texture: Fix use-nearest check when viewports are scaled

We checked that the content size was appropriately painted in the stage,
but didn't take into account that the size of the sampled texture
region, meaning that when stage views were scaled, we'd think that we
would draw a texture scaled, as e.g. a 200x200 sized texture with buffer
scale 2 would have the size 100x100. When stage views were not scaled,
we'd apply a geometry scale meaning it'd end up as 200x200 anyway, thus
pass the check, but when stage views are scaled, it'd still be painted
as a 100x100 shaped texture on the stage, thus failing the
are-we-unscaled test.

Fix this by comparing the transformed paint size with the sampled size,
instead of the paint size again, when checking whether we are being
painted scaled or not. For example, when stage views are scaled, our
200x200 buffer with buffer scale 2, thus content size 100x100 will
transform to a 200x200 paint command, thus passing the test. For
non-scaled stage views, our 200x200 buffer with buffer scale 2 thus
content size 100x100 will also transform into a 200x200 paint command,
and will also pass the check, as the texture sample region is still
200x200.

Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/804

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1124
This commit is contained in:
Jonas Ådahl 2020-03-13 19:31:23 +01:00
parent 62d0dd907b
commit 8beef8ccd0
5 changed files with 42 additions and 3 deletions

View File

@ -115,6 +115,8 @@ meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
* meta_actor_painting_untransformed: * meta_actor_painting_untransformed:
* @paint_width: the width of the painted area * @paint_width: the width of the painted area
* @paint_height: the height of the painted area * @paint_height: the height of the painted area
* @sample_width: the width of the sampled area of the texture
* @sample_height: the height of the sampled area of the texture
* @x_origin: if the transform is only an integer translation * @x_origin: if the transform is only an integer translation
* then the X coordinate of the location of the origin under the transformation * then the X coordinate of the location of the origin under the transformation
* from drawing space to screen pixel space is returned here. * from drawing space to screen pixel space is returned here.
@ -133,6 +135,8 @@ gboolean
meta_actor_painting_untransformed (CoglFramebuffer *fb, meta_actor_painting_untransformed (CoglFramebuffer *fb,
int paint_width, int paint_width,
int paint_height, int paint_height,
int sample_width,
int sample_height,
int *x_origin, int *x_origin,
int *y_origin) int *y_origin)
{ {
@ -177,6 +181,8 @@ meta_actor_painting_untransformed (CoglFramebuffer *fb,
viewport[3], viewport[1]); viewport[3], viewport[1]);
} }
return meta_actor_vertices_are_untransformed (vertices, paint_width, paint_height, x_origin, y_origin); return meta_actor_vertices_are_untransformed (vertices,
sample_width, sample_height,
x_origin, y_origin);
} }

View File

@ -32,6 +32,8 @@ gboolean meta_actor_vertices_are_untransformed (graphene_point3d_t *verts,
gboolean meta_actor_painting_untransformed (CoglFramebuffer *fb, gboolean meta_actor_painting_untransformed (CoglFramebuffer *fb,
int paint_width, int paint_width,
int paint_height, int paint_height,
int sample_widthf,
int sample_heightf,
int *x_origin, int *x_origin,
int *y_origin); int *y_origin);

View File

@ -450,6 +450,8 @@ setup_pipeline (MetaBackgroundActor *self,
fb = clutter_paint_context_get_framebuffer (paint_context); fb = clutter_paint_context_get_framebuffer (paint_context);
if (!self->force_bilinear && if (!self->force_bilinear &&
meta_actor_painting_untransformed (fb, meta_actor_painting_untransformed (fb,
actor_pixel_rect->width,
actor_pixel_rect->height,
actor_pixel_rect->width, actor_pixel_rect->width,
actor_pixel_rect->height, actor_pixel_rect->height,
NULL, NULL)) NULL, NULL))

View File

@ -507,6 +507,17 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
return G_SOURCE_REMOVE; return G_SOURCE_REMOVE;
} }
static inline void
flip_ints (int *x,
int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
static void static void
do_paint_content (MetaShapedTexture *stex, do_paint_content (MetaShapedTexture *stex,
ClutterPaintNode *root_node, ClutterPaintNode *root_node,
@ -522,6 +533,7 @@ do_paint_content (MetaShapedTexture *stex,
CoglContext *ctx; CoglContext *ctx;
CoglPipelineFilter filter; CoglPipelineFilter filter;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
int sample_width, sample_height;
ensure_size_valid (stex); ensure_size_valid (stex);
@ -542,15 +554,30 @@ do_paint_content (MetaShapedTexture *stex,
* improves performance, especially with software rendering. * improves performance, especially with software rendering.
*/ */
filter = COGL_PIPELINE_FILTER_LINEAR;
framebuffer = clutter_paint_node_get_framebuffer (root_node); framebuffer = clutter_paint_node_get_framebuffer (root_node);
if (!framebuffer) if (!framebuffer)
framebuffer = clutter_paint_context_get_framebuffer (paint_context); framebuffer = clutter_paint_context_get_framebuffer (paint_context);
if (stex->has_viewport_src_rect)
{
sample_width = stex->viewport_src_rect.size.width * stex->buffer_scale;
sample_height = stex->viewport_src_rect.size.height * stex->buffer_scale;
}
else
{
sample_width = cogl_texture_get_width (stex->texture);
sample_height = cogl_texture_get_height (stex->texture);
}
if (meta_monitor_transform_is_rotated (stex->transform))
flip_ints (&sample_width, &sample_height);
if (meta_actor_painting_untransformed (framebuffer, if (meta_actor_painting_untransformed (framebuffer,
dst_width, dst_height, dst_width, dst_height,
sample_width, sample_height,
NULL, NULL)) NULL, NULL))
filter = COGL_PIPELINE_FILTER_NEAREST; filter = COGL_PIPELINE_FILTER_NEAREST;
else
filter = COGL_PIPELINE_FILTER_LINEAR;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());

View File

@ -94,6 +94,8 @@ meta_window_group_paint (ClutterActor *actor,
fb = clutter_paint_context_get_framebuffer (paint_context); fb = clutter_paint_context_get_framebuffer (paint_context);
if (!meta_actor_painting_untransformed (fb, if (!meta_actor_painting_untransformed (fb,
screen_width,
screen_height,
screen_width, screen_width,
screen_height, screen_height,
&paint_x_origin, &paint_x_origin,