summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-01 01:46:38 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-01 01:46:38 +0000
commitfbe2037a09135bc592d77d10ebe7b057a4a6b3d2 (patch)
treebb6f4abca72b53bdf9e8ca860dba420dec09b448 /ui/gfx
parent1cce54290389788770bff8997c5d9fe7f323e3ea (diff)
downloadchromium_src-fbe2037a09135bc592d77d10ebe7b057a4a6b3d2.zip
chromium_src-fbe2037a09135bc592d77d10ebe7b057a4a6b3d2.tar.gz
chromium_src-fbe2037a09135bc592d77d10ebe7b057a4a6b3d2.tar.bz2
Reland 87371 - Support for glSetSurfaceCHROMIUM.
This command allows a previously created GPU surface to be made current for a command buffer. There are no surfaces registered at this point so this command is currently a no-op. Review URL: http://codereview.chromium.org/7077001 Review URL: http://codereview.chromium.org/7006019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87408 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/compositor/compositor_gl.cc16
-rw-r--r--ui/gfx/gl/gl_context.cc6
-rw-r--r--ui/gfx/gl/gl_context.h15
-rw-r--r--ui/gfx/gl/gl_context_linux.cc17
-rw-r--r--ui/gfx/gl/gl_context_mac.cc13
-rw-r--r--ui/gfx/gl/gl_context_win.cc17
-rw-r--r--ui/gfx/gl/gl_interface.h2
-rw-r--r--ui/gfx/gl/gl_surface.h14
-rw-r--r--ui/gfx/gl/gl_surface_linux.cc32
-rw-r--r--ui/gfx/gl/gl_surface_mac.cc24
-rw-r--r--ui/gfx/gl/gl_surface_win.cc32
-rw-r--r--ui/gfx/surface/accelerated_surface_mac.cc10
-rw-r--r--ui/gfx/surface/accelerated_surface_mac.h4
13 files changed, 115 insertions, 87 deletions
diff --git a/ui/gfx/compositor/compositor_gl.cc b/ui/gfx/compositor/compositor_gl.cc
index cacf54b..7e6e297 100644
--- a/ui/gfx/compositor/compositor_gl.cc
+++ b/ui/gfx/compositor/compositor_gl.cc
@@ -71,8 +71,8 @@ class CompositorGL : public Compositor {
bool InitShaders();
// The GL context used for compositing.
- scoped_ptr<gfx::GLSurface> gl_surface_;
- scoped_ptr<gfx::GLContext> gl_context_;
+ scoped_refptr<gfx::GLSurface> gl_surface_;
+ scoped_refptr<gfx::GLContext> gl_context_;
gfx::Size size_;
// Shader program, attributes and uniforms.
@@ -205,8 +205,8 @@ void TextureGL::Draw(const ui::Transform& transform) {
CompositorGL::CompositorGL(gfx::AcceleratedWidget widget)
: started_(false) {
- gl_surface_.reset(gfx::GLSurface::CreateViewGLSurface(widget));
- gl_context_.reset(gfx::GLContext::CreateGLContext(NULL, gl_surface_.get())),
+ gl_surface_ = gfx::GLSurface::CreateViewGLSurface(widget);
+ gl_context_ = gfx::GLContext::CreateGLContext(NULL, gl_surface_.get());
gl_context_->MakeCurrent(gl_surface_.get());
if (!InitShaders())
LOG(ERROR) << "Unable to initialize shaders (context = "
@@ -372,8 +372,8 @@ class CompositorGL : public Compositor {
void RestoreTransform() OVERRIDE;
// The GL context used for compositing.
- scoped_ptr<gfx::GLSurface> gl_surface_;
- scoped_ptr<gfx::GLContext> gl_context_;
+ scoped_refptr<gfx::GLSurface> gl_surface_;
+ scoped_refptr<gfx::GLContext> gl_context_;
// Keep track of whether compositing has started or not.
bool started_;
@@ -383,8 +383,8 @@ class CompositorGL : public Compositor {
CompositorGL::CompositorGL(gfx::AcceleratedWidget widget)
: started_(false) {
- gl_surface_.reset(gfx::GLSurface::CreateViewGLSurface(widget));
- gl_context_.reset(gfx::GLContext::CreateGLContext(NULL, gl_surface_.get()));
+ gl_surface_ = gfx::GLSurface::CreateViewGLSurface(widget);
+ gl_context_ = gfx::GLContext::CreateGLContext(NULL, gl_surface_.get());
}
void CompositorGL::NotifyStart() {
diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc
index 6391dc5..9cf1e40 100644
--- a/ui/gfx/gl/gl_context.cc
+++ b/ui/gfx/gl/gl_context.cc
@@ -13,6 +13,12 @@
namespace gfx {
+GLContext::GLContext() {
+}
+
+GLContext::~GLContext() {
+}
+
std::string GLContext::GetExtensions() {
DCHECK(IsCurrent(NULL));
const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h
index 45b944c..77f167f 100644
--- a/ui/gfx/gl/gl_context.h
+++ b/ui/gfx/gl/gl_context.h
@@ -9,16 +9,16 @@
#include <string>
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
namespace gfx {
class GLSurface;
// Encapsulates an OpenGL context, hiding platform specific management.
-class GLContext {
+class GLContext : public base::RefCounted<GLContext> {
public:
- GLContext() {}
- virtual ~GLContext() {}
+ GLContext();
// Initializes the GL context to be compatible with the given surface. The GL
// context can be made with other surface's of the same type. The compatible
@@ -56,12 +56,17 @@ class GLContext {
// Create a GL context that is compatible with the given surface.
// |share_context|, if non-NULL, is a context which the
// internally created OpenGL context shares textures and other resources.
- static GLContext* CreateGLContext(GLContext* shared_context,
- GLSurface* compatible_surface);
+ static scoped_refptr<GLContext> CreateGLContext(
+ GLContext* shared_context,
+ GLSurface* compatible_surface);
static bool LosesAllContextsOnContextLost();
+ protected:
+ virtual ~GLContext();
+
private:
+ friend class base::RefCounted<GLContext>;
DISALLOW_COPY_AND_ASSIGN(GLContext);
};
diff --git a/ui/gfx/gl/gl_context_linux.cc b/ui/gfx/gl/gl_context_linux.cc
index b68ed183..8cf2eeb 100644
--- a/ui/gfx/gl/gl_context_linux.cc
+++ b/ui/gfx/gl/gl_context_linux.cc
@@ -20,29 +20,30 @@
namespace gfx {
-GLContext* GLContext::CreateGLContext(GLContext* shared_context,
- GLSurface* compatible_surface) {
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLContext* shared_context,
+ GLSurface* compatible_surface) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLContextOSMesa> context(new GLContextOSMesa);
+ scoped_refptr<GLContext> context(new GLContextOSMesa);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<GLContextEGL> context(new GLContextEGL);
+ scoped_refptr<GLContext> context(new GLContextEGL);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<GLContextGLX> context(new GLContextGLX);
+ scoped_refptr<GLContext> context(new GLContextGLX);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationMockGL:
return new GLContextStub;
diff --git a/ui/gfx/gl/gl_context_mac.cc b/ui/gfx/gl/gl_context_mac.cc
index 5627d2c..482d93d 100644
--- a/ui/gfx/gl/gl_context_mac.cc
+++ b/ui/gfx/gl/gl_context_mac.cc
@@ -16,22 +16,23 @@
namespace gfx {
-GLContext* GLContext::CreateGLContext(GLContext* shared_context,
- GLSurface* compatible_surface) {
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLContext* shared_context,
+ GLSurface* compatible_surface) {
switch (GetGLImplementation()) {
case kGLImplementationDesktopGL: {
- scoped_ptr<GLContextCGL> context(new GLContextCGL);
+ scoped_refptr<GLContext> context(new GLContextCGL);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLContextOSMesa> context(new GLContextOSMesa);
+ scoped_refptr<GLContext> context(new GLContextOSMesa);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationMockGL:
return new GLContextStub;
diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc
index 90bca79..c9f90706 100644
--- a/ui/gfx/gl/gl_context_win.cc
+++ b/ui/gfx/gl/gl_context_win.cc
@@ -20,29 +20,30 @@
namespace gfx {
-GLContext* GLContext::CreateGLContext(GLContext* shared_context,
- GLSurface* compatible_surface) {
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLContext* shared_context,
+ GLSurface* compatible_surface) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLContextOSMesa> context(new GLContextOSMesa);
+ scoped_refptr<GLContext> context(new GLContextOSMesa);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<GLContextEGL> context(new GLContextEGL);
+ scoped_refptr<GLContext> context(new GLContextEGL);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<GLContextWGL> context(new GLContextWGL);
+ scoped_refptr<GLContext> context(new GLContextWGL);
if (!context->Initialize(shared_context, compatible_surface))
return NULL;
- return context.release();
+ return context;
}
case kGLImplementationMockGL:
return new GLContextStub;
diff --git a/ui/gfx/gl/gl_interface.h b/ui/gfx/gl/gl_interface.h
index bbd2b63..5422186 100644
--- a/ui/gfx/gl/gl_interface.h
+++ b/ui/gfx/gl/gl_interface.h
@@ -427,6 +427,8 @@ class GLInterface {
virtual void GetFenceivNV(GLuint fence, GLenum pname, GLint *params) = 0;
+ virtual void SetSurfaceCHROMIUM(GLuint id) = 0;
+
private:
static GLInterface* interface_;
};
diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h
index 9c1dcc4..513f37d 100644
--- a/ui/gfx/gl/gl_surface.h
+++ b/ui/gfx/gl/gl_surface.h
@@ -6,6 +6,7 @@
#define UI_GFX_GL_GL_SURFACE_H_
#pragma once
+#include "base/memory/ref_counted.h"
#include "build/build_config.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/size.h"
@@ -14,10 +15,9 @@ namespace gfx {
// Encapsulates a surface that can be rendered to with GL, hiding platform
// specific management.
-class GLSurface {
+class GLSurface : public base::RefCounted<GLSurface> {
public:
GLSurface();
- virtual ~GLSurface();
// (Re)create the surface. TODO(apatrick): This is an ugly hack to allow the
// EGL surface associated to be recreated without destroying the associated
@@ -49,13 +49,19 @@ class GLSurface {
#if !defined(OS_MACOSX)
// Create a GL surface that renders directly to a view.
- static GLSurface* CreateViewGLSurface(gfx::PluginWindowHandle window);
+ static scoped_refptr<GLSurface> CreateViewGLSurface(
+ gfx::PluginWindowHandle window);
#endif
// Create a GL surface used for offscreen rendering.
- static GLSurface* CreateOffscreenGLSurface(const gfx::Size& size);
+ static scoped_refptr<GLSurface> CreateOffscreenGLSurface(
+ const gfx::Size& size);
+
+ protected:
+ virtual ~GLSurface();
private:
+ friend class base::RefCounted<GLSurface>;
DISALLOW_COPY_AND_ASSIGN(GLSurface);
};
diff --git a/ui/gfx/gl/gl_surface_linux.cc b/ui/gfx/gl/gl_surface_linux.cc
index 26c1631..fe96989 100644
--- a/ui/gfx/gl/gl_surface_linux.cc
+++ b/ui/gfx/gl/gl_surface_linux.cc
@@ -243,31 +243,32 @@ bool NativeViewGLSurfaceOSMesa::UpdateSize() {
return true;
}
-GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ gfx::PluginWindowHandle window) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<NativeViewGLSurfaceOSMesa> surface(
+ scoped_refptr<GLSurface> surface(
new NativeViewGLSurfaceOSMesa(window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<NativeViewGLSurfaceEGL> surface(new NativeViewGLSurfaceEGL(
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(
window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<NativeViewGLSurfaceGLX> surface(new NativeViewGLSurfaceGLX(
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(
window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
@@ -277,29 +278,30 @@ GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
}
}
-GLSurface* GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) {
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ const gfx::Size& size) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
- size));
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<PbufferGLSurfaceEGL> surface(new PbufferGLSurfaceEGL(size));
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<PbufferGLSurfaceGLX> surface(new PbufferGLSurfaceGLX(size));
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
diff --git a/ui/gfx/gl/gl_surface_mac.cc b/ui/gfx/gl/gl_surface_mac.cc
index bb08ef8..2367679 100644
--- a/ui/gfx/gl/gl_surface_mac.cc
+++ b/ui/gfx/gl/gl_surface_mac.cc
@@ -50,23 +50,24 @@ bool GLSurface::InitializeOneOff() {
// TODO(apatrick): support ViewGLSurface on mac.
#if 0
-GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ gfx::PluginWindowHandle window) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<NativeViewGLSurfaceOSMesa> surface(
+ scoped_refptr<GLSurface> surface(
new NativeViewGLSurfaceOSMesa(window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<NativeViewGLSurfaceCGL> surface(new NativeViewGLSurfaceCGL(
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceCGL(
window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
@@ -77,22 +78,23 @@ GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
}
#endif
-GLSurface* GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) {
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ const gfx::Size& size) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
- size));
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<PbufferGLSurfaceCGL> surface(new PbufferGLSurfaceCGL(size));
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceCGL(size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
diff --git a/ui/gfx/gl/gl_surface_win.cc b/ui/gfx/gl/gl_surface_win.cc
index 594a263..6b3ea8c 100644
--- a/ui/gfx/gl/gl_surface_win.cc
+++ b/ui/gfx/gl/gl_surface_win.cc
@@ -167,31 +167,32 @@ void NativeViewGLSurfaceOSMesa::UpdateSize() {
Resize(window_size);
}
-GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ gfx::PluginWindowHandle window) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<NativeViewGLSurfaceOSMesa> surface(
+ scoped_refptr<GLSurface> surface(
new NativeViewGLSurfaceOSMesa(window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<NativeViewGLSurfaceEGL> surface(new NativeViewGLSurfaceEGL(
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(
window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<NativeViewGLSurfaceWGL> surface(new NativeViewGLSurfaceWGL(
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceWGL(
window));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
@@ -201,29 +202,30 @@ GLSurface* GLSurface::CreateViewGLSurface(gfx::PluginWindowHandle window) {
}
}
-GLSurface* GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) {
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ const gfx::Size& size) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
- scoped_ptr<GLSurfaceOSMesa> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
- size));
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationEGLGLES2: {
- scoped_ptr<PbufferGLSurfaceEGL> surface(new PbufferGLSurfaceEGL(size));
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationDesktopGL: {
- scoped_ptr<PbufferGLSurfaceWGL> surface(new PbufferGLSurfaceWGL(size));
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceWGL(size));
if (!surface->Initialize())
return NULL;
- return surface.release();
+ return surface;
}
case kGLImplementationMockGL:
return new GLSurfaceStub;
diff --git a/ui/gfx/surface/accelerated_surface_mac.cc b/ui/gfx/surface/accelerated_surface_mac.cc
index a749c46..ce2f7a0 100644
--- a/ui/gfx/surface/accelerated_surface_mac.cc
+++ b/ui/gfx/surface/accelerated_surface_mac.cc
@@ -35,14 +35,14 @@ bool AcceleratedSurface::Initialize(gfx::GLContext* share_context,
if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL)
return false;
- gl_surface_.reset(gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1)));
+ gl_surface_ = gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
if (!gl_surface_.get()) {
Destroy();
return false;
}
- gl_context_.reset(gfx::GLContext::CreateGLContext(share_context,
- gl_surface_.get()));
+ gl_context_ = gfx::GLContext::CreateGLContext(share_context,
+ gl_surface_.get());
if (!gl_context_.get()) {
Destroy();
return false;
@@ -66,8 +66,8 @@ void AcceleratedSurface::Destroy() {
}
transport_dib_.reset();
- gl_context_.reset();
- gl_surface_.reset();
+ gl_context_ = NULL;
+ gl_surface_ = NULL;
}
// Call after making changes to the surface which require a visual update.
diff --git a/ui/gfx/surface/accelerated_surface_mac.h b/ui/gfx/surface/accelerated_surface_mac.h
index 13bec9b..d9ee833 100644
--- a/ui/gfx/surface/accelerated_surface_mac.h
+++ b/ui/gfx/surface/accelerated_surface_mac.h
@@ -129,8 +129,8 @@ class AcceleratedSurface {
// speaking, we do not need to allocate a GL context all of the
// time. We only need one if (a) we are using the IOSurface code
// path, or (b) if we are allocating an FBO internally.
- scoped_ptr<gfx::GLSurface> gl_surface_;
- scoped_ptr<gfx::GLContext> gl_context_;
+ scoped_refptr<gfx::GLSurface> gl_surface_;
+ scoped_refptr<gfx::GLContext> gl_context_;
// Either |io_surface_| or |transport_dib_| is a valid pointer, but not both.
// |io_surface_| is non-NULL if the IOSurface APIs are supported (Mac OS X
// 10.6 and later).