1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "base/basictypes.h"
9 #include "mozilla/dom/ContentParent.h"
10 #include "mozilla/dom/TabParent.h"
11 #include "mozilla/layers/CompositorBridgeParent.h"
12 #include "mozilla/layers/CompositorTypes.h"
13 #include "mozilla/layers/LayerTransactionParent.h"
14 #include "nsFrameLoader.h"
15 #include "nsStyleStructInlines.h"
16 #include "nsSubDocumentFrame.h"
17 #include "RenderFrame.h"
18 #include "mozilla/gfx/GPUProcessManager.h"
19 #include "mozilla/layers/CompositorBridgeChild.h"
20 #include "mozilla/layers/WebRenderLayerManager.h"
21 #include "mozilla/layers/WebRenderScrollData.h"
22 #include "mozilla/webrender/WebRenderAPI.h"
24 using namespace mozilla::dom
;
25 using namespace mozilla::gfx
;
26 using namespace mozilla::layers
;
31 static already_AddRefed
<LayerManager
> GetLayerManager(TabParent
* aTabParent
) {
32 if (Element
* element
= aTabParent
->GetOwnerElement()) {
33 if (RefPtr
<LayerManager
> lm
=
34 nsContentUtils::LayerManagerForContent(element
)) {
37 return nsContentUtils::LayerManagerForDocument(element
->OwnerDoc());
42 RenderFrame::RenderFrame()
45 mLayerManager(nullptr),
47 mLayersConnected(false) {}
49 RenderFrame::~RenderFrame() {}
51 bool RenderFrame::Initialize(TabParent
* aTabParent
) {
52 if (mInitialized
|| !aTabParent
) {
56 mTabParent
= aTabParent
;
57 RefPtr
<LayerManager
> lm
= GetLayerManager(mTabParent
);
58 PCompositorBridgeChild
* compositor
=
59 lm
? lm
->GetCompositorBridgeChild() : nullptr;
60 mTabProcessId
= mTabParent
->Manager()->OtherPid();
62 // Our remote frame will push layers updates to the compositor,
63 // and we'll keep an indirect reference to that tree.
64 GPUProcessManager
* gpm
= GPUProcessManager::Get();
65 mLayersConnected
= gpm
->AllocateAndConnectLayerTreeId(
66 compositor
, mTabProcessId
, &mLayersId
, &mCompositorOptions
);
72 void RenderFrame::Destroy() {
73 if (mLayersId
.IsValid()) {
74 GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId
, mTabProcessId
);
78 mLayerManager
= nullptr;
81 void RenderFrame::EnsureLayersConnected(CompositorOptions
* aCompositorOptions
) {
82 RefPtr
<LayerManager
> lm
= GetLayerManager(mTabParent
);
87 if (!lm
->GetCompositorBridgeChild()) {
91 mLayersConnected
= lm
->GetCompositorBridgeChild()->SendNotifyChildRecreated(
92 mLayersId
, &mCompositorOptions
);
93 *aCompositorOptions
= mCompositorOptions
;
96 LayerManager
* RenderFrame::AttachLayerManager() {
97 RefPtr
<LayerManager
> lm
;
99 lm
= GetLayerManager(mTabParent
);
102 // Perhaps the document containing this frame currently has no presentation?
103 if (lm
&& lm
->GetCompositorBridgeChild() && lm
!= mLayerManager
) {
105 lm
->GetCompositorBridgeChild()->SendAdoptChild(mLayersId
);
106 FrameLayerBuilder::InvalidateAllLayers(lm
);
109 mLayerManager
= lm
.forget();
110 return mLayerManager
;
113 void RenderFrame::OwnerContentChanged() { Unused
<< AttachLayerManager(); }
115 void RenderFrame::GetTextureFactoryIdentifier(
116 TextureFactoryIdentifier
* aTextureFactoryIdentifier
) const {
117 RefPtr
<LayerManager
> lm
= mTabParent
? GetLayerManager(mTabParent
) : nullptr;
118 // Perhaps the document containing this frame currently has no presentation?
120 *aTextureFactoryIdentifier
= lm
->GetTextureFactoryIdentifier();
122 *aTextureFactoryIdentifier
= TextureFactoryIdentifier();
126 } // namespace layout
127 } // namespace mozilla
130 * Gets the layer-pixel offset of aContainerFrame's content rect top-left
131 * from the nearest display item reference frame (which we assume will be
132 * inducing a ContainerLayer).
134 static mozilla::LayoutDeviceIntPoint
GetContentRectLayerOffset(
135 nsIFrame
* aContainerFrame
, nsDisplayListBuilder
* aBuilder
) {
136 nscoord auPerDevPixel
= aContainerFrame
->PresContext()->AppUnitsPerDevPixel();
138 // Offset to the content rect in case we have borders or padding
139 // Note that aContainerFrame could be a reference frame itself, so
140 // we need to be careful here to ensure that we call ToReferenceFrame
141 // on aContainerFrame and not its parent.
142 nsPoint frameOffset
=
143 aBuilder
->ToReferenceFrame(aContainerFrame
) +
144 aContainerFrame
->GetContentRectRelativeToSelf().TopLeft();
146 return mozilla::LayoutDeviceIntPoint::FromAppUnitsToNearest(frameOffset
,
150 // Return true iff |aManager| is a "temporary layer manager". They're
151 // used for small software rendering tasks, like drawWindow. That's
152 // currently implemented by a BasicLayerManager without a backing
153 // widget, and hence in non-retained mode.
154 inline static bool IsTempLayerManager(mozilla::layers::LayerManager
* aManager
) {
155 return (mozilla::layers::LayersBackend::LAYERS_BASIC
==
156 aManager
->GetBackendType() &&
157 !static_cast<BasicLayerManager
*>(aManager
)->IsRetained());
160 nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder
* aBuilder
,
161 nsSubDocumentFrame
* aFrame
)
162 : nsDisplayItem(aBuilder
, aFrame
),
164 mEventRegionsOverride(EventRegionsOverride::NoOverride
) {
165 bool frameIsPointerEventsNone
= aFrame
->StyleUI()->GetEffectivePointerEvents(
166 aFrame
) == NS_STYLE_POINTER_EVENTS_NONE
;
167 if (aBuilder
->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone
) {
168 mEventRegionsOverride
|= EventRegionsOverride::ForceEmptyHitRegion
;
170 if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(
171 aFrame
->PresShell())) {
172 mEventRegionsOverride
|= EventRegionsOverride::ForceDispatchToContent
;
175 nsFrameLoader
* frameLoader
= GetFrameLoader();
176 MOZ_ASSERT(frameLoader
&& frameLoader
->IsRemoteFrame());
177 mLayersId
= frameLoader
->GetLayersId();
179 if (nsFrameLoader
* frameLoader
= GetFrameLoader()) {
180 // TODO: We need to handle acquiring a TabId in the remote sub-frame case
182 if (TabParent
* browser
= TabParent::GetFrom(frameLoader
)) {
183 mTabId
= browser
->GetTabId();
188 mozilla::LayerState
nsDisplayRemote::GetLayerState(
189 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
190 const ContainerLayerParameters
& aParameters
) {
191 if (IsTempLayerManager(aManager
)) {
192 return mozilla::LAYER_NONE
;
194 return mozilla::LAYER_ACTIVE_FORCE
;
197 bool nsDisplayRemote::HasDeletedFrame() const {
198 // RenderFrame might change without invalidating nsSubDocumentFrame.
199 return !GetFrameLoader() || nsDisplayItem::HasDeletedFrame();
202 already_AddRefed
<Layer
> nsDisplayRemote::BuildLayer(
203 nsDisplayListBuilder
* aBuilder
, LayerManager
* aManager
,
204 const ContainerLayerParameters
& aContainerParameters
) {
205 MOZ_ASSERT(mFrame
, "Makes no sense to have a shadow tree without a frame");
207 if (IsTempLayerManager(aManager
)) {
208 // This can happen if aManager is a "temporary" manager, or if the
209 // widget's layer manager changed out from under us. We need to
210 // FIXME handle the former case somehow, probably with an API to
211 // draw a manager's subtree. The latter is bad bad bad, but the the
212 // MOZ_ASSERT() above will flag it. Returning nullptr here will just
213 // cause the shadow subtree not to be rendered.
214 if (!aContainerParameters
.mForEventsAndPluginsOnly
) {
215 NS_WARNING("Remote iframe not rendered");
220 if (!mLayersId
.IsValid()) {
224 RefPtr
<Layer
> layer
=
225 aManager
->GetLayerBuilder()->GetLeafLayerFor(aBuilder
, this);
228 layer
= aManager
->CreateRefLayer();
232 // Probably a temporary layer manager that doesn't know how to
237 static_cast<RefLayer
*>(layer
.get())->SetReferentId(mLayersId
);
238 LayoutDeviceIntPoint offset
= GetContentRectLayerOffset(Frame(), aBuilder
);
239 // We can only have an offset if we're a child of an inactive
240 // container, but our display item is LAYER_ACTIVE_FORCE which
241 // forces all layers above to be active.
242 MOZ_ASSERT(aContainerParameters
.mOffset
== nsIntPoint());
243 Matrix4x4 m
= Matrix4x4::Translation(offset
.x
, offset
.y
, 0.0);
244 // Remote content can't be repainted by us, so we multiply down
245 // the resolution that our container expects onto our container.
246 m
.PreScale(aContainerParameters
.mXScale
, aContainerParameters
.mYScale
, 1.0);
247 layer
->SetBaseTransform(m
);
249 if (layer
->AsRefLayer()) {
250 layer
->AsRefLayer()->SetEventRegionsOverride(mEventRegionsOverride
);
253 return layer
.forget();
256 void nsDisplayRemote::Paint(nsDisplayListBuilder
* aBuilder
, gfxContext
* aCtx
) {
257 DrawTarget
* target
= aCtx
->GetDrawTarget();
258 if (!target
->IsRecording() || mTabId
== 0) {
259 NS_WARNING("Remote iframe not rendered");
263 int32_t appUnitsPerDevPixel
= mFrame
->PresContext()->AppUnitsPerDevPixel();
264 Rect destRect
= mozilla::NSRectToSnappedRect(GetContentRect(),
265 appUnitsPerDevPixel
, *target
);
266 target
->DrawDependentSurface(mTabId
, destRect
);
269 bool nsDisplayRemote::CreateWebRenderCommands(
270 mozilla::wr::DisplayListBuilder
& aBuilder
,
271 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
272 const StackingContextHelper
& aSc
,
273 mozilla::layers::RenderRootStateManager
* aManager
,
274 nsDisplayListBuilder
* aDisplayListBuilder
) {
275 if (!mLayersId
.IsValid()) {
279 mOffset
= GetContentRectLayerOffset(mFrame
, aDisplayListBuilder
);
281 LayoutDeviceRect rect
= LayoutDeviceRect::FromAppUnits(
282 mFrame
->GetContentRectRelativeToSelf(),
283 mFrame
->PresContext()->AppUnitsPerDevPixel());
286 aBuilder
.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect
),
287 !BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId
),
288 /*ignoreMissingPipelines*/ true);
293 bool nsDisplayRemote::UpdateScrollData(
294 mozilla::layers::WebRenderScrollData
* aData
,
295 mozilla::layers::WebRenderLayerScrollData
* aLayerData
) {
296 if (!mLayersId
.IsValid()) {
301 aLayerData
->SetReferentId(mLayersId
);
302 aLayerData
->SetTransform(
303 mozilla::gfx::Matrix4x4::Translation(mOffset
.x
, mOffset
.y
, 0.0));
304 aLayerData
->SetEventRegionsOverride(mEventRegionsOverride
);
309 nsFrameLoader
* nsDisplayRemote::GetFrameLoader() const {
310 return mFrame
? static_cast<nsSubDocumentFrame
*>(mFrame
)->FrameLoader()