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"',