summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 23:08:56 +0000
committerkbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-09 23:08:56 +0000
commitc777de5b0773fad970c88b748c237120e5d6d563 (patch)
tree9eac25d954ce3d7b8ac39b2de428546d3350da94 /ui
parentc257d0561bfaf52c37fcbc3cc2f9b457836b8db5 (diff)
downloadchromium_src-c777de5b0773fad970c88b748c237120e5d6d563.zip
chromium_src-c777de5b0773fad970c88b748c237120e5d6d563.tar.gz
chromium_src-c777de5b0773fad970c88b748c237120e5d6d563.tar.bz2
Keep track of the current per-thread context and surface. Add
ScopedMakeCurrent to make it easier to briefly make another context current. Use it in AcceleratedSurface implementation and verify in the caller that it is working. This infrastructure would have made it possible to catch http://crbug.com/95492 and similar bugs where the wrong context was current. BUG=95962 TEST=ran CSS 3D example poster-circle; no assertion failures Review URL: http://codereview.chromium.org/7787022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100528 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/gl/gl.gyp2
-rw-r--r--ui/gfx/gl/gl_context.cc16
-rw-r--r--ui/gfx/gl/gl_context.h3
-rw-r--r--ui/gfx/gl/gl_context_cgl.cc8
-rw-r--r--ui/gfx/gl/gl_context_egl.cc9
-rw-r--r--ui/gfx/gl/gl_context_glx.cc9
-rw-r--r--ui/gfx/gl/gl_context_osmesa.cc10
-rw-r--r--ui/gfx/gl/gl_context_wgl.cc9
-rw-r--r--ui/gfx/gl/gl_surface.cc13
-rw-r--r--ui/gfx/gl/gl_surface.h4
-rw-r--r--ui/gfx/gl/scoped_make_current.cc36
-rw-r--r--ui/gfx/gl/scoped_make_current.h33
-rw-r--r--ui/gfx/surface/accelerated_surface_mac.cc4
13 files changed, 150 insertions, 6 deletions
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp
index 65b949e..3a9ad6d 100644
--- a/ui/gfx/gl/gl.gyp
+++ b/ui/gfx/gl/gl.gyp
@@ -69,6 +69,8 @@
'gl_surface_osmesa.h',
'gl_switches.cc',
'gl_switches.h',
+ 'scoped_make_current.cc',
+ 'scoped_make_current.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_gl.cc',
'<(gl_binding_output_dir)/gl_bindings_autogen_gl.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_mock.cc',
diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc
index 87379bf..6c25052e 100644
--- a/ui/gfx/gl/gl_context.cc
+++ b/ui/gfx/gl/gl_context.cc
@@ -6,13 +6,17 @@
#include "base/command_line.h"
#include "base/logging.h"
+#include "base/threading/thread_local.h"
#include "ui/gfx/gl/gl_context.h"
#include "ui/gfx/gl/gl_bindings.h"
#include "ui/gfx/gl/gl_implementation.h"
+#include "ui/gfx/gl/gl_surface.h"
#include "ui/gfx/gl/gl_switches.h"
namespace gfx {
+static base::ThreadLocalPointer<GLContext> current_context_;
+
GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
if (!share_group_.get())
share_group_ = new GLShareGroup;
@@ -22,6 +26,9 @@ GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
GLContext::~GLContext() {
share_group_->RemoveContext(this);
+ if (GetCurrent() == this) {
+ SetCurrent(NULL, NULL);
+ }
}
std::string GLContext::GetExtensions() {
@@ -61,6 +68,15 @@ bool GLContext::LosesAllContextsOnContextLost()
}
}
+GLContext* GLContext::GetCurrent() {
+ return current_context_.Get();
+}
+
+void GLContext::SetCurrent(GLContext* context, GLSurface* surface) {
+ current_context_.Set(context);
+ GLSurface::SetCurrent(surface);
+}
+
bool GLContext::WasAllocatedUsingARBRobustness() {
return false;
}
diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h
index 5340ada..0a617f4 100644
--- a/ui/gfx/gl/gl_context.h
+++ b/ui/gfx/gl/gl_context.h
@@ -64,10 +64,13 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
static bool LosesAllContextsOnContextLost();
+ static GLContext* GetCurrent();
+
virtual bool WasAllocatedUsingARBRobustness();
protected:
virtual ~GLContext();
+ static void SetCurrent(GLContext* context, GLSurface* surface);
private:
scoped_refptr<GLShareGroup> share_group_;
diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc
index 5598dd65..6e5defa 100644
--- a/ui/gfx/gl/gl_context_cgl.cc
+++ b/ui/gfx/gl/gl_context_cgl.cc
@@ -64,6 +64,7 @@ bool GLContextCGL::MakeCurrent(GLSurface* surface) {
return false;
}
+ SetCurrent(this, surface);
surface->OnMakeCurrent(this);
return true;
}
@@ -72,12 +73,17 @@ void GLContextCGL::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ SetCurrent(NULL, NULL);
CGLSetCurrentContext(NULL);
CGLSetPBuffer(static_cast<CGLContextObj>(context_), NULL, 0, 0, 0);
}
bool GLContextCGL::IsCurrent(GLSurface* surface) {
- if (CGLGetCurrentContext() != context_)
+ bool native_context_is_current = CGLGetCurrentContext() == context_;
+
+ DCHECK(native_context_is_current == (GetCurrent() == this));
+
+ if (!native_context_is_current)
return false;
if (surface) {
diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc
index ba25498..cde22d2 100644
--- a/ui/gfx/gl/gl_context_egl.cc
+++ b/ui/gfx/gl/gl_context_egl.cc
@@ -95,6 +95,7 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
return false;
}
+ SetCurrent(this, surface);
surface->OnMakeCurrent(this);
return true;
}
@@ -103,6 +104,7 @@ void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ SetCurrent(NULL, NULL);
eglMakeCurrent(display_,
EGL_NO_SURFACE,
EGL_NO_SURFACE,
@@ -111,7 +113,12 @@ void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
bool GLContextEGL::IsCurrent(GLSurface* surface) {
DCHECK(context_);
- if (context_ != eglGetCurrentContext())
+
+ bool native_context_is_current = context_ == eglGetCurrentContext();
+
+ DCHECK(native_context_is_current == (GetCurrent() == this));
+
+ if (!native_context_is_current)
return false;
if (surface) {
diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc
index 47238cc..c7d5998 100644
--- a/ui/gfx/gl/gl_context_glx.cc
+++ b/ui/gfx/gl/gl_context_glx.cc
@@ -171,6 +171,7 @@ bool GLContextGLX::MakeCurrent(GLSurface* surface) {
return false;
}
+ SetCurrent(this, surface);
surface->OnMakeCurrent(this);
return true;
}
@@ -179,11 +180,17 @@ void GLContextGLX::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ SetCurrent(NULL, NULL);
glXMakeContextCurrent(GLSurfaceGLX::GetDisplay(), 0, 0, NULL);
}
bool GLContextGLX::IsCurrent(GLSurface* surface) {
- if (glXGetCurrentContext() != static_cast<GLXContext>(context_))
+ bool native_context_is_current =
+ glXGetCurrentContext() == static_cast<GLXContext>(context_);
+
+ DCHECK(native_context_is_current == (GetCurrent() == this));
+
+ if (!native_context_is_current)
return false;
if (surface) {
diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc
index c6b8c42..0db285f 100644
--- a/ui/gfx/gl/gl_context_osmesa.cc
+++ b/ui/gfx/gl/gl_context_osmesa.cc
@@ -67,6 +67,7 @@ bool GLContextOSMesa::MakeCurrent(GLSurface* surface) {
// Row 0 is at the top.
OSMesaPixelStore(OSMESA_Y_UP, 0);
+ SetCurrent(this, surface);
surface->OnMakeCurrent(this);
return true;
}
@@ -75,12 +76,19 @@ void GLContextOSMesa::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ SetCurrent(NULL, NULL);
OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0);
}
bool GLContextOSMesa::IsCurrent(GLSurface* surface) {
DCHECK(context_);
- if (context_ != OSMesaGetCurrentContext())
+
+ bool native_context_is_current =
+ context_ == OSMesaGetCurrentContext();
+
+ DCHECK(native_context_is_current == (GetCurrent() == this));
+
+ if (!native_context_is_current)
return false;
if (surface) {
diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc
index f86e955..487f950 100644
--- a/ui/gfx/gl/gl_context_wgl.cc
+++ b/ui/gfx/gl/gl_context_wgl.cc
@@ -82,6 +82,7 @@ bool GLContextWGL::MakeCurrent(GLSurface* surface) {
return false;
}
+ SetCurrent(this, surface);
surface->OnMakeCurrent(this);
return true;
}
@@ -90,11 +91,17 @@ void GLContextWGL::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ SetCurrent(NULL, NULL);
wglMakeCurrent(NULL, NULL);
}
bool GLContextWGL::IsCurrent(GLSurface* surface) {
- if (wglGetCurrentContext() != context_)
+ bool native_context_is_current =
+ wglGetCurrentContext() == context_;
+
+ DCHECK(native_context_is_current == (GetCurrent() == this));
+
+ if (!native_context_is_current)
return false;
if (surface) {
diff --git a/ui/gfx/gl/gl_surface.cc b/ui/gfx/gl/gl_surface.cc
index 399d816..a0e881d 100644
--- a/ui/gfx/gl/gl_surface.cc
+++ b/ui/gfx/gl/gl_surface.cc
@@ -4,14 +4,19 @@
#include "ui/gfx/gl/gl_surface.h"
+#include "base/threading/thread_local.h"
#include "ui/gfx/gl/gl_context.h"
namespace gfx {
+static base::ThreadLocalPointer<GLSurface> current_surface_;
+
GLSurface::GLSurface() {
}
GLSurface::~GLSurface() {
+ if (GetCurrent() == this)
+ SetCurrent(NULL);
}
bool GLSurface::Initialize()
@@ -26,4 +31,12 @@ unsigned int GLSurface::GetBackingFrameBufferObject() {
void GLSurface::OnMakeCurrent(GLContext* context) {
}
+GLSurface* GLSurface::GetCurrent() {
+ return current_surface_.Get();
+}
+
+void GLSurface::SetCurrent(GLSurface* surface) {
+ current_surface_.Set(surface);
+}
+
} // namespace gfx
diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h
index 88b4f24..6e31418 100644
--- a/ui/gfx/gl/gl_surface.h
+++ b/ui/gfx/gl/gl_surface.h
@@ -65,11 +65,15 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
bool software,
const gfx::Size& size);
+ static GLSurface* GetCurrent();
+
protected:
virtual ~GLSurface();
+ static void SetCurrent(GLSurface* surface);
private:
friend class base::RefCounted<GLSurface>;
+ friend class GLContext;
DISALLOW_COPY_AND_ASSIGN(GLSurface);
};
diff --git a/ui/gfx/gl/scoped_make_current.cc b/ui/gfx/gl/scoped_make_current.cc
new file mode 100644
index 0000000..6939861
--- /dev/null
+++ b/ui/gfx/gl/scoped_make_current.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/gl/scoped_make_current.h"
+
+#include "base/logging.h"
+
+namespace gfx {
+
+ScopedMakeCurrent::ScopedMakeCurrent(GLContext* context, GLSurface* surface)
+ : previous_context_(GLContext::GetCurrent())
+ , previous_surface_(GLSurface::GetCurrent())
+ , context_(context)
+ , surface_(surface)
+ , succeeded_(false) {
+ DCHECK(context);
+ DCHECK(surface);
+ succeeded_ = context->MakeCurrent(surface);
+}
+
+ScopedMakeCurrent::~ScopedMakeCurrent() {
+ if (previous_context_.get()) {
+ DCHECK(previous_surface_.get());
+ previous_context_->MakeCurrent(previous_surface_.get());
+ } else {
+ context_->ReleaseCurrent(surface_.get());
+ }
+}
+
+bool ScopedMakeCurrent::Succeeded() {
+ return succeeded_;
+}
+
+} // namespace gfx
+
diff --git a/ui/gfx/gl/scoped_make_current.h b/ui/gfx/gl/scoped_make_current.h
new file mode 100644
index 0000000..d0d74f7
--- /dev/null
+++ b/ui/gfx/gl/scoped_make_current.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_GL_SCOPED_MAKE_CURRENT_H_
+#define UI_GFX_GL_SCOPED_MAKE_CURRENT_H_
+#pragma once
+
+#include "ui/gfx/gl/gl_context.h"
+#include "ui/gfx/gl/gl_surface.h"
+
+namespace gfx {
+
+class GL_EXPORT ScopedMakeCurrent {
+ public:
+ explicit ScopedMakeCurrent(GLContext* context, GLSurface* surface);
+ ~ScopedMakeCurrent();
+
+ bool Succeeded();
+
+ private:
+ scoped_refptr<GLContext> previous_context_;
+ scoped_refptr<GLSurface> previous_surface_;
+ scoped_refptr<GLContext> context_;
+ scoped_refptr<GLSurface> surface_;
+ bool succeeded_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedMakeCurrent);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_SCOPED_MAKE_CURRENT_H_
+
diff --git a/ui/gfx/surface/accelerated_surface_mac.cc b/ui/gfx/surface/accelerated_surface_mac.cc
index cbbee4b..d6b63cd 100644
--- a/ui/gfx/surface/accelerated_surface_mac.cc
+++ b/ui/gfx/surface/accelerated_surface_mac.cc
@@ -10,6 +10,7 @@
#include "ui/gfx/gl/gl_context.h"
#include "ui/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_surface.h"
+#include "ui/gfx/gl/scoped_make_current.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/surface/io_surface_support_mac.h"
@@ -237,7 +238,8 @@ uint64 AcceleratedSurface::SetSurfaceSize(const gfx::Size& size) {
if (!io_surface_support)
return 0; // Caller can try using SetWindowSizeForTransportDIB().
- if (!MakeCurrent())
+ gfx::ScopedMakeCurrent make_current(gl_context_.get(), gl_surface_.get());
+ if (!make_current.Succeeded())
return 0;
gfx::Size clamped_size = ClampToValidDimensions(size);