summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-09 21:16:02 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-09 21:16:02 +0000
commitd37231fa18e0978822c6aa2c9d03e7a56e61810b (patch)
tree2765f8b09fe2f23a667cc1c0fb821d384a35dbd0 /gpu
parent7b70a92006d329a3e2df40ec6b61322212f75d95 (diff)
downloadchromium_src-d37231fa18e0978822c6aa2c9d03e7a56e61810b.zip
chromium_src-d37231fa18e0978822c6aa2c9d03e7a56e61810b.tar.gz
chromium_src-d37231fa18e0978822c6aa2c9d03e7a56e61810b.tar.bz2
- Extracted platform specific code from GLES2 command decoder to platform specific GLContext classes.
- GLContext encapsulates management of GL contexts on each platform. - ReadPixels uses actual current window size to validate source rectangle. TEST=trybots, running Pepper 3D and WebGL demos on all platforms BUG=none Review URL: http://codereview.chromium.org/1605014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44129 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
-rw-r--r--gpu/command_buffer/client/gles2_demo.cc2
-rw-r--r--gpu/command_buffer/service/cmd_parser.cc1
-rw-r--r--gpu/command_buffer/service/cmd_parser_test.cc2
-rw-r--r--gpu/command_buffer/service/common_decoder.cc1
-rw-r--r--gpu/command_buffer/service/gl_context.cc81
-rw-r--r--gpu/command_buffer/service/gl_context.h169
-rw-r--r--gpu/command_buffer/service/gl_context_linux.cc (renamed from gpu/command_buffer/service/x_utils.cc)240
-rw-r--r--gpu/command_buffer/service/gl_context_mac.cc191
-rw-r--r--gpu/command_buffer/service/gl_context_win.cc376
-rw-r--r--gpu/command_buffer/service/gl_utils.h4
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc803
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.h59
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_mock.h14
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc2
-rw-r--r--gpu/command_buffer/service/gpu_processor.cc64
-rw-r--r--gpu/command_buffer/service/gpu_processor.h34
-rw-r--r--gpu/command_buffer/service/gpu_processor_linux.cc82
-rw-r--r--gpu/command_buffer/service/gpu_processor_mac.cc95
-rw-r--r--gpu/command_buffer/service/gpu_processor_mock.h2
-rw-r--r--gpu/command_buffer/service/gpu_processor_win.cc65
-rw-r--r--gpu/command_buffer/service/precompile.cc5
-rw-r--r--gpu/command_buffer/service/precompile.h22
-rw-r--r--gpu/command_buffer/service/x_utils.h109
-rw-r--r--gpu/demos/framework/window.cc2
-rw-r--r--gpu/gpu.gyp73
25 files changed, 1381 insertions, 1117 deletions
diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc
index 6035042..3e9ea77 100644
--- a/gpu/command_buffer/client/gles2_demo.cc
+++ b/gpu/command_buffer/client/gles2_demo.cc
@@ -56,8 +56,8 @@ bool GLES2Demo::Setup(void* hwnd, int32 size) {
GPUProcessor* gpu_processor = new GPUProcessor(command_buffer.get());
if (!gpu_processor->Initialize(reinterpret_cast<HWND>(hwnd),
- NULL,
gfx::Size(),
+ NULL,
0)) {
return NULL;
}
diff --git a/gpu/command_buffer/service/cmd_parser.cc b/gpu/command_buffer/service/cmd_parser.cc
index 804b894..191ddfa 100644
--- a/gpu/command_buffer/service/cmd_parser.cc
+++ b/gpu/command_buffer/service/cmd_parser.cc
@@ -4,7 +4,6 @@
// This file contains the implementation of the command parser.
-#include "gpu/command_buffer/service/precompile.h"
#include "gpu/command_buffer/service/cmd_parser.h"
namespace gpu {
diff --git a/gpu/command_buffer/service/cmd_parser_test.cc b/gpu/command_buffer/service/cmd_parser_test.cc
index d46cf3b..0f2509e 100644
--- a/gpu/command_buffer/service/cmd_parser_test.cc
+++ b/gpu/command_buffer/service/cmd_parser_test.cc
@@ -4,8 +4,6 @@
// Tests for the command parser.
-#include "gpu/command_buffer/service/precompile.h"
-
#include "base/scoped_ptr.h"
#include "gpu/command_buffer/service/cmd_parser.h"
#include "gpu/command_buffer/service/mocks.h"
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
index feb59eb..c28c448 100644
--- a/gpu/command_buffer/service/common_decoder.cc
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -2,7 +2,6 @@
// 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/precompile.h"
#include "gpu/command_buffer/service/common_decoder.h"
#include "gpu/command_buffer/service/cmd_buffer_engine.h"
diff --git a/gpu/command_buffer/service/gl_context.cc b/gpu/command_buffer/service/gl_context.cc
new file mode 100644
index 0000000..3602a07
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context.cc
@@ -0,0 +1,81 @@
+// 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
+}
+
+} // 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..832624db9
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context.h
@@ -0,0 +1,169 @@
+// 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 "base/basictypes.h"
+#include "gfx/native_widget_types.h"
+#include "gfx/size.h"
+#include "gpu/command_buffer/common/logging.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+
+class AcceleratedSurface;
+
+namespace gpu {
+
+#if defined(UNIT_TEST)
+typedef void* HDC;
+struct Display;
+typedef void* GLContextHandle;
+typedef void* PbufferHandle;
+#elif defined(OS_WIN)
+typedef HGLRC GLContextHandle;
+typedef HPBUFFERARB PbufferHandle;
+#elif defined(OS_LINUX)
+typedef GLXContext GLContextHandle;
+typedef GLXPbuffer PbufferHandle;
+#elif defined(OS_MACOSX)
+typedef CGLContextObj GLContextHandle;
+typedef CGLPBufferObj PbufferHandle;
+#endif
+
+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 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 GLContextHandle GetHandle() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLContext);
+};
+
+// This class is a wrapper around a GL context that renders directly to a
+// window.
+class ViewGLContext : public GLContext {
+ public:
+#if defined(OS_WIN)
+ explicit ViewGLContext(gfx::PluginWindowHandle window)
+ : window_(window),
+ device_context_(NULL),
+ context_(NULL) {
+ DCHECK(window);
+ }
+#elif defined(OS_LINUX)
+ ViewGLContext(Display* display, gfx::PluginWindowHandle window)
+ : display_(display),
+ window_(window),
+ context_(NULL) {
+ DCHECK(display);
+ DCHECK(window);
+ }
+#elif defined(OS_MACOSX)
+ explicit ViewGLContext(AcceleratedSurface* surface) : surface_(surface) {
+ DCHECK(surface);
+ }
+#endif
+
+ // Initializes the GL context.
+ bool Initialize(bool multisampled);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual GLContextHandle GetHandle();
+
+ private:
+#if defined(OS_WIN)
+ gfx::PluginWindowHandle window_;
+ HDC device_context_;
+ GLContextHandle context_;
+#elif defined(OS_LINUX)
+ Display* display_;
+ gfx::PluginWindowHandle window_;
+ GLContextHandle context_;
+#elif defined(OS_MACOSX)
+ AcceleratedSurface* surface_;
+#endif
+
+ 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:
+#if defined(OS_WIN)
+ PbufferGLContext()
+ : context_(NULL),
+ device_context_(NULL),
+ pbuffer_(NULL) {
+ }
+#elif defined(OS_LINUX)
+ explicit PbufferGLContext(Display* display)
+ : context_(NULL),
+ display_(display),
+ pbuffer_(NULL) {
+ DCHECK(display_);
+ }
+#elif defined(OS_MACOSX)
+ PbufferGLContext()
+ : context_(NULL),
+ pbuffer_(NULL) {
+ }
+#endif
+
+ // Initializes the GL context.
+ bool Initialize(GLContext* shared_context);
+
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsOffscreen();
+ virtual void SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual GLContextHandle GetHandle();
+
+ private:
+ GLContextHandle context_;
+#if defined(OS_WIN)
+ HDC device_context_;
+ PbufferHandle pbuffer_;
+#elif defined(OS_LINUX)
+ Display* display_;
+ PbufferHandle pbuffer_;
+#elif defined(OS_MACOSX)
+ PbufferHandle pbuffer_;
+#endif
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
+};
+
+} // namespace gpu
+
+#endif // GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_H_
diff --git a/gpu/command_buffer/service/x_utils.cc b/gpu/command_buffer/service/gl_context_linux.cc
index 30a9167..0acbb02 100644
--- a/gpu/command_buffer/service/x_utils.cc
+++ b/gpu/command_buffer/service/gl_context_linux.cc
@@ -1,18 +1,24 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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 class implements the XWindowWrapper class.
+// This file implements the ViewGLContext and PbufferGLContext classes.
+#if !defined(UNIT_TEST)
#include <dlfcn.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#endif
+#include "gpu/command_buffer/service/gl_context.h"
#include "base/scoped_ptr.h"
-#include "gpu/command_buffer/service/precompile.h"
+#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/common/logging.h"
-#include "gpu/command_buffer/service/x_utils.h"
namespace gpu {
+#if !defined(UNIT_TEST)
+
// 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.
@@ -28,11 +34,9 @@ class ScopedPtrXFree {
// load it, and use glew to dynamically resolve symbols.
// See http://code.google.com/p/chromium/issues/detail?id=16800
-static bool g_glxew_initialized = false;
-static bool g_glew_initialized = false;
-
static bool InitializeGLXEW(Display* display) {
- if (!g_glxew_initialized) {
+ static bool glxew_initialized = false;
+ if (!glxew_initialized) {
void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
LOG(ERROR) << "Could not find libGL.so.1";
@@ -52,36 +56,45 @@ static bool InitializeGLXEW(Display* display) {
LOG(ERROR) << "glxewContextInit failed";
return false;
}
- g_glxew_initialized = true;
+ glxew_initialized = true;
}
+
return true;
}
-// 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.
-static bool InitializeGLEW() {
- if (!g_glew_initialized) {
- // Initializes context-dependent parts of GLEW
- if (glewInit() != GLEW_OK) {
- LOG(ERROR) << "GLEW failed initialization";
- return false;
- }
+#endif // UNIT_TEST
- if (!glewIsSupported("GL_VERSION_2_0")) {
- LOG(ERROR) << "GL implementation doesn't support GL version 2.0";
- return false;
- }
- g_glew_initialized = true;
+bool ViewGLContext::Initialize(bool multisampled) {
+#if !defined(UNIT_TEST)
+ if (multisampled) {
+ DLOG(WARNING) << "Multisampling not implemented.";
}
- return true;
-}
-GLXContextWrapper::~GLXContextWrapper() {
-}
+ if (!InitializeGLXEW(display_))
+ return false;
+
+ 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;
+ }
-bool GLXContextWrapper::Initialize() {
if (!MakeCurrent()) {
Destroy();
DLOG(ERROR) << "Couldn't make context current for initialization.";
@@ -92,75 +105,73 @@ bool GLXContextWrapper::Initialize() {
Destroy();
return false;
}
+#endif // UNIT_TEST
return true;
}
-void GLXContextWrapper::Destroy() {
- Bool result = glXMakeCurrent(GetDisplay(), 0, 0);
+void ViewGLContext::Destroy() {
+ #if !defined(UNIT_TEST)
+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 (GetContext()) {
- glXDestroyContext(GetDisplay(), GetContext());
- SetContext(NULL);
+ if (context_) {
+ glXDestroyContext(display_, context_);
+ context_ = NULL;
}
+#endif // UNIT_TEST
}
-bool XWindowWrapper::Initialize() {
- if (!InitializeGLXEW(GetDisplay()))
- return false;
-
- XWindowAttributes attributes;
- XGetWindowAttributes(GetDisplay(), 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(GetDisplay(), VisualIDMask,
- &visual_info_template,
- &visual_info_count));
- DCHECK(visual_info_list.get());
- DCHECK_GT(visual_info_count, 0);
- SetContext(NULL);
- for (int i = 0; i < visual_info_count; ++i) {
- SetContext(glXCreateContext(GetDisplay(), visual_info_list.get() + i, 0,
- True));
- if (GetContext())
- break;
- }
- if (!GetContext()) {
- DLOG(ERROR) << "Couldn't create GL context.";
- return false;
- }
- return GLXContextWrapper::Initialize();
-}
-
-bool XWindowWrapper::MakeCurrent() {
+bool ViewGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
if (glXGetCurrentDrawable() == window_ &&
- glXGetCurrentContext() == GetContext()) {
+ glXGetCurrentContext() == context_) {
return true;
}
- if (glXMakeCurrent(GetDisplay(), window_, GetContext()) != True) {
- glXDestroyContext(GetDisplay(), GetContext());
- SetContext(0);
+ if (glXMakeCurrent(display_, window_, context_) != True) {
+ glXDestroyContext(display_, context_);
+ context_ = 0;
DLOG(ERROR) << "Couldn't make context current.";
return false;
}
+#endif // UNIT_TEST
+
return true;
}
-bool XWindowWrapper::IsOffscreen() {
+bool ViewGLContext::IsOffscreen() {
return false;
}
-void XWindowWrapper::SwapBuffers() {
- glXSwapBuffers(GetDisplay(), window_);
+void ViewGLContext::SwapBuffers() {
+#if !defined(UNIT_TEST)
+ glXSwapBuffers(display_, window_);
+#endif // UNIT_TEST
}
-bool GLXPbufferWrapper::Initialize() {
- if (!InitializeGLXEW(GetDisplay()))
+gfx::Size ViewGLContext::GetSize() {
+#if !defined(UNIT_TEST)
+ XWindowAttributes attributes;
+ XGetWindowAttributes(display_, window_, &attributes);
+ return gfx::Size(attributes.width, attributes.height);
+#else
+ return gfx::Size();
+#endif // UNIT_TEST
+}
+
+GLContextHandle ViewGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return context_;
+#else
+ return NULL;
+#endif // UNIT_TEST
+}
+
+bool PbufferGLContext::Initialize(GLContext* shared_context) {
+#if !defined(UNIT_TEST)
+ if (!InitializeGLXEW(display_))
return false;
if (!glXChooseFBConfig ||
@@ -171,6 +182,11 @@ bool GLXPbufferWrapper::Initialize() {
return false;
}
+ // Get the shared context handle.
+ GLContextHandle shared_handle = NULL;
+ if (shared_context)
+ shared_handle = shared_context->GetHandle();
+
static const int config_attributes[] = {
GLX_DRAWABLE_TYPE,
GLX_PBUFFER_BIT,
@@ -184,7 +200,7 @@ bool GLXPbufferWrapper::Initialize() {
int nelements = 0;
// TODO(kbr): figure out whether hardcoding screen to 0 is sufficient.
scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config(
- glXChooseFBConfig(GetDisplay(), 0, config_attributes, &nelements));
+ glXChooseFBConfig(display_, 0, config_attributes, &nelements));
if (!config.get()) {
DLOG(ERROR) << "glXChooseFBConfig failed.";
return false;
@@ -193,9 +209,12 @@ bool GLXPbufferWrapper::Initialize() {
DLOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
return false;
}
- SetContext(glXCreateNewContext(GetDisplay(),
- config.get()[0], GLX_RGBA_TYPE, 0, True));
- if (!GetContext()) {
+ context_ = glXCreateNewContext(display_,
+ config.get()[0],
+ GLX_RGBA_TYPE,
+ shared_handle,
+ True);
+ if (!context_) {
DLOG(ERROR) << "glXCreateNewContext failed.";
return false;
}
@@ -206,43 +225,84 @@ bool GLXPbufferWrapper::Initialize() {
1,
0
};
- pbuffer_ = glXCreatePbuffer(GetDisplay(),
+ pbuffer_ = glXCreatePbuffer(display_,
config.get()[0], pbuffer_attributes);
if (!pbuffer_) {
Destroy();
DLOG(ERROR) << "glXCreatePbuffer failed.";
return false;
}
- return GLXContextWrapper::Initialize();
+
+ if (!MakeCurrent()) {
+ Destroy();
+ DLOG(ERROR) << "Couldn't make context current for initialization.";
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+#endif // UNIT_TEST
+
+ return true;
}
-void GLXPbufferWrapper::Destroy() {
- GLXContextWrapper::Destroy();
+void PbufferGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ 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(GetDisplay(), pbuffer_);
+ glXDestroyPbuffer(display_, pbuffer_);
pbuffer_ = NULL;
}
+#endif // UNIT_TEST
}
-bool GLXPbufferWrapper::MakeCurrent() {
+bool PbufferGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
if (glXGetCurrentDrawable() == pbuffer_ &&
- glXGetCurrentContext() == GetContext()) {
+ glXGetCurrentContext() == context_) {
return true;
}
- if (glXMakeCurrent(GetDisplay(), pbuffer_, GetContext()) != True) {
- glXDestroyContext(GetDisplay(), GetContext());
- SetContext(0);
+ if (glXMakeCurrent(display_, pbuffer_, context_) != True) {
+ glXDestroyContext(display_, context_);
+ context_ = NULL;
DLOG(ERROR) << "Couldn't make context current.";
return false;
}
+#endif // UNIT_TEST
+
return true;
}
-bool GLXPbufferWrapper::IsOffscreen() {
+bool PbufferGLContext::IsOffscreen() {
return true;
}
-void GLXPbufferWrapper::SwapBuffers() {
+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);
+}
+
+GLContextHandle PbufferGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return context_;
+#else
+ return NULL;
+#endif // UNIT_TEST
}
} // 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..9e79a69
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_mac.cc
@@ -0,0 +1,191 @@
+// 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 "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/common/logging.h"
+
+#if !defined(UNIT_TEST)
+#include "app/surface/accelerated_surface_mac.h"
+#endif
+
+namespace gpu {
+
+bool ViewGLContext::Initialize(bool multisampled) {
+#if !defined(UNIT_TEST)
+ if (multisampled) {
+ DLOG(WARNING) << "Multisampling not implemented.";
+ }
+
+ if (!surface_->Initialize()) {
+ DLOG(ERROR) << "Error initializing accelerated surface.";
+ return false;
+ }
+
+ if (!MakeCurrent()) {
+ Destroy();
+ DLOG(ERROR) << "Couldn't make context current for initialization.";
+ return false;
+ }
+
+ if (!InitializeGLEW()) {
+ Destroy();
+ return false;
+ }
+
+ return true;
+#else
+ return true;
+#endif // UNIT_TEST
+}
+
+void ViewGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ surface_->Destroy();
+#endif // UNIT_TEST
+}
+
+bool ViewGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
+ return surface_->MakeCurrent();
+#else
+ return true;
+#endif
+}
+
+bool ViewGLContext::IsOffscreen() {
+ return false;
+}
+
+void ViewGLContext::SwapBuffers() {
+#if !defined(UNIT_TEST)
+ surface_->SwapBuffers();
+#endif // UNIT_TEST
+}
+
+gfx::Size ViewGLContext::GetSize() {
+#if !defined(UNIT_TEST)
+ return surface_->GetSize();
+#else
+ return gfx::Size();
+#endif // UNIT_TEST
+}
+
+GLContextHandle ViewGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return surface_->context();
+#else
+ return NULL;
+#endif // UNIT_TEST
+}
+
+bool PbufferGLContext::Initialize(GLContext* shared_context) {
+#if !defined(UNIT_TEST)
+ // Get the shared context handle.
+ GLContextHandle shared_handle = NULL;
+ if (shared_context)
+ shared_handle = shared_context->GetHandle();
+
+ // 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, 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;
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+void PbufferGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ if (context_) {
+ CGLDestroyContext(context_);
+ context_ = NULL;
+ }
+
+ if (pbuffer_) {
+ CGLDestroyPBuffer(pbuffer_);
+ pbuffer_ = NULL;
+ }
+#endif // UNIT_TEST
+}
+
+bool PbufferGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
+ if (CGLGetCurrentContext() != context_) {
+ if (CGLSetCurrentContext(context_) != kCGLNoError) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+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);
+}
+
+GLContextHandle PbufferGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return context_;
+#else
+ return NULL;
+#endif // UNIT_TEST
+}
+
+} // 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..3be106a
--- /dev/null
+++ b/gpu/command_buffer/service/gl_context_win.cc
@@ -0,0 +1,376 @@
+// 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 "gpu/command_buffer/service/gl_context.h"
+#include "gpu/command_buffer/common/logging.h"
+
+namespace gpu {
+
+#if !defined(UNIT_TEST)
+
+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);
+}
+
+#endif // UNIT_TEST
+
+// Helper routine that does one-off initialization like determining the
+// pixel format and initializing glew.
+static bool InitializeOneOff() {
+#if !defined(UNIT_TEST)
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ // 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;
+#endif // UNIT_TEST
+
+ return true;
+}
+
+bool ViewGLContext::Initialize(bool multisampled) {
+#if !defined(UNIT_TEST)
+ InitializeOneOff();
+
+ // 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;
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+void ViewGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ window_ = NULL;
+ device_context_ = NULL;
+#endif // UNIT_TEST
+}
+
+bool ViewGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
+ if (wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_) {
+ return true;
+ }
+ if (!wglMakeCurrent(device_context_, context_)) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+bool ViewGLContext::IsOffscreen() {
+ return false;
+}
+
+void ViewGLContext::SwapBuffers() {
+#if !defined(UNIT_TEST)
+ DCHECK(device_context_);
+ ::SwapBuffers(device_context_);
+#endif // UNIT_TEST
+}
+
+gfx::Size ViewGLContext::GetSize() {
+#if !defined(UNIT_TEST)
+ RECT rect;
+ CHECK(GetClientRect(window_, &rect));
+ return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
+#else
+ return gfx::Size();
+#endif // UNIT_TEST
+}
+
+GLContextHandle ViewGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return context_;
+#else
+ return NULL;
+#endif // UNIT_TEST
+}
+
+bool PbufferGLContext::Initialize(GLContext* shared_context) {
+#if !defined(UNIT_TEST)
+ InitializeOneOff();
+
+ // 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_context) {
+ if (!wglShareLists(shared_context->GetHandle(), context_)) {
+ DLOG(ERROR) << "Could not share GL contexts.";
+ Destroy();
+ return false;
+ }
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+void PbufferGLContext::Destroy() {
+#if !defined(UNIT_TEST)
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+
+ if (pbuffer_ && device_context_)
+ wglReleasePbufferDCARB(pbuffer_, device_context_);
+
+ device_context_ = NULL;
+
+ if (pbuffer_) {
+ wglDestroyPbufferARB(pbuffer_);
+ pbuffer_ = NULL;
+ }
+#endif // UNIT_TEST
+}
+
+bool PbufferGLContext::MakeCurrent() {
+#if !defined(UNIT_TEST)
+ if (wglGetCurrentDC() == device_context_ &&
+ wglGetCurrentContext() == context_) {
+ return true;
+ }
+ if (!wglMakeCurrent(device_context_, context_)) {
+ DLOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+#endif // UNIT_TEST
+
+ return true;
+}
+
+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);
+}
+
+GLContextHandle PbufferGLContext::GetHandle() {
+#if !defined(UNIT_TEST)
+ return context_;
+#else
+ return NULL;
+#endif // UNIT_TEST
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/service/gl_utils.h b/gpu/command_buffer/service/gl_utils.h
index 943681c..c5a3c98 100644
--- a/gpu/command_buffer/service/gl_utils.h
+++ b/gpu/command_buffer/service/gl_utils.h
@@ -53,8 +53,12 @@
#include <GL/glew.h> // NOLINT
#if defined(OS_WIN)
#include <GL/wglew.h> // NOLINT
+ #include <windows.h> // NOLINT
#elif defined(OS_LINUX)
#include <GL/glxew.h> // NOLINT
+ #include <GL/glx.h> // NOLINT
+ #elif defined(OS_MACOSX)
+ #include <OpenGL/OpenGL.h> // NOLINT
#endif // OS_WIN
// GLES2 defines not part of Desktop GL
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index 32308a5..4f70ecf 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -10,11 +10,11 @@
#include <vector>
#include <string>
#include <map>
-#include <build/build_config.h> // NOLINT
#include "base/callback.h"
#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
#include "base/weak_ptr.h"
+#include "build/build_config.h"
#define GLES2_GPU_SERVICE 1
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
@@ -22,6 +22,7 @@
#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"
@@ -29,13 +30,6 @@
#include "gpu/command_buffer/service/renderbuffer_manager.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
-#if defined(UNIT_TEST)
-#elif defined(OS_LINUX)
-// GLXContextWrapper is stubbed out for unit-tests.
-#include "gpu/command_buffer/service/x_utils.h"
-#elif defined(OS_MACOSX)
-#include "app/surface/accelerated_surface_mac.h"
-#endif
#if !defined(GL_DEPTH24_STENCIL8)
#define GL_DEPTH24_STENCIL8 0x88F0
@@ -185,9 +179,14 @@ class Texture {
return id_;
}
+ gfx::Size size() const {
+ return size_;
+ }
+
private:
GLES2DecoderImpl* decoder_;
GLuint id_;
+ gfx::Size size_;
DISALLOW_COPY_AND_ASSIGN(Texture);
};
@@ -256,17 +255,7 @@ class FrameBuffer {
GLES2Decoder::GLES2Decoder(ContextGroup* group)
: group_(group),
-#if defined(UNIT_TEST)
debug_(false) {
-#elif defined(OS_LINUX)
- debug_(false),
- context_(NULL) {
-#elif defined(OS_WIN)
- debug_(false),
- hwnd_(NULL) {
-#else
- debug_(false) {
-#endif
}
GLES2Decoder::~GLES2Decoder() {
@@ -356,34 +345,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
virtual const char* GetCommandName(unsigned int command_id) const;
// Overridden from GLES2Decoder.
- virtual bool Initialize(GLES2Decoder* parent,
+ virtual bool Initialize(GLContext* context,
const gfx::Size& size,
+ GLES2Decoder* parent,
uint32 parent_client_texture_id);
virtual void Destroy();
virtual void ResizeOffscreenFrameBuffer(const gfx::Size& size);
virtual bool MakeCurrent();
virtual uint32 GetServiceIdForTesting(uint32 client_id);
virtual GLES2Util* GetGLES2Util() { return &util_; }
-
-#if defined(OS_MACOSX)
- // Overridden from GLES2Decoder.
-
- // The recommended usage is to call SetWindowSizeForIOSurface() first, and if
- // that returns 0, try calling SetWindowSizeForTransportDIB(). A return value
- // of 0 from SetWindowSizeForIOSurface() might mean the IOSurface API is not
- // available, which is true if you are not running on Max OS X 10.6 or later.
- // If SetWindowSizeForTransportDIB() also returns a NULL handle, then an
- // error has occured.
- virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
- virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
- int32 height);
- // |allocator| sends a message to the renderer asking for a new
- // TransportDIB big enough to hold the rendered bits. The parameters to the
- // call back are the size of the DIB and the handle (filled in on return).
- virtual void SetTransportDIBAllocAndFree(
- Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator);
-#endif
+ virtual GLContext* GetGLContext() { return context_; }
virtual void SetSwapBuffersCallback(Callback0::Type* callback);
@@ -456,15 +427,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
return group_->texture_manager();
}
-#if defined(OS_WIN)
- static bool InitializeOneOff(bool anti_aliased);
-#endif
-
-
- bool InitPlatformSpecific();
- static bool InitGlew();
- void DestroyPlatformSpecific();
-
bool UpdateOffscreenFrameBufferSize();
// Template to help call glGenXXX functions.
@@ -517,6 +479,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
texture_manager()->RemoveTextureInfo(texture);
}
+ // Get the size (in pixels) of the currently bound frame buffer (either FBO
+ // or regular back buffer).
+ gfx::Size GetBoundFrameBufferSize();
+
// Wrapper for CompressedTexImage2D commands.
error::Error DoCompressedTexImage2D(
GLenum target,
@@ -813,16 +779,16 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
#undef GLES2_CMD_OP
+ // The GL context this decoder renders to.
+ GLContext* context_;
+
// A parent decoder can access this decoders saved offscreen frame buffer.
// The parent pointer is reset if the parent is destroyed.
base::WeakPtr<GLES2DecoderImpl> parent_;
// Width and height to which an offscreen frame buffer should be resized on
// the next call to SwapBuffers.
- gfx::Size pending_size_;
-
- // Width and height of a decoder that renders to an offscreen frame buffer.
- gfx::Size current_size_;
+ gfx::Size pending_offscreen_size_;
// Current GL error bits.
uint32 error_bits_;
@@ -871,19 +837,6 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// The currently bound renderbuffer
GLuint bound_renderbuffer_;
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
- static int pixel_format_;
- HDC gl_device_context_;
- HGLRC gl_context_;
- HPBUFFERARB pbuffer_;
-#elif defined(OS_MACOSX)
- CGLContextObj gl_context_;
- CGLPBufferObj pbuffer_;
- AcceleratedSurface surface_;
-#endif
-
bool anti_aliased_;
// The offscreen frame buffer that the client renders to.
@@ -1006,6 +959,8 @@ bool Texture::AllocateStorage(const gfx::Size& size) {
GL_UNSIGNED_BYTE,
NULL);
+ size_ = size;
+
return glGetError() == GL_NO_ERROR;
}
@@ -1136,14 +1091,9 @@ GLES2Decoder* GLES2Decoder::Create(ContextGroup* group) {
return new GLES2DecoderImpl(group);
}
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
-int GLES2DecoderImpl::pixel_format_;
-#endif
-
GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
: GLES2Decoder(group),
+ context_(NULL),
error_bits_(0),
util_(0), // TODO(gman): Set to actual num compress texture formats.
pack_alignment_(4),
@@ -1153,48 +1103,26 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
black_cube_texture_id_(0),
bound_framebuffer_(0),
bound_renderbuffer_(0),
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
- gl_device_context_(NULL),
- gl_context_(NULL),
- pbuffer_(NULL),
-#elif defined(OS_MAC)
- gl_context_(NULL),
- pbuffer_(NULL),
-#endif
anti_aliased_(false) {
}
-bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent,
+bool GLES2DecoderImpl::Initialize(GLContext* context,
const gfx::Size& size,
+ GLES2Decoder* parent,
uint32 parent_client_texture_id) {
+ DCHECK(!context_);
+ context_ = context;
+
// Keep only a weak pointer to the parent so we don't unmap its client
- // frame buffer is after it has been destroyed.
+ // frame buffer after it has been destroyed.
if (parent)
parent_ = static_cast<GLES2DecoderImpl*>(parent)->AsWeakPtr();
- pending_size_ = size;
-
- if (!InitPlatformSpecific()) {
- Destroy();
- return false;
- }
-
if (!MakeCurrent()) {
Destroy();
return false;
}
- // This happens in InitializeOneOff in windows. TODO(apatrick): generalize to
- // other platforms.
-#if !defined(OS_WIN)
- if (!InitGlew()) {
- Destroy();
- return false;
- }
-#endif
-
CHECK_GL_ERROR();
if (!group_->Initialize()) {
@@ -1232,7 +1160,8 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent,
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
CHECK_GL_ERROR();
- if (size.width() > 0 && size.height() > 0) {
+#if !defined(UNIT_TEST)
+ if (context_->IsOffscreen()) {
// Create the target frame buffer. This is the one that the client renders
// directly to.
offscreen_target_frame_buffer_.reset(new FrameBuffer(this));
@@ -1267,6 +1196,7 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent,
// Allocate the render buffers at their initial size and check the status
// of the frame buffers is okay.
+ pending_offscreen_size_ = size;
if (!UpdateOffscreenFrameBufferSize()) {
DLOG(ERROR) << "Could not allocate offscreen buffer storage.";
Destroy();
@@ -1277,6 +1207,7 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent,
// This should now be associated with ID zero.
DoBindFramebuffer(GL_FRAMEBUFFER, 0);
}
+#endif // UNIT_TEST
#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
// OpenGL ES 2.0 implicitly enables the desktop GL capability
@@ -1289,176 +1220,6 @@ bool GLES2DecoderImpl::Initialize(GLES2Decoder* parent,
return true;
}
-// TODO(kbr): the use of this anonymous namespace core dumps the
-// linker on Mac OS X 10.6 when the symbol ordering file is used
-// namespace {
-
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
-
-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.
-bool GLES2DecoderImpl::InitializeOneOff(bool anti_aliased) {
- // 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);
- pixel_format_ = ::ChoosePixelFormat(intermediate_dc,
- &kPixelFormatDescriptor);
- if (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, 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 (InitGlew()) {
- 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 (anti_aliased && 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};
- int msaa_pixel_format;
- 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,
- &msaa_pixel_format,
- &num_formats)) {
- pixel_format_ = msaa_pixel_format;
- 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);
- return true;
-}
-
-#endif // OS_WIN
-
// These commands convert from c calls to local os calls.
void GLGenBuffersHelper(
GLES2DecoderImpl* decoder, GLsizei n, GLuint* ids) {
@@ -1537,36 +1298,8 @@ void GLDeleteTexturesHelper(
bool GLES2DecoderImpl::MakeCurrent() {
#if defined(UNIT_TEST)
return true;
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
- return true;
-#elif defined(OS_WIN)
- if (::wglGetCurrentDC() == gl_device_context_ &&
- ::wglGetCurrentContext() == gl_context_) {
- return true;
- }
- if (!::wglMakeCurrent(gl_device_context_, gl_context_)) {
- DLOG(ERROR) << "Unable to make gl context current.";
- return false;
- }
- return true;
-#elif defined(OS_LINUX)
- // TODO(apatrick): offscreen rendering not yet supported on this platform.
- return context()->MakeCurrent();
-#elif defined(OS_MACOSX)
- if (gl_context_) {
- if (CGLGetCurrentContext() != gl_context_) {
- if (CGLSetCurrentContext(gl_context_) != kCGLNoError) {
- DLOG(ERROR) << "Unable to make gl context current.";
- return false;
- }
- }
- return true;
- } else {
- return surface_.MakeCurrent();
- }
#else
- NOTREACHED();
- return false;
+ return context_->MakeCurrent();
#endif
}
@@ -1614,233 +1347,99 @@ void GLES2DecoderImpl::UnregisterObjects(
}
}
-bool GLES2DecoderImpl::InitPlatformSpecific() {
-#if !defined(UNIT_TEST) && !defined(OS_LINUX)
- bool offscreen = pending_size_.width() > 0 && pending_size_.height() > 0;
-#endif
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
- // Do one-off initialization.
- static bool success = InitializeOneOff(anti_aliased_);
- if (!success)
- return false;
-
- if (offscreen) {
- // 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,
- pixel_format_,
- 1, 1,
- kNoAttributes);
- ::DeleteDC(display_device_context);
- if (!pbuffer_) {
- DLOG(ERROR) << "Unable to create pbuffer.";
- DestroyPlatformSpecific();
- return false;
- }
-
- gl_device_context_ = ::wglGetPbufferDCARB(pbuffer_);
- if (!gl_device_context_) {
- DLOG(ERROR) << "Unable to get pbuffer device context.";
- DestroyPlatformSpecific();
- return false;
- }
- } else {
- // The GL context will render to this window.
- gl_device_context_ = ::GetDC(hwnd());
-
- if (!::SetPixelFormat(gl_device_context_,
- pixel_format_,
- &kPixelFormatDescriptor)) {
- DLOG(ERROR) << "Unable to set the pixel format for GL context.";
- DestroyPlatformSpecific();
- return false;
- }
- }
-
- gl_context_ = ::wglCreateContext(gl_device_context_);
- if (!gl_context_) {
- DLOG(ERROR) << "Failed to create GL context.";
- DestroyPlatformSpecific();
- return false;
- }
+gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() {
+ if (bound_framebuffer_ != 0) {
+ int width = 0;
+ int height = 0;
- if (parent_) {
- if (!wglShareLists(parent_->gl_context_, gl_context_)) {
- DLOG(ERROR) << "Could not share GL contexts.";
- DestroyPlatformSpecific();
- return false;
+ // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
+ // stencil.
+ GLint fb_type = 0;
+ glGetFramebufferAttachmentParameterivEXT(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
+ &fb_type);
+ switch (fb_type) {
+ case GL_RENDERBUFFER:
+ {
+ GLint renderbuffer_id = 0;
+ glGetFramebufferAttachmentParameterivEXT(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ &renderbuffer_id);
+ if (renderbuffer_id != 0) {
+ glGetRenderbufferParameterivEXT(
+ GL_RENDERBUFFER,
+ GL_RENDERBUFFER_WIDTH,
+ &width);
+ glGetRenderbufferParameterivEXT(
+ GL_RENDERBUFFER,
+ GL_RENDERBUFFER_HEIGHT,
+ &height);
+ }
+ break;
+ }
+ case GL_TEXTURE:
+ {
+ GLint texture_id = 0;
+ glGetFramebufferAttachmentParameterivEXT(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
+ &texture_id);
+ if (texture_id != 0) {
+ TextureManager::TextureInfo* texture_info =
+ GetTextureInfo(texture_id);
+ if (texture_info) {
+ GLint level = 0;
+ GLint face = 0;
+ glGetFramebufferAttachmentParameterivEXT(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
+ &level);
+ glGetFramebufferAttachmentParameterivEXT(
+ GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
+ &face);
+ texture_info->GetLevelSize(
+ face ? face : GL_TEXTURE_2D, level, &width, &height);
+ }
+ }
+ break;
+ }
+ default:
+ // unknown so assume width and height are zero.
+ break;
}
- }
-#elif defined(OS_LINUX)
- // TODO(apatrick): parent contexts not yet supported on this platform.
- DCHECK(!parent_);
-
- DCHECK(context());
-
- // Offscreen / onscreen handling done earlier on this platform (in
- // GPUProcessor::Initialize).
-
- if (!context()->Initialize())
- return false;
-#elif defined(OS_MACOSX)
- // TODO(apatrick): parent contexts not yet supported on this platform.
- DCHECK(!parent_);
-
- if (offscreen) {
- // 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.";
- DestroyPlatformSpecific();
- return false;
- }
- if (!pixel_format) {
- return false;
- }
- CGLError res = CGLCreateContext(pixel_format, 0, &gl_context_);
- CGLDestroyPixelFormat(pixel_format);
- if (res != kCGLNoError) {
- DLOG(ERROR) << "Error creating context.";
- DestroyPlatformSpecific();
- return false;
- }
- if (CGLCreatePBuffer(1, 1,
- GL_TEXTURE_2D, GL_RGBA,
- 0, &pbuffer_) != kCGLNoError) {
- DLOG(ERROR) << "Error creating pbuffer.";
- DestroyPlatformSpecific();
- return false;
- }
- if (CGLSetPBuffer(gl_context_, pbuffer_, 0, 0, 0) != kCGLNoError) {
- DLOG(ERROR) << "Error attaching pbuffer to context.";
- DestroyPlatformSpecific();
- return false;
- }
- return true;
+ return gfx::Size(width, height);
+ } else if (offscreen_target_color_texture_.get()) {
+ return offscreen_target_color_texture_->size();
} else {
- return surface_.Initialize();
- }
-#endif
-
- return true;
-}
-
-bool GLES2DecoderImpl::InitGlew() {
-#if !defined(UNIT_TEST) && !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
- DLOG(INFO) << "Initializing GL and GLEW for GLES2Decoder.";
-
- GLenum glew_error = glewInit();
- if (glew_error != GLEW_OK) {
- DLOG(ERROR) << "Unable to initialise GLEW : "
- << glewGetErrorString(glew_error);
- 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.";
- }
-
- 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;
- }
- // Check for necessary extensions
- 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;
-#endif
-
- return true;
-}
-
-void GLES2DecoderImpl::DestroyPlatformSpecific() {
#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
- if (gl_context_) {
- ::wglDeleteContext(gl_context_);
- }
-
- if (gl_device_context_) {
- if (hwnd())
- ::ReleaseDC(hwnd(), gl_device_context_);
- else
- ::wglReleasePbufferDCARB(pbuffer_, gl_device_context_);
-
- gl_device_context_ = NULL;
- }
-
- if (pbuffer_) {
- ::wglDestroyPbufferARB(pbuffer_);
- pbuffer_ = NULL;
- }
-#elif defined(OS_MAC)
- if (gl_context_) {
- CGLDestroyContext(gl_context_);
- gl_context_ = NULL;
- }
-
- if (pbuffer_) {
- CGLDestroyPBuffer(pbuffer_);
- pbuffer_ = NULL;
- }
+ return gfx::Size(INT_MAX, INT_MAX);
+#else
+ return context_->GetSize();
#endif
+ }
}
bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
- if (current_size_ != pending_size_)
+ if (offscreen_target_color_texture_->size() == pending_offscreen_size_)
return true;
// Reallocate the offscreen target buffers.
- if (!offscreen_target_color_texture_->AllocateStorage(pending_size_)) {
+ if (!offscreen_target_color_texture_->AllocateStorage(
+ pending_offscreen_size_)) {
return false;
}
if (!offscreen_target_depth_stencil_render_buffer_->AllocateStorage(
- pending_size_, GL_DEPTH24_STENCIL8)) {
+ pending_offscreen_size_, GL_DEPTH24_STENCIL8)) {
return false;
}
@@ -1875,20 +1474,21 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
return false;
}
- // Create the saved offscreen color texture.
- offscreen_saved_color_texture_->AllocateStorage(pending_size_);
-
- // Clear the offscreen saved color texture by copying the cleared target
- // frame buffer into it.
- {
- ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
- offscreen_saved_color_texture_->Copy(pending_size_);
- }
-
// Update the info about the offscreen saved color texture in the parent.
// The reference to the parent is a weak pointer and will become null if the
// parent is later destroyed.
if (parent_) {
+ // Create the saved offscreen color texture (only accessible to parent).
+ offscreen_saved_color_texture_->AllocateStorage(pending_offscreen_size_);
+
+ // Clear the offscreen saved color texture by copying the cleared target
+ // frame buffer into it.
+ {
+ ScopedFrameBufferBinder binder(this,
+ offscreen_target_frame_buffer_->id());
+ offscreen_saved_color_texture_->Copy(pending_offscreen_size_);
+ }
+
GLuint service_id = offscreen_saved_color_texture_->id();
TextureManager::TextureInfo* info =
@@ -1898,49 +1498,17 @@ bool GLES2DecoderImpl::UpdateOffscreenFrameBufferSize() {
info->SetLevelInfo(GL_TEXTURE_2D,
0, // level
GL_RGBA,
- pending_size_.width(), pending_size_.height(),
+ pending_offscreen_size_.width(),
+ pending_offscreen_size_.height(),
1, // depth
0, // border
GL_RGBA,
GL_UNSIGNED_BYTE);
}
- current_size_ = pending_size_;
return true;
}
-#if defined(OS_MACOSX)
-
-uint64 GLES2DecoderImpl::SetWindowSizeForIOSurface(int32 width, int32 height) {
-#if defined(UNIT_TEST)
- return 0;
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
- return 0;
-#else
- return surface_.SetSurfaceSize(width, height);
-#endif // !defined(UNIT_TEST)
-}
-
-TransportDIB::Handle GLES2DecoderImpl::SetWindowSizeForTransportDIB(
- int32 width, int32 height) {
-#if defined(UNIT_TEST)
- return TransportDIB::DefaultHandleValue();
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
- return TransportDIB::DefaultHandleValue();
-#else
- return surface_.SetTransportDIBSize(width, height);
-#endif // !defined(UNIT_TEST)
-}
-
-void GLES2DecoderImpl::SetTransportDIBAllocAndFree(
- Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator) {
-#if !defined(UNIT_TEST)
- surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
-#endif
-}
-#endif // defined(OS_MACOSX)
-
void GLES2DecoderImpl::SetSwapBuffersCallback(Callback0::Type* callback) {
swap_buffers_callback_.reset(callback);
}
@@ -1962,38 +1530,37 @@ void GLES2DecoderImpl::Destroy() {
}
}
- if (offscreen_target_frame_buffer_.get())
+ if (offscreen_target_frame_buffer_.get()) {
offscreen_target_frame_buffer_->Destroy();
+ offscreen_target_frame_buffer_.reset();
+ }
- if (offscreen_target_color_texture_.get())
+ if (offscreen_target_color_texture_.get()) {
offscreen_target_color_texture_->Destroy();
+ offscreen_target_color_texture_.reset();
+ }
- if (offscreen_target_depth_stencil_render_buffer_.get())
+ if (offscreen_target_depth_stencil_render_buffer_.get()) {
offscreen_target_depth_stencil_render_buffer_->Destroy();
+ offscreen_target_depth_stencil_render_buffer_.reset();
+ }
- if (temporary_frame_buffer_.get())
+ if (temporary_frame_buffer_.get()) {
temporary_frame_buffer_->Destroy();
+ temporary_frame_buffer_.reset();
+ }
- if (offscreen_saved_color_texture_.get())
+ if (offscreen_saved_color_texture_.get()) {
offscreen_saved_color_texture_->Destroy();
-
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_LINUX)
- DCHECK(context());
- context()->Destroy();
-#elif defined(OS_MACOSX)
- surface_.Destroy();
-#endif
-
- DestroyPlatformSpecific();
+ offscreen_saved_color_texture_.reset();
+ }
}
void GLES2DecoderImpl::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
// We can't resize the render buffers immediately because there might be a
// partial frame rendered into them and we don't want the tail end of that
// rendered into the reallocated storage. Defer until the next SwapBuffers.
- pending_size_ = size;
+ pending_offscreen_size_ = size;
}
const char* GLES2DecoderImpl::GetCommandName(unsigned int command_id) const {
@@ -2831,77 +2398,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
CopyRealGLErrorsToWrapper();
// Get the size of the current fbo or backbuffer.
- GLsizei max_width = 0;
- GLsizei max_height = 0;
- if (bound_framebuffer_ != 0) {
- // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and
- // stencil.
- GLint fb_type = 0;
- glGetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,
- &fb_type);
- switch (fb_type) {
- case GL_RENDERBUFFER:
- {
- GLint renderbuffer_id = 0;
- glGetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- &renderbuffer_id);
- if (renderbuffer_id != 0) {
- glGetRenderbufferParameterivEXT(
- GL_RENDERBUFFER,
- GL_RENDERBUFFER_WIDTH,
- &max_width);
- glGetRenderbufferParameterivEXT(
- GL_RENDERBUFFER,
- GL_RENDERBUFFER_HEIGHT,
- &max_height);
- }
- break;
- }
- case GL_TEXTURE:
- {
- GLint texture_id = 0;
- glGetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME,
- &texture_id);
- if (texture_id != 0) {
- TextureManager::TextureInfo* texture_info =
- GetTextureInfo(texture_id);
- if (texture_info) {
- GLint level = 0;
- GLint face = 0;
- glGetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,
- &level);
- glGetFramebufferAttachmentParameterivEXT(
- GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,
- &face);
- texture_info->GetLevelSize(
- face ? face : GL_TEXTURE_2D, level, &max_width, &max_height);
- }
- }
- break;
- }
- default:
- // unknown so assume max_width = 0.
- break;
- }
- } else {
- // TODO(gman): Get these values from the proper place.
- max_width = 300;
- max_height = 300;
- }
+ gfx::Size max_size = GetBoundFrameBufferSize();
GLint max_x;
GLint max_y;
@@ -2910,7 +2407,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
return error::kNoError;
}
- if (x < 0 || y < 0 || max_x > max_width || max_y > max_height) {
+ if (x < 0 || y < 0 || max_x > max_size.width() || max_y > max_size.height()) {
// The user requested an out of range area. Get the results 1 line
// at a time.
uint32 temp_size;
@@ -2942,7 +2439,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
// Copy each row into the larger dest rect.
int8* dst = static_cast<int8*>(pixels);
GLint read_x = std::max(0, x);
- GLint read_end_x = std::max(0, std::min(max_width, max_x));
+ GLint read_end_x = std::max(0, std::min(max_size.width(), max_x));
GLint read_width = read_end_x - read_x;
for (GLint yy = 0; yy < height; ++yy) {
GLint ry = y + yy;
@@ -2951,7 +2448,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels(
memset(dst, 0, unpadded_row_size);
// If the row is in range, copy it.
- if (ry >= 0 && ry < max_height && read_width > 0) {
+ if (ry >= 0 && ry < max_size.height() && read_width > 0) {
glReadPixels(
read_x, ry, read_width, 1, format, type, dst + dest_row_offset);
}
@@ -3679,19 +3176,11 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers(
return error::kLostContext;
ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
- offscreen_saved_color_texture_->Copy(current_size_);
+ offscreen_saved_color_texture_->Copy(
+ offscreen_saved_color_texture_->size());
} else {
-#if defined(UNIT_TEST)
-#elif defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
-#elif defined(OS_WIN)
- ::SwapBuffers(gl_device_context_);
-#elif defined(OS_LINUX)
- DCHECK(context());
- context()->SwapBuffers();
-#elif defined(OS_MACOSX)
- // TODO(kbr): Need to property hook up and track the OpenGL state and hook
- // up the notion of the currently bound FBO.
- surface_.SwapBuffers();
+#if !defined(UNIT_TEST)
+ context_->SwapBuffers();
#endif
}
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 05951a2..08e664b 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -7,23 +7,16 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_H_
#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_H_
-#include <build/build_config.h>
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
#include "base/callback.h"
-#if defined(OS_MACOSX)
-#include "app/surface/transport_dib.h"
-#endif
-
+#include "build/build_config.h"
#include "gfx/size.h"
#include "gpu/command_buffer/service/common_decoder.h"
namespace gpu {
-// Forward-declared instead of including x_utils.h, because including glx.h
+// Forward-declared instead of including gl_context.h, because including glx.h
// causes havok.
-class GLXContextWrapper;
+class GLContext;
namespace gles2 {
@@ -49,37 +42,21 @@ class GLES2Decoder : public CommonDecoder {
debug_ = debug;
}
-#if defined(OS_LINUX)
- void set_context_wrapper(GLXContextWrapper *context) {
- context_ = context;
- }
- GLXContextWrapper* context() const {
- return context_;
- }
-#elif defined(OS_WIN)
- void set_hwnd(HWND hwnd) {
- hwnd_ = hwnd;
- }
-
- HWND hwnd() const {
- return hwnd_;
- }
-#elif defined(OS_MACOSX)
- virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height) = 0;
- virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
- int32 height) = 0;
- virtual void SetTransportDIBAllocAndFree(
- Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator) = 0;
-#endif
-
// Initializes the graphics context. Can create an offscreen
// decoder with a frame buffer that can be referenced from the parent.
+ // Parameters:
+ // context: the GL context to render to.
+ // size: the size if the GL context is offscreen.
+ // parent: the GLES2 decoder that can access this decoder's front buffer
+ // through a texture ID in its namespace.
+ // parent_client_texture_id: the texture ID of the front buffer in the
+ // parent's namespace.
// Returns:
// true if successful.
- virtual bool Initialize(GLES2Decoder* parent,
+ virtual bool Initialize(GLContext* context,
const gfx::Size& size,
- uint32 parent_texture_id) = 0;
+ GLES2Decoder* parent,
+ uint32 parent_client_texture_id) = 0;
// Destroys the graphics context.
virtual void Destroy() = 0;
@@ -96,6 +73,9 @@ class GLES2Decoder : public CommonDecoder {
// Gets the GLES2 Util which holds info.
virtual GLES2Util* GetGLES2Util() = 0;
+ // Gets the associated GLContext.
+ virtual GLContext* GetGLContext() = 0;
+
// Sets a callback which is called when a SwapBuffers command is processed.
virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0;
@@ -107,13 +87,6 @@ class GLES2Decoder : public CommonDecoder {
private:
bool debug_;
-#if defined(OS_LINUX)
- GLXContextWrapper *context_;
-#elif defined(OS_WIN)
- // Handle to the GL device.
- HWND hwnd_;
-#endif
-
DISALLOW_COPY_AND_ASSIGN(GLES2Decoder);
};
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index 4ba9217..e29a1fe8 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -13,6 +13,8 @@
#include "testing/gmock/include/gmock/gmock.h"
namespace gpu {
+class GLContext;
+
namespace gles2 {
class ContextGroup;
@@ -26,22 +28,16 @@ class MockGLES2Decoder : public GLES2Decoder {
.WillByDefault(testing::Return(true));
}
-#if defined(OS_MACOSX)
- MOCK_METHOD2(SetWindowSizeForIOSurface, uint64(int32 width, int32 height));
- MOCK_METHOD2(SetWindowSizeForTransportDIB,
- TransportDIB::Handle(int32 width, int32 height));
- MOCK_METHOD2(SetTransportDIBAllocAndFree,
- void(Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator));
-#endif
- MOCK_METHOD3(Initialize, bool(GLES2Decoder* parent,
+ MOCK_METHOD4(Initialize, bool(GLContext* context,
const gfx::Size& size,
+ GLES2Decoder* parent,
uint32 parent_texture_id));
MOCK_METHOD0(Destroy, void());
MOCK_METHOD1(ResizeOffscreenFrameBuffer, void(const gfx::Size& size));
MOCK_METHOD0(MakeCurrent, bool());
MOCK_METHOD1(GetServiceIdForTesting, uint32(uint32 client_id));
MOCK_METHOD0(GetGLES2Util, GLES2Util*());
+ 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 63a4bd5..35b5ec6 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -95,7 +95,7 @@ void GLES2DecoderTestBase::SetUp() {
shared_memory_id_ = kSharedMemoryId;
decoder_.reset(GLES2Decoder::Create(&group_));
- decoder_->Initialize(NULL, gfx::Size(), 0);
+ decoder_->Initialize(NULL, gfx::Size(), NULL, 0);
decoder_->set_engine(engine_.get());
EXPECT_CALL(*gl_, GenBuffersARB(_, _))
diff --git a/gpu/command_buffer/service/gpu_processor.cc b/gpu/command_buffer/service/gpu_processor.cc
index d08069c..4514211 100644
--- a/gpu/command_buffer/service/gpu_processor.cc
+++ b/gpu/command_buffer/service/gpu_processor.cc
@@ -5,6 +5,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/message_loop.h"
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
@@ -36,6 +37,52 @@ GPUProcessor::~GPUProcessor() {
Destroy();
}
+bool GPUProcessor::InitializeCommon(const gfx::Size& size,
+ gles2::GLES2Decoder* parent_decoder,
+ uint32 parent_texture_id) {
+ // Context should have been created by platform specific Initialize().
+ DCHECK(context_.get());
+
+ // Map the ring buffer and create the parser.
+ Buffer ring_buffer = command_buffer_->GetRingBuffer();
+ if (ring_buffer.ptr) {
+ parser_.reset(new CommandParser(ring_buffer.ptr,
+ ring_buffer.size,
+ 0,
+ ring_buffer.size,
+ 0,
+ decoder_.get()));
+ } else {
+ parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
+ decoder_.get()));
+ }
+
+ // Initialize the decoder with either the view or pbuffer GLContext.
+ if (!decoder_->Initialize(context_.get(),
+ size,
+ parent_decoder,
+ parent_texture_id)) {
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void GPUProcessor::Destroy() {
+ if (decoder_.get()) {
+ decoder_->Destroy();
+ decoder_.reset();
+ }
+
+ if (context_.get()) {
+ context_->Destroy();
+ context_.reset();
+ }
+
+ parser_.reset();
+}
+
void GPUProcessor::ProcessCommands() {
CommandBuffer::State state = command_buffer_->GetState();
if (state.error != error::kNoError)
@@ -92,23 +139,6 @@ void GPUProcessor::ResizeOffscreenFrameBuffer(const gfx::Size& size) {
decoder_->ResizeOffscreenFrameBuffer(size);
}
-#if defined(OS_MACOSX)
-uint64 GPUProcessor::SetWindowSizeForIOSurface(int32 width, int32 height) {
- return decoder_->SetWindowSizeForIOSurface(width, height);
-}
-
-TransportDIB::Handle GPUProcessor::SetWindowSizeForTransportDIB(int32 width,
- int32 height) {
- return decoder_->SetWindowSizeForTransportDIB(width, height);
-}
-
-void GPUProcessor::SetTransportDIBAllocAndFree(
- Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
- Callback1<TransportDIB::Id>::Type* deallocator) {
- decoder_->SetTransportDIBAllocAndFree(allocator, deallocator);
-}
-#endif
-
void GPUProcessor::SetSwapBuffersCallback(
Callback0::Type* callback) {
decoder_->SetSwapBuffersCallback(callback);
diff --git a/gpu/command_buffer/service/gpu_processor.h b/gpu/command_buffer/service/gpu_processor.h
index d61bd60..c4c0ea5 100644
--- a/gpu/command_buffer/service/gpu_processor.h
+++ b/gpu/command_buffer/service/gpu_processor.h
@@ -5,6 +5,7 @@
#ifndef GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
#define GPU_COMMAND_BUFFER_SERVICE_GPU_PROCESSOR_H_
+#include "app/surface/transport_dib.h"
#include "base/callback.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
@@ -18,8 +19,14 @@
#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#if defined(OS_MACOSX) && !defined(UNIT_TEST)
+#include "app/surface/accelerated_surface_mac.h"
+#endif
+
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 {
@@ -32,14 +39,18 @@ class GPUProcessor : public CommandBufferEngine {
CommandParser* parser,
int commands_per_update);
- virtual bool Initialize(gfx::PluginWindowHandle hwnd,
- GPUProcessor* parent,
- const gfx::Size& size,
- uint32 parent_texture_id);
-
virtual ~GPUProcessor();
- virtual void Destroy();
+ bool Initialize(gfx::PluginWindowHandle hwnd,
+ const gfx::Size& size,
+ GPUProcessor* parent,
+ uint32 parent_texture_id);
+
+ bool InitializeCommon(const gfx::Size& size,
+ gles2::GLES2Decoder* parent_decoder,
+ uint32 parent_texture_id);
+
+ void Destroy();
virtual void ProcessCommands();
@@ -59,9 +70,9 @@ class GPUProcessor : public CommandBufferEngine {
// There are two versions of this method: one for use with the IOSurface
// available in Mac OS X 10.6; and, one for use with the
// TransportDIB-based version used on Mac OS X 10.5.
- virtual uint64 SetWindowSizeForIOSurface(int32 width, int32 height);
- virtual TransportDIB::Handle SetWindowSizeForTransportDIB(int32 width,
- int32 height);
+ virtual uint64 SetWindowSizeForIOSurface(const gfx::Size& size);
+ virtual TransportDIB::Handle SetWindowSizeForTransportDIB(
+ const gfx::Size& size);
virtual void SetTransportDIBAllocAndFree(
Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
Callback1<TransportDIB::Id>::Type* deallocator);
@@ -83,6 +94,11 @@ class GPUProcessor : public CommandBufferEngine {
gles2::ContextGroup group_;
scoped_ptr<gles2::GLES2Decoder> decoder_;
scoped_ptr<CommandParser> parser_;
+ scoped_ptr<GLContext> context_;
+
+#if defined(OS_MACOSX) && !defined(UNIT_TEST)
+ AcceleratedSurface surface_;
+#endif
ScopedRunnableMethodFactory<GPUProcessor> method_factory_;
};
diff --git a/gpu/command_buffer/service/gpu_processor_linux.cc b/gpu/command_buffer/service/gpu_processor_linux.cc
index b477021..10f1a87 100644
--- a/gpu/command_buffer/service/gpu_processor_linux.cc
+++ b/gpu/command_buffer/service/gpu_processor_linux.cc
@@ -2,71 +2,59 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#if !defined(UNIT_TEST)
#include <gdk/gdkx.h>
+#else
+#define GDK_DISPLAY() NULL
+#endif
+
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
-#include "gpu/command_buffer/service/x_utils.h"
using ::base::SharedMemory;
namespace gpu {
-bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle,
- GPUProcessor* parent,
+bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
const gfx::Size& size,
+ GPUProcessor* parent,
uint32 parent_texture_id) {
// Cannot reinitialize.
- if (decoder_->context() != NULL)
+ if (context_.get())
return false;
- // Map the ring buffer and create the parser.
- Buffer ring_buffer = command_buffer_->GetRingBuffer();
- if (ring_buffer.ptr) {
- parser_.reset(new CommandParser(ring_buffer.ptr,
- ring_buffer.size,
- 0,
- ring_buffer.size,
- 0,
- decoder_.get()));
- } else {
- parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
- decoder_.get()));
+ // Get the parent decoder and the GLContext to share IDs with, if any.
+ gles2::GLES2Decoder* parent_decoder = NULL;
+ GLContext* parent_context = NULL;
+ if (parent) {
+ parent_decoder = parent->decoder_.get();
+ DCHECK(parent_decoder);
+
+ parent_context = parent_decoder->GetGLContext();
+ DCHECK(parent_context);
}
- // Initialize GAPI immediately.
- GLXContextWrapper* wrapper = NULL;
- if (size.width() > 0 && size.height() > 0) {
- // Offscreen code path.
- DCHECK(!handle);
- wrapper = new GLXPbufferWrapper(GDK_DISPLAY());
+ // Create either a view or pbuffer based GLContext.
+ if (window) {
+ scoped_ptr<ViewGLContext> context(new ViewGLContext(GDK_DISPLAY(), window));
+ // TODO(apatrick): support multisampling.
+ if (!context->Initialize(false)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
} else {
- DCHECK(handle);
- // Onscreen code path.
- wrapper = new XWindowWrapper(GDK_DISPLAY(), handle);
- }
- decoder_->set_context_wrapper(wrapper);
- gles2::GLES2Decoder* parent_decoder = parent ? parent->decoder_.get() : NULL;
- if (!decoder_->Initialize(parent_decoder,
- size,
- parent_texture_id)) {
- Destroy();
- return false;
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext(GDK_DISPLAY()));
+ if (!context->Initialize(parent_context)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
}
- return true;
-}
-
-void GPUProcessor::Destroy() {
- // Destroy decoder if initialized.
- // TODO(gman): simplify cleanup logic. http://crbug.com/39895
- if (decoder_.get()) {
- GLXContextWrapper *context = decoder_->context();
- decoder_->Destroy();
- decoder_->set_context_wrapper(NULL);
- delete context;
- decoder_.reset();
- }
+ return InitializeCommon(size, parent_decoder, parent_texture_id);
- parser_.reset();
+ return true;
}
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor_mac.cc b/gpu/command_buffer/service/gpu_processor_mac.cc
index ef13fc6..55b6816 100644
--- a/gpu/command_buffer/service/gpu_processor_mac.cc
+++ b/gpu/command_buffer/service/gpu_processor_mac.cc
@@ -2,55 +2,84 @@
// 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/gpu_processor.h"
using ::base::SharedMemory;
namespace gpu {
-bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle,
- GPUProcessor* parent,
+bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
const gfx::Size& size,
+ GPUProcessor* parent,
uint32 parent_texture_id) {
- // At this level we do not need the PluginWindowHandle. It is only
- // needed at the CommandBufferStub level to identify which GPU
- // plugin instance is creating a new backing store in response to a
- // resize event.
-
- // Map the ring buffer and create the parser.
- Buffer ring_buffer = command_buffer_->GetRingBuffer();
- if (ring_buffer.ptr) {
- parser_.reset(new CommandParser(ring_buffer.ptr,
- ring_buffer.size,
- 0,
- ring_buffer.size,
- 0,
- decoder_.get()));
- } else {
- parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
- decoder_.get()));
+ // Cannot reinitialize.
+ if (context_.get())
+ return false;
+
+ // Get the parent decoder and the GLContext to share IDs with, if any.
+ gles2::GLES2Decoder* parent_decoder = NULL;
+ GLContext* parent_context = NULL;
+ if (parent) {
+ parent_decoder = parent->decoder_.get();
+ DCHECK(parent_decoder);
+
+ parent_context = parent_decoder->GetGLContext();
+ DCHECK(parent_context);
}
- // Initialize GAPI.
- gles2::GLES2Decoder* parent_decoder = parent ? parent->decoder_.get() : NULL;
- if (!decoder_->Initialize(parent_decoder,
- size,
- parent_texture_id)) {
- Destroy();
- return false;
+ // Create either a view or pbuffer based GLContext.
+ if (window) {
+#if !defined(UNIT_TEST)
+ AcceleratedSurface* surface_ptr = &surface_;
+#else
+ AcceleratedSurface* surface_ptr = NULL;
+#endif
+ scoped_ptr<ViewGLContext> context(new ViewGLContext(surface_ptr));
+ // TODO(apatrick): support multisampling.
+ if (!context->Initialize(false)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
+ } else {
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ if (!context->Initialize(parent_context)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
}
+ return InitializeCommon(size, parent_decoder, parent_texture_id);
+
return true;
}
-void GPUProcessor::Destroy() {
- // Destroy decoder if initialized.
- if (decoder_.get()) {
- decoder_->Destroy();
- decoder_.reset();
- }
+uint64 GPUProcessor::SetWindowSizeForIOSurface(const gfx::Size& size) {
+#if !defined(UNIT_TEST)
+ return surface_.SetSurfaceSize(size);
+#else
+ return 0;
+#endif
+}
- parser_.reset();
+TransportDIB::Handle GPUProcessor::SetWindowSizeForTransportDIB(
+ const gfx::Size& size) {
+#if !defined(UNIT_TEST)
+ return surface_.SetTransportDIBSize(size);
+#else
+ return TransportDIB::DefaultHandleValue();
+#endif
}
+
+void GPUProcessor::SetTransportDIBAllocAndFree(
+ Callback2<size_t, TransportDIB::Handle*>::Type* allocator,
+ Callback1<TransportDIB::Id>::Type* deallocator) {
+#if !defined(UNIT_TEST)
+ surface_.SetTransportDIBAllocAndFree(allocator, deallocator);
+#endif
+}
+
} // namespace gpu
diff --git a/gpu/command_buffer/service/gpu_processor_mock.h b/gpu/command_buffer/service/gpu_processor_mock.h
index ca257e8..8eab35d 100644
--- a/gpu/command_buffer/service/gpu_processor_mock.h
+++ b/gpu/command_buffer/service/gpu_processor_mock.h
@@ -16,8 +16,6 @@ class MockGPUProcessor : public GPUProcessor {
: GPUProcessor(command_buffer) {
}
- MOCK_METHOD1(Initialize, bool(gfx::PluginWindowHandle handle));
- MOCK_METHOD0(Destroy, void());
MOCK_METHOD0(ProcessCommands, void());
MOCK_METHOD1(GetSharedMemoryBuffer, Buffer(int32 shm_id));
MOCK_METHOD1(set_token, void(int32 token));
diff --git a/gpu/command_buffer/service/gpu_processor_win.cc b/gpu/command_buffer/service/gpu_processor_win.cc
index 537872c..143d5a6 100644
--- a/gpu/command_buffer/service/gpu_processor_win.cc
+++ b/gpu/command_buffer/service/gpu_processor_win.cc
@@ -4,55 +4,52 @@
#include <windows.h>
+#include "gpu/command_buffer/service/gl_context.h"
#include "gpu/command_buffer/service/gpu_processor.h"
using ::base::SharedMemory;
namespace gpu {
-bool GPUProcessor::Initialize(gfx::PluginWindowHandle handle,
- GPUProcessor* parent,
+bool GPUProcessor::Initialize(gfx::PluginWindowHandle window,
const gfx::Size& size,
+ GPUProcessor* parent,
uint32 parent_texture_id) {
// Cannot reinitialize.
- if (parser_.get())
+ if (context_.get())
return false;
- // Map the ring buffer and create the parser.
- Buffer ring_buffer = command_buffer_->GetRingBuffer();
- if (ring_buffer.ptr) {
- parser_.reset(new CommandParser(ring_buffer.ptr,
- ring_buffer.size,
- 0,
- ring_buffer.size,
- 0,
- decoder_.get()));
- } else {
- parser_.reset(new CommandParser(NULL, 0, 0, 0, 0,
- decoder_.get()));
- }
+ // Get the parent decoder and the GLContext to share IDs with, if any.
+ gles2::GLES2Decoder* parent_decoder = NULL;
+ GLContext* parent_context = NULL;
+ if (parent) {
+ parent_decoder = parent->decoder_.get();
+ DCHECK(parent_decoder);
- // Initialize GAPI immediately if the window handle is valid.
- decoder_->set_hwnd(handle);
- gles2::GLES2Decoder* parent_decoder = parent ? parent->decoder_.get() : NULL;
- if (!decoder_->Initialize(parent_decoder,
- size,
- parent_texture_id)) {
- Destroy();
- return false;
+ parent_context = parent_decoder->GetGLContext();
+ DCHECK(parent_context);
}
- return true;
-}
-
-void GPUProcessor::Destroy() {
- // Destroy decoder if initialized.
- if (decoder_.get()) {
- decoder_->Destroy();
- decoder_->set_hwnd(NULL);
- decoder_.reset();
+ // Create either a view or pbuffer based GLContext.
+ if (window) {
+ scoped_ptr<ViewGLContext> context(new ViewGLContext(window));
+ // TODO(apatrick): support multisampling.
+ if (!context->Initialize(false)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
+ } else {
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ if (!context->Initialize(parent_context)) {
+ Destroy();
+ return false;
+ }
+ context_.reset(context.release());
}
- parser_.reset();
+ return InitializeCommon(size, parent_decoder, parent_texture_id);
+
+ return true;
}
} // namespace gpu
diff --git a/gpu/command_buffer/service/precompile.cc b/gpu/command_buffer/service/precompile.cc
deleted file mode 100644
index 07870fa..0000000
--- a/gpu/command_buffer/service/precompile.cc
+++ /dev/null
@@ -1,5 +0,0 @@
-// 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/precompile.h"
diff --git a/gpu/command_buffer/service/precompile.h b/gpu/command_buffer/service/precompile.h
deleted file mode 100644
index 19dc80c..0000000
--- a/gpu/command_buffer/service/precompile.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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.
-
-// This file contains includes for common headers used by command buffer server
-// files. It is used for pre-compiled header support.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_PRECOMPILE_H_
-#define GPU_COMMAND_BUFFER_SERVICE_PRECOMPILE_H_
-
-#include <build/build_config.h>
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include <assert.h>
-#include <algorithm>
-#include <map>
-#include <vector>
-
-#endif // O3D_CORE_PRECOMPILE_H_
diff --git a/gpu/command_buffer/service/x_utils.h b/gpu/command_buffer/service/x_utils.h
deleted file mode 100644
index ca88f73..0000000
--- a/gpu/command_buffer/service/x_utils.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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.
-
-// This file declares the XWindowWrapper class.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
-#define GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
-
-#include "base/basictypes.h"
-#include "gpu/command_buffer/common/logging.h"
-#include "gpu/command_buffer/service/gl_utils.h"
-
-namespace gpu {
-
-// Abstracts between on-screen and off-screen GLX contexts.
-class GLXContextWrapper {
- public:
- explicit GLXContextWrapper(Display* display)
- : display_(display),
- context_(NULL) {
- DCHECK(display_);
- }
-
- virtual ~GLXContextWrapper();
-
- // Initializes the GL context. Subclasses should perform their
- // initialization work and then call the superclass implementation.
- virtual bool Initialize();
-
- // Destroys the GL context. Subclasses may call this before or after
- // doing any necessary cleanup work.
- virtual void Destroy();
-
- // Makes the GL context current on the current thread.
- virtual bool MakeCurrent() = 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;
-
- // Fetches the GLX context for sharing of server-side objects.
- GLXContext GetContext() {
- return context_;
- }
-
- protected:
- Display* GetDisplay() {
- return display_;
- }
-
- void SetContext(GLXContext context) {
- context_ = context;
- }
-
- private:
- Display* display_;
- GLXContext context_;
-
- DISALLOW_COPY_AND_ASSIGN(GLXContextWrapper);
-};
-
-// This class is a wrapper around an X Window and associated GL context. It is
-// useful to isolate intrusive X headers, since it can be forward declared
-// (Window and GLXContext can't).
-class XWindowWrapper : public GLXContextWrapper {
- public:
- XWindowWrapper(Display *display, Window window)
- : GLXContextWrapper(display),
- window_(window) {
- DCHECK(window_);
- }
-
- virtual bool Initialize();
- virtual bool MakeCurrent();
- virtual bool IsOffscreen();
- virtual void SwapBuffers();
-
- private:
- Window window_;
- DISALLOW_COPY_AND_ASSIGN(XWindowWrapper);
-};
-
-// This class is a wrapper around a GLX pbuffer and associated GL context. It
-// serves the same purpose as the XWindowWrapper for initializing off-screen
-// rendering.
-class GLXPbufferWrapper : public GLXContextWrapper {
- public:
- explicit GLXPbufferWrapper(Display* display)
- : GLXContextWrapper(display) {
- }
-
- virtual bool Initialize();
- virtual void Destroy();
- virtual bool MakeCurrent();
- virtual bool IsOffscreen();
- virtual void SwapBuffers();
-
- private:
- GLXPbuffer pbuffer_;
- DISALLOW_COPY_AND_ASSIGN(GLXPbufferWrapper);
-};
-
-} // namespace gpu
-
-#endif // GPU_COMMAND_BUFFER_SERVICE_X_UTILS_H_
diff --git a/gpu/demos/framework/window.cc b/gpu/demos/framework/window.cc
index 0a9db79..5e3a309 100644
--- a/gpu/demos/framework/window.cc
+++ b/gpu/demos/framework/window.cc
@@ -61,7 +61,7 @@ bool Window::CreateRenderContext(gfx::PluginWindowHandle hwnd) {
GPUProcessor* gpu_processor(
new GPUProcessor(command_buffer.get()));
- if (!gpu_processor->Initialize(hwnd, NULL, gfx::Size(), 0)) {
+ if (!gpu_processor->Initialize(hwnd, gfx::Size(), NULL, 0)) {
return false;
}
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index fac0dee..da7172b 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -22,7 +22,12 @@
'command_buffer/service/gles2_cmd_validation.cc',
'command_buffer/service/gles2_cmd_validation_autogen.h',
'command_buffer/service/gles2_cmd_validation_implementation_autogen.h',
+ 'command_buffer/service/gl_context.cc',
+ 'command_buffer/service/gl_context.h',
'command_buffer/service/gl_utils.h',
+ 'command_buffer/service/gpu_processor.h',
+ 'command_buffer/service/gpu_processor.cc',
+ 'command_buffer/service/gpu_processor_mock.h',
'command_buffer/service/id_manager.h',
'command_buffer/service/id_manager.cc',
'command_buffer/service/program_manager.h',
@@ -34,6 +39,32 @@
'command_buffer/service/texture_manager.h',
'command_buffer/service/texture_manager.cc',
],
+ 'conditions': [
+ ['OS == "linux"',
+ {
+ 'gpu_service_source_files': [
+ 'command_buffer/service/gl_context_linux.cc',
+ 'command_buffer/service/gpu_processor_linux.cc',
+ ],
+ },
+ ],
+ ['OS == "win"',
+ {
+ 'gpu_service_source_files': [
+ 'command_buffer/service/gl_context_win.cc',
+ 'command_buffer/service/gpu_processor_win.cc',
+ ],
+ },
+ ],
+ ['OS == "mac"',
+ {
+ 'gpu_service_source_files': [
+ 'command_buffer/service/gl_context_mac.cc',
+ 'command_buffer/service/gpu_processor_mac.cc',
+ ],
+ },
+ ],
+ ],
},
'targets': [
{
@@ -233,40 +264,7 @@
'command_buffer/service/command_buffer_service.h',
'command_buffer/service/cmd_parser.cc',
'command_buffer/service/cmd_parser.h',
- 'command_buffer/service/gpu_processor.h',
- 'command_buffer/service/gpu_processor.cc',
- 'command_buffer/service/gpu_processor_mock.h',
'command_buffer/service/mocks.h',
- 'command_buffer/service/precompile.cc',
- 'command_buffer/service/precompile.h',
- ],
- 'conditions': [
- ['OS == "linux"',
- {
- 'sources': [
- 'command_buffer/service/gpu_processor_linux.cc',
- 'command_buffer/service/x_utils.cc',
- 'command_buffer/service/x_utils.h',
- ],
- 'dependencies': [
- '../build/linux/system.gyp:gtk',
- ]
- },
- ],
- ['OS == "win"',
- {
- 'sources': [
- 'command_buffer/service/gpu_processor_win.cc',
- ],
- },
- ],
- ['OS == "mac"',
- {
- 'sources': [
- 'command_buffer/service/gpu_processor_mac.cc',
- ],
- },
- ],
],
},
{
@@ -287,6 +285,15 @@
'sources': [
'<@(gpu_service_source_files)',
],
+ 'conditions': [
+ ['OS == "linux"',
+ {
+ 'dependencies': [
+ '../build/linux/system.gyp:gtk',
+ ]
+ },
+ ],
+ ],
},
{
'target_name': 'gpu_plugin',