summaryrefslogtreecommitdiffstats
path: root/app/gfx/gl/gl_context_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'app/gfx/gl/gl_context_mac.cc')
-rw-r--r--app/gfx/gl/gl_context_mac.cc183
1 files changed, 183 insertions, 0 deletions
diff --git a/app/gfx/gl/gl_context_mac.cc b/app/gfx/gl/gl_context_mac.cc
new file mode 100644
index 0000000..ab08c60
--- /dev/null
+++ b/app/gfx/gl/gl_context_mac.cc
@@ -0,0 +1,183 @@
+// Copyright (c) 2010 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.
+
+// This file implements the ViewGLContext and PbufferGLContext classes.
+
+#include <GL/glew.h>
+#include <GL/osmew.h>
+#include <OpenGL/OpenGL.h>
+
+#include "app/surface/accelerated_surface_mac.h"
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "app/gfx/gl/gl_context.h"
+#include "app/gfx/gl/gl_context_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(void* shared_handle);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ GLContextHandle context_;
+ PbufferHandle pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
+};
+
+static bool InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ osmewInit();
+ initialized = true;
+ return true;
+}
+
+bool PbufferGLContext::Initialize(void* shared_handle) {
+ // 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) {
+ DLOG(ERROR) << "Error choosing pixel format.";
+ Destroy();
+ return false;
+ }
+ if (!pixel_format) {
+ return false;
+ }
+ CGLError res = CGLCreateContext(pixel_format,
+ static_cast<GLContextHandle>(shared_handle),
+ &context_);
+ CGLDestroyPixelFormat(pixel_format);
+ if (res != kCGLNoError) {
+ DLOG(ERROR) << "Error creating context.";
+ Destroy();
+ return false;
+ }
+ if (CGLCreatePBuffer(1, 1,
+ GL_TEXTURE_2D, GL_RGBA,
+ 0, &pbuffer_) != kCGLNoError) {
+ DLOG(ERROR) << "Error creating pbuffer.";
+ Destroy();
+ return false;
+ }
+ if (CGLSetPBuffer(context_, pbuffer_, 0, 0, 0) != kCGLNoError) {
+ DLOG(ERROR) << "Error attaching pbuffer to context.";
+ Destroy();
+ return false;
+ }
+
+ if (!MakeCurrent()) {
+ Destroy();
+ DLOG(ERROR) << "Couldn't make context current for initialization.";
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeCommon()) {
+ 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) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool PbufferGLContext::IsCurrent() {
+ return CGLGetCurrentContext() == context_;
+}
+
+bool PbufferGLContext::IsOffscreen() {
+ return true;
+}
+
+void PbufferGLContext::SwapBuffers() {
+ NOTREACHED() << "Cannot call SwapBuffers on a PbufferGLContext.";
+}
+
+gfx::Size PbufferGLContext::GetSize() {
+ NOTREACHED() << "Should not be requesting size of a PbufferGLContext.";
+ return gfx::Size(1, 1);
+}
+
+void* PbufferGLContext::GetHandle() {
+ return context_;
+}
+
+GLContext* GLContext::CreateOffscreenGLContext(void* shared_handle) {
+ if (!InitializeOneOff())
+ return NULL;
+
+ if (OSMesaCreateContext) {
+ scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext);
+
+ if (!context->Initialize(shared_handle))
+ return NULL;
+
+ return context.release();
+ } else {
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ if (!context->Initialize(shared_handle))
+ return NULL;
+
+ return context.release();
+ }
+}
+
+} // namespace gfx