diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 20:47:04 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-14 20:47:04 +0000 |
commit | 30aa5c1ab237fa0940b04ffd78cc9033d9ca3afe (patch) | |
tree | bcc87f53bf61028f8cd3fcf27d4218f287ad2155 /app/gfx | |
parent | 6164c8d2a67aa8346b9f7735d849f4ee4f1c63cd (diff) | |
download | chromium_src-30aa5c1ab237fa0940b04ffd78cc9033d9ca3afe.zip chromium_src-30aa5c1ab237fa0940b04ffd78cc9033d9ca3afe.tar.gz chromium_src-30aa5c1ab237fa0940b04ffd78cc9033d9ca3afe.tar.bz2 |
Added --use-gl command line flag to select GL implementation.
- Options are desktop, egl and osmesa.
- Also added support for bliting an OSMesa bask buffer to a GDK window.
TEST=trybots, manual verification that WebGL and Pepper 3D work
BUG=45898
Review URL: http://codereview.chromium.org/2825005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52388 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app/gfx')
-rw-r--r-- | app/gfx/gl/gl_context.h | 2 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_egl.cc | 11 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_egl.h | 2 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_linux.cc | 233 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_mac.cc | 32 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_osmesa.cc | 13 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_osmesa.h | 2 | ||||
-rw-r--r-- | app/gfx/gl/gl_context_win.cc | 196 | ||||
-rw-r--r-- | app/gfx/gl/gl_implementation.cc | 130 | ||||
-rw-r--r-- | app/gfx/gl/gl_implementation.h | 30 | ||||
-rw-r--r-- | app/gfx/gl/gl_implementation_linux.cc | 156 | ||||
-rw-r--r-- | app/gfx/gl/gl_implementation_mac.cc | 88 | ||||
-rw-r--r-- | app/gfx/gl/gl_implementation_win.cc | 138 |
13 files changed, 700 insertions, 333 deletions
diff --git a/app/gfx/gl/gl_context.h b/app/gfx/gl/gl_context.h index 9da7583..34819b8 100644 --- a/app/gfx/gl/gl_context.h +++ b/app/gfx/gl/gl_context.h @@ -40,6 +40,8 @@ class GLContext { // Get the underlying platform specific GL context "handle". virtual void* GetHandle() = 0; + static bool InitializeOneOff(); + #if !defined(OS_MACOSX) // Create a GL context that renders directly to a view. static GLContext* CreateViewGLContext(gfx::PluginWindowHandle window, diff --git a/app/gfx/gl/gl_context_egl.cc b/app/gfx/gl/gl_context_egl.cc index 4bea175..1d05eb0 100644 --- a/app/gfx/gl/gl_context_egl.cc +++ b/app/gfx/gl/gl_context_egl.cc @@ -21,7 +21,9 @@ namespace { EGLDisplay g_display; EGLConfig g_config; -bool InitializeOneOff() { +} // namespace anonymous + +bool BaseEGLContext::InitializeOneOff() { static bool initialized = false; if (initialized) return true; @@ -81,7 +83,6 @@ bool InitializeOneOff() { initialized = true; return true; } -} // namespace anonymous NativeViewEGLContext::NativeViewEGLContext(void* window) : window_(window), @@ -96,9 +97,6 @@ NativeViewEGLContext::~NativeViewEGLContext() { bool NativeViewEGLContext::Initialize() { DCHECK(!context_); - if (!InitializeOneOff()) - return NULL; - // Create a surface for the native window. EGLNativeWindowType native_window = reinterpret_cast<EGLNativeWindowType>(window_); @@ -198,9 +196,6 @@ SecondaryEGLContext::~SecondaryEGLContext() { bool SecondaryEGLContext::Initialize(GLContext* shared_context) { DCHECK(!context_); - if (!InitializeOneOff()) - return NULL; - static const EGLint kContextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE diff --git a/app/gfx/gl/gl_context_egl.h b/app/gfx/gl/gl_context_egl.h index 016a770..0681b3d 100644 --- a/app/gfx/gl/gl_context_egl.h +++ b/app/gfx/gl/gl_context_egl.h @@ -23,6 +23,8 @@ class BaseEGLContext : public GLContext { // Implement GLContext. virtual EGLSurface GetSurface() = 0; + static bool InitializeOneOff(); + private: DISALLOW_COPY_AND_ASSIGN(BaseEGLContext); }; diff --git a/app/gfx/gl/gl_context_linux.cc b/app/gfx/gl/gl_context_linux.cc index 550f967..8701bc3 100644 --- a/app/gfx/gl/gl_context_linux.cc +++ b/app/gfx/gl/gl_context_linux.cc @@ -4,15 +4,19 @@ // This file implements the ViewGLContext and PbufferGLContext classes. -#include "app/x11_util.h" -#include "base/logging.h" -#include "base/scoped_ptr.h" -#include "app/gfx/gl/gl_bindings.h" #include "app/gfx/gl/gl_context.h" + +#include <GL/osmesa.h> + +#include "app/gfx/gl/gl_bindings.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" +#include "app/x11_util.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" namespace gfx { @@ -47,6 +51,41 @@ class ViewGLContext : public GLContext { DISALLOW_COPY_AND_ASSIGN(ViewGLContext); }; +// This class is a wrapper around a GL context that uses OSMesa to render +// to an offscreen buffer and then blits it to a window. +class OSMesaViewGLContext : public GLContext { + public: + explicit OSMesaViewGLContext(gfx::PluginWindowHandle window) + : window_graphics_context_(0), + window_(window), + pixmap_graphics_context_(0), + pixmap_(0) { + DCHECK(window); + } + + // Initializes the GL context. + bool Initialize(); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual void SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + + private: + bool UpdateSize(); + + GC window_graphics_context_; + gfx::PluginWindowHandle window_; + GC pixmap_graphics_context_; + Pixmap pixmap_; + OSMesaGLContext osmesa_context_; + + DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext); +}; + // This class is a wrapper around a GL context used for offscreen rendering. // It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful // rendering. @@ -113,19 +152,21 @@ class ScopedPtrXFree { } }; -static bool InitializeOneOff() { +bool GLContext::InitializeOneOff() { static bool initialized = false; if (initialized) return true; - // Initialize the GL bindings if they haven't already been initialized. If - // the GPU unit tests are running, the mock GL implementation will already - // have been initialized. - if (!InitializeGLBindings(kGLImplementationEGLGLES2)) { - if (!InitializeGLBindings(kGLImplementationDesktopGL)) { - LOG(ERROR) << "Could not initialize GL."; - return false; - } + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationEGLGLES2, + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL + }; + + if (!InitializeBestGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations))) { + return false; } // Only check the GLX version if we are in fact using GLX. We might actually @@ -244,11 +285,153 @@ void* ViewGLContext::GetHandle() { return context_; } +bool OSMesaViewGLContext::Initialize() { + if (!osmesa_context_.Initialize(OSMESA_BGRA, NULL)) { + Destroy(); + return false; + } + + window_graphics_context_ = XCreateGC(x11_util::GetXDisplay(), + window_, + 0, + NULL); + if (!window_graphics_context_) { + LOG(ERROR) << "XCreateGC failed."; + Destroy(); + return false; + } + + UpdateSize(); + + return true; +} + +void OSMesaViewGLContext::Destroy() { + osmesa_context_.Destroy(); + + Display* display = x11_util::GetXDisplay(); + + if (pixmap_graphics_context_) { + XFreeGC(display, pixmap_graphics_context_); + pixmap_graphics_context_ = NULL; + } + + if (pixmap_) { + XFreePixmap(display, pixmap_); + pixmap_ = NULL; + } + + if (window_graphics_context_) { + XFreeGC(display, window_graphics_context_); + window_graphics_context_ = NULL; + } +} + +bool OSMesaViewGLContext::MakeCurrent() { + // TODO(apatrick): This is a bit of a hack. The window might have had zero + // size when the context was initialized. Assume it has a valid size when + // MakeCurrent is called and resize the back buffer if necessary. + UpdateSize(); + return osmesa_context_.MakeCurrent(); +} + +bool OSMesaViewGLContext::IsCurrent() { + return osmesa_context_.IsCurrent(); +} + +bool OSMesaViewGLContext::IsOffscreen() { + return false; +} + +void OSMesaViewGLContext::SwapBuffers() { + // Update the size before blitting so that the blit size is exactly the same + // as the window. + if (!UpdateSize()) + return; + + gfx::Size size = osmesa_context_.GetSize(); + + Display* display = x11_util::GetXDisplay(); + + // Copy the frame into the pixmap. + XWindowAttributes attributes; + XGetWindowAttributes(display, window_, &attributes); + x11_util::PutARGBImage(display, + attributes.visual, + attributes.depth, + pixmap_, + pixmap_graphics_context_, + static_cast<const uint8*>(osmesa_context_.buffer()), + size.width(), + size.height()); + + // Copy the pixmap to the window. + XCopyArea(display, + pixmap_, + window_, + window_graphics_context_, + 0, 0, + size.width(), size.height(), + 0, 0); +} + +gfx::Size OSMesaViewGLContext::GetSize() { + return osmesa_context_.GetSize(); +} + +void* OSMesaViewGLContext::GetHandle() { + return osmesa_context_.GetHandle(); +} + +bool OSMesaViewGLContext::UpdateSize() { + // Get the window size. + XWindowAttributes attributes; + Display* display = x11_util::GetXDisplay(); + XGetWindowAttributes(display, window_, &attributes); + gfx::Size window_size = gfx::Size(std::max(1, attributes.width), + std::max(1, attributes.height)); + + // Early out if the size has not changed. + gfx::Size osmesa_size = osmesa_context_.GetSize(); + if (pixmap_graphics_context_ && pixmap_ && window_size == osmesa_size) + return true; + + // Change osmesa surface size to that of window. + osmesa_context_.Resize(window_size); + + // Destroy the previous pixmap and graphics context. + if (pixmap_graphics_context_) { + XFreeGC(display, pixmap_graphics_context_); + pixmap_graphics_context_ = NULL; + } + if (pixmap_) { + XFreePixmap(display, pixmap_); + pixmap_ = NULL; + } + + // Recreate a pixmap to hold the frame. + pixmap_ = XCreatePixmap(display, + window_, + window_size.width(), + window_size.height(), + attributes.depth); + if (!pixmap_) { + LOG(ERROR) << "XCreatePixmap failed."; + return false; + } + + // Recreate a graphics context for the pixmap. + pixmap_graphics_context_ = XCreateGC(display, pixmap_, 0, NULL); + if (!pixmap_graphics_context_) { + LOG(ERROR) << "XCreateGC failed"; + return false; + } + + return true; +} + GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, bool multisampled) { - if (!InitializeOneOff()) - return NULL; - switch (GetGLImplementation()) { case kGLImplementationDesktopGL: { scoped_ptr<ViewGLContext> context(new ViewGLContext(window)); @@ -266,6 +449,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, return context.release(); } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); + + if (!context->Initialize()) + return NULL; + + return context.release(); + } case kGLImplementationMockGL: return new StubGLContext; default: @@ -514,9 +705,6 @@ void* PixmapGLContext::GetHandle() { } GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { - if (!InitializeOneOff()) - return NULL; - switch (GetGLImplementation()) { case kGLImplementationDesktopGL: { scoped_ptr<PbufferGLContext> context(new PbufferGLContext); @@ -537,6 +725,13 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { return context.release(); } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + if (!context->Initialize(OSMESA_RGBA, shared_context)) + return NULL; + + return context.release(); + } case kGLImplementationMockGL: return new StubGLContext; default: diff --git a/app/gfx/gl/gl_context_mac.cc b/app/gfx/gl/gl_context_mac.cc index 7d5bc39..16a22eb 100644 --- a/app/gfx/gl/gl_context_mac.cc +++ b/app/gfx/gl/gl_context_mac.cc @@ -4,14 +4,18 @@ // This file implements the ViewGLContext and PbufferGLContext classes. +#include "app/gfx/gl/gl_context.h" + +#include <GL/osmesa.h> #include <OpenGL/OpenGL.h> -#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_osmesa.h" #include "app/gfx/gl/gl_context_stub.h" #include "app/gfx/gl/gl_implementation.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" namespace gfx { @@ -46,13 +50,19 @@ class PbufferGLContext : public GLContext { DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); }; -static bool InitializeOneOff() { +bool GLContext::InitializeOneOff() { static bool initialized = false; if (initialized) return true; - if (!InitializeGLBindings(kGLImplementationDesktopGL)) { - LOG(ERROR) << "Could not initialize GL."; + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL + }; + + if (!InitializeBestGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations))) { return false; } @@ -162,9 +172,6 @@ void* PbufferGLContext::GetHandle() { } GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { - if (!InitializeOneOff()) - return NULL; - switch (GetGLImplementation()) { case kGLImplementationDesktopGL: { scoped_ptr<PbufferGLContext> context(new PbufferGLContext); @@ -173,6 +180,13 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { return context.release(); } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + if (!context->Initialize(OSMESA_RGBA, shared_context)) + return NULL; + + return context.release(); + } case kGLImplementationMockGL: return new StubGLContext; default: diff --git a/app/gfx/gl/gl_context_osmesa.cc b/app/gfx/gl/gl_context_osmesa.cc index 6d144cb..451c4d7 100644 --- a/app/gfx/gl/gl_context_osmesa.cc +++ b/app/gfx/gl/gl_context_osmesa.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <GL/osmesa.h> + #include <algorithm> #include "app/gfx/gl/gl_bindings.h" @@ -16,7 +18,7 @@ OSMesaGLContext::OSMesaGLContext() : context_(NULL) OSMesaGLContext::~OSMesaGLContext() { } -bool OSMesaGLContext::Initialize(GLContext* shared_context) { +bool OSMesaGLContext::Initialize(GLuint format, GLContext* shared_context) { DCHECK(!context_); size_ = gfx::Size(1, 1); @@ -26,7 +28,11 @@ bool OSMesaGLContext::Initialize(GLContext* shared_context) { if (shared_context) shared_handle = static_cast<OSMesaContext>(shared_context->GetHandle()); - context_ = OSMesaCreateContext(GL_RGBA, shared_handle); + context_ = OSMesaCreateContextExt(format, + 24, // depth bits + 8, // stencil bits + 0, // accum bits + shared_handle); if (!context_) return false; @@ -35,6 +41,9 @@ bool OSMesaGLContext::Initialize(GLContext* shared_context) { return false; } + // Row 0 is at the top. + OSMesaPixelStore(OSMESA_Y_UP, 0); + if (!InitializeCommon()) { Destroy(); return false; diff --git a/app/gfx/gl/gl_context_osmesa.h b/app/gfx/gl/gl_context_osmesa.h index 62acc5b..2359ba6 100644 --- a/app/gfx/gl/gl_context_osmesa.h +++ b/app/gfx/gl/gl_context_osmesa.h @@ -20,7 +20,7 @@ class OSMesaGLContext : public GLContext { virtual ~OSMesaGLContext(); // Initialize an OSMesa GL context with the default 1 x 1 initial size. - bool Initialize(GLContext* shared_context); + bool Initialize(GLuint format, GLContext* shared_context); // Implement GLContext. virtual void Destroy(); diff --git a/app/gfx/gl/gl_context_win.cc b/app/gfx/gl/gl_context_win.cc index e481325..8e24f94 100644 --- a/app/gfx/gl/gl_context_win.cc +++ b/app/gfx/gl/gl_context_win.cc @@ -4,17 +4,21 @@ // This file implements the NativeViewGLContext and PbufferGLContext classes. +#include "app/gfx/gl/gl_context.h" + +#include <GL/osmesa.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" +#include "base/logging.h" +#include "base/scoped_ptr.h" + namespace gfx { typedef HGLRC GLContextHandle; @@ -148,20 +152,22 @@ LRESULT CALLBACK IntermediateWindowProc(HWND window, // Helper routine that does one-off initialization like determining the // pixel format and initializing glew. -static bool InitializeOneOff() { +bool GLContext::InitializeOneOff() { static bool initialized = false; if (initialized) return true; - if (!InitializeGLBindings(kGLImplementationOSMesaGL)) { - if (!InitializeGLBindings(kGLImplementationEGLGLES2)) { - if (!InitializeGLBindings(kGLImplementationDesktopGL)) { - LOG(ERROR) << "Could not initialize GL."; - return false; - } - } - } + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationEGLGLES2, + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL + }; + if (!InitializeBestGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations))) { + 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 @@ -209,87 +215,91 @@ static bool InitializeOneOff() { } // 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; - } + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + 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, - 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; + // 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 (!BaseEGLContext::InitializeOneOff()) + return false; + break; } - 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; } @@ -381,7 +391,7 @@ bool OSMesaViewGLContext::Initialize() { // The GL context will render to this window. device_context_ = GetDC(window_); - if (!osmesa_context_.Initialize(NULL)) { + if (!osmesa_context_.Initialize(OSMESA_RGBA, NULL)) { Destroy(); return false; } @@ -426,9 +436,11 @@ void OSMesaViewGLContext::SwapBuffers() { gfx::Size size = osmesa_context_.GetSize(); + // Note: negating the height below causes GDI to treat the bitmap data as row + // 0 being at the top. BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) }; info.bV4Width = size.width(); - info.bV4Height = size.height(); + info.bV4Height = -size.height(); info.bV4Planes = 1; info.bV4BitCount = 32; info.bV4V4Compression = BI_BITFIELDS; @@ -467,9 +479,6 @@ void OSMesaViewGLContext::UpdateSize() { GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, bool multisampled) { - if (!InitializeOneOff()) - return NULL; - switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); @@ -608,13 +617,10 @@ void* PbufferGLContext::GetHandle() { } GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { - if (!InitializeOneOff()) - return NULL; - switch (GetGLImplementation()) { case kGLImplementationOSMesaGL: { scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); - if (!context->Initialize(shared_context)) + if (!context->Initialize(OSMESA_RGBA, shared_context)) return NULL; return context.release(); diff --git a/app/gfx/gl/gl_implementation.cc b/app/gfx/gl/gl_implementation.cc new file mode 100644 index 0000000..9c8686a --- /dev/null +++ b/app/gfx/gl/gl_implementation.cc @@ -0,0 +1,130 @@ +// 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. + +#include "app/gfx/gl/gl_implementation.h" + +#include <algorithm> +#include <string> + +#include "app/app_switches.h" +#include "base/at_exit.h" +#include "base/command_line.h" + +namespace gfx { +namespace { +struct NamePair { + std::wstring name; + GLImplementation implemention; +}; + +typedef std::vector<base::NativeLibrary> LibraryArray; + +GLImplementation g_gl_implementation = kGLImplementationNone; +LibraryArray* g_libraries; +GLGetProcAddressProc g_get_proc_address; + +void CleanupNativeLibraries(void* unused) { + if (g_libraries) { + for (LibraryArray::iterator it = g_libraries->begin(); + it != g_libraries->end(); ++it) { + base::UnloadNativeLibrary(*it); + } + delete g_libraries; + g_libraries = NULL; + } +} +} + +GLImplementation GetNamedGLImplementation(const std::wstring& name) { + static const NamePair name_pairs[] = { + { L"desktop", kGLImplementationDesktopGL }, + { L"osmesa", kGLImplementationOSMesaGL }, + { L"egl", kGLImplementationEGLGLES2 }, + { L"mock", kGLImplementationMockGL } + }; + + for (size_t i = 0; i < arraysize(name_pairs); ++i) { + if (name == name_pairs[i].name) + return name_pairs[i].implemention; + } + + return kGLImplementationNone; +} + +bool InitializeBestGLBindings( + const GLImplementation* allowed_implementations_begin, + const GLImplementation* allowed_implementations_end) { + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { + std::wstring requested_implementation_name = + CommandLine::ForCurrentProcess()->GetSwitchValue(switches::kUseGL); + GLImplementation requested_implementation = + GetNamedGLImplementation(requested_implementation_name); + if (std::find(allowed_implementations_begin, + allowed_implementations_end, + requested_implementation) == allowed_implementations_end) { + LOG(ERROR) << "Requested GL implementation is not allowed."; + return false; + } + + if (InitializeGLBindings(requested_implementation)) + return true; + } else { + for (const GLImplementation* p = allowed_implementations_begin; + p < allowed_implementations_end; + ++p) { + if (InitializeGLBindings(*p)) + return true; + } + } + + LOG(ERROR) << "Could not initialize GL."; + return false; +} + +void SetGLImplementation(GLImplementation implementation) { + g_gl_implementation = implementation; +} + +GLImplementation GetGLImplementation() { + return g_gl_implementation; +} + +void AddGLNativeLibrary(base::NativeLibrary library) { + DCHECK(library); + + if (!g_libraries) { + g_libraries = new LibraryArray; + base::AtExitManager::RegisterCallback(CleanupNativeLibraries, NULL); + } + + g_libraries->push_back(library); +} + +void SetGLGetProcAddressProc(GLGetProcAddressProc proc) { + DCHECK(proc); + g_get_proc_address = proc; +} + +void* GetGLProcAddress(const char* name) { + DCHECK(g_gl_implementation != kGLImplementationNone); + + if (g_get_proc_address) { + void* proc = g_get_proc_address(name); + if (proc) + return proc; + } + + if (g_libraries) { + for (size_t i = 0; i < g_libraries->size(); ++i) { + void* proc = base::GetFunctionPointerFromNativeLibrary((*g_libraries)[i], + name); + if (proc) + return proc; + } + } + + return NULL; +} + +} // namespace gfx diff --git a/app/gfx/gl/gl_implementation.h b/app/gfx/gl/gl_implementation.h index 0f1df36..85cbfa2 100644 --- a/app/gfx/gl/gl_implementation.h +++ b/app/gfx/gl/gl_implementation.h @@ -5,6 +5,11 @@ #ifndef APP_GFX_GL_GL_IMPLEMENTATION_H_ #define APP_GFX_GL_GL_IMPLEMENTATION_H_ +#include <string> + +#include "base/native_library.h" +#include "build/build_config.h" + namespace gfx { // The GL implementation currently in use. @@ -16,12 +21,37 @@ enum GLImplementation { kGLImplementationMockGL }; +#if defined(OS_WIN) +typedef void* (WINAPI *GLGetProcAddressProc)(const char* name); +#else +typedef void* (*GLGetProcAddressProc)(const char* name); +#endif + // Initialize a particular GL implementation. bool InitializeGLBindings(GLImplementation implementation); +// Set the current GL implementation. +void SetGLImplementation(GLImplementation implementation); + // Get the current GL implementation. GLImplementation GetGLImplementation(); +// Get the GL implementation with a given name. +GLImplementation GetNamedGLImplementation(const std::wstring& name); + +// Initialize the preferred GL binding from the given list. The preferred GL +// bindings depend on command line switches passed by the user and which GL +// implementations are available and working on the system +bool InitializeBestGLBindings( + const GLImplementation* allowed_implementations_begin, + const GLImplementation* allowed_implementations_end); + +// Add a native library to those searched for GL entry points. +void AddGLNativeLibrary(base::NativeLibrary library); + +// Set an additional function that will be called to find GL entry points. +void SetGLGetProcAddressProc(GLGetProcAddressProc proc); + // Find an entry point in the current GL implementation. void* GetGLProcAddress(const char* name); diff --git a/app/gfx/gl/gl_implementation_linux.cc b/app/gfx/gl/gl_implementation_linux.cc index 3bad24e..89f6ce3 100644 --- a/app/gfx/gl/gl_implementation_linux.cc +++ b/app/gfx/gl/gl_implementation_linux.cc @@ -2,23 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <dlfcn.h> #include <vector> -#include "base/at_exit.h" -#include "base/logging.h" +#include "app/app_switches.h" #include "app/gfx/gl/gl_bindings.h" #include "app/gfx/gl/gl_context_stub.h" #include "app/gfx/gl/gl_implementation.h" +#include "base/base_paths.h" +#include "base/command_line.h" +#include "base/file_path.h" +#include "base/logging.h" +#include "base/native_library.h" +#include "base/path_service.h" namespace gfx { namespace { -typedef void* (*GetProcAddressProc)(const char* name); - -GLImplementation g_gl_implementation = kGLImplementationNone; -typedef std::vector<void*> PointerArray; -PointerArray* g_shared_libraries = NULL; -GetProcAddressProc g_get_proc_address; // TODO(piman): it should be Desktop GL marshalling from double to float. Today // on native GLES, we do float->double->float. @@ -31,80 +29,87 @@ void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near, glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far)); } -void CleanupSharedLibraries(void* unused) { - if (g_shared_libraries) { - for (PointerArray::iterator it = g_shared_libraries->begin(); - it != g_shared_libraries->end(); ++it) { - dlclose(*it); - } - delete g_shared_libraries; - g_shared_libraries = NULL; - } -} - } // namespace anonymous bool InitializeGLBindings(GLImplementation implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. - if (g_gl_implementation != kGLImplementationNone) + if (GetGLImplementation() != kGLImplementationNone) return true; - if (!g_shared_libraries) { - g_shared_libraries = new PointerArray(); - base::AtExitManager::RegisterCallback(CleanupSharedLibraries, NULL); - } - - void* shared_library = NULL; - switch (implementation) { - case kGLImplementationDesktopGL: - DLOG(INFO) << "Initializing Desktop GL"; - shared_library = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); - if (!shared_library) { - DLOG(ERROR) << "Failed to load libGL.so.1"; + case kGLImplementationOSMesaGL: { + FilePath exe_path; + if (!PathService::Get(base::DIR_EXE, &exe_path)) return false; - } - g_shared_libraries->push_back(shared_library); + base::NativeLibrary library = base::LoadNativeLibrary( + exe_path.Append("libosmesa.so")); + if (!library) { + DLOG(INFO) << "libosmesa.so not found"; + return false; + } - g_gl_implementation = kGLImplementationDesktopGL; + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + library, "OSMesaGetProcAddress")); - g_get_proc_address = reinterpret_cast<GetProcAddressProc>( - dlsym(shared_library, "glXGetProcAddress")); - CHECK(g_get_proc_address); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationOSMesaGL); InitializeGLBindingsGL(); - InitializeGLBindingsGLX(); + InitializeGLBindingsOSMESA(); break; - - case kGLImplementationEGLGLES2: - DLOG(INFO) << "Initializing EGL"; - shared_library = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL); - if (!shared_library) { - DLOG(ERROR) << "Failed to load libEGL.so"; + } + case kGLImplementationDesktopGL: { + base::NativeLibrary library = base::LoadNativeLibrary( + FilePath("libGL.so.1")); + if (!library) { + DLOG(INFO) << "libGL.so.1 not found."; return false; } - g_gl_implementation = kGLImplementationEGLGLES2; - - g_get_proc_address = reinterpret_cast<GetProcAddressProc>( - dlsym(shared_library, "eglGetProcAddress")); - DCHECK(g_get_proc_address); + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + library, "glXGetProcAddress")); - g_shared_libraries->push_back(shared_library); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationDesktopGL); - shared_library = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_LOCAL); - if (!shared_library) { - DLOG(ERROR) << "Failed to load libGLESv2.so"; - g_shared_libraries->clear(); + InitializeGLBindingsGL(); + InitializeGLBindingsGLX(); + break; + } + case kGLImplementationEGLGLES2: { + base::NativeLibrary egl_library = base::LoadNativeLibrary( + FilePath("libEGL.so")); + if (!egl_library) { + DLOG(INFO) << "libEGL.so not found"; return false; } - DCHECK(shared_library); + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + egl_library, "eglGetProcAddress")); + + base::NativeLibrary gles_library = base::LoadNativeLibrary( + FilePath("libGLESv2.so")); + if (!gles_library) { + base::UnloadNativeLibrary(egl_library); + DLOG(INFO) << "libGLESv2.so not found"; + return false; + } - g_shared_libraries->push_back(shared_library); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(egl_library); + AddGLNativeLibrary(gles_library); + SetGLImplementation(kGLImplementationEGLGLES2); InitializeGLBindingsGL(); InitializeGLBindingsEGL(); @@ -114,13 +119,13 @@ bool InitializeGLBindings(GLImplementation implementation) { ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf; ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef; break; - - case kGLImplementationMockGL: - g_get_proc_address = GetMockGLProcAddress; - g_gl_implementation = kGLImplementationMockGL; + } + case kGLImplementationMockGL: { + SetGLGetProcAddressProc(GetMockGLProcAddress); + SetGLImplementation(kGLImplementationMockGL); InitializeGLBindingsGL(); break; - + } default: return false; } @@ -129,29 +134,4 @@ bool InitializeGLBindings(GLImplementation implementation) { return true; } -GLImplementation GetGLImplementation() { - return g_gl_implementation; -} - -void* GetGLProcAddress(const char* name) { - DCHECK(g_gl_implementation != kGLImplementationNone); - - if (g_get_proc_address) { - void* proc = g_get_proc_address(name); - if (proc) - return proc; - } - - if (g_shared_libraries) { - for (PointerArray::iterator it = g_shared_libraries->begin(); - it != g_shared_libraries->end(); ++it) { - void* proc = dlsym(*it, name); - if (proc) - return proc; - } - } - - return NULL; -} - } // namespace gfx diff --git a/app/gfx/gl/gl_implementation_mac.cc b/app/gfx/gl/gl_implementation_mac.cc index 7975726..d82c2e0 100644 --- a/app/gfx/gl/gl_implementation_mac.cc +++ b/app/gfx/gl/gl_implementation_mac.cc @@ -2,48 +2,74 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <dlfcn.h> - -#include "base/logging.h" #include "app/gfx/gl/gl_bindings.h" #include "app/gfx/gl/gl_implementation.h" +#include "base/base_paths.h" +#include "base/file_path.h" +#include "base/logging.h" +#include "base/native_library.h" +#include "base/path_service.h" namespace gfx { namespace { -typedef void* (*GetProcAddressProc)(const char* name); - -GLImplementation g_gl_implementation = kGLImplementationNone; -void* g_shared_library; -GetProcAddressProc g_get_proc_address; +const char kOpenGLFrameworkPath[] = + "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"; } // namespace anonymous bool InitializeGLBindings(GLImplementation implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. - if (g_gl_implementation != kGLImplementationNone) + if (GetGLImplementation() != kGLImplementationNone) return true; switch (implementation) { - case kGLImplementationDesktopGL: - g_shared_library = dlopen( - "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", - RTLD_LAZY | RTLD_LOCAL); - if (!g_shared_library) + case kGLImplementationOSMesaGL: { + FilePath exe_path; + if (!PathService::Get(base::DIR_EXE, &exe_path)) + return false; + + // When using OSMesa, just use OSMesaGetProcAddress to find entry points. + base::NativeLibrary library = base::LoadNativeLibrary( + exe_path.Append("libosmesa.dylib")); + if (!library) { + LOG(INFO) << "libosmesa.so not found"; return false; + } - g_gl_implementation = kGLImplementationDesktopGL; - g_get_proc_address = NULL; + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + library, "OSMesaGetProcAddress")); + + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationOSMesaGL); InitializeGLBindingsGL(); + InitializeGLBindingsOSMESA(); break; + } + case kGLImplementationDesktopGL: { + base::NativeLibrary library = base::LoadNativeLibrary( + FilePath(kOpenGLFrameworkPath)); + if (!library) { + LOG(INFO) << "OpenGL framework not found"; + return false; + } + + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationDesktopGL); - case kGLImplementationMockGL: - g_get_proc_address = GetMockGLProcAddress; - g_gl_implementation = kGLImplementationMockGL; InitializeGLBindingsGL(); break; - + } + case kGLImplementationMockGL: { + SetGLGetProcAddressProc(GetMockGLProcAddress); + SetGLImplementation(kGLImplementationMockGL); + InitializeGLBindingsGL(); + break; + } default: return false; } @@ -51,26 +77,4 @@ bool InitializeGLBindings(GLImplementation implementation) { return true; } -GLImplementation GetGLImplementation() { - return g_gl_implementation; -} - -void* GetGLProcAddress(const char* name) { - DCHECK(g_gl_implementation != kGLImplementationNone); - - if (g_get_proc_address) { - void* proc = g_get_proc_address(name); - if (proc) - return proc; - } - - if (g_shared_library) { - void* proc = dlsym(g_shared_library, name); - if (proc) - return proc; - } - - return NULL; -} - } // namespace gfx diff --git a/app/gfx/gl/gl_implementation_win.cc b/app/gfx/gl/gl_implementation_win.cc index cb25f07..3ff0127 100644 --- a/app/gfx/gl/gl_implementation_win.cc +++ b/app/gfx/gl/gl_implementation_win.cc @@ -4,7 +4,11 @@ #include <vector> +#include "base/base_paths.h" +#include "base/file_path.h" #include "base/logging.h" +#include "base/native_library.h" +#include "base/path_service.h" #include "app/gfx/gl/gl_bindings.h" #include "app/gfx/gl/gl_implementation.h" @@ -12,12 +16,6 @@ namespace gfx { namespace { -typedef void* (GL_BINDING_CALL *GetProcAddressProc)(const char* name); - -GLImplementation g_gl_implementation = kGLImplementationNone; -std::vector<HMODULE> g_modules; -static GetProcAddressProc g_get_proc_address; - void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) { glClearDepthf(static_cast<GLclampf>(depth)); } @@ -33,81 +31,105 @@ bool InitializeGLBindings(GLImplementation implementation) { // Prevent reinitialization with a different implementation. Once the gpu // unit tests have initialized with kGLImplementationMock, we don't want to // later switch to another GL implementation. - if (g_gl_implementation != kGLImplementationNone) + if (GetGLImplementation() != kGLImplementationNone) return true; - HMODULE module; switch (implementation) { - case kGLImplementationOSMesaGL: - // When using OSMesa, just use OSMesaGetProcAddress to find entry points. - module = LoadLibraryA("osmesa.dll"); - if (!module) + case kGLImplementationOSMesaGL: { + FilePath exe_path; + if (!PathService::Get(base::DIR_EXE, &exe_path)) + return false; + + base::NativeLibrary library = base::LoadNativeLibrary( + exe_path.Append(L"osmesa.dll")); + if (!library) { + LOG(INFO) << "osmesa.dll not found"; return false; + } - g_gl_implementation = kGLImplementationOSMesaGL; + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + library, "OSMesaGetProcAddress")); - g_get_proc_address = reinterpret_cast<GetProcAddressProc>( - GetProcAddress(module, "OSMesaGetProcAddress")); - DCHECK(g_get_proc_address); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationOSMesaGL); InitializeGLBindingsGL(); InitializeGLBindingsOSMESA(); break; + } + case kGLImplementationEGLGLES2: { + FilePath exe_path; + if (!PathService::Get(base::DIR_EXE, &exe_path)) + return false; - case kGLImplementationEGLGLES2: // When using EGL, first try eglGetProcAddress and then Windows // GetProcAddress on both the EGL and GLES2 DLLs. - module = LoadLibraryA("libegl.dll"); - if (!module) + base::NativeLibrary egl_library = base::LoadNativeLibrary( + exe_path.Append(L"libegl.dll")); + if (!egl_library) { + LOG(INFO) << "libegl.dll not found."; return false; + } + + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + egl_library, "eglGetProcAddress")); + + base::NativeLibrary gles_library = base::LoadNativeLibrary( + exe_path.Append(L"libglesv2.dll")); + if (!gles_library) { + base::UnloadNativeLibrary(egl_library); + LOG(ERROR) << "libglesv2.dll not found"; + return false; + } - g_gl_implementation = kGLImplementationEGLGLES2; - - g_get_proc_address = reinterpret_cast<GetProcAddressProc>( - GetProcAddress(module, "eglGetProcAddress")); - DCHECK(g_get_proc_address); - - g_modules.push_back(module); - - module = LoadLibraryA("libglesv2.dll"); - DCHECK(module); - - g_modules.push_back(module); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(egl_library); + AddGLNativeLibrary(gles_library); + SetGLImplementation(kGLImplementationEGLGLES2); InitializeGLBindingsGL(); InitializeGLBindingsEGL(); - // These two functions take single precision float ranther than double + // These two functions take single precision float rather than double // precision float parameters in GLES. ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf; ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef; break; - - case kGLImplementationDesktopGL: + } + case kGLImplementationDesktopGL: { // When using Windows OpenGL, first try wglGetProcAddress and then // Windows GetProcAddress. - module = LoadLibraryA("opengl32.dll"); - if (!module) + base::NativeLibrary library = base::LoadNativeLibrary( + FilePath(L"opengl32.dll")); + if (!library) { + LOG(INFO) << "opengl32.dll not found"; return false; + } - g_gl_implementation = kGLImplementationDesktopGL; - - g_get_proc_address = reinterpret_cast<GetProcAddressProc>( - GetProcAddress(module, "wglGetProcAddress")); - DCHECK(g_get_proc_address); + GLGetProcAddressProc get_proc_address = + reinterpret_cast<GLGetProcAddressProc>( + base::GetFunctionPointerFromNativeLibrary( + library, "wglGetProcAddress")); - g_modules.push_back(module); + SetGLGetProcAddressProc(get_proc_address); + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationDesktopGL); InitializeGLBindingsGL(); InitializeGLBindingsWGL(); break; - - case kGLImplementationMockGL: - g_get_proc_address = GetMockGLProcAddress; - g_gl_implementation = kGLImplementationMockGL; + } + case kGLImplementationMockGL: { + SetGLGetProcAddressProc(GetMockGLProcAddress); + SetGLImplementation(kGLImplementationMockGL); InitializeGLBindingsGL(); break; - + } default: return false; } @@ -115,26 +137,4 @@ bool InitializeGLBindings(GLImplementation implementation) { return true; } -GLImplementation GetGLImplementation() { - return g_gl_implementation; -} - -void* GetGLProcAddress(const char* name) { - DCHECK(g_gl_implementation != kGLImplementationNone); - - if (g_get_proc_address) { - void* proc = g_get_proc_address(name); - if (proc) - return proc; - } - - for (size_t i = 0; i < g_modules.size(); ++i) { - void* proc = GetProcAddress(g_modules[i], name); - if (proc) - return proc; - } - - return NULL; -} - } // namespace gfx |