Commit fd08a959 by Corentin Wallez Committed by Commit Bot

DisplayGLX: make the Mesa context creation workaround Mesa specific.

BUG=598902 Change-Id: Ib2ca69fb3573dbd0df3dafb4caec0500c7a8aa3b Reviewed-on: https://chromium-review.googlesource.com/347071Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent 00ed7a1f
...@@ -18,7 +18,7 @@ struct Optional ...@@ -18,7 +18,7 @@ struct Optional
mValue(T()) mValue(T())
{} {}
explicit Optional(const T &valueIn) Optional(const T &valueIn)
: mValid(true), : mValid(true),
mValue(valueIn) mValue(valueIn)
{} {}
......
...@@ -23,6 +23,8 @@ struct Version ...@@ -23,6 +23,8 @@ struct Version
GLuint minor; GLuint minor;
}; };
bool operator==(const Version &a, const Version &b);
bool operator!=(const Version &a, const Version &b);
bool operator>=(const Version &a, const Version &b); bool operator>=(const Version &a, const Version &b);
bool operator<(const Version &a, const Version &b); bool operator<(const Version &a, const Version &b);
......
...@@ -20,6 +20,16 @@ inline Version::Version(GLuint major_, GLuint minor_) ...@@ -20,6 +20,16 @@ inline Version::Version(GLuint major_, GLuint minor_)
minor = minor_; minor = minor_;
} }
inline bool operator==(const Version &a, const Version &b)
{
return a.major == b.major && a.minor == b.minor;
}
inline bool operator!=(const Version &a, const Version &b)
{
return !(a == b);
}
inline bool operator>=(const Version &a, const Version &b) inline bool operator>=(const Version &a, const Version &b)
{ {
return a.major > b.major || (a.major == b.major && a.minor >= b.minor); return a.major > b.major || (a.major == b.major && a.minor >= b.minor);
......
...@@ -161,6 +161,9 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -161,6 +161,9 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile"); mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile"); mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile");
std::string clientVendor = mGLX.getClientString(GLX_VENDOR);
mIsMesa = clientVendor.find("Mesa") != std::string::npos;
// Choose the swap_control extension to use, if any. // Choose the swap_control extension to use, if any.
// The EXT version is better as it allows glXSwapInterval to be called per // The EXT version is better as it allows glXSwapInterval to be called per
// window, while we'll potentially need to change the swap interval on each // window, while we'll potentially need to change the swap interval on each
...@@ -351,13 +354,6 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -351,13 +354,6 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
syncXCommands(); syncXCommands();
std::string rendererString =
reinterpret_cast<const char*>(mFunctionsGL->getString(GL_RENDERER));
mIsMesa = rendererString.find("Mesa") != std::string::npos;
std::string version;
getDriverVersion(&version);
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -472,76 +468,84 @@ egl::Error DisplayGLX::initializeContext(glx::FBConfig config, ...@@ -472,76 +468,84 @@ egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
// It is commonly assumed that glXCreateContextAttrib will create a context // It is commonly assumed that glXCreateContextAttrib will create a context
// of the highest version possible but it is not specified in the spec and // 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 // is not true on the Mesa drivers. On Mesa, Instead we try to create a
// GL version until we succeed, starting from newer version. When the default // context per GL version until we succeed, starting from newer version.
// platform is selected, if no desktop context can be created, we fallback to // On both Mesa and other drivers we try to create a desktop context and fall
// an ES context. // back to ES context.
// clang-format off // The code could be simpler if the Mesa code path was used for all drivers,
const gl::Version desktopVersionsFrom3_2[] = { // however the cost of failing a context creation can be high (3 milliseconds
gl::Version(4, 5), // for the NVIDIA driver). The good thing is that failed context creation only
gl::Version(4, 4), // takes 0.1 milliseconds on Mesa.
gl::Version(4, 3),
gl::Version(4, 2), struct ContextCreationInfo
gl::Version(4, 1), {
gl::Version(4, 0), EGLint displayType;
gl::Version(3, 3), int profileFlag;
gl::Version(3, 2), Optional<gl::Version> version;
}; };
const gl::Version desktopVersionsPre3_2[] = {
gl::Version(3, 1), // clang-format off
gl::Version(3, 0), // For regular drivers we try to create a core, compatibility, then ES context.
gl::Version(2, 0), // Without requiring any specific version (the Optional version is undefined).
gl::Version(1, 5), const ContextCreationInfo contextsToTry[] = {
gl::Version(1, 4), { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, {} },
gl::Version(1, 3), { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, {} },
gl::Version(1, 2), { EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, {} },
gl::Version(1, 1),
gl::Version(1, 0),
}; };
const gl::Version esVersionsFrom2_0[] = {
gl::Version(3, 2), // On Mesa we try to create a core context, except for versions below 3.2
gl::Version(3, 1), // where it is not applicable. (and fallback to ES as well)
gl::Version(3, 0), const ContextCreationInfo mesaContextsToTry[] = {
gl::Version(2, 0), { EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 5) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 4) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 3) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 2) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 1) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(4, 0) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 3) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { gl::Version(3, 2) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 1) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(3, 0) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(2, 0) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 5) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 4) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 3) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 2) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 1) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, { gl::Version(1, 0) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 2) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 1) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(3, 0) } },
{ EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { gl::Version(2, 0) } },
}; };
// clang-format on // clang-format on
const ContextCreationInfo *toTry = contextsToTry;
size_t toTryLength = ArraySize(contextsToTry);
if (mIsMesa)
{
toTry = mesaContextsToTry;
toTryLength = ArraySize(mesaContextsToTry);
}
// NOTE: below we return as soon as we're able to create a context so the // NOTE: below we return as soon as we're able to create a context so the
// "error" variable is EGL_SUCCESS when returned contrary to the common idiom // "error" variable is EGL_SUCCESS when returned contrary to the common idiom
// of returning "error" when there is an actual error. // of returning "error" when there is an actual error.
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) for (size_t i = 0; i < toTryLength; ++i)
{
for (auto &version : desktopVersionsFrom3_2)
{
egl::Error error =
createContextAttribs(config, version, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, context);
if (!error.isError())
{
return error;
}
}
for (auto &version : desktopVersionsPre3_2)
{ {
egl::Error error = createContextAttribs(config, version, 0, context); const ContextCreationInfo &info = toTry[i];
if (!error.isError()) if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE &&
requestedDisplayType != info.displayType)
{ {
return error; continue;
}
}
} }
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context);
{
for (auto &version : esVersionsFrom2_0)
{
egl::Error error =
createContextAttribs(config, version, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, context);
if (!error.isError()) if (!error.isError())
{ {
return error; return error;
} }
} }
}
return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context."); return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
} }
...@@ -903,16 +907,20 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const ...@@ -903,16 +907,20 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
} }
egl::Error DisplayGLX::createContextAttribs(glx::FBConfig, egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
gl::Version version, const Optional<gl::Version> &version,
int profileMask, int profileMask,
glx::Context *context) const glx::Context *context) const
{ {
std::vector<int> attribs; std::vector<int> attribs;
if (version.valid())
{
attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
attribs.push_back(version.major); attribs.push_back(version.value().major);
attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
attribs.push_back(version.minor); attribs.push_back(version.value().minor);
}
if (profileMask != 0 && mHasARBCreateContextProfile) if (profileMask != 0 && mHasARBCreateContextProfile)
{ {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/Optional.h"
#include "libANGLE/renderer/gl/DisplayGL.h" #include "libANGLE/renderer/gl/DisplayGL.h"
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h" #include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
...@@ -104,7 +105,7 @@ class DisplayGLX : public DisplayGL ...@@ -104,7 +105,7 @@ class DisplayGLX : public DisplayGL
int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const; int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
egl::Error createContextAttribs(glx::FBConfig, egl::Error createContextAttribs(glx::FBConfig,
gl::Version version, const Optional<gl::Version> &version,
int profileMask, int profileMask,
glx::Context *context) const; glx::Context *context) const;
......
...@@ -45,6 +45,7 @@ struct FunctionsGLX::GLXFunctionTable ...@@ -45,6 +45,7 @@ struct FunctionsGLX::GLXFunctionTable
getCurrentDrawablePtr(nullptr), getCurrentDrawablePtr(nullptr),
waitXPtr(nullptr), waitXPtr(nullptr),
waitGLPtr(nullptr), waitGLPtr(nullptr),
getClientStringPtr(nullptr),
queryExtensionsStringPtr(nullptr), queryExtensionsStringPtr(nullptr),
getFBConfigsPtr(nullptr), getFBConfigsPtr(nullptr),
chooseFBConfigPtr(nullptr), chooseFBConfigPtr(nullptr),
...@@ -75,6 +76,7 @@ struct FunctionsGLX::GLXFunctionTable ...@@ -75,6 +76,7 @@ struct FunctionsGLX::GLXFunctionTable
PFNGLXWAITGLPROC waitGLPtr; PFNGLXWAITGLPROC waitGLPtr;
// GLX 1.1 // GLX 1.1
PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr; PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;
//GLX 1.3 //GLX 1.3
...@@ -175,6 +177,7 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS ...@@ -175,6 +177,7 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL); GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);
// GLX 1.1 // GLX 1.1
GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString); GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);
// Check we have a working GLX // Check we have a working GLX
...@@ -314,6 +317,11 @@ void FunctionsGLX::waitGL() const ...@@ -314,6 +317,11 @@ void FunctionsGLX::waitGL() const
} }
// GLX 1.1 // GLX 1.1
const char *FunctionsGLX::getClientString(int name) const
{
return mFnPtrs->getClientStringPtr(mXDisplay, name);
}
const char *FunctionsGLX::queryExtensionsString() const const char *FunctionsGLX::queryExtensionsString() const
{ {
return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen); return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
......
...@@ -49,6 +49,7 @@ class FunctionsGLX ...@@ -49,6 +49,7 @@ class FunctionsGLX
void waitGL() const; void waitGL() const;
// GLX 1.1 // GLX 1.1
const char *getClientString(int name) const;
const char *queryExtensionsString() const; const char *queryExtensionsString() const;
// GLX 1.3 // GLX 1.3
......
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