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::HasGlass() const {
122 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread() ||
123 wr::RenderThread::IsInRenderThread());
125 return mTransparencyMode
== uint32_t(TransparencyMode::BorderlessGlass
);
128 bool CompositorWidgetParent::IsHidden() const { return ::IsIconic(mWnd
); }
130 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvInitialize(
131 const RemoteBackbufferHandles
& aRemoteHandles
) {
132 Unused
<< Initialize(aRemoteHandles
);
136 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvEnterPresentLock() {
137 mPresentLock
.Enter();
141 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvLeavePresentLock() {
142 mPresentLock
.Leave();
146 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvUpdateTransparency(
147 const TransparencyMode
& aMode
) {
148 mTransparencyMode
= uint32_t(aMode
);
152 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvNotifyVisibilityUpdated(
153 const nsSizeMode
& aSizeMode
, const bool& aIsFullyOccluded
) {
154 mSizeMode
= aSizeMode
;
155 mIsFullyOccluded
= aIsFullyOccluded
;
159 nsSizeMode
CompositorWidgetParent::CompositorWidgetParent::GetWindowSizeMode()
161 nsSizeMode sizeMode
= mSizeMode
;
165 bool CompositorWidgetParent::CompositorWidgetParent::GetWindowIsFullyOccluded()
167 bool isFullyOccluded
= mIsFullyOccluded
;
168 return isFullyOccluded
;
171 mozilla::ipc::IPCResult
CompositorWidgetParent::RecvClearTransparentWindow() {
172 gfx::CriticalSectionAutoEnter
lock(&mPresentLock
);
174 RefPtr
<DrawTarget
> drawTarget
= mRemoteBackbufferClient
->BorrowDrawTarget();
179 IntSize size
= drawTarget
->GetSize();
180 if (size
.IsEmpty()) {
184 drawTarget
->ClearRect(Rect(0, 0, size
.width
, size
.height
));
186 Unused
<< mRemoteBackbufferClient
->PresentDrawTarget(
187 IntRect(0, 0, size
.width
, size
.height
));
192 nsIWidget
* CompositorWidgetParent::RealWidget() { return nullptr; }
194 void CompositorWidgetParent::ObserveVsync(VsyncObserver
* aObserver
) {
196 Unused
<< SendObserveVsync();
198 Unused
<< SendUnobserveVsync();
200 mVsyncObserver
= aObserver
;
203 RefPtr
<VsyncObserver
> CompositorWidgetParent::GetVsyncObserver() const {
204 MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU
);
205 return mVsyncObserver
;
208 void CompositorWidgetParent::UpdateCompositorWnd(const HWND aCompositorWnd
,
209 const HWND aParentWnd
) {
210 MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
211 MOZ_ASSERT(mRootLayerTreeID
.isSome());
213 RefPtr
<CompositorWidgetParent
> self
= this;
214 SendUpdateCompositorWnd(reinterpret_cast<WindowsHandle
>(aCompositorWnd
),
215 reinterpret_cast<WindowsHandle
>(aParentWnd
))
217 layers::CompositorThread(), __func__
,
218 [self
](const bool& aSuccess
) {
219 if (aSuccess
&& self
->mRootLayerTreeID
.isSome() &&
220 layers::CompositorThreadHolder::IsActive()) {
221 self
->mSetParentCompleted
= true;
222 // Schedule composition after ::SetParent() call in parent
224 layers::CompositorBridgeParent::ScheduleForcedComposition(
225 self
->mRootLayerTreeID
.ref(), wr::RenderReasons::WIDGET
);
228 [self
](const mozilla::ipc::ResponseRejectReason
&) {});
231 void CompositorWidgetParent::SetRootLayerTreeID(
232 const layers::LayersId
& aRootLayerTreeId
) {
233 mRootLayerTreeID
= Some(aRootLayerTreeId
);
236 void CompositorWidgetParent::ActorDestroy(ActorDestroyReason aWhy
) {}
238 } // namespace widget
239 } // namespace mozilla