diff options
Diffstat (limited to 'widget/windows/CompositorWidgetParent.cpp')
-rw-r--r-- | widget/windows/CompositorWidgetParent.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/widget/windows/CompositorWidgetParent.cpp b/widget/windows/CompositorWidgetParent.cpp new file mode 100644 index 0000000000..b25d30d9d5 --- /dev/null +++ b/widget/windows/CompositorWidgetParent.cpp @@ -0,0 +1,232 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "CompositorWidgetParent.h" + +#include "mozilla/Unused.h" +#include "mozilla/StaticPrefs_layers.h" +#include "mozilla/gfx/DeviceManagerDx.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/layers/Compositor.h" +#include "mozilla/layers/CompositorBridgeParent.h" +#include "mozilla/layers/CompositorThread.h" +#include "mozilla/webrender/RenderThread.h" +#include "mozilla/widget/PlatformWidgetTypes.h" +#include "nsWindow.h" +#include "VsyncDispatcher.h" +#include "WinCompositorWindowThread.h" +#include "VRShMem.h" +#include "RemoteBackbuffer.h" + +#include <ddraw.h> + +namespace mozilla { +namespace widget { + +using namespace mozilla::gfx; +using namespace mozilla; + +CompositorWidgetParent::CompositorWidgetParent( + const CompositorWidgetInitData& aInitData, + const layers::CompositorOptions& aOptions) + : WinCompositorWidget(aInitData.get_WinCompositorWidgetInitData(), + aOptions), + mWnd(reinterpret_cast<HWND>( + aInitData.get_WinCompositorWidgetInitData().hWnd())), + mTransparencyMode(uint32_t( + aInitData.get_WinCompositorWidgetInitData().transparencyMode())), + mSizeMode(nsSizeMode_Normal), + mIsFullyOccluded(false), + mRemoteBackbufferClient() { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU); + MOZ_ASSERT(mWnd && ::IsWindow(mWnd)); +} + +CompositorWidgetParent::~CompositorWidgetParent() {} + +bool CompositorWidgetParent::Initialize( + const RemoteBackbufferHandles& aRemoteHandles) { + mRemoteBackbufferClient = std::make_unique<remote_backbuffer::Client>(); + if (!mRemoteBackbufferClient->Initialize(aRemoteHandles)) { + return false; + } + + return true; +} + +bool CompositorWidgetParent::PreRender(WidgetRenderingContext* aContext) { + // This can block waiting for WM_SETTEXT to finish + // Using PreRender is unnecessarily pessimistic because + // we technically only need to block during the present call + // not all of compositor rendering + mPresentLock.Enter(); + return true; +} + +void CompositorWidgetParent::PostRender(WidgetRenderingContext* aContext) { + mPresentLock.Leave(); +} + +LayoutDeviceIntSize CompositorWidgetParent::GetClientSize() { + RECT r; + if (!::GetClientRect(mWnd, &r)) { + return LayoutDeviceIntSize(); + } + return LayoutDeviceIntSize(r.right - r.left, r.bottom - r.top); +} + +already_AddRefed<gfx::DrawTarget> +CompositorWidgetParent::StartRemoteDrawingInRegion( + const LayoutDeviceIntRegion& aInvalidRegion, + layers::BufferMode* aBufferMode) { + MOZ_ASSERT(mRemoteBackbufferClient); + MOZ_ASSERT(aBufferMode); + + // Because we use remote backbuffering, there is no need to use a local + // backbuffer too. + (*aBufferMode) = layers::BufferMode::BUFFER_NONE; + + return mRemoteBackbufferClient->BorrowDrawTarget(); +} + +void CompositorWidgetParent::EndRemoteDrawingInRegion( + gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) { + Unused << mRemoteBackbufferClient->PresentDrawTarget( + aInvalidRegion.ToUnknownRegion()); +} + +bool CompositorWidgetParent::NeedsToDeferEndRemoteDrawing() { return false; } + +already_AddRefed<gfx::DrawTarget> +CompositorWidgetParent::GetBackBufferDrawTarget(gfx::DrawTarget* aScreenTarget, + const gfx::IntRect& aRect, + bool* aOutIsCleared) { + MOZ_CRASH( + "Unexpected call to GetBackBufferDrawTarget() with remote " + "backbuffering in use"); +} + +already_AddRefed<gfx::SourceSurface> +CompositorWidgetParent::EndBackBufferDrawing() { + MOZ_CRASH( + "Unexpected call to EndBackBufferDrawing() with remote " + "backbuffering in use"); +} + +bool CompositorWidgetParent::InitCompositor(layers::Compositor* aCompositor) { + return true; +} + +bool CompositorWidgetParent::IsHidden() const { return ::IsIconic(mWnd); } + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvInitialize( + const RemoteBackbufferHandles& aRemoteHandles) { + Unused << Initialize(aRemoteHandles); + return IPC_OK(); +} + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvEnterPresentLock() { + mPresentLock.Enter(); + return IPC_OK(); +} + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvLeavePresentLock() { + mPresentLock.Leave(); + return IPC_OK(); +} + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvUpdateTransparency( + const TransparencyMode& aMode) { + mTransparencyMode = uint32_t(aMode); + return IPC_OK(); +} + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvNotifyVisibilityUpdated( + const nsSizeMode& aSizeMode, const bool& aIsFullyOccluded) { + mSizeMode = aSizeMode; + mIsFullyOccluded = aIsFullyOccluded; + return IPC_OK(); +} + +nsSizeMode CompositorWidgetParent::CompositorWidgetParent::GetWindowSizeMode() + const { + nsSizeMode sizeMode = mSizeMode; + return sizeMode; +} + +bool CompositorWidgetParent::CompositorWidgetParent::GetWindowIsFullyOccluded() + const { + bool isFullyOccluded = mIsFullyOccluded; + return isFullyOccluded; +} + +mozilla::ipc::IPCResult CompositorWidgetParent::RecvClearTransparentWindow() { + gfx::CriticalSectionAutoEnter lock(&mPresentLock); + + RefPtr<DrawTarget> drawTarget = mRemoteBackbufferClient->BorrowDrawTarget(); + if (!drawTarget) { + return IPC_OK(); + } + + IntSize size = drawTarget->GetSize(); + if (size.IsEmpty()) { + return IPC_OK(); + } + + drawTarget->ClearRect(Rect(0, 0, size.width, size.height)); + + Unused << mRemoteBackbufferClient->PresentDrawTarget( + IntRect(0, 0, size.width, size.height)); + + return IPC_OK(); +} + +nsIWidget* CompositorWidgetParent::RealWidget() { return nullptr; } + +void CompositorWidgetParent::ObserveVsync(VsyncObserver* aObserver) { + if (aObserver) { + Unused << SendObserveVsync(); + } else { + Unused << SendUnobserveVsync(); + } + mVsyncObserver = aObserver; +} + +RefPtr<VsyncObserver> CompositorWidgetParent::GetVsyncObserver() const { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU); + return mVsyncObserver; +} + +void CompositorWidgetParent::UpdateCompositorWnd(const HWND aCompositorWnd, + const HWND aParentWnd) { + MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread()); + MOZ_ASSERT(mRootLayerTreeID.isSome()); + + RefPtr<CompositorWidgetParent> self = this; + SendUpdateCompositorWnd(reinterpret_cast<WindowsHandle>(aCompositorWnd), + reinterpret_cast<WindowsHandle>(aParentWnd)) + ->Then( + layers::CompositorThread(), __func__, + [self](const bool& aSuccess) { + if (aSuccess && self->mRootLayerTreeID.isSome() && + layers::CompositorThreadHolder::IsActive()) { + self->mSetParentCompleted = true; + // Schedule composition after ::SetParent() call in parent + // process. + layers::CompositorBridgeParent::ScheduleForcedComposition( + self->mRootLayerTreeID.ref(), wr::RenderReasons::WIDGET); + } + }, + [self](const mozilla::ipc::ResponseRejectReason&) {}); +} + +void CompositorWidgetParent::SetRootLayerTreeID( + const layers::LayersId& aRootLayerTreeId) { + mRootLayerTreeID = Some(aRootLayerTreeId); +} + +void CompositorWidgetParent::ActorDestroy(ActorDestroyReason aWhy) {} + +} // namespace widget +} // namespace mozilla |