rust-windowing / glutin

A low-level library for OpenGL context creation
Apache License 2.0
2k stars 477 forks source link

sRGB findings on various platforms #1652

Open MarijnS95 opened 10 months ago

MarijnS95 commented 10 months ago

For the past while I've been working on and off on turning the current sRGB colorspace support into full-fledged color space support, with a focus on EGL (Wayland desktop and Android phones). As it turns out there are quite a few backend differences that only make this feasible for the EGL backend. But before we get into some design questions I'd like to ask (separate issue), let's first look at sRGB as every backend and implementation has already gotten me totally confused. This is not really a Glutin issue but more of a general OpenGL ecosystem mess, though it might definitely be relevant to keep our implementation and documentation in check so I'm sharing it anyway.

The following was tested on a:

Preface

Android EGL

:+1:, all working as expected.

Wayland EGL (AMD Mesa)

Wayland EGL (AMD ProGL)

(using progl command)

X11 (AMD Mesa)

X11 (AMD ProGL)

Wayland EGL (Intel UHD 620 on Mesa)

X11 (Intel UHD 620 on Mesa)

Windows (RX 6800 XT)

kchibisov commented 10 months ago

Changing the color space via EGL_GL_COLORSPACE makes no difference (color stays the same, COLOR_ENCODING always returns GL_SRGB);

SRGB setting in EGL is mostly when you're dealing with GLES context and not OpenGL from what I understand, because you can't manipulate with attachment function in OpenGL.

Setting EGL_COLORSPACE has no effect

It should have it with gles context..

I'm not that familiar with real OpenGL use.

MarijnS95 commented 10 months ago

SRGB setting in EGL is mostly when you're dealing with GLES context and not OpenGL from what I understand, because you can't manipulate with attachment function in OpenGL.

Should be available on both afaik: https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_image_gl_colorspace.txt

Setting EGL_COLORSPACE has no effect

It should have it with gles context..

I'm not that familiar with real OpenGL use.

Oh no, more variables; maybe I should retest this all again and put the results in a big table that's a bit more clear. More on that later.


Replying to the rest of your sRGB comments from https://github.com/rust-windowing/glutin/issues/1653#issuecomment-1858715266 here:

There does not seem to be a way to query which color spaces a certain config/surface supports, [..]

This is present because some platform determine the framebuffer type at the surface/context creation time and you can't switch at runtime.

Do you imply from *FRAMEBUFFER_SRGB_CAPABLE_ARB/EXT that the framebuffer must be an SRGB texture? Renderdoc seems to agree with that thought but https://registry.khronos.org/OpenGL/extensions/ARB/ARB_framebuffer_sRGB.txt seems to suggest that it only exposes whether sRGB blending/conversion is available (which only makes sense on sRGB surfaces, so implying that it's sRGB)?

As outlined in this issue that sRGB blending/conversion seems to be applied to non-sRGB-capable configs. And COLOR_ENCODING is not always representing the actual value of a texture. Do you think I am querying it correctly?

gl.GetFramebufferAttachmentParameteriv(
    gl::FRAMEBUFFER,
    gl::FRONT,
    gl::FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING,
    &mut ce
);

Basically GLES and that's why we have those checks, mostly. Since when you have OpenGL context you don't have GL_ARB_framebuffer_sRGB.

Isn't it the other way around? GL_ARB_framebuffer_sRGB is in the OpenGL extensions but not in ES. They have https://registry.khronos.org/OpenGL/extensions/EXT/EXT_sRGB.txt and https://registry.khronos.org/OpenGL/extensions/EXT/EXT_sRGB_write_control.txt.

After all I also had to switch gl_generator from Api::Gles to Api::Gl to use that extension and get the constant for FRAMEBUFFER_SRGB.

kchibisov commented 10 months ago

Should be available on both afaik

Hm, I know that with gles you can't change buffer colorspace at runtime, at least with gles2, maybe you can with gles3. It should be testable if you pick ES context and play with srgb on a surface, though, you likely did that already.

Do you imply from *FRAMEBUFFER_SRGB_CAPABLE_ARB/EXT that the framebuffer must be an SRGB texture?

Not sure what you mean. I was saying that some platforms define buffer type at surface creation, e.g. EGLSurface with gles2 context. That's the only reason we have sRGB API on a surface creation.

MarijnS95 commented 10 months ago

Hm, I know that with gles you can't change buffer colorspace at runtime, at least with gles2, maybe you can with gles3. It should be testable if you pick ES context and play with srgb on a surface, though, you likely did that already.

I can get an ES 3.2 and OpenGL 4.6 context on the RX 6800 XT from Mesa. Via Wayland EGL, on OpenGL 4.6, as above FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING always returns GL_SRGB. However, renderdoc says that it is R8G8B8A8_UNORM as opposed to _SRGB when I set EGL_GL_COLORSPACE to GL_COLORSPACE_LINEAR. GL_FRAMEBUFFER_SRGB always facilitates a conversion though, the image looks the same regardless of the colorspace.

(Maybe I am reading FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING from the wrong place?)

On GLES3 on the same Mesa driver it works better: the linear->sRGB conversion only happens when I set EGL_GL_COLORSPACE to EGL_COLORSPACE_sRGB. Renderdoc also confirms SRGB vs UNORM as texture format.

On GLX on this Mesa driver I get identical behaviour.

Not sure what you mean. I was saying that some platforms define buffer type at surface creation, e.g. EGLSurface with gles2 context. That's the only reason we have sRGB API on a surface creation.

Only EGL does this, WGL has a way to set it on the config, GLX doesn't expose any parameters.


I think I should leave this here and focus on EGL colorspace support, instead of messing with broken sRGB support :)

MarijnS95 commented 10 months ago

https://registry.khronos.org/EGL/specs/eglspec.1.5.pdf

Only OpenGL and OpenGL ES contexts which support sRGB rendering must respect requests for EGL_GL_COLORSPACE_SRGB, and only to sRGB formats supported by the context (normally just SRGB8) Older versions not supporting sRGB rendering will ignore this surface attribute. Applications using OpenGL must additionally enable GL_FRAMEBUFFER_SRGB to perform sRGB rendering, even when an sRGB surface is bound; this enable is not required (or supported) for OpenGL ES.


Strange because I need that flag on ES to get sRGB conversion working :sweat_smile: