summaryrefslogtreecommitdiffstats
path: root/ui/gfx/gl
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-14 00:11:59 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-14 00:11:59 +0000
commit24edbd0b34b7177a781da8f5d0bbf4121d692b31 (patch)
treebf2e9f5b9e21ad74b358e48821d0dc1d63bb700c /ui/gfx/gl
parent866940781aa790de0a1e35f5d76163198e85e11c (diff)
downloadchromium_src-24edbd0b34b7177a781da8f5d0bbf4121d692b31.zip
chromium_src-24edbd0b34b7177a781da8f5d0bbf4121d692b31.tar.gz
chromium_src-24edbd0b34b7177a781da8f5d0bbf4121d692b31.tar.bz2
Split EGLContext in GLContextEGL and GLSurfaceEGL.
Surfaces are independent of contexts in GL. To facilitate sharing of surfaces between processes, I have separated them from the notion of contexts because contexts cannot be shared between processes. I have started with EGL. GLContextEGL still has a pointer to a surface and still has some surface specific operations that just forward through to it. Once I have refactored all the GLContext implementations in this way, I will remove these pointers and the surface specific opertations. There will not be "view" and "offscreen" GL contexts. Rather there will be a single context type for each backend which can be made current with a surface that directs output either to a view or offscreen surface. TEST=try, WebGL puppy works BUG=none Review URL: http://codereview.chromium.org/6839008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81512 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx/gl')
-rw-r--r--ui/gfx/gl/egl_util.cc47
-rw-r--r--ui/gfx/gl/egl_util.h15
-rw-r--r--ui/gfx/gl/gl.gyp37
-rw-r--r--ui/gfx/gl/gl_context_egl.cc364
-rw-r--r--ui/gfx/gl/gl_context_egl.h92
-rw-r--r--ui/gfx/gl/gl_context_linux.cc24
-rw-r--r--ui/gfx/gl/gl_context_win.cc38
-rw-r--r--ui/gfx/gl/gl_surface.cc13
-rw-r--r--ui/gfx/gl/gl_surface.h56
-rw-r--r--ui/gfx/gl/gl_surface_egl.cc245
-rw-r--r--ui/gfx/gl/gl_surface_egl.h80
11 files changed, 557 insertions, 454 deletions
diff --git a/ui/gfx/gl/egl_util.cc b/ui/gfx/gl/egl_util.cc
new file mode 100644
index 0000000..29eb92d
--- /dev/null
+++ b/ui/gfx/gl/egl_util.cc
@@ -0,0 +1,47 @@
+// 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/egl_util.h"
+
+#include "third_party/angle/include/EGL/egl.h"
+#include "ui/gfx/gl/gl_bindings.h"
+
+namespace gfx {
+
+// Returns the last EGL error as a string.
+const char* GetLastEGLErrorString() {
+ EGLint error = eglGetError();
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gfx/gl/egl_util.h b/ui/gfx/gl/egl_util.h
new file mode 100644
index 0000000..71f471f
--- /dev/null
+++ b/ui/gfx/gl/egl_util.h
@@ -0,0 +1,15 @@
+// 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_EGL_UTIL_H_
+#define UI_GFX_GL_EGL_UTIL_H_
+
+namespace gfx {
+
+// Returns the last EGL error as a string.
+const char* GetLastEGLErrorString();
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_EGL_UTIL_H_
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp
index 4cdb279..50a9785 100644
--- a/ui/gfx/gl/gl.gyp
+++ b/ui/gfx/gl/gl.gyp
@@ -55,7 +55,6 @@
],
},
'sources': [
- 'gl_bindings.gypi',
'gl_bindings.h',
'gl_bindings_skia_in_process.cc',
'gl_bindings_skia_in_process.h',
@@ -75,6 +74,8 @@
'gl_implementation_win.cc',
'gl_interface.cc',
'gl_interface.h',
+ 'gl_surface.cc',
+ 'gl_surface.h',
'gl_switches.cc',
'gl_switches.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_gl.cc',
@@ -115,25 +116,38 @@
},
],
'conditions': [
- ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="win"', {
'sources': [
+ 'egl_util.cc',
+ 'egl_util.h',
'gl_context_egl.cc',
'gl_context_egl.h',
+ 'gl_surface_egl.cc',
+ 'gl_surface_egl.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
'<(gl_binding_output_dir)/gl_bindings_autogen_egl.h',
- '<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc',
- '<(gl_binding_output_dir)/gl_bindings_autogen_glx.h',
],
'include_dirs': [
- # We don't use angle, but pull the EGL/GLES headers from there.
'<(DEPTH)/third_party/angle/include',
],
+ }],
+ ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+ 'sources': [
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.h',
+ ],
'all_dependent_settings': {
'defines': [
'GL_GLEXT_PROTOTYPES',
],
},
}],
+ ['OS=="win"', {
+ 'sources': [
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h',
+ ],
+ }],
['OS=="mac"', {
'link_settings': {
'libraries': [
@@ -141,19 +155,6 @@
],
},
}],
- ['OS=="win"', {
- 'sources': [
- 'gl_context_egl.cc',
- 'gl_context_egl.h',
- '<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
- '<(gl_binding_output_dir)/gl_bindings_autogen_egl.h',
- '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.cc',
- '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h',
- ],
- 'include_dirs': [
- '<(DEPTH)/third_party/angle/include',
- ],
- }],
],
},
],
diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc
index 967329d..dd2ed27 100644
--- a/ui/gfx/gl/gl_context_egl.cc
+++ b/ui/gfx/gl/gl_context_egl.cc
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "ui/gfx/gl/gl_context_egl.h"
#include "build/build_config.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/angle/include/EGL/egl.h"
-#include "ui/gfx/gl/gl_context_egl.h"
+#include "ui/gfx/gl/gl_surface_egl.h"
+#include "ui/gfx/gl/egl_util.h"
// This header must come after the above third-party include, as
// it brings in #defines that cause conflicts.
@@ -22,180 +24,37 @@ extern "C" {
namespace gfx {
-namespace {
-
-// The EGL configuration to use.
-EGLDisplay g_display;
-EGLConfig g_config;
-
-// Returns the last EGL error as a string.
-const char* GetLastEGLErrorString() {
- EGLint error = eglGetError();
- switch (error) {
- case EGL_SUCCESS:
- return "EGL_SUCCESS";
- case EGL_BAD_ACCESS:
- return "EGL_BAD_ACCESS";
- case EGL_BAD_ALLOC:
- return "EGL_BAD_ALLOC";
- case EGL_BAD_ATTRIBUTE:
- return "EGL_BAD_ATTRIBUTE";
- case EGL_BAD_CONTEXT:
- return "EGL_BAD_CONTEXT";
- case EGL_BAD_CONFIG:
- return "EGL_BAD_CONFIG";
- case EGL_BAD_CURRENT_SURFACE:
- return "EGL_BAD_CURRENT_SURFACE";
- case EGL_BAD_DISPLAY:
- return "EGL_BAD_DISPLAY";
- case EGL_BAD_SURFACE:
- return "EGL_BAD_SURFACE";
- case EGL_BAD_MATCH:
- return "EGL_BAD_MATCH";
- case EGL_BAD_PARAMETER:
- return "EGL_BAD_PARAMETER";
- case EGL_BAD_NATIVE_PIXMAP:
- return "EGL_BAD_NATIVE_PIXMAP";
- case EGL_BAD_NATIVE_WINDOW:
- return "EGL_BAD_NATIVE_WINDOW";
- default:
- return "UNKNOWN";
- }
-}
-} // 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)
- return true;
-
-#ifdef OS_LINUX
- EGLNativeDisplayType native_display = XOpenDisplay(NULL);
-#else
- EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY;
-#endif
- g_display = eglGetDisplay(native_display);
- if (!g_display) {
- LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
- return false;
- }
-
- if (!eglInitialize(g_display, NULL, NULL)) {
- LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
- return false;
- }
-
- // Choose an EGL configuration.
- static const EGLint kConfigAttribs[] = {
- EGL_BUFFER_SIZE, 32,
- EGL_ALPHA_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_RED_SIZE, 8,
- EGL_DEPTH_SIZE, 16,
- EGL_STENCIL_SIZE, 8,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#ifdef EGL_HAS_PBUFFERS
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
-#else
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-#endif
- EGL_NONE
- };
-
- EGLint num_configs;
- if (!eglChooseConfig(g_display,
- kConfigAttribs,
- NULL,
- 0,
- &num_configs)) {
- LOG(ERROR) << "eglChooseConfig failed failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
- if (num_configs == 0) {
- LOG(ERROR) << "No suitable EGL configs found.";
- return false;
- }
-
- scoped_array<EGLConfig> configs(new EGLConfig[num_configs]);
- if (!eglChooseConfig(g_display,
- kConfigAttribs,
- configs.get(),
- num_configs,
- &num_configs)) {
- LOG(ERROR) << "eglChooseConfig failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
- g_config = configs[0];
-
- initialized = true;
- return true;
-}
-
-EGLDisplay BaseEGLContext::GetDisplay() {
- return g_display;
-}
-
-std::string BaseEGLContext::GetExtensions() {
- const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS);
+std::string GLContextEGL::GetExtensions() {
+ const char* extensions = eglQueryString(GLSurfaceEGL::GetDisplay(),
+ EGL_EXTENSIONS);
if (!extensions)
return GLContext::GetExtensions();
return GLContext::GetExtensions() + " " + extensions;
}
-NativeViewEGLContext::NativeViewEGLContext(void* window)
- : window_(window),
+GLContextEGL::GLContextEGL(GLSurfaceEGL* surface)
+ : surface_(surface),
context_(NULL)
{
}
-NativeViewEGLContext::~NativeViewEGLContext() {
+GLContextEGL::~GLContextEGL() {
}
-bool NativeViewEGLContext::Initialize() {
+bool GLContextEGL::Initialize(GLContext* shared_context) {
DCHECK(!context_);
- // Create a surface for the native window.
- EGLNativeWindowType native_window =
- reinterpret_cast<EGLNativeWindowType>(window_);
- surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display,
- g_config,
- native_window,
- NULL));
-
- if (!surface_->egl_surface()) {
- LOG(ERROR) << "eglCreateWindowSurface failed with error "
- << GetLastEGLErrorString();
- Destroy();
- return false;
- }
-
static const EGLint kContextAttributes[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
- context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
+ context_ = eglCreateContext(
+ GLSurfaceEGL::GetDisplay(),
+ GLSurfaceEGL::GetConfig(),
+ shared_context ? shared_context->GetHandle() : NULL,
+ kContextAttributes);
if (!context_) {
LOG(ERROR) << "eglCreateContext failed with error "
<< GetLastEGLErrorString();
@@ -218,26 +77,25 @@ bool NativeViewEGLContext::Initialize() {
return true;
}
-void NativeViewEGLContext::Destroy() {
+void GLContextEGL::Destroy() {
if (context_) {
- if (!eglDestroyContext(g_display, context_)) {
+ if (!eglDestroyContext(GLSurfaceEGL::GetDisplay(), context_)) {
LOG(ERROR) << "eglDestroyContext failed with error "
<< GetLastEGLErrorString();
}
context_ = NULL;
}
-
- surface_ = NULL;
}
-bool NativeViewEGLContext::MakeCurrent() {
+bool GLContextEGL::MakeCurrent() {
DCHECK(context_);
- if (context_ == eglGetCurrentContext())
+ if (IsCurrent())
return true;
- if (!eglMakeCurrent(g_display,
- surface_->egl_surface(),
- surface_->egl_surface(),
+
+ if (!eglMakeCurrent(GLSurfaceEGL::GetDisplay(),
+ surface_->GetHandle(),
+ surface_->GetHandle(),
context_)) {
VLOG(1) << "eglMakeCurrent failed with error "
<< GetLastEGLErrorString();
@@ -247,186 +105,36 @@ bool NativeViewEGLContext::MakeCurrent() {
return true;
}
-bool NativeViewEGLContext::IsCurrent() {
+bool GLContextEGL::IsCurrent() {
DCHECK(context_);
return context_ == eglGetCurrentContext();
}
-bool NativeViewEGLContext::IsOffscreen() {
- return false;
+bool GLContextEGL::IsOffscreen() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->IsOffscreen();
}
-bool NativeViewEGLContext::SwapBuffers() {
- if (!eglSwapBuffers(g_display, surface_->egl_surface())) {
- VLOG(1) << "eglSwapBuffers failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
- return true;
+bool GLContextEGL::SwapBuffers() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->SwapBuffers();
}
-gfx::Size NativeViewEGLContext::GetSize() {
-#if defined(OS_WIN)
- RECT rect;
- if (!GetClientRect(static_cast<HWND>(window_), &rect)) {
- DCHECK(false) << "GetClientRect failed.";
- return gfx::Size();
- }
-
- return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
-#else
- // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't
- // get updated on resize. When it does, we can share the code.
- EGLint width;
- EGLint 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();
- }
-
- return gfx::Size(width, height);
-#endif
+gfx::Size GLContextEGL::GetSize() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->GetSize();
}
-void* NativeViewEGLContext::GetHandle() {
+void* GLContextEGL::GetHandle() {
return context_;
}
-void NativeViewEGLContext::SetSwapInterval(int interval) {
+void GLContextEGL::SetSwapInterval(int interval) {
DCHECK(IsCurrent());
- if (!eglSwapInterval(g_display, interval)) {
+ if (!eglSwapInterval(GLSurfaceEGL::GetDisplay(), interval)) {
LOG(ERROR) << "eglSwapInterval failed with error "
<< GetLastEGLErrorString();
}
}
-SharedEGLSurface* NativeViewEGLContext::GetSurface() {
- return surface_;
-}
-
-SecondaryEGLContext::SecondaryEGLContext()
- : context_(NULL)
-{
-}
-
-SecondaryEGLContext::~SecondaryEGLContext() {
-}
-
-bool SecondaryEGLContext::Initialize(GLContext* shared_context) {
- DCHECK(!context_);
-
- static const EGLint kContextAttributes[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
-
- if (shared_context) {
- surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface();
-
- // Create a context.
- context_ = eglCreateContext(g_display,
- g_config,
- shared_context->GetHandle(),
- kContextAttributes);
- } else {
-#ifdef EGL_HAS_PBUFFERS
- static const EGLint kPbufferAttribs[] = {
- EGL_WIDTH, 1,
- EGL_HEIGHT, 1,
- EGL_NONE
- };
-
- surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display,
- g_config,
- kPbufferAttribs));
- if (!surface_->egl_surface()) {
- LOG(ERROR) << "eglCreatePbufferSurface failed with error "
- << GetLastEGLErrorString();
- Destroy();
- return false;
- }
-
- context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
-#else
- NOTIMPLEMENTED() << "Offscreen non-shared GLES context";
- return false;
-#endif
- }
-
- if (!context_) {
- LOG(ERROR) << "eglCreateContext failed with error "
- << GetLastEGLErrorString();
- Destroy();
- return false;
- }
-
- return true;
-}
-
-void SecondaryEGLContext::Destroy() {
- if (context_) {
- if (!eglDestroyContext(g_display, context_)) {
- LOG(ERROR) << "eglDestroyContext failed with error "
- << GetLastEGLErrorString();
- }
-
- context_ = NULL;
- }
-
- surface_ = NULL;
-}
-
-bool SecondaryEGLContext::MakeCurrent() {
- DCHECK(context_);
- if (context_ == eglGetCurrentContext())
- return true;
- if (!eglMakeCurrent(g_display,
- surface_->egl_surface(),
- surface_->egl_surface(),
- context_)) {
- VLOG(1) << "eglMakeCurrent failed with error "
- << GetLastEGLErrorString();
- return false;
- }
-
- return true;
-}
-
-bool SecondaryEGLContext::IsCurrent() {
- DCHECK(context_);
- return context_ == eglGetCurrentContext();
-}
-
-bool SecondaryEGLContext::IsOffscreen() {
- return true;
-}
-
-bool SecondaryEGLContext::SwapBuffers() {
- NOTREACHED() << "Attempted to call SwapBuffers on a SecondaryEGLContext.";
- return false;
-}
-
-gfx::Size SecondaryEGLContext::GetSize() {
- NOTREACHED() << "Should not be requesting size of this SecondaryEGLContext.";
- return gfx::Size(1, 1);
-}
-
-void* SecondaryEGLContext::GetHandle() {
- return context_;
-}
-
-void SecondaryEGLContext::SetSwapInterval(int interval) {
- DCHECK(IsCurrent());
- NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext.";
-}
-
-SharedEGLSurface* SecondaryEGLContext::GetSurface() {
- return surface_;
-}
-
} // namespace gfx
diff --git a/ui/gfx/gl/gl_context_egl.h b/ui/gfx/gl/gl_context_egl.h
index 4250457..43cbe922 100644
--- a/ui/gfx/gl/gl_context_egl.h
+++ b/ui/gfx/gl/gl_context_egl.h
@@ -6,92 +6,28 @@
#define UI_GFX_GL_GL_CONTEXT_EGL_H_
#pragma once
-#include "base/memory/ref_counted.h"
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
#include "ui/gfx/gl/gl_context.h"
#include "ui/gfx/size.h"
-typedef void* EGLDisplay;
typedef void* EGLContext;
-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 {
- public:
- BaseEGLContext() {}
- virtual ~BaseEGLContext() {}
-
- static bool InitializeOneOff();
-
- static EGLDisplay GetDisplay();
-
- // Get the associated EGL surface.
- virtual SharedEGLSurface* GetSurface() = 0;
-
- // Implement GLContext.
- virtual std::string GetExtensions();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BaseEGLContext);
-};
+class GLSurfaceEGL;
// Encapsulates an EGL OpenGL ES context that renders to a view.
-class NativeViewEGLContext : public BaseEGLContext {
+class GLContextEGL : public GLContext {
public:
- explicit NativeViewEGLContext(void* window);
- virtual ~NativeViewEGLContext();
+ // Takes ownership of surface. TODO(apatrick): separate notion of surface
+ // from context.
+ explicit GLContextEGL(GLSurfaceEGL* surface);
- // Initialize an EGL context.
- bool Initialize();
+ virtual ~GLContextEGL();
- // Implement GLContext.
- virtual void Destroy();
- virtual bool MakeCurrent();
- virtual bool IsCurrent();
- virtual bool IsOffscreen();
- virtual bool SwapBuffers();
- virtual gfx::Size GetSize();
- virtual void* GetHandle();
- virtual void SetSwapInterval(int interval);
-
- // Implement BaseEGLContext.
- virtual SharedEGLSurface* GetSurface();
-
- private:
- void* window_;
- 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 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();
- virtual ~SecondaryEGLContext();
-
- // Initialize an EGL context that shares a namespace with another.
+ // Initialize an EGL context.
bool Initialize(GLContext* shared_context);
// Implement GLContext.
@@ -103,15 +39,13 @@ class SecondaryEGLContext : public BaseEGLContext {
virtual gfx::Size GetSize();
virtual void* GetHandle();
virtual void SetSwapInterval(int interval);
-
- // Implement BaseEGLContext.
- virtual SharedEGLSurface* GetSurface();
+ virtual std::string GetExtensions();
private:
- scoped_refptr<SharedEGLSurface> surface_;
+ scoped_ptr<GLSurfaceEGL> surface_;
EGLContext context_;
- DISALLOW_COPY_AND_ASSIGN(SecondaryEGLContext);
+ DISALLOW_COPY_AND_ASSIGN(GLContextEGL);
};
} // namespace gfx
diff --git a/ui/gfx/gl/gl_context_linux.cc b/ui/gfx/gl/gl_context_linux.cc
index 430bba5..1a114d8 100644
--- a/ui/gfx/gl/gl_context_linux.cc
+++ b/ui/gfx/gl/gl_context_linux.cc
@@ -21,6 +21,7 @@ extern "C" {
#include "ui/gfx/gl/gl_context_osmesa.h"
#include "ui/gfx/gl/gl_context_stub.h"
#include "ui/gfx/gl/gl_implementation.h"
+#include "ui/gfx/gl/gl_surface_egl.h"
namespace {
@@ -217,8 +218,8 @@ bool GLContext::InitializeOneOff() {
break;
}
case kGLImplementationEGLGLES2:
- if (!BaseEGLContext::InitializeOneOff()) {
- LOG(ERROR) << "BaseEGLContext::InitializeOneOff failed.";
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
return false;
}
break;
@@ -515,9 +516,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
return context.release();
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<NativeViewEGLContext> context(
- new NativeViewEGLContext(reinterpret_cast<void *>(window)));
- if (!context->Initialize())
+ scoped_ptr<NativeViewGLSurfaceEGL> surface(new NativeViewGLSurfaceEGL(
+ reinterpret_cast<void*>(window)));
+ if (!surface->Initialize())
+ return NULL;
+
+ scoped_ptr<GLContextEGL> context(
+ new GLContextEGL(surface.release()));
+ if (!context->Initialize(NULL))
return NULL;
return context.release();
@@ -805,8 +811,12 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) {
return NULL;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<SecondaryEGLContext> context(
- new SecondaryEGLContext());
+ scoped_ptr<PbufferGLSurfaceEGL> surface(new PbufferGLSurfaceEGL(
+ gfx::Size(1, 1)));
+ if (!surface->Initialize())
+ return NULL;
+
+ scoped_ptr<GLContextEGL> context(new GLContextEGL(surface.release()));
if (!context->Initialize(shared_context))
return NULL;
diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc
index 23f98b2..d2bbe77 100644
--- a/ui/gfx/gl/gl_context_win.cc
+++ b/ui/gfx/gl/gl_context_win.cc
@@ -17,6 +17,7 @@
#include "ui/gfx/gl/gl_context_osmesa.h"
#include "ui/gfx/gl/gl_context_stub.h"
#include "ui/gfx/gl/gl_implementation.h"
+#include "ui/gfx/gl/gl_surface_egl.h"
namespace gfx {
@@ -132,10 +133,6 @@ static HWND g_window;
static int g_regular_pixel_format = 0;
static int g_multisampled_pixel_format = 0;
-// When using ANGLE we still need a window for D3D. This context creates the
-// D3D device.
-static BaseEGLContext* g_default_context;
-
const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
sizeof(kPixelFormatDescriptor), // Size of structure.
1, // Default version.
@@ -313,8 +310,8 @@ bool GLContext::InitializeOneOff() {
break;
}
case kGLImplementationEGLGLES2:
- if (!BaseEGLContext::InitializeOneOff()) {
- LOG(ERROR) << "BaseEGLContext::InitializeOneOff failed.";
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
return false;
}
break;
@@ -551,9 +548,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
return context.release();
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<NativeViewEGLContext> context(
- new NativeViewEGLContext(window));
- if (!context->Initialize())
+ scoped_ptr<NativeViewGLSurfaceEGL> surface(new NativeViewGLSurfaceEGL(
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ scoped_ptr<GLContextEGL> context(
+ new GLContextEGL(surface.release()));
+ if (!context->Initialize(NULL))
return NULL;
return context.release();
@@ -706,20 +708,12 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) {
return context.release();
}
case kGLImplementationEGLGLES2: {
- if (!shared_context) {
- if (!g_default_context) {
- scoped_ptr<NativeViewEGLContext> default_context(
- new NativeViewEGLContext(g_window));
- if (!default_context->Initialize())
- return NULL;
-
- g_default_context = default_context.release();
- }
- shared_context = g_default_context;
- }
+ scoped_ptr<PbufferGLSurfaceEGL> surface(new PbufferGLSurfaceEGL(
+ gfx::Size(1, 1)));
+ if (!surface->Initialize())
+ return NULL;
- scoped_ptr<SecondaryEGLContext> context(
- new SecondaryEGLContext());
+ scoped_ptr<GLContextEGL> context(new GLContextEGL(surface.release()));
if (!context->Initialize(shared_context))
return NULL;
diff --git a/ui/gfx/gl/gl_surface.cc b/ui/gfx/gl/gl_surface.cc
new file mode 100644
index 0000000..b1dd505
--- /dev/null
+++ b/ui/gfx/gl/gl_surface.cc
@@ -0,0 +1,13 @@
+// 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/gl_surface.h"
+
+namespace gfx {
+
+unsigned int GLSurface::GetBackingFrameBufferObject() {
+ return 0;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h
new file mode 100644
index 0000000..c0ab1e9
--- /dev/null
+++ b/ui/gfx/gl/gl_surface.h
@@ -0,0 +1,56 @@
+// 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_GL_SURFACE_H_
+#define UI_GFX_GL_GL_SURFACE_H_
+#pragma once
+
+#include "build/build_config.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+
+namespace gfx {
+
+// Encapsulates a surface that can be rendered to with GL, hiding platform
+// specific management.
+class GLSurface {
+ public:
+ GLSurface() {}
+ virtual ~GLSurface() {}
+
+ // Destroys the surface.
+ virtual void Destroy() = 0;
+
+ // Returns true if this surface is offscreen.
+ virtual bool IsOffscreen() = 0;
+
+ // Swaps front and back buffers. This has no effect for off-screen
+ // contexts.
+ virtual bool SwapBuffers() = 0;
+
+ // Get the size of the surface.
+ virtual gfx::Size GetSize() = 0;
+
+ // Get the underlying platform specific surface "handle".
+ virtual void* GetHandle() = 0;
+
+ // Returns the internal frame buffer object name if the surface is backed by
+ // FBO. Otherwise returns 0.
+ virtual unsigned int GetBackingFrameBufferObject();
+
+#if !defined(OS_MACOSX)
+ // Create a surface corresponding to a view.
+ static GLSurface* CreateViewGLContext(gfx::PluginWindowHandle window);
+#endif
+
+ // Create a surface used for offscreen rendering.
+ static GLSurface* CreateOffscreenGLContext(const gfx::Size& size);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurface);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_GL_SURFACE_H_
diff --git a/ui/gfx/gl/gl_surface_egl.cc b/ui/gfx/gl/gl_surface_egl.cc
new file mode 100644
index 0000000..ae17a1b
--- /dev/null
+++ b/ui/gfx/gl/gl_surface_egl.cc
@@ -0,0 +1,245 @@
+// 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/gl_surface_egl.h"
+
+#include "build/build_config.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/angle/include/EGL/egl.h"
+#include "ui/gfx/gl/egl_util.h"
+
+// This header must come after the above third-party include, as
+// it brings in #defines that cause conflicts.
+#include "ui/gfx/gl/gl_bindings.h"
+
+#if defined(OS_LINUX)
+extern "C" {
+#include <X11/Xlib.h>
+}
+#endif
+
+namespace gfx {
+
+namespace {
+EGLConfig g_config;
+EGLDisplay g_display;
+}
+
+GLSurfaceEGL::GLSurfaceEGL() {
+}
+
+GLSurfaceEGL::~GLSurfaceEGL() {
+}
+
+bool GLSurfaceEGL::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+#ifdef OS_LINUX
+ EGLNativeDisplayType native_display = XOpenDisplay(NULL);
+#else
+ EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY;
+#endif
+ g_display = eglGetDisplay(native_display);
+ if (!g_display) {
+ LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
+ return false;
+ }
+
+ if (!eglInitialize(g_display, NULL, NULL)) {
+ LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
+ return false;
+ }
+
+ // Choose an EGL configuration.
+ static const EGLint kConfigAttribs[] = {
+ EGL_BUFFER_SIZE, 32,
+ EGL_ALPHA_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_DEPTH_SIZE, 16,
+ EGL_STENCIL_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#ifdef EGL_HAS_PBUFFERS
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+#else
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+#endif
+ EGL_NONE
+ };
+
+ EGLint num_configs;
+ if (!eglChooseConfig(g_display,
+ kConfigAttribs,
+ NULL,
+ 0,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ if (num_configs == 0) {
+ LOG(ERROR) << "No suitable EGL configs found.";
+ return false;
+ }
+
+ scoped_array<EGLConfig> configs(new EGLConfig[num_configs]);
+ if (!eglChooseConfig(g_display,
+ kConfigAttribs,
+ configs.get(),
+ num_configs,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ g_config = configs[0];
+
+ initialized = true;
+ return true;
+}
+
+EGLDisplay GLSurfaceEGL::GetDisplay() {
+ return g_display;
+}
+
+EGLConfig GLSurfaceEGL::GetConfig() {
+ return g_config;
+}
+
+NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(void* window)
+ : window_(window),
+ surface_(NULL)
+{
+}
+
+NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceEGL::Initialize() {
+ DCHECK(!surface_);
+
+ // Create a surface for the native window.
+ EGLNativeWindowType native_window =
+ reinterpret_cast<EGLNativeWindowType>(window_);
+ surface_ = eglCreateWindowSurface(g_display,
+ g_config,
+ native_window,
+ NULL);
+
+ if (!surface_) {
+ LOG(ERROR) << "eglCreateWindowSurface failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void NativeViewGLSurfaceEGL::Destroy() {
+ if (surface_) {
+ if (!eglDestroySurface(g_display, surface_)) {
+ LOG(ERROR) << "eglDestroySurface failed with error "
+ << GetLastEGLErrorString();
+ }
+ surface_ = NULL;
+ }
+}
+
+bool NativeViewGLSurfaceEGL::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceEGL::SwapBuffers() {
+ if (!eglSwapBuffers(g_display, surface_)) {
+ VLOG(1) << "eglSwapBuffers failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ return true;
+}
+
+gfx::Size NativeViewGLSurfaceEGL::GetSize() {
+ EGLint width;
+ EGLint height;
+ if (!eglQuerySurface(g_display, surface_, EGL_WIDTH, &width) ||
+ !eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height)) {
+ NOTREACHED() << "eglQuerySurface failed with error "
+ << GetLastEGLErrorString();
+ return gfx::Size();
+ }
+
+ return gfx::Size(width, height);
+}
+
+EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
+ return surface_;
+}
+
+PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(const gfx::Size& size)
+ : size_(size),
+ surface_(NULL) {
+}
+
+PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
+ Destroy();
+}
+
+bool PbufferGLSurfaceEGL::Initialize() {
+ DCHECK(!surface_);
+
+ const EGLint pbuffer_attribs[] = {
+ EGL_WIDTH, size_.width(),
+ EGL_HEIGHT, size_.height(),
+ EGL_NONE
+ };
+
+ surface_ = eglCreatePbufferSurface(g_display,
+ g_config,
+ pbuffer_attribs);
+ if (!surface_) {
+ LOG(ERROR) << "eglCreatePbufferSurface failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLSurfaceEGL::Destroy() {
+ if (surface_) {
+ if (!eglDestroySurface(g_display, surface_)) {
+ LOG(ERROR) << "eglDestroySurface failed with error "
+ << GetLastEGLErrorString();
+ }
+ surface_ = NULL;
+ }
+}
+
+bool PbufferGLSurfaceEGL::IsOffscreen() {
+ return true;
+}
+
+bool PbufferGLSurfaceEGL::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
+ return false;
+}
+
+gfx::Size PbufferGLSurfaceEGL::GetSize() {
+ return size_;
+}
+
+EGLSurface PbufferGLSurfaceEGL::GetHandle() {
+ return surface_;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/gl/gl_surface_egl.h b/ui/gfx/gl/gl_surface_egl.h
new file mode 100644
index 0000000..9ff1c2b
--- /dev/null
+++ b/ui/gfx/gl/gl_surface_egl.h
@@ -0,0 +1,80 @@
+// 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_GL_SURFACE_EGL_H_
+#define UI_GFX_GL_GL_SURFACE_EGL_H_
+#pragma once
+
+#include "ui/gfx/gl/gl_surface.h"
+#include "ui/gfx/size.h"
+
+typedef void* EGLConfig;
+typedef void* EGLDisplay;
+typedef void* EGLSurface;
+
+namespace gfx {
+
+// Interface for EGL contexts.
+class GLSurfaceEGL : public GLSurface {
+ public:
+ GLSurfaceEGL();
+ virtual ~GLSurfaceEGL();
+
+ static bool InitializeOneOff();
+ static EGLDisplay GetDisplay();
+ static EGLConfig GetConfig();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceEGL);
+};
+
+// Encapsulates an EGL surface bound to a view.
+class NativeViewGLSurfaceEGL : public GLSurfaceEGL {
+ public:
+ explicit NativeViewGLSurfaceEGL(void* window);
+ virtual ~NativeViewGLSurfaceEGL();
+
+ // Initialize an EGL context.
+ bool Initialize();
+
+ // Implement GLSurface.
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual EGLSurface GetHandle();
+
+ private:
+ void* window_;
+ EGLSurface surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceEGL);
+};
+
+// Encapsulates a pbuffer EGL surface.
+class PbufferGLSurfaceEGL : public GLSurfaceEGL {
+ public:
+ explicit PbufferGLSurfaceEGL(const gfx::Size& size);
+ virtual ~PbufferGLSurfaceEGL();
+
+ // Initialize an EGL context that shares a namespace with another.
+ bool Initialize();
+
+ // Implement GLSurface.
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual EGLSurface GetHandle();
+
+ private:
+ gfx::Size size_;
+ EGLSurface surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceEGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_GL_SURFACE_EGL_H_