Remove the dependency on OpenGL32.lib by loading all WGL functions.
BUG=angle:879
Change-Id: I1a10a86b710cb0c76be1907136345bcac078da4d
Reviewed-on: https://chromium-review.googlesource.com/249740
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
index eb7760d..5c53f3f 100644
--- a/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
+++ b/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -12,6 +12,7 @@
#include "libANGLE/Config.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/SurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
@@ -22,27 +23,12 @@
namespace rx
{
-template <typename T>
-static T GetWGLProcAddress(HMODULE glModule, const std::string &name)
-{
- T proc = reinterpret_cast<T>(wglGetProcAddress(name.c_str()));
- if (proc)
- {
- return proc;
- }
-
- return reinterpret_cast<T>(GetProcAddress(glModule, name.c_str()));
-}
-
DisplayWGL::DisplayWGL()
: DisplayGL(),
mOpenGLModule(nullptr),
mGLVersionMajor(0),
mGLVersionMinor(0),
- mExtensions(),
- mCreateContextAttribsARB(nullptr),
- mGetPixelFormatAttribivARB(nullptr),
- mSwapIntervalEXT(nullptr),
+ mFunctionsWGL(nullptr),
mWindowClass(0),
mWindow(nullptr),
mDeviceContext(nullptr),
@@ -86,6 +72,9 @@
return egl::Error(EGL_NOT_INITIALIZED, "Failed to load OpenGL library.");
}
+ mFunctionsWGL = new FunctionsWGL();
+ mFunctionsWGL->intialize(mOpenGLModule, nullptr);
+
// WGL can't grab extensions until it creates a context because it needs to load the driver's DLLs first.
// Create a dummy context to load the driver and determine which GL versions are available.
@@ -145,13 +134,13 @@
return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
}
- HGLRC dummyWGLContext = wglCreateContext(dummyDeviceContext);
+ HGLRC dummyWGLContext = mFunctionsWGL->createContext(dummyDeviceContext);
if (!dummyDeviceContext)
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the dummy OpenGL window.");
}
- if (!wglMakeCurrent(dummyDeviceContext, dummyWGLContext))
+ if (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext))
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current.");
}
@@ -173,45 +162,12 @@
GLuint maxGLVersionMajor = dummyGLVersionString[0] - '0';
GLuint maxGLVersionMinor = dummyGLVersionString[2] - '0';
- // Grab WGL extensions
- PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT = GetWGLProcAddress<PFNWGLGETEXTENSIONSSTRINGEXTPROC>(mOpenGLModule, "wglGetExtensionsStringEXT");
- PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB = GetWGLProcAddress<PFNWGLGETEXTENSIONSSTRINGARBPROC>(mOpenGLModule, "wglGetExtensionsStringARB");
- const char *extensions = "";
- if (getExtensionStringEXT)
- {
- extensions = getExtensionStringEXT();
- }
- else if (getExtensionStringARB)
- {
- extensions = getExtensionStringARB(dummyDeviceContext);
- }
-
- // Put all the extensions into a vector
- std::stringstream stream(extensions);
- std::string extension;
- while (std::getline(stream, extension, ' '))
- {
- mExtensions.push_back(extension);
- }
-
- if (isWGLExtensionSupported("WGL_ARB_create_context"))
- {
- mCreateContextAttribsARB = GetWGLProcAddress<PFNWGLCREATECONTEXTATTRIBSARBPROC>(mOpenGLModule, "wglCreateContextAttribsARB");
- }
-
- if (isWGLExtensionSupported("WGL_ARB_pixel_format"))
- {
- mGetPixelFormatAttribivARB = GetWGLProcAddress<PFNWGLGETPIXELFORMATATTRIBIVARBPROC>(mOpenGLModule, "wglGetPixelFormatAttribivARB");
- }
-
- if (isWGLExtensionSupported("WGL_EXT_swap_control"))
- {
- mSwapIntervalEXT = GetWGLProcAddress<PFNWGLSWAPINTERVALEXTPROC>(mOpenGLModule, "wglSwapIntervalEXT");
- }
+ // Reinitialize the wgl functions to grab the extensions
+ mFunctionsWGL->intialize(mOpenGLModule, dummyDeviceContext);
// Destroy the dummy window and context
- wglMakeCurrent(dummyDeviceContext, NULL);
- wglDeleteContext(dummyWGLContext);
+ mFunctionsWGL->makeCurrent(dummyDeviceContext, NULL);
+ mFunctionsWGL->deleteContext(dummyWGLContext);
ReleaseDC(dummyWindow, dummyDeviceContext);
DestroyWindow(dummyWindow);
@@ -253,7 +209,7 @@
return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
}
- if (mCreateContextAttribsARB)
+ if (mFunctionsWGL->createContextAttribsARB)
{
int flags = 0;
// TODO: also allow debug contexts through a user flag
@@ -294,7 +250,7 @@
contextCreationAttibutes.push_back(0);
contextCreationAttibutes.push_back(0);
- mWGLContext = mCreateContextAttribsARB(mDeviceContext, NULL, &contextCreationAttibutes[0]);
+ mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttibutes[0]);
}
// If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
@@ -304,7 +260,7 @@
mGLVersionMajor = maxGLVersionMajor;
mGLVersionMinor = maxGLVersionMinor;
- mWGLContext = wglCreateContext(mDeviceContext);
+ mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
}
if (!mWGLContext)
@@ -312,7 +268,7 @@
return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the intermediate OpenGL window.");
}
- if (!wglMakeCurrent(mDeviceContext, mWGLContext))
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current.");
}
@@ -328,8 +284,8 @@
{
DisplayGL::terminate();
- wglMakeCurrent(mDeviceContext, NULL);
- wglDeleteContext(mWGLContext);
+ mFunctionsWGL->makeCurrent(mDeviceContext, NULL);
+ mFunctionsWGL->deleteContext(mWGLContext);
mWGLContext = NULL;
ReleaseDC(mWindow, mDeviceContext);
@@ -341,18 +297,17 @@
UnregisterClassA(reinterpret_cast<const char*>(mWindowClass), NULL);
mWindowClass = NULL;
+ SafeDelete(mFunctionsWGL);
+
FreeLibrary(mOpenGLModule);
- mExtensions.clear();
- mCreateContextAttribsARB = NULL;
- mGetPixelFormatAttribivARB = NULL;
- mSwapIntervalEXT = NULL;
+ mOpenGLModule = nullptr;
}
egl::Error DisplayWGL::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window,
const egl::AttributeMap &attribs, SurfaceImpl **outSurface)
{
SurfaceWGL *surface = new SurfaceWGL(mDisplay, configuration, EGL_FALSE, EGL_FALSE, EGL_NO_TEXTURE, EGL_NO_TEXTURE,
- window, mWindowClass, mPixelFormat, mWGLContext, mSwapIntervalEXT);
+ window, mWindowClass, mPixelFormat, mWGLContext, mFunctionsWGL);
egl::Error error = surface->initialize();
if (error.isError())
{
@@ -395,7 +350,7 @@
int minSwapInterval = 1;
int maxSwapInterval = 1;
- if (mSwapIntervalEXT)
+ if (mFunctionsWGL->swapIntervalEXT)
{
// No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number
minSwapInterval = 0;
@@ -488,9 +443,4 @@
outCaps->textureNPOT = true;
}
-bool DisplayWGL::isWGLExtensionSupported(const std::string &name) const
-{
- return std::find(mExtensions.begin(), mExtensions.end(), name) != mExtensions.end();
-}
-
}
diff --git a/src/libANGLE/renderer/gl/wgl/DisplayWGL.h b/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
index 1f0fe8a..c9d45eb 100644
--- a/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
+++ b/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
@@ -16,6 +16,8 @@
namespace rx
{
+class FunctionsWGL;
+
class DisplayWGL : public DisplayGL
{
public:
@@ -50,19 +52,11 @@
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override;
- bool isWGLExtensionSupported(const std::string &name) const;
-
HMODULE mOpenGLModule;
GLuint mGLVersionMajor;
GLuint mGLVersionMinor;
- std::vector<std::string> mExtensions;
-
- PFNWGLCREATECONTEXTATTRIBSARBPROC mCreateContextAttribsARB;
-
- PFNWGLGETPIXELFORMATATTRIBIVARBPROC mGetPixelFormatAttribivARB;
-
- PFNWGLSWAPINTERVALEXTPROC mSwapIntervalEXT;
+ FunctionsWGL *mFunctionsWGL;
ATOM mWindowClass;
HWND mWindow;
diff --git a/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
new file mode 100644
index 0000000..a77369a
--- /dev/null
+++ b/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsWGL.h: Implements the FuntionsWGL class.
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+typedef PROC(WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR);
+
+template <typename T>
+static void GetWGLProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+ const std::string &procName, T *outProcAddress)
+{
+ T proc = nullptr;
+ if (getProcAddressWGL)
+ {
+ proc = reinterpret_cast<T>(getProcAddressWGL(procName.c_str()));
+ }
+
+ if (!proc)
+ {
+ proc = reinterpret_cast<T>(GetProcAddress(glModule, procName.c_str()));
+ }
+
+ *outProcAddress = proc;
+}
+
+template <typename T>
+static void GetWGLExtensionProcAddress(HMODULE glModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL,
+ const std::string &extensions, const std::string &extensionName,
+ const std::string &procName, T *outProcAddress)
+{
+ T proc = nullptr;
+ if (extensions.find(extensionName) != std::string::npos)
+ {
+ GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc);
+ }
+
+ *outProcAddress = proc;
+}
+
+FunctionsWGL::FunctionsWGL()
+ : createContext(nullptr),
+ deleteContext(nullptr),
+ makeCurrent(nullptr),
+ createContextAttribsARB(nullptr),
+ getPixelFormatAttribivARB(nullptr),
+ swapIntervalEXT(nullptr)
+{
+}
+
+void FunctionsWGL::intialize(HMODULE glModule, HDC context)
+{
+ // First grab the wglGetProcAddress function from the gl module
+ PFNWGLGETPROCADDRESSPROC getProcAddressWGL = nullptr;
+ GetWGLProcAddress(glModule, nullptr, "wglGetProcAddress", &getProcAddressWGL);
+
+ // Load the core wgl functions
+ GetWGLProcAddress(glModule, getProcAddressWGL, "wglCreateContext", &createContext);
+ GetWGLProcAddress(glModule, getProcAddressWGL, "wglDeleteContext", &deleteContext);
+ GetWGLProcAddress(glModule, getProcAddressWGL, "wglMakeCurrent", &makeCurrent);
+
+ // Load extension string getter functions
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT = nullptr;
+ GetWGLProcAddress(glModule, getProcAddressWGL, "wglGetExtensionsStringEXT", &getExtensionStringEXT);
+
+ PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB = nullptr;
+ GetWGLProcAddress(glModule, getProcAddressWGL, "wglGetExtensionsStringARB", &getExtensionStringARB);
+
+ std::string extensions = "";
+ if (getExtensionStringEXT)
+ {
+ extensions = getExtensionStringEXT();
+ }
+ else if (getExtensionStringARB && context)
+ {
+ extensions = getExtensionStringARB(context);
+ }
+
+ // Load the wgl extension functions by checking if the context supports the extension first
+ GetWGLExtensionProcAddress(glModule, getProcAddressWGL, extensions, "WGL_ARB_create_context", "wglCreateContextAttribsARB", &createContextAttribsARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddressWGL, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribivARB", &getPixelFormatAttribivARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddressWGL, extensions, "WGL_EXT_swap_control", "wglSwapIntervalEXT", &swapIntervalEXT);
+}
+
+}
diff --git a/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
new file mode 100644
index 0000000..b95e692
--- /dev/null
+++ b/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
@@ -0,0 +1,44 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FunctionsWGL.h: Defines the FuntionsWGL class to contain loaded WGL functions
+
+#include "common/debug.h"
+#include "common/platform.h"
+#include "libANGLE/Error.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+typedef HGLRC(WINAPI *PFNWGLCREATECONTEXTPROC)(HDC);
+typedef BOOL(WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC);
+typedef BOOL(WINAPI *PFNWGLMAKECURRENTPROC)(HDC, HGLRC);
+
+class FunctionsWGL
+{
+ public:
+ FunctionsWGL();
+
+ // Loads all available wgl functions, may be called multiple times
+ void intialize(HMODULE glModule, HDC context);
+
+ // Base WGL functions
+ PFNWGLCREATECONTEXTPROC createContext;
+ PFNWGLDELETECONTEXTPROC deleteContext;
+ PFNWGLMAKECURRENTPROC makeCurrent;
+
+ // Extension functions, may be NULL
+ PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribsARB;
+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribivARB;
+ PFNWGLSWAPINTERVALEXTPROC swapIntervalEXT;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FunctionsWGL);
+};
+
+}
diff --git a/src/libANGLE/renderer/gl/wgl/SurfaceWGL.cpp b/src/libANGLE/renderer/gl/wgl/SurfaceWGL.cpp
index a001968..9c72e72 100644
--- a/src/libANGLE/renderer/gl/wgl/SurfaceWGL.cpp
+++ b/src/libANGLE/renderer/gl/wgl/SurfaceWGL.cpp
@@ -9,6 +9,7 @@
#include "libANGLE/renderer/gl/wgl/SurfaceWGL.h"
#include "common/debug.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
namespace rx
@@ -16,7 +17,7 @@
SurfaceWGL::SurfaceWGL(egl::Display *display, const egl::Config *config, EGLint fixedSize, EGLint postSubBufferSupported,
EGLenum textureFormat, EGLenum textureType, EGLNativeWindowType window, ATOM windowClass, int pixelFormat,
- HGLRC wglContext, PFNWGLSWAPINTERVALEXTPROC swapIntervalExt)
+ HGLRC wglContext, const FunctionsWGL *functions)
: SurfaceGL(display, config, fixedSize, postSubBufferSupported, textureFormat, textureType),
mWindowClass(windowClass),
mPixelFormat(pixelFormat),
@@ -24,7 +25,7 @@
mParentWindow(window),
mChildWindow(nullptr),
mChildDeviceContext(nullptr),
- mSwapIntervalEXT(swapIntervalExt)
+ mFunctionsWGL(functions)
{
}
@@ -34,14 +35,12 @@
mPixelFormat = 0;
mShareWGLContext = nullptr;
- wglMakeCurrent(mChildDeviceContext, nullptr);
+ mFunctionsWGL->makeCurrent(mChildDeviceContext, nullptr);
ReleaseDC(mChildWindow, mChildDeviceContext);
mChildDeviceContext = nullptr;
DestroyWindow(mChildWindow);
mChildWindow = nullptr;
-
- mSwapIntervalEXT = nullptr;
}
SurfaceWGL *SurfaceWGL::makeSurfaceWGL(SurfaceImpl *impl)
@@ -94,7 +93,7 @@
egl::Error SurfaceWGL::makeCurrent()
{
- if (!wglMakeCurrent(mChildDeviceContext, mShareWGLContext))
+ if (!mFunctionsWGL->makeCurrent(mChildDeviceContext, mShareWGLContext))
{
// TODO: What error type here?
return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
@@ -154,9 +153,9 @@
void SurfaceWGL::setSwapInterval(EGLint interval)
{
- if (mSwapIntervalEXT)
+ if (mFunctionsWGL->swapIntervalEXT)
{
- mSwapIntervalEXT(interval);
+ mFunctionsWGL->swapIntervalEXT(interval);
}
}
diff --git a/src/libANGLE/renderer/gl/wgl/SurfaceWGL.h b/src/libANGLE/renderer/gl/wgl/SurfaceWGL.h
index 4d33554..c94363d 100644
--- a/src/libANGLE/renderer/gl/wgl/SurfaceWGL.h
+++ b/src/libANGLE/renderer/gl/wgl/SurfaceWGL.h
@@ -16,12 +16,14 @@
namespace rx
{
+class FunctionsWGL;
+
class SurfaceWGL : public SurfaceGL
{
public:
SurfaceWGL(egl::Display *display, const egl::Config *config, EGLint fixedSize, EGLint postSubBufferSupported,
EGLenum textureFormat, EGLenum textureType, EGLNativeWindowType window, ATOM windowClass, int pixelFormat,
- HGLRC wglContext, PFNWGLSWAPINTERVALEXTPROC swapIntervalExt);
+ HGLRC wglContext, const FunctionsWGL *functions);
~SurfaceWGL() override;
@@ -54,7 +56,7 @@
HWND mChildWindow;
HDC mChildDeviceContext;
- PFNWGLSWAPINTERVALEXTPROC mSwapIntervalEXT;
+ const FunctionsWGL *mFunctionsWGL;
};
}
diff --git a/src/libGLESv2.gypi b/src/libGLESv2.gypi
index b3f9167..b7266be 100644
--- a/src/libGLESv2.gypi
+++ b/src/libGLESv2.gypi
@@ -398,6 +398,8 @@
[
'libANGLE/renderer/gl/wgl/DisplayWGL.cpp',
'libANGLE/renderer/gl/wgl/DisplayWGL.h',
+ 'libANGLE/renderer/gl/wgl/FunctionsWGL.cpp',
+ 'libANGLE/renderer/gl/wgl/FunctionsWGL.h',
'libANGLE/renderer/gl/wgl/SurfaceWGL.cpp',
'libANGLE/renderer/gl/wgl/SurfaceWGL.h',
'libANGLE/renderer/gl/wgl/wgl_utils.cpp',
@@ -606,19 +608,6 @@
[
'ANGLE_ENABLE_OPENGL',
],
- 'link_settings':
- {
- 'msvs_settings':
- {
- 'VCLinkerTool':
- {
- 'AdditionalDependencies':
- [
- 'OpenGL32.lib',
- ],
- },
- },
- },
'conditions':
[
['OS=="win"',