LCOV - code coverage report
Current view: top level - layout/ipc - RenderFrameParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 97 154 63.0 %
Date: 2017-07-14 16:53:18 Functions: 14 21 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * vim: sw=2 ts=8 et :
       3             :  */
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #include "base/basictypes.h"
       9             : 
      10             : #include "BasicLayers.h"
      11             : #include "gfxPrefs.h"
      12             : #include "mozilla/BrowserElementParent.h"
      13             : #include "mozilla/EventForwards.h"  // for Modifiers
      14             : #include "mozilla/ViewportFrame.h"
      15             : #include "mozilla/dom/ContentChild.h"
      16             : #include "mozilla/dom/ContentParent.h"
      17             : #include "mozilla/dom/TabChild.h"
      18             : #include "mozilla/dom/TabParent.h"
      19             : #include "mozilla/layers/APZCTreeManager.h"
      20             : #include "mozilla/layers/APZThreadUtils.h"
      21             : #include "mozilla/layers/CompositorBridgeParent.h"
      22             : #include "mozilla/layers/LayerTransactionParent.h"
      23             : #include "nsContentUtils.h"
      24             : #include "nsFocusManager.h"
      25             : #include "nsFrameLoader.h"
      26             : #include "nsIObserver.h"
      27             : #include "nsStyleStructInlines.h"
      28             : #include "nsSubDocumentFrame.h"
      29             : #include "nsView.h"
      30             : #include "RenderFrameParent.h"
      31             : #include "mozilla/gfx/GPUProcessManager.h"
      32             : #include "mozilla/layers/LayerManagerComposite.h"
      33             : #include "mozilla/layers/CompositorBridgeChild.h"
      34             : #include "mozilla/layers/WebRenderLayerManager.h"
      35             : #include "ClientLayerManager.h"
      36             : #include "FrameLayerBuilder.h"
      37             : 
      38             : using namespace mozilla::dom;
      39             : using namespace mozilla::gfx;
      40             : using namespace mozilla::layers;
      41             : 
      42             : namespace mozilla {
      43             : namespace layout {
      44             : 
      45             : typedef FrameMetrics::ViewID ViewID;
      46             : 
      47             : /**
      48             :  * Gets the layer-pixel offset of aContainerFrame's content rect top-left
      49             :  * from the nearest display item reference frame (which we assume will be inducing
      50             :  * a ContainerLayer).
      51             :  */
      52             : static nsIntPoint
      53          24 : GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder)
      54             : {
      55          24 :   nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
      56             : 
      57             :   // Offset to the content rect in case we have borders or padding
      58             :   // Note that aContainerFrame could be a reference frame itself, so
      59             :   // we need to be careful here to ensure that we call ToReferenceFrame
      60             :   // on aContainerFrame and not its parent.
      61          48 :   nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
      62          72 :     aContainerFrame->GetContentRectRelativeToSelf().TopLeft();
      63             : 
      64          24 :   return frameOffset.ToNearestPixels(auPerDevPixel);
      65             : }
      66             : 
      67             : // Return true iff |aManager| is a "temporary layer manager".  They're
      68             : // used for small software rendering tasks, like drawWindow.  That's
      69             : // currently implemented by a BasicLayerManager without a backing
      70             : // widget, and hence in non-retained mode.
      71             : inline static bool
      72          24 : IsTempLayerManager(LayerManager* aManager)
      73             : {
      74          24 :   return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() &&
      75          24 :           !static_cast<BasicLayerManager*>(aManager)->IsRetained());
      76             : }
      77             : 
      78             : already_AddRefed<LayerManager>
      79           3 : GetLayerManager(nsFrameLoader* aFrameLoader)
      80             : {
      81           3 :   if (nsIContent* content = aFrameLoader->GetOwnerContent()) {
      82           3 :     RefPtr<LayerManager> lm = nsContentUtils::LayerManagerForContent(content);
      83           3 :     if (lm) {
      84           3 :       return lm.forget();
      85             :     }
      86             :   }
      87             : 
      88           0 :   nsIDocument* doc = aFrameLoader->GetOwnerDoc();
      89           0 :   if (!doc) {
      90           0 :     return nullptr;
      91             :   }
      92           0 :   return nsContentUtils::LayerManagerForDocument(doc);
      93             : }
      94             : 
      95           1 : RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader)
      96             :   : mLayersId(0)
      97             :   , mLayersConnected(false)
      98             :   , mFrameLoader(aFrameLoader)
      99             :   , mFrameLoaderDestroyed(false)
     100             :   , mAsyncPanZoomEnabled(false)
     101           1 :   , mInitted(false)
     102             : {
     103           1 :   mInitted = Init(aFrameLoader);
     104           1 : }
     105             : 
     106           0 : RenderFrameParent::~RenderFrameParent()
     107           0 : {}
     108             : 
     109             : bool
     110           1 : RenderFrameParent::Init(nsFrameLoader* aFrameLoader)
     111             : {
     112           1 :   if (mInitted || !aFrameLoader) {
     113           0 :     return false;
     114             :   }
     115             : 
     116           1 :   mFrameLoader = aFrameLoader;
     117             : 
     118           2 :   RefPtr<LayerManager> lm = GetLayerManager(mFrameLoader);
     119             : 
     120           1 :   mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled();
     121             : 
     122           1 :   TabParent* browser = TabParent::GetFrom(mFrameLoader);
     123           1 :   if (XRE_IsParentProcess()) {
     124           1 :     PCompositorBridgeChild* compositor = nullptr;
     125           1 :     if (lm) {
     126           1 :       compositor = lm->GetCompositorBridgeChild();
     127             :     }
     128             : 
     129             :     // Our remote frame will push layers updates to the compositor,
     130             :     // and we'll keep an indirect reference to that tree.
     131           1 :     GPUProcessManager* gpm = GPUProcessManager::Get();
     132           3 :     mLayersConnected = gpm->AllocateAndConnectLayerTreeId(
     133             :       compositor,
     134           2 :       browser->Manager()->AsContentParent()->OtherPid(),
     135             :       &mLayersId,
     136             :       &mCompositorOptions);
     137           0 :   } else if (XRE_IsContentProcess()) {
     138           0 :     ContentChild::GetSingleton()->SendAllocateLayerTreeId(browser->Manager()->ChildID(), browser->GetTabId(), &mLayersId);
     139           0 :     mLayersConnected = CompositorBridgeChild::Get()->SendNotifyChildCreated(mLayersId, &mCompositorOptions);
     140             :   }
     141             : 
     142           1 :   mInitted = true;
     143           1 :   return true;
     144             : }
     145             : 
     146             : bool
     147           1 : RenderFrameParent::IsInitted()
     148             : {
     149           1 :   return mInitted;
     150             : }
     151             : 
     152             : void
     153           0 : RenderFrameParent::Destroy()
     154             : {
     155           0 :   mFrameLoaderDestroyed = true;
     156           0 :   mLayerManager = nullptr;
     157           0 : }
     158             : 
     159             : already_AddRefed<Layer>
     160          24 : RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
     161             :                               nsIFrame* aFrame,
     162             :                               LayerManager* aManager,
     163             :                               const nsIntRect& aVisibleRect,
     164             :                               nsDisplayItem* aItem,
     165             :                               const ContainerLayerParameters& aContainerParameters)
     166             : {
     167          24 :   MOZ_ASSERT(aFrame,
     168             :              "makes no sense to have a shadow tree without a frame");
     169          24 :   MOZ_ASSERT(!mContainer ||
     170             :              IsTempLayerManager(aManager) ||
     171             :              mContainer->Manager() == aManager,
     172             :              "retaining manager changed out from under us ... HELP!");
     173             : 
     174          48 :   if (IsTempLayerManager(aManager) ||
     175          24 :       (mContainer && mContainer->Manager() != aManager)) {
     176             :     // This can happen if aManager is a "temporary" manager, or if the
     177             :     // widget's layer manager changed out from under us.  We need to
     178             :     // FIXME handle the former case somehow, probably with an API to
     179             :     // draw a manager's subtree.  The latter is bad bad bad, but the the
     180             :     // MOZ_ASSERT() above will flag it.  Returning nullptr here will just
     181             :     // cause the shadow subtree not to be rendered.
     182           0 :     if (!aContainerParameters.mForEventsAndPluginsOnly) {
     183           0 :       NS_WARNING("Remote iframe not rendered");
     184             :     }
     185           0 :     return nullptr;
     186             :   }
     187             : 
     188          24 :   if (!mLayersId) {
     189           0 :     return nullptr;
     190             :   }
     191             : 
     192             :   RefPtr<Layer> layer =
     193          48 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
     194          24 :   if (!layer) {
     195           1 :     layer = aManager->CreateRefLayer();
     196             :   }
     197          24 :   if (!layer) {
     198             :     // Probably a temporary layer manager that doesn't know how to
     199             :     // use ref layers.
     200           0 :     return nullptr;
     201             :   }
     202          24 :   static_cast<RefLayer*>(layer.get())->SetReferentId(mLayersId);
     203          24 :   nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
     204             :   // We can only have an offset if we're a child of an inactive
     205             :   // container, but our display item is LAYER_ACTIVE_FORCE which
     206             :   // forces all layers above to be active.
     207          24 :   MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
     208          24 :   gfx::Matrix4x4 m = gfx::Matrix4x4::Translation(offset.x, offset.y, 0.0);
     209             :   // Remote content can't be repainted by us, so we multiply down
     210             :   // the resolution that our container expects onto our container.
     211          24 :   m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0);
     212          24 :   layer->SetBaseTransform(m);
     213             : 
     214          24 :   return layer.forget();
     215             : }
     216             : 
     217             : LayerManager*
     218           1 : RenderFrameParent::AttachLayerManager()
     219             : {
     220           2 :   RefPtr<LayerManager> lm;
     221           1 :   if (mFrameLoader) {
     222           1 :     lm = GetLayerManager(mFrameLoader);
     223             :   }
     224             : 
     225             :   // Perhaps the document containing this frame currently has no presentation?
     226           1 :   if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) {
     227           1 :     mLayersConnected = lm->GetCompositorBridgeChild()->SendAdoptChild(mLayersId);
     228           1 :     FrameLayerBuilder::InvalidateAllLayers(lm);
     229             :   }
     230             : 
     231           1 :   mLayerManager = lm.forget();
     232           2 :   return mLayerManager;
     233             : }
     234             : 
     235             : void
     236           0 : RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
     237             : {
     238           0 :   MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent,
     239             :              "Don't build new map if owner is same!");
     240             : 
     241           0 :   Unused << AttachLayerManager();
     242           0 : }
     243             : 
     244             : void
     245           0 : RenderFrameParent::ActorDestroy(ActorDestroyReason why)
     246             : {
     247           0 :   if (mLayersId != 0) {
     248           0 :     if (XRE_IsParentProcess()) {
     249           0 :       GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, OtherPid());
     250           0 :     } else if (XRE_IsContentProcess()) {
     251           0 :       TabParent* browser = TabParent::GetFrom(mFrameLoader);
     252           0 :       ContentChild::GetSingleton()->SendDeallocateLayerTreeId(browser->Manager()->ChildID(), mLayersId);
     253             :     }
     254             :   }
     255             : 
     256           0 :   mFrameLoader = nullptr;
     257           0 :   mLayerManager = nullptr;
     258           0 : }
     259             : 
     260             : mozilla::ipc::IPCResult
     261           1 : RenderFrameParent::RecvNotifyCompositorTransaction()
     262             : {
     263           1 :   TriggerRepaint();
     264           1 :   return IPC_OK();
     265             : }
     266             : 
     267             : void
     268           1 : RenderFrameParent::TriggerRepaint()
     269             : {
     270           1 :   nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
     271           1 :   if (!docFrame) {
     272             :     // Bad, but nothing we can do about it (XXX/cjones: or is there?
     273             :     // maybe bug 589337?).  When the new frame is created, we'll
     274             :     // probably still be the current render frame and will get to draw
     275             :     // our content then.  Or, we're shutting down and this update goes
     276             :     // to /dev/null.
     277           0 :     return;
     278             :   }
     279             : 
     280           1 :   docFrame->InvalidateLayer(nsDisplayItem::TYPE_REMOTE);
     281             : }
     282             : 
     283             : void
     284          33 : RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
     285             :                                     nsSubDocumentFrame* aFrame,
     286             :                                     const nsRect& aDirtyRect,
     287             :                                     const nsDisplayListSet& aLists)
     288             : {
     289             :   // We're the subdoc for <browser remote="true"> and it has
     290             :   // painted content.  Display its shadow layer tree.
     291          66 :   DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     292             : 
     293          33 :   nsPoint offset = aBuilder->ToReferenceFrame(aFrame);
     294          66 :   nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset;
     295          33 :   clipState.ClipContentDescendants(bounds);
     296             : 
     297          33 :   aLists.Content()->AppendToTop(
     298          66 :     new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
     299          33 : }
     300             : 
     301             : void
     302           1 : RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
     303             : {
     304           2 :   RefPtr<LayerManager> lm = mFrameLoader ? GetLayerManager(mFrameLoader) : nullptr;
     305             :   // Perhaps the document containing this frame currently has no presentation?
     306           1 :   if (lm) {
     307           1 :     *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier();
     308             :   } else {
     309           0 :     *aTextureFactoryIdentifier = TextureFactoryIdentifier();
     310             :   }
     311           1 : }
     312             : 
     313             : void
     314           0 : RenderFrameParent::TakeFocusForClickFromTap()
     315             : {
     316           0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
     317           0 :   if (!fm) {
     318           0 :     return;
     319             :   }
     320           0 :   nsCOMPtr<nsIContent> owner = mFrameLoader->GetOwnerContent();
     321           0 :   if (!owner) {
     322           0 :     return;
     323             :   }
     324           0 :   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(owner);
     325           0 :   if (!element) {
     326           0 :     return;
     327             :   }
     328           0 :   fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
     329             :                         nsIFocusManager::FLAG_BYTOUCH |
     330           0 :                         nsIFocusManager::FLAG_NOSCROLL);
     331             : }
     332             : 
     333             : void
     334           0 : RenderFrameParent::EnsureLayersConnected(CompositorOptions* aCompositorOptions)
     335             : {
     336           0 :   RefPtr<LayerManager> lm = GetLayerManager(mFrameLoader);
     337           0 :   if (!lm) {
     338           0 :     return;
     339             :   }
     340             : 
     341           0 :   if (!lm->GetCompositorBridgeChild()) {
     342           0 :     return;
     343             :   }
     344             : 
     345           0 :   mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated(mLayersId, &mCompositorOptions);
     346           0 :   *aCompositorOptions = mCompositorOptions;
     347             : }
     348             : 
     349             : } // namespace layout
     350             : } // namespace mozilla
     351             : 
     352          33 : nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
     353             :                                  nsSubDocumentFrame* aFrame,
     354          33 :                                  RenderFrameParent* aRemoteFrame)
     355             :   : nsDisplayItem(aBuilder, aFrame)
     356             :   , mRemoteFrame(aRemoteFrame)
     357          33 :   , mEventRegionsOverride(EventRegionsOverride::NoOverride)
     358             : {
     359          33 :   if (aBuilder->IsBuildingLayerEventRegions()) {
     360             :     bool frameIsPointerEventsNone =
     361          24 :       aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame) ==
     362          24 :         NS_STYLE_POINTER_EVENTS_NONE;
     363          24 :     if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) {
     364           0 :       mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion;
     365             :     }
     366          24 :     if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell())) {
     367           0 :       mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent;
     368             :     }
     369             :   }
     370          33 : }
     371             : 
     372             : already_AddRefed<Layer>
     373          24 : nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
     374             :                             LayerManager* aManager,
     375             :                             const ContainerLayerParameters& aContainerParameters)
     376             : {
     377          24 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
     378          24 :   nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel);
     379          24 :   visibleRect += aContainerParameters.mOffset;
     380          48 :   RefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters);
     381          24 :   if (layer && layer->AsContainerLayer()) {
     382          24 :     layer->AsContainerLayer()->SetEventRegionsOverride(mEventRegionsOverride);
     383             :   }
     384          48 :   return layer.forget();
     385             : }

Generated by: LCOV version 1.13