Commit 31e60cf2 by Corentin Wallez

DisplayGLX: rework how glXCreateContextAttribsARB is called

This patch adds handling of the EGL ANGLE platform api version display attributes for better testing. It makes the code more resilient by ignoring X11 errors that could crash our program in the call to glXCreateContextAttribsARB. It also makes sure that we always choose the most recent OpenGL version available on the system. BUG=angleproject:1188 Change-Id: I26e1bf6733215db6f5841b54c471f644e2b15e89 Reviewed-on: https://chromium-review.googlesource.com/309633Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 3e14e2b1
...@@ -21,6 +21,11 @@ ...@@ -21,6 +21,11 @@
namespace rx namespace rx
{ {
static int IgnoreX11Errors(Display *, XErrorEvent *)
{
return 0;
}
class FunctionsGLGLX : public FunctionsGL class FunctionsGLGLX : public FunctionsGL
{ {
public: public:
...@@ -137,7 +142,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -137,7 +142,7 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
XFree(candidates); XFree(candidates);
} }
mContext = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, nullptr); mContext = initializeContext(mContextConfig, display->getAttributeMap());
if (!mContext) if (!mContext)
{ {
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context."); return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
...@@ -246,6 +251,83 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device) ...@@ -246,6 +251,83 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device)
return egl::Error(EGL_BAD_DISPLAY); return egl::Error(EGL_BAD_DISPLAY);
} }
glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
const egl::AttributeMap &eglAttributes)
{
// Create a context of the requested version, if any.
EGLint requestedMajorVersion =
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
EGLint requestedMinorVersion =
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
{
std::vector<int> contextAttributes;
contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
contextAttributes.push_back(requestedMajorVersion);
contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
contextAttributes.push_back(requestedMinorVersion);
contextAttributes.push_back(None);
return createContextAttribs(config, contextAttributes);
}
// It is commonly assumed that glXCreateContextAttrib will create a context
// of the highest version possible but it is not specified in the spec and
// is not true on the Mesa drivers. Instead we try to create a context per
// desktop GL version until we succeed, starting from newer version.
// clang-format off
const gl::Version desktopVersions[] = {
gl::Version(4, 5),
gl::Version(4, 4),
gl::Version(4, 3),
gl::Version(4, 2),
gl::Version(4, 1),
gl::Version(4, 0),
gl::Version(3, 3),
gl::Version(3, 2),
gl::Version(3, 1),
gl::Version(3, 0),
gl::Version(2, 0),
gl::Version(1, 5),
gl::Version(1, 4),
gl::Version(1, 3),
gl::Version(1, 2),
gl::Version(1, 1),
gl::Version(1, 0),
};
// clang-format on
bool useProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
for (size_t i = 0; i < ArraySize(desktopVersions); ++i)
{
const auto &version = desktopVersions[i];
std::vector<int> contextAttributes;
contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
contextAttributes.push_back(version.major);
contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
contextAttributes.push_back(version.minor);
if (useProfile && version >= gl::Version(3, 2))
{
contextAttributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
contextAttributes.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
}
contextAttributes.push_back(None);
auto context = createContextAttribs(config, contextAttributes);
if (context)
{
return context;
}
}
return nullptr;
}
egl::ConfigSet DisplayGLX::generateConfigs() const egl::ConfigSet DisplayGLX::generateConfigs() const
{ {
egl::ConfigSet configs; egl::ConfigSet configs;
...@@ -477,4 +559,15 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const ...@@ -477,4 +559,15 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
return result; return result;
} }
glx::Context DisplayGLX::createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const
{
// When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
// be generated. To prevent these errors from crashing our process, we simply ignore
// them and only look if GLXContext was created.
auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
auto context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
XSetErrorHandler(oldErrorHandler);
return context;
}
} }
...@@ -62,10 +62,13 @@ class DisplayGLX : public DisplayGL ...@@ -62,10 +62,13 @@ class DisplayGLX : public DisplayGL
private: private:
const FunctionsGL *getFunctionsGL() const override; const FunctionsGL *getFunctionsGL() const override;
glx::Context initializeContext(glx::FBConfig config, const egl::AttributeMap &eglAttributes);
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const; int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
glx::Context createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const;
FunctionsGL *mFunctionsGL; FunctionsGL *mFunctionsGL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment