GL_FRAMEBUFFER_SRGB functions incorrectly

The GL implementation doesn’t seem to handle sRGB framebuffers correctly. If you ask for a default framebuffer with sRGB encoding (GL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GLFW_SRGB_CAPABLE, SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, etc) the framebuffer you are given does not appear to be sRGB. If you query for GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING it will always return GL_LINEAR, not GL_SRGB like you would expect. Secondly, if you enable GL_FRAMEBUFFER_SRGB then you will get sRGB conversion happening regardless of whether or not you specify the framebuffer to be sRGB. The correct behavior is for sRGB conversion to take place only if GL_FRAMEBUFFER_SRGB is enabled and the framebuffer format is sRGB.

I can only test this on 340.76 at the moment but I suspect this effects all versions. Frankly I am really surprised that this hasn’t been caught already.
WGLTestSRGB.cpp (6.63 KB)

The default framebuffer is provided by the windowing system so the blame should not solely lay on Nvidia. I saw GLFW_SRGB_CAPABLE, which I’m going to assume is a GLFW flags, who is to say that GLFW is selecting the correct pixel format that support sRGB. Have you verified the behavior with a non-system default frame buffer object created with a sRGB attachment?

This isn’t a GLFW issue. The same thing happens if you create the window and context with other APIs like SDL and WGL. If I create a FBO with GL_SRGB and query the encoding it returns GL_SRGB, so it appears that this issue may only be for the default framebuffer. Then again I cannot really tell whether or not sRGB conversion is being applied correctly to the FBO as I need to blit it to the default framebuffer, which isn’t working correctly.

I’ve filed an internal bugreport for the OpenGL driver team to investigate this.

Could you please add some additional information on your system setup:
OS version, OS bitness, installed GPUs?

It would be helpful if you could attach the WGL version of a minimal reproducer source code which shows the two issues you’re describing.
Hover with the mouse over one of your submitted posts and click the paper clip icon in the upper right corner to attach files.

I’ve added a file to my original post. Hopefully it will suffice.

My system info is:

OS: Windows 7 64-bit
GPU: NV GTX 760
Driver: 340.76 & 340.82

Thanks for the additional information.

From looking over the WGLtestSRGB.cpp file there seems to be a problem with the number of times you use SetPixelFormat() on your window. It’s not allowed to call SetPixelFormat() more than once per window. See
http://msdn.microsoft.com/en-us/library/windows/desktop/dd369049%28v=vs.85%29.aspx

Please change the pixelformat selection to use a temporary dummy window to get the wglChoosePixelformatARB() function pointer and set the intended pixelformat on the main application window only once.

If that still reproduces the problem, please replace the reproducer.

I will attach an updated file to this post.

If there are no bugs then what should happen is that the first window should be accompanied by a message box that says “GL_SRGB”. This window is created with WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB = TRUE and GL_FRAMEBUFFER_SRGB enabled, so the color value for the window should be close to (188, 188, 188).

The second window is created with WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB = FALSE and GL_FRAMEBUFFER_SRGB enabled. You should get a message box that says “GL_LINEAR” and the color value for the window should be (127, 127, 127).

I get “GL_LINEAR” for both windows and I get a color value of (188, 188, 188) for both windows.

I apologize that this code isn’t the best. I don’t normally work with Win32 or WGL.
WGLTestSRGB-2.cpp (7.59 KB)

No problem. Thanks for the updated reproducer.
I’ve added the additional information to the bug report for investigation.

Did this ever get fixed?
Because on Linux, after requesting an SRGB capable context using SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, I still see that:

GLint encoding=-1;
    glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding);
    if (encoding == GL_LINEAR)
        LOGW("Framebuffer attachment color encoding is linear.");
    if (encoding == GL_SRGB)
        LOGI("Framebuffer attachment color encoding is sRGB.");

will return a linear encoding.

Note: the returned parameter reports linear, but the framebuffer itself is actually SRGB.
So it’s the reporting that seems off, not the actual SRGB operation.

I Experience similar issues:

  • reports linear despite GLX context created with GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, both in OpenGL ES 3.2 context and in 4.6.0 context. Driver 396.24.

Unfortunately, it is not only a reporting error. In OpenGL ES 3.2 it is not working correctly. I setup a SRGB framebuffer, clear to black, and an SRGB texture with all texels set to (R=1,G=1,B=1,A=255). When rendering the texture on a quad. The result shows just a black window.

In OpenGL 4.6.0 however (same driver), it shows correctly: a dark-grey quad rendered on the black window.

Minimal example code can be found here:

Hope this will be fixed soon.

I just tested render to an FBO, and then render that FBO to the default framebuffer using a shader that converts linear to sRGB and then it looks correct in OpenGL ES context. I have pushed this change to the git repo: https://github.com/julienaubert/glsrgb

So it is definitely the default framebuffer in OpenGL ES context that is not working as it should.