summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 21:31:53 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-21 21:31:53 +0000
commit96f8063420f0170207f8b8fad211c70d3ad66db6 (patch)
treeecd625784f6ccf6a699f51a888e7e70056ab4bc0 /gpu/command_buffer/service
parentd3d0ef9739170a270dcb2f070f2364aa003aea9c (diff)
downloadchromium_src-96f8063420f0170207f8b8fad211c70d3ad66db6.zip
chromium_src-96f8063420f0170207f8b8fad211c70d3ad66db6.tar.gz
chromium_src-96f8063420f0170207f8b8fad211c70d3ad66db6.tar.bz2
Revert 45240 - Moved GLContext class to gfx/gl.
Now it can be used by code outside of the gpu project, for example AcceleratedSurface. TEST=trybots BUG=none Review URL: http://codereview.chromium.org/1694003 TBR=jamesr@chromium.org Review URL: http://codereview.chromium.org/1747007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45244 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service')
-rw-r--r--gpu/command_buffer/service/gl_context.cc91
-rw-r--r--gpu/command_buffer/service/gl_context.h64
-rw-r--r--gpu/command_buffer/service/gl_context_linux.cc401
-rw-r--r--gpu/command_buffer/service/gl_context_mac.cc182
-rw-r--r--gpu/command_buffer/service/gl_context_osmesa.cc106
-rw-r--r--gpu/command_buffer/service/gl_context_osmesa.h58
-rw-r--r--gpu/command_buffer/service/gl_context_stub.cc19
-rw-r--r--gpu/command_buffer/service/gl_context_win.cc623
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc14
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h10
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h4
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h4
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc2
-rw-r--r--gpu/command_buffer/service/gpu_processor.h8
-rw-r--r--gpu/command_buffer/service/gpu_processor_linux.cc8
-rw-r--r--gpu/command_buffer/service/gpu_processor_mac.cc6
-rw-r--r--gpu/command_buffer/service/gpu_processor_win.cc8
18 files changed, 1564 insertions, 46 deletions
diff --git a/gpu/command_buffer/service/gl_context.cc b/gpu/command_buffer/service/gl_context.cc
new file mode 100644
index 0000000..e123936
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context.cc
@@ -0,0 +1,91 @@
+// Copyright (c) 2009 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 "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+GLContext::GLContext() {
+}
+
+GLContext::~GLContext() {
+}
+
+// GLEW initialization is extremely expensive because it looks up
+// hundreds of function pointers. Realistically we are not going to
+// switch between GL implementations on the fly, so for the time being
+// we only do the context-dependent GLEW initialization once.
+bool InitializeGLEW() {
+#if defined(UNIT_TEST)
+ return true;
+#else
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ // Initializes context-dependent parts of GLEW.
+ if (glewInit() != GLEW_OK) {
+ LOG(ERROR) << "GLEW failed initialization";
+ return false;
+ }
+
+ // Check to see that we can use the OpenGL vertex attribute APIs
+ // TODO(petersont): Return false if this check fails, but because some
+ // Intel hardware does not support OpenGL 2.0, yet does support all of the
+ // extensions we require, we only log an error. A future CL should change
+ // this check to ensure that all of the extension strings we require are
+ // present.
+ if (!GLEW_VERSION_2_0) {
+ DLOG(ERROR) << "GL drivers do not have OpenGL 2.0 functionality.";
+ }
+
+ // Check for necessary extensions.
+ bool extensions_found = true;
+ if (!GLEW_ARB_vertex_buffer_object) {
+ // NOTE: Linux NVidia drivers claim to support OpenGL 2.0 when using
+ // indirect rendering (e.g. remote X), but it is actually lying. The
+ // ARB_vertex_buffer_object functions silently no-op (!) when using
+ // indirect rendering, leading to crashes. Fortunately, in that case, the
+ // driver claims to not support ARB_vertex_buffer_object, so fail in that
+ // case.
+ DLOG(ERROR) << "GL drivers do not support vertex buffer objects.";
+ extensions_found = false;
+ }
+ if (!GLEW_EXT_framebuffer_object) {
+ DLOG(ERROR) << "GL drivers do not support framebuffer objects.";
+ extensions_found = false;
+ }
+ if (!GLEW_VERSION_2_0 && !GLEW_EXT_stencil_two_side) {
+ DLOG(ERROR) << "Two sided stencil extension missing.";
+ extensions_found = false;
+ }
+ if (!GLEW_VERSION_1_4 && !GLEW_EXT_blend_func_separate) {
+ DLOG(ERROR) <<"Separate blend func extension missing.";
+ extensions_found = false;
+ }
+ if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) {
+ DLOG(ERROR) << "Separate blend function extension missing.";
+ extensions_found = false;
+ }
+ if (!extensions_found)
+ return false;
+
+ initialized = true;
+ return true;
+#endif
+}
+
+bool GLContext::InitializeCommon() {
+ if (!MakeCurrent())
+ return false;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ if (glGetError() != GL_NO_ERROR)
+ return false;
+
+ return true;
+}
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context.h b/gpu/command_buffer/service/gl_context.h
new file mode 100644
index 0000000..cd41b56
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context.h
@@ -0,0 +1,64 @@
+// 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.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_H_
+
+#include "build/build_config.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+bool InitializeGLEW();
+
+// Encapsulates an OpenGL context, hiding platform specific management.
+class GLContext {
+ public:
+ GLContext();
+ virtual ~GLContext();
+
+ // Destroys the GL context.
+ virtual void Destroy() = 0;
+
+ // Makes the GL context current on the current thread.
+ virtual bool MakeCurrent() = 0;
+
+ // Returns true if this context is current.
+ virtual bool IsCurrent() = 0;
+
+ // Returns true if this context is offscreen.
+ virtual bool IsOffscreen() = 0;
+
+ // Swaps front and back buffers. This has no effect for off-screen
+ // contexts.
+ virtual void SwapBuffers() = 0;
+
+ // Get the size of the back buffer.
+ virtual gfx::Size GetSize() = 0;
+
+ // Get the underlying platform specific GL context "handle".
+ virtual void* GetHandle() = 0;
+
+#if !defined(OS_MACOSX)
+ // Create a GL context that renders directly to a view.
+ static GLContext* CreateViewGLContext(gfx::PluginWindowHandle window,
+ bool multisampled);
+#endif
+
+ // Create 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.
+ static GLContext* CreateOffscreenGLContext(void* shared_handle);
+
+ protected:
+ bool InitializeCommon();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLContext);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_H_
diff --git a/gpu/command_buffer/service/gl_context_linux.cc b/gpu/command_buffer/service/gl_context_linux.cc
new file mode 100644
index 0000000..1c04d91
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_linux.cc
@@ -0,0 +1,401 @@
+// 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 <dlfcn.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+// Ensure that gl_utils.h is included before any GL headers.
+#include "gpu/command_buffer/service/gl_utils.h"
+
+#include "app/x11_util.h"
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/service/gl_context_osmesa.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+typedef GLXContext GLContextHandle;
+typedef GLXPbuffer PbufferHandle;
+
+// This class is a wrapper around a GL context that renders directly to a
+// window.
+class ViewGLContext : public GLContext {
+ public:
+ explicit ViewGLContext(gfx::PluginWindowHandle window)
+ : window_(window),
+ context_(NULL) {
+ DCHECK(window);
+ }
+
+ // Initializes the GL context.
+ bool Initialize(bool multisampled);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::PluginWindowHandle window_;
+ GLContextHandle context_;
+
+ DISALLOW_COPY_AND_ASSIGN(ViewGLContext);
+};
+
+// 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:
+ explicit 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);
+};
+
+// scoped_ptr functor for XFree(). Use as follows:
+// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
+// where "XVisualInfo" is any X type that is freed with XFree.
+class ScopedPtrXFree {
+ public:
+ void operator()(void* x) const {
+ ::XFree(x);
+ }
+};
+
+// Some versions of NVIDIA's GL libGL.so include a broken version of
+// dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically
+// load it, and use glew to dynamically resolve symbols.
+// See http://code.google.com/p/chromium/issues/detail?id=16800
+
+static bool InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ osmewInit();
+ if (!OSMesaCreateContext) {
+ void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
+ if (!handle) {
+ LOG(ERROR) << "Could not find libGL.so.1";
+ return false;
+ }
+
+ // Initializes context-independent parts of GLEW
+ if (glxewInit() != GLEW_OK) {
+ LOG(ERROR) << "glxewInit failed";
+ return false;
+ }
+ // glxewContextInit really only needs a display connection to
+ // complete, and we don't want to have to create an OpenGL context
+ // just to get access to GLX 1.3 entry points to create pbuffers.
+ // We therefore added a glxewContextInitWithDisplay entry point.
+ Display* display = x11_util::GetXDisplay();
+ if (glxewContextInitWithDisplay(display) != GLEW_OK) {
+ LOG(ERROR) << "glxewContextInit failed";
+ return false;
+ }
+ }
+
+ initialized = true;
+ return true;
+}
+
+bool ViewGLContext::Initialize(bool multisampled) {
+ if (multisampled) {
+ DLOG(WARNING) << "Multisampling not implemented.";
+ }
+
+ Display* display = x11_util::GetXDisplay();
+ XWindowAttributes attributes;
+ XGetWindowAttributes(display, window_, &attributes);
+ XVisualInfo visual_info_template;
+ visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
+ int visual_info_count = 0;
+ scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
+ XGetVisualInfo(display, VisualIDMask,
+ &visual_info_template,
+ &visual_info_count));
+ DCHECK(visual_info_list.get());
+ DCHECK_GT(visual_info_count, 0);
+ context_ = NULL;
+ for (int i = 0; i < visual_info_count; ++i) {
+ context_ = glXCreateContext(display, visual_info_list.get() + i, 0, True);
+ if (context_)
+ break;
+ }
+ if (!context_) {
+ DLOG(ERROR) << "Couldn't create GL context.";
+ 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 ViewGLContext::Destroy() {
+ Display* display = x11_util::GetXDisplay();
+ Bool result = glXMakeCurrent(display, 0, 0);
+
+ // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
+ // we have pending draws on an invalid window - which shouldn't be the case
+ // here.
+ DCHECK(result);
+ if (context_) {
+ glXDestroyContext(display, context_);
+ context_ = NULL;
+ }
+}
+
+bool ViewGLContext::MakeCurrent() {
+ if (IsCurrent()) {
+ return true;
+ }
+
+ Display* display = x11_util::GetXDisplay();
+ if (glXMakeCurrent(display, window_, context_) != True) {
+ glXDestroyContext(display, context_);
+ context_ = 0;
+ DLOG(ERROR) << "Couldn't make context current.";
+ return false;
+ }
+
+ return true;
+}
+
+bool ViewGLContext::IsCurrent() {
+ return glXGetCurrentDrawable() == window_ &&
+ glXGetCurrentContext() == context_;
+}
+
+bool ViewGLContext::IsOffscreen() {
+ return false;
+}
+
+void ViewGLContext::SwapBuffers() {
+ Display* display = x11_util::GetXDisplay();
+ glXSwapBuffers(display, window_);
+}
+
+gfx::Size ViewGLContext::GetSize() {
+ XWindowAttributes attributes;
+ Display* display = x11_util::GetXDisplay();
+ XGetWindowAttributes(display, window_, &attributes);
+ return gfx::Size(attributes.width, attributes.height);
+}
+
+void* ViewGLContext::GetHandle() {
+ return context_;
+}
+
+GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
+ bool multisampled) {
+ if (!InitializeOneOff())
+ return NULL;
+
+ if (OSMesaCreateContext) {
+ // TODO(apatrick): Support OSMesa rendering to a window on Linux.
+ NOTREACHED() << "OSMesa rendering to a window is not yet implemented.";
+ return NULL;
+ } else {
+ scoped_ptr<ViewGLContext> context(new ViewGLContext(window));
+
+ if (!context->Initialize(multisampled))
+ return NULL;
+
+ return context.release();
+ }
+}
+
+bool PbufferGLContext::Initialize(void* shared_handle) {
+ if (!glXChooseFBConfig ||
+ !glXCreateNewContext ||
+ !glXCreatePbuffer ||
+ !glXDestroyPbuffer) {
+ DLOG(ERROR) << "Pbuffer support not available.";
+ return false;
+ }
+
+ static const int config_attributes[] = {
+ GLX_DRAWABLE_TYPE,
+ GLX_PBUFFER_BIT,
+ GLX_RENDER_TYPE,
+ GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER,
+ 0,
+ 0
+ };
+
+ Display* display = x11_util::GetXDisplay();
+
+ int nelements = 0;
+ // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
+ glXChooseFBConfig(display, 0, config_attributes, &nelements));
+ if (!config.get()) {
+ DLOG(ERROR) << "glXChooseFBConfig failed.";
+ return false;
+ }
+ if (!nelements) {
+ DLOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
+ return false;
+ }
+ context_ = glXCreateNewContext(display,
+ config.get()[0],
+ GLX_RGBA_TYPE,
+ static_cast<GLContextHandle>(shared_handle),
+ True);
+ if (!context_) {
+ DLOG(ERROR) << "glXCreateNewContext failed.";
+ return false;
+ }
+ static const int pbuffer_attributes[] = {
+ GLX_PBUFFER_WIDTH,
+ 1,
+ GLX_PBUFFER_HEIGHT,
+ 1,
+ 0
+ };
+ pbuffer_ = glXCreatePbuffer(display,
+ config.get()[0], pbuffer_attributes);
+ if (!pbuffer_) {
+ Destroy();
+ DLOG(ERROR) << "glXCreatePbuffer failed.";
+ 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() {
+ Display* display = x11_util::GetXDisplay();
+ Bool result = glXMakeCurrent(display, 0, 0);
+ // glXMakeCurrent isn't supposed to fail when unsetting the context, unless
+ // we have pending draws on an invalid window - which shouldn't be the case
+ // here.
+ DCHECK(result);
+ if (context_) {
+ glXDestroyContext(display, context_);
+ context_ = NULL;
+ }
+
+ if (pbuffer_) {
+ glXDestroyPbuffer(display, pbuffer_);
+ pbuffer_ = NULL;
+ }
+}
+
+bool PbufferGLContext::MakeCurrent() {
+ if (IsCurrent()) {
+ return true;
+ }
+ Display* display = x11_util::GetXDisplay();
+ if (glXMakeCurrent(display, pbuffer_, context_) != True) {
+ glXDestroyContext(display, context_);
+ context_ = NULL;
+ DLOG(ERROR) << "Couldn't make context current.";
+ return false;
+ }
+
+ return true;
+}
+
+bool PbufferGLContext::IsCurrent() {
+ return glXGetCurrentDrawable() == pbuffer_ &&
+ glXGetCurrentContext() == context_;
+}
+
+bool PbufferGLContext::IsOffscreen() {
+ return true;
+}
+
+void PbufferGLContext::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
+}
+
+gfx::Size PbufferGLContext::GetSize() {
+ NOTREACHED() << "Should not be requesting size of this pbuffer.";
+ 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 gpu
diff --git a/gpu/command_buffer/service/gl_context_mac.cc b/gpu/command_buffer/service/gl_context_mac.cc
new file mode 100644
index 0000000..7fed885
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_mac.cc
@@ -0,0 +1,182 @@
+// 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.
+
+// Ensure that gl_utils.h is included before any GL headers.
+#include "gpu/command_buffer/service/gl_utils.h"
+
+#include "app/surface/accelerated_surface_mac.h"
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/service/gl_context_osmesa.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+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 gpu
diff --git a/gpu/command_buffer/service/gl_context_osmesa.cc b/gpu/command_buffer/service/gl_context_osmesa.cc
new file mode 100644
index 0000000..6ec7489
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_osmesa.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2009 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 <algorithm>
+
+#include "gpu/command_buffer/service/gl_context_osmesa.h"
+
+namespace gpu {
+
+OSMesaGLContext::OSMesaGLContext()
+#if !defined(UNIT_TEST)
+ : context_(NULL)
+#endif
+{
+}
+
+OSMesaGLContext::~OSMesaGLContext() {
+}
+
+bool OSMesaGLContext::Initialize(void* shared_handle) {
+#if !defined(UNIT_TEST)
+ DCHECK(!context_);
+
+ size_ = gfx::Size(1, 1);
+ buffer_.reset(new int32[1]);
+
+ context_ = OSMesaCreateContext(GL_RGBA,
+ static_cast<OSMesaContext>(shared_handle));
+ return context_ != NULL;
+#else
+ return true;
+#endif
+}
+
+void OSMesaGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ if (context_) {
+ OSMesaDestroyContext(static_cast<OSMesaContext>(context_));
+ context_ = NULL;
+ }
+#endif
+}
+
+bool OSMesaGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
+ DCHECK(context_);
+ return OSMesaMakeCurrent(static_cast<OSMesaContext>(context_),
+ buffer_.get(),
+ GL_UNSIGNED_BYTE,
+ size_.width(), size_.height()) == GL_TRUE;
+#endif
+ return true;
+}
+
+bool OSMesaGLContext::IsCurrent() {
+#if !defined(UNIT_TEST)
+ DCHECK(context_);
+ return context_ == OSMesaGetCurrentContext();
+#endif
+ return true;
+}
+
+bool OSMesaGLContext::IsOffscreen() {
+ return true;
+}
+
+void OSMesaGLContext::SwapBuffers() {
+ NOTREACHED() << "Should not call SwapBuffers on an OSMesaGLContext.";
+}
+
+gfx::Size OSMesaGLContext::GetSize() {
+ return size_;
+}
+
+void* OSMesaGLContext::GetHandle() {
+ return context_;
+}
+
+void OSMesaGLContext::Resize(const gfx::Size& new_size) {
+ if (new_size == size_)
+ return;
+
+ // Allocate a new back buffer.
+ scoped_array<int32> new_buffer(new int32[new_size.GetArea()]);
+ memset(new_buffer.get(), 0, new_size.GetArea() * sizeof(new_buffer[0]));
+
+ // Copy the current back buffer into the new buffer.
+ int copy_width = std::min(size_.width(), new_size.width());
+ int copy_height = std::min(size_.height(), new_size.height());
+ for (int y = 0; y < copy_height; ++y) {
+ for (int x = 0; x < copy_width; ++x) {
+ new_buffer[y * new_size.width() + x] = buffer_[y * size_.width() + x];
+ }
+ }
+
+ buffer_.reset(new_buffer.release());
+ size_ = new_size;
+
+ // If this context is current, need to call MakeCurrent again so OSMesa uses
+ // the new buffer.
+ if (IsCurrent())
+ MakeCurrent();
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context_osmesa.h b/gpu/command_buffer/service/gl_context_osmesa.h
new file mode 100644
index 0000000..06b14ca
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_osmesa.h
@@ -0,0 +1,58 @@
+// 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.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_OSMESA_H_
+#define GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_OSMESA_H_
+
+// Ensure that gl_utils.h is included before any GL headers.
+#include "gpu/command_buffer/service/gl_utils.h"
+
+#include "base/scoped_ptr.h"
+#include "gfx/size.h"
+#include "gpu/command_buffer/service/gl_context.h"
+
+namespace gpu {
+
+// Encapsulates an OSMesa OpenGL context that uses software rendering.
+class OSMesaGLContext : public GLContext {
+ public:
+ OSMesaGLContext();
+ virtual ~OSMesaGLContext();
+
+ // Initialize an OSMesa GL context with the default 1 x 1 initial size.
+ bool Initialize(void* shared_handle);
+
+ // Implement GLContext.
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ // Resize the back buffer, preserving the old content. Does nothing if the
+ // size is unchanged.
+ void Resize(const gfx::Size& new_size);
+
+ const void* buffer() const {
+ return buffer_.get();
+ }
+
+ protected:
+ bool InitializeCommon();
+
+ private:
+#if !defined(UNIT_TEST)
+ gfx::Size size_;
+ scoped_array<int32> buffer_;
+ OSMesaContext context_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(OSMesaGLContext);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_OSMESA_H_
diff --git a/gpu/command_buffer/service/gl_context_stub.cc b/gpu/command_buffer/service/gl_context_stub.cc
index 5b776db..84e6209 100644
--- a/gpu/command_buffer/service/gl_context_stub.cc
+++ b/gpu/command_buffer/service/gl_context_stub.cc
@@ -5,12 +5,12 @@
// This file implements the StubGLContext.
#include "build/build_config.h"
-#include "gfx/gl/gl_context.h"
+#include "gpu/command_buffer/service/gl_context.h"
namespace gpu {
// A GLContext that does nothing for unit tests.
-class StubGLContext : public gfx::GLContext {
+class StubGLContext : public GLContext {
public:
// Implement GLContext.
@@ -23,22 +23,17 @@ class StubGLContext : public gfx::GLContext {
virtual void* GetHandle() { return NULL; }
};
-} // namespace gpu
-
-namespace gfx {
-
#if !defined(OS_MACOSX)
-GLContext* GLContext::CreateViewGLContext(PluginWindowHandle /* window */,
+GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle /* window */,
bool /* multisampled */) {
- return new gpu::StubGLContext;
+ return new StubGLContext;
}
#endif // OS_MACOSX
-GLContext* GLContext::CreateOffscreenGLContext(
- void* /* shared_handle */) {
- return new gpu::StubGLContext;
+GLContext* GLContext::CreateOffscreenGLContext(void* /* shared_handle */) {
+ return new StubGLContext;
}
-} // namespace gfx
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context_win.cc b/gpu/command_buffer/service/gl_context_win.cc
new file mode 100644
index 0000000..05cee5b
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_win.cc
@@ -0,0 +1,623 @@
+// 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 NativeViewGLContext and PbufferGLContext classes.
+
+#include <algorithm>
+
+// Ensure that gl_utils.h is included before any GL headers.
+#include "gpu/command_buffer/service/gl_utils.h"
+
+#include "base/scoped_ptr.h"
+#include "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/service/gl_context_osmesa.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+typedef HGLRC GLContextHandle;
+typedef HPBUFFERARB PbufferHandle;
+
+// This class is a wrapper around a GL context that renders directly to a
+// window.
+class NativeViewGLContext : public GLContext {
+ public:
+ explicit NativeViewGLContext(gfx::PluginWindowHandle window)
+ : window_(window),
+ device_context_(NULL),
+ context_(NULL) {
+ DCHECK(window);
+ }
+
+ // Initializes the GL context.
+ bool Initialize(bool multisampled);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::PluginWindowHandle window_;
+ HDC device_context_;
+ GLContextHandle context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLContext);
+};
+
+// This class is a wrapper around a GL context that uses OSMesa to render
+// to an offscreen buffer and then blits it to a window.
+class OSMesaViewGLContext : public GLContext {
+ public:
+ explicit OSMesaViewGLContext(gfx::PluginWindowHandle window)
+ : window_(window),
+ device_context_(NULL) {
+ DCHECK(window);
+ }
+
+ // Initializes the GL context.
+ bool Initialize();
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ void UpdateSize();
+
+ gfx::PluginWindowHandle window_;
+ HDC device_context_;
+ OSMesaGLContext osmesa_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext);
+};
+
+// 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),
+ device_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_;
+ HDC device_context_;
+ PbufferHandle pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
+};
+
+static int g_regular_pixel_format = 0;
+static int g_multisampled_pixel_format = 0;
+
+const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
+ sizeof(kPixelFormatDescriptor), // Size of structure.
+ 1, // Default version.
+ PFD_DRAW_TO_WINDOW | // Window drawing support.
+ PFD_SUPPORT_OPENGL | // OpenGL support.
+ PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
+ PFD_TYPE_RGBA, // RGBA color mode (not indexed).
+ 24, // 24 bit color mode.
+ 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
+ 8, 0, // 8 bit alpha
+ 0, // No accumulation buffer.
+ 0, 0, 0, 0, // Ignore accumulation bits.
+ 24, // 24 bit z-buffer size.
+ 8, // 8-bit stencil buffer.
+ 0, // No aux buffer.
+ PFD_MAIN_PLANE, // Main drawing plane (not overlay).
+ 0, // Reserved.
+ 0, 0, 0, // Layer masks ignored.
+};
+
+LRESULT CALLBACK IntermediateWindowProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return ::DefWindowProc(window, message, w_param, l_param);
+}
+
+// Helper routine that does one-off initialization like determining the
+// pixel format and initializing glew.
+static bool InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ osmewInit();
+ if (!OSMesaCreateContext) {
+ // We must initialize a GL context before we can determine the multi-
+ // sampling supported on the current hardware, so we create an intermediate
+ // window and context here.
+ HINSTANCE module_handle;
+ if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ reinterpret_cast<wchar_t*>(IntermediateWindowProc),
+ &module_handle)) {
+ return false;
+ }
+
+ WNDCLASS intermediate_class;
+ intermediate_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ intermediate_class.lpfnWndProc = IntermediateWindowProc;
+ intermediate_class.cbClsExtra = 0;
+ intermediate_class.cbWndExtra = 0;
+ intermediate_class.hInstance = module_handle;
+ intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ intermediate_class.hbrBackground = NULL;
+ intermediate_class.lpszMenuName = NULL;
+ intermediate_class.lpszClassName = L"Intermediate GL Window";
+
+ ATOM class_registration = ::RegisterClass(&intermediate_class);
+ if (!class_registration) {
+ return false;
+ }
+
+ HWND intermediate_window = ::CreateWindow(
+ reinterpret_cast<wchar_t*>(class_registration),
+ L"",
+ WS_OVERLAPPEDWINDOW,
+ 0, 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!intermediate_window) {
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ HDC intermediate_dc = ::GetDC(intermediate_window);
+ g_regular_pixel_format = ::ChoosePixelFormat(intermediate_dc,
+ &kPixelFormatDescriptor);
+ if (g_regular_pixel_format == 0) {
+ DLOG(ERROR) << "Unable to get the pixel format for GL context.";
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+ if (!::SetPixelFormat(intermediate_dc, g_regular_pixel_format,
+ &kPixelFormatDescriptor)) {
+ DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // Create a temporary GL context to query for multisampled pixel formats.
+ HGLRC gl_context = ::wglCreateContext(intermediate_dc);
+ if (::wglMakeCurrent(intermediate_dc, gl_context)) {
+ // GL context was successfully created and applied to the window's DC.
+ // Startup GLEW, the GL extensions wrangler.
+ if (InitializeGLEW()) {
+ DLOG(INFO) << "Initialized GLEW " << glewGetString(GLEW_VERSION);
+ } else {
+ ::wglMakeCurrent(intermediate_dc, NULL);
+ ::wglDeleteContext(gl_context);
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // If the multi-sample extensions are present, query the api to determine
+ // the pixel format.
+ if (WGLEW_ARB_pixel_format && WGLEW_ARB_multisample) {
+ int pixel_attributes[] = {
+ WGL_SAMPLES_ARB, 4,
+ WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
+ WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
+ WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+ WGL_COLOR_BITS_ARB, 24,
+ WGL_ALPHA_BITS_ARB, 8,
+ WGL_DEPTH_BITS_ARB, 24,
+ WGL_STENCIL_BITS_ARB, 8,
+ WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
+ WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
+ 0, 0};
+
+ float pixel_attributes_f[] = {0, 0};
+ unsigned int num_formats;
+
+ // Query for the highest sampling rate supported, starting at 4x.
+ static const int kSampleCount[] = {4, 2};
+ static const int kNumSamples = 2;
+ for (int sample = 0; sample < kNumSamples; ++sample) {
+ pixel_attributes[1] = kSampleCount[sample];
+ if (GL_TRUE == ::wglChoosePixelFormatARB(intermediate_dc,
+ pixel_attributes,
+ pixel_attributes_f,
+ 1,
+ &g_multisampled_pixel_format,
+ &num_formats)) {
+ break;
+ }
+ }
+ }
+ }
+
+ ::wglMakeCurrent(intermediate_dc, NULL);
+ ::wglDeleteContext(gl_context);
+ ::ReleaseDC(intermediate_window, intermediate_dc);
+ ::DestroyWindow(intermediate_window);
+ ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ }
+
+ initialized = true;
+
+ return true;
+}
+
+bool NativeViewGLContext::Initialize(bool multisampled) {
+ // The GL context will render to this window.
+ device_context_ = GetDC(window_);
+
+ int pixel_format =
+ multisampled ? g_multisampled_pixel_format : g_regular_pixel_format;
+ if (!SetPixelFormat(device_context_,
+ pixel_format,
+ &kPixelFormatDescriptor)) {
+ DLOG(ERROR) << "Unable to set the pixel format for GL context.";
+ Destroy();
+ return false;
+ }
+
+ context_ = wglCreateContext(device_context_);
+ if (!context_) {
+ DLOG(ERROR) << "Failed to create GL context.";
+ Destroy();
+ return false;
+ }
+
+ if (!MakeCurrent()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeCommon()) {
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void NativeViewGLContext::Destroy() {
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ window_ = NULL;
+ device_context_ = NULL;
+}
+
+bool NativeViewGLContext::MakeCurrent() {
+ if (IsCurrent()) {
+ return true;
+ }
+ if (!wglMakeCurrent(device_context_, context_)) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ return true;
+}
+
+bool NativeViewGLContext::IsCurrent() {
+ return wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_;
+}
+
+bool NativeViewGLContext::IsOffscreen() {
+ return false;
+}
+
+void NativeViewGLContext::SwapBuffers() {
+ DCHECK(device_context_);
+ ::SwapBuffers(device_context_);
+}
+
+gfx::Size NativeViewGLContext::GetSize() {
+ RECT rect;
+ CHECK(GetClientRect(window_, &rect));
+ return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void* NativeViewGLContext::GetHandle() {
+ return context_;
+}
+
+bool OSMesaViewGLContext::Initialize() {
+ // The GL context will render to this window.
+ device_context_ = GetDC(window_);
+
+ if (!osmesa_context_.Initialize(NULL)) {
+ Destroy();
+ return false;
+ }
+
+ if (!MakeCurrent()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeCommon()) {
+ Destroy();
+ return false;
+ }
+
+ UpdateSize();
+
+ return true;
+}
+
+void OSMesaViewGLContext::Destroy() {
+ osmesa_context_.Destroy();
+
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ window_ = NULL;
+ device_context_ = NULL;
+}
+
+bool OSMesaViewGLContext::MakeCurrent() {
+ return osmesa_context_.MakeCurrent();
+}
+
+bool OSMesaViewGLContext::IsCurrent() {
+ return osmesa_context_.IsCurrent();
+}
+
+bool OSMesaViewGLContext::IsOffscreen() {
+ return false;
+}
+
+void OSMesaViewGLContext::SwapBuffers() {
+ DCHECK(device_context_);
+
+ // Update the size before blitting so that the blit size is exactly the same
+ // as the window.
+ UpdateSize();
+
+ gfx::Size size = osmesa_context_.GetSize();
+
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0xFF000000;
+ info.bV4GreenMask = 0x00FF0000;
+ info.bV4BlueMask = 0x0000FF00;
+ info.bV4AlphaMask = 0x000000FF;
+
+ // Copy the back buffer to the window's device context.
+ StretchDIBits(device_context_,
+ 0, 0, size.width(), size.height(),
+ 0, 0, size.width(), size.height(),
+ osmesa_context_.buffer(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+}
+
+gfx::Size OSMesaViewGLContext::GetSize() {
+ return osmesa_context_.GetSize();
+}
+
+void* OSMesaViewGLContext::GetHandle() {
+ return osmesa_context_.GetHandle();
+}
+
+void OSMesaViewGLContext::UpdateSize() {
+ // Change back buffer size to that of window.
+ RECT rect;
+ GetWindowRect(window_, &rect);
+ gfx::Size window_size = gfx::Size(
+ std::max(1, static_cast<int>(rect.right - rect.left)),
+ std::max(1, static_cast<int>(rect.bottom - rect.top)));
+ osmesa_context_.Resize(window_size);
+}
+
+GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
+ bool multisampled) {
+ if (!InitializeOneOff())
+ return NULL;
+
+ if (OSMesaCreateContext) {
+ scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window));
+
+ if (!context->Initialize())
+ return NULL;
+
+ return context.release();
+ } else {
+ scoped_ptr<NativeViewGLContext> context(new NativeViewGLContext(window));
+
+ if (!context->Initialize(multisampled))
+ return NULL;
+
+ return context.release();
+ }
+}
+
+bool PbufferGLContext::Initialize(void* shared_handle) {
+ // Create a device context compatible with the primary display.
+ HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL);
+
+ // Create a 1 x 1 pbuffer suitable for use with the device. This is just
+ // a stepping stone towards creating a frame buffer object. It doesn't
+ // matter what size it is.
+ const int kNoAttributes[] = { 0 };
+ pbuffer_ = ::wglCreatePbufferARB(display_device_context,
+ g_regular_pixel_format,
+ 1, 1,
+ kNoAttributes);
+ ::DeleteDC(display_device_context);
+ if (!pbuffer_) {
+ DLOG(ERROR) << "Unable to create pbuffer.";
+ Destroy();
+ return false;
+ }
+
+ device_context_ = ::wglGetPbufferDCARB(pbuffer_);
+ if (!device_context_) {
+ DLOG(ERROR) << "Unable to get pbuffer device context.";
+ Destroy();
+ return false;
+ }
+
+ context_ = ::wglCreateContext(device_context_);
+ if (!context_) {
+ DLOG(ERROR) << "Failed to create GL context.";
+ Destroy();
+ return false;
+ }
+
+ if (shared_handle) {
+ if (!wglShareLists(static_cast<GLContextHandle>(shared_handle), context_)) {
+ DLOG(ERROR) << "Could not share GL contexts.";
+ Destroy();
+ return false;
+ }
+ }
+
+ if (!MakeCurrent()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ if (!InitializeCommon()) {
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLContext::Destroy() {
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+
+ if (pbuffer_ && device_context_)
+ wglReleasePbufferDCARB(pbuffer_, device_context_);
+
+ device_context_ = NULL;
+
+ if (pbuffer_) {
+ wglDestroyPbufferARB(pbuffer_);
+ pbuffer_ = NULL;
+ }
+}
+
+bool PbufferGLContext::MakeCurrent() {
+ if (IsCurrent()) {
+ return true;
+ }
+ if (!wglMakeCurrent(device_context_, context_)) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ return true;
+}
+
+bool PbufferGLContext::IsCurrent() {
+ return wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_;
+}
+
+bool PbufferGLContext::IsOffscreen() {
+ return true;
+}
+
+void PbufferGLContext::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
+}
+
+gfx::Size PbufferGLContext::GetSize() {
+ NOTREACHED() << "Should not be requesting size of this pbuffer.";
+ 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 gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 26ab67f..13654c1 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -16,13 +16,13 @@
#include "base/weak_ptr.h"
#include "build/build_config.h"
#define GLES2_GPU_SERVICE 1
-#include "gfx/gl/gl_context.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
#include "gpu/command_buffer/service/id_manager.h"
@@ -368,7 +368,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual const char* GetCommandName(unsigned int command_id) const;
// Overridden from GLES2Decoder.
- virtual bool Initialize(gfx::GLContext* context,
+ virtual bool Initialize(GLContext* context,
const gfx::Size& size,
GLES2Decoder* parent,
uint32 parent_client_texture_id);
@@ -377,7 +377,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual bool MakeCurrent();
virtual uint32 GetServiceIdForTesting(uint32 client_id);
virtual GLES2Util* GetGLES2Util() { return &util_; }
- virtual gfx::GLContext* GetGLContext() { return context_; }
+ virtual GLContext* GetGLContext() { return context_; }
virtual void SetSwapBuffersCallback(Callback0::Type* callback);
@@ -827,14 +827,14 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
#undef GLES2_CMD_OP
// The GL context this decoder renders to on behalf of the client.
- gfx::GLContext* context_;
+ GLContext* context_;
// A GLContext that is kept in its default state. It is used to perform
// operations that should not be dependent on client set GLContext state, like
// clearing a render buffer when it is created.
// TODO(apatrick): Decoders in the same ContextGroup could potentially share
// the same default GL context.
- scoped_ptr<gfx::GLContext> default_context_;
+ scoped_ptr<GLContext> default_context_;
// A parent decoder can access this decoders saved offscreen frame buffer.
// The parent pointer is reset if the parent is destroyed.
@@ -1168,7 +1168,7 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
anti_aliased_(false) {
}
-bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
+bool GLES2DecoderImpl::Initialize(GLContext* context,
const gfx::Size& size,
GLES2Decoder* parent,
uint32 parent_client_texture_id) {
@@ -1178,7 +1178,7 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
// Create a GL context that is kept in a default state and shares a namespace
// with the main GL context.
- default_context_.reset(gfx::GLContext::CreateOffscreenGLContext(
+ default_context_.reset(GLContext::CreateOffscreenGLContext(
context_->GetHandle()));
if (!default_context_.get()) {
Destroy();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 4acd379..08e664b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -12,11 +12,11 @@
#include "gfx/size.h"
#include "gpu/command_buffer/service/common_decoder.h"
-namespace gfx {
-class GLContext;
-}
namespace gpu {
+// Forward-declared instead of including gl_context.h, because including glx.h
+// causes havok.
+class GLContext;
namespace gles2 {
@@ -53,7 +53,7 @@ class GLES2Decoder : public CommonDecoder {
// parent's namespace.
// Returns:
// true if successful.
- virtual bool Initialize(gfx::GLContext* context,
+ virtual bool Initialize(GLContext* context,
const gfx::Size& size,
GLES2Decoder* parent,
uint32 parent_client_texture_id) = 0;
@@ -74,7 +74,7 @@ class GLES2Decoder : public CommonDecoder {
virtual GLES2Util* GetGLES2Util() = 0;
// Gets the associated GLContext.
- virtual gfx::GLContext* GetGLContext() = 0;
+ virtual GLContext* GetGLContext() = 0;
// Sets a callback which is called when a SwapBuffers command is processed.
virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index d69d755..e29a1fe8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -28,7 +28,7 @@ class MockGLES2Decoder : public GLES2Decoder {
.WillByDefault(testing::Return(true));
}
- MOCK_METHOD4(Initialize, bool(gfx::GLContext* context,
+ MOCK_METHOD4(Initialize, bool(GLContext* context,
const gfx::Size& size,
GLES2Decoder* parent,
uint32 parent_texture_id));
@@ -37,7 +37,7 @@ class MockGLES2Decoder : public GLES2Decoder {
MOCK_METHOD0(MakeCurrent, bool());
MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id));
MOCK_METHOD0(GetGLES2Util, GLES2Util*());
- MOCK_METHOD0(GetGLContext, gfx::GLContext*());
+ MOCK_METHOD0(GetGLContext, GLContext*());
MOCK_METHOD1(SetSwapBuffersCallback, void(Callback0::Type*));
MOCK_METHOD3(DoCommand, error::Error(unsigned int command,
unsigned int arg_count,
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 9da6955..385779e 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -94,7 +94,7 @@ void GLES2DecoderTestBase::SetUp() {
shared_memory_offset_;
shared_memory_id_ = kSharedMemoryId;
- context_.reset(gfx::GLContext::CreateOffscreenGLContext(NULL));
+ context_.reset(GLContext::CreateOffscreenGLContext(NULL));
decoder_.reset(GLES2Decoder::Create(&group_));
decoder_->Initialize(context_.get(), gfx::Size(), NULL, 0);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index d12a1a0..773e285 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -5,13 +5,13 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_BASE_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_BASE_H_
-#include "gfx/gl/gl_context.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/buffer_manager.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/framebuffer_manager.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gl_mock.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/program_manager.h"
@@ -174,7 +174,7 @@ class GLES2DecoderTestBase : public testing::Test {
// Use StrictMock to make 100% sure we know how GL will be called.
scoped_ptr< ::testing::StrictMock< ::gles2::MockGLInterface> > gl_;
- scoped_ptr<gfx::GLContext> context_;
+ scoped_ptr<GLContext> context_;
scoped_ptr<GLES2Decoder> decoder_;
GLuint client_buffer_id_;
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index be0798f..ab3230b 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -5,7 +5,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
-#include "gfx/gl/gl_context.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index 47164cd..eb2d52b 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -23,12 +23,10 @@
#include "app/surface/accelerated_surface_mac.h"
#endif
-namespace gfx {
-class GLContext;
-}
-
namespace gpu {
+class GLContext;
+
// This class processes commands in a command buffer. It is event driven and
// posts tasks to the current message loop to do additional work.
class GPUProcessor : public CommandBufferEngine {
@@ -101,7 +99,7 @@ class GPUProcessor : public CommandBufferEngine {
gles2::ContextGroup group_;
scoped_ptr<gles2::GLES2Decoder> decoder_;
scoped_ptr<CommandParser> parser_;
- scoped_ptr<gfx::GLContext> context_;
+ scoped_ptr<GLContext> context_;
#if defined(OS_MACOSX) && !defined(UNIT_TEST)
scoped_ptr<AcceleratedSurface> surface_;
diff --git a/gpu/command_buffer/service/gpu_processor_linux.cc b/gpu/command_buffer/service/gpu_processor_linux.cc
index 5c4ef38..39fd234 100644
--- a/gpu/command_buffer/service/gpu_processor_linux.cc
+++ b/gpu/command_buffer/service/gpu_processor_linux.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "gfx/gl/gl_context.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
@@ -19,7 +19,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
// Get the parent decoder and the GLContext to share IDs with, if any.
gles2::GLES2Decoder* parent_decoder = NULL;
- gfx::GLContext* parent_context = NULL;
+ GLContext* parent_context = NULL;
void* parent_handle = NULL;
if (parent) {
parent_decoder = parent->decoder_.get();
@@ -37,9 +37,9 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
DCHECK(!parent_handle);
// TODO(apatrick): support multisampling.
- context_.reset(gfx::GLContext::CreateViewGLContext(window, false));
+ context_.reset(GLContext::CreateViewGLContext(window, false));
} else {
- context_.reset(gfx::GLContext::CreateOffscreenGLContext(parent_handle));
+ context_.reset(GLContext::CreateOffscreenGLContext(parent_handle));
}
if (!context_.get())
diff --git a/gpu/command_buffer/service/gpu_processor_mac.cc b/gpu/command_buffer/service/gpu_processor_mac.cc
index 01a247c..e7a3f6a 100644
--- a/gpu/command_buffer/service/gpu_processor_mac.cc
+++ b/gpu/command_buffer/service/gpu_processor_mac.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "gfx/gl/gl_context.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
@@ -19,7 +19,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
// Get the parent decoder and the GLContext to share IDs with, if any.
gles2::GLES2Decoder* parent_decoder = NULL;
- gfx::GLContext* parent_context = NULL;
+ GLContext* parent_context = NULL;
void* parent_handle = NULL;
if (parent) {
parent_decoder = parent->decoder_.get();
@@ -32,7 +32,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
DCHECK(parent_handle);
}
- context_.reset(gfx::GLContext::CreateOffscreenGLContext(parent_handle));
+ context_.reset(GLContext::CreateOffscreenGLContext(parent_handle));
if (!context_.get())
return false;
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
index 0f6e044..f4e3d54 100644
--- a/gpu/command_buffer/service/gpu_processor_win.cc
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -4,7 +4,7 @@
#include <windows.h>
-#include "gfx/gl/gl_context.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
@@ -21,7 +21,7 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
// Get the parent decoder and the GLContext to share IDs with, if any.
gles2::GLES2Decoder* parent_decoder = NULL;
- gfx::GLContext* parent_context = NULL;
+ GLContext* parent_context = NULL;
void* parent_handle = NULL;
if (parent) {
parent_decoder = parent->decoder_.get();
@@ -39,9 +39,9 @@ bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
DCHECK(!parent_handle);
// TODO(apatrick): support multisampling.
- context_.reset(gfx::GLContext::CreateViewGLContext(window, false));
+ context_.reset(GLContext::CreateViewGLContext(window, false));
} else {
- context_.reset(gfx::GLContext::CreateOffscreenGLContext(parent_handle));
+ context_.reset(GLContext::CreateOffscreenGLContext(parent_handle));
}
if (!context_.get())