Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Unified Diff: ui/gl/gl_context_glx.cc

Issue 1999543003: GLContextGLX: try all GL versions from the highest. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Only use the workaround on Mesa Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | ui/gl/gl_surface_glx.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gl/gl_context_glx.cc
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc
index aee3fedeab5a040d8ff9373200787657c485bb8a..220af7ae9ef59920ddaa8a3d3245c672669247c5 100644
--- a/ui/gl/gl_context_glx.cc
+++ b/ui/gl/gl_context_glx.cc
@@ -19,6 +19,134 @@ extern "C" {
namespace gfx {
+namespace {
+
+static int IgnoreX11Errors(Display*, XErrorEvent*) {
+ return 0;
+}
+
+using GLVersion = std::pair<int, int>;
+
+GLXContext CreateContextAttribs(Display* display,
+ GLXFBConfig config,
+ GLXContext share,
+ GLVersion version,
+ int profileMask) {
+ std::vector<int> attribs;
+
+ if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) {
+ attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ if (version.first == 0 && version.second == 0) {
+ attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ attribs.push_back(version.first);
+
+ attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ attribs.push_back(version.second);
+ }
+
+ if (profileMask != 0 && GLSurfaceGLX::IsCreateContextProfileSupported()) {
+ attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ attribs.push_back(profileMask);
+ }
+
+ attribs.push_back(0);
+
+ // 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 the GLXContext was created.
+ auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
+ GLXContext context =
+ glXCreateContextAttribsARB(display, config, share, True, attribs.data());
+ XSetErrorHandler(oldErrorHandler);
+
+ return context;
+}
+
+GLXContext CreateHighestVersionContext(Display* display,
+ GLXFBConfig config,
+ GLXContext share) {
+ // 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. On Mesa, Instead we try to create a
+ // context per GL version until we succeed, starting from newer version.
+ // On both Mesa and other drivers we try to create a desktop context and fall
+ // back to ES context.
+ // The code could be simpler if the Mesa code path was used for all drivers,
+ // however the cost of failing a context creation can be high (3 milliseconds
+ // for the NVIDIA driver). The good thing is that failed context creation only
+ // takes 0.1 milliseconds on Mesa.
+
+ struct ContextCreationInfo {
+ int profileFlag;
+ GLVersion version;
+ };
+
+ // clang-format off
+ // For regular drivers we try to create a core, compatibility, then ES
+ // context. Without requiring any specific version.
+ const ContextCreationInfo contextsToTry[] = {
piman 2016/05/25 22:35:17 nit: chrome style contexts_to_try
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLVersion(0, 0) },
+ { 0, GLVersion(0, 0) },
+ { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, GLVersion(0, 0) },
+ };
+
+ // On Mesa we try to create a core context, except for versions below 3.2
+ // where it is not applicable. (and fallback to ES as well)
+ const ContextCreationInfo mesaContextsToTry[] = {
piman 2016/05/25 22:35:17 nit: mesa_contexts_to_try
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 5) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 4) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 3) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 2) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 1) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(4, 0) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(3, 3) } },
+ { GLX_CONTEXT_CORE_PROFILE_BIT_ARB, { GLVersion(3, 2) } },
+ { 0, { GLVersion(3, 1) } },
+ { 0, { GLVersion(3, 0) } },
+ { 0, { GLVersion(2, 0) } },
+ { 0, { GLVersion(1, 5) } },
+ { 0, { GLVersion(1, 4) } },
+ { 0, { GLVersion(1, 3) } },
+ { 0, { GLVersion(1, 2) } },
+ { 0, { GLVersion(1, 1) } },
+ { 0, { GLVersion(1, 0) } },
+ { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 2) } },
+ { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 1) } },
+ { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(3, 0) } },
+ { GLX_CONTEXT_ES2_PROFILE_BIT_EXT, { GLVersion(2, 0) } },
+ };
+ // clang-format on
+
+ std::string clientVendor = glXGetClientString(display, GLX_VENDOR);
piman 2016/05/25 22:35:17 nit: client_vendor
+ bool isMesa = clientVendor.find("Mesa") != std::string::npos;
piman 2016/05/25 22:35:17 nit: is_mesa
+
+ const ContextCreationInfo* toTry = contextsToTry;
piman 2016/05/25 22:35:17 nit: to_try
+ size_t toTryLength = arraysize(contextsToTry);
piman 2016/05/25 22:35:17 nit: to_try_length
+ if (isMesa) {
+ toTry = mesaContextsToTry;
+ toTryLength = arraysize(mesaContextsToTry);
+ }
+
+ for (size_t i = 0; i < toTryLength; ++i) {
+ const ContextCreationInfo& info = toTry[i];
+ if (!GLSurfaceGLX::IsCreateContextES2ProfileSupported() &&
+ info.profileFlag == GLX_CONTEXT_ES2_PROFILE_BIT_EXT) {
+ continue;
+ }
+ GLXContext context = CreateContextAttribs(display, config, share,
+ info.version, info.profileFlag);
+ if (context != nullptr) {
+ return context;
+ }
+ }
+
+ return nullptr;
+}
+}
+
GLContextGLX::GLContextGLX(GLShareGroup* share_group)
: GLContextReal(share_group),
context_(nullptr),
@@ -38,19 +166,9 @@ bool GLContextGLX::Initialize(
if (GLSurfaceGLX::IsCreateContextSupported()) {
DVLOG(1) << "GLX_ARB_create_context supported.";
- std::vector<int> attribs;
- if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) {
- DVLOG(1) << "GLX_ARB_create_context_robustness supported.";
- attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
- attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
- }
- attribs.push_back(0);
- context_ = glXCreateContextAttribsARB(
- display_,
- static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
- share_handle,
- True,
- &attribs.front());
+ context_ = CreateHighestVersionContext(
+ display_, static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
+ share_handle);
if (!context_) {
LOG(ERROR) << "Failed to create GL context with "
<< "glXCreateContextAttribsARB.";
« no previous file with comments | « no previous file | ui/gl/gl_surface_glx.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698