summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/libANGLE/renderer/gl/wgl
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /gfx/angle/src/libANGLE/renderer/gl/wgl
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'gfx/angle/src/libANGLE/renderer/gl/wgl')
-rw-r--r--gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp384
-rw-r--r--gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h86
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp553
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h106
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp741
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h112
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp181
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h94
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp196
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h74
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp178
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h64
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h43
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp85
-rwxr-xr-xgfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h32
15 files changed, 2929 insertions, 0 deletions
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
new file mode 100644
index 000000000..f19e8fdf3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp
@@ -0,0 +1,384 @@
+//
+// 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.
+//
+
+// D3DTextureSurfaceWGL.cpp: WGL implementation of egl::Surface for D3D texture interop.
+
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace
+{
+
+egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
+ size_t *width,
+ size_t *height,
+ IUnknown **object,
+ IUnknown **device)
+{
+ IUnknown *buffer = static_cast<IUnknown *>(clientBuffer);
+
+ IDirect3DTexture9 *texture9 = nullptr;
+ ID3D11Texture2D *texture11 = nullptr;
+ if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
+ {
+ D3D11_TEXTURE2D_DESC textureDesc;
+ texture11->GetDesc(&textureDesc);
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (textureDesc.Format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ break;
+
+ default:
+ SafeRelease(texture11);
+ return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ textureDesc.Format);
+ }
+
+ ID3D11Device *d3d11Device = nullptr;
+ texture11->GetDevice(&d3d11Device);
+ if (d3d11Device == nullptr)
+ {
+ SafeRelease(texture11);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query the D3D11 device from the client buffer.");
+ }
+
+ if (width)
+ {
+ *width = textureDesc.Width;
+ }
+ if (height)
+ {
+ *height = textureDesc.Height;
+ }
+
+ if (device)
+ {
+ *device = d3d11Device;
+ }
+ else
+ {
+ SafeRelease(d3d11Device);
+ }
+
+ if (object)
+ {
+ *object = texture11;
+ }
+ else
+ {
+ SafeRelease(texture11);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+ }
+ else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
+ {
+ D3DSURFACE_DESC surfaceDesc;
+ if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc)))
+ {
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query description of the D3D9 surface.");
+ }
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (surfaceDesc.Format)
+ {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ break;
+
+ default:
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
+ surfaceDesc.Format);
+ }
+
+ if (width)
+ {
+ *width = surfaceDesc.Width;
+ }
+ if (height)
+ {
+ *height = surfaceDesc.Height;
+ }
+
+ IDirect3DDevice9 *d3d9Device = nullptr;
+ HRESULT result = texture9->GetDevice(&d3d9Device);
+ if (FAILED(result))
+ {
+ SafeRelease(texture9);
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Could not query the D3D9 device from the client buffer.");
+ }
+
+ if (device)
+ {
+ *device = d3d9Device;
+ }
+ else
+ {
+ SafeRelease(d3d9Device);
+ }
+
+ if (object)
+ {
+ *object = texture9;
+ }
+ else
+ {
+ SafeRelease(texture9);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+ }
+ else
+ {
+ return egl::Error(EGL_BAD_PARAMETER,
+ "Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D.");
+ }
+}
+
+} // anonymous namespace
+
+D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLClientBuffer clientBuffer,
+ DisplayWGL *display,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL)
+ : SurfaceGL(state, renderer),
+ mClientBuffer(clientBuffer),
+ mRenderer(renderer),
+ mDisplay(display),
+ mStateManager(renderer->getStateManager()),
+ mWorkarounds(renderer->getWorkarounds()),
+ mFunctionsGL(functionsGL),
+ mFunctionsWGL(functionsWGL),
+ mWGLContext(wglContext),
+ mDeviceContext(deviceContext),
+ mWidth(0),
+ mHeight(0),
+ mDeviceHandle(nullptr),
+ mObject(nullptr),
+ mBoundObjectTextureHandle(nullptr),
+ mBoundObjectRenderbufferHandle(nullptr),
+ mRenderbufferID(0),
+ mFramebufferID(0)
+{
+}
+
+D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
+{
+ ASSERT(mBoundObjectTextureHandle == nullptr);
+
+ SafeRelease(mObject);
+
+ if (mDeviceHandle)
+ {
+ if (mBoundObjectRenderbufferHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectRenderbufferHandle);
+ mBoundObjectRenderbufferHandle = nullptr;
+ }
+ mStateManager->deleteRenderbuffer(mRenderbufferID);
+
+ if (mBoundObjectTextureHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle);
+ mBoundObjectTextureHandle = nullptr;
+ }
+
+ // GL framebuffer is deleted by the default framebuffer object
+ mFramebufferID = 0;
+
+ mDisplay->releaseD3DDevice(mDeviceHandle);
+ mDeviceHandle = nullptr;
+ }
+}
+
+egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer)
+{
+ return GetD3DTextureInfo(clientBuffer, nullptr, nullptr, nullptr, nullptr);
+}
+
+egl::Error D3DTextureSurfaceWGL::initialize()
+{
+ IUnknown *device = nullptr;
+ ANGLE_TRY(GetD3DTextureInfo(mClientBuffer, &mWidth, &mHeight, &mObject, &device));
+
+ ASSERT(device != nullptr);
+ egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle);
+ SafeRelease(device);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mFunctionsGL->genRenderbuffers(1, &mRenderbufferID);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
+ mBoundObjectRenderbufferHandle = mFunctionsWGL->dxRegisterObjectNV(
+ mDeviceHandle, mObject, mRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+ if (mBoundObjectRenderbufferHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ mRenderbufferID);
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ // TODO(geofflang): What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::unMakeCurrent()
+{
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(mBoundObjectTextureHandle == nullptr);
+
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+ GLuint textureID = textureGL->getTextureID();
+
+ mBoundObjectTextureHandle = mFunctionsWGL->dxRegisterObjectNV(
+ mDeviceHandle, mObject, textureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ if (mBoundObjectTextureHandle == nullptr)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error D3DTextureSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ ASSERT(mBoundObjectTextureHandle != nullptr);
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+
+ if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+ HRESULT_CODE(error));
+ }
+ mBoundObjectTextureHandle = nullptr;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void D3DTextureSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ UNIMPLEMENTED();
+}
+
+EGLint D3DTextureSurfaceWGL::getWidth() const
+{
+ return static_cast<EGLint>(mWidth);
+}
+
+EGLint D3DTextureSurfaceWGL::getHeight() const
+{
+ return static_cast<EGLint>(mHeight);
+}
+
+EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const
+{
+ return EGL_FALSE;
+}
+
+EGLint D3DTextureSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data)
+{
+ return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+ mRenderer->getBlitter(), mStateManager);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
new file mode 100644
index 000000000..8fb1d4003
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h
@@ -0,0 +1,86 @@
+
+// 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.
+//
+
+// D3DTextureSurfaceWGL.h: WGL implementation of egl::Surface for D3D texture interop.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class D3DTextureSurfaceWGL : public SurfaceGL
+{
+ public:
+ D3DTextureSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLClientBuffer clientBuffer,
+ DisplayWGL *display,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL);
+ ~D3DTextureSurfaceWGL() override;
+
+ static egl::Error ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer);
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+ egl::Error unMakeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+ private:
+ EGLClientBuffer mClientBuffer;
+
+ RendererGL *mRenderer;
+
+ DisplayWGL *mDisplay;
+ StateManagerGL *mStateManager;
+ const WorkaroundsGL &mWorkarounds;
+ const FunctionsGL *mFunctionsGL;
+ const FunctionsWGL *mFunctionsWGL;
+
+ HGLRC mWGLContext;
+ HDC mDeviceContext;
+
+ size_t mWidth;
+ size_t mHeight;
+
+ HANDLE mDeviceHandle;
+ IUnknown *mObject;
+ HANDLE mBoundObjectTextureHandle;
+ HANDLE mBoundObjectRenderbufferHandle;
+
+ GLuint mRenderbufferID;
+ GLuint mFramebufferID;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
new file mode 100755
index 000000000..7c5214e82
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp
@@ -0,0 +1,553 @@
+//
+// 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.
+//
+
+// DXGISwapChainWindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/gl/FramebufferGL.h"
+#include "libANGLE/renderer/gl/TextureGL.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DXGISwapChainWindowSurfaceWGL::DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ ID3D11Device *device,
+ HANDLE deviceHandle,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL,
+ EGLint orientation)
+ : SurfaceGL(state, renderer),
+ mWindow(window),
+ mStateManager(renderer->getStateManager()),
+ mWorkarounds(renderer->getWorkarounds()),
+ mRenderer(renderer),
+ mFunctionsGL(functionsGL),
+ mFunctionsWGL(functionsWGL),
+ mDevice(device),
+ mDeviceHandle(deviceHandle),
+ mWGLDevice(deviceContext),
+ mWGLContext(wglContext),
+ mSwapChainFormat(DXGI_FORMAT_UNKNOWN),
+ mSwapChainFlags(0),
+ mDepthBufferFormat(GL_NONE),
+ mFirstSwap(true),
+ mSwapChain(nullptr),
+ mSwapChain1(nullptr),
+ mColorRenderbufferID(0),
+ mRenderbufferBufferHandle(nullptr),
+ mDepthRenderbufferID(0),
+ mFramebufferID(0),
+ mTextureID(0),
+ mTextureHandle(nullptr),
+ mWidth(0),
+ mHeight(0),
+ mSwapInterval(1),
+ mOrientation(orientation)
+{
+}
+
+DXGISwapChainWindowSurfaceWGL::~DXGISwapChainWindowSurfaceWGL()
+{
+ if (mRenderbufferBufferHandle != nullptr)
+ {
+ mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mRenderbufferBufferHandle);
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+ }
+
+ if (mColorRenderbufferID != 0)
+ {
+ mStateManager->deleteRenderbuffer(mColorRenderbufferID);
+ mColorRenderbufferID = 0;
+ }
+
+ if (mDepthRenderbufferID != 0)
+ {
+ mStateManager->deleteRenderbuffer(mDepthRenderbufferID);
+ mDepthRenderbufferID = 0;
+ }
+
+ SafeRelease(mSwapChain);
+ SafeRelease(mSwapChain1);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::initialize()
+{
+ if (mOrientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE)
+ {
+ // TODO(geofflang): Support the orientation extensions fully. Currently only inverting Y is
+ // supported. To support all orientations, an intermediate framebuffer will be needed with
+ // a blit before swap.
+ return egl::Error(EGL_BAD_ATTRIBUTE,
+ "DXGISwapChainWindowSurfaceWGL requires an orientation of "
+ "EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE.");
+ }
+
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+ }
+ mWidth = rect.right - rect.left;
+ mHeight = rect.bottom - rect.top;
+
+ mSwapChainFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
+ mSwapChainFlags = 0;
+ mDepthBufferFormat = GL_DEPTH24_STENCIL8;
+
+ mFunctionsGL->genFramebuffers(1, &mFramebufferID);
+ mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+ mFunctionsGL->genRenderbuffers(1, &mDepthRenderbufferID);
+
+ return createSwapChain();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mWGLDevice, mWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::swap()
+{
+ mFunctionsGL->flush();
+
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = mSwapChain->Present(mSwapInterval, 0);
+ mFirstSwap = false;
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+ }
+
+ return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::postSubBuffer(EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ ASSERT(mSwapChain1 != nullptr);
+
+ mFunctionsGL->flush();
+
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = S_OK;
+ if (mFirstSwap)
+ {
+ result = mSwapChain1->Present(mSwapInterval, 0);
+ mFirstSwap = false;
+ }
+ else
+ {
+ RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+ static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+ DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+ result = mSwapChain1->Present1(mSwapInterval, 0, &params);
+ }
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to present swap chain, result: 0x%X", result);
+ }
+
+ return checkForResize();
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNREACHABLE();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(mTextureHandle == nullptr);
+
+ const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
+ GLuint textureID = textureGL->getTextureID();
+
+ ID3D11Texture2D *colorBuffer = nullptr;
+ HRESULT result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&colorBuffer));
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+ result);
+ }
+
+ mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, textureID,
+ GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ SafeRelease(colorBuffer);
+ if (mTextureHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+ mTextureHandle = nullptr;
+
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mTextureID = textureID;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ ASSERT(mTextureHandle != nullptr);
+
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mTextureHandle))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unlock D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ mTextureID = 0;
+ mTextureHandle = nullptr;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DXGISwapChainWindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ mSwapInterval = interval;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getWidth() const
+{
+ return static_cast<EGLint>(mWidth);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getHeight() const
+{
+ return static_cast<EGLint>(mHeight);
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::isPostSubBufferSupported() const
+{
+ return mSwapChain1 != nullptr;
+}
+
+EGLint DXGISwapChainWindowSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_DESTROYED;
+}
+
+FramebufferImpl *DXGISwapChainWindowSurfaceWGL::createDefaultFramebuffer(
+ const gl::FramebufferState &data)
+{
+ return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
+ mRenderer->getBlitter(), mStateManager);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::setObjectsLocked(bool locked)
+{
+ if (mRenderbufferBufferHandle == nullptr)
+ {
+ ASSERT(mTextureHandle == nullptr);
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ HANDLE resources[] = {
+ mRenderbufferBufferHandle, mTextureHandle,
+ };
+ GLint count = (mTextureHandle != nullptr) ? 2 : 1;
+
+ if (locked)
+ {
+ if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, count, resources))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+ else
+ {
+ if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, count, resources))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::checkForResize()
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the window size.");
+ }
+
+ size_t newWidth = rect.right - rect.left;
+ size_t newHeight = rect.bottom - rect.top;
+ if (newWidth != mWidth || newHeight != mHeight)
+ {
+ mWidth = newWidth;
+ mHeight = newHeight;
+
+ // TODO(geofflang): Handle resize by resizing the swap chain instead of re-creating it.
+ egl::Error error = createSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+static IDXGIFactory *GetDXGIFactoryFromDevice(ID3D11Device *device)
+{
+ IDXGIDevice *dxgiDevice = nullptr;
+ HRESULT result =
+ device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDevice));
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ IDXGIAdapter *dxgiAdapter = nullptr;
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void **>(&dxgiAdapter));
+ SafeRelease(dxgiDevice);
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ IDXGIFactory *dxgiFactory = nullptr;
+ result =
+ dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void **>(&dxgiFactory));
+ SafeRelease(dxgiAdapter);
+ if (FAILED(result))
+ {
+ return nullptr;
+ }
+
+ return dxgiFactory;
+}
+
+egl::Error DXGISwapChainWindowSurfaceWGL::createSwapChain()
+{
+ egl::Error error = setObjectsLocked(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (mRenderbufferBufferHandle)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mRenderbufferBufferHandle);
+ mRenderbufferBufferHandle = nullptr;
+ }
+
+ // If this surface is bound to a texture, unregister it.
+ bool hadBoundSurface = (mTextureHandle != nullptr);
+ if (hadBoundSurface)
+ {
+ mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mTextureHandle);
+ mTextureHandle = nullptr;
+ }
+
+ IDXGIFactory *dxgiFactory = GetDXGIFactoryFromDevice(mDevice);
+ if (dxgiFactory == nullptr)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to query the DXGIFactory.");
+ }
+
+ IDXGIFactory2 *dxgiFactory2 = nullptr;
+ HRESULT result = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2),
+ reinterpret_cast<void **>(&dxgiFactory2));
+ if (SUCCEEDED(result))
+ {
+ ASSERT(dxgiFactory2 != nullptr);
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.Format = mSwapChainFormat;
+ swapChainDesc.Width = static_cast<UINT>(mWidth);
+ swapChainDesc.Height = static_cast<UINT>(mHeight);
+ swapChainDesc.Format = mSwapChainFormat;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+ swapChainDesc.Flags = mSwapChainFlags;
+
+ result = dxgiFactory2->CreateSwapChainForHwnd(mDevice, mWindow, &swapChainDesc, nullptr,
+ nullptr, &mSwapChain1);
+ SafeRelease(dxgiFactory2);
+ SafeRelease(dxgiFactory);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+ result);
+ }
+
+ mSwapChain = mSwapChain1;
+ mSwapChain->AddRef();
+ }
+ else
+ {
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferDesc.Format = mSwapChainFormat;
+ swapChainDesc.BufferDesc.Width = static_cast<UINT>(mWidth);
+ swapChainDesc.BufferDesc.Height = static_cast<UINT>(mHeight);
+ swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
+ swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.Flags = mSwapChainFlags;
+ swapChainDesc.OutputWindow = mWindow;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ result = dxgiFactory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
+ SafeRelease(dxgiFactory);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create swap chain for window, result: 0x%X",
+ result);
+ }
+ }
+
+ ID3D11Texture2D *colorBuffer = nullptr;
+ result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&colorBuffer));
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query texture from swap chain, result: 0x%X",
+ result);
+ }
+
+ mFunctionsGL->genRenderbuffers(1, &mColorRenderbufferID);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mColorRenderbufferID);
+ mRenderbufferBufferHandle =
+ mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mColorRenderbufferID,
+ GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
+ SafeRelease(colorBuffer);
+ if (mRenderbufferBufferHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+ HRESULT_CODE(GetLastError()));
+ }
+
+ // Rebind the surface to the texture if needed.
+ if (hadBoundSurface)
+ {
+ mTextureHandle = mFunctionsWGL->dxRegisterObjectNV(mDeviceHandle, colorBuffer, mTextureID,
+ GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
+ if (mTextureHandle == nullptr)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%X.",
+ HRESULT_CODE(GetLastError()));
+ }
+ }
+
+ error = setObjectsLocked(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(mFramebufferID != 0);
+ mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
+ mColorRenderbufferID);
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ ASSERT(mDepthRenderbufferID != 0);
+ mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mDepthRenderbufferID);
+ mFunctionsGL->renderbufferStorage(GL_RENDERBUFFER, mDepthBufferFormat,
+ static_cast<GLsizei>(mWidth),
+ static_cast<GLsizei>(mHeight));
+
+ const gl::InternalFormat &depthStencilFormatInfo =
+ gl::GetInternalFormatInfo(mDepthBufferFormat);
+ if (depthStencilFormatInfo.depthBits > 0)
+ {
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, mDepthRenderbufferID);
+ }
+ if (depthStencilFormatInfo.stencilBits > 0)
+ {
+ mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, mDepthRenderbufferID);
+ }
+ }
+
+ mFirstSwap = true;
+
+ return egl::Error(EGL_SUCCESS);
+}
+} // namespace rx
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
new file mode 100755
index 000000000..f516239c9
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h
@@ -0,0 +1,106 @@
+//
+// 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.
+//
+
+// DXGISwapChainWindowSurfaceWGL.h: WGL implementation of egl::Surface for windows using a DXGI
+// swapchain.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsGL;
+class FunctionsWGL;
+class DisplayWGL;
+class StateManagerGL;
+struct WorkaroundsGL;
+
+class DXGISwapChainWindowSurfaceWGL : public SurfaceGL
+{
+ public:
+ DXGISwapChainWindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ ID3D11Device *device,
+ HANDLE deviceHandle,
+ HGLRC wglContext,
+ HDC deviceContext,
+ const FunctionsGL *functionsGL,
+ const FunctionsWGL *functionsWGL,
+ EGLint orientation);
+ ~DXGISwapChainWindowSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
+
+ private:
+ egl::Error setObjectsLocked(bool locked);
+ egl::Error checkForResize();
+
+ egl::Error createSwapChain();
+
+ EGLNativeWindowType mWindow;
+
+ StateManagerGL *mStateManager;
+ const WorkaroundsGL &mWorkarounds;
+ RendererGL *mRenderer;
+ const FunctionsGL *mFunctionsGL;
+ const FunctionsWGL *mFunctionsWGL;
+
+ ID3D11Device *mDevice;
+ HANDLE mDeviceHandle;
+
+ HDC mWGLDevice;
+ HGLRC mWGLContext;
+
+ DXGI_FORMAT mSwapChainFormat;
+ UINT mSwapChainFlags;
+ GLenum mDepthBufferFormat;
+
+ bool mFirstSwap;
+ IDXGISwapChain *mSwapChain;
+ IDXGISwapChain1 *mSwapChain1;
+
+ GLuint mColorRenderbufferID;
+ HANDLE mRenderbufferBufferHandle;
+
+ GLuint mDepthRenderbufferID;
+
+ GLuint mFramebufferID;
+
+ GLuint mTextureID;
+ HANDLE mTextureHandle;
+
+ size_t mWidth;
+ size_t mHeight;
+
+ EGLint mSwapInterval;
+
+ EGLint mOrientation;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_WGL_DXGISWAPCHAINSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
new file mode 100755
index 000000000..188321115
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -0,0 +1,741 @@
+//
+// 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.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
+#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "platform/Platform.h"
+
+#include <EGL/eglext.h>
+#include <string>
+#include <sstream>
+
+namespace rx
+{
+
+class FunctionsGLWindows : public FunctionsGL
+{
+ public:
+ FunctionsGLWindows(HMODULE openGLModule, PFNWGLGETPROCADDRESSPROC getProcAddressWGL)
+ : mOpenGLModule(openGLModule),
+ mGetProcAddressWGL(getProcAddressWGL)
+ {
+ ASSERT(mOpenGLModule);
+ ASSERT(mGetProcAddressWGL);
+ }
+
+ ~FunctionsGLWindows() override {}
+
+ private:
+ void *loadProcAddress(const std::string &function) override
+ {
+ void *proc = reinterpret_cast<void*>(mGetProcAddressWGL(function.c_str()));
+ if (!proc)
+ {
+ proc = reinterpret_cast<void*>(GetProcAddress(mOpenGLModule, function.c_str()));
+ }
+ return proc;
+ }
+
+ HMODULE mOpenGLModule;
+ PFNWGLGETPROCADDRESSPROC mGetProcAddressWGL;
+};
+
+DisplayWGL::DisplayWGL()
+ : DisplayGL(),
+ mOpenGLModule(nullptr),
+ mFunctionsWGL(nullptr),
+ mFunctionsGL(nullptr),
+ mHasRobustness(false),
+ mWindowClass(0),
+ mWindow(nullptr),
+ mDeviceContext(nullptr),
+ mPixelFormat(0),
+ mWGLContext(nullptr),
+ mUseDXGISwapChains(false),
+ mDxgiModule(nullptr),
+ mD3d11Module(nullptr),
+ mD3D11DeviceHandle(nullptr),
+ mD3D11Device(nullptr),
+ mDisplay(nullptr)
+{
+}
+
+DisplayWGL::~DisplayWGL()
+{
+}
+
+egl::Error DisplayWGL::initialize(egl::Display *display)
+{
+ mDisplay = display;
+
+ mOpenGLModule = LoadLibraryA("opengl32.dll");
+ if (!mOpenGLModule)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load OpenGL library.");
+ }
+
+ mFunctionsWGL = new FunctionsWGL();
+ mFunctionsWGL->initialize(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.
+
+ // Work around compile error from not defining "UNICODE" while Chromium does
+ const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
+
+ std::string className = FormatString("ANGLE DisplayWGL 0x%0.8p Intermediate Window Class", mDisplay);
+
+ WNDCLASSA intermediateClassDesc = { 0 };
+ intermediateClassDesc.style = CS_OWNDC;
+ intermediateClassDesc.lpfnWndProc = DefWindowProc;
+ intermediateClassDesc.cbClsExtra = 0;
+ intermediateClassDesc.cbWndExtra = 0;
+ intermediateClassDesc.hInstance = GetModuleHandle(nullptr);
+ intermediateClassDesc.hIcon = nullptr;
+ intermediateClassDesc.hCursor = LoadCursorA(nullptr, idcArrow);
+ intermediateClassDesc.hbrBackground = 0;
+ intermediateClassDesc.lpszMenuName = nullptr;
+ intermediateClassDesc.lpszClassName = className.c_str();
+ mWindowClass = RegisterClassA(&intermediateClassDesc);
+ if (!mWindowClass)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to register intermediate OpenGL window class.");
+ }
+
+ HWND dummyWindow = CreateWindowExA(0,
+ reinterpret_cast<const char *>(mWindowClass),
+ "ANGLE Dummy Window",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr);
+ if (!dummyWindow)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create dummy OpenGL window.");
+ }
+
+ HDC dummyDeviceContext = GetDC(dummyWindow);
+ if (!dummyDeviceContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the dummy OpenGL window.");
+ }
+
+ const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();
+
+ int dummyPixelFormat = ChoosePixelFormat(dummyDeviceContext, &pixelFormatDescriptor);
+ if (dummyPixelFormat == 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the dummy OpenGL window.");
+ }
+
+ if (!SetPixelFormat(dummyDeviceContext, dummyPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+ }
+
+ 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 (!mFunctionsWGL->makeCurrent(dummyDeviceContext, dummyWGLContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the dummy WGL context current.");
+ }
+
+ // Grab the GL version from this context and use it as the maximum version available.
+ typedef const GLubyte* (GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+ PFNGLGETSTRINGPROC getString = reinterpret_cast<PFNGLGETSTRINGPROC>(GetProcAddress(mOpenGLModule, "glGetString"));
+ if (!getString)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get glGetString pointer.");
+ }
+
+ // Reinitialize the wgl functions to grab the extensions
+ mFunctionsWGL->initialize(mOpenGLModule, dummyDeviceContext);
+
+ bool hasWGLCreateContextRobustness =
+ mFunctionsWGL->hasExtension("WGL_ARB_create_context_robustness");
+
+ // Destroy the dummy window and context
+ mFunctionsWGL->makeCurrent(dummyDeviceContext, nullptr);
+ mFunctionsWGL->deleteContext(dummyWGLContext);
+ ReleaseDC(dummyWindow, dummyDeviceContext);
+ DestroyWindow(dummyWindow);
+
+ const egl::AttributeMap &displayAttributes = display->getAttributeMap();
+ EGLint requestedDisplayType = static_cast<EGLint>(displayAttributes.get(
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
+ !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es2_profile") &&
+ !mFunctionsWGL->hasExtension("WGL_EXT_create_context_es_profile"))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED,
+ "Cannot create an OpenGL ES platform on Windows without "
+ "the WGL_EXT_create_context_es(2)_profile extension.");
+ }
+
+ // Create the real intermediate context and windows
+ mWindow = CreateWindowExA(0,
+ reinterpret_cast<const char *>(mWindowClass),
+ "ANGLE Intermediate Window",
+ WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr);
+ if (!mWindow)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create intermediate OpenGL window.");
+ }
+
+ mDeviceContext = GetDC(mWindow);
+ if (!mDeviceContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to get the device context of the intermediate OpenGL window.");
+ }
+
+ if (mFunctionsWGL->choosePixelFormatARB)
+ {
+ std::vector<int> attribs = wgl::GetDefaultPixelFormatAttributes(false);
+
+ UINT matchingFormats = 0;
+ mFunctionsWGL->choosePixelFormatARB(mDeviceContext, &attribs[0], nullptr, 1u, &mPixelFormat,
+ &matchingFormats);
+ }
+
+ if (mPixelFormat == 0)
+ {
+ mPixelFormat = ChoosePixelFormat(mDeviceContext, &pixelFormatDescriptor);
+ }
+
+ if (mPixelFormat == 0)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not find a compatible pixel format for the intermediate OpenGL window.");
+ }
+
+ if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the intermediate OpenGL window.");
+ }
+
+ if (mFunctionsWGL->createContextAttribsARB)
+ {
+ int flags = 0;
+ // TODO: allow debug contexts
+ // TODO: handle robustness
+
+ int mask = 0;
+
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ mask |= WGL_CONTEXT_ES_PROFILE_BIT_EXT;
+ }
+ else
+ {
+ // Request core profile
+ mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+
+ std::vector<int> contextCreationAttributes;
+
+ if (hasWGLCreateContextRobustness)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ contextCreationAttributes.push_back(WGL_LOSE_CONTEXT_ON_RESET_ARB);
+ }
+
+ // Don't request a specific version unless the user wants one. WGL will return the highest version
+ // that the driver supports if no version is requested.
+ EGLint requestedMajorVersion = static_cast<EGLint>(
+ displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+ EGLint requestedMinorVersion = static_cast<EGLint>(
+ displayAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
+ if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMajorVersion);
+
+ contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ contextCreationAttributes.push_back(requestedMinorVersion);
+ }
+ else
+ {
+ // the ES profile will give us ES version 1.1 unless a higher version is requested.
+ // Requesting version 2.0 will give us the highest compatible version available (2.0,
+ // 3.0, 3.1, etc).
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_MAJOR_VERSION_ARB);
+ contextCreationAttributes.push_back(2);
+
+ contextCreationAttributes.push_back(WGL_CONTEXT_MINOR_VERSION_ARB);
+ contextCreationAttributes.push_back(0);
+ }
+ }
+
+ // Set the flag attributes
+ if (flags != 0)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_FLAGS_ARB);
+ contextCreationAttributes.push_back(flags);
+ }
+
+ // Set the mask attribute
+ if (mask != 0)
+ {
+ contextCreationAttributes.push_back(WGL_CONTEXT_PROFILE_MASK_ARB);
+ contextCreationAttributes.push_back(mask);
+ }
+
+ // Signal the end of the attributes
+ contextCreationAttributes.push_back(0);
+ contextCreationAttributes.push_back(0);
+
+ mWGLContext = mFunctionsWGL->createContextAttribsARB(mDeviceContext, NULL, &contextCreationAttributes[0]);
+ }
+
+ // If wglCreateContextAttribsARB is unavailable or failed, try the standard wglCreateContext
+ if (!mWGLContext)
+ {
+ // Don't have control over GL versions
+ mWGLContext = mFunctionsWGL->createContext(mDeviceContext);
+ }
+
+ if (!mWGLContext)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to create a WGL context for the intermediate OpenGL window.");
+ }
+
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to make the intermediate WGL context current.");
+ }
+
+ mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress);
+ mFunctionsGL->initialize();
+
+ mHasRobustness = mFunctionsGL->getGraphicsResetStatus != nullptr;
+ if (hasWGLCreateContextRobustness != mHasRobustness)
+ {
+ ANGLEPlatformCurrent()->logWarning(
+ "WGL_ARB_create_context_robustness exists but unable to OpenGL context with "
+ "robustness.");
+ }
+
+ // Intel OpenGL ES drivers are not currently supported due to bugs in the driver and ANGLE
+ VendorID vendor = GetVendorID(mFunctionsGL);
+ if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE && IsIntel(vendor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Intel OpenGL ES drivers are not supported.");
+ }
+
+ // Create DXGI swap chains for windows that come from other processes. Windows is unable to
+ // SetPixelFormat on windows from other processes when a sandbox is enabled.
+ HDC nativeDisplay = display->getNativeDisplayId();
+ HWND nativeWindow = WindowFromDC(nativeDisplay);
+ if (nativeWindow != nullptr)
+ {
+ DWORD currentProcessId = GetCurrentProcessId();
+ DWORD windowProcessId;
+ GetWindowThreadProcessId(nativeWindow, &windowProcessId);
+
+ // AMD drivers advertise the WGL_NV_DX_interop and WGL_NV_DX_interop2 extensions but fail
+ mUseDXGISwapChains = !IsAMD(vendor) && (currentProcessId != windowProcessId);
+ }
+ else
+ {
+ mUseDXGISwapChains = false;
+ }
+
+ if (mUseDXGISwapChains)
+ {
+ egl::Error error = initializeD3DDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return DisplayGL::initialize(display);
+}
+
+void DisplayWGL::terminate()
+{
+ DisplayGL::terminate();
+
+ releaseD3DDevice(mD3D11DeviceHandle);
+
+ mFunctionsWGL->makeCurrent(mDeviceContext, NULL);
+ mFunctionsWGL->deleteContext(mWGLContext);
+ mWGLContext = NULL;
+
+ ReleaseDC(mWindow, mDeviceContext);
+ mDeviceContext = NULL;
+
+ DestroyWindow(mWindow);
+ mWindow = NULL;
+
+ UnregisterClassA(reinterpret_cast<const char*>(mWindowClass), NULL);
+ mWindowClass = NULL;
+
+ SafeDelete(mFunctionsWGL);
+ SafeDelete(mFunctionsGL);
+
+ FreeLibrary(mOpenGLModule);
+ mOpenGLModule = nullptr;
+
+ SafeRelease(mD3D11Device);
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = nullptr;
+ }
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = nullptr;
+ }
+
+ ASSERT(mRegisteredD3DDevices.empty());
+}
+
+SurfaceImpl *DisplayWGL::createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ EGLint orientation = static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+ if (mUseDXGISwapChains)
+ {
+ return new DXGISwapChainWindowSurfaceWGL(state, getRenderer(), window, mD3D11Device,
+ mD3D11DeviceHandle, mWGLContext, mDeviceContext,
+ mFunctionsGL, mFunctionsWGL, orientation);
+ }
+ else
+ {
+ return new WindowSurfaceWGL(state, getRenderer(), window, mPixelFormat, mWGLContext,
+ mFunctionsWGL, orientation);
+ }
+}
+
+SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs)
+{
+ EGLint width = static_cast<EGLint>(attribs.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0));
+ bool largest = (attribs.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+ EGLenum textureFormat = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
+ EGLenum textureTarget = static_cast<EGLenum>(attribs.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+
+ return new PbufferSurfaceWGL(state, getRenderer(), width, height, textureFormat, textureTarget,
+ largest, mPixelFormat, mDeviceContext, mWGLContext, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(buftype == EGL_D3D_TEXTURE_ANGLE);
+ return new D3DTextureSurfaceWGL(state, getRenderer(), clientBuffer, this, mWGLContext,
+ mDeviceContext, mFunctionsGL, mFunctionsWGL);
+}
+
+SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+egl::Error DisplayWGL::getDevice(DeviceImpl **device)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::ConfigSet DisplayWGL::generateConfigs()
+{
+ egl::ConfigSet configs;
+
+ int minSwapInterval = 1;
+ int maxSwapInterval = 1;
+ if (mFunctionsWGL->swapIntervalEXT)
+ {
+ // No defined maximum swap interval in WGL_EXT_swap_control, use a reasonable number
+ minSwapInterval = 0;
+ maxSwapInterval = 8;
+ }
+
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+ ASSERT(maxVersion >= gl::Version(2, 0));
+ bool supportsES3 = maxVersion >= gl::Version(3, 0);
+
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor;
+ DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor);
+
+ auto getAttrib = [this](int attrib)
+ {
+ return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL);
+ };
+
+ const EGLint optimalSurfaceOrientation =
+ mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0;
+
+ egl::Config config;
+ config.renderTargetFormat = GL_RGBA8; // TODO: use the bit counts to determine the format
+ config.depthStencilFormat = GL_DEPTH24_STENCIL8; // TODO: use the bit counts to determine the format
+ config.bufferSize = pixelFormatDescriptor.cColorBits;
+ config.redSize = pixelFormatDescriptor.cRedBits;
+ config.greenSize = pixelFormatDescriptor.cGreenBits;
+ config.blueSize = pixelFormatDescriptor.cBlueBits;
+ config.luminanceSize = 0;
+ config.alphaSize = pixelFormatDescriptor.cAlphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (getAttrib(WGL_BIND_TO_TEXTURE_RGB_ARB) == TRUE);
+ config.bindToTextureRGBA = (getAttrib(WGL_BIND_TO_TEXTURE_RGBA_ARB) == TRUE);
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configCaveat = EGL_NONE;
+ config.conformant = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.depthSize = pixelFormatDescriptor.cDepthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = getAttrib(WGL_MAX_PBUFFER_WIDTH_ARB);
+ config.maxPBufferHeight = getAttrib(WGL_MAX_PBUFFER_HEIGHT_ARB);
+ config.maxPBufferPixels = getAttrib(WGL_MAX_PBUFFER_PIXELS_ARB);
+ config.maxSwapInterval = maxSwapInterval;
+ config.minSwapInterval = minSwapInterval;
+ config.nativeRenderable = EGL_TRUE; // Direct rendering
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+ config.renderableType = EGL_OPENGL_ES2_BIT | (supportsES3 ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = pixelFormatDescriptor.cStencilBits;
+ config.surfaceType =
+ ((pixelFormatDescriptor.dwFlags & PFD_DRAW_TO_WINDOW) ? EGL_WINDOW_BIT : 0) |
+ ((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_BIT : 0) |
+ ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT
+ : 0);
+ config.optimalOrientation = optimalSurfaceOrientation;
+
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+
+ configs.add(config);
+
+ return configs;
+}
+
+bool DisplayWGL::testDeviceLost()
+{
+ if (mHasRobustness)
+ {
+ return getRenderer()->getResetStatus() != GL_NO_ERROR;
+ }
+
+ return false;
+}
+
+egl::Error DisplayWGL::restoreLostDevice()
+{
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return (IsWindow(window) == TRUE);
+}
+
+egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_ANGLE:
+ return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(clientBuffer);
+
+ default:
+ return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+ }
+}
+
+std::string DisplayWGL::getVendorString() const
+{
+ //UNIMPLEMENTED();
+ return "";
+}
+
+const FunctionsGL *DisplayWGL::getFunctionsGL() const
+{
+ return mFunctionsGL;
+}
+
+egl::Error DisplayWGL::initializeD3DDevice()
+{
+ if (mD3D11Device != nullptr)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ if (!mDxgiModule)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load DXGI library.");
+ }
+
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ if (!mD3d11Module)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to load d3d11 library.");
+ }
+
+ PFN_D3D11_CREATE_DEVICE d3d11CreateDevice = nullptr;
+ d3d11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+ if (d3d11CreateDevice == nullptr)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not retrieve D3D11CreateDevice address.");
+ }
+
+ HRESULT result = d3d11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0,
+ D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr);
+ if (FAILED(result))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Could not create D3D11 device, error: 0x%X",
+ result);
+ }
+
+ egl::Error error = registerD3DDevice(mD3D11Device, &mD3D11DeviceHandle);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ // Only enable the surface orientation and post sub buffer for DXGI swap chain surfaces, they
+ // prefer to swap with inverted Y.
+ outExtensions->postSubBuffer = mUseDXGISwapChains;
+ outExtensions->surfaceOrientation = mUseDXGISwapChains;
+
+ outExtensions->createContextRobustness = mHasRobustness;
+
+ outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");
+}
+
+void DisplayWGL::generateCaps(egl::Caps *outCaps) const
+{
+ outCaps->textureNPOT = true;
+}
+
+egl::Error DisplayWGL::waitClient() const
+{
+ // Unimplemented as this is not needed for WGL
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const
+{
+ // Unimplemented as this is not needed for WGL
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::getDriverVersion(std::string *version) const
+{
+ *version = "";
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle)
+{
+ ASSERT(device != nullptr);
+ ASSERT(outHandle != nullptr);
+
+ auto iter = mRegisteredD3DDevices.find(device);
+ if (iter != mRegisteredD3DDevices.end())
+ {
+ iter->second.refCount++;
+ *outHandle = iter->second.handle;
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ HANDLE handle = mFunctionsWGL->dxOpenDeviceNV(device);
+ if (!handle)
+ {
+ return egl::Error(EGL_BAD_PARAMETER, "Failed to open D3D device.");
+ }
+
+ device->AddRef();
+
+ D3DObjectHandle newDeviceInfo;
+ newDeviceInfo.handle = handle;
+ newDeviceInfo.refCount = 1;
+ mRegisteredD3DDevices[device] = newDeviceInfo;
+
+ *outHandle = handle;
+ return egl::Error(EGL_SUCCESS);
+}
+
+void DisplayWGL::releaseD3DDevice(HANDLE deviceHandle)
+{
+ for (auto iter = mRegisteredD3DDevices.begin(); iter != mRegisteredD3DDevices.end(); iter++)
+ {
+ if (iter->second.handle == deviceHandle)
+ {
+ iter->second.refCount--;
+ if (iter->second.refCount == 0)
+ {
+ mFunctionsWGL->dxCloseDeviceNV(iter->second.handle);
+ iter->first->Release();
+ mRegisteredD3DDevices.erase(iter);
+ break;
+ }
+ }
+ }
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
new file mode 100755
index 000000000..509ea9b39
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.h
@@ -0,0 +1,112 @@
+//
+// 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.
+//
+
+// DisplayWGL.h: WGL implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
+
+#include "libANGLE/renderer/gl/DisplayGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class DisplayWGL : public DisplayGL
+{
+ public:
+ DisplayWGL();
+ ~DisplayWGL() override;
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ // Surface creation
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ const egl::Config *configuration,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ egl::Error validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
+
+ egl::Error getDevice(DeviceImpl **device) override;
+
+ std::string getVendorString() const override;
+
+ egl::Error waitClient() const override;
+ egl::Error waitNative(EGLint engine,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface) const override;
+
+ egl::Error getDriverVersion(std::string *version) const override;
+
+ egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle);
+ void releaseD3DDevice(HANDLE handle);
+
+ private:
+ const FunctionsGL *getFunctionsGL() const override;
+
+ egl::Error initializeD3DDevice();
+
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ HMODULE mOpenGLModule;
+
+ FunctionsWGL *mFunctionsWGL;
+ FunctionsGL *mFunctionsGL;
+
+ bool mHasRobustness;
+
+ ATOM mWindowClass;
+ HWND mWindow;
+ HDC mDeviceContext;
+ int mPixelFormat;
+ HGLRC mWGLContext;
+
+ bool mUseDXGISwapChains;
+ HMODULE mDxgiModule;
+ HMODULE mD3d11Module;
+ HANDLE mD3D11DeviceHandle;
+ ID3D11Device *mD3D11Device;
+
+ struct D3DObjectHandle
+ {
+ HANDLE handle;
+ size_t refCount;
+ };
+ std::map<IUnknown *, D3DObjectHandle> mRegisteredD3DDevices;
+
+ egl::Display *mDisplay;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_DISPLAYWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
new file mode 100755
index 000000000..2cfe6e9eb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.cpp
@@ -0,0 +1,181 @@
+//
+// 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"
+
+#include <algorithm>
+
+#include "common/string_utils.h"
+
+namespace rx
+{
+
+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::vector<std::string> &extensions,
+ const std::string &extensionName,
+ const std::string &procName,
+ T *outProcAddress)
+{
+ T proc = nullptr;
+ if (std::find(extensions.begin(), extensions.end(), extensionName) != extensions.end())
+ {
+ GetWGLProcAddress(glModule, getProcAddressWGL, procName, &proc);
+ }
+
+ *outProcAddress = proc;
+}
+
+FunctionsWGL::FunctionsWGL()
+ : copyContext(nullptr),
+ createContext(nullptr),
+ createLayerContext(nullptr),
+ deleteContext(nullptr),
+ getCurrentContext(nullptr),
+ getCurrentDC(nullptr),
+ getProcAddress(nullptr),
+ makeCurrent(nullptr),
+ shareLists(nullptr),
+ useFontBitmapsA(nullptr),
+ useFontBitmapsW(nullptr),
+ swapBuffers(nullptr),
+ useFontOutlinesA(nullptr),
+ useFontOutlinesW(nullptr),
+ describeLayerPlane(nullptr),
+ setLayerPaletteEntries(nullptr),
+ getLayerPaletteEntries(nullptr),
+ realizeLayerPalette(nullptr),
+ swapLayerBuffers(nullptr),
+ swapMultipleBuffers(nullptr),
+ getExtensionStringEXT(nullptr),
+ getExtensionStringARB(nullptr),
+ createContextAttribsARB(nullptr),
+ getPixelFormatAttribivARB(nullptr),
+ getPixelFormatAttribfvARB(nullptr),
+ choosePixelFormatARB(nullptr),
+ swapIntervalEXT(nullptr),
+ createPbufferARB(nullptr),
+ getPbufferDCARB(nullptr),
+ releasePbufferDCARB(nullptr),
+ destroyPbufferARB(nullptr),
+ queryPbufferARB(nullptr),
+ bindTexImageARB(nullptr),
+ releaseTexImageARB(nullptr),
+ setPbufferAttribARB(nullptr),
+ dxSetResourceShareHandleNV(nullptr),
+ dxOpenDeviceNV(nullptr),
+ dxCloseDeviceNV(nullptr),
+ dxRegisterObjectNV(nullptr),
+ dxUnregisterObjectNV(nullptr),
+ dxObjectAccessNV(nullptr),
+ dxLockObjectsNV(nullptr),
+ dxUnlockObjectsNV(nullptr)
+{
+}
+
+void FunctionsWGL::initialize(HMODULE glModule, HDC context)
+{
+ // First grab the wglGetProcAddress function from the gl module
+ GetWGLProcAddress(glModule, nullptr, "wglGetProcAddress", &getProcAddress);
+
+ // Load the core wgl functions
+ GetWGLProcAddress(glModule, getProcAddress, "wglCopyContext", &copyContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglCreateContext", &createContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglCreateLayerContext", &createLayerContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglDeleteContext", &deleteContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentContext", &getCurrentContext);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetCurrentDC", &getCurrentDC);
+ GetWGLProcAddress(glModule, getProcAddress, "wglMakeCurrent", &makeCurrent);
+ GetWGLProcAddress(glModule, getProcAddress, "wglShareLists", &shareLists);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsA", &useFontBitmapsA);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontBitmapsW", &useFontBitmapsW);
+ swapBuffers = SwapBuffers; // SwapBuffers is statically linked from GDI
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesA", &useFontOutlinesA);
+ GetWGLProcAddress(glModule, getProcAddress, "wglUseFontOutlinesW", &useFontOutlinesW);
+ GetWGLProcAddress(glModule, getProcAddress, "wglDescribeLayerPlane", &describeLayerPlane);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSetLayerPaletteEntries", &setLayerPaletteEntries);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetLayerPaletteEntries", &getLayerPaletteEntries);
+ GetWGLProcAddress(glModule, getProcAddress, "wglRealizeLayerPalette", &realizeLayerPalette);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSwapLayerBuffers", &swapLayerBuffers);
+ GetWGLProcAddress(glModule, getProcAddress, "wglSwapMultipleBuffers", &swapMultipleBuffers);
+
+ // Load extension string getter functions
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringEXT", &getExtensionStringEXT);
+ GetWGLProcAddress(glModule, getProcAddress, "wglGetExtensionsStringARB", &getExtensionStringARB);
+
+ std::string extensionString = "";
+ if (getExtensionStringEXT)
+ {
+ extensionString = getExtensionStringEXT();
+ }
+ else if (getExtensionStringARB && context)
+ {
+ extensionString = getExtensionStringARB(context);
+ }
+ angle::SplitStringAlongWhitespace(extensionString, &extensions);
+
+ // Load the wgl extension functions by checking if the context supports the extension first
+
+ // WGL_ARB_create_context
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_create_context", "wglCreateContextAttribsARB", &createContextAttribsARB);
+
+ // WGL_ARB_pixel_format
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribivARB", &getPixelFormatAttribivARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglGetPixelFormatAttribfvARB", &getPixelFormatAttribfvARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pixel_format", "wglChoosePixelFormatARB", &choosePixelFormatARB);
+
+ // WGL_EXT_swap_control
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_EXT_swap_control", "wglSwapIntervalEXT", &swapIntervalEXT);
+
+ // WGL_ARB_pbuffer
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglCreatePbufferARB", &createPbufferARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglGetPbufferDCARB", &getPbufferDCARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglReleasePbufferDCARB", &releasePbufferDCARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglDestroyPbufferARB", &destroyPbufferARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_pbuffer", "wglQueryPbufferARB", &queryPbufferARB);
+
+ // WGL_ARB_render_texture
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglBindTexImageARB", &bindTexImageARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglReleaseTexImageARB", &releaseTexImageARB);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_ARB_render_texture", "wglSetPbufferAttribARB", &setPbufferAttribARB);
+
+ // WGL_NV_DX_interop
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXSetResourceShareHandleNV", &dxSetResourceShareHandleNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXOpenDeviceNV", &dxOpenDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXCloseDeviceNV", &dxCloseDeviceNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXRegisterObjectNV", &dxRegisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnregisterObjectNV", &dxUnregisterObjectNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXObjectAccessNV", &dxObjectAccessNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXLockObjectsNV", &dxLockObjectsNV);
+ GetWGLExtensionProcAddress(glModule, getProcAddress, extensions, "WGL_NV_DX_interop", "wglDXUnlockObjectsNV", &dxUnlockObjectsNV);
+}
+
+bool FunctionsWGL::hasExtension(const std::string &ext) const
+{
+ return std::find(extensions.begin(), extensions.end(), ext) != extensions.end();
+}
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
new file mode 100755
index 000000000..30cf9ebc0
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/FunctionsWGL.h
@@ -0,0 +1,94 @@
+//
+// 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
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/gl/wgl/functionswgl_typedefs.h"
+
+namespace rx
+{
+
+class FunctionsWGL : angle::NonCopyable
+{
+ public:
+ FunctionsWGL();
+
+ // Loads all available wgl functions, may be called multiple times
+ void initialize(HMODULE glModule, HDC context);
+
+ // Extension information
+ std::vector<std::string> extensions;
+ bool hasExtension(const std::string &ext) const;
+
+ // Base WGL functions
+ PFNWGLCOPYCONTEXTPROC copyContext;
+ PFNWGLCREATECONTEXTPROC createContext;
+ PFNWGLCREATELAYERCONTEXTPROC createLayerContext;
+ PFNWGLDELETECONTEXTPROC deleteContext;
+ PFNWGLGETCURRENTCONTEXTPROC getCurrentContext;
+ PFNWGLGETCURRENTDCPROC getCurrentDC;
+ PFNWGLGETPROCADDRESSPROC getProcAddress;
+ PFNWGLMAKECURRENTPROC makeCurrent;
+ PFNWGLSHARELISTSPROC shareLists;
+ PFNWGLUSEFONTBITMAPSAPROC useFontBitmapsA;
+ PFNWGLUSEFONTBITMAPSWPROC useFontBitmapsW;
+ PFNSWAPBUFFERSPROC swapBuffers;
+ PFNWGLUSEFONTOUTLINESAPROC useFontOutlinesA;
+ PFNWGLUSEFONTOUTLINESWPROC useFontOutlinesW;
+ PFNWGLDESCRIBELAYERPLANEPROC describeLayerPlane;
+ PFNWGLSETLAYERPALETTEENTRIESPROC setLayerPaletteEntries;
+ PFNWGLGETLAYERPALETTEENTRIESPROC getLayerPaletteEntries;
+ PFNWGLREALIZELAYERPALETTEPROC realizeLayerPalette;
+ PFNWGLSWAPLAYERBUFFERSPROC swapLayerBuffers;
+ PFNWGLSWAPMULTIPLEBUFFERSPROC swapMultipleBuffers;
+
+ // WGL_EXT_extensions_string
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC getExtensionStringEXT;
+
+ // WGL_ARB_extensions_string
+ PFNWGLGETEXTENSIONSSTRINGARBPROC getExtensionStringARB;
+
+ // WGL_ARB_create_context
+ PFNWGLCREATECONTEXTATTRIBSARBPROC createContextAttribsARB;
+
+ // WGL_ARB_pixel_format
+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC getPixelFormatAttribivARB;
+ PFNWGLGETPIXELFORMATATTRIBFVARBPROC getPixelFormatAttribfvARB;
+ PFNWGLCHOOSEPIXELFORMATARBPROC choosePixelFormatARB;
+
+ // WGL_EXT_swap_control
+ PFNWGLSWAPINTERVALEXTPROC swapIntervalEXT;
+
+ // WGL_ARB_pbuffer
+ PFNWGLCREATEPBUFFERARBPROC createPbufferARB;
+ PFNWGLGETPBUFFERDCARBPROC getPbufferDCARB;
+ PFNWGLRELEASEPBUFFERDCARBPROC releasePbufferDCARB;
+ PFNWGLDESTROYPBUFFERARBPROC destroyPbufferARB;
+ PFNWGLQUERYPBUFFERARBPROC queryPbufferARB;
+
+ // WGL_ARB_render_texture
+ PFNWGLBINDTEXIMAGEARBPROC bindTexImageARB;
+ PFNWGLRELEASETEXIMAGEARBPROC releaseTexImageARB;
+ PFNWGLSETPBUFFERATTRIBARBPROC setPbufferAttribARB;
+
+ // WGL_NV_DX_interop
+ PFNWGLDXSETRESOURCESHAREHANDLENVPROC dxSetResourceShareHandleNV;
+ PFNWGLDXOPENDEVICENVPROC dxOpenDeviceNV;
+ PFNWGLDXCLOSEDEVICENVPROC dxCloseDeviceNV;
+ PFNWGLDXREGISTEROBJECTNVPROC dxRegisterObjectNV;
+ PFNWGLDXUNREGISTEROBJECTNVPROC dxUnregisterObjectNV;
+ PFNWGLDXOBJECTACCESSNVPROC dxObjectAccessNV;
+ PFNWGLDXLOCKOBJECTSNVPROC dxLockObjectsNV;
+ PFNWGLDXUNLOCKOBJECTSNVPROC dxUnlockObjectsNV;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONS_WGL
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
new file mode 100755
index 000000000..f2c503616
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp
@@ -0,0 +1,196 @@
+//
+// 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.
+//
+
+// SurfaceWGL.cpp: WGL implementation of egl::Surface
+
+#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+PbufferSurfaceWGL::PbufferSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ EGLenum textureFormat,
+ EGLenum textureTarget,
+ bool largest,
+ int pixelFormat,
+ HDC deviceContext,
+ HGLRC wglContext,
+ const FunctionsWGL *functions)
+ : SurfaceGL(state, renderer),
+ mWidth(width),
+ mHeight(height),
+ mLargest(largest),
+ mTextureFormat(textureFormat),
+ mTextureTarget(textureTarget),
+ mPixelFormat(pixelFormat),
+ mShareWGLContext(wglContext),
+ mParentDeviceContext(deviceContext),
+ mPbuffer(nullptr),
+ mPbufferDeviceContext(nullptr),
+ mFunctionsWGL(functions)
+{
+}
+
+PbufferSurfaceWGL::~PbufferSurfaceWGL()
+{
+ mFunctionsWGL->releasePbufferDCARB(mPbuffer, mPbufferDeviceContext);
+ mPbufferDeviceContext = nullptr;
+
+ mFunctionsWGL->destroyPbufferARB(mPbuffer);
+ mPbuffer = nullptr;
+}
+
+static int GetWGLTextureType(EGLenum eglTextureType)
+{
+ switch (eglTextureType)
+ {
+ case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB;
+ case EGL_TEXTURE_RGB: return WGL_TEXTURE_RGB_ARB;
+ case EGL_TEXTURE_RGBA: return WGL_TEXTURE_RGBA_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static int GetWGLTextureTarget(EGLenum eglTextureTarget)
+{
+ switch (eglTextureTarget)
+ {
+ case EGL_NO_TEXTURE: return WGL_NO_TEXTURE_ARB;
+ case EGL_TEXTURE_2D: return WGL_TEXTURE_2D_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+egl::Error PbufferSurfaceWGL::initialize()
+{
+ const int pbufferCreationAttributes[] =
+ {
+ WGL_PBUFFER_LARGEST_ARB, mLargest ? 1 : 0,
+ WGL_TEXTURE_FORMAT_ARB, GetWGLTextureType(mTextureFormat),
+ WGL_TEXTURE_TARGET_ARB, GetWGLTextureTarget(mTextureTarget),
+ 0, 0,
+ };
+
+ mPbuffer = mFunctionsWGL->createPbufferARB(mParentDeviceContext, mPixelFormat, mWidth, mHeight,
+ pbufferCreationAttributes);
+ if (mPbuffer == nullptr)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to create a native WGL pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ // The returned pbuffer may not be as large as requested, update the size members.
+ if (mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_WIDTH_ARB, &mWidth) != TRUE ||
+ mFunctionsWGL->queryPbufferARB(mPbuffer, WGL_PBUFFER_HEIGHT_ARB, &mHeight) != TRUE)
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to query the WGL pbuffer's dimensions, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ mPbufferDeviceContext = mFunctionsWGL->getPbufferDCARB(mPbuffer);
+ if (mPbufferDeviceContext == nullptr)
+ {
+ mFunctionsWGL->destroyPbufferARB(mPbuffer);
+ mPbuffer = nullptr;
+
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_ALLOC, "Failed to get the WGL pbuffer handle, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mPbufferDeviceContext, mShareWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::swap()
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+static int GetWGLBufferBindTarget(EGLint buffer)
+{
+ switch (buffer)
+ {
+ case EGL_BACK_BUFFER: return WGL_BACK_LEFT_ARB;
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+egl::Error PbufferSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ if (!mFunctionsWGL->bindTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_SURFACE, "Failed to bind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error PbufferSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ if (!mFunctionsWGL->releaseTexImageARB(mPbuffer, GetWGLBufferBindTarget(buffer)))
+ {
+ DWORD error = GetLastError();
+ return egl::Error(EGL_BAD_SURFACE, "Failed to unbind native wgl pbuffer, error: 0x%08x.", HRESULT_CODE(error));
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+void PbufferSurfaceWGL::setSwapInterval(EGLint interval)
+{
+}
+
+EGLint PbufferSurfaceWGL::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint PbufferSurfaceWGL::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint PbufferSurfaceWGL::isPostSubBufferSupported() const
+{
+ return EGL_FALSE;
+}
+
+EGLint PbufferSurfaceWGL::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
new file mode 100755
index 000000000..56235293a
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h
@@ -0,0 +1,74 @@
+//
+// 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.
+//
+
+// PBufferSurfaceWGL.h: WGL implementation of egl::Surface for PBuffers
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class PbufferSurfaceWGL : public SurfaceGL
+{
+ public:
+ PbufferSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLint width,
+ EGLint height,
+ EGLenum textureFormat,
+ EGLenum textureTarget,
+ bool largest,
+ int pixelFormat,
+ HDC deviceContext,
+ HGLRC wglContext,
+ const FunctionsWGL *functions);
+ ~PbufferSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ EGLint mWidth;
+ EGLint mHeight;
+ bool mLargest;
+ EGLenum mTextureFormat;
+ EGLenum mTextureTarget;
+
+ int mPixelFormat;
+
+ HGLRC mShareWGLContext;
+
+ HDC mParentDeviceContext;
+
+ HPBUFFERARB mPbuffer;
+ HDC mPbufferDeviceContext;
+
+ const FunctionsWGL *mFunctionsWGL;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_PBUFFERSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
new file mode 100755
index 000000000..f22943acb
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.cpp
@@ -0,0 +1,178 @@
+//
+// 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.
+//
+
+// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows
+
+#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/gl/RendererGL.h"
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+namespace rx
+{
+
+WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ int pixelFormat,
+ HGLRC wglContext,
+ const FunctionsWGL *functions,
+ EGLint orientation)
+ : SurfaceGL(state, renderer),
+ mPixelFormat(pixelFormat),
+ mWGLContext(wglContext),
+ mWindow(window),
+ mDeviceContext(nullptr),
+ mFunctionsWGL(functions),
+ mSwapBehavior(0)
+{
+ // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
+ ASSERT(orientation == 0);
+}
+
+WindowSurfaceWGL::~WindowSurfaceWGL()
+{
+ ReleaseDC(mWindow, mDeviceContext);
+ mDeviceContext = nullptr;
+}
+
+egl::Error WindowSurfaceWGL::initialize()
+{
+ mDeviceContext = GetDC(mWindow);
+ if (!mDeviceContext)
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context from the native window, "
+ "error: 0x%X.", GetLastError());
+ }
+
+ // Require that the pixel format for this window has not been set yet or is equal to the Display's pixel format.
+ int windowPixelFormat = GetPixelFormat(mDeviceContext);
+ if (windowPixelFormat == 0)
+ {
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+ if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor), &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to DescribePixelFormat, error: 0x%X.", GetLastError());
+ }
+
+ if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Failed to set the pixel format on the device context, "
+ "error: 0x%X.", GetLastError());
+ }
+ }
+ else if (windowPixelFormat != mPixelFormat)
+ {
+ return egl::Error(EGL_NOT_INITIALIZED, "Pixel format of the NativeWindow and NativeDisplayType must match.");
+ }
+
+ // Check for the swap behavior of this pixel format
+ switch (
+ wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
+ {
+ case WGL_SWAP_COPY_ARB:
+ mSwapBehavior = EGL_BUFFER_PRESERVED;
+ break;
+
+ case WGL_SWAP_EXCHANGE_ARB:
+ case WGL_SWAP_UNDEFINED_ARB:
+ default:
+ mSwapBehavior = EGL_BUFFER_DESTROYED;
+ break;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::makeCurrent()
+{
+ if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::swap()
+{
+ if (!mFunctionsWGL->swapBuffers(mDeviceContext))
+ {
+ // TODO: What error type here?
+ return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer)
+{
+ UNIMPLEMENTED();
+ return egl::Error(EGL_SUCCESS);
+}
+
+void WindowSurfaceWGL::setSwapInterval(EGLint interval)
+{
+ if (mFunctionsWGL->swapIntervalEXT)
+ {
+ mFunctionsWGL->swapIntervalEXT(interval);
+ }
+}
+
+EGLint WindowSurfaceWGL::getWidth() const
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return 0;
+ }
+ return rect.right - rect.left;
+}
+
+EGLint WindowSurfaceWGL::getHeight() const
+{
+ RECT rect;
+ if (!GetClientRect(mWindow, &rect))
+ {
+ return 0;
+ }
+ return rect.bottom - rect.top;
+}
+
+EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
+{
+ // PostSubBuffer extension not exposed on WGL.
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint WindowSurfaceWGL::getSwapBehavior() const
+{
+ return mSwapBehavior;
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
new file mode 100755
index 000000000..eb95e4dc2
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h
@@ -0,0 +1,64 @@
+//
+// 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.
+//
+
+// WindowSurfaceWGL.h: WGL implementation of egl::Surface for windows
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+#define LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
+
+#include "libANGLE/renderer/gl/SurfaceGL.h"
+
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+class WindowSurfaceWGL : public SurfaceGL
+{
+ public:
+ WindowSurfaceWGL(const egl::SurfaceState &state,
+ RendererGL *renderer,
+ EGLNativeWindowType window,
+ int pixelFormat,
+ HGLRC wglContext,
+ const FunctionsWGL *functions,
+ EGLint orientation);
+ ~WindowSurfaceWGL() override;
+
+ egl::Error initialize() override;
+ egl::Error makeCurrent() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ private:
+ int mPixelFormat;
+
+ HGLRC mWGLContext;
+
+ HWND mWindow;
+ HDC mDeviceContext;
+
+ const FunctionsWGL *mFunctionsWGL;
+
+ EGLint mSwapBehavior;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WINDOWSURFACEWGL_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
new file mode 100755
index 000000000..c4b79ee02
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/functionswgl_typedefs.h
@@ -0,0 +1,43 @@
+//
+// 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_typedefs.h: Typedefs of WGL functions.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+#define LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
+
+#include "common/platform.h"
+
+#include <angle_gl.h>
+#include <GL/wglext.h>
+
+namespace rx
+{
+
+typedef BOOL(WINAPI *PFNWGLCOPYCONTEXTPROC)(HGLRC, HGLRC, UINT);
+typedef HGLRC(WINAPI *PFNWGLCREATECONTEXTPROC)(HDC);
+typedef HGLRC(WINAPI *PFNWGLCREATELAYERCONTEXTPROC)(HDC, int);
+typedef BOOL(WINAPI *PFNWGLDELETECONTEXTPROC)(HGLRC);
+typedef HGLRC(WINAPI *PFNWGLGETCURRENTCONTEXTPROC)(VOID);
+typedef HDC(WINAPI *PFNWGLGETCURRENTDCPROC)(VOID);
+typedef PROC(WINAPI *PFNWGLGETPROCADDRESSPROC)(LPCSTR);
+typedef BOOL(WINAPI *PFNWGLMAKECURRENTPROC)(HDC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLSHARELISTSPROC)(HGLRC, HGLRC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSAPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNWGLUSEFONTBITMAPSWPROC)(HDC, DWORD, DWORD, DWORD);
+typedef BOOL(WINAPI *PFNSWAPBUFFERSPROC)(HDC);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESAPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLUSEFONTOUTLINESWPROC)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT);
+typedef BOOL(WINAPI *PFNWGLDESCRIBELAYERPLANEPROC)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+typedef int(WINAPI *PFNWGLSETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, CONST COLORREF *);
+typedef int(WINAPI *PFNWGLGETLAYERPALETTEENTRIESPROC)(HDC, int, int, int, COLORREF *);
+typedef BOOL(WINAPI *PFNWGLREALIZELAYERPALETTEPROC)(HDC, int, BOOL);
+typedef BOOL(WINAPI *PFNWGLSWAPLAYERBUFFERSPROC)(HDC, UINT);
+typedef DWORD(WINAPI *PFNWGLSWAPMULTIPLEBUFFERSPROC)(UINT, CONST WGLSWAP *);
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_FUNCTIONSWGLTYPEDEFS_H_
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
new file mode 100755
index 000000000..641c3fbc4
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.cpp
@@ -0,0 +1,85 @@
+//
+// 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.
+//
+
+// wgl_utils.cpp: Utility routines specific to the WGL->EGL implementation.
+
+#include "libANGLE/renderer/gl/wgl/wgl_utils.h"
+
+#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
+
+namespace rx
+{
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor()
+{
+ PIXELFORMATDESCRIPTOR pixelFormatDescriptor = { 0 };
+ pixelFormatDescriptor.nSize = sizeof(pixelFormatDescriptor);
+ pixelFormatDescriptor.nVersion = 1;
+ pixelFormatDescriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pixelFormatDescriptor.iPixelType = PFD_TYPE_RGBA;
+ pixelFormatDescriptor.cColorBits = 24;
+ pixelFormatDescriptor.cAlphaBits = 8;
+ pixelFormatDescriptor.cDepthBits = 24;
+ pixelFormatDescriptor.cStencilBits = 8;
+ pixelFormatDescriptor.iLayerType = PFD_MAIN_PLANE;
+
+ return pixelFormatDescriptor;
+}
+
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap)
+{
+ std::vector<int> attribs;
+ attribs.push_back(WGL_DRAW_TO_WINDOW_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_ACCELERATION_ARB);
+ attribs.push_back(WGL_FULL_ACCELERATION_ARB);
+
+ attribs.push_back(WGL_SUPPORT_OPENGL_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_DOUBLE_BUFFER_ARB);
+ attribs.push_back(TRUE);
+
+ attribs.push_back(WGL_PIXEL_TYPE_ARB);
+ attribs.push_back(WGL_TYPE_RGBA_ARB);
+
+ attribs.push_back(WGL_COLOR_BITS_ARB);
+ attribs.push_back(24);
+
+ attribs.push_back(WGL_ALPHA_BITS_ARB);
+ attribs.push_back(8);
+
+ attribs.push_back(WGL_DEPTH_BITS_ARB);
+ attribs.push_back(24);
+
+ attribs.push_back(WGL_STENCIL_BITS_ARB);
+ attribs.push_back(8);
+
+ attribs.push_back(WGL_SWAP_METHOD_ARB);
+ attribs.push_back(preservedSwap ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB);
+
+ attribs.push_back(0);
+
+ return attribs;
+}
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions)
+{
+ int result = 0;
+ if (functions->getPixelFormatAttribivARB == nullptr ||
+ !functions->getPixelFormatAttribivARB(dc, format, 0, 1, &attribName, &result))
+ {
+ return 0;
+ }
+ return result;
+}
+}
+
+}
diff --git a/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
new file mode 100755
index 000000000..d4914b5d3
--- /dev/null
+++ b/gfx/angle/src/libANGLE/renderer/gl/wgl/wgl_utils.h
@@ -0,0 +1,32 @@
+//
+// 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.
+//
+
+// wgl_utils.h: Utility routines specific to the WGL->EGL implementation.
+
+#ifndef LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+#define LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_
+
+#include <vector>
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+class FunctionsWGL;
+
+namespace wgl
+{
+
+PIXELFORMATDESCRIPTOR GetDefaultPixelFormatDescriptor();
+std::vector<int> GetDefaultPixelFormatAttributes(bool preservedSwap);
+
+int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const FunctionsWGL *functions);
+}
+
+}
+
+#endif // LIBANGLE_RENDERER_GL_WGL_WGLUTILS_H_