diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-21 21:31:53 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-21 21:31:53 +0000 |
commit | 96f8063420f0170207f8b8fad211c70d3ad66db6 (patch) | |
tree | ecd625784f6ccf6a699f51a888e7e70056ab4bc0 /gpu/command_buffer/service | |
parent | d3d0ef9739170a270dcb2f070f2364aa003aea9c (diff) | |
download | chromium_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')
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()) |