In GLX and EGL, contexts are created with respect to a config that describes the type of surfaces they will be used to render to. Likewise surfaces are created with respect to a config and for a context to be able to render to a surface, both their configs must be compatible. Compatibility is losely described in both the GLX and EGL specs but the following is clear:
Obviously the EGLconfig we will expose will have a one-to-one correspondance with GLXFBConfigs.
Our EGL implementation uses a single OpenGL context to back all the EGLcontexts created by the application. Since our GL context and GLXContext are the same object but in two APIs, we will make the confusion and call the GLX context our backing context.
The problem we have is that the the GLX context is created before the application can choose what type of context it wants to use, that means we have to expose EGLconfigs whose respective GLXFBConfigs are compatible with the GLXFBConfig of our GLX context; we also need to choose the GLXFBConfig of our GLX context so that it matches the most common needs of application.
We decided that our GLX context's configuration must satisfy the following:
WINDOW_BIT
set.When using the condition of compatibility defined in the GLX spec and filtering out the non-conformant GLXFBConfig we got the following list (see function print_visual_attribs_short
in glxinfo's source code to understand how to read the table):
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat Result ---------------------------------------------------------------------------- 0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail 0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch 0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass 0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None BadMatch 0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail 0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass 0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail 0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch 0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass 0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None BadMatch 0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail 0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
The last column shows the result of trying to render on a window using the config, with a GLX context using config 0x024. The first thing we see is that BadMatch is thrown by the X server when creating the subwindow for rendering. This was because we didn't set the border pixel of the subwindow shake fist at X11 (see this StackOverflow question). The result updated with this fix give:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x02e 24 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail 0x0e4 32 tc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail 0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass 0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass 0x089 24 dc 0 32 0 r . . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Fail 0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None Pass 0x026 24 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail 0x0dc 32 tc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail 0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass 0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass 0x081 24 dc 0 32 0 r . . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Fail 0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None Pass
From this we see that our rendering test passed if and only if the config was double buffered like 0x024 which is our GLX context config. The compatible configs are then:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x02c 24 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None 0x0e2 32 tc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None 0x087 24 dc 0 32 0 r y . 8 8 8 8 . s 4 0 0 16 16 16 16 0 0 None 0x024 24 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None 0x0da 32 tc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None 0x07f 24 dc 0 32 0 r y . 8 8 8 8 . s 4 24 8 16 16 16 16 0 0 None
We can see two dimensions, with our without a depth-stencil buffer and with TrueColor or DirectColor. The depth-stencil will be useful to expose to application.
The tests above show that double-buffered contexts are not compatible with single- buffered surfaces; however other tests show that single-buffered contexts are compatible with both single and double-buffered surfaces. The problem is that in that case, we can see some flickering even with double-buffered surfaces. If we can find a trick to avoid that flicker, then we would be able to expose single and double-buffered surfaces at the EGL level. Not exposing them isn't too much of a problem though as the vast majority of application want double-buffering.
As can be seen above, NVIDIA does not expose conformant context with multisampled buffers or non RGBA16 accumulation buffers. The behavior is different on AMD that exposes them as conformant, which gives the following list after filtering as explained above:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x023 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None 0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x02b 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None 0x02f 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None 0x03b 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 16 16 16 16 0 0 None 0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x043 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 2 1 None 0x047 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 4 1 None
ANGLE‘s context is created using 0x027 and experimentation shows it is only compatible with 0x03f which is the only other config lacking both an accumulation buffer and a multisample buffer. The GLX spec seems to hint it should still work (“should have the same size, if they exist”) but it doesn’t work in this case. Filtering the configs to have the same multisample and accumulation buffers gives the following:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x027 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x03f 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
In GLX, a criterium for context and surface compatibility is that buffers should have the same depth, if they exist at all in the surface. This means that it should be possible to make a context with a D24S8 depth-stencil buffer to a surface without a depth-stencil buffer. This doesn't work on the Mesa Intel driver. The list before the workaround was the following, with 0x020 being the fbconfig chosen for the context:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x0d0 24 tc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None 0x0e2 24 dc 0 32 0 r y . 8 8 8 8 . . 0 0 0 0 0 0 0 0 0 None 0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
After the workaround that list becomes the following:
visual x bf lv rg d st colorbuffer sr ax dp st accumbuffer ms cav id dep cl sp sz l ci b ro r g b a F gb bf th cl r g b a ns b eat ---------------------------------------------------------------------------- 0x020 24 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x021 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x08f 32 tc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None 0x0e9 24 dc 0 32 0 r y . 8 8 8 8 . . 0 24 8 0 0 0 0 0 0 None
All the non-conformant configs have a multisampled buffer, so it could be interesting to see if we can use them to expose another EGL extension.
Finally this document is written with respect to a small number of drivers, before using the GLX EGL implementation in the wild it would be good to test it on other drivers and hardware.
The drivers tested were: