Bug 1535077 - Switch to using Ref and PureComponent in the SearchBox component. r...
[gecko.git] / layout / ipc / RenderFrame.cpp
blob337004859f166b6deedb2b8a87db0312e60ed4a0
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;
28 namespace mozilla {
29 namespace layout {
31 static already_AddRefed<LayerManager> GetLayerManager(TabParent* aTabParent) {
32 if (Element* element = aTabParent->GetOwnerElement()) {
33 if (RefPtr<LayerManager> lm =
34 nsContentUtils::LayerManagerForContent(element)) {
35 return lm.forget();
37 return nsContentUtils::LayerManagerForDocument(element->OwnerDoc());
39 return nullptr;
42 RenderFrame::RenderFrame()
43 : mLayersId{0},
44 mTabParent(nullptr),
45 mLayerManager(nullptr),
46 mInitialized(false),
47 mLayersConnected(false) {}
49 RenderFrame::~RenderFrame() {}
51 bool RenderFrame::Initialize(TabParent* aTabParent) {
52 if (mInitialized || !aTabParent) {
53 return false;
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);
68 mInitialized = true;
69 return true;
72 void RenderFrame::Destroy() {
73 if (mLayersId.IsValid()) {
74 GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, mTabProcessId);
77 mTabParent = nullptr;
78 mLayerManager = nullptr;
81 void RenderFrame::EnsureLayersConnected(CompositorOptions* aCompositorOptions) {
82 RefPtr<LayerManager> lm = GetLayerManager(mTabParent);
83 if (!lm) {
84 return;
87 if (!lm->GetCompositorBridgeChild()) {
88 return;
91 mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated(
92 mLayersId, &mCompositorOptions);
93 *aCompositorOptions = mCompositorOptions;
96 LayerManager* RenderFrame::AttachLayerManager() {
97 RefPtr<LayerManager> lm;
98 if (mTabParent) {
99 lm = GetLayerManager(mTabParent);
102 // Perhaps the document containing this frame currently has no presentation?
103 if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) {
104 mLayersConnected =
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?
119 if (lm) {
120 *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier();
121 } else {
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,
147 auPerDevPixel);
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),
163 mTabId{0},
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
181 // for fission.
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");
217 return nullptr;
220 if (!mLayersId.IsValid()) {
221 return nullptr;
224 RefPtr<Layer> layer =
225 aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this);
227 if (!layer) {
228 layer = aManager->CreateRefLayer();
231 if (!layer) {
232 // Probably a temporary layer manager that doesn't know how to
233 // use ref layers.
234 return nullptr;
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");
260 return;
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()) {
276 return true;
279 mOffset = GetContentRectLayerOffset(mFrame, aDisplayListBuilder);
281 LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits(
282 mFrame->GetContentRectRelativeToSelf(),
283 mFrame->PresContext()->AppUnitsPerDevPixel());
284 rect += mOffset;
286 aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect),
287 !BackfaceIsHidden(), mozilla::wr::AsPipelineId(mLayersId),
288 /*ignoreMissingPipelines*/ true);
290 return true;
293 bool nsDisplayRemote::UpdateScrollData(
294 mozilla::layers::WebRenderScrollData* aData,
295 mozilla::layers::WebRenderLayerScrollData* aLayerData) {
296 if (!mLayersId.IsValid()) {
297 return true;
300 if (aLayerData) {
301 aLayerData->SetReferentId(mLayersId);
302 aLayerData->SetTransform(
303 mozilla::gfx::Matrix4x4::Translation(mOffset.x, mOffset.y, 0.0));
304 aLayerData->SetEventRegionsOverride(mEventRegionsOverride);
306 return true;
309 nsFrameLoader* nsDisplayRemote::GetFrameLoader() const {
310 return mFrame ? static_cast<nsSubDocumentFrame*>(mFrame)->FrameLoader()
311 : nullptr;