Commit 80cdc376 by Corentin Wallez Committed by Commit Bot

DisplayWGL: try all GL context version from the highest

The only way to get a core profile context of the highest version using CreateContextAttrib is to try creationg contexts in decreasing version numbers. It might look that asking for a core context of version (0, 0) works on some driver but it create a _compatibility_ context of the highest version instead which might not be supported on some drivers. BUG=angleproject:1994 Change-Id: Ic8a33243909c54ea5940ee81c9c866b141bea420 Reviewed-on: https://chromium-review.googlesource.com/480739 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 63fa2e94
...@@ -425,65 +425,22 @@ egl::Error DisplayGLX::initializeContext(glx::FBConfig config, ...@@ -425,65 +425,22 @@ egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
// Also try to get any Desktop GL context, but if that fails fallback to // Also try to get any Desktop GL context, but if that fails fallback to
// asking for OpenGL ES contexts. // asking for OpenGL ES contexts.
struct ContextCreationInfo
{
ContextCreationInfo(EGLint displayType, int profileFlag, gl::Version version)
: displayType(displayType), profileFlag(profileFlag), version(version)
{
}
EGLint displayType;
int profileFlag;
gl::Version version;
};
// clang-format off
std::vector<ContextCreationInfo> contextsToTry;
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 5));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 4));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 3));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 2));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 1));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(4, 0));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(3, 3));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, gl::Version(3, 2));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 3));
// On Mesa, do not try to create OpenGL context versions between 3.0 and
// 3.2 because of compatibility problems. See crbug.com/659030
if (!mIsMesa)
{
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 2));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 1));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(3, 0));
}
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(2, 1));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(2, 0));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 5));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 4));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 3));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 2));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 1));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, 0, gl::Version(1, 0));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 2));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 1));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(3, 0));
contextsToTry.emplace_back(EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, gl::Version(2, 0));
// clang-format on
// 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.
for (const auto &info : contextsToTry) for (const auto &info : GenerateContextCreationToTry(requestedDisplayType, mIsMesa))
{ {
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE && int profileFlag = 0;
requestedDisplayType != info.displayType) if (info.type == ContextCreationTry::Type::DESKTOP_CORE)
{ {
continue; profileFlag |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
}
else if (info.type == ContextCreationTry::Type::ES)
{
profileFlag |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
} }
egl::Error error = createContextAttribs(config, info.version, info.profileFlag, context); egl::Error error = createContextAttribs(config, info.version, profileFlag, context);
if (!error.isError()) if (!error.isError())
{ {
return error; return error;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <algorithm> #include <algorithm>
#include <sstream> #include <sstream>
#include <EGL/eglext.h>
using angle::CheckedNumeric; using angle::CheckedNumeric;
...@@ -1114,4 +1115,55 @@ gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &s ...@@ -1114,4 +1115,55 @@ gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &s
return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize()); return checkedEndByte.ValueOrDie() > static_cast<size_t>(state.pixelBuffer->getSize());
} }
std::vector<ContextCreationTry> GenerateContextCreationToTry(EGLint requestedType, bool isMesaGLX)
{
using Type = ContextCreationTry::Type;
constexpr EGLint kPlatformOpenGL = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
constexpr EGLint kPlatformOpenGLES = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
std::vector<ContextCreationTry> contextsToTry;
if (requestedType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE || requestedType == kPlatformOpenGL)
{
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 5));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 4));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 3));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 2));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 1));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(4, 0));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(3, 3));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_CORE, gl::Version(3, 2));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(3, 3));
// On Mesa, do not try to create OpenGL context versions between 3.0 and
// 3.2 because of compatibility problems. See crbug.com/659030
if (!isMesaGLX)
{
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(3, 2));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(3, 1));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(3, 0));
}
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(2, 1));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(2, 0));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 5));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 4));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 3));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 2));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 1));
contextsToTry.emplace_back(kPlatformOpenGL, Type::DESKTOP_LEGACY, gl::Version(1, 0));
}
if (requestedType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE ||
requestedType == kPlatformOpenGLES)
{
contextsToTry.emplace_back(kPlatformOpenGLES, Type::ES, gl::Version(3, 2));
contextsToTry.emplace_back(kPlatformOpenGLES, Type::ES, gl::Version(3, 1));
contextsToTry.emplace_back(kPlatformOpenGLES, Type::ES, gl::Version(3, 0));
contextsToTry.emplace_back(kPlatformOpenGLES, Type::ES, gl::Version(2, 0));
}
return contextsToTry;
}
} }
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/Version.h"
#include "libANGLE/renderer/driver_utils.h" #include "libANGLE/renderer/driver_utils.h"
#include "libANGLE/renderer/gl/functionsgl_typedefs.h" #include "libANGLE/renderer/gl/functionsgl_typedefs.h"
...@@ -66,6 +67,27 @@ gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &s ...@@ -66,6 +67,27 @@ gl::ErrorOrResult<bool> ShouldApplyLastRowPaddingWorkaround(const gl::Extents &s
GLenum type, GLenum type,
bool is3D, bool is3D,
const void *pixels); const void *pixels);
struct ContextCreationTry
{
enum class Type
{
DESKTOP_CORE,
DESKTOP_LEGACY,
ES,
};
ContextCreationTry(EGLint displayType, Type type, gl::Version version)
: displayType(displayType), type(type), version(version)
{
}
EGLint displayType;
Type type;
gl::Version version;
};
std::vector<ContextCreationTry> GenerateContextCreationToTry(EGLint requestedType, bool isMesaGLX);
} }
#endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_ #endif // LIBANGLE_RENDERER_GL_RENDERERGLUTILS_H_
...@@ -63,6 +63,7 @@ DisplayWGL::DisplayWGL(const egl::DisplayState &state) ...@@ -63,6 +63,7 @@ DisplayWGL::DisplayWGL(const egl::DisplayState &state)
mOpenGLModule(nullptr), mOpenGLModule(nullptr),
mFunctionsWGL(nullptr), mFunctionsWGL(nullptr),
mFunctionsGL(nullptr), mFunctionsGL(nullptr),
mHasWGLCreateContextRobustness(false),
mHasRobustness(false), mHasRobustness(false),
mWindowClass(0), mWindowClass(0),
mWindow(nullptr), mWindow(nullptr),
...@@ -168,18 +169,10 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -168,18 +169,10 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current."); return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current.");
} }
// Grab the GL version from this context and use it as the maximum version available.
typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(GetProcAddress(mOpenGLModule, "glGetString"));
if (!getString)
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer.");
}
// Reinitialize the wgl functions to grab the extensions // Reinitialize the wgl functions to grab the extensions
mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext); mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext);
bool hasWGLCreateContextRobustness = mHasWGLCreateContextRobustness =
mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness"); mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness");
// Destroy the dummy window and context // Destroy the dummy window and context
...@@ -250,79 +243,8 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -250,79 +243,8 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
if (mFunctionsWGL->createContextAttribsARB) if (mFunctionsWGL->createContextAttribsARB)
{ {
int flags = 0;
// TODO: allow debug contexts
// TODO: handle robustness
int mask = 0;
if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
{
mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
}
else
{
// Request core profile
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
}
std::vector<int> contextCreationAttributes;
if (hasWGLCreateContextRobustness)
{
contextCreationAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
contextCreationAttributes.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
// Don't request a specific version unless the user wants one. WGL will return the highest version
// that the driver supports if no version is requested.
EGLint requestedMajorVersion = static_cast<EGLint>(
displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
EGLint requestedMinorVersion = static_cast<EGLint>(
displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
{
contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
contextCreationAttributes.push_back(requestedMajorVersion);
contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
contextCreationAttributes.push_back(requestedMinorVersion);
}
else
{
// the ES profile will give us ES version 1.1 unless a higher version is requested.
// Requesting version 2.0 will give us the highest compatible version available (2.0,
// 3.0, 3.1, etc).
if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
{
contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
contextCreationAttributes.push_back(2);
contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
contextCreationAttributes.push_back(0);
}
}
// Set the flag attributes
if (flags != 0)
{
contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
contextCreationAttributes.push_back(flags);
}
// Set the mask attribute
if (mask != 0)
{
contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
contextCreationAttributes.push_back(mask);
}
// Signal the end of the attributes
contextCreationAttributes.push_back(0);
contextCreationAttributes.push_back(0);
mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, nullptr, mWGLContext = initializeContextAttribs(displayAttributes);
&contextCreationAttributes[0]);
} }
// If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
...@@ -346,7 +268,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -346,7 +268,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
mFunctionsGL->initialize(); mFunctionsGL->initialize();
mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr; mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr;
if (hasWGLCreateContextRobustness != mHasRobustness) if (mHasWGLCreateContextRobustness != mHasRobustness)
{ {
WARN() << "WGL_ARB_create_context_robustness exists but unable to OpenGL context with " WARN() << "WGL_ARB_create_context_robustness exists but unable to OpenGL context with "
"robustness."; "robustness.";
...@@ -757,4 +679,78 @@ void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle) ...@@ -757,4 +679,78 @@ void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle)
} }
} }
} }
HGLRC DisplayWGL::initializeContextAttribs(const egl::AttributeMap &eglAttributes) const
{
EGLint requestedDisplayType = static_cast<EGLint>(
eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
// Create a context of the requested version, if any.
gl::Version requestedVersion(static_cast<EGLint>(eglAttributes.get(
EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)),
static_cast<EGLint>(eglAttributes.get(
EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)));
if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
{
int profileMask = 0;
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
requestedVersion >= gl::Version(3, 2))
{
profileMask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
}
return createContextAttribs(requestedVersion, profileMask);
}
// Try all the GL version in order as a workaround for Mesa context creation where the driver
// doesn't automatically return the highest version available.
for (const auto &info : GenerateContextCreationToTry(requestedDisplayType, false))
{
int profileFlag = 0;
if (info.type == ContextCreationTry::Type::DESKTOP_CORE)
{
profileFlag |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
}
else if (info.type == ContextCreationTry::Type::ES)
{
profileFlag |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
}
HGLRC context = createContextAttribs(info.version, profileFlag);
if (context != nullptr)
{
return context;
}
}
return nullptr;
}
HGLRC DisplayWGL::createContextAttribs(const gl::Version &version, int profileMask) const
{
std::vector<int> attribs;
if (mHasWGLCreateContextRobustness)
{
attribs.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
attribs.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
attribs.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
attribs.push_back(version.major);
attribs.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
attribs.push_back(version.minor);
if (profileMask != 0)
{
attribs.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
attribs.push_back(profileMask);
}
attribs.push_back(0);
attribs.push_back(0);
return mFunctionsWGL->createContextAttribsARB(mDeviceContext, nullptr, &attribs[0]);
}
} }
...@@ -72,11 +72,15 @@ class DisplayWGL : public DisplayGL ...@@ -72,11 +72,15 @@ class DisplayWGL : public DisplayGL
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;
HGLRC initializeContextAttribs(const egl::AttributeMap &eglAttributes) const;
HGLRC createContextAttribs(const gl::Version &version, int profileMask) const;
HMODULE mOpenGLModule; HMODULE mOpenGLModule;
FunctionsWGL *mFunctionsWGL; FunctionsWGL *mFunctionsWGL;
FunctionsGL *mFunctionsGL; FunctionsGL *mFunctionsGL;
bool mHasWGLCreateContextRobustness;
bool mHasRobustness; bool mHasRobustness;
ATOM mWindowClass; ATOM mWindowClass;
......
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