Index: app/gfx/gl/gl_context_win.cc |
=================================================================== |
--- app/gfx/gl/gl_context_win.cc (revision 49195) |
+++ app/gfx/gl/gl_context_win.cc (working copy) |
@@ -4,17 +4,16 @@ |
// This file implements the NativeViewGLContext and PbufferGLContext classes. |
-#include <GL/glew.h> |
-#include <GL/osmew.h> |
-#include <GL/wglew.h> |
-#include <windows.h> |
- |
#include <algorithm> |
#include "base/logging.h" |
#include "base/scoped_ptr.h" |
+#include "app/gfx/gl/gl_bindings.h" |
#include "app/gfx/gl/gl_context.h" |
+#include "app/gfx/gl/gl_context_egl.h" |
#include "app/gfx/gl/gl_context_osmesa.h" |
+#include "app/gfx/gl/gl_context_stub.h" |
+#include "app/gfx/gl/gl_implementation.h" |
namespace gfx { |
@@ -100,7 +99,7 @@ |
} |
// Initializes the GL context. |
- bool Initialize(void* shared_handle); |
+ bool Initialize(GLContext* shared_context); |
virtual void Destroy(); |
virtual bool MakeCurrent(); |
@@ -118,9 +117,14 @@ |
DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); |
}; |
+static HWND g_window; |
static int g_regular_pixel_format = 0; |
static int g_multisampled_pixel_format = 0; |
+// When using ANGLE we still need a window for D3D. This context creates the |
+// D3D device. |
+static BaseEGLContext* g_default_context; |
+ |
const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = { |
sizeof(kPixelFormatDescriptor), // Size of structure. |
1, // Default version. |
@@ -155,94 +159,103 @@ |
if (initialized) |
return true; |
- osmewInit(); |
- if (!OSMesaCreateContext) { |
- // We must initialize a GL context before we can determine the multi- |
- // sampling supported on the current hardware, so we create an intermediate |
- // window and context here. |
- HINSTANCE module_handle; |
- if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | |
- GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, |
- reinterpret_cast<wchar_t*>(IntermediateWindowProc), |
- &module_handle)) { |
- return false; |
+ if (!InitializeGLBindings(kGLImplementationOSMesaGL)) { |
+ if (!InitializeGLBindings(kGLImplementationEGLGLES2)) { |
+ if (!InitializeGLBindings(kGLImplementationDesktopGL)) { |
+ LOG(ERROR) << "Could not initialize GL."; |
+ 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; |
- } |
+ // 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; |
+ } |
- HWND intermediate_window = ::CreateWindow( |
- reinterpret_cast<wchar_t*>(class_registration), |
- L"", |
- WS_OVERLAPPEDWINDOW, |
- 0, 0, |
- CW_USEDEFAULT, CW_USEDEFAULT, |
- NULL, |
- NULL, |
- NULL, |
- NULL); |
+ 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"; |
- if (!intermediate_window) { |
- ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), |
- module_handle); |
- return false; |
- } |
+ ATOM class_registration = ::RegisterClass(&intermediate_class); |
+ if (!class_registration) { |
+ 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; |
- } |
+ g_window = ::CreateWindow( |
+ reinterpret_cast<wchar_t*>(class_registration), |
+ L"", |
+ WS_OVERLAPPEDWINDOW, |
+ 0, 0, |
+ 100, 100, |
+ NULL, |
+ NULL, |
+ NULL, |
+ NULL); |
- // 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 (!g_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) { |
+ // Early out if OSMesa offscreen renderer or EGL is present. |
+ if (GetGLImplementation() != kGLImplementationDesktopGL) { |
+ initialized = true; |
+ return true; |
+ } |
+ |
+ HDC intermediate_dc = ::GetDC(g_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(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)) { |
+ DLOG(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); |
+ 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, |
@@ -264,28 +277,26 @@ |
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)) { |
+ 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); |
} |
+ wglMakeCurrent(intermediate_dc, NULL); |
+ wglDeleteContext(gl_context); |
+ ReleaseDC(g_window, intermediate_dc); |
+ UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), |
+ module_handle); |
+ |
initialized = true; |
- |
return true; |
} |
@@ -352,11 +363,6 @@ |
return false; |
} |
- if (!InitializeGLEW()) { |
- Destroy(); |
- return false; |
- } |
- |
if (!InitializeCommon()) { |
Destroy(); |
return false; |
@@ -510,7 +516,7 @@ |
void OSMesaViewGLContext::UpdateSize() { |
// Change back buffer size to that of window. |
RECT rect; |
- GetWindowRect(window_, &rect); |
+ GetClientRect(window_, &rect); |
gfx::Size window_size = gfx::Size( |
std::max(1, static_cast<int>(rect.right - rect.left)), |
std::max(1, static_cast<int>(rect.bottom - rect.top))); |
@@ -522,24 +528,38 @@ |
if (!InitializeOneOff()) |
return NULL; |
- if (OSMesaCreateContext) { |
- scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); |
+ switch (GetGLImplementation()) { |
+ case kGLImplementationOSMesaGL: { |
+ scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); |
+ if (!context->Initialize()) |
+ return NULL; |
- if (!context->Initialize()) |
- return NULL; |
+ return context.release(); |
+ } |
+ case kGLImplementationEGLGLES2: { |
+ scoped_ptr<NativeViewEGLContext> context( |
+ new NativeViewEGLContext(window)); |
+ if (!context->Initialize()) |
+ return NULL; |
- return context.release(); |
- } else { |
- scoped_ptr<NativeViewGLContext> context(new NativeViewGLContext(window)); |
+ return context.release(); |
+ } |
+ case kGLImplementationDesktopGL: { |
+ scoped_ptr<NativeViewGLContext> context(new NativeViewGLContext(window)); |
+ if (!context->Initialize(multisampled)) |
+ return NULL; |
- if (!context->Initialize(multisampled)) |
+ return context.release(); |
+ } |
+ case kGLImplementationMockGL: |
+ return new StubGLContext; |
+ default: |
+ NOTREACHED(); |
return NULL; |
- |
- return context.release(); |
} |
} |
-bool PbufferGLContext::Initialize(void* shared_handle) { |
+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); |
@@ -547,10 +567,10 @@ |
// 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); |
+ pbuffer_ = wglCreatePbufferARB(display_device_context, |
+ g_regular_pixel_format, |
+ 1, 1, |
+ kNoAttributes); |
::DeleteDC(display_device_context); |
if (!pbuffer_) { |
DLOG(ERROR) << "Unable to create pbuffer."; |
@@ -558,22 +578,23 @@ |
return false; |
} |
- device_context_ = ::wglGetPbufferDCARB(pbuffer_); |
+ device_context_ = wglGetPbufferDCARB(pbuffer_); |
if (!device_context_) { |
DLOG(ERROR) << "Unable to get pbuffer device context."; |
Destroy(); |
return false; |
} |
- context_ = ::wglCreateContext(device_context_); |
+ context_ = wglCreateContext(device_context_); |
if (!context_) { |
DLOG(ERROR) << "Failed to create GL context."; |
Destroy(); |
return false; |
} |
- if (shared_handle) { |
- if (!wglShareLists(static_cast<GLContextHandle>(shared_handle), context_)) { |
+ if (shared_context) { |
+ if (!wglShareLists( |
+ static_cast<GLContextHandle>(shared_context->GetHandle()), context_)) { |
DLOG(ERROR) << "Could not share GL contexts."; |
Destroy(); |
return false; |
@@ -585,11 +606,6 @@ |
return false; |
} |
- if (!InitializeGLEW()) { |
- Destroy(); |
- return false; |
- } |
- |
if (!InitializeCommon()) { |
Destroy(); |
return false; |
@@ -649,23 +665,50 @@ |
return context_; |
} |
-GLContext* GLContext::CreateOffscreenGLContext(void* shared_handle) { |
+GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { |
if (!InitializeOneOff()) |
return NULL; |
- if (OSMesaCreateContext) { |
- scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); |
+ switch (GetGLImplementation()) { |
+ case kGLImplementationOSMesaGL: { |
+ scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); |
+ if (!context->Initialize(shared_context)) |
+ return NULL; |
- if (!context->Initialize(shared_handle)) |
- return NULL; |
+ return context.release(); |
+ } |
+ case kGLImplementationEGLGLES2: { |
+ if (!shared_context) { |
+ if (!g_default_context) { |
+ scoped_ptr<NativeViewEGLContext> default_context( |
+ new NativeViewEGLContext(g_window)); |
+ if (!default_context->Initialize()) |
+ return NULL; |
- return context.release(); |
- } else { |
- scoped_ptr<PbufferGLContext> context(new PbufferGLContext); |
- if (!context->Initialize(shared_handle)) |
+ g_default_context = default_context.release(); |
+ } |
+ shared_context = g_default_context; |
+ } |
+ |
+ scoped_ptr<SecondaryEGLContext> context( |
+ new SecondaryEGLContext()); |
+ if (!context->Initialize(shared_context)) |
+ return NULL; |
+ |
+ return context.release(); |
+ } |
+ case kGLImplementationDesktopGL: { |
+ scoped_ptr<PbufferGLContext> context(new PbufferGLContext); |
+ if (!context->Initialize(shared_context)) |
+ return NULL; |
+ |
+ return context.release(); |
+ } |
+ case kGLImplementationMockGL: |
+ return new StubGLContext; |
+ default: |
+ NOTREACHED(); |
return NULL; |
- |
- return context.release(); |
} |
} |