summaryrefslogtreecommitdiffstats
path: root/app/gfx
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 20:47:04 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 20:47:04 +0000
commit30aa5c1ab237fa0940b04ffd78cc9033d9ca3afe (patch)
treebcc87f53bf61028f8cd3fcf27d4218f287ad2155 /app/gfx
parent6164c8d2a67aa8346b9f7735d849f4ee4f1c63cd (diff)
downloadchromium_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.h2
-rw-r--r--app/gfx/gl/gl_context_egl.cc11
-rw-r--r--app/gfx/gl/gl_context_egl.h2
-rw-r--r--app/gfx/gl/gl_context_linux.cc233
-rw-r--r--app/gfx/gl/gl_context_mac.cc32
-rw-r--r--app/gfx/gl/gl_context_osmesa.cc13
-rw-r--r--app/gfx/gl/gl_context_osmesa.h2
-rw-r--r--app/gfx/gl/gl_context_win.cc196
-rw-r--r--app/gfx/gl/gl_implementation.cc130
-rw-r--r--app/gfx/gl/gl_implementation.h30
-rw-r--r--app/gfx/gl/gl_implementation_linux.cc156
-rw-r--r--app/gfx/gl/gl_implementation_mac.cc88
-rw-r--r--app/gfx/gl/gl_implementation_win.cc138
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