diff options
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gfx/gl/generate_bindings.py | 4 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context.cc | 4 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context.h | 2 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_glx.cc | 118 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_glx.h | 1 | ||||
-rw-r--r-- | ui/gfx/gl/gl_interface.h | 2 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_glx.cc | 85 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_glx.h | 8 |
8 files changed, 183 insertions, 41 deletions
diff --git a/ui/gfx/gl/generate_bindings.py b/ui/gfx/gl/generate_bindings.py index b083229..e0475c2 100644 --- a/ui/gfx/gl/generate_bindings.py +++ b/ui/gfx/gl/generate_bindings.py @@ -121,6 +121,7 @@ GL_FUNCTIONS = [ ['void', ['glGetFramebufferAttachmentParameterivEXT', 'glGetFramebufferAttachmentParameteriv'], 'GLenum target, ' 'GLenum attachment, GLenum pname, GLint* params'], +['GLenum', ['glGetGraphicsResetStatusARB'], 'void'], ['void', ['glGetIntegerv'], 'GLenum pname, GLint* params'], ['void', ['glGetProgramiv'], 'GLuint program, GLenum pname, GLint* params'], ['void', ['glGetProgramInfoLog'], @@ -432,6 +433,9 @@ GLX_FUNCTIONS = [ 'Display* dpy, GLXDrawable drawable, int interval'], ['GLXFBConfig', ['glXGetFBConfigFromVisualSGIX'], 'Display* dpy, XVisualInfo* visualInfo'], +['GLXContext', ['glXCreateContextAttribsARB'], + 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, ' + 'const int* attrib_list'], ] FUNCTION_SETS = [ diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc index c19741f..87379bf 100644 --- a/ui/gfx/gl/gl_context.cc +++ b/ui/gfx/gl/gl_context.cc @@ -61,4 +61,8 @@ bool GLContext::LosesAllContextsOnContextLost() } } +bool GLContext::WasAllocatedUsingARBRobustness() { + return false; +} + } // namespace gfx diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h index 2159423..ff88e0c 100644 --- a/ui/gfx/gl/gl_context.h +++ b/ui/gfx/gl/gl_context.h @@ -64,6 +64,8 @@ class GLContext : public base::RefCounted<GLContext> { static bool LosesAllContextsOnContextLost(); + virtual bool WasAllocatedUsingARBRobustness(); + protected: virtual ~GLContext(); diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc index ba8d7ab..aa863cc 100644 --- a/ui/gfx/gl/gl_context_glx.cc +++ b/ui/gfx/gl/gl_context_glx.cc @@ -56,50 +56,81 @@ GLContextGLX::~GLContextGLX() { bool GLContextGLX::Initialize(GLSurface* compatible_surface) { GLSurfaceGLX* surface_glx = static_cast<GLSurfaceGLX*>(compatible_surface); - GLXFBConfig config = static_cast<GLXFBConfig>(surface_glx->GetConfig()); GLXContext share_handle = static_cast<GLXContext>( share_group() ? share_group()->GetHandle() : NULL); - // The means by which the context is created depends on whether the drawable - // type works reliably with GLX 1.3. If it does not then fall back to GLX 1.2. - if (config) { - context_ = glXCreateNewContext( + if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) { + DLOG(INFO) << "GLX_ARB_create_context_robustness supported."; + + std::vector<int> attribs; + attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB); + attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB); + attribs.push_back(0); + context_ = glXCreateContextAttribsARB( GLSurfaceGLX::GetDisplay(), static_cast<GLXFBConfig>(surface_glx->GetConfig()), - GLX_RGBA_TYPE, share_handle, - True); - } else { - Display* display = GLSurfaceGLX::GetDisplay(); - - // Get the visuals for the X drawable. - XWindowAttributes attributes; - XGetWindowAttributes( - display, - reinterpret_cast<GLXDrawable>(surface_glx->GetHandle()), - &attributes); - - XVisualInfo visual_info_template; - visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); - - int visual_info_count = 0; - scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( - XGetVisualInfo(display, VisualIDMask, - &visual_info_template, - &visual_info_count)); - - DCHECK(visual_info_list.get()); - if (visual_info_count == 0) { - LOG(ERROR) << "No visual info for visual ID."; - return false; + True, + &attribs.front()); + if (context_) { + DLOG(INFO) << " Successfully allocated " + << (surface_glx->IsOffscreen() ? "offscreen" : "onscreen") + << " GL context with LOSE_CONTEXT_ON_RESET_ARB"; + } else { + // TODO(kbr): it is not expected that things will work properly + // in this case, since we will likely allocate our offscreen + // contexts with this bit set and the onscreen contexts without, + // and won't be able to put them in the same share group. + // Consider what to do here; force loss of all contexts and + // reallocation without ARB_robustness? + LOG(ERROR) << + " FAILED to allocate GL context with LOSE_CONTEXT_ON_RESET_ARB"; } + } - // Attempt to create a context with each visual in turn until one works. - context_ = glXCreateContext( - display, - visual_info_list.get(), - share_handle, - True); + if (!context_) { + // The means by which the context is created depends on whether + // the drawable type works reliably with GLX 1.3. If it does not + // then fall back to GLX 1.2. + if (surface_glx->IsOffscreen()) { + context_ = glXCreateNewContext( + GLSurfaceGLX::GetDisplay(), + static_cast<GLXFBConfig>(surface_glx->GetConfig()), + GLX_RGBA_TYPE, + share_handle, + True); + } else { + Display* display = GLSurfaceGLX::GetDisplay(); + + // Get the visuals for the X drawable. + XWindowAttributes attributes; + XGetWindowAttributes( + display, + reinterpret_cast<GLXDrawable>(surface_glx->GetHandle()), + &attributes); + + XVisualInfo visual_info_template; + visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); + + int visual_info_count = 0; + scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list( + XGetVisualInfo(display, VisualIDMask, + &visual_info_template, + &visual_info_count)); + + DCHECK(visual_info_list.get()); + if (visual_info_count == 0) { + LOG(ERROR) << "No visual info for visual ID."; + return false; + } + + // Attempt to create a context with each visual in turn until one works. + context_ = glXCreateContext( + display, + visual_info_list.get(), + share_handle, + True); + } } if (!context_) { @@ -108,6 +139,13 @@ bool GLContextGLX::Initialize(GLSurface* compatible_surface) { return false; } + DLOG(INFO) << (surface_glx->IsOffscreen() ? "Offscreen" : "Onscreen") + << " context was " + << (glXIsDirect(GLSurfaceGLX::GetDisplay(), + static_cast<GLXContext>(context_)) + ? "direct" : "indirect") + << "."; + return true; } @@ -188,9 +226,7 @@ void GLContextGLX::SetSwapInterval(int interval) { std::string GLContextGLX::GetExtensions() { DCHECK(IsCurrent(NULL)); - const char* extensions = glXQueryExtensionsString( - GLSurfaceGLX::GetDisplay(), - 0); + const char* extensions = GLSurfaceGLX::GetGLXExtensions(); if (extensions) { return GLContext::GetExtensions() + " " + extensions; } @@ -198,4 +234,8 @@ std::string GLContextGLX::GetExtensions() { return GLContext::GetExtensions(); } +bool GLContextGLX::WasAllocatedUsingARBRobustness() { + return GLSurfaceGLX::IsCreateContextRobustnessSupported(); +} + } // namespace gfx diff --git a/ui/gfx/gl/gl_context_glx.h b/ui/gfx/gl/gl_context_glx.h index e89bcb2..5432df7 100644 --- a/ui/gfx/gl/gl_context_glx.h +++ b/ui/gfx/gl/gl_context_glx.h @@ -25,6 +25,7 @@ class GLContextGLX : public GLContext { virtual void* GetHandle(); virtual void SetSwapInterval(int interval); virtual std::string GetExtensions(); + virtual bool WasAllocatedUsingARBRobustness(); private: void* context_; diff --git a/ui/gfx/gl/gl_interface.h b/ui/gfx/gl/gl_interface.h index 55ea9d1..3c3b3fa 100644 --- a/ui/gfx/gl/gl_interface.h +++ b/ui/gfx/gl/gl_interface.h @@ -540,6 +540,8 @@ class GLInterface { virtual void SetSurfaceCHROMIUM(GLuint id) = 0; + virtual GLenum GetGraphicsResetStatusARB() = 0; + private: static GLInterface* interface_; }; diff --git a/ui/gfx/gl/gl_surface_glx.cc b/ui/gfx/gl/gl_surface_glx.cc index 5a051de..b584080 100644 --- a/ui/gfx/gl/gl_surface_glx.cc +++ b/ui/gfx/gl/gl_surface_glx.cc @@ -32,6 +32,8 @@ class ScopedPtrXFree { }; Display* g_display; +const char* g_glx_extensions = NULL; +bool g_glx_create_context_robustness_supported = false; } // namespace anonymous @@ -63,6 +65,10 @@ bool GLSurfaceGLX::InitializeOneOff() { return false; } + g_glx_extensions = glXQueryExtensionsString(g_display, 0); + g_glx_create_context_robustness_supported = + HasGLXExtension("GLX_ARB_create_context_robustness"); + initialized = true; return true; } @@ -71,8 +77,31 @@ Display* GLSurfaceGLX::GetDisplay() { return g_display; } +const char* GLSurfaceGLX::GetGLXExtensions() { + return g_glx_extensions; +} + +bool GLSurfaceGLX::HasGLXExtension(const char* name) { + DCHECK(name); + const char* c_extensions = GetGLXExtensions(); + if (!c_extensions) + return false; + std::string extensions(c_extensions); + extensions += " "; + + std::string delimited_name(name); + delimited_name += " "; + + return extensions.find(delimited_name) != std::string::npos; +} + +bool GLSurfaceGLX::IsCreateContextRobustnessSupported() { + return g_glx_create_context_robustness_supported; +} + NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::PluginWindowHandle window) - : window_(window) { + : window_(window), + config_(NULL) { } NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() { @@ -106,7 +135,59 @@ void* NativeViewGLSurfaceGLX::GetHandle() { } void* NativeViewGLSurfaceGLX::GetConfig() { - return NULL; + if (!config_) { + // This code path is expensive, but we only take it when + // attempting to use GLX_ARB_create_context_robustness, in which + // case we need a GLXFBConfig for the window in order to create a + // context for it. + // + // TODO(kbr): this is not a reliable code path. On platforms which + // support it, we should use glXChooseFBConfig in the browser + // process to choose the FBConfig and from there the X Visual to + // use when creating the window in the first place. Then we can + // pass that FBConfig down rather than attempting to reconstitute + // it. + + XWindowAttributes attributes; + XGetWindowAttributes( + g_display, + reinterpret_cast<GLXDrawable>(GetHandle()), + &attributes); + int visual_id = XVisualIDFromVisual(attributes.visual); + + int num_elements = 0; + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs( + glXGetFBConfigs(g_display, + DefaultScreen(g_display), + &num_elements)); + if (!configs.get()) { + LOG(ERROR) << "glXGetFBConfigs failed."; + return NULL; + } + if (!num_elements) { + LOG(ERROR) << "glXGetFBConfigs returned 0 elements."; + return NULL; + } + bool found = false; + int i; + for (i = 0; i < num_elements; ++i) { + int value; + if (glXGetFBConfigAttrib( + g_display, configs.get()[i], GLX_VISUAL_ID, &value)) { + LOG(ERROR) << "glXGetFBConfigAttrib failed."; + return NULL; + } + if (value == visual_id) { + found = true; + break; + } + } + if (found) { + config_ = configs.get()[i]; + } + } + + return config_; } PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size) diff --git a/ui/gfx/gl/gl_surface_glx.h b/ui/gfx/gl/gl_surface_glx.h index 343137c..54a52e0 100644 --- a/ui/gfx/gl/gl_surface_glx.h +++ b/ui/gfx/gl/gl_surface_glx.h @@ -22,6 +22,13 @@ class GLSurfaceGLX : public GLSurface { static bool InitializeOneOff(); static Display* GetDisplay(); + // These aren't particularly tied to surfaces, but since we already + // have the static InitializeOneOff here, it's easiest to reuse its + // initialization guards. + static const char* GetGLXExtensions(); + static bool HasGLXExtension(const char* name); + static bool IsCreateContextRobustnessSupported(); + // Get the FB config that the surface was created with or NULL if it is not // a GLX drawable. virtual void* GetConfig() = 0; @@ -47,6 +54,7 @@ class NativeViewGLSurfaceGLX : public GLSurfaceGLX { private: gfx::PluginWindowHandle window_; + void* config_; DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceGLX); }; |