[mutter] clutter/offscreen-effect: Support adding effect to resource scaled actors



commit e3966882e8a125d66b0222601922f5c0a77c792c
Author: Marco Trevisan (Treviño) <mail 3v1n0 net>
Date:   Thu Sep 7 22:59:50 2017 +0200

    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

 clutter/clutter/clutter-offscreen-effect.c | 75 ++++++++++++++++++++++--------
 1 file changed, 55 insertions(+), 20 deletions(-)
---
diff --git a/clutter/clutter/clutter-offscreen-effect.c b/clutter/clutter/clutter-offscreen-effect.c
index 9dae899ed..ad338a935 100644
--- a/clutter/clutter/clutter-offscreen-effect.c
+++ b/clutter/clutter/clutter-offscreen-effect.c
@@ -66,6 +66,8 @@
 
 #include "clutter-offscreen-effect.h"
 
+#include <math.h>
+
 #include "cogl/cogl.h"
 
 #include "clutter-actor-private.h"
@@ -93,8 +95,8 @@ struct _ClutterOffscreenEffectPrivate
      through create_texture(). This needs to be tracked separately so
      that we can detect when a different size is calculated and
      regenerate the fbo */
-  int fbo_width;
-  int fbo_height;
+  int target_width;
+  int target_height;
 
   gint old_opacity_override;
 };
@@ -136,7 +138,10 @@ clutter_offscreen_effect_real_create_texture (ClutterOffscreenEffect *effect,
 }
 
 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);
   ClutterOffscreenEffectPrivate *priv = self->priv;
@@ -151,8 +156,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
       return FALSE;
     }
 
-  if (priv->fbo_width == fbo_width &&
-      priv->fbo_height == fbo_height &&
+  if (priv->target_width == target_width &&
+      priv->target_height == target_height &&
       priv->offscreen != NULL)
     return TRUE;
 
@@ -163,13 +168,16 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
 
       priv->target = cogl_pipeline_new (ctx);
 
-      /* We're always going to render the texture at a 1:1 texel:pixel
-         ratio so we can use 'nearest' filtering to decrease the
-         effects of rounding errors in the geometry calculation */
-      cogl_pipeline_set_layer_filters (priv->target,
-                                       0, /* layer_index */
-                                       COGL_PIPELINE_FILTER_NEAREST,
-                                       COGL_PIPELINE_FILTER_NEAREST);
+      if (fmodf (resource_scale, 1.0f) == 0)
+        {
+          /* We're always going to render the texture at a 1:1 texel:pixel
+            ratio so we can use 'nearest' filtering to decrease the
+            effects of rounding errors in the geometry calculation */
+          cogl_pipeline_set_layer_filters (priv->target,
+                                           0, /* layer_index */
+                                           COGL_PIPELINE_FILTER_NEAREST,
+                                           COGL_PIPELINE_FILTER_NEAREST);
+        }
     }
 
   if (priv->texture != NULL)
@@ -185,14 +193,14 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
     }
 
   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)
     return FALSE;
 
   cogl_pipeline_set_layer_texture (priv->target, 0, priv->texture);
 
-  priv->fbo_width = fbo_width;
-  priv->fbo_height = fbo_height;
+  priv->target_width = target_width;
+  priv->target_height = target_height;
 
   priv->offscreen = cogl_offscreen_new_to_texture (priv->texture);
   if (priv->offscreen == NULL)
@@ -202,8 +210,8 @@ update_fbo (ClutterEffect *effect, int fbo_width, int fbo_height)
       cogl_handle_unref (priv->target);
       priv->target = NULL;
 
-      priv->fbo_width = 0;
-      priv->fbo_height = 0;
+      priv->target_width = 0;
+      priv->target_height = 0;
 
       return FALSE;
     }
@@ -222,7 +230,9 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
   const ClutterPaintVolume *volume;
   CoglColor transparent;
   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 };
   gfloat old_viewport[4];
 
@@ -235,6 +245,18 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
   stage = _clutter_actor_get_stage_internal (priv->actor);
   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
    * 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
@@ -261,10 +283,14 @@ clutter_offscreen_effect_pre_paint (ClutterEffect *effect)
   priv->fbo_offset_x = box.x1 - raw_box.x1;
   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... */
-  if (!update_fbo (effect, fbo_width, fbo_height))
+  if (!update_fbo (effect, target_width, target_height, resource_scale))
     return FALSE;
 
   cogl_get_modelview_matrix (&old_modelview);
@@ -366,6 +392,7 @@ clutter_offscreen_effect_paint_texture (ClutterOffscreenEffect *effect)
 {
   ClutterOffscreenEffectPrivate *priv = effect->priv;
   CoglMatrix modelview;
+  float resource_scale;
 
   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...
    */
   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,
                          priv->fbo_offset_x,
                          priv->fbo_offset_y,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]