clutter/offscreen-effect: Support adding effect to resource scaled actors
At this level we use ceiled resource-scale when painting fractional value When using fractional scaling we still need to create an integer-sized texture and then we should paint it using a size which is proportional to the real actor size ratio, and only paint a subsample of it, but this doesn't seem to work properly with some weird scaling values. Then, it's just better to draw the texture ceiled and then we scale it down to match the proper actor scaling at paint level. https://bugzilla.gnome.org/show_bug.cgi?id=765011 https://gitlab.gnome.org/GNOME/mutter/merge_requests/3
This commit is contained in:
parent
af3662775e
commit
e3966882e8
@ -66,6 +66,8 @@
|
|||||||
|
|
||||||
#include "clutter-offscreen-effect.h"
|
#include "clutter-offscreen-effect.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
|
||||||
#include "clutter-actor-private.h"
|
#include "clutter-actor-private.h"
|
||||||
@ -93,8 +95,8 @@ struct _ClutterOffscreenEffectPrivate
|
|||||||
through create_texture(). This needs to be tracked separately so
|
through create_texture(). This needs to be tracked separately so
|
||||||
that we can detect when a different size is calculated and
|
that we can detect when a different size is calculated and
|
||||||
regenerate the fbo */
|
regenerate the fbo */
|
||||||
int fbo_width;
|
int target_width;
|
||||||
int fbo_height;
|
int target_height;
|
||||||
|
|
||||||
gint old_opacity_override;
|
gint old_opacity_override;
|
||||||
};
|
};
|
||||||
@ -136,7 +138,10 @@ clutter_offscreen_effect_real_create_texture (ClutterOffscreenEffect *effect,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
update_fbo (ClutterEffect *effect,
|
||||||
|
int target_width,
|
||||||
|
int target_height,
|
||||||
|
float resource_scale)
|
||||||
{
|
{
|
||||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (effect);
|
||||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||||
@ -151,8 +156,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->fbo_width == fbo_width &&
|
if (priv->target_width == target_width &&
|
||||||
priv->fbo_height == fbo_height &&
|
priv->target_height == target_height &&
|
||||||
priv->offscreen != NULL)
|
priv->offscreen != NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -163,6 +168,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
|
|
||||||
priv->target = cogl_pipeline_new (ctx);
|
priv->target = cogl_pipeline_new (ctx);
|
||||||
|
|
||||||
|
if (fmodf (resource_scale, 1.0f) == 0)
|
||||||
|
{
|
||||||
/* We're always going to render the texture at a 1:1 texel:pixel
|
/* We're always going to render the texture at a 1:1 texel:pixel
|
||||||
ratio so we can use 'nearest' filtering to decrease the
|
ratio so we can use 'nearest' filtering to decrease the
|
||||||
effects of rounding errors in the geometry calculation */
|
effects of rounding errors in the geometry calculation */
|
||||||
@ -171,6 +178,7 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
COGL_PIPELINE_FILTER_NEAREST,
|
COGL_PIPELINE_FILTER_NEAREST,
|
||||||
COGL_PIPELINE_FILTER_NEAREST);
|
COGL_PIPELINE_FILTER_NEAREST);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (priv->texture != NULL)
|
if (priv->texture != NULL)
|
||||||
{
|
{
|
||||||
@ -185,14 +193,14 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->texture =
|
priv->texture =
|
||||||
clutter_offscreen_effect_create_texture (self, fbo_width, fbo_height);
|
clutter_offscreen_effect_create_texture (self, target_width, target_height);
|
||||||
if (priv->texture == NULL)
|
if (priv->texture == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture);
|
cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture);
|
||||||
|
|
||||||
priv->fbo_width = fbo_width;
|
priv->target_width = target_width;
|
||||||
priv->fbo_height = fbo_height;
|
priv->target_height = target_height;
|
||||||
|
|
||||||
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
|
priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
|
||||||
if (priv->offscreen == NULL)
|
if (priv->offscreen == NULL)
|
||||||
@ -202,8 +210,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
|
|||||||
cogl_handle_unref (priv->target);
|
cogl_handle_unref (priv->target);
|
||||||
priv->target = NULL;
|
priv->target = NULL;
|
||||||
|
|
||||||
priv->fbo_width = 0;
|
priv->target_width = 0;
|
||||||
priv->fbo_height = 0;
|
priv->target_height = 0;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -222,7 +230,9 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
const ClutterPaintVolume *volume;
|
const ClutterPaintVolume *volume;
|
||||||
CoglColor transparent;
|
CoglColor transparent;
|
||||||
gfloat stage_width, stage_height;
|
gfloat stage_width, stage_height;
|
||||||
gfloat fbo_width = -1, fbo_height = -1;
|
gfloat target_width = -1, target_height = -1;
|
||||||
|
gfloat resource_scale;
|
||||||
|
gfloat ceiled_resource_scale;
|
||||||
ClutterVertex local_offset = { 0.f, 0.f, 0.f };
|
ClutterVertex local_offset = { 0.f, 0.f, 0.f };
|
||||||
gfloat old_viewport[4];
|
gfloat old_viewport[4];
|
||||||
|
|
||||||
@ -235,6 +245,18 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
stage = _clutter_actor_get_stage_internal (priv->actor);
|
stage = _clutter_actor_get_stage_internal (priv->actor);
|
||||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||||
|
|
||||||
|
if (_clutter_actor_get_real_resource_scale (priv->actor, &resource_scale))
|
||||||
|
{
|
||||||
|
ceiled_resource_scale = ceilf (resource_scale);
|
||||||
|
stage_width *= ceiled_resource_scale;
|
||||||
|
stage_height *= ceiled_resource_scale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We are sure we have a resource scale set to a good value at paint */
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the minimal bounding box for what we want to paint, relative to the
|
/* Get the minimal bounding box for what we want to paint, relative to the
|
||||||
* parent of priv->actor. Note that we may actually be painting a clone of
|
* parent of priv->actor. Note that we may actually be painting a clone of
|
||||||
* priv->actor so we need to be careful to avoid querying the transformation
|
* priv->actor so we need to be careful to avoid querying the transformation
|
||||||
@ -261,10 +283,14 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
|
|||||||
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
priv->fbo_offset_x = box.x1 - raw_box.x1;
|
||||||
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
priv->fbo_offset_y = box.y1 - raw_box.y1;
|
||||||
|
|
||||||
clutter_actor_box_get_size (&box, &fbo_width, &fbo_height);
|
clutter_actor_box_scale (&box, ceiled_resource_scale);
|
||||||
|
clutter_actor_box_get_size (&box, &target_width, &target_height);
|
||||||
|
|
||||||
|
target_width = ceilf (target_width);
|
||||||
|
target_height = ceilf (target_height);
|
||||||
|
|
||||||
/* First assert that the framebuffer is the right size... */
|
/* First assert that the framebuffer is the right size... */
|
||||||
if (!update_fbo (effect, fbo_width, fbo_height))
|
if (!update_fbo (effect, target_width, target_height, resource_scale))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
cogl_get_modelview_matrix (&old_modelview);
|
cogl_get_modelview_matrix (&old_modelview);
|
||||||
@ -366,6 +392,7 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
|
|||||||
{
|
{
|
||||||
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
ClutterOffscreenEffectPrivate *priv = effect->priv;
|
||||||
CoglMatrix modelview;
|
CoglMatrix modelview;
|
||||||
|
float resource_scale;
|
||||||
|
|
||||||
cogl_push_matrix ();
|
cogl_push_matrix ();
|
||||||
|
|
||||||
@ -373,6 +400,14 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
|
|||||||
* missing a correction for the expanded FBO and offset rendering within...
|
* missing a correction for the expanded FBO and offset rendering within...
|
||||||
*/
|
*/
|
||||||
cogl_get_modelview_matrix (&modelview);
|
cogl_get_modelview_matrix (&modelview);
|
||||||
|
|
||||||
|
if (clutter_actor_get_resource_scale (priv->actor, &resource_scale) &&
|
||||||
|
resource_scale != 1.0f)
|
||||||
|
{
|
||||||
|
float paint_scale = 1.0f / resource_scale;
|
||||||
|
cogl_matrix_scale (&modelview, paint_scale, paint_scale, 1);
|
||||||
|
}
|
||||||
|
|
||||||
cogl_matrix_translate (&modelview,
|
cogl_matrix_translate (&modelview,
|
||||||
priv->fbo_offset_x,
|
priv->fbo_offset_x,
|
||||||
priv->fbo_offset_y,
|
priv->fbo_offset_y,
|
||||||
|
Loading…
Reference in New Issue
Block a user