mirror of https://github.com/yshui/picom.git
Merge pull request #881 from yshui/blur
Fix blur behind rounded corner windows
This commit is contained in:
commit
95e5732d66
|
@ -246,6 +246,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
* is transparent or not. for now we will just rely on the force_win_blend
|
||||
* option */
|
||||
auto real_win_mode = w->mode;
|
||||
coord_t window_coord = {.x = w->g.x, .y = w->g.y};
|
||||
|
||||
if (w->blur_background &&
|
||||
(ps->o.force_win_blend || real_win_mode == WMODE_TRANS ||
|
||||
|
@ -289,7 +290,8 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
// We need to blur the bounding shape of the window
|
||||
// (reg_paint_in_bound = reg_bound \cap reg_paint)
|
||||
ps->backend_data->ops->blur(
|
||||
ps->backend_data, blur_opacity, ps->backend_blur_context,
|
||||
ps->backend_data, blur_opacity,
|
||||
ps->backend_blur_context, w->mask_image, window_coord,
|
||||
®_paint_in_bound, ®_visible);
|
||||
} else {
|
||||
// Window itself is solid, we only need to blur the frame
|
||||
|
@ -308,14 +310,13 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
|||
pixman_region32_intersect(®_blur, ®_blur,
|
||||
®_visible);
|
||||
}
|
||||
ps->backend_data->ops->blur(ps->backend_data, blur_opacity,
|
||||
ps->backend_blur_context,
|
||||
®_blur, ®_visible);
|
||||
ps->backend_data->ops->blur(
|
||||
ps->backend_data, blur_opacity, ps->backend_blur_context,
|
||||
w->mask_image, window_coord, ®_blur, ®_visible);
|
||||
pixman_region32_fini(®_blur);
|
||||
}
|
||||
}
|
||||
|
||||
coord_t window_coord = {.x = w->g.x, .y = w->g.y};
|
||||
// Draw shadow on target
|
||||
if (w->shadow) {
|
||||
assert(!(w->flags & WIN_FLAGS_SHADOW_NONE));
|
||||
|
|
|
@ -185,9 +185,12 @@ struct backend_operations {
|
|||
void (*fill)(backend_t *backend_data, struct color, const region_t *clip);
|
||||
|
||||
/// Blur a given region of the rendering buffer.
|
||||
bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx,
|
||||
const region_t *reg_blur, const region_t *reg_visible)
|
||||
attr_nonnull(1, 3, 4, 5);
|
||||
///
|
||||
/// The blur is limited by `mask`. `mask_dst` specifies the top left corner of the
|
||||
/// mask is.
|
||||
bool (*blur)(backend_t *backend_data, double opacity, void *blur_ctx, void *mask,
|
||||
coord_t mask_dst, const region_t *reg_blur,
|
||||
const region_t *reg_visible) attr_nonnull(1, 3, 4, 6, 7);
|
||||
|
||||
/// Update part of the back buffer with the rendering buffer, then present the
|
||||
/// back buffer onto the target window (if not back buffered, update part of the
|
||||
|
|
|
@ -75,7 +75,8 @@ void dummy_fill(struct backend_base *backend_data attr_unused, struct color c at
|
|||
}
|
||||
|
||||
bool dummy_blur(struct backend_base *backend_data attr_unused, double opacity attr_unused,
|
||||
void *blur_ctx attr_unused, const region_t *reg_blur attr_unused,
|
||||
void *blur_ctx attr_unused, void *mask attr_unused,
|
||||
coord_t mask_dst attr_unused, const region_t *reg_blur attr_unused,
|
||||
const region_t *reg_visible attr_unused) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -494,6 +494,11 @@ static void _gl_compose(backend_t *base, struct backend_image *img, GLuint targe
|
|||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
// Cleanup
|
||||
glActiveTexture(GL_TEXTURE2);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glDrawBuffer(GL_BACK);
|
||||
|
@ -511,7 +516,7 @@ static void _gl_compose(backend_t *base, struct backend_image *img, GLuint targe
|
|||
|
||||
/// Convert rectangles in X coordinates to OpenGL vertex and texture coordinates
|
||||
/// @param[in] nrects, rects rectangles
|
||||
/// @param[in] dst_x, dst_y origin of the OpenGL texture, affect the calculated texture
|
||||
/// @param[in] image_dst origin of the OpenGL texture, affect the calculated texture
|
||||
/// coordinates
|
||||
/// @param[in] texture_height height of the OpenGL texture
|
||||
/// @param[in] root_height height of the back buffer
|
||||
|
@ -612,7 +617,8 @@ void gl_compose(backend_t *base, void *image_data, coord_t image_dst, void *mask
|
|||
* Blur contents in a particular region.
|
||||
*/
|
||||
bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *extent,
|
||||
const GLuint vao[2], const int vao_nelems[2]) {
|
||||
struct backend_image *mask, coord_t mask_dst, const GLuint vao[2],
|
||||
const int vao_nelems[2]) {
|
||||
auto bctx = (struct gl_blur_context *)ctx;
|
||||
auto gd = (struct gl_data *)base;
|
||||
|
||||
|
@ -641,11 +647,20 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
tex_height = src_size.height;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, src_texture);
|
||||
glUseProgram(p->prog);
|
||||
glUniform2f(p->uniform_pixel_norm, 1.0F / (GLfloat)tex_width,
|
||||
1.0F / (GLfloat)tex_height);
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, gd->default_mask_texture);
|
||||
|
||||
glUniform1i(p->uniform_mask_tex, 1);
|
||||
glUniform2f(p->uniform_mask_offset, 0.0F, 0.0F);
|
||||
glUniform1i(p->uniform_mask_inverted, 0);
|
||||
glUniform1f(p->uniform_mask_corner_radius, 0.0F);
|
||||
|
||||
// The number of indices in the selected vertex array
|
||||
GLsizei nelems;
|
||||
|
||||
|
@ -668,7 +683,18 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
glUniform1f(p->uniform_opacity, 1.0F);
|
||||
} else {
|
||||
// last pass, draw directly into the back buffer, with origin
|
||||
// regions
|
||||
// regions. And apply mask if requested
|
||||
if (mask) {
|
||||
auto inner = (struct gl_texture *)mask->inner;
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, inner->texture);
|
||||
glUniform1i(p->uniform_mask_inverted, mask->color_inverted);
|
||||
glUniform1f(p->uniform_mask_corner_radius,
|
||||
(float)mask->corner_radius);
|
||||
glUniform2f(
|
||||
p->uniform_mask_offset, (float)(mask_dst.x),
|
||||
(float)(bctx->fb_height - mask_dst.y - inner->height));
|
||||
}
|
||||
glBindVertexArray(vao[0]);
|
||||
nelems = vao_nelems[0];
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gd->back_fbo);
|
||||
|
@ -689,6 +715,7 @@ bool gl_kernel_blur(backend_t *base, double opacity, void *ctx, const rect_t *ex
|
|||
}
|
||||
|
||||
bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_t *extent,
|
||||
struct backend_image *mask, coord_t mask_dst,
|
||||
const GLuint vao[2], const int vao_nelems[2]) {
|
||||
auto bctx = (struct gl_blur_context *)ctx;
|
||||
auto gd = (struct gl_data *)base;
|
||||
|
@ -764,7 +791,15 @@ bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_
|
|||
// The number of indices in the selected vertex array
|
||||
GLsizei nelems;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, src_texture);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, gd->default_mask_texture);
|
||||
|
||||
glUniform1i(up_pass->uniform_mask_tex, 1);
|
||||
glUniform2f(up_pass->uniform_mask_offset, 0.0F, 0.0F);
|
||||
glUniform1i(up_pass->uniform_mask_inverted, 0);
|
||||
glUniform1f(up_pass->uniform_mask_corner_radius, 0.0F);
|
||||
if (i > 0) {
|
||||
assert(bctx->blur_fbos[i - 1]);
|
||||
|
||||
|
@ -777,6 +812,18 @@ bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_
|
|||
glUniform1f(up_pass->uniform_opacity, (GLfloat)1);
|
||||
} else {
|
||||
// last pass, draw directly into the back buffer
|
||||
if (mask) {
|
||||
auto inner = (struct gl_texture *)mask->inner;
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, inner->texture);
|
||||
glUniform1i(up_pass->uniform_mask_inverted,
|
||||
mask->color_inverted);
|
||||
glUniform1f(up_pass->uniform_mask_corner_radius,
|
||||
(float)mask->corner_radius);
|
||||
glUniform2f(
|
||||
up_pass->uniform_mask_offset, (float)(mask_dst.x),
|
||||
(float)(bctx->fb_height - mask_dst.y - inner->height));
|
||||
}
|
||||
glBindVertexArray(vao[0]);
|
||||
nelems = vao_nelems[0];
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, gd->back_fbo);
|
||||
|
@ -794,8 +841,8 @@ bool gl_dual_kawase_blur(backend_t *base, double opacity, void *ctx, const rect_
|
|||
return true;
|
||||
}
|
||||
|
||||
bool gl_blur(backend_t *base, double opacity, void *ctx, const region_t *reg_blur,
|
||||
const region_t *reg_visible attr_unused) {
|
||||
bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mask_dst,
|
||||
const region_t *reg_blur, const region_t *reg_visible attr_unused) {
|
||||
auto bctx = (struct gl_blur_context *)ctx;
|
||||
auto gd = (struct gl_data *)base;
|
||||
|
||||
|
@ -904,12 +951,17 @@ bool gl_blur(backend_t *base, double opacity, void *ctx, const region_t *reg_blu
|
|||
int vao_nelems[2] = {nrects * 6, nrects_resized * 6};
|
||||
|
||||
if (bctx->method == BLUR_METHOD_DUAL_KAWASE) {
|
||||
ret = gl_dual_kawase_blur(base, opacity, ctx, extent_resized, vao, vao_nelems);
|
||||
ret = gl_dual_kawase_blur(base, opacity, ctx, extent_resized, mask,
|
||||
mask_dst, vao, vao_nelems);
|
||||
} else {
|
||||
ret = gl_kernel_blur(base, opacity, ctx, extent_resized, vao, vao_nelems);
|
||||
ret = gl_kernel_blur(base, opacity, ctx, extent_resized, mask, mask_dst,
|
||||
vao, vao_nelems);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
@ -1005,6 +1057,15 @@ static const char dummy_frag[] = GLSL(330,
|
|||
}
|
||||
);
|
||||
|
||||
static const char copy_with_mask_frag[] = GLSL(330,
|
||||
uniform sampler2D tex;
|
||||
in vec2 texcoord;
|
||||
float mask_factor();
|
||||
void main() {
|
||||
gl_FragColor = texelFetch(tex, ivec2(texcoord.xy), 0) * mask_factor();
|
||||
}
|
||||
);
|
||||
|
||||
static const char fill_frag[] = GLSL(330,
|
||||
uniform vec4 color;
|
||||
void main() {
|
||||
|
@ -1204,6 +1265,7 @@ void gl_destroy_blur_context(backend_t *base attr_unused, void *ctx) {
|
|||
gl_check_err();
|
||||
}
|
||||
|
||||
const char *masking_glsl;
|
||||
/**
|
||||
* Initialize GL blur filters.
|
||||
*/
|
||||
|
@ -1247,11 +1309,12 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
uniform float opacity;
|
||||
in vec2 texcoord;
|
||||
out vec4 out_color;
|
||||
float mask_factor();
|
||||
void main() {
|
||||
vec2 uv = texcoord * pixel_norm;
|
||||
vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
%s //body of the convolution
|
||||
out_color = sum / float(%.7g) * opacity;
|
||||
out_color = sum / float(%.7g) * opacity * mask_factor();
|
||||
}
|
||||
);
|
||||
static const char *FRAG_SHADER_BLUR_ADD = QUOTE(
|
||||
|
@ -1342,7 +1405,9 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
free(shader_body);
|
||||
|
||||
// Build program
|
||||
pass->prog = gl_create_program_from_str(vertex_shader, shader_str);
|
||||
pass->prog = gl_create_program_from_strv(
|
||||
(const char *[]){vertex_shader, NULL},
|
||||
(const char *[]){shader_str, masking_glsl, NULL});
|
||||
free(shader_str);
|
||||
if (!pass->prog) {
|
||||
log_error("Failed to create GLSL program.");
|
||||
|
@ -1354,6 +1419,14 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
// Get uniform addresses
|
||||
bind_uniform(pass, pixel_norm);
|
||||
bind_uniform(pass, opacity);
|
||||
|
||||
bind_uniform(pass, mask_tex);
|
||||
bind_uniform(pass, mask_offset);
|
||||
bind_uniform(pass, mask_inverted);
|
||||
bind_uniform(pass, mask_corner_radius);
|
||||
log_info("Uniform locations: %d %d %d %d %d", pass->uniform_mask_tex,
|
||||
pass->uniform_mask_offset, pass->uniform_mask_inverted,
|
||||
pass->uniform_mask_corner_radius, pass->uniform_opacity);
|
||||
pass->texorig_loc = glGetUniformLocationChecked(pass->prog, "texorig");
|
||||
|
||||
// Setup projection matrix
|
||||
|
@ -1370,10 +1443,16 @@ bool gl_create_kernel_blur_context(void *blur_context, GLfloat *projection,
|
|||
// Generate an extra null pass so we don't need special code path for
|
||||
// the single pass case
|
||||
auto pass = &ctx->blur_shader[1];
|
||||
pass->prog = gl_create_program_from_str(vertex_shader, dummy_frag);
|
||||
pass->prog = gl_create_program_from_strv(
|
||||
(const char *[]){vertex_shader, NULL},
|
||||
(const char *[]){copy_with_mask_frag, masking_glsl, NULL});
|
||||
pass->uniform_pixel_norm = -1;
|
||||
pass->uniform_opacity = -1;
|
||||
pass->texorig_loc = glGetUniformLocationChecked(pass->prog, "texorig");
|
||||
bind_uniform(pass, mask_tex);
|
||||
bind_uniform(pass, mask_offset);
|
||||
bind_uniform(pass, mask_inverted);
|
||||
bind_uniform(pass, mask_corner_radius);
|
||||
|
||||
// Setup projection matrix
|
||||
glUseProgram(pass->prog);
|
||||
|
@ -1495,6 +1574,7 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
uniform float opacity;
|
||||
in vec2 texcoord;
|
||||
out vec4 out_color;
|
||||
float mask_factor();
|
||||
void main() {
|
||||
vec2 offset = %.7g * pixel_norm;
|
||||
vec2 uv = texcoord * pixel_norm / (2 * scale);
|
||||
|
@ -1506,7 +1586,7 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
sum += texture2D(tex_src, uv + vec2(0.5, -0.5) * offset) * 2.0;
|
||||
sum += texture2D(tex_src, uv + vec2(0.0, -1.0) * offset);
|
||||
sum += texture2D(tex_src, uv + vec2(-0.5, -0.5) * offset) * 2.0;
|
||||
out_color = sum / 12.0 * opacity;
|
||||
out_color = sum / 12.0 * opacity * mask_factor();
|
||||
}
|
||||
);
|
||||
// clang-format on
|
||||
|
@ -1521,7 +1601,9 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
CHECK((size_t)real_shader_len < shader_len);
|
||||
|
||||
// Build program
|
||||
up_pass->prog = gl_create_program_from_str(vertex_shader, shader_str);
|
||||
up_pass->prog = gl_create_program_from_strv(
|
||||
(const char *[]){vertex_shader, NULL},
|
||||
(const char *[]){shader_str, masking_glsl, NULL});
|
||||
free(shader_str);
|
||||
if (!up_pass->prog) {
|
||||
log_error("Failed to create GLSL program.");
|
||||
|
@ -1533,6 +1615,12 @@ bool gl_create_dual_kawase_blur_context(void *blur_context, GLfloat *projection,
|
|||
// Get uniform addresses
|
||||
bind_uniform(up_pass, pixel_norm);
|
||||
bind_uniform(up_pass, opacity);
|
||||
|
||||
bind_uniform(up_pass, mask_tex);
|
||||
bind_uniform(up_pass, mask_offset);
|
||||
bind_uniform(up_pass, mask_inverted);
|
||||
bind_uniform(up_pass, mask_corner_radius);
|
||||
|
||||
up_pass->texorig_loc =
|
||||
glGetUniformLocationChecked(up_pass->prog, "texorig");
|
||||
up_pass->scale_loc = glGetUniformLocationChecked(up_pass->prog, "scale");
|
||||
|
@ -1633,6 +1721,34 @@ void gl_get_blur_size(void *blur_context, int *width, int *height) {
|
|||
}
|
||||
|
||||
// clang-format off
|
||||
const char *masking_glsl = GLSL(330,
|
||||
uniform sampler2D mask_tex;
|
||||
uniform vec2 mask_offset;
|
||||
uniform float mask_corner_radius;
|
||||
uniform bool mask_inverted;
|
||||
in vec2 texcoord;
|
||||
float mask_rectangle_sdf(vec2 point, vec2 half_size) {
|
||||
vec2 d = abs(point) - half_size;
|
||||
return length(max(d, 0.0));
|
||||
}
|
||||
float mask_factor() {
|
||||
vec2 mask_size = textureSize(mask_tex, 0);
|
||||
vec2 maskcoord = texcoord - mask_offset;
|
||||
vec4 mask = texture2D(mask_tex, maskcoord / mask_size);
|
||||
if (mask_corner_radius != 0) {
|
||||
vec2 inner_size = mask_size - vec2(mask_corner_radius) * 2.0f;
|
||||
float dist = mask_rectangle_sdf(maskcoord - mask_size / 2.0f,
|
||||
inner_size / 2.0f) - mask_corner_radius;
|
||||
if (dist > 0.0f) {
|
||||
mask.r = (1.0f - clamp(dist, 0.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
if (mask_inverted) {
|
||||
mask.rgb = 1.0 - mask.rgb;
|
||||
}
|
||||
return mask.r;
|
||||
}
|
||||
);
|
||||
const char *win_shader_glsl = GLSL(330,
|
||||
uniform float opacity;
|
||||
uniform float dim;
|
||||
|
@ -1643,11 +1759,6 @@ const char *win_shader_glsl = GLSL(330,
|
|||
uniform sampler2D tex;
|
||||
uniform sampler2D brightness;
|
||||
uniform float max_brightness;
|
||||
|
||||
uniform sampler2D mask_tex;
|
||||
uniform vec2 mask_offset;
|
||||
uniform float mask_corner_radius;
|
||||
uniform bool mask_inverted;
|
||||
// Signed distance field for rectangle center at (0, 0), with size of
|
||||
// half_size * 2
|
||||
float rectangle_sdf(vec2 point, vec2 half_size) {
|
||||
|
@ -1694,23 +1805,10 @@ const char *win_shader_glsl = GLSL(330,
|
|||
}
|
||||
|
||||
vec4 window_shader();
|
||||
float mask_factor();
|
||||
|
||||
void main() {
|
||||
vec2 mask_size = textureSize(mask_tex, 0);
|
||||
vec2 maskcoord = texcoord - mask_offset;
|
||||
vec4 mask = texture2D(mask_tex, maskcoord / mask_size);
|
||||
if (mask_corner_radius != 0) {
|
||||
vec2 inner_size = mask_size - vec2(mask_corner_radius) * 2.0f;
|
||||
float dist = rectangle_sdf(maskcoord - mask_size / 2.0f,
|
||||
inner_size / 2.0f) - mask_corner_radius;
|
||||
if (dist > 0.0f) {
|
||||
mask.r = (1.0f - clamp(dist, 0.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
if (mask_inverted) {
|
||||
mask.rgb = 1.0 - mask.rgb;
|
||||
}
|
||||
gl_FragColor = window_shader() * mask.r;
|
||||
gl_FragColor = window_shader() * mask_factor();
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1739,7 +1837,7 @@ void *gl_create_window_shader(backend_t *backend_data attr_unused, const char *s
|
|||
auto win_shader = (gl_win_shader_t *)ccalloc(1, gl_win_shader_t);
|
||||
|
||||
const char *vert_shaders[2] = {vertex_shader, NULL};
|
||||
const char *frag_shaders[3] = {win_shader_glsl, source, NULL};
|
||||
const char *frag_shaders[4] = {win_shader_glsl, masking_glsl, source, NULL};
|
||||
|
||||
if (!gl_win_shader_from_stringv(vert_shaders, frag_shaders, win_shader)) {
|
||||
free(win_shader);
|
||||
|
|
|
@ -59,6 +59,11 @@ typedef struct {
|
|||
GLint uniform_opacity;
|
||||
GLint texorig_loc;
|
||||
GLint scale_loc;
|
||||
|
||||
GLint uniform_mask_tex;
|
||||
GLint uniform_mask_offset;
|
||||
GLint uniform_mask_corner_radius;
|
||||
GLint uniform_mask_inverted;
|
||||
} gl_blur_shader_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -142,8 +147,8 @@ void *gl_make_mask(backend_t *base, geometry_t size, const region_t *reg);
|
|||
|
||||
void *gl_clone(backend_t *base, const void *image_data, const region_t *reg_visible);
|
||||
|
||||
bool gl_blur(backend_t *base, double opacity, void *, const region_t *reg_blur,
|
||||
const region_t *reg_visible);
|
||||
bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mask_dst,
|
||||
const region_t *reg_blur, const region_t *reg_visible);
|
||||
void *gl_create_blur_context(backend_t *base, enum blur_method, void *args);
|
||||
void gl_destroy_blur_context(backend_t *base, void *ctx);
|
||||
void gl_get_blur_size(void *blur_context, int *width, int *height);
|
||||
|
|
|
@ -373,8 +373,8 @@ static void fill(backend_t *base, struct color c, const region_t *clip) {
|
|||
.height = to_u16_checked(extent->y2 - extent->y1)}});
|
||||
}
|
||||
|
||||
static bool blur(backend_t *backend_data, double opacity, void *ctx_,
|
||||
const region_t *reg_blur, const region_t *reg_visible) {
|
||||
static bool blur(backend_t *backend_data, double opacity, void *ctx_, void *mask,
|
||||
coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible) {
|
||||
struct _xrender_blur_context *bctx = ctx_;
|
||||
if (bctx->method == BLUR_METHOD_NONE) {
|
||||
return true;
|
||||
|
@ -425,7 +425,12 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_,
|
|||
pixman_region32_fini(&clip);
|
||||
|
||||
xcb_render_picture_t src_pict = xd->back[2], dst_pict = tmp_picture[0];
|
||||
auto alpha_pict = xd->alpha_pict[(int)(opacity * MAX_ALPHA)];
|
||||
auto mask_pict = xd->alpha_pict[(int)(opacity * MAX_ALPHA)];
|
||||
bool mask_allocated = false;
|
||||
if (mask != NULL) {
|
||||
mask_pict = process_mask(xd, mask, opacity != 1.0 ? mask_pict : XCB_NONE,
|
||||
&mask_allocated);
|
||||
}
|
||||
int current = 0;
|
||||
x_set_picture_clip_region(c, src_pict, 0, 0, ®_op_resized);
|
||||
|
||||
|
@ -461,11 +466,12 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_,
|
|||
} else {
|
||||
x_set_picture_clip_region(c, xd->back[2], 0, 0, ®_op);
|
||||
// This is the last pass, and we are doing more than 1 pass
|
||||
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict,
|
||||
alpha_pict, xd->back[2], 0, 0, 0, 0,
|
||||
to_i16_checked(extent_resized->x1),
|
||||
to_i16_checked(extent_resized->y1),
|
||||
width_resized, height_resized);
|
||||
xcb_render_composite(
|
||||
c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2],
|
||||
0, 0, to_i16_checked(extent_resized->x1 - mask_dst.x + 1),
|
||||
to_i16_checked(extent_resized->y1 - mask_dst.y + 1),
|
||||
to_i16_checked(extent_resized->x1),
|
||||
to_i16_checked(extent_resized->y1), width_resized, height_resized);
|
||||
}
|
||||
|
||||
// reset filter
|
||||
|
@ -481,8 +487,10 @@ static bool blur(backend_t *backend_data, double opacity, void *ctx_,
|
|||
if (i == 1) {
|
||||
x_set_picture_clip_region(c, xd->back[2], 0, 0, ®_op);
|
||||
xcb_render_composite(
|
||||
c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict, xd->back[2], 0, 0,
|
||||
0, 0, to_i16_checked(extent_resized->x1),
|
||||
c, XCB_RENDER_PICT_OP_OVER, src_pict, mask_pict, xd->back[2], 0, 0,
|
||||
to_i16_checked(extent_resized->x1 - mask_dst.x + 1),
|
||||
to_i16_checked(extent_resized->y1 - mask_dst.y + 1),
|
||||
to_i16_checked(extent_resized->x1),
|
||||
to_i16_checked(extent_resized->y1), width_resized, height_resized);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue