Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[linux] Added EGL headless backend support #7007

Merged
merged 5 commits into from
Nov 17, 2016
Merged

Conversation

brunoabinader
Copy link
Member

Follow-up to the work started by @tiagovignatti in #5843 - thanks Tiago!

This PR implements EGL headless backend, using EGL_DEFAULT_DISPLAY as primary display - thus no need for handling render nodes directly via gbm.

Though we use software rendering via LLVMpipe, we still need a valid display for EGL to be properly initialized. On Travis CI, like the Qt builds, we still need to start Xvfb to obtain a valid display.

I've put some effort attempting to find a working setup for Mesa to have its EGL platform working with a native display that doesn't require a window system, but so far no success. The most promising option, though, comes from this recent Mesa extension - MESA_platform_surfaceless - that promises to provide a native display independent of any native window system. Given this solution already works and is testable via CI, we can pursuit this as a follow-up work.

@mention-bot
Copy link

@brunoabinader, thanks for your PR! By analyzing the history of the files in this pull request, we identified @kkaefer, @tmpsantos and @jfirebaugh to be potential reviewers.

- &clang35_packages [ 'clang-3.5', 'libstdc++-4.9-dev', 'libstdc++6' ]
- &gcc5_packages [ 'gcc-5', 'g++-5' ]
- &egl_packages [ 'libgles2-mesa-dev', 'libgbm-dev' ]
- &glfw_packages [ 'libxrandr-dev', 'libxcursor-dev', 'libxinerama-dev' ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😍

PRIVATE platform/linux/src/headless_backend_egl.cpp
PRIVATE platform/linux/src/headless_display_egl.cpp
)
# XXX: Provide surface-less EGL mesa for CI builds.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remaining todo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - #7020
I'll add that link to the comment 👍

EGLDisplay display_ = display->attribute<EGLDisplay>();
EGLConfig& config = display->attribute<EGLConfig&>();

eglBindAPI(EGL_OPENGL_API);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing error handling

EGL_ALPHA_SIZE, 0,
EGL_DEPTH_SIZE, 1,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a note that the configuration here doesn't matter since we're rendering to a framebuffer anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea 👍

EGLDisplay display_ = display->attribute<EGLDisplay>();
EGLConfig& config = display->attribute<EGLConfig&>();

if (!eglBindAPI(EGL_OPENGL_API)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are setting MBGL_USE_GLES2 above, but requesting a desktop OpenGL API here. Did you try requesting EGL_OPENGL_ES_API?

Copy link
Member Author

@brunoabinader brunoabinader Nov 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - I initially used EGL_OPENGL_ES_API, but then I obtained a crash right after when querying for the shading version string.

I believe this happens because when I attempt to use that enum, querying for the version string of my local EGL implementation returns Version: OpenGL ES-CM 1.1 Mesa 10.1.3. From the eglBindAPI documentation, it says eglBindAPI and the corresponding EGL_OPENGL_ES_API and EGL_OPENVG_API api parameters are supported only if the EGL version is 1.2 or greater.

@@ -25,6 +26,15 @@ HeadlessDisplay::Impl::Impl() {
throw std::runtime_error("eglInitialize() failed.\n");
}

if (major >= 1 && minor >= 2) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that fails for EGL 2.0

@@ -25,6 +26,15 @@ HeadlessDisplay::Impl::Impl() {
throw std::runtime_error("eglInitialize() failed.\n");
}

if (major >= 1 && minor >= 2) {
EGLenum api = minor >= 4 ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also problematic works for 1.4, but not for 2.0? If it works, we /always/ want the OpenGL ES API, since that's what we're mainly targeting. We just happen to be largely compatible with Desktop OpenGL due to the limited featureset we're using.

@brunoabinader
Copy link
Member Author

@kkaefer I found the reason why we were unable to compile the shader.

Even though we bind to EGL_OPENGL_ES_API by default, the client version is set to 1 by default when creating the context - which doesn't have support for OpenGL ES Shading Language. Support for shaders only comes with OpenGL ES 2.0.

To fix that, we need to pass EGL_CONTEXT_CLIENT_VERSION, 2 as an attribute inside attrib_list in which we pass to eglCreateContext.

@brunoabinader brunoabinader force-pushed the headless-egl branch 2 times, most recently from 4bb04b0 to 9a4f6cf Compare November 11, 2016 22:20
@brunoabinader
Copy link
Member Author

Heh, this worked better than I've expected: Because we really use OpenGL ES 2.0 client API, I had to append the code snippet below to each of the test shaders from OffscreenTexture.RenderToTexture to account for it:

#ifdef GL_ES
precision mediump float;
#endif

If my assumptions about Android using EGL as backend are correct, then this is probably one step further running core tests on Android.

@brunoabinader
Copy link
Member Author

@kkaefer 🚢 ?

Copy link
Contributor

@kkaefer kkaefer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the only test that runs the render test-suite are the node-bindings, so it seems that we're only testing rendering with OSMesa, but not with EGL or GLX. Can we add on a render test to those as well?

@brunoabinader
Copy link
Member Author

Can we add on a render test to those as well?

This is going to be provided in #7053 👍

Prevents some OpenGL implementations from bailing out.
@brunoabinader brunoabinader force-pushed the headless-egl branch 4 times, most recently from a06ae5a to 2247a0e Compare November 16, 2016 11:17
@brunoabinader
Copy link
Member Author

@kkaefer I've rebased this after #7053 got merged. There are now 4 new Travis CI builds added:

  • EGL:
    • EGL/Node/Clang38/Debug: runs Node render/query tests
    • EGL/GCC5/Release: runs core unit tests
  • GLX:
    • GLX/Node/Clang38/Debug: runs Node render/query tests
    • GLX/GCC5/Release: runs core unit tests

@mikemorris the added Node builds won't affect the release node build. These are just for ensuring our Node render/query test passes using these OpenGL APIs.

addons: *qt4
before_script:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the GLX - Node - Clang 3.8 - Release build currently using RUN_XVFB be switched to these setup scripts instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, forgot about that :)


export -f mapbox_start_xvfb

function mapbox_install_mesa_glx {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed as a separate script for only the QT builds because Mesa is installed in platform/linux/config.cmake for Linux builds, right? Is there any way we could consolidate these into a single script that accepts args to install the necessary version of Mesa?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instructions we set in platform/linux/config.cmake should be sufficient for all things Mapbox GL-wise. However, Qt libraries don't know about our custom libGL.so, so we must tell 'em to use it via LD_LIBRARY_PATH.

Because that's the only reason for having this function, I'm not sure if we should add extra functionality in this. Do we have a need for this elsewhere?

@@ -1,5 +1,5 @@
mason_use(glfw VERSION 3.2.1)
if (WITH_OSMESA OR IS_CI_BUILD)
if(IS_CI_BUILD AND NOT WITH_EGL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused by this - are we installing Mesa somewhere else for EGL CI builds? It appears that we're still setting MASON_MESA_SUFFIX for WITH_EGL builds in CMakeLists.txt.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused by this - are we installing Mesa somewhere else for EGL CI builds?

Yes - we are using the system's mesa install via libgles2-mesa-dev.

It appears that we're still setting MASON_MESA_SUFFIX for WITH_EGL builds in CMakeLists.txt.

That should cause no harm - it's going to be used when we get the EGL surface-less mesa build :)

Original author: Tiago Vignatti <tvignatti@gmail.com>

Calling X11 window system is superfluous for headless rendering. This patch
implements EGL platform using GBM, which is slightly more simple than the GLX
path when using X11.

In principle there are no big advantages in terms of performance etc. My
motivation behind this was to get in touch with the code and the project. For
testing I'm using:

  $ unset DISPLAY && ./build/linux-x86_64/Debug/mbgl-test

v2: rebased patch against the new cmake changes; walk through render node to
find a valid one; remove EGLSurface completely cause windows are not needed
here.
@brunoabinader brunoabinader force-pushed the headless-egl branch 3 times, most recently from 03481a2 to e95ff7e Compare November 16, 2016 17:09
Copy link
Contributor

@jfirebaugh jfirebaugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to put the breaks on here for a sec. We already have quite a few rows in the Travis matrix, and frequently bump up against our built limits, leading to time waiting for the queue to clear.

Can we think about ways to make the matrix smaller?

@brunoabinader brunoabinader force-pushed the headless-egl branch 2 times, most recently from e90a379 to 65d541c Compare November 16, 2016 18:11
@brunoabinader
Copy link
Member Author

Can we think about ways to make the matrix smaller?

@jfirebaugh we've reduced the build matrix to 10 items.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants