Commit b7f1a8b0 by Geoff Lang

Create a child window in SurfaceD3D when needed.

BUG=angleproject:961 Change-Id: I61931961f8cb86b47012edd2bc08d0e1e7a5d0f7 Reviewed-on: https://chromium-review.googlesource.com/266515Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJohn Bauman <jbauman@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 5b028d18
...@@ -140,8 +140,37 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) ...@@ -140,8 +140,37 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
return result; return result;
} }
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
namespace
{
LRESULT CALLBACK IntermediateWindowProc(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ERASEBKGND:
// Prevent windows from erasing the background.
return 1;
case WM_PAINT:
// Do not paint anything.
PAINTSTRUCT paint;
if (BeginPaint(window, &paint))
{
EndPaint(window, &paint);
}
return 0;
}
return DefWindowProc(window, message, wParam, lParam);
}
}
#endif
DisplayD3D::DisplayD3D() DisplayD3D::DisplayD3D()
: mRenderer(nullptr), : mDisplay(nullptr),
mRenderer(nullptr),
mChildWindowClass(0),
mDevice(nullptr) mDevice(nullptr)
{ {
} }
...@@ -262,13 +291,45 @@ egl::Error DisplayD3D::initialize(egl::Display *display) ...@@ -262,13 +291,45 @@ egl::Error DisplayD3D::initialize(egl::Display *display)
ASSERT(mDevice == nullptr); ASSERT(mDevice == nullptr);
mDevice = new DeviceD3D(mRenderer); mDevice = new DeviceD3D(mRenderer);
return error;
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
// Work around compile error from not defining "UNICODE" while Chromium does
const LPSTR idcArrow = MAKEINTRESOURCEA(32512);
WNDCLASSA childWindowClassDesc = { 0 };
childWindowClassDesc.style = CS_OWNDC;
childWindowClassDesc.lpfnWndProc = IntermediateWindowProc;
childWindowClassDesc.cbClsExtra = 0;
childWindowClassDesc.cbWndExtra = 0;
childWindowClassDesc.hInstance = GetModuleHandle(nullptr);
childWindowClassDesc.hIcon = LoadIconA(nullptr, IDI_APPLICATION);
childWindowClassDesc.hCursor = LoadCursorA(nullptr, idcArrow);
childWindowClassDesc.hbrBackground = 0;
childWindowClassDesc.lpszMenuName = nullptr;
childWindowClassDesc.lpszClassName = "ANGLE DisplayD3D Child Window Class";
mChildWindowClass = RegisterClassA(&childWindowClassDesc);
if (!mChildWindowClass)
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to register child window class.");
}
#endif
return egl::Error(EGL_SUCCESS);
} }
void DisplayD3D::terminate() void DisplayD3D::terminate()
{ {
SafeDelete(mDevice); SafeDelete(mDevice);
SafeDelete(mRenderer); SafeDelete(mRenderer);
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (mChildWindowClass != 0)
{
UnregisterClassA(reinterpret_cast<const char*>(mChildWindowClass), NULL);
mChildWindowClass = 0;
}
#endif
} }
egl::ConfigSet DisplayD3D::generateConfigs() const egl::ConfigSet DisplayD3D::generateConfigs() const
...@@ -370,4 +431,9 @@ void DisplayD3D::generateCaps(egl::Caps *outCaps) const ...@@ -370,4 +431,9 @@ void DisplayD3D::generateCaps(egl::Caps *outCaps) const
outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT; outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT;
} }
ATOM DisplayD3D::getChildWindowClass() const
{
return mChildWindowClass;
}
} }
...@@ -50,6 +50,8 @@ class DisplayD3D : public DisplayImpl ...@@ -50,6 +50,8 @@ class DisplayD3D : public DisplayImpl
std::string getVendorString() const override; std::string getVendorString() const override;
ATOM getChildWindowClass() const;
private: private:
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;
...@@ -57,6 +59,7 @@ class DisplayD3D : public DisplayImpl ...@@ -57,6 +59,7 @@ class DisplayD3D : public DisplayImpl
egl::Display *mDisplay; egl::Display *mDisplay;
rx::RendererD3D *mRenderer; rx::RendererD3D *mRenderer;
ATOM mChildWindowClass;
DeviceImpl *mDevice; DeviceImpl *mDevice;
}; };
......
...@@ -97,6 +97,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D ...@@ -97,6 +97,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// Direct3D Specific methods // Direct3D Specific methods
virtual GUID getAdapterIdentifier() const = 0; virtual GUID getAdapterIdentifier() const = 0;
virtual bool shouldCreateChildWindowForSurface(EGLNativeWindowType window) const = 0;
virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h"
...@@ -46,6 +47,7 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl:: ...@@ -46,6 +47,7 @@ SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::
mNativeWindow(window), mNativeWindow(window),
mWidth(width), mWidth(width),
mHeight(height), mHeight(height),
mChildWindow(nullptr),
mSwapInterval(1), mSwapInterval(1),
mShareHandle(reinterpret_cast<HANDLE*>(shareHandle)) mShareHandle(reinterpret_cast<HANDLE*>(shareHandle))
{ {
...@@ -56,6 +58,13 @@ SurfaceD3D::~SurfaceD3D() ...@@ -56,6 +58,13 @@ SurfaceD3D::~SurfaceD3D()
{ {
unsubclassWindow(); unsubclassWindow();
releaseSwapChain(); releaseSwapChain();
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (mChildWindow.getNativeWindow() != nullptr)
{
DestroyWindow(mChildWindow.getNativeWindow());
}
#endif
} }
void SurfaceD3D::releaseSwapChain() void SurfaceD3D::releaseSwapChain()
...@@ -67,6 +76,44 @@ egl::Error SurfaceD3D::initialize() ...@@ -67,6 +76,44 @@ egl::Error SurfaceD3D::initialize()
{ {
if (mNativeWindow.getNativeWindow()) if (mNativeWindow.getNativeWindow())
{ {
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (mRenderer->shouldCreateChildWindowForSurface(mNativeWindow.getNativeWindow()))
{
RECT rect;
if (!mNativeWindow.getClientRect(&rect))
{
return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the size of the native window.");
}
DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(mDisplay);
ATOM windowClass = displayD3D->getChildWindowClass();
HWND childWindow = CreateWindowExA(WS_EX_NOPARENTNOTIFY,
reinterpret_cast<const char*>(windowClass),
"ANGLE Intermediate Surface Window",
WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
0,
0,
rect.right - rect.left,
rect.bottom - rect.top,
mNativeWindow.getNativeWindow(),
nullptr,
nullptr,
nullptr);
if (!childWindow)
{
return egl::Error(EGL_NOT_INITIALIZED, "Failed to create child window.");
}
mChildWindow = NativeWindow(childWindow);
if (!mChildWindow.initialize())
{
return egl::Error(EGL_BAD_SURFACE);
}
}
#endif
if (!mNativeWindow.initialize()) if (!mNativeWindow.initialize())
{ {
return egl::Error(EGL_BAD_SURFACE); return egl::Error(EGL_BAD_SURFACE);
...@@ -119,7 +166,8 @@ egl::Error SurfaceD3D::resetSwapChain() ...@@ -119,7 +166,8 @@ egl::Error SurfaceD3D::resetSwapChain()
height = mHeight; height = mHeight;
} }
mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); const NativeWindow &window = (mChildWindow.getNativeWindow() != nullptr) ? mChildWindow : mNativeWindow;
mSwapChain = mRenderer->createSwapChain(window, mShareHandle, mRenderTargetFormat, mDepthStencilFormat);
if (!mSwapChain) if (!mSwapChain)
{ {
return egl::Error(EGL_BAD_ALLOC); return egl::Error(EGL_BAD_ALLOC);
...@@ -155,6 +203,17 @@ egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight ...@@ -155,6 +203,17 @@ egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight
mWidth = backbufferWidth; mWidth = backbufferWidth;
mHeight = backbufferHeight; mHeight = backbufferHeight;
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (mChildWindow.getNativeWindow())
{
// Resize the child window
if (!MoveWindow(mChildWindow.getNativeWindow(), 0, 0, mWidth, mHeight, FALSE))
{
return egl::Error(EGL_BAD_SURFACE, "Failed to move the child window.");
}
}
#endif
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
......
...@@ -81,6 +81,8 @@ class SurfaceD3D : public SurfaceImpl ...@@ -81,6 +81,8 @@ class SurfaceD3D : public SurfaceImpl
EGLint mWidth; EGLint mWidth;
EGLint mHeight; EGLint mHeight;
NativeWindow mChildWindow;
EGLint mSwapInterval; EGLint mSwapInterval;
HANDLE mShareHandle; HANDLE mShareHandle;
......
...@@ -389,42 +389,6 @@ egl::Error Renderer11::initialize() ...@@ -389,42 +389,6 @@ egl::Error Renderer11::initialize()
ANGLE_HISTOGRAM_TIMES("GPU.ANGLE.D3D11CreateDeviceMS", createDeviceMS); ANGLE_HISTOGRAM_TIMES("GPU.ANGLE.D3D11CreateDeviceMS", createDeviceMS);
} }
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#if !ANGLE_SKIP_DXGI_1_2_CHECK
{
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
// In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
// The easiest way to check is to query for a IDXGIDevice2.
bool requireDXGI1_2 = false;
HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
if (hwnd)
{
DWORD currentProcessId = GetCurrentProcessId();
DWORD wndProcessId;
GetWindowThreadProcessId(hwnd, &wndProcessId);
requireDXGI1_2 = (currentProcessId != wndProcessId);
}
else
{
requireDXGI1_2 = true;
}
if (requireDXGI1_2)
{
IDXGIDevice2 *dxgiDevice2 = NULL;
result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2);
if (FAILED(result))
{
return egl::Error(EGL_NOT_INITIALIZED,
D3D11_INIT_INCOMPATIBLE_DXGI,
"DXGI 1.2 required to present to HWNDs owned by another process.");
}
SafeRelease(dxgiDevice2);
}
}
#endif
#endif
{ {
TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
// Cast the DeviceContext to a DeviceContext1. // Cast the DeviceContext to a DeviceContext1.
...@@ -714,6 +678,35 @@ gl::Error Renderer11::finish() ...@@ -714,6 +678,35 @@ gl::Error Renderer11::finish()
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
bool Renderer11::shouldCreateChildWindowForSurface(EGLNativeWindowType window) const
{
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
// In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
// The easiest way to check is to query for a IDXGIDevice2.
DWORD currentProcessId = GetCurrentProcessId();
DWORD wndProcessId;
GetWindowThreadProcessId(window, &wndProcessId);
if (currentProcessId == wndProcessId)
{
// Window is from this process, can always create a swap chain for it
return false;
}
IDXGIDevice2 *dxgiDevice2 = d3d11::DynamicCastComObject<IDXGIDevice2>(mDevice);
if (dxgiDevice2 != nullptr)
{
// DXGI 1.2 is available, can create a swap chain for this cross-process window
SafeRelease(dxgiDevice2);
return false;
}
// DXGI 1.2 is not available, need to create a child window.
return true;
#else
return false;
#endif
}
SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
{ {
return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
......
...@@ -95,6 +95,7 @@ class Renderer11 : public RendererD3D ...@@ -95,6 +95,7 @@ class Renderer11 : public RendererD3D
gl::Error flush() override; gl::Error flush() override;
gl::Error finish() override; gl::Error finish() override;
bool shouldCreateChildWindowForSurface(EGLNativeWindowType window) const override;
virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
virtual gl::Error generateSwizzle(gl::Texture *texture); virtual gl::Error generateSwizzle(gl::Texture *texture);
......
...@@ -637,6 +637,12 @@ gl::Error Renderer9::finish() ...@@ -637,6 +637,12 @@ gl::Error Renderer9::finish()
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
bool Renderer9::shouldCreateChildWindowForSurface(EGLNativeWindowType window) const
{
// D3D9 never needs to create child windows
return false;
}
SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
{ {
return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
......
...@@ -75,6 +75,7 @@ class Renderer9 : public RendererD3D ...@@ -75,6 +75,7 @@ class Renderer9 : public RendererD3D
gl::Error flush() override; gl::Error flush() override;
gl::Error finish() override; gl::Error finish() override;
bool shouldCreateChildWindowForSurface(EGLNativeWindowType window) const override;
virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
......
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