diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-13 23:59:03 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-13 23:59:03 +0000 |
commit | b0dc569d27817cccc7b09108da41054892c35bf7 (patch) | |
tree | 20c04c14a47197e57e637a6a910df6ff7bce0784 /app | |
parent | 440e7e0151dae967e5ab4d031c82b8c901dc88f8 (diff) | |
download | chromium_src-b0dc569d27817cccc7b09108da41054892c35bf7.zip chromium_src-b0dc569d27817cccc7b09108da41054892c35bf7.tar.gz chromium_src-b0dc569d27817cccc7b09108da41054892c35bf7.tar.bz2 |
EGL contexts reference count the EGL surfaces they share.
This fixes the case where a NativeViewEGLContext and a SecondaryEGL context are backed by the same EGL surface and the native one, which previously owned the surface, is destroyed first.
TEST=try
BUG=none
Review URL: http://codereview.chromium.org/6296004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71390 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rw-r--r-- | app/gfx/gl/gl_context_egl.cc | 76 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_egl.h | 36 |
2 files changed, 66 insertions, 46 deletions
diff --git a/app/gfx/gl/gl_context_egl.cc b/app/gfx/gl/gl_context_egl.cc index fa82e6d..3fddb30 100644 --- a/app/gfx/gl/gl_context_egl.cc +++ b/app/gfx/gl/gl_context_egl.cc @@ -58,6 +58,22 @@ const char* GetLastEGLErrorString() { } } // namespace anonymous +SharedEGLSurface::SharedEGLSurface(EGLSurface surface) : surface_(surface) { +} + +SharedEGLSurface::~SharedEGLSurface() { + if (surface_) { + if (!eglDestroySurface(g_display, surface_)) { + LOG(ERROR) << "eglDestroySurface failed with error " + << GetLastEGLErrorString(); + } + } +} + +EGLSurface SharedEGLSurface::egl_surface() const { + return surface_; +} + bool BaseEGLContext::InitializeOneOff() { static bool initialized = false; if (initialized) @@ -143,7 +159,6 @@ std::string BaseEGLContext::GetExtensions() { NativeViewEGLContext::NativeViewEGLContext(void* window) : window_(window), - surface_(NULL), context_(NULL) { } @@ -157,9 +172,12 @@ bool NativeViewEGLContext::Initialize() { // Create a surface for the native window. EGLNativeWindowType native_window = reinterpret_cast<EGLNativeWindowType>(window_); - surface_ = eglCreateWindowSurface(g_display, g_config, native_window, NULL); + surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display, + g_config, + native_window, + NULL)); - if (!surface_) { + if (!surface_->egl_surface()) { LOG(ERROR) << "eglCreateWindowSurface failed with error " << GetLastEGLErrorString(); Destroy(); @@ -204,20 +222,14 @@ void NativeViewEGLContext::Destroy() { context_ = NULL; } - if (surface_) { - if (!eglDestroySurface(g_display, surface_)) { - LOG(ERROR) << "eglDestroySurface failed with error " - << GetLastEGLErrorString(); - } - - surface_ = NULL; - } + surface_ = NULL; } bool NativeViewEGLContext::MakeCurrent() { DCHECK(context_); if (!eglMakeCurrent(g_display, - surface_, surface_, + surface_->egl_surface(), + surface_->egl_surface(), context_)) { VLOG(1) << "eglMakeCurrent failed with error " << GetLastEGLErrorString(); @@ -237,7 +249,7 @@ bool NativeViewEGLContext::IsOffscreen() { } bool NativeViewEGLContext::SwapBuffers() { - if (!eglSwapBuffers(g_display, surface_)) { + if (!eglSwapBuffers(g_display, surface_->egl_surface())) { VLOG(1) << "eglSwapBuffers failed with error " << GetLastEGLErrorString(); return false; @@ -260,8 +272,10 @@ gfx::Size NativeViewEGLContext::GetSize() { // get updated on resize. When it does, we can share the code. EGLint width; EGLint height; - if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) || - !eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) { + if (!eglQuerySurface( + g_display, surface_->egl_surface(), EGL_WIDTH, &width) || + !eglQuerySurface( + g_display, surface_->egl_surface(), EGL_HEIGHT, &height)) { NOTREACHED() << "eglQuerySurface failed with error " << GetLastEGLErrorString(); return gfx::Size(); @@ -283,14 +297,12 @@ void NativeViewEGLContext::SetSwapInterval(int interval) { } } -EGLSurface NativeViewEGLContext::GetSurface() { +SharedEGLSurface* NativeViewEGLContext::GetSurface() { return surface_; } SecondaryEGLContext::SecondaryEGLContext() - : surface_(NULL), - own_surface_(false), - context_(NULL) + : context_(NULL) { } @@ -307,7 +319,6 @@ bool SecondaryEGLContext::Initialize(GLContext* shared_context) { if (shared_context) { surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface(); - own_surface_ = false; // Create a context. context_ = eglCreateContext(g_display, @@ -322,13 +333,15 @@ bool SecondaryEGLContext::Initialize(GLContext* shared_context) { EGL_NONE }; - surface_ = eglCreatePbufferSurface(g_display, g_config, kPbufferAttribs); - if (!surface_) { + surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display, + g_config, + kPbufferAttribs)); + if (!surface_->egl_surface()) { LOG(ERROR) << "eglCreatePbufferSurface failed with error " << GetLastEGLErrorString(); + Destroy(); return false; } - own_surface_ = true; context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); #else @@ -348,16 +361,6 @@ bool SecondaryEGLContext::Initialize(GLContext* shared_context) { } void SecondaryEGLContext::Destroy() { - if (own_surface_) { - if (!eglDestroySurface(g_display, surface_)) { - LOG(ERROR) << "eglDestroySurface failed with error " - << GetLastEGLErrorString(); - } - - own_surface_ = false; - } - surface_ = NULL; - if (context_) { if (!eglDestroyContext(g_display, context_)) { LOG(ERROR) << "eglDestroyContext failed with error " @@ -366,12 +369,15 @@ void SecondaryEGLContext::Destroy() { context_ = NULL; } + + surface_ = NULL; } bool SecondaryEGLContext::MakeCurrent() { DCHECK(context_); if (!eglMakeCurrent(g_display, - surface_, surface_, + surface_->egl_surface(), + surface_->egl_surface(), context_)) { VLOG(1) << "eglMakeCurrent failed with error " << GetLastEGLErrorString(); @@ -409,7 +415,7 @@ void SecondaryEGLContext::SetSwapInterval(int interval) { NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; } -EGLSurface SecondaryEGLContext::GetSurface() { +SharedEGLSurface* SecondaryEGLContext::GetSurface() { return surface_; } diff --git a/app/gfx/gl/gl_context_egl.h b/app/gfx/gl/gl_context_egl.h index 1647239..fbbdabb 100644 --- a/app/gfx/gl/gl_context_egl.h +++ b/app/gfx/gl/gl_context_egl.h @@ -6,8 +6,9 @@ #define APP_GFX_GL_GL_CONTEXT_EGL_H_ #pragma once -#include "gfx/size.h" #include "app/gfx/gl/gl_context.h" +#include "base/ref_counted.h" +#include "gfx/size.h" typedef void* EGLDisplay; typedef void* EGLContext; @@ -15,6 +16,20 @@ typedef void* EGLSurface; namespace gfx { +// Takes ownership of an EGL surface and reference counts it so it can be shared +// by multiple EGL contexts and destroyed with the last. +class SharedEGLSurface : public base::RefCounted<SharedEGLSurface> { + public: + explicit SharedEGLSurface(EGLSurface surface); + ~SharedEGLSurface(); + + EGLSurface egl_surface() const; + + private: + EGLSurface surface_; + DISALLOW_COPY_AND_ASSIGN(SharedEGLSurface); +}; + // Interface for EGL contexts. Adds an EGL specific accessor for retreiving // the surface. class BaseEGLContext : public GLContext { @@ -27,7 +42,7 @@ class BaseEGLContext : public GLContext { static EGLDisplay GetDisplay(); // Get the associated EGL surface. - virtual EGLSurface GetSurface() = 0; + virtual SharedEGLSurface* GetSurface() = 0; // Implement GLContext. virtual std::string GetExtensions(); @@ -56,20 +71,21 @@ class NativeViewEGLContext : public BaseEGLContext { virtual void SetSwapInterval(int interval); // Implement BaseEGLContext. - virtual EGLSurface GetSurface(); + virtual SharedEGLSurface* GetSurface(); private: void* window_; - EGLSurface surface_; + scoped_refptr<SharedEGLSurface> surface_; EGLContext context_; DISALLOW_COPY_AND_ASSIGN(NativeViewEGLContext); }; // Encapsulates an EGL OpenGL ES context intended for offscreen use. It is -// actually associated with a native window and will render to it. The caller -// must bind an FBO to prevent this. Not using pbuffers because ANGLE does not -// support them. +// actually associated with a native window or a pbuffer on supporting platforms +// and will render to it. The caller must bind an FBO to prevent this. +// TODO(apatrick): implement pbuffers in ANGLE and change this to +// PbufferEGLContext and use it on all EGL platforms. class SecondaryEGLContext : public BaseEGLContext { public: SecondaryEGLContext(); @@ -89,12 +105,10 @@ class SecondaryEGLContext : public BaseEGLContext { virtual void SetSwapInterval(int interval); // Implement BaseEGLContext. - virtual EGLSurface GetSurface(); + virtual SharedEGLSurface* GetSurface(); private: - // All offscreen - EGLSurface surface_; - bool own_surface_; + scoped_refptr<SharedEGLSurface> surface_; EGLContext context_; DISALLOW_COPY_AND_ASSIGN(SecondaryEGLContext); |