summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 21:35:12 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 21:35:12 +0000
commita3e1b635a1f31e1c736ebb5dad2e772b12ac7aac (patch)
tree87fad4399b3337096e825e88d213ad88e939955a /ui
parent95aa1a3d894423e0ac4f7075ef369ab103cfbf64 (diff)
downloadchromium_src-a3e1b635a1f31e1c736ebb5dad2e772b12ac7aac.zip
chromium_src-a3e1b635a1f31e1c736ebb5dad2e772b12ac7aac.tar.gz
chromium_src-a3e1b635a1f31e1c736ebb5dad2e772b12ac7aac.tar.bz2
Split WGL implementations of *GLContext in GLContextWGL and *GLSurfaceWGL.
Surfaces are independent of contexts in GL. To facilitate sharing of surfaces between processes, I have separated them from the notion of contexts because contexts cannot be shared between processes. I started with EGL in r81512. This is the same thing for WGL. GLContextEGL still has a pointer to a surface and still has some surface specific operations that just forward through to it. Once I have refactored all the GLContext implementations in this way, I will remove these pointers and the surface specific opertations. There will not be "view" and "offscreen" GL contexts. Rather there will be a single context type for each backend which can be made current with a surface that directs output either to a view or offscreen surface. Review URL: http://codereview.chromium.org/6864002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81807 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/gl/gl.gyp4
-rw-r--r--ui/gfx/gl/gl_context_egl.cc6
-rw-r--r--ui/gfx/gl/gl_context_wgl.cc122
-rw-r--r--ui/gfx/gl/gl_context_wgl.h46
-rw-r--r--ui/gfx/gl/gl_context_win.cc484
-rw-r--r--ui/gfx/gl/gl_surface.h8
-rw-r--r--ui/gfx/gl/gl_surface_wgl.cc297
-rw-r--r--ui/gfx/gl/gl_surface_wgl.h74
8 files changed, 567 insertions, 474 deletions
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp
index 50a9785..507d9b4 100644
--- a/ui/gfx/gl/gl.gyp
+++ b/ui/gfx/gl/gl.gyp
@@ -144,6 +144,10 @@
}],
['OS=="win"', {
'sources': [
+ 'gl_context_wgl.cc',
+ 'gl_context_wgl.h',
+ 'gl_surface_wgl.cc',
+ 'gl_surface_wgl.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_wgl.cc',
'<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h',
],
diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc
index dd2ed27..8f64041 100644
--- a/ui/gfx/gl/gl_context_egl.cc
+++ b/ui/gfx/gl/gl_context_egl.cc
@@ -40,6 +40,7 @@ GLContextEGL::GLContextEGL(GLSurfaceEGL* surface)
}
GLContextEGL::~GLContextEGL() {
+ Destroy();
}
bool GLContextEGL::Initialize(GLContext* shared_context) {
@@ -86,6 +87,11 @@ void GLContextEGL::Destroy() {
context_ = NULL;
}
+
+ if (surface_.get()) {
+ surface_->Destroy();
+ surface_.reset();
+ }
}
bool GLContextEGL::MakeCurrent() {
diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc
new file mode 100644
index 0000000..361f8e9
--- /dev/null
+++ b/ui/gfx/gl/gl_context_wgl.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file implements the GLContextWGL and PbufferGLContext classes.
+
+#include "ui/gfx/gl/gl_context_wgl.h"
+
+#include "base/logging.h"
+#include "ui/gfx/gl/gl_bindings.h"
+#include "ui/gfx/gl/gl_implementation.h"
+
+namespace gfx {
+
+GLContextWGL::GLContextWGL(GLSurfaceWGL* surface)
+ : surface_(surface),
+ context_(NULL) {
+ DCHECK(surface);
+}
+
+GLContextWGL::~GLContextWGL() {
+ Destroy();
+}
+
+std::string GLContextWGL::GetExtensions() {
+ if (wglGetExtensionsStringARB) {
+ // TODO(apatrick): When contexts and surfaces are separated, we won't be
+ // able to use surface_ here. Either use a display device context or the
+ // surface that was passed to MakeCurrent.
+ const char* extensions = wglGetExtensionsStringARB(
+ static_cast<HDC>(surface_->GetHandle()));
+ if (extensions) {
+ return GLContext::GetExtensions() + " " + extensions;
+ }
+ }
+
+ return GLContext::GetExtensions();
+}
+
+bool GLContextWGL::Initialize(GLContext* shared_context) {
+ // TODO(apatrick): When contexts and surfaces are separated, we won't be
+ // able to use surface_ here. Either use a display device context or a
+ // surface that the context is compatible with not necessarily limited to
+ // rendering to.
+ context_ = wglCreateContext(static_cast<HDC>(surface_->GetHandle()));
+ if (!context_) {
+ LOG(ERROR) << "Failed to create GL context.";
+ Destroy();
+ return false;
+ }
+
+ if (shared_context) {
+ if (!wglShareLists(
+ static_cast<HGLRC>(shared_context->GetHandle()),
+ context_)) {
+ LOG(ERROR) << "Could not share GL contexts.";
+ Destroy();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void GLContextWGL::Destroy() {
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+
+ if (surface_.get()) {
+ surface_->Destroy();
+ surface_.reset();
+ }
+}
+
+bool GLContextWGL::MakeCurrent() {
+ if (IsCurrent()) {
+ return true;
+ }
+
+ if (!wglMakeCurrent(static_cast<HDC>(surface_->GetHandle()),
+ context_)) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ return true;
+}
+
+bool GLContextWGL::IsCurrent() {
+ return wglGetCurrentDC() == surface_->GetHandle() &&
+ wglGetCurrentContext() == context_;
+}
+
+bool GLContextWGL::IsOffscreen() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->IsOffscreen();
+}
+
+bool GLContextWGL::SwapBuffers() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->SwapBuffers();
+}
+
+gfx::Size GLContextWGL::GetSize() {
+ // TODO(apatrick): remove this from GLContext interface.
+ return surface_->GetSize();
+}
+
+void* GLContextWGL::GetHandle() {
+ return context_;
+}
+
+void GLContextWGL::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent());
+ if (HasExtension("WGL_EXT_swap_control") && wglSwapIntervalEXT) {
+ wglSwapIntervalEXT(interval);
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gfx/gl/gl_context_wgl.h b/ui/gfx/gl/gl_context_wgl.h
new file mode 100644
index 0000000..c5c5783
--- /dev/null
+++ b/ui/gfx/gl/gl_context_wgl.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_GL_GL_CONTEXT_WGL_H_
+#define UI_GFX_GL_GL_CONTEXT_WGL_H_
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/gl/gl_context.h"
+#include "ui/gfx/gl/gl_surface_wgl.h"
+#include "ui/gfx/size.h"
+
+namespace gfx {
+
+// This class is a wrapper around a GL context.
+class GLContextWGL : public GLContext {
+ public:
+ explicit GLContextWGL(GLSurfaceWGL* surface);
+ virtual ~GLContextWGL();
+
+ // Initializes the GL context.
+ bool Initialize(GLContext* shared_context);
+
+ // Implement GLContext.
+ virtual void Destroy();
+ virtual bool MakeCurrent();
+ virtual bool IsCurrent();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+ virtual void SetSwapInterval(int interval);
+ virtual std::string GetExtensions();
+
+ private:
+ scoped_ptr<GLSurfaceWGL> surface_;
+ HGLRC context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextWGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_GL_CONTEXT_WGL_H_
diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc
index d2bbe77..87f3d98 100644
--- a/ui/gfx/gl/gl_context_win.cc
+++ b/ui/gfx/gl/gl_context_win.cc
@@ -16,54 +16,13 @@
#include "ui/gfx/gl/gl_context_egl.h"
#include "ui/gfx/gl/gl_context_osmesa.h"
#include "ui/gfx/gl/gl_context_stub.h"
+#include "ui/gfx/gl/gl_context_wgl.h"
#include "ui/gfx/gl/gl_implementation.h"
#include "ui/gfx/gl/gl_surface_egl.h"
+#include "ui/gfx/gl/gl_surface_wgl.h"
namespace gfx {
-typedef HGLRC GLContextHandle;
-typedef HPBUFFERARB PbufferHandle;
-
-class BaseWinGLContext : public GLContext {
- public:
- virtual std::string GetExtensions();
-
- virtual HDC GetDC() = 0;
-};
-
-// This class is a wrapper around a GL context that renders directly to a
-// window.
-class NativeViewGLContext : public BaseWinGLContext {
- public:
- explicit NativeViewGLContext(gfx::PluginWindowHandle window)
- : window_(window),
- device_context_(NULL),
- context_(NULL) {
- DCHECK(window);
- }
-
- // Initializes the GL context.
- bool Initialize(bool multisampled);
-
- virtual void Destroy();
- virtual bool MakeCurrent();
- virtual bool IsCurrent();
- virtual bool IsOffscreen();
- virtual bool SwapBuffers();
- virtual gfx::Size GetSize();
- virtual void* GetHandle();
- virtual void SetSwapInterval(int interval);
-
- virtual HDC GetDC();
-
- private:
- gfx::PluginWindowHandle window_;
- HDC device_context_;
- GLContextHandle context_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeViewGLContext);
-};
-
// This class is a wrapper around a GL context that uses OSMesa to render
// to an offscreen buffer and then blits it to a window.
class OSMesaViewGLContext : public GLContext {
@@ -96,70 +55,6 @@ class OSMesaViewGLContext : public GLContext {
DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext);
};
-// This class is a wrapper around a GL context used for offscreen rendering.
-// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful
-// rendering.
-class PbufferGLContext : public GLContext {
- public:
- PbufferGLContext()
- : context_(NULL),
- device_context_(NULL),
- pbuffer_(NULL) {
- }
-
- // Initializes the GL context.
- bool Initialize(GLContext* shared_context);
-
- virtual void Destroy();
- virtual bool MakeCurrent();
- virtual bool IsCurrent();
- virtual bool IsOffscreen();
- virtual bool SwapBuffers();
- virtual gfx::Size GetSize();
- virtual void* GetHandle();
- virtual void SetSwapInterval(int interval);
-
- virtual HDC GetDC();
-
- private:
- GLContextHandle context_;
- HDC device_context_;
- PbufferHandle pbuffer_;
-
- DISALLOW_COPY_AND_ASSIGN(PbufferGLContext);
-};
-
-static HWND g_window;
-static int g_regular_pixel_format = 0;
-static int g_multisampled_pixel_format = 0;
-
-const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
- sizeof(kPixelFormatDescriptor), // Size of structure.
- 1, // Default version.
- PFD_DRAW_TO_WINDOW | // Window drawing support.
- PFD_SUPPORT_OPENGL | // OpenGL support.
- PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
- PFD_TYPE_RGBA, // RGBA color mode (not indexed).
- 24, // 24 bit color mode.
- 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
- 8, 0, // 8 bit alpha
- 0, // No accumulation buffer.
- 0, 0, 0, 0, // Ignore accumulation bits.
- 24, // 24 bit z-buffer size.
- 8, // 8-bit stencil buffer.
- 0, // No aux buffer.
- PFD_MAIN_PLANE, // Main drawing plane (not overlay).
- 0, // Reserved.
- 0, 0, 0, // Layer masks ignored.
-};
-
-LRESULT CALLBACK IntermediateWindowProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- return ::DefWindowProc(window, message, w_param, l_param);
-}
-
// Helper routine that does one-off initialization like determining the
// pixel format and initializing the GL bindings.
bool GLContext::InitializeOneOff() {
@@ -181,134 +76,11 @@ bool GLContext::InitializeOneOff() {
return false;
}
- // 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)) {
- LOG(ERROR) << "GetModuleHandleEx failed.";
- 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) {
- LOG(ERROR) << "RegisterClass failed.";
- return false;
- }
-
- g_window = ::CreateWindow(
- reinterpret_cast<wchar_t*>(class_registration),
- L"",
- WS_OVERLAPPEDWINDOW,
- 0, 0,
- 100, 100,
- NULL,
- NULL,
- NULL,
- NULL);
-
- if (!g_window) {
- ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
- module_handle);
- LOG(ERROR) << "CreateWindow failed.";
- return false;
- }
-
- // Early out if OSMesa offscreen renderer or EGL is present.
switch (GetGLImplementation()) {
- case kGLImplementationDesktopGL: {
- HDC intermediate_dc = ::GetDC(g_window);
- g_regular_pixel_format = ::ChoosePixelFormat(intermediate_dc,
- &kPixelFormatDescriptor);
- if (g_regular_pixel_format == 0) {
- LOG(ERROR) << "Unable to get the pixel format for GL context.";
- ::ReleaseDC(g_window, intermediate_dc);
- ::DestroyWindow(g_window);
- ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
- module_handle);
- return false;
- }
- if (!::SetPixelFormat(intermediate_dc, g_regular_pixel_format,
- &kPixelFormatDescriptor)) {
- LOG(ERROR) << "Unable to set the pixel format for GL context.";
- ::ReleaseDC(g_window, intermediate_dc);
- ::DestroyWindow(g_window);
- ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
- module_handle);
+ case kGLImplementationDesktopGL:
+ if (!GLSurfaceWGL::InitializeOneOff())
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)) {
- // Get bindings to extension functions that cannot be acquired without a
- // current context.
- InitializeGLBindingsGL();
- InitializeGLBindingsWGL();
-
- // If the multi-sample extensions are present, query the api to
- // determine the pixel format.
- if (wglGetExtensionsStringARB) {
- std::string extensions =
- std::string(wglGetExtensionsStringARB(intermediate_dc));
- extensions += std::string(" ");
- if (extensions.find("WGL_ARB_pixel_format ")) {
- 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 (wglChoosePixelFormatARB(intermediate_dc,
- pixel_attributes,
- pixel_attributes_f,
- 1,
- &g_multisampled_pixel_format,
- &num_formats)) {
- break;
- }
- }
- }
- }
- }
-
- wglMakeCurrent(intermediate_dc, NULL);
- wglDeleteContext(gl_context);
- ReleaseDC(g_window, intermediate_dc);
- UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
- module_handle);
break;
- }
case kGLImplementationEGLGLES2:
if (!GLSurfaceEGL::InitializeOneOff()) {
LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
@@ -321,114 +93,6 @@ bool GLContext::InitializeOneOff() {
return true;
}
-
-std::string BaseWinGLContext::GetExtensions() {
- if (wglGetExtensionsStringARB) {
- const char* extensions = wglGetExtensionsStringARB(GetDC());
- if (extensions) {
- return GLContext::GetExtensions() + " " + extensions;
- }
- }
-
- return GLContext::GetExtensions();
-}
-
-bool NativeViewGLContext::Initialize(bool multisampled) {
- // The GL context will render to this window.
- device_context_ = ::GetDC(window_);
-
- int pixel_format =
- multisampled ? g_multisampled_pixel_format : g_regular_pixel_format;
- if (!SetPixelFormat(device_context_,
- pixel_format,
- &kPixelFormatDescriptor)) {
- LOG(ERROR) << "Unable to set the pixel format for GL context.";
- Destroy();
- return false;
- }
-
- context_ = wglCreateContext(device_context_);
- if (!context_) {
- LOG(ERROR) << "Failed to create GL context.";
- Destroy();
- return false;
- }
-
- if (!MakeCurrent()) {
- LOG(ERROR) << "MakeCurrent failed.";
- Destroy();
- return false;
- }
-
- if (!InitializeCommon()) {
- LOG(ERROR) << "GLContext::InitializeCommon failed.";
- Destroy();
- return false;
- }
-
- return true;
-}
-
-void NativeViewGLContext::Destroy() {
- if (context_) {
- wglDeleteContext(context_);
- context_ = NULL;
- }
-
- if (window_ && device_context_)
- ReleaseDC(window_, device_context_);
-
- window_ = NULL;
- device_context_ = NULL;
-}
-
-bool NativeViewGLContext::MakeCurrent() {
- if (IsCurrent()) {
- return true;
- }
- if (!wglMakeCurrent(device_context_, context_)) {
- LOG(ERROR) << "Unable to make gl context current.";
- return false;
- }
-
- return true;
-}
-
-bool NativeViewGLContext::IsCurrent() {
- return wglGetCurrentDC() == device_context_ &&
- wglGetCurrentContext() == context_;
-}
-
-bool NativeViewGLContext::IsOffscreen() {
- return false;
-}
-
-bool NativeViewGLContext::SwapBuffers() {
- DCHECK(device_context_);
- return ::SwapBuffers(device_context_) == TRUE;
-}
-
-gfx::Size NativeViewGLContext::GetSize() {
- RECT rect;
- CHECK(GetClientRect(window_, &rect));
- return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
-}
-
-void* NativeViewGLContext::GetHandle() {
- return context_;
-}
-
-void NativeViewGLContext::SetSwapInterval(int interval) {
- DCHECK(IsCurrent());
- if (HasExtension("WGL_EXT_swap_control") && wglSwapIntervalEXT) {
- wglSwapIntervalEXT(interval);
- }
-}
-
-HDC NativeViewGLContext::GetDC() {
- return device_context_;
-}
-
bool OSMesaViewGLContext::Initialize() {
// The GL context will render to this window.
device_context_ = GetDC(window_);
@@ -561,8 +225,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
return context.release();
}
case kGLImplementationDesktopGL: {
- scoped_ptr<NativeViewGLContext> context(new NativeViewGLContext(window));
- if (!context->Initialize(multisampled))
+ scoped_ptr<NativeViewGLSurfaceWGL> surface(new NativeViewGLSurfaceWGL(
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ scoped_ptr<GLContextWGL> context(
+ new GLContextWGL(surface.release()));
+ if (!context->Initialize(NULL))
return NULL;
return context.release();
@@ -575,129 +245,6 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
}
}
-bool PbufferGLContext::Initialize(GLContext* shared_context) {
- // 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.
- if (!wglCreatePbufferARB) {
- LOG(ERROR) << "wglCreatePbufferARB not available.";
- Destroy();
- return false;
- }
- const int kNoAttributes[] = { 0 };
- pbuffer_ = wglCreatePbufferARB(display_device_context,
- g_regular_pixel_format,
- 1, 1,
- kNoAttributes);
- ::DeleteDC(display_device_context);
- if (!pbuffer_) {
- LOG(ERROR) << "Unable to create pbuffer.";
- Destroy();
- return false;
- }
-
- device_context_ = wglGetPbufferDCARB(pbuffer_);
- if (!device_context_) {
- LOG(ERROR) << "Unable to get pbuffer device context.";
- Destroy();
- return false;
- }
-
- context_ = wglCreateContext(device_context_);
- if (!context_) {
- LOG(ERROR) << "Failed to create GL context.";
- Destroy();
- return false;
- }
-
- if (shared_context) {
- if (!wglShareLists(
- static_cast<GLContextHandle>(shared_context->GetHandle()), context_)) {
- LOG(ERROR) << "Could not share GL contexts.";
- Destroy();
- return false;
- }
- }
-
- if (!MakeCurrent()) {
- LOG(ERROR) << "MakeCurrent failed.";
- Destroy();
- return false;
- }
-
- if (!InitializeCommon()) {
- LOG(ERROR) << "GLContext::InitializeCommon failed.";
- Destroy();
- return false;
- }
-
- return true;
-}
-
-void PbufferGLContext::Destroy() {
- if (context_) {
- wglDeleteContext(context_);
- context_ = NULL;
- }
-
- if (pbuffer_ && device_context_)
- wglReleasePbufferDCARB(pbuffer_, device_context_);
-
- device_context_ = NULL;
-
- if (pbuffer_) {
- wglDestroyPbufferARB(pbuffer_);
- pbuffer_ = NULL;
- }
-}
-
-bool PbufferGLContext::MakeCurrent() {
- if (IsCurrent()) {
- return true;
- }
- if (!wglMakeCurrent(device_context_, context_)) {
- LOG(ERROR) << "Unable to make gl context current.";
- return false;
- }
-
- return true;
-}
-
-bool PbufferGLContext::IsCurrent() {
- return wglGetCurrentDC() == device_context_ &&
- wglGetCurrentContext() == context_;
-}
-
-bool PbufferGLContext::IsOffscreen() {
- return true;
-}
-
-bool PbufferGLContext::SwapBuffers() {
- NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
- return false;
-}
-
-gfx::Size PbufferGLContext::GetSize() {
- NOTREACHED() << "Should not be requesting size of this pbuffer.";
- return gfx::Size(1, 1);
-}
-
-void* PbufferGLContext::GetHandle() {
- return context_;
-}
-
-void PbufferGLContext::SetSwapInterval(int interval) {
- DCHECK(IsCurrent());
- NOTREACHED() << "Attempt to call SetSwapInterval on a PbufferGLContext.";
-}
-
-HDC PbufferGLContext::GetDC() {
- return device_context_;
-}
-
GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) {
switch (GetGLImplementation()) {
case kGLImplementationOSMesaGL: {
@@ -720,7 +267,12 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) {
return context.release();
}
case kGLImplementationDesktopGL: {
- scoped_ptr<PbufferGLContext> context(new PbufferGLContext);
+ scoped_ptr<PbufferGLSurfaceWGL> surface(new PbufferGLSurfaceWGL(
+ gfx::Size(1, 1)));
+ if (!surface->Initialize())
+ return NULL;
+
+ scoped_ptr<GLContextWGL> context(new GLContextWGL(surface.release()));
if (!context->Initialize(shared_context))
return NULL;
diff --git a/ui/gfx/gl/gl_surface.h b/ui/gfx/gl/gl_surface.h
index c0ab1e9..811b232 100644
--- a/ui/gfx/gl/gl_surface.h
+++ b/ui/gfx/gl/gl_surface.h
@@ -39,14 +39,6 @@ class GLSurface {
// FBO. Otherwise returns 0.
virtual unsigned int GetBackingFrameBufferObject();
-#if !defined(OS_MACOSX)
- // Create a surface corresponding to a view.
- static GLSurface* CreateViewGLContext(gfx::PluginWindowHandle window);
-#endif
-
- // Create a surface used for offscreen rendering.
- static GLSurface* CreateOffscreenGLContext(const gfx::Size& size);
-
private:
DISALLOW_COPY_AND_ASSIGN(GLSurface);
};
diff --git a/ui/gfx/gl/gl_surface_wgl.cc b/ui/gfx/gl/gl_surface_wgl.cc
new file mode 100644
index 0000000..0218266
--- /dev/null
+++ b/ui/gfx/gl/gl_surface_wgl.cc
@@ -0,0 +1,297 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/gl/gl_context_wgl.h"
+
+#include "base/logging.h"
+#include "ui/gfx/gl/gl_bindings.h"
+#include "ui/gfx/gl/gl_implementation.h"
+
+namespace gfx {
+
+static HWND g_window;
+static int g_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.
+};
+
+static LRESULT CALLBACK IntermediateWindowProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ return ::DefWindowProc(window, message, w_param, l_param);
+}
+
+GLSurfaceWGL::GLSurfaceWGL() {
+}
+
+GLSurfaceWGL::~GLSurfaceWGL() {
+}
+
+bool GLSurfaceWGL::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ // We must initialize a GL context before we can bind to extension entry
+ // points. This requires the device context for a window.
+ 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)) {
+ LOG(ERROR) << "GetModuleHandleEx failed.";
+ 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) {
+ LOG(ERROR) << "RegisterClass failed.";
+ return false;
+ }
+
+ g_window = CreateWindow(
+ reinterpret_cast<wchar_t*>(class_registration),
+ L"",
+ WS_OVERLAPPEDWINDOW,
+ 0, 0,
+ 100, 100,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!g_window) {
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ LOG(ERROR) << "CreateWindow failed.";
+ return false;
+ }
+
+ HDC temporary_dc = GetDC(g_window);
+
+ g_pixel_format = ChoosePixelFormat(temporary_dc,
+ &kPixelFormatDescriptor);
+
+ if (g_pixel_format == 0) {
+ LOG(ERROR) << "Unable to get the pixel format for GL context.";
+ ReleaseDC(g_window, temporary_dc);
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ if (!SetPixelFormat(temporary_dc,
+ g_pixel_format,
+ &kPixelFormatDescriptor)) {
+ LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
+ ReleaseDC(g_window, temporary_dc);
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // Create a temporary GL context to bind to extension entry points.
+ HGLRC gl_context = wglCreateContext(temporary_dc);
+ if (!gl_context) {
+ LOG(ERROR) << "Failed to create temporary context.";
+ ReleaseDC(g_window, temporary_dc);
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ if (!wglMakeCurrent(temporary_dc, gl_context)) {
+ LOG(ERROR) << "Failed to make temporary GL context current.";
+ wglDeleteContext(gl_context);
+ ReleaseDC(g_window, temporary_dc);
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+ return false;
+ }
+
+ // Get bindings to extension functions that cannot be acquired without a
+ // current context.
+ InitializeGLBindingsGL();
+ InitializeGLBindingsWGL();
+
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(gl_context);
+ ReleaseDC(g_window, temporary_dc);
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration),
+ module_handle);
+
+ initialized = true;
+ return true;
+}
+
+NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::PluginWindowHandle window)
+ : window_(window),
+ device_context_(NULL) {
+ DCHECK(window);
+}
+
+NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceWGL::Initialize() {
+ DCHECK(!device_context_);
+
+ // The GL context will render to this window.
+ device_context_ = GetDC(window_);
+ if (!device_context_) {
+ LOG(ERROR) << "Unable to get device context for window.";
+ Destroy();
+ return false;
+ }
+
+ if (!SetPixelFormat(device_context_,
+ g_pixel_format,
+ &kPixelFormatDescriptor)) {
+ LOG(ERROR) << "Unable to set the pixel format for GL context.";
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void NativeViewGLSurfaceWGL::Destroy() {
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ window_ = NULL;
+ device_context_ = NULL;
+}
+
+bool NativeViewGLSurfaceWGL::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceWGL::SwapBuffers() {
+ DCHECK(device_context_);
+ return ::SwapBuffers(device_context_) == TRUE;
+}
+
+gfx::Size NativeViewGLSurfaceWGL::GetSize() {
+ RECT rect;
+ DCHECK(GetClientRect(window_, &rect));
+ return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void* NativeViewGLSurfaceWGL::GetHandle() {
+ return device_context_;
+}
+
+PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
+ : size_(size),
+ device_context_(NULL),
+ pbuffer_(NULL) {
+}
+
+PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
+ Destroy();
+}
+
+bool PbufferGLSurfaceWGL::Initialize() {
+ DCHECK(!device_context_);
+
+ if (!wglCreatePbufferARB) {
+ LOG(ERROR) << "wglCreatePbufferARB not available.";
+ Destroy();
+ return false;
+ }
+
+ // Create a temporary device context for the display. The pbuffer will be
+ // compatible with it.
+ HDC temporary_dc = GetDC(g_window);
+ if (!temporary_dc) {
+ LOG(ERROR) << "Unable to get device context.";
+ return false;
+ }
+
+ const int kNoAttributes[] = { 0 };
+ pbuffer_ = wglCreatePbufferARB(temporary_dc,
+ g_pixel_format,
+ size_.width(), size_.height(),
+ kNoAttributes);
+
+ ReleaseDC(g_window, temporary_dc);
+
+ if (!pbuffer_) {
+ LOG(ERROR) << "Unable to create pbuffer.";
+ Destroy();
+ return false;
+ }
+
+ device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
+ if (!device_context_) {
+ LOG(ERROR) << "Unable to get pbuffer device context.";
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLSurfaceWGL::Destroy() {
+ if (pbuffer_ && device_context_)
+ wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);
+
+ device_context_ = NULL;
+
+ if (pbuffer_) {
+ wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
+ pbuffer_ = NULL;
+ }
+}
+
+bool PbufferGLSurfaceWGL::IsOffscreen() {
+ return true;
+}
+
+bool PbufferGLSurfaceWGL::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
+ return false;
+}
+
+gfx::Size PbufferGLSurfaceWGL::GetSize() {
+ return size_;
+}
+
+void* PbufferGLSurfaceWGL::GetHandle() {
+ return device_context_;
+}
+
+} // namespace gfx
diff --git a/ui/gfx/gl/gl_surface_wgl.h b/ui/gfx/gl/gl_surface_wgl.h
new file mode 100644
index 0000000..d94c565
--- /dev/null
+++ b/ui/gfx/gl/gl_surface_wgl.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GFX_GL_GL_SURFACE_WGL_H_
+#define UI_GFX_GL_GL_SURFACE_WGL_H_
+
+#include "ui/gfx/gl/gl_surface.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+
+// Base interface for WGL surfaces.
+class GLSurfaceWGL : public GLSurface {
+ public:
+ GLSurfaceWGL();
+ virtual ~GLSurfaceWGL();
+
+ static bool InitializeOneOff();
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceWGL);
+};
+
+// A surface used to render to a view.
+class NativeViewGLSurfaceWGL : public GLSurfaceWGL {
+ public:
+ explicit NativeViewGLSurfaceWGL(gfx::PluginWindowHandle window);
+ virtual ~NativeViewGLSurfaceWGL();
+
+ // Initializes the GL context.
+ bool Initialize();
+
+ // Implement GLSurface.
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::PluginWindowHandle window_;
+ HDC device_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceWGL);
+};
+
+
+// A surface used to render to an offscreen pbuffer.
+class PbufferGLSurfaceWGL : public GLSurfaceWGL {
+ public:
+ explicit PbufferGLSurfaceWGL(const gfx::Size& size);
+ virtual ~PbufferGLSurfaceWGL();
+
+ // Initializes the GL context.
+ bool Initialize();
+
+ // Implement GLSurface.
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::Size size_;
+ HDC device_context_;
+ void* pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceWGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_GL_GL_SURFACE_WGL_H_