summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/gl/generate_bindings.py4
-rw-r--r--ui/gfx/gl/gl_context.cc4
-rw-r--r--ui/gfx/gl/gl_context.h2
-rw-r--r--ui/gfx/gl/gl_context_glx.cc118
-rw-r--r--ui/gfx/gl/gl_context_glx.h1
-rw-r--r--ui/gfx/gl/gl_interface.h2
-rw-r--r--ui/gfx/gl/gl_surface_glx.cc85
-rw-r--r--ui/gfx/gl/gl_surface_glx.h8
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);
};