picom icon indicating copy to clipboard operation
picom copied to clipboard

Custom shader for new backends

Open yshui opened this issue 1 year ago • 7 comments

Creating a new PR because I want to preserve @tryone144's original PR (#507) as a reference.

yshui avatar Jul 17 '22 13:07 yshui

Codecov Report

Merging #851 (35b403a) into next (896acab) will decrease coverage by 0.19%. The diff coverage is 51.38%.

Impacted file tree graph

@@            Coverage Diff             @@
##             next     #851      +/-   ##
==========================================
- Coverage   39.22%   39.02%   -0.20%     
==========================================
  Files          46       46              
  Lines        9753     9977     +224     
==========================================
+ Hits         3826     3894      +68     
- Misses       5927     6083     +156     
Impacted Files Coverage Δ
src/backend/backend.c 60.34% <ø> (ø)
src/backend/backend_common.c 39.09% <0.00%> (-0.66%) :arrow_down:
src/backend/gl/gl_common.h 30.95% <ø> (+0.71%) :arrow_up:
src/backend/gl/glx.c 36.89% <ø> (-0.33%) :arrow_down:
src/common.h 75.00% <ø> (-3.27%) :arrow_down:
src/config.h 23.52% <ø> (ø)
src/win.h 78.12% <ø> (ø)
src/picom.c 67.99% <28.88%> (-3.53%) :arrow_down:
src/options.c 21.79% <36.36%> (+0.22%) :arrow_up:
src/backend/gl/gl_common.c 16.10% <54.36%> (+1.28%) :arrow_up:
... and 15 more

codecov[bot] avatar Jul 17 '22 20:07 codecov[bot]

This should be ready for prime time. Only thing left is to document the shader interface.

Can you have a look, @tryone144 ?

yshui avatar Jul 17 '22 21:07 yshui

Ah, I forgot to set projection for custom shaders.

Update: fixed.

yshui avatar Jul 17 '22 21:07 yshui

Also, the time parameter is kinda useless unless we have an option to force picom to redraw every frame.

I propose adding a force-redraw = bool; option and a force-redraw-rule = []; option.

yshui avatar Jul 17 '22 21:07 yshui

Can you have a look, @tryone144 ?

I will try to get around to this week.

Also, the time parameter is kinda useless unless we have an option to force picom to redraw every frame.

I propose adding a force-redraw = bool; option and a force-redraw-rule = []; option.

I initially though about force-redrawing every window with a custom shader, but that is overkill performance wise. And I don't think autodetecting the use of time is reliable enough. force-redraw and force-redraw-rule should be fine. Maybe even add a force-blend-rule option while we are at it? These options however, leave the user responsible to ensure correct behaviour of their shaders (for animations and transparency).

tryone144 avatar Jul 19 '22 12:07 tryone144

hmm, actually i think we can detect use of time automatically. glGetUniformLocation would return -1 if the variable isn't used.

yshui avatar Aug 06 '22 12:08 yshui

@tryone144 Thanks for the review! I will try to get to it ASAP


The create_shader() backend operation could return a bool

Yes. I am also thinking maybe add a get_shader_property function with the only property being ANIMATED for now. I think this API is conceptually nicer, but I don't know if it's overkill. What other properties could a shader have?

yshui avatar Aug 08 '22 13:08 yshui

@tryone144 I think I resolved most of the complaints :+1:

yshui avatar Aug 11 '22 03:08 yshui

@tryone144 i think this PR is complete.

yshui avatar Aug 12 '22 13:08 yshui

Another thing that just came to mind: While it might be intuitive that redrawing the animated shaders continuously will inevitably increase the CPU load, we could add a short note to the docs.

Are we re-drawing with the screen refresh-rate when vsync is enabled (even on nvidia that has problems with glFinish())? Or do we re-draw as fast as the idle-loop permits? A short test supports the assumption we draw at the vsync limit (i.e. vsync = false results in 100% utilization).

tryone144 avatar Aug 13 '22 20:08 tryone144

A short test supports the assumption we draw at the vsync limit (i.e. vsync = false results in 100% utilization).

Hmm, it's an interesting question. But I think this is more or less expected behavior. I tried glxgears, and it does the same sort of thing if I disable vsync.

yshui avatar Aug 21 '22 03:08 yshui

Where can I find documentation on how to use this myself? Can it be used to create rounded corners also, or work at the same time as them? I want to try to use it to implement #824 as a shader

LoganDark avatar Aug 21 '22 04:08 LoganDark

@LoganDark see man picom, the SHADER INTERFACE section. Yes, it's possible to implement rounded corners in your custom shaders.

yshui avatar Aug 21 '22 05:08 yshui

Will it be possible to separate the post processing passes in the future? Like apply the color adjustments and then my own filter and then the vanilla rounded corners?

LoganDark avatar Aug 21 '22 05:08 LoganDark

@LoganDark you can copy the default_post_processing code if you want.

yshui avatar Aug 21 '22 05:08 yshui

I see, it looks like rewriting / copying all the code is the only option, well I suppose this is fine for an initial release, thank you :)

Hope that more modular/granular options are added in the future

LoganDark avatar Aug 21 '22 05:08 LoganDark

Is it possible for a shader to change the opacity of the background-blur? So outside of the window is not blurred if the window has rounded corners?

Is it also possible for a shader to sample behind the window so things like color filters can be implemented?

Should I open issues for these?

LoganDark avatar Aug 21 '22 05:08 LoganDark

@LoganDark No, this option is for custom foreground shaders, hence the fg in the name. You can open a feature request for background shaders if you want.

yshui avatar Aug 21 '22 13:08 yshui

Hmm, I try to start picom like this: picom --config ~/.config/picom/picom.conf --window-shader-fg ~/.config/picom/shader.glsl (the config is the sample one from the source tree, with backend = "xrender";), but I get the following:

[ 08/27/2022 11:25:49.881 get_cfg WARN ] The new window shader interface does not work with the legacy glx backend.

I've tried explicitly adding a --backend xrender arg, but the result is the same.

The picom version is vgit-e0758 and the shader is:

#version 330
in      vec2      texcoord;       // texture coordinate of the fragment
uniform float     opacity;        // opacity of the window (0.0 - 1.0)
uniform float     dim;            // dimming factor of the window (0.0 - 1.0, higher means more dim)
uniform float     corner_radius;  // corner radius of the window (pixels)
uniform float     border_width;   // estimated border width of the window (pixels)
uniform bool      invert_color;   // whether to invert the color of the window
uniform sampler2D tex;            // texture of the window
uniform sampler2D brightness;     // estimated brightness of the window, 1x1 texture
uniform float     max_brightness; // configured maximum brightness of the window (0.0 - 1.0)
uniform float     time;           // time in milliseconds, counting from an unspecified starting point

vec4 default_post_processing( vec4 c );

vec4 window_shader() {
	vec4 c = texelFetch(tex, ivec2(texcoord), 0);
	mix( c, vec4(.5, 1.0, .5, 1.0), .5 ); // just for feedback that the shader works
	return default_post_processing(c);
}

Any idea what's going wrong?

Falkgaard avatar Aug 27 '22 09:08 Falkgaard

I've tried explicitly adding a --backend xrender arg, but the result is the same.

The OpenGL shader only work with a gl compatible backend — only glx for now. The xrender backend can't use shaders directly.

tryone144 avatar Aug 27 '22 10:08 tryone144

Thank you, with glx it works great! (For some reason I thought the glx backend was the legacy one...)

By the way, do you know if it's possible to make the shader apply to the whole screen (and not specific windows) with the shader conditions? I'm trying to make a CRT-ish shader (scanlines, curvature, etc). I'm using bspwm, if that makes any difference. I tried --window-shader-fg-rule ~/.config/picom/retro.glsl:'wmwin', but that condition seems to be the wrong one for what I'm trying to achieve.


edit:

If there were a window offset uniform available, then I could use that to convert the texcoord to a screen space UV and correctly calculate the curvature, displacement, etc for any shaded window's fragments, but I don't currently see a way of achieving this. Any suggestions?

Falkgaard avatar Aug 27 '22 11:08 Falkgaard

@Falkgaard I guess it's a bit confusing. There are the legacy backends and the new backends. Each set of backends has its own glx and xrender backend. You were using the legacy backend, because you probably are not using the latest commit and didn't pass --experiment-backends.

The new backends are now the default thus if you use the latest git commit you don't need that option anymore.

yshui avatar Aug 27 '22 17:08 yshui

shader apply to the whole screen

This is better achieved with a overall shader, the per-window shader isn't suited for this job.

yshui avatar Aug 27 '22 17:08 yshui

I see. Updated to the latest commit. Cheers!

This is better achieved with a overall shader, the per-window shader isn't suited for this job.

Mm, makes sense. Does Picom support overall shaders or just per-window shaders?

(And if not, if anyone knows of some software that allows this when running a tiling WM, I'd love to hear about it.)

Falkgaard avatar Aug 28 '22 03:08 Falkgaard

curvature

Keep in mind this would cause the cursor to no longer be accurate, because picom doesn't render the cursor itself

LoganDark avatar Aug 28 '22 06:08 LoganDark

CRT

Would you mind sharing your shader with us? I've been looking for an accurate CRT shader for PICOM, I found one, but its not accurate at all. I tried porting zfast-crt but failed

xplshn avatar Mar 17 '24 23:03 xplshn