Commit 722b0d31 by Geoff Lang

Add a WGL Surface implementation that renders to a DXGI swap chain.

This avoids sandbox issues when calling SetPixelFormat on windows from other processes while in a sandboxed process. BUG=540829 Change-Id: I012168531d8c2e5b189671533cea9f57ec713538 Reviewed-on: https://chromium-review.googlesource.com/296340Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Tryjob-Request: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 0dfa807f
//
// 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(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::Framebuffer::Data &data) override;
private:
egl::Error setObjectsLocked(bool locked);
egl::Error checkForResize();
egl::Error createSwapChain();
EGLNativeWindowType mWindow;
StateManagerGL *mStateManager;
const WorkaroundsGL &mWorkarounds;
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_
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/renderergl_utils.h" #include "libANGLE/renderer/gl/renderergl_utils.h"
#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h" #include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h" #include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
...@@ -65,6 +66,11 @@ DisplayWGL::DisplayWGL() ...@@ -65,6 +66,11 @@ DisplayWGL::DisplayWGL()
mDeviceContext(nullptr), mDeviceContext(nullptr),
mPixelFormat(0), mPixelFormat(0),
mWGLContext(nullptr), mWGLContext(nullptr),
mUseDXGISwapChains(false),
mDxgiModule(nullptr),
mD3d11Module(nullptr),
mD3D11DeviceHandle(nullptr),
mD3D11Device(nullptr),
mDisplay(nullptr) mDisplay(nullptr)
{ {
} }
...@@ -323,6 +329,31 @@ egl::Error DisplayWGL::initialize(egl::Display *display) ...@@ -323,6 +329,31 @@ egl::Error DisplayWGL::initialize(egl::Display *display)
mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress); mFunctionsGL = new FunctionsGLWindows(mOpenGLModule, mFunctionsWGL->getProcAddress);
mFunctionsGL->initialize(); mFunctionsGL->initialize();
// 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);
mUseDXGISwapChains = (currentProcessId != windowProcessId);
}
else
{
mUseDXGISwapChains = false;
}
if (mUseDXGISwapChains)
{
egl::Error error = initializeD3DDevice();
if (error.isError())
{
return error;
}
}
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -330,6 +361,8 @@ void DisplayWGL::terminate() ...@@ -330,6 +361,8 @@ void DisplayWGL::terminate()
{ {
DisplayGL::terminate(); DisplayGL::terminate();
releaseD3DDevice(mD3D11DeviceHandle);
mFunctionsWGL->makeCurrent(mDeviceContext, NULL); mFunctionsWGL->makeCurrent(mDeviceContext, NULL);
mFunctionsWGL->deleteContext(mWGLContext); mFunctionsWGL->deleteContext(mWGLContext);
mWGLContext = NULL; mWGLContext = NULL;
...@@ -348,14 +381,40 @@ void DisplayWGL::terminate() ...@@ -348,14 +381,40 @@ void DisplayWGL::terminate()
FreeLibrary(mOpenGLModule); FreeLibrary(mOpenGLModule);
mOpenGLModule = nullptr; mOpenGLModule = nullptr;
SafeRelease(mD3D11Device);
if (mDxgiModule)
{
FreeLibrary(mDxgiModule);
mDxgiModule = nullptr;
}
if (mD3d11Module)
{
FreeLibrary(mD3d11Module);
mD3d11Module = nullptr;
}
ASSERT(mRegisteredD3DDevices.empty());
} }
SurfaceImpl *DisplayWGL::createWindowSurface(const egl::Config *configuration, SurfaceImpl *DisplayWGL::createWindowSurface(const egl::Config *configuration,
EGLNativeWindowType window, EGLNativeWindowType window,
const egl::AttributeMap &attribs) const egl::AttributeMap &attribs)
{ {
return new WindowSurfaceWGL(this->getRenderer(), window, mPixelFormat, mWGLContext, EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0);
mFunctionsWGL); if (mUseDXGISwapChains)
{
return new DXGISwapChainWindowSurfaceWGL(this->getRenderer(), window, mD3D11Device,
mD3D11DeviceHandle, mWGLContext, mDeviceContext,
mFunctionsGL, mFunctionsWGL, orientation);
}
else
{
return new WindowSurfaceWGL(this->getRenderer(), window, mPixelFormat, mWGLContext,
mFunctionsWGL, orientation);
}
} }
SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::Config *configuration, SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::Config *configuration,
...@@ -418,6 +477,9 @@ egl::ConfigSet DisplayWGL::generateConfigs() const ...@@ -418,6 +477,9 @@ egl::ConfigSet DisplayWGL::generateConfigs() const
return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL); return wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, attrib, mFunctionsWGL);
}; };
const EGLint optimalSurfaceOrientation =
mUseDXGISwapChains ? EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE : 0;
egl::Config config; egl::Config config;
config.renderTargetFormat = GL_RGBA8; // TODO: use the bit counts to determine the format 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.depthStencilFormat = GL_DEPTH24_STENCIL8; // TODO: use the bit counts to determine the format
...@@ -453,6 +515,8 @@ egl::ConfigSet DisplayWGL::generateConfigs() const ...@@ -453,6 +515,8 @@ egl::ConfigSet DisplayWGL::generateConfigs() const
((getAttrib(WGL_DRAW_TO_PBUFFER_ARB) == TRUE) ? EGL_PBUFFER_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 ((getAttrib(WGL_SWAP_METHOD_ARB) == WGL_SWAP_COPY_ARB) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT
: 0); : 0);
config.optimalOrientation = optimalSurfaceOrientation;
config.transparentType = EGL_NONE; config.transparentType = EGL_NONE;
config.transparentRedValue = 0; config.transparentRedValue = 0;
config.transparentGreenValue = 0; config.transparentGreenValue = 0;
...@@ -497,10 +561,60 @@ const FunctionsGL *DisplayWGL::getFunctionsGL() const ...@@ -497,10 +561,60 @@ const FunctionsGL *DisplayWGL::getFunctionsGL() const
return mFunctionsGL; 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 void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{ {
outExtensions->createContext = true; outExtensions->createContext = true;
outExtensions->createContextNoError = true; outExtensions->createContextNoError = true;
// 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;
} }
void DisplayWGL::generateCaps(egl::Caps *outCaps) const void DisplayWGL::generateCaps(egl::Caps *outCaps) const
...@@ -521,4 +635,52 @@ egl::Error DisplayWGL::waitNative(EGLint engine, ...@@ -521,4 +635,52 @@ egl::Error DisplayWGL::waitNative(EGLint engine,
// Unimplemented as this is not needed for WGL // Unimplemented as this is not needed for WGL
return egl::Error(EGL_SUCCESS); 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;
}
}
}
}
} }
...@@ -57,9 +57,14 @@ class DisplayWGL : public DisplayGL ...@@ -57,9 +57,14 @@ class DisplayWGL : public DisplayGL
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const override; egl::Surface *readSurface) const override;
egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle);
void releaseD3DDevice(HANDLE handle);
private: private:
const FunctionsGL *getFunctionsGL() const override; const FunctionsGL *getFunctionsGL() const override;
egl::Error initializeD3DDevice();
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
...@@ -74,6 +79,19 @@ class DisplayWGL : public DisplayGL ...@@ -74,6 +79,19 @@ class DisplayWGL : public DisplayGL
int mPixelFormat; int mPixelFormat;
HGLRC mWGLContext; 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; egl::Display *mDisplay;
}; };
......
...@@ -20,7 +20,8 @@ WindowSurfaceWGL::WindowSurfaceWGL(RendererGL *renderer, ...@@ -20,7 +20,8 @@ WindowSurfaceWGL::WindowSurfaceWGL(RendererGL *renderer,
EGLNativeWindowType window, EGLNativeWindowType window,
int pixelFormat, int pixelFormat,
HGLRC wglContext, HGLRC wglContext,
const FunctionsWGL *functions) const FunctionsWGL *functions,
EGLint orientation)
: SurfaceGL(renderer), : SurfaceGL(renderer),
mPixelFormat(pixelFormat), mPixelFormat(pixelFormat),
mWGLContext(wglContext), mWGLContext(wglContext),
...@@ -29,6 +30,8 @@ WindowSurfaceWGL::WindowSurfaceWGL(RendererGL *renderer, ...@@ -29,6 +30,8 @@ WindowSurfaceWGL::WindowSurfaceWGL(RendererGL *renderer,
mFunctionsWGL(functions), mFunctionsWGL(functions),
mSwapBehavior(0) mSwapBehavior(0)
{ {
// EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
ASSERT(orientation == 0);
} }
WindowSurfaceWGL::~WindowSurfaceWGL() WindowSurfaceWGL::~WindowSurfaceWGL()
......
...@@ -25,7 +25,8 @@ class WindowSurfaceWGL : public SurfaceGL ...@@ -25,7 +25,8 @@ class WindowSurfaceWGL : public SurfaceGL
EGLNativeWindowType window, EGLNativeWindowType window,
int pixelFormat, int pixelFormat,
HGLRC wglContext, HGLRC wglContext,
const FunctionsWGL *functions); const FunctionsWGL *functions,
EGLint orientation);
~WindowSurfaceWGL() override; ~WindowSurfaceWGL() override;
egl::Error initialize() override; egl::Error initialize() override;
......
...@@ -461,6 +461,8 @@ ...@@ -461,6 +461,8 @@
[ [
'libANGLE/renderer/gl/wgl/DisplayWGL.cpp', 'libANGLE/renderer/gl/wgl/DisplayWGL.cpp',
'libANGLE/renderer/gl/wgl/DisplayWGL.h', 'libANGLE/renderer/gl/wgl/DisplayWGL.h',
'libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp',
'libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h',
'libANGLE/renderer/gl/wgl/FunctionsWGL.cpp', 'libANGLE/renderer/gl/wgl/FunctionsWGL.cpp',
'libANGLE/renderer/gl/wgl/FunctionsWGL.h', 'libANGLE/renderer/gl/wgl/FunctionsWGL.h',
'libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp', 'libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.cpp',
......
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