diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp index b1f7d7fb3c16..9be0bd60886c 100644 --- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -79,6 +79,7 @@ #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop #ifdef XP_WIN #include "mozilla/layers/CompositorD3D11.h" +#include "mozilla/widget/WinCompositorWidget.h" #endif #include "GeckoProfiler.h" #include "mozilla/ipc/ProtocolTypes.h" @@ -1749,9 +1750,14 @@ CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipel MOZ_ASSERT(!mWrBridge); MOZ_ASSERT(!mCompositor); MOZ_ASSERT(!mCompositorScheduler); - - MOZ_ASSERT(mWidget); + +#ifdef XP_WIN + if (XRE_IsGPUProcess() && gfx::gfxVars::UseWebRenderANGLE() && mWidget) { + mWidget->AsWindows()->EnsureCompositorWindow(); + } +#endif + RefPtr widget = mWidget; RefPtr api = wr::WebRenderAPI::Create(this, Move(widget), aSize); if (!api) { @@ -1796,6 +1802,11 @@ CompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aA it->second.mWrBridge = nullptr; } } +#ifdef XP_WIN + if (XRE_IsGPUProcess() && gfx::gfxVars::UseWebRenderANGLE() && mWidget) { + mWidget->AsWindows()->DestroyCompositorWindow(); + } +#endif parent->Release(); // IPDL reference return true; } diff --git a/gfx/webrender_bindings/RenderCompositorANGLE.cpp b/gfx/webrender_bindings/RenderCompositorANGLE.cpp index db21654b0306..3d982b52f9cf 100644 --- a/gfx/webrender_bindings/RenderCompositorANGLE.cpp +++ b/gfx/webrender_bindings/RenderCompositorANGLE.cpp @@ -196,6 +196,8 @@ RenderCompositorANGLE::Initialize() bool RenderCompositorANGLE::BeginFrame() { + mWidget->AsWindows()->UpdateCompositorWndSizeIfNecessary(); + if (!ResizeBufferIfNeeded()) { return false; } diff --git a/gfx/webrender_bindings/RenderThread.cpp b/gfx/webrender_bindings/RenderThread.cpp index e98128c220f9..8a49dd3de77f 100644 --- a/gfx/webrender_bindings/RenderThread.cpp +++ b/gfx/webrender_bindings/RenderThread.cpp @@ -16,6 +16,10 @@ #include "mozilla/webrender/RenderTextureHost.h" #include "mozilla/widget/CompositorWidget.h" +#ifdef XP_WIN +#include "mozilla/widget/WinCompositorWindowThread.h" +#endif + namespace mozilla { namespace wr { @@ -60,6 +64,9 @@ RenderThread::Start() } sRenderThread = new RenderThread(thread); +#ifdef XP_WIN + widget::WinCompositorWindowThread::Start(); +#endif } // static @@ -83,6 +90,9 @@ RenderThread::ShutDown() task.Wait(); sRenderThread = nullptr; +#ifdef XP_WIN + widget::WinCompositorWindowThread::ShutDown(); +#endif } void diff --git a/widget/windows/WinCompositorWidget.cpp b/widget/windows/WinCompositorWidget.cpp index 5f28bb13b606..383b61a4e4e9 100644 --- a/widget/windows/WinCompositorWidget.cpp +++ b/widget/windows/WinCompositorWidget.cpp @@ -11,6 +11,7 @@ #include "mozilla/widget/PlatformWidgetTypes.h" #include "nsWindow.h" #include "VsyncDispatcher.h" +#include "WinCompositorWindowThread.h" #include @@ -24,6 +25,7 @@ WinCompositorWidget::WinCompositorWidget(const WinCompositorWidgetInitData& aIni : CompositorWidget(aOptions) , mWidgetKey(aInitData.widgetKey()), mWnd(reinterpret_cast(aInitData.hWnd())), + mCompositorWnd(nullptr), mTransparencyMode(static_cast(aInitData.transparencyMode())), mMemoryDC(nullptr), mCompositeDC(nullptr), @@ -38,6 +40,11 @@ WinCompositorWidget::WinCompositorWidget(const WinCompositorWidgetInitData& aIni gfxPlatform::ForceSoftwareVsync(); } +WinCompositorWidget::~WinCompositorWidget() +{ + DestroyCompositorWindow(); +} + void WinCompositorWidget::OnDestroyWindow() { @@ -339,5 +346,48 @@ WinCompositorWidget::IsHidden() const return ::IsIconic(mWnd); } +void +WinCompositorWidget::EnsureCompositorWindow() +{ + if (mCompositorWnd) { + return; + } + mCompositorWnd = WinCompositorWindowThread::CreateCompositorWindow(mWnd); + MOZ_ASSERT(mCompositorWnd); +} + +void +WinCompositorWidget::DestroyCompositorWindow() +{ + if (!mCompositorWnd) { + return; + } + WinCompositorWindowThread::DestroyCompositorWindow(mCompositorWnd); + mCompositorWnd = nullptr; +} + +void +WinCompositorWidget::UpdateCompositorWndSizeIfNecessary() +{ + MOZ_ASSERT(mCompositorWnd); + + if (!mCompositorWnd) { + return; + } + + LayoutDeviceIntSize size = GetClientSize(); + if (mLastCompositorWndSize == size) { + return; + } + + // Force a resize and redraw (but not a move, activate, etc.). + if (!::SetWindowPos(mCompositorWnd, nullptr, 0, 0, size.width, size.height, + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOOWNERZORDER | SWP_NOZORDER)) { + return; + } + mLastCompositorWndSize = size; +} + } // namespace widget } // namespace mozilla diff --git a/widget/windows/WinCompositorWidget.h b/widget/windows/WinCompositorWidget.h index 97d957047ef3..ab4377a24258 100644 --- a/widget/windows/WinCompositorWidget.h +++ b/widget/windows/WinCompositorWidget.h @@ -54,6 +54,7 @@ class WinCompositorWidget public: WinCompositorWidget(const WinCompositorWidgetInitData& aInitData, const layers::CompositorOptions& aOptions); + ~WinCompositorWidget() override; // CompositorWidget Overrides @@ -94,9 +95,19 @@ public: return mMemoryDC; } HWND GetHwnd() const { - return mWnd; + return mCompositorWnd ? mCompositorWnd : mWnd; } + HWND GetCompositorHwnd() const { + return mCompositorWnd; + } + + void EnsureCompositorWindow(); + void DestroyCompositorWindow(); + void UpdateCompositorWndSizeIfNecessary(); + +protected: + private: HDC GetWindowSurface(); void FreeWindowSurface(HDC dc); @@ -106,6 +117,10 @@ private: private: uintptr_t mWidgetKey; HWND mWnd; + + HWND mCompositorWnd; + LayoutDeviceIntSize mLastCompositorWndSize; + gfx::CriticalSection mPresentLock; // Transparency handling. diff --git a/widget/windows/WinCompositorWindowThread.cpp b/widget/windows/WinCompositorWindowThread.cpp new file mode 100644 index 000000000000..3810fad5b714 --- /dev/null +++ b/widget/windows/WinCompositorWindowThread.cpp @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "base/platform_thread.h" +#include "WinCompositorWindowThread.h" +#include "mozilla/layers/SynchronousTask.h" +#include "mozilla/StaticPtr.h" +#include "mtransport/runnable_utils.h" + +namespace mozilla { +namespace widget { + +static StaticRefPtr sWinCompositorWindowThread; + +WinCompositorWindowThread::WinCompositorWindowThread(base::Thread* aThread) + : mThread(aThread) +{ +} + +WinCompositorWindowThread::~WinCompositorWindowThread() +{ + delete mThread; +} + +/* static */ WinCompositorWindowThread* +WinCompositorWindowThread::Get() +{ + return sWinCompositorWindowThread; +} + +/* static */ void +WinCompositorWindowThread::Start() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!sWinCompositorWindowThread); + + base::Thread* thread = new base::Thread("Renderer"); + + base::Thread::Options options; + // HWND requests ui thread. + options.message_loop_type = MessageLoop::TYPE_UI; + + if (!thread->StartWithOptions(options)) { + delete thread; + return; + } + + sWinCompositorWindowThread = new WinCompositorWindowThread(thread); +} + +/* static */ void +WinCompositorWindowThread::ShutDown() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(sWinCompositorWindowThread); + + layers::SynchronousTask task("WinCompositorWindowThread"); + RefPtr runnable = WrapRunnable( + RefPtr(sWinCompositorWindowThread.get()), + &WinCompositorWindowThread::ShutDownTask, + &task); + sWinCompositorWindowThread->Loop()->PostTask(runnable.forget()); + task.Wait(); + + sWinCompositorWindowThread = nullptr; +} + +void +WinCompositorWindowThread::ShutDownTask(layers::SynchronousTask* aTask) +{ + layers::AutoCompleteTask complete(aTask); + MOZ_ASSERT(IsInCompositorWindowThread()); +} + +/* static */ MessageLoop* +WinCompositorWindowThread::Loop() +{ + return sWinCompositorWindowThread ? sWinCompositorWindowThread->mThread->message_loop() : nullptr; +} + +/* static */ bool +WinCompositorWindowThread::IsInCompositorWindowThread() +{ + return sWinCompositorWindowThread && sWinCompositorWindowThread->mThread->thread_id() == PlatformThread::CurrentId(); +} + +const wchar_t kClassNameCompositor[] = L"MozillaCompositorWindowClass"; + +ATOM g_compositor_window_class; + +// This runs on the window owner thread. +void InitializeWindowClass() { + + if (g_compositor_window_class) { + return; + } + + WNDCLASSW wc; + wc.style = CS_OWNDC; + wc.lpfnWndProc = ::DefWindowProcW; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(nullptr); + wc.hIcon = nullptr; + wc.hCursor = nullptr; + wc.hbrBackground = nullptr; + wc.lpszMenuName = nullptr; + wc.lpszClassName = kClassNameCompositor; + g_compositor_window_class = ::RegisterClassW(&wc); +} + +/* static */ HWND +WinCompositorWindowThread::CreateCompositorWindow(HWND aParentWnd) +{ + MOZ_ASSERT(Loop()); + MOZ_ASSERT(aParentWnd); + + if (!Loop()) { + return nullptr; + } + + layers::SynchronousTask task("Create compositor window"); + + HWND compositorWnd = nullptr; + + RefPtr runnable = + NS_NewRunnableFunction("WinCompositorWindowThread::CreateCompositorWindow::Runnable", [&]() { + layers::AutoCompleteTask complete(&task); + + InitializeWindowClass(); + + compositorWnd = + ::CreateWindowEx(WS_EX_NOPARENTNOTIFY, + kClassNameCompositor, + nullptr, + WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, + 0, 0, 1, 1, + aParentWnd, 0, GetModuleHandle(nullptr), 0); + }); + + Loop()->PostTask(runnable.forget()); + + task.Wait(); + + return compositorWnd; +} + +/* static */ void +WinCompositorWindowThread::DestroyCompositorWindow(HWND aWnd) +{ + MOZ_ASSERT(aWnd); + MOZ_ASSERT(Loop()); + + if (!Loop()) { + return; + } + + RefPtr runnable = + NS_NewRunnableFunction("WinCompositorWidget::CreateNativeWindow::Runnable", [aWnd]() { + ::DestroyWindow(aWnd); + }); + + Loop()->PostTask(runnable.forget()); +} + +} // namespace widget +} // namespace mozilla diff --git a/widget/windows/WinCompositorWindowThread.h b/widget/windows/WinCompositorWindowThread.h new file mode 100644 index 000000000000..ea9c4a3bc499 --- /dev/null +++ b/widget/windows/WinCompositorWindowThread.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef widget_windows_WinCompositorWindowThread_h +#define widget_windows_WinCompositorWindowThread_h + +#include "base/thread.h" +#include "base/message_loop.h" +#include "ThreadSafeRefcountingWithMainThreadDestruction.h" + +namespace mozilla { + +namespace layers { +class SynchronousTask; +} + +namespace widget { + +class WinCompositorWindowThread final +{ + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(WinCompositorWindowThread) + +public: + /// Can be called from any thread. + static WinCompositorWindowThread* Get(); + + /// Can only be called from the main thread. + static void Start(); + + /// Can only be called from the main thread. + static void ShutDown(); + + /// Can be called from any thread. + static MessageLoop* Loop(); + + /// Can be called from any thread. + static bool IsInCompositorWindowThread(); + + /// Can be called from any thread. + static HWND CreateCompositorWindow(HWND aParentWnd); + + /// Can be called from any thread. + static void DestroyCompositorWindow(HWND aWnd); + +private: + explicit WinCompositorWindowThread(base::Thread* aThread); + ~WinCompositorWindowThread(); + + void ShutDownTask(layers::SynchronousTask* aTask); + + base::Thread* const mThread; +}; + +} // namespace widget +} // namespace mozilla + +#endif // widget_windows_WinCompositorWindowThread_h diff --git a/widget/windows/moz.build b/widget/windows/moz.build index b3cfc4ed48a0..a15d35a7e2e8 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -30,6 +30,7 @@ EXPORTS.mozilla.widget += [ 'PDFiumProcessParent.h', 'PDFViaEMFPrintHelper.h', 'WinCompositorWidget.h', + 'WinCompositorWindowThread.h', 'WindowsEMF.h', 'WinMessages.h', 'WinModifierKeyState.h', @@ -74,6 +75,7 @@ UNIFIED_SOURCES += [ 'TaskbarTabPreview.cpp', 'TaskbarWindowPreview.cpp', 'WidgetTraceEvent.cpp', + 'WinCompositorWindowThread.cpp', 'WindowHook.cpp', 'WinIMEHandler.cpp', 'WinPointerEvents.cpp',