Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 74 additions & 93 deletions src/BackgroundBlurEffect.vala
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {

public float blur_radius { get; construct; }
public float clip_radius { get; construct; }
public float monitor_scale { get; construct set; }

public uint left { get; set; default = 0; }
public uint right { get; set; default = 0; }
public uint top { get; set; default = 0; }
public uint bottom { get; set; default = 0; }

private float real_blur_radius;
private float downscale_factor;

private int texture_width;
private int texture_height;

private Cogl.Framebuffer actor_framebuffer;
private Cogl.Pipeline actor_pipeline;
private Cogl.Texture actor_texture;
Expand All @@ -34,8 +35,8 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {

private int frame_counter = 0;

public BackgroundBlurEffect (float blur_radius, float clip_radius, float monitor_scale) {
Object (blur_radius: blur_radius, clip_radius: clip_radius, monitor_scale: monitor_scale);
public BackgroundBlurEffect (float blur_radius, float clip_radius) {
Object (blur_radius: blur_radius, clip_radius: clip_radius);
}

construct {
Expand Down Expand Up @@ -122,64 +123,29 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {

round_clip_radius_location = round_pipeline.get_uniform_location ("clip_radius");
round_actor_size_location = round_pipeline.get_uniform_location ("actor_size");

update_clip_radius ();
update_actor_size ();

notify["monitor-scale"].connect (update_clip_radius);
}

public override void set_actor (Clutter.Actor? new_actor) {
if (actor != null) {
actor.notify["width"].disconnect (update_actor_size);
actor.notify["height"].disconnect (update_actor_size);
}

base.set_actor (new_actor);
private float get_stage_view_scale (Clutter.PaintContext paint_context) {
unowned var stage_view = paint_context.get_stage_view ();

if (actor != null) {
actor.notify["width"].connect (update_actor_size);
actor.notify["height"].connect (update_actor_size);
update_actor_size ();
}
}

private void update_clip_radius () {
float[] _clip_radius = { clip_radius * monitor_scale };
round_pipeline.set_uniform_float (round_clip_radius_location, 1, 1, _clip_radius);
}

private void update_actor_size () {
float[] actor_size = {
actor.width,
actor.height
};

round_pipeline.set_uniform_float (round_actor_size_location, 2, 1, actor_size);
return stage_view != null ? stage_view.scale : 1.0f;
}

private void update_actor_box (Clutter.PaintContext paint_context, ref Clutter.ActorBox source_actor_box) {
float box_scale_factor = 1.0f;
float origin_x, origin_y;
float width, height;

var stage_view = paint_context.get_stage_view ();

float origin_x, origin_y, width, height;
actor.get_transformed_position (out origin_x, out origin_y);
actor.get_transformed_size (out width, out height);

float box_scale_factor = get_stage_view_scale (paint_context);
var stage_view = paint_context.get_stage_view ();

if (stage_view != null) {
Mtk.Rectangle stage_view_layout = {};

box_scale_factor = stage_view.get_scale ();
stage_view.get_layout (ref stage_view_layout);

origin_x -= stage_view_layout.x;
origin_y -= stage_view_layout.y;
} else {
/* If we're drawing off stage, just assume scale = 1, this won't work
* with stage-view scaling though.
*/
}

source_actor_box.set_origin (origin_x, origin_y);
Expand Down Expand Up @@ -223,16 +189,13 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
framebuffer.set_projection_matrix (projection);
}

private bool update_actor_fbo (int width, int height, float downscale_factor) {
if (width <= 0 || height <= 0) {
return false;
}

private bool update_actor_fbo (int width, int height, float new_downscale_factor) {
if (
texture_width == width &&
texture_height == height &&
this.downscale_factor == downscale_factor &&
actor_framebuffer != null
actor_framebuffer != null &&
actor_texture != null &&
actor_texture.get_width () == width &&
actor_texture.get_height () == height &&
downscale_factor == new_downscale_factor
) {
return true;
}
Expand All @@ -243,8 +206,8 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
unowned var ctx = Clutter.get_default_backend ().get_cogl_context ();
#endif

var new_width = (int) Math.floorf (width / downscale_factor);
var new_height = (int) Math.floorf (height / downscale_factor);
var new_width = (int) Math.floorf (width / new_downscale_factor);
var new_height = (int) Math.floorf (height / new_downscale_factor);

#if HAS_MUTTER46
actor_texture = new Cogl.Texture2D.with_size (ctx, new_width, new_height);
Expand All @@ -266,12 +229,13 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
return true;
}

private bool update_rounded_fbo (int width, int height, float downscale_factor) {
private bool update_rounded_fbo (int width, int height, float new_downscale_factor) {
if (
texture_width == width &&
texture_height == height &&
this.downscale_factor == downscale_factor &&
round_framebuffer != null
round_framebuffer != null &&
round_texture != null &&
round_texture.get_width () == width &&
round_texture.get_height () == height &&
downscale_factor == new_downscale_factor
) {
return true;
}
Expand All @@ -282,8 +246,8 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
unowned var ctx = Clutter.get_default_backend ().get_cogl_context ();
#endif

var new_width = (int) Math.floorf (width / downscale_factor);
var new_height = (int) Math.floorf (height / downscale_factor);
var new_width = (int) Math.floorf (width / new_downscale_factor);
var new_height = (int) Math.floorf (height / new_downscale_factor);

#if HAS_MUTTER46
round_texture = new Cogl.Texture2D.with_size (ctx, new_width, new_height);
Expand All @@ -307,9 +271,10 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {

private bool update_background_fbo (int width, int height) {
if (
texture_width == width &&
texture_height == height &&
background_framebuffer != null
background_framebuffer != null &&
background_texture != null &&
background_texture.get_width () == width &&
background_texture.get_height () == height
) {
return true;
}
Expand Down Expand Up @@ -341,32 +306,34 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
}

private bool update_framebuffers (Clutter.PaintContext paint_context, Clutter.ActorBox actor_box) {
var width = (int) actor_box.get_width ();
var height = (int) actor_box.get_height ();
var actor_width = (int) actor_box.get_width ();
var actor_height = (int) actor_box.get_height ();

var blur_width = (int) (actor_width - left - right);
var blur_height = (int) (actor_height - top - bottom);

if (width < 0 || height < 0) {
if (actor_width <= 0 || actor_height <= 0 || blur_width <= 0 || blur_height <= 0) {
warning ("BackgroundBlurEffect: Couldn't update framebuffers, incorrect size");
return false;
}

var downscale_factor = calculate_downscale_factor (width, height, real_blur_radius);
var new_downscale_factor = calculate_downscale_factor (blur_width, blur_height, real_blur_radius);

var updated = update_actor_fbo (width, height, downscale_factor) && update_rounded_fbo (width, height, downscale_factor) && update_background_fbo (width, height);
var updated = (
update_actor_fbo (actor_width, actor_height, new_downscale_factor) &&
update_rounded_fbo (blur_width, blur_height, new_downscale_factor) &&
update_background_fbo (blur_width, blur_height)
);

texture_width = width;
texture_height = height;
this.downscale_factor = downscale_factor;
downscale_factor = new_downscale_factor;

return updated;
}

private Clutter.PaintNode create_blur_nodes (Clutter.PaintNode node) {
float width, height;
actor.get_size (out width, out height);

var blur_node = new Clutter.BlurNode (
(uint) (texture_width / downscale_factor),
(uint) (texture_height / downscale_factor),
round_texture.get_width (),
round_texture.get_height (),
real_blur_radius / downscale_factor
);
blur_node.add_rectangle ({
Expand All @@ -378,7 +345,7 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {

var round_node = new Clutter.LayerNode.to_framebuffer (round_framebuffer, round_pipeline);
round_node.add_child (blur_node);
round_node.add_rectangle ({ 0.0f, 0.0f, width, height });
round_node.add_rectangle ({ left, top, actor_texture.get_width () - right, actor_texture.get_height () - bottom });

node.add_child (round_node);

Expand All @@ -391,25 +358,24 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
}

private void paint_background (Clutter.PaintNode node, Clutter.PaintContext paint_context, Clutter.ActorBox source_actor_box) {
float transformed_x, transformed_y, transformed_width, transformed_height;

float transformed_x, transformed_y;
source_actor_box.get_origin (out transformed_x, out transformed_y);
source_actor_box.get_size (out transformed_width, out transformed_height);

/* Background layer node */
var background_node = new Clutter.LayerNode.to_framebuffer (background_framebuffer, background_pipeline);
node.add_child (background_node);
background_node.add_rectangle ({ 0.0f, 0.0f, texture_width / downscale_factor, texture_height / downscale_factor });
background_node.add_rectangle ({ 0.0f, 0.0f, background_texture.get_width (), background_texture.get_height () });

/* Blit node */
var blit_node = new Clutter.BlitNode (paint_context.get_framebuffer ());
background_node.add_child (blit_node);
blit_node.add_blit_rectangle (
(int) transformed_x,
(int) transformed_y,
0, 0,
(int) transformed_width,
(int) transformed_height
(int) (transformed_x + left),
(int) (transformed_y + top),
0,
0,
(int) background_texture.get_width (),
(int) background_texture.get_height ()
);
}

Expand All @@ -427,7 +393,7 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
}

var relative_opacity = (float) actor.opacity / 255.0f;
real_blur_radius = blur_radius * (float) Math.pow (relative_opacity, 2) * monitor_scale * (float) total_scale;
real_blur_radius = blur_radius * (float) Math.pow (relative_opacity, 2) * get_stage_view_scale (paint_context) * (float) total_scale;

Clutter.ActorBox source_actor_box = {};
update_actor_box (paint_context, ref source_actor_box);
Expand All @@ -443,6 +409,21 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
var blur_node = create_blur_nodes (node);
paint_background (blur_node, paint_context, source_actor_box);
add_actor_node (node);

update_uniforms (paint_context);
}

private void update_uniforms (Clutter.PaintContext paint_context) requires (round_texture != null) {
float[] actor_size = {
round_texture.get_width (),
round_texture.get_height ()
};
round_pipeline.set_uniform_float (round_actor_size_location, 2, 1, actor_size);

float[] clip_vals = {
(clip_radius * get_stage_view_scale (paint_context)) / downscale_factor
};
round_pipeline.set_uniform_float (round_clip_radius_location, 1, 1, clip_vals);
}

public override void paint (Clutter.PaintNode node, Clutter.PaintContext paint_context, Clutter.EffectPaintFlags flags) {
Expand Down
40 changes: 18 additions & 22 deletions src/BlurManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

public class Gala.BlurManager : Object {
private struct BlurData {
Clutter.Actor actor;
BackgroundBlurEffect blur_effect;
uint left;
uint right;
Expand Down Expand Up @@ -57,42 +56,39 @@ public class Gala.BlurManager : Object {

var blur_data = blurred_windows[window];
if (blur_data == null) {
var blur_effect = new BackgroundBlurEffect (BLUR_RADIUS, (int) clip_radius, 1.0f);
var blur_effect = new BackgroundBlurEffect (BLUR_RADIUS, (int) clip_radius);

var blurred_actor = new Clutter.Actor ();
blurred_actor.add_effect (blur_effect);
window_actor.insert_child_below (blurred_actor, null);
window_actor.add_effect (blur_effect);

blur_data = { blurred_actor, blur_effect, left, right, top, bottom, clip_radius };
blur_data = { blur_effect, left, right, top, bottom, clip_radius };
blurred_windows[window] = blur_data;

// TODO: We can require users of blur API to calculate shadow_size themselves and remove connecting to this
window.size_changed.connect (on_size_changed);
}

var buffer_rect = window.get_buffer_rect ();
var frame_rect = window.get_frame_rect ();
var x_shadow_size = frame_rect.x - buffer_rect.x;
var y_shadow_size = frame_rect.y - buffer_rect.y;

blur_data.actor.set_position (x_shadow_size + left, y_shadow_size + top);
blur_data.actor.set_size (frame_rect.width - left - right, frame_rect.height - top - bottom);
var left_shadow_size = frame_rect.x - buffer_rect.x;
var right_shadow_size = buffer_rect.width - frame_rect.width - left_shadow_size;
var top_shadow_size = frame_rect.y - buffer_rect.y;
var bottom_shadow_size = buffer_rect.height - frame_rect.height - top_shadow_size;

blur_data.blur_effect.left = left_shadow_size + left;
blur_data.blur_effect.right = right_shadow_size + right;
blur_data.blur_effect.top = top_shadow_size + top;
blur_data.blur_effect.bottom = bottom_shadow_size + bottom;
}

public void remove_blur (Meta.Window window) {
var blur_data = blurred_windows[window];
if (blur_data == null) {
return;
}

var actor = blur_data.actor;
actor.remove_effect (blur_data.blur_effect);
unowned var window_actor = (Meta.WindowActor) window.get_compositor_private ();
var blur_data = blurred_windows.take (window);

unowned var parent = actor.get_parent ();
if (parent != null) {
parent.remove_child (actor);
if (blur_data == null || window_actor == null) {
return;
}

blurred_windows.remove (window);
window_actor.remove_effect (blur_data.blur_effect);
}

private void on_size_changed (Meta.Window window) {
Expand Down
3 changes: 1 addition & 2 deletions src/Widgets/WindowSwitcher/WindowSwitcher.vala
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public class Gala.WindowSwitcher : CanvasActor, GestureTarget, RootTarget {
add_effect (shadow_effect);


blur_effect = new BackgroundBlurEffect (40, 9, scaling_factor);
blur_effect = new BackgroundBlurEffect (40, 9);
add_effect (blur_effect);

scale ();
Expand All @@ -123,7 +123,6 @@ public class Gala.WindowSwitcher : CanvasActor, GestureTarget, RootTarget {
scaling_factor = display.get_monitor_scale (display.get_current_monitor ());

shadow_effect.monitor_scale = scaling_factor;
blur_effect.monitor_scale = scaling_factor;

var margin = Utils.scale_to_int (WRAPPER_PADDING, scaling_factor);

Expand Down
Loading