diff options
author | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-09 23:08:56 +0000 |
---|---|---|
committer | kbr@google.com <kbr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-09 23:08:56 +0000 |
commit | c777de5b0773fad970c88b748c237120e5d6d563 (patch) | |
tree | 9eac25d954ce3d7b8ac39b2de428546d3350da94 /ui | |
parent | c257d0561bfaf52c37fcbc3cc2f9b457836b8db5 (diff) | |
download | chromium_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.gyp | 2 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context.cc | 16 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context.h | 3 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_cgl.cc | 8 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_egl.cc | 9 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_glx.cc | 9 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_osmesa.cc | 10 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_wgl.cc | 9 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface.cc | 13 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface.h | 4 | ||||
-rw-r--r-- | ui/gfx/gl/scoped_make_current.cc | 36 | ||||
-rw-r--r-- | ui/gfx/gl/scoped_make_current.h | 33 | ||||
-rw-r--r-- | ui/gfx/surface/accelerated_surface_mac.cc | 4 |
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); |