Commit 12892c91 by Geoff Lang

Remove the dependency on OpenGL32.lib by loading all WGL functions.

BUG=angle:879 Change-Id: I1a10a86b710cb0c76be1907136345bcac078da4d Reviewed-on: https://chromium-review.googlesource.com/249740Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent d12971af
......@@ -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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
mGLVersionMajor = maxGLVersionMajor;
mGLVersionMinor = maxGLVersionMinor;
mWGLContext = wglCreateContext(mDeviceContext);
mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
}
if (!mWGLContext)
......@@ -312,7 +268,7 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
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 @@ void DisplayWGL::terminate()
{
DisplayGL::terminate();
wglMakeCurrent(mDeviceContext, NULL);
wglDeleteContext(mWGLContext);
mFunctionsWGL->makeCurrent(mDeviceContext, NULL);
mFunctionsWGL->deleteContext(mWGLContext);
mWGLContext = NULL;
ReleaseDC(mWindow, mDeviceContext);
......@@ -341,18 +297,17 @@ void DisplayWGL::terminate()
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 @@ egl::ConfigSet DisplayWGL::generateConfigs() const
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 @@ void DisplayWGL::generateCaps(egl::Caps *outCaps) const
outCaps->textureNPOT = true;
}
bool DisplayWGL::isWGLExtensionSupported(const std::string &name) const
{
return std::find(mExtensions.begin(), mExtensions.end(), name) != mExtensions.end();
}
}
......@@ -16,6 +16,8 @@
namespace rx
{
class FunctionsWGL;
class DisplayWGL : public DisplayGL
{
public:
......@@ -50,19 +52,11 @@ class DisplayWGL : public DisplayGL
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;
......
//
// 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);
}
}
//
// 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);
};
}
......@@ -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 @@ namespace rx
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 @@ SurfaceWGL::SurfaceWGL(egl::Display *display, const egl::Config *config, EGLint
mParentWindow(window),
mChildWindow(nullptr),
mChildDeviceContext(nullptr),
mSwapIntervalEXT(swapIntervalExt)
mFunctionsWGL(functions)
{
}
......@@ -34,14 +35,12 @@ SurfaceWGL::~SurfaceWGL()
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::initialize()
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 @@ egl::Error SurfaceWGL::releaseTexImage(EGLint buffer)
void SurfaceWGL::setSwapInterval(EGLint interval)
{
if (mSwapIntervalEXT)
if (mFunctionsWGL->swapIntervalEXT)
{
mSwapIntervalEXT(interval);
mFunctionsWGL->swapIntervalEXT(interval);
}
}
......
......@@ -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 @@ class SurfaceWGL : public SurfaceGL
HWND mChildWindow;
HDC mChildDeviceContext;
PFNWGLSWAPINTERVALEXTPROC mSwapIntervalEXT;
const FunctionsWGL *mFunctionsWGL;
};
}
......
......@@ -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"',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment