1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "CompositorWidgetParent.h"
7 #include "mozilla/Unused.h"
8 #include "mozilla/StaticPrefs_layers.h"
9 #include "mozilla/gfx/DeviceManagerDx.h"
10 #include "mozilla/gfx/Point.h"
11 #include "mozilla/layers/Compositor.h"
12 #include "mozilla/layers/CompositorBridgeParent.h"
13 #include "mozilla/layers/CompositorThread.h"
14 #include "mozilla/webrender/RenderThread.h"
15 #include "mozilla/widget/PlatformWidgetTypes.h"
17 #include "VsyncDispatcher.h"
18 #include "WinCompositorWindowThread.h"
20 #include "RemoteBackbuffer.h"
27 using namespace mozilla::gfx
;
28 using namespace mozilla
;
30 CompositorWidgetParent::CompositorWidgetParent(
31 const CompositorWidgetInitData
& aInitData
,
32 const layers::CompositorOptions
& aOptions
)
33 : WinCompositorWidget(aInitData
.get_WinCompositorWidgetInitData(),
35 mWnd(reinterpret_cast<HWND
>(
36 aInitData
.get_WinCompositorWidgetInitData().hWnd())),
37 mTransparencyMode(uint32_t(
38 aInitData
.get_WinCompositorWidgetInitData().transparencyMode())),
39 mSizeMode(nsSizeMode_Normal
),
40 mIsFullyOccluded(false),
41 mRemoteBackbufferClient() {
42 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU
);
43 MOZ_ASSERT(mWnd
&& ::IsWindow(mWnd
));
46 CompositorWidgetParent::~CompositorWidgetParent() {}
48 bool CompositorWidgetParent::Initialize(
49 const RemoteBackbufferHandles
& aRemoteHandles
) {
50 mRemoteBackbufferClient
= std::make_unique
<remote_backbuffer::Client
>();
51 if (!mRemoteBackbufferClient
->Initialize(aRemoteHandles
)) {
58 bool CompositorWidgetParent::PreRender(WidgetRenderingContext
* aContext
) {
59 // This can block waiting for WM_SETTEXT to finish
60 // Using PreRender is unnecessarily pessimistic because
61 // we technically only need to block during the present call
62 // not all of compositor rendering
67 void CompositorWidgetParent::PostRender(WidgetRenderingContext
* aContext
) {
71 LayoutDeviceIntSize
CompositorWidgetParent::GetClientSize() {
73 if (!::GetClientRect(mWnd
, &r
)) {
74 return LayoutDeviceIntSize();
76 return LayoutDeviceIntSize(r
.right
- r
.left
, r
.bottom
- r
.top
);
79 already_AddRefed
<gfx::DrawTarget
>
80 CompositorWidgetParent::StartRemoteDrawingInRegion(
81 const LayoutDeviceIntRegion
& aInvalidRegion
,
82 layers::BufferMode
* aBufferMode
) {
83 MOZ_ASSERT(mRemoteBackbufferClient
);
84 MOZ_ASSERT(aBufferMode
);
86 // Because we use remote backbuffering, there is no need to use a local
88 (*aBufferMode
) = layers::BufferMode::BUFFER_NONE
;
90 return mRemoteBackbufferClient
->BorrowDrawTarget();
93 void CompositorWidgetParent::EndRemoteDrawingInRegion(
94 gfx::DrawTarget
* aDrawTarget
, const LayoutDeviceIntRegion
& aInvalidRegion
) {
95 Unused
<< mRemoteBackbufferClient
->PresentDrawTarget(
96 aInvalidRegion
.ToUnknownRegion());
99 bool CompositorWidgetParent::NeedsToDeferEndRemoteDrawing() { return false; }
101 already_AddRefed
<gfx::DrawTarget
>
102 CompositorWidgetParent::GetBackBufferDrawTarget(gfx::DrawTarget
* aScreenTarget
,
103 const gfx::IntRect
& aRect
,
104 bool* aOutIsCleared
) {
106 "Unexpected call to GetBackBufferDrawTarget() with remote "
107 "backbuffering in use");
110 already_AddRefed
<gfx::SourceSurface
>
111 CompositorWidgetParent::EndBackBufferDrawing() {
113 "Unexpected call to EndBackBufferDrawing() with remote "
114 "backbuffering in use");
117 bool CompositorWidgetParent::InitCompositor(layers::Compositor
* aCompositor
) {
121 bool CompositorWidgetParent::IsHidden() const { return ::IsIconic(mWnd
); }
123 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvInitialize(
124 const RemoteBackbufferHandles
& aRemoteHandles
) {
125 Unused
<< Initialize(aRemoteHandles
);
129 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvEnterPresentLock() {
130 mPresentLock
.Enter();
134 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvLeavePresentLock() {
135 mPresentLock
.Leave();
139 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvUpdateTransparency(
140 const TransparencyMode
& aMode
) {
141 mTransparencyMode
= uint32_t(aMode
);
145 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvNotifyVisibilityUpdated(
146 const nsSizeMode
& aSizeMode
, const bool& aIsFullyOccluded
) {
147 mSizeMode
= aSizeMode
;
148 mIsFullyOccluded
= aIsFullyOccluded
;
152 nsSizeMode
CompositorWidgetParent::CompositorWidgetParent::GetWindowSizeMode()
154 nsSizeMode sizeMode
= mSizeMode
;
158 bool CompositorWidgetParent::CompositorWidgetParent::GetWindowIsFullyOccluded()
160 bool isFullyOccluded
= mIsFullyOccluded
;
161 return isFullyOccluded
;
164 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvClearTransparentWindow() {
165 gfx::CriticalSectionAutoEnter
lock(&mPresentLock
);
167 RefPtr
<DrawTarget
> drawTarget
= mRemoteBackbufferClient
->BorrowDrawTarget();
172 IntSize size
= drawTarget
->GetSize();
173 if (size
.IsEmpty()) {
177 drawTarget
->ClearRect(Rect(0, 0, size
.width
, size
.height
));
179 Unused
<< mRemoteBackbufferClient
->PresentDrawTarget(
180 IntRect(0, 0, size
.width
, size
.height
));
185 nsIWidget
* CompositorWidgetParent::RealWidget() { return nullptr; }
187 void CompositorWidgetParent::ObserveVsync(VsyncObserver
* aObserver
) {
189 Unused
<< SendObserveVsync();
191 Unused
<< SendUnobserveVsync();
193 mVsyncObserver
= aObserver
;
196 RefPtr
<VsyncObserver
> CompositorWidgetParent::GetVsyncObserver() const {
197 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU
);
198 return mVsyncObserver
;
201 void CompositorWidgetParent::UpdateCompositorWnd(const HWND aCompositorWnd
,
202 const HWND aParentWnd
) {
203 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
204 MOZ_ASSERT(mRootLayerTreeID
.isSome());
206 RefPtr
<CompositorWidgetParent
> self
= this;
207 SendUpdateCompositorWnd(reinterpret_cast<WindowsHandle
>(aCompositorWnd
),
208 reinterpret_cast<WindowsHandle
>(aParentWnd
))
210 layers::CompositorThread(), __func__
,
211 [self
](const bool& aSuccess
) {
212 if (aSuccess
&& self
->mRootLayerTreeID
.isSome() &&
213 layers::CompositorThreadHolder::IsActive()) {
214 self
->mSetParentCompleted
= true;
215 // Schedule composition after ::SetParent() call in parent
217 layers::CompositorBridgeParent::ScheduleForcedComposition(
218 self
->mRootLayerTreeID
.ref(), wr::RenderReasons::WIDGET
);
221 [self
](const mozilla::ipc::ResponseRejectReason
&) {});
224 void CompositorWidgetParent::SetRootLayerTreeID(
225 const layers::LayersId
& aRootLayerTreeId
) {
226 mRootLayerTreeID
= Some(aRootLayerTreeId
);
229 void CompositorWidgetParent::ActorDestroy(ActorDestroyReason aWhy
) {}
231 } // namespace widget
232 } // namespace mozilla