-
-
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
[RFC] Custom window shader in experimental OpenGL backend #507
Conversation
i don't think that it's a good idea to leave the ability to pass a custom shader as string, the only sense is backwards-compatibility. the best way to pass a custom shader is to pass the path to a file containing a custom shader. |
df94985
to
ae24fce
Compare
Since the new option has a different name altogether, we shouldn't be concerned too much about backwards-compatibility. |
why we have to use what do you think about implementing a file-watching mechanism similiar to the one implemented for the configuration file? when the file containing a custom shader is changed the shader is reloaded. it would be useful for developing and debugging shaders (especially complex ones). but i think it may have some performance hit when watching for, say, 10 shaders, so maybe it should be configurable for a particular shader. |
Because the custom shader currently doesn't replace the "default" rendering pipeline completely, but is just an extension. The default fragment shader still has the
File-watching should be theoretically possible. Currently, a change in one of the shaders would require completely destroying and re-initializing the backend like a config change already does. We could extend the backend-interface to separately initialize and destroy the shaders, depending on how tightly we want to couple this feature. |
Another thing to consider: Are we fine with just a single pass for each window or do we want a pass for each shader? The former wouldn't require complete redrawing of the window for each supplied shader while the latter would offer more freedom for the shaders (i.e. multiple "blur" passes) as each shader is self-contained and has access to the whole rendered image of the previous pass. If we opt to do multiple passes, how do we separate them in the config? |
Parse `--window-shader-fg` and `--window-shader-fg-rules` in the config file and as cli options. Load the specified fragment shader files. Configuration options are NULL-ed on unsupported backends.
…end) Initialize window programs with custom fragment shader. Support for arbitrary number of vertex and fragment shaders. Add new `IMAGE_OP_SET_SHADER` to specify window specific shader on a texture. Use this shader on compose.
ae24fce
to
4658613
Compare
Codecov Report
@@ Coverage Diff @@
## next #507 +/- ##
==========================================
- Coverage 37.72% 36.96% -0.77%
==========================================
Files 46 46
Lines 9049 9307 +258
==========================================
+ Hits 3414 3440 +26
- Misses 5635 5867 +232
|
Implemented shader file loading and removed support for inline shader source. We need a way to reliably mark windows with a custom shader as damaged (as the shader might change any of the window's pixels), mark them to be blended (to not rely on the |
See #295 (comment) for some additional considerations regarding the interface. |
Accept an array of file names? |
@tryone144 hello! is it possible to revive this? I am thinking getting custom shader support into the new backends and enable them by default in v10. |
@yshui I am definitively open to putting more work into this. This was a bit on the back-burner, since I am not too fond of the way the Some additional design considerations:
|
|
Perhaps looking into implementing #726 as part of this should be considered as well? (Or some sort of functionality that would offer easier support of applying a 3D LUT?) I recently came across a tool on the Windows side that allows you apply a 3D LUT to the entire desktop, allowing proper color management for all apps for the first time (instead of the mess that is color management on Windows; though, a similar mess exists on Linux. Allegedly, Wayland has a protocol that allows for full-desktop color management. GNOME apparently plans to implement this protocol for Wayland and a similar feature for X with their Mutter compositor - though it's been stuck in the planning and PR stages for a while). A hacky way to load the 3D lookup table would be to convert it to an inline constant table within the It would probably be cleaner and easier to allow for the loading of a texture-format file (where it becomes the user's responsibility to convert from, for example, a 3D LUT filetype to a supported texture format file) or, if it's easier for now, implementing 3D LUT loading and application as a separate flag. Adding 3D LUTs support for color management would be a great feature to add for the compositor. I'm told 3D LUT color management is superior to I believe this would be the first time 3D LUTs would be supported on a standalone X compositor; the only other (Linux) compositor that supports this is apparently this plugin for compiz. Edit: Looks like I mispoke. According to the README of Second edit: There is this unmerged pull request into KWin/Plasma's compositor that may be useful as a reference (for ICC profile loading to create a 3D LUT - though I prefer the pipeline of using a dedicated LUT maker such as DisplayCal's 3DLUTMaker and supplying a .cube 3D LUT (same format used in Windows' |
Just reading the most recent comment here; does this mean picom will be able to perform proper color space conversions to display sRGB colors accurately on my Adobe RGB monitor? I'd be on board, as long as it's toggleable at runtime so I can take sRGB screenshots - currently my biggest problem with Windows color correction is that the correction shows up in screenshots. Can't hide the entire compositor for screenshots though, because that would also disable transparency and blur and other effects! |
@kwand Yes, custom texture would be a good thing to have, but as a first step I just want to get to feature parity with the old backend. |
@tryone144 I am thinking maybe it would be better to have the custom shader take over everything, and provide the default processing as a utility function. This way, if the user still wants the default processing, it would just be one extra function call; if they don't they won't have to disable them one-by-one by using rules. BTW, I am trying to rebasing this PR. |
Sounds good to me |
Hmm, I don't really like the fact a id -> shader mapping is maintained at 2 places. |
Okay. I would do that myself, but I'm still quite limited on time. If you need any hints, let me know.
It's been a while, but where exactly are those stored? |
@tryone144 There is one in config.c and keeps a map of path -> custom_shader, as well as a map tracking available ids. Then there is one in backend tracking id -> shader. I am thinking adding a |
As long as we keep this consistent across backend destruction and recreation, this might work. I think I used a specific integer id to reference the shaders instead of the path string to avoid sharing and duplicating strings between the configuration and the backend. Letting the frontend track the appropriate backend shader-id returned by some |
Superseded by #851 |
Implementation of an advanced interface for custom window shaders in the new experimental OpenGL backend (see #386). This will offer similar functionality to the existing
glx-fshader-win
option in the legacy backend but should be easier to use and cover more use-cases.WARNING: This is currently just a Proof-of-Concept to gather some feedback on the interface.
This has known bugs and will likely crash with an improper config as some checks are still missing.
Implementation details
The implementation is up for debate. Comments and ideas for improvements welcome!
Configuration
Custom (foreground) window shaders can be supplied with the
window-shader-fg
option.Supported values are either:
inline shader source in single quotes ('
)PWD
when on cli, config file else) / in folderpicom/shaders/
similar to the config-file search pathsThe supplied shader must be a glsl fragment shader and at least consist of the function
vec4 window_shader()
which should return the current pixel for further processing (inversion, alpha-baking, brightness-clamping).Window specific shaders can be specified with the
window-shader-fg-rule
option, similar to howopacity-rule
works. Each entry is one of the supported values fromwindow-shader-fg
separated with a colon (:
) from a window rule.This currently comes with the limitation that the filename and inline source must not contain a colon.
Example configuration to desaturate unfocused windows:
And a file
desaturate.frag
next to the configuration file:Rendering Pipeline
Each specified shader is saved in a hash-map with a unique id. Each managed window has a reference to the configured shader in this hash-map and is updated with the reference of a window rule if specified. Else the configured default (
window-shader-fg
) or a fallback is used.A hash-map is used to prevent loading the same shader multiple times and generating multiple programs for the same shader.
The OpenGL backend initializes programs for each shader in a new hash-map based on the shaders unique id. The
gl_image
struct keeps a reference to one entry in the program hash-map. The referenced program is used in_gl_compose()
to render the image to screen.The backend is extended with a new image operation
IMAGE_OP_SET_SHADER
. This is called on the image beforecompose()
when the window uses a custom shader and should not be called on backends that do not support custom shaders (currently only thegl
backend has support). The correct program is then selected from the hash-map (via id) and referenced in the image.Discussion of new features
Additional step in the rendering pipeline analogous to blurring with
window-shader-bg
. Render the background blur to a temporary texture and call a custom user-supplied shader on this and the original background. This may allow custom effects behind transparent windows or other deformations with background blur.Support for multiple shaders per rule by allowing multiple "shader objects" to be passed. This would allow modularized shaders for advanced use cases (common filters in separate files, custom composition for different rules, i.e. a separate color-key filter with different constants for different windows). This could probably be done by allowing multiple values separated by semi-colons (
;
) in the relevant config-options.The configuration options could be made more robust by explicitly stating
default()
,andinline('#version 333…')
,file('shader.frag')
.Additional uniforms that might be useful:
glx-fshader-win
)Should there be an option to use a completely custom shader and bypass the current pipeline completely?
We currently depend on alpha-baking in the window shader. Color-inversion and brightness-clamping are features specified via user configuration. When we completely replace the window shader, the user must make sure to re-implement these features or else these options would loose their effect.
Todo
glx-fshader-win
time
uniform for animationswindow-shader-fg
option on the commandline