-
-
Notifications
You must be signed in to change notification settings - Fork 589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Correct shadows for shaped and rounded windows #882
Conversation
This is used to create image masks that can be used to mask out `compose` regions. For example, this can be used to mask out window body so shadow won't be painted on them. This could be more efficient than using rectangular regions for masking, when there are a large number of rectangles; or more flexible, in the case of window with rounded corners. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Use masks in compose. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
There are some complications, when sampling pixels outside a xrender picture, xrender doesn't support a behaviour similar to OpenGL's clamp to border. So we give the masks an extra 1-pixel outer rim, so we can control what color the outside pixels would be, by using the "Pad" repeat mode. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
When removing shadow behind a window with rounded corners, keep the corner part - those parts will be removed using the mask instead. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
gl_common.c is getting too big. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Instead of always using the back texture/fbo. Also use the size of the source texture, instead of hard coded back buffer size. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Using integral to estimate the sum of the kernel will overestimate a little bit. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Since image_dst is in X coordinates, after flipping Y, we need to subtract the height of the drawing area, to make it the bottom right corner for OpenGL. However, this breaks blur. Because we assumed the drawing area is the same size as the texture, which is not the case for blur. So add the height of the drawing area as another parameter. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
If the backend implements shadow_from_mask then it doesn't need to implement render_shadow. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Do this for shaped, and rounded windows. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Codecov Report
@@ Coverage Diff @@
## next #882 +/- ##
==========================================
- Coverage 39.01% 38.22% -0.80%
==========================================
Files 46 47 +1
Lines 9976 10342 +366
==========================================
+ Hits 3892 3953 +61
- Misses 6084 6389 +305
|
This will be an awesome feature 👍 Dunno if it is ready for testing, shadow branch (0777f07) dosen't draw any shadows, i get following error: Nvidia Closed Source Driver Shadows work on branch |
@nawuko can you record a trace? |
@nawuko also, is there more in the log? |
Nothing more in the logs, with default logging level, with trace logging i get the following (truncated) [ 29.08.2022 13:13:13.295 redirect_start DEBUG ] Redirecting the screen.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_SGI_video_sync.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_SGI_swap_control.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Missing GLX extension GLX_OML_sync_control.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Missing GLX extension GLX_MESA_swap_control.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_EXT_swap_control.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_EXT_texture_from_pixmap.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_ARB_create_context.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_EXT_buffer_age.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Found GLX extension GLX_ARB_create_context_robustness.
[ 29.08.2022 13:13:13.297 glx_has_extension INFO ] Missing GLX extension GLX_MESA_query_renderer.
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; uniform float scale = 1.0; uniform vec2 texorig; layout(location = 0) in vec2 coord; layout(location = 1) in vec2 in_texcoord; out vec2 texcoord; void main() { gl_Position = projection * vec4(coord, 0, scale); texcoord = in_texcoord + texorig; }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform float opacity; uniform float dim; uniform float corner_radius; uniform float border_width; uniform bool invert_color; in vec2 texcoord; uniform sampler2D tex; uniform sampler2D brightness; uniform float max_brightness; float rectangle_sdf(vec2 point, vec2 half_size) { vec2 d = abs(point) - half_size; return length(max(d, 0.0)); } vec4 default_post_processing(vec4 c) { vec4 border_color = texture(tex, vec2(0.0, 0.5)); if (invert_color) { c = vec4(c.aaa - c.rgb, c.a); border_color = vec4(border_color.aaa - border_color.rgb, border_color.a); } c = vec4(c.rgb * (1.0 - dim), c.a) * opacity; border_color = vec4(border_color.rgb * (1.0 - dim), border_color.a) * opacity; vec3 rgb_brightness = texelFetch(brightness, ivec2(0, 0), 0).rgb; float brightness = rgb_brightness.r * 0.21 + rgb_brightness.g * 0.72 + rgb_brightness.b * 0.07; if (brightness > max_brightness) { c.rgb = c.rgb * (max_brightness / brightness); border_color.rgb = border_color.rgb * (max_brightness / brightness); } vec4 rim_color = mix(c, border_color, clamp(border_width, 0.0f, 1.0f)); vec2 outer_size = vec2(textureSize(tex, 0)); vec2 inner_size = outer_size - vec2(corner_radius) * 2.0f; float rect_distance = rectangle_sdf(texcoord - outer_size / 2.0f, inner_size / 2.0f) - corner_radius; if (rect_distance > 0.0f) { c = (1.0f - clamp(rect_distance, 0.0f, 1.0f)) * rim_color; } else { float factor = clamp(rect_distance + border_width, 0.0f, 1.0f); c = (1.0f - factor) * c + factor * border_color; } return c; } vec4 window_shader(); float mask_factor(); void main() { gl_FragColor = window_shader() * mask_factor(); }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 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; }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
in vec2 texcoord; uniform sampler2D tex; vec4 default_post_processing(vec4 c); vec4 window_shader() { vec4 c = texelFetch(tex, ivec2(texcoord), 0); return default_post_processing(c); }
===
[ 29.08.2022 13:13:13.327 glGetUniformLocationChecked INFO ] Failed to get location of uniform 'time'. This is normal when using custom shaders.
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
layout(location = 0) in vec2 in_coord; uniform mat4 projection; void main() { gl_Position = projection * vec4(in_coord, 0, 1); }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform vec4 color; void main() { gl_FragColor = color; }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; layout(location = 0) in vec2 coord; out vec2 texcoord; void main() { gl_Position = projection * vec4(coord, 0, 1); texcoord = coord; }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform sampler2D tex; in vec2 texcoord; void main() { gl_FragColor = texelFetch(tex, ivec2(texcoord.xy), 0); }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; layout(location = 0) in vec2 coord; out vec2 texcoord; void main() { gl_Position = projection * vec4(coord, 0, 1); texcoord = coord; }
===
[ 29.08.2022 13:13:13.327 gl_create_shader TRACE ] ===
#version 330
uniform vec4 color; uniform sampler2D tex; in vec2 texcoord; out vec4 out_color; void main() { vec4 c = texelFetch(tex, ivec2(texcoord), 0); out_color = c.r * color; }
===
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; uniform vec2 texsize; layout(location = 0) in vec2 in_coord; layout(location = 1) in vec2 in_texcoord; out vec2 texcoord; void main() { gl_Position = projection * vec4(in_coord, 0, 1); texcoord = in_texcoord / texsize; }
===
-[ 29.08.2022 13:13:13.328 gl_create_shader ERROR ] GLX error at line 61: GL_INVALID_OPERATION
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform sampler2D tex; in vec2 texcoord; void main() { gl_FragColor = vec4(texture2D(tex, vec2(texcoord.xy), 0).rgb, 1); }
===
[ 29.08.2022 13:13:13.328 gl_has_extension INFO ] Missing GL extension GL_GREMEDY_string_marker.
[ 29.08.2022 13:13:13.328 gl_init DEBUG ] GL_VENDOR = NVIDIA Corporation
[ 29.08.2022 13:13:13.328 gl_init INFO ] GL vendor is NVIDIA, don't use glFinish
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; uniform float scale = 1.0; uniform vec2 texorig; layout(location = 0) in vec2 coord; layout(location = 1) in vec2 in_texcoord; out vec2 texcoord; void main() { gl_Position = projection * vec4(coord, 0, scale); texcoord = in_texcoord + texorig; }
===
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform sampler2D tex_src; uniform float scale = 1.0; uniform vec2 pixel_norm; in vec2 texcoord; out vec4 out_color; void main() { vec2 offset = 4.25 * pixel_norm; vec2 uv = texcoord * pixel_norm * (2.0 / scale); vec4 sum = texture2D(tex_src, uv) * 4.0; sum += texture2D(tex_src, uv - vec2(0.5, 0.5) * offset); sum += texture2D(tex_src, uv + vec2(0.5, 0.5) * offset); sum += texture2D(tex_src, uv + vec2(0.5, -0.5) * offset); sum += texture2D(tex_src, uv - vec2(0.5, -0.5) * offset); out_color = sum / 8.0; }
===
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform mat4 projection; uniform float scale = 1.0; uniform vec2 texorig; layout(location = 0) in vec2 coord; layout(location = 1) in vec2 in_texcoord; out vec2 texcoord; void main() { gl_Position = projection * vec4(coord, 0, scale); texcoord = in_texcoord + texorig; }
===
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 330
uniform sampler2D tex_src; uniform float scale = 1.0; uniform vec2 pixel_norm; uniform float opacity; in vec2 texcoord; out vec4 out_color; float mask_factor(); void main() { vec2 offset = 4.25 * pixel_norm; vec2 uv = texcoord * pixel_norm / (2 * scale); vec4 sum = texture2D(tex_src, uv + vec2(-1.0, 0.0) * offset); 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; sum += texture2D(tex_src, uv + vec2(1.0, 0.0) * offset); 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 * mask_factor(); }
===
[ 29.08.2022 13:13:13.328 gl_create_shader TRACE ] ===
#version 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; }
=== Sadly can't provide an apitrace atm. |
Hello, I observe the same error, no shadow is rendered. Arch Linux 5.19.4-arch1-1 you can find my config here -> https://github.com/doums/dotfiles/blob/master/.config/picom.conf error in picom logs
I tried to generate a trace, sadly I got an error with apitrace preventing to start picom.
Edit: On a different machine, same Linux distribution, similar install, but with xf86-video-intel and mesa instead of |
I can also reproduce this with A small snippet from the dumped trace:
|
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
@frebib Thanks for the trace! I have fixed the problem, apparently a typo... 😢 |
Can confirm, its working for me now on nvidia 👍 |
Works great for me too. Thanks for the quick fix! |
Out of curiosity, should this fix the shadow/blur behind windows with strange bounding boxes like the context menus in Firefox? I still see a small ~5-6 pixel border of shadow/blur even with this patch and I'm not sure if that's intentional. I have |
@frebib unfortunately no, firefox's context menu doesn't use the X shape extension, it just has parts of it being completely transparent. that's why there are gaps. i am considering adding an option to use windows' alpha channels as their bounding shape, which would solve this. |
I wonder how many people has already tested this branch? |
At least 3 peoples, me on two different machines, with both Nvidia proprietary and free drivers. |
Second that. I have this running on two computers with one running proprietary nvidia drivers and the other i915 iGPU and it's running great |
OK, let's make the call and merge this without @tryone144's review. @tryone144 please still do have a look at this when you find some time! i still would like to hear your input. |
Wth happened to the shadows. They are ugly now. P.S. My config is here: #863 Nothing has changed ever since. |
@Monsterovich I was trying out using dual kawase blur for shadow, I changed it back to gaussian now. |
I was observing the same as @Monsterovich, but playing a bit with shadow values fixed the issue, but yea shadow was rendered differently. |
How did you fix it? |
Using these values
at least for me it kinda fix what we observe on your first screenshot |
@Monsterovich it should be back to what it used to be on latest git. |
I don't see any new commits in the "next" branch. Have you pushed them yet? |
@Monsterovich oops, I didn't. 😅 Sorry about that! |
@yshui There is also a bit of a problem with the new changes. The underside of the shadow is smooth as it was before. But the sides are not smooth. Why is that? Without zooming in it looks like graphical artifacts. |
@yshui Can you suggest a fix for the ugly effect with the shadows? #882 (comment)? |
https://build.opensuse.org/request/show/1035698 by user mia + dimstar_suse - Update to version 10 * picom now needs libEGL to build Notable changes: * experimental-backends is now the default. Everything should keep working, except the --glx-fshader-win option. The old window shader support has been replaced by --window-shader-fd. This new shader support has a different interface, so you have to adapt your existing shaders. gh#yshui/picom#875 * legacy-backends option has been added so you can go back to the old backends, which will eventually be removed. * picom.desktop is installed to /etc/xdg/autostart/. picom should autostart now. gh#yshui/picom#791 * Shadows and blur now match the shape of the window. This includes windows using the XShape extension, and windows with rounded corners. gh#yshui/picom#882 *
Example:
Based on #881 This is only implemented for glx, not xrender.