wlroots
wlroots copied to clipboard
Blending currently gamma-incorrect
Maybe i'm missing something but it seems to me that wlroots (and weston, compton, ...) actually do blending of surfaces incorrectly. Investigated with rootston.
This is how blending with rootston (and sway and every compositor that builds upon wlroots) looks today (two different surfaces overlapping, the top one with low alpha):
I haven't followed the wayland colorspace discussion too closely but i guess we assume that all input we get from clients is roughly in srgb space, right? At least that's what pretty much every program out there outputs. But we don't transform it back to linear space before blending surfaces. That means we blend in srgb space, which is wrong and looks bad. An article that explains it nicely is this: http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/ (see especially the section about blending).
I noticed this when writing the vulkan renderer and had to select a colorspace for images and framebuffer (vulkan is explicit about it) so i tried interpreting textures as srgb and also output srgb (which means that when sampling we get the image data in linear space and also blend in linear space) which gives this result:
The thing is, pretty much every compositor out there does it like wlroots at the moment so this is probably rather a discussion about expected behavior. Below are compton on i3 and weston with the same two example surfaces:
I guess it's obvious in this case which result is "correct" though. If we change this we should probably at least provide an option for the user to choose since wlroots would then be doing it differently than everyone out there and everything with alpha looks quite a bit different. If this is really an issue and not just a misunderstanding on my side, we should probably discuss it with the weston folks as well. Although i only tried it with vulkan, a patch for opengl shouldn't be much harder (make the framebuffer srgb and interpret textures as srgb), i could dive into that.
Do you agree that it currently is an issue? If so, how should we handle it? My idea would be to allow to choose on renderer creation whether or not it should blend correctly or use the legacy mode for compatibility. And then compositors can expose that in their configuration somehow. It's probably more of a temporary solution anyways until wayland gets more elaborate colorspace negotiation support.
wlroots has migrated to gitlab.freedesktop.org. This issue has been moved to:
https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/1703
It's actually really vague as to whether a client buffer is in sRGB or linear RGB. It's not actually defined anywhere. I think the prevailing assumption that everything is in linear RGB, but it's more likely than not that people just didn't really think about it that much (well, at least I didn't). I think that colour management protocol being discussed is the solution to this.
Proper colour management and blending is definitely something I agree that we should be working towards.
hm ok let's wait for the color management protocol then, hopefully it'll clear things up.
Just FYI, most clients simply assume sRGB and most monitors are somewhere near sRGB so even color managed applications produce images with near sRGB gamma. In the absence of a color management protocol blending should assume sRGB and apply degamma before blending.
I think I stumbled on this specification hole while writing a client application with transparent backgrounds. In my case, blending seems to require premultiplied alpha in the wl_surface
to produce the normal over operator. Is this expected?
I'll be waiting for the color management protocol to settle down and define this clearly. Until this happens, is there any sort of documentation or source reference that shows how wlroots does it?
blending seems to require premultiplied alpha in the wl_surface to produce the normal over operator. Is this expected?
Yes.
Ref EXT_sRGB for the GL side of things
Can confirm that unless otherwise specified clients send sRGB, not linear.
@nyorain, do you have the source of your test client somewhere?
GL_EXT_sRGB
is usable during texture uploads, however it can't be used when importing DMA-BUFs. So we can't use it to gamma-decode textures coming from clients and gamma-encode FBOs.
I was about to give up, but then found out about EGL_KHR_gl_colorspace
and EGL_EXT_image_gl_colorspace
. I'll try to see whether it helps.
Another option is to manually write up the gamma encoding/decoding in the shaders, however that will have a performance impact.
@nyorain, do you have the source of your test client somewhere?
It's here but it's old and you are probably better off just pasting the drawing code into your own sample framework.
Another option is to manually write up the gamma encoding/decoding in the shaders, however that will have a performance impact.
Using hardware decoding would be nice but the performance impact shouldn't be too huge either way, it's not much more than a pow (see e.g. here for an efficient implementation) and often done manually in GL. In Vulkan, we should be able to import as SRGB.
I've incorporated the test pattern from the article your linked above into wleird: https://github.com/emersion/wleird/commit/06664c180c028068e5cf7ae19317fea209d4a209