diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-05 22:21:01 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-05 22:21:01 +0000 |
commit | f96c7c517f99b8ed7490b1883fec672fcf2c2f2c (patch) | |
tree | a36dd1d257f4a25ba4f57d79de5bfef9a3b4247b | |
parent | 42cde658b2ffe6f3a31750d47986922afc48aa47 (diff) | |
download | chromium_src-f96c7c517f99b8ed7490b1883fec672fcf2c2f2c.zip chromium_src-f96c7c517f99b8ed7490b1883fec672fcf2c2f2c.tar.gz chromium_src-f96c7c517f99b8ed7490b1883fec672fcf2c2f2c.tar.bz2 |
Split CGL implementations of *GLContext into GLContextCGL and *GLSurfaceCGL.
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 started with EGL in r81512, WGL in r81807, OSMesa in r81998 and GLX in r84090. This is the same thing for CGL.
GLContextCGL 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=WebGL locally, try
BUG=none
Review URL: http://codereview.chromium.org/6933020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84334 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ui/gfx/gl/gl.gyp | 6 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_cgl.cc | 95 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_cgl.h | 41 | ||||
-rw-r--r-- | ui/gfx/gl/gl_context_mac.cc | 168 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_cgl.cc | 106 | ||||
-rw-r--r-- | ui/gfx/gl/gl_surface_cgl.h | 49 |
6 files changed, 317 insertions, 148 deletions
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp index e70ccae..4e45a72 100644 --- a/ui/gfx/gl/gl.gyp +++ b/ui/gfx/gl/gl.gyp @@ -159,6 +159,12 @@ ], }], ['OS=="mac"', { + 'sources': [ + 'gl_context_cgl.cc', + 'gl_context_cgl.h', + 'gl_surface_cgl.cc', + 'gl_surface_cgl.h', + ], 'link_settings': { 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc new file mode 100644 index 0000000..bee8ac2 --- /dev/null +++ b/ui/gfx/gl/gl_context_cgl.cc @@ -0,0 +1,95 @@ +// 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_context_cgl.h" + +#include "base/logging.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_surface_cgl.h" + +namespace gfx { + +GLContextCGL::GLContextCGL(GLSurfaceCGL* surface) + : surface_(surface), + context_(NULL) { +} + +GLContextCGL::~GLContextCGL() { + Destroy(); +} + +bool GLContextCGL::Initialize(GLContext* shared_context) { + CGLError res = CGLCreateContext( + static_cast<CGLPixelFormatObj>(GLSurfaceCGL::GetPixelFormat()), + shared_context ? + static_cast<CGLContextObj>(shared_context->GetHandle()) : NULL, + reinterpret_cast<CGLContextObj*>(&context_)); + if (res != kCGLNoError) { + LOG(ERROR) << "Error creating context."; + Destroy(); + return false; + } + + return true; +} + +void GLContextCGL::Destroy() { + if (context_) { + CGLDestroyContext(static_cast<CGLContextObj>(context_)); + context_ = NULL; + } +} + +bool GLContextCGL::MakeCurrent() { + if (IsCurrent()) + return true; + + if (CGLSetPBuffer(static_cast<CGLContextObj>(context_), + static_cast<CGLPBufferObj>(surface_->GetHandle()), + 0, + 0, + 0) != kCGLNoError) { + LOG(ERROR) << "Error attaching pbuffer to context."; + Destroy(); + return false; + } + + if (CGLSetCurrentContext( + static_cast<CGLContextObj>(context_)) != kCGLNoError) { + LOG(ERROR) << "Unable to make gl context current."; + return false; + } + + return true; +} + +bool GLContextCGL::IsCurrent() { + return CGLGetCurrentContext() == context_; +} + +bool GLContextCGL::IsOffscreen() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->IsOffscreen(); +} + +bool GLContextCGL::SwapBuffers() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->SwapBuffers(); +} + +gfx::Size GLContextCGL::GetSize() { + // TODO(apatrick): remove this from GLContext interface. + return surface_->GetSize(); +} + +void* GLContextCGL::GetHandle() { + return context_; +} + +void GLContextCGL::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED() << "Attempt to call SetSwapInterval on a GLContextCGL."; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_cgl.h b/ui/gfx/gl/gl_context_cgl.h new file mode 100644 index 0000000..23c77682 --- /dev/null +++ b/ui/gfx/gl/gl_context_cgl.h @@ -0,0 +1,41 @@ +// 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 <string> + +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/size.h" + +namespace gfx { + +class GLSurfaceCGL; + +// Encapsulates a CGL OpenGL context. +class GLContextCGL : public GLContext { + public: + explicit GLContextCGL(GLSurfaceCGL* surface); + virtual ~GLContextCGL(); + + // Initializes the GL context. + bool Initialize(GLContext* shared_context); + + // 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); + + private: + scoped_ptr<GLSurfaceCGL> surface_; + void* context_; + + DISALLOW_COPY_AND_ASSIGN(GLContextCGL); +}; + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_mac.cc b/ui/gfx/gl/gl_context_mac.cc index 21b0403..fbb18b0 100644 --- a/ui/gfx/gl/gl_context_mac.cc +++ b/ui/gfx/gl/gl_context_mac.cc @@ -2,55 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file implements the ViewGLContext and PbufferGLContext classes. - -#include "ui/gfx/gl/gl_context.h" - -#include <GL/osmesa.h> -#include <OpenGL/OpenGL.h> - #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "third_party/mesa/MesaLib/include/GL/osmesa.h" #include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context_cgl.h" #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_cgl.h" +#include "ui/gfx/gl/gl_surface_osmesa.h" namespace gfx { -typedef CGLContextObj GLContextHandle; -typedef CGLPBufferObj PbufferHandle; - -// This class is a wrapper around a GL context used for offscreen rendering. -// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful -// rendering. -class PbufferGLContext : public GLContext { - public: - PbufferGLContext() - : context_(NULL), - pbuffer_(NULL) { - } - - // Initializes the GL context. - bool Initialize(GLContext* shared_context); - - 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); - - private: - GLContextHandle context_; - PbufferHandle pbuffer_; - - DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); -}; - bool GLContext::InitializeOneOff() { static bool initialized = false; if (initialized) @@ -69,123 +34,30 @@ bool GLContext::InitializeOneOff() { return false; } - initialized = true; - return true; -} - -bool PbufferGLContext::Initialize(GLContext* shared_context) { - // Create a 1x1 pbuffer and associated context to bootstrap things. - static const CGLPixelFormatAttribute attribs[] = { - (CGLPixelFormatAttribute) kCGLPFAPBuffer, - (CGLPixelFormatAttribute) 0 - }; - CGLPixelFormatObj pixel_format; - GLint num_pixel_formats; - if (CGLChoosePixelFormat(attribs, - &pixel_format, - &num_pixel_formats) != kCGLNoError) { - LOG(ERROR) << "Error choosing pixel format."; - Destroy(); - return false; - } - if (!pixel_format) { - LOG(ERROR) << "pixel_format == 0."; - return false; - } - - GLContextHandle shared_handle = NULL; - if (shared_context) - shared_handle = static_cast<GLContextHandle>(shared_context->GetHandle()); - - CGLError res = CGLCreateContext(pixel_format, shared_handle, &context_); - CGLDestroyPixelFormat(pixel_format); - if (res != kCGLNoError) { - LOG(ERROR) << "Error creating context."; - Destroy(); - return false; - } - if (CGLCreatePBuffer(1, 1, - GL_TEXTURE_2D, GL_RGBA, - 0, &pbuffer_) != kCGLNoError) { - LOG(ERROR) << "Error creating pbuffer."; - Destroy(); - return false; - } - if (CGLSetPBuffer(context_, pbuffer_, 0, 0, 0) != kCGLNoError) { - LOG(ERROR) << "Error attaching pbuffer to context."; - Destroy(); - return false; - } - - if (!MakeCurrent()) { - Destroy(); - LOG(ERROR) << "Couldn't make context current for initialization."; - return false; - } - - if (!InitializeCommon()) { - LOG(ERROR) << "GLContext::InitializeCommon failed."; - Destroy(); - return false; - } - - return true; -} - -void PbufferGLContext::Destroy() { - if (context_) { - CGLDestroyContext(context_); - context_ = NULL; - } - - if (pbuffer_) { - CGLDestroyPBuffer(pbuffer_); - pbuffer_ = NULL; - } -} - -bool PbufferGLContext::MakeCurrent() { - if (!IsCurrent()) { - if (CGLSetCurrentContext(context_) != kCGLNoError) { - LOG(ERROR) << "Unable to make gl context current."; - return false; - } + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: + if (!GLSurfaceCGL::InitializeOneOff()) { + LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed."; + return false; + } + break; + default: + break; } + initialized = true; return true; } -bool PbufferGLContext::IsCurrent() { - return CGLGetCurrentContext() == context_; -} - -bool PbufferGLContext::IsOffscreen() { - return true; -} - -bool PbufferGLContext::SwapBuffers() { - NOTREACHED() << "Cannot call SwapBuffers on a PbufferGLContext."; - return false; -} - -gfx::Size PbufferGLContext::GetSize() { - NOTREACHED() << "Should not be requesting size of a PbufferGLContext."; - return gfx::Size(1, 1); -} - -void* PbufferGLContext::GetHandle() { - return context_; -} - -void PbufferGLContext::SetSwapInterval(int interval) { - DCHECK(IsCurrent()); - NOTREACHED() << "Attempt to call SetSwapInterval on a PbufferGLContext."; -} - GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { switch (GetGLImplementation()) { case kGLImplementationDesktopGL: { - scoped_ptr<PbufferGLContext> context(new PbufferGLContext); + scoped_ptr<PbufferGLSurfaceCGL> surface(new PbufferGLSurfaceCGL( + gfx::Size(1, 1))); + if (!surface->Initialize()) + return false; + + scoped_ptr<GLContextCGL> context(new GLContextCGL(surface.release())); if (!context->Initialize(shared_context)) return NULL; diff --git a/ui/gfx/gl/gl_surface_cgl.cc b/ui/gfx/gl/gl_surface_cgl.cc new file mode 100644 index 0000000..7b6b89c --- /dev/null +++ b/ui/gfx/gl/gl_surface_cgl.cc @@ -0,0 +1,106 @@ +// 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_cgl.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "ui/gfx/gl/gl_bindings.h" + +namespace gfx { + +namespace { +CGLPixelFormatObj g_pixel_format; +} + +GLSurfaceCGL::GLSurfaceCGL() { +} + +GLSurfaceCGL::~GLSurfaceCGL() { +} + +bool GLSurfaceCGL::InitializeOneOff() { + static bool initialized = false; + if (initialized) + return true; + + static const CGLPixelFormatAttribute attribs[] = { + (CGLPixelFormatAttribute) kCGLPFAPBuffer, + (CGLPixelFormatAttribute) 0 + }; + CGLPixelFormatObj pixel_format; + GLint num_pixel_formats; + if (CGLChoosePixelFormat(attribs, + &g_pixel_format, + &num_pixel_formats) != kCGLNoError) { + LOG(ERROR) << "Error choosing pixel format."; + return false; + } + if (num_pixel_formats == 0) { + LOG(ERROR) << "num_pixel_formats == 0."; + return false; + } + if (!g_pixel_format) { + LOG(ERROR) << "pixel_format == 0."; + return false; + } + + initialized = true; + return true; +} + +void* GLSurfaceCGL::GetPixelFormat() { + return g_pixel_format; +} + +PbufferGLSurfaceCGL::PbufferGLSurfaceCGL(const gfx::Size& size) + : size_(size), + pbuffer_(NULL) { +} + +PbufferGLSurfaceCGL::~PbufferGLSurfaceCGL() { + Destroy(); +} + +bool PbufferGLSurfaceCGL::Initialize() { + if (CGLCreatePBuffer(size_.width(), + size_.height(), + GL_TEXTURE_2D, + GL_RGBA, + 0, + reinterpret_cast<CGLPBufferObj*>(&pbuffer_)) + != kCGLNoError) { + LOG(ERROR) << "Error creating pbuffer."; + Destroy(); + return false; + } + + return true; +} + +void PbufferGLSurfaceCGL::Destroy() { + if (pbuffer_) { + CGLDestroyPBuffer(static_cast<CGLPBufferObj>(pbuffer_)); + pbuffer_ = NULL; + } +} + +bool PbufferGLSurfaceCGL::IsOffscreen() { + return true; +} + +bool PbufferGLSurfaceCGL::SwapBuffers() { + NOTREACHED() << "Cannot call SwapBuffers on a PbufferGLSurfaceCGL."; + return false; +} + +gfx::Size PbufferGLSurfaceCGL::GetSize() { + return size_; +} + +void* PbufferGLSurfaceCGL::GetHandle() { + return pbuffer_; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_surface_cgl.h b/ui/gfx/gl/gl_surface_cgl.h new file mode 100644 index 0000000..98775c6 --- /dev/null +++ b/ui/gfx/gl/gl_surface_cgl.h @@ -0,0 +1,49 @@ +// 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_CGL_H_ +#define UI_GFX_GL_GL_SURFACE_CGL_H_ + +#include "ui/gfx/gl/gl_surface.h" +#include "ui/gfx/size.h" + +namespace gfx { + +// Base class for CGL surfaces. +class GLSurfaceCGL : public GLSurface { + public: + GLSurfaceCGL(); + virtual ~GLSurfaceCGL(); + + static bool InitializeOneOff(); + static void* GetPixelFormat(); + + private: + DISALLOW_COPY_AND_ASSIGN(GLSurfaceCGL); +}; + +// A surface used to render to an offscreen pbuffer. +class PbufferGLSurfaceCGL : public GLSurfaceCGL { + public: + explicit PbufferGLSurfaceCGL(const gfx::Size& size); + virtual ~PbufferGLSurfaceCGL(); + + // Implement GLSurface. + virtual bool Initialize(); + virtual void Destroy(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + + private: + gfx::Size size_; + void* pbuffer_; + + DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceCGL); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_SURFACE_CGL_H_ |