Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
145 changes: 64 additions & 81 deletions src/BackgroundBlurEffect.vala
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ public class Gala.BackgroundBlurEffect : Clutter.Effect {
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 Down Expand Up @@ -122,40 +124,6 @@ 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);

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);
}

private void update_actor_box (Clutter.PaintContext paint_context, ref Clutter.ActorBox source_actor_box) {
Expand Down Expand Up @@ -223,16 +191,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 +208,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 +231,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 +248,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 +273,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 +308,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 +347,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 +360,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 Down Expand Up @@ -443,6 +411,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 ();
}

private void update_uniforms () 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 * monitor_scale) / 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
51 changes: 29 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 @@ -43,6 +42,13 @@ public class Gala.BlurManager : Object {
window.notify["mutter-hints"].connect ((obj, pspec) => parse_mutter_hints ((Meta.Window) obj));
parse_mutter_hints (window);
});

unowned var monitor_manager = wm.get_display ().get_context ().get_backend ().get_monitor_manager ();
monitor_manager.monitors_changed.connect (() => {
foreach (unowned var window in blurred_windows.get_keys ()) {
blurred_windows[window].blur_effect.monitor_scale = window.display.get_monitor_scale (window.get_monitor ());
}
});
}

/**
Expand All @@ -57,42 +63,43 @@ 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,
window.display.get_monitor_scale (window.get_monitor ())
);

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