summaryrefslogtreecommitdiff
path: root/layout/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'layout/ipc')
-rw-r--r--layout/ipc/PRenderFrame.ipdl37
-rw-r--r--layout/ipc/PVsync.ipdl42
-rw-r--r--layout/ipc/RenderFrameChild.cpp35
-rw-r--r--layout/ipc/RenderFrameChild.h33
-rw-r--r--layout/ipc/RenderFrameParent.cpp368
-rw-r--r--layout/ipc/RenderFrameParent.h161
-rw-r--r--layout/ipc/VsyncChild.cpp94
-rw-r--r--layout/ipc/VsyncChild.h62
-rw-r--r--layout/ipc/VsyncParent.cpp121
-rw-r--r--layout/ipc/VsyncParent.h56
-rw-r--r--layout/ipc/moz.build41
11 files changed, 1050 insertions, 0 deletions
diff --git a/layout/ipc/PRenderFrame.ipdl b/layout/ipc/PRenderFrame.ipdl
new file mode 100644
index 0000000000..3a1a47fe06
--- /dev/null
+++ b/layout/ipc/PRenderFrame.ipdl
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PBrowser;
+include protocol PLayerTransaction;
+
+
+using class nsRegion from "nsRegion.h";
+
+namespace mozilla {
+namespace layout {
+
+/**
+ * PRenderFrame (in the layout sense of "frame") represents one web
+ * "page". It's used to graft content processes' layer trees into
+ * chrome's rendering path. The lifetime of a PRenderFrame is tied to
+ * its PresShell in the child process.
+ *
+ * The child process conceptually "owns" a PRenderFrame, because it
+ * only makes sense wrt documents loaded by the child.
+ */
+sync protocol PRenderFrame
+{
+ manager PBrowser;
+
+parent:
+ async NotifyCompositorTransaction();
+
+ async __delete__();
+};
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/ipc/PVsync.ipdl b/layout/ipc/PVsync.ipdl
new file mode 100644
index 0000000000..5d31e34d4c
--- /dev/null
+++ b/layout/ipc/PVsync.ipdl
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PBackground;
+
+using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
+
+namespace mozilla {
+namespace layout {
+
+/*
+ * The PVsync is a sub-protocol in PBackground and it is used to notify
+ * the vsync event from chrome to content process. It also provides the
+ * interfaces for content to observe/unobserve vsync event notifications.
+ */
+async protocol PVsync
+{
+ manager PBackground;
+
+child:
+ // Send vsync event from chrome to content process.
+ async Notify(TimeStamp aVsyncTimestamp) compress;
+
+ // Send the vsync rate to the content process.
+ async VsyncRate(float aVsyncRate);
+
+parent:
+ // Content process use these messages to acquire the vsync event.
+ async Observe();
+ async Unobserve();
+ async RequestVsyncRate();
+
+ // This message is never sent. Each PVsync actor will stay alive as long as
+ // its PBackground manager.
+ async __delete__();
+};
+
+} // namespace layout
+} // namespace mozilla
+
diff --git a/layout/ipc/RenderFrameChild.cpp b/layout/ipc/RenderFrameChild.cpp
new file mode 100644
index 0000000000..72225abc09
--- /dev/null
+++ b/layout/ipc/RenderFrameChild.cpp
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RenderFrameChild.h"
+#include "mozilla/layers/LayerTransactionChild.h"
+
+using mozilla::layers::PLayerTransactionChild;
+using mozilla::layers::LayerTransactionChild;
+
+namespace mozilla {
+namespace layout {
+
+void
+RenderFrameChild::ActorDestroy(ActorDestroyReason why)
+{
+ mWasDestroyed = true;
+}
+
+void
+RenderFrameChild::Destroy()
+{
+ if (mWasDestroyed) {
+ return;
+ }
+
+ Send__delete__(this);
+ // WARNING: |this| is dead, hands off
+}
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/ipc/RenderFrameChild.h b/layout/ipc/RenderFrameChild.h
new file mode 100644
index 0000000000..059f54a658
--- /dev/null
+++ b/layout/ipc/RenderFrameChild.h
@@ -0,0 +1,33 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_RenderFrameChild_h
+#define mozilla_dom_RenderFrameChild_h
+
+#include "mozilla/layout/PRenderFrameChild.h"
+
+namespace mozilla {
+namespace layout {
+
+class RenderFrameChild : public PRenderFrameChild
+{
+public:
+ RenderFrameChild() : mWasDestroyed(false) {}
+ virtual ~RenderFrameChild() {}
+
+ void ActorDestroy(ActorDestroyReason why) override;
+
+ void Destroy();
+
+private:
+ bool mWasDestroyed;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif // mozilla_dom_RenderFrameChild_h
diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp
new file mode 100644
index 0000000000..8162d02d79
--- /dev/null
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "base/basictypes.h"
+
+#include "BasicLayers.h"
+#include "gfxPrefs.h"
+#ifdef MOZ_ENABLE_D3D9_LAYER
+# include "LayerManagerD3D9.h"
+#endif //MOZ_ENABLE_D3D9_LAYER
+#include "mozilla/BrowserElementParent.h"
+#include "mozilla/EventForwards.h" // for Modifiers
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/TabParent.h"
+#include "mozilla/layers/APZCTreeManager.h"
+#include "mozilla/layers/APZThreadUtils.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/LayerTransactionParent.h"
+#include "nsContentUtils.h"
+#include "nsFocusManager.h"
+#include "nsFrameLoader.h"
+#include "nsIObserver.h"
+#include "nsStyleStructInlines.h"
+#include "nsSubDocumentFrame.h"
+#include "nsView.h"
+#include "nsViewportFrame.h"
+#include "RenderFrameParent.h"
+#include "mozilla/gfx/GPUProcessManager.h"
+#include "mozilla/layers/LayerManagerComposite.h"
+#include "mozilla/layers/CompositorBridgeChild.h"
+#include "ClientLayerManager.h"
+#include "FrameLayerBuilder.h"
+
+using namespace mozilla::dom;
+using namespace mozilla::gfx;
+using namespace mozilla::layers;
+
+namespace mozilla {
+namespace layout {
+
+typedef FrameMetrics::ViewID ViewID;
+
+/**
+ * Gets the layer-pixel offset of aContainerFrame's content rect top-left
+ * from the nearest display item reference frame (which we assume will be inducing
+ * a ContainerLayer).
+ */
+static nsIntPoint
+GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder)
+{
+ nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
+
+ // Offset to the content rect in case we have borders or padding
+ // Note that aContainerFrame could be a reference frame itself, so
+ // we need to be careful here to ensure that we call ToReferenceFrame
+ // on aContainerFrame and not its parent.
+ nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
+ aContainerFrame->GetContentRectRelativeToSelf().TopLeft();
+
+ return frameOffset.ToNearestPixels(auPerDevPixel);
+}
+
+// Return true iff |aManager| is a "temporary layer manager". They're
+// used for small software rendering tasks, like drawWindow. That's
+// currently implemented by a BasicLayerManager without a backing
+// widget, and hence in non-retained mode.
+inline static bool
+IsTempLayerManager(LayerManager* aManager)
+{
+ return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() &&
+ !static_cast<BasicLayerManager*>(aManager)->IsRetained());
+}
+
+already_AddRefed<LayerManager>
+GetFrom(nsFrameLoader* aFrameLoader)
+{
+ nsIDocument* doc = aFrameLoader->GetOwnerDoc();
+ if (!doc) {
+ return nullptr;
+ }
+ return nsContentUtils::LayerManagerForDocument(doc);
+}
+
+RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader, bool* aSuccess)
+ : mLayersId(0)
+ , mFrameLoader(aFrameLoader)
+ , mFrameLoaderDestroyed(false)
+ , mAsyncPanZoomEnabled(false)
+ , mInitted(false)
+{
+ mInitted = Init(aFrameLoader);
+ *aSuccess = mInitted;
+}
+
+RenderFrameParent::~RenderFrameParent()
+{}
+
+bool
+RenderFrameParent::Init(nsFrameLoader* aFrameLoader)
+{
+ if (mInitted || !aFrameLoader) {
+ return false;
+ }
+
+ mFrameLoader = aFrameLoader;
+
+ RefPtr<LayerManager> lm = GetFrom(mFrameLoader);
+
+ mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled();
+
+ TabParent* browser = TabParent::GetFrom(mFrameLoader);
+ if (XRE_IsParentProcess()) {
+ // Our remote frame will push layers updates to the compositor,
+ // and we'll keep an indirect reference to that tree.
+ browser->Manager()->AsContentParent()->AllocateLayerTreeId(browser, &mLayersId);
+ if (lm && lm->AsClientLayerManager()) {
+ if (!lm->AsClientLayerManager()->GetRemoteRenderer()->SendNotifyChildCreated(mLayersId)) {
+ return false;
+ }
+ }
+ } else if (XRE_IsContentProcess()) {
+ ContentChild::GetSingleton()->SendAllocateLayerTreeId(browser->Manager()->ChildID(), browser->GetTabId(), &mLayersId);
+ if (!CompositorBridgeChild::Get()->SendNotifyChildCreated(mLayersId)) {
+ return false;
+ }
+ }
+
+ mInitted = true;
+ return true;
+}
+
+bool
+RenderFrameParent::IsInitted()
+{
+ return mInitted;
+}
+
+void
+RenderFrameParent::Destroy()
+{
+ mFrameLoaderDestroyed = true;
+}
+
+already_AddRefed<Layer>
+RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ LayerManager* aManager,
+ const nsIntRect& aVisibleRect,
+ nsDisplayItem* aItem,
+ const ContainerLayerParameters& aContainerParameters)
+{
+ MOZ_ASSERT(aFrame,
+ "makes no sense to have a shadow tree without a frame");
+ MOZ_ASSERT(!mContainer ||
+ IsTempLayerManager(aManager) ||
+ mContainer->Manager() == aManager,
+ "retaining manager changed out from under us ... HELP!");
+
+ if (IsTempLayerManager(aManager) ||
+ (mContainer && mContainer->Manager() != aManager)) {
+ // This can happen if aManager is a "temporary" manager, or if the
+ // widget's layer manager changed out from under us. We need to
+ // FIXME handle the former case somehow, probably with an API to
+ // draw a manager's subtree. The latter is bad bad bad, but the the
+ // MOZ_ASSERT() above will flag it. Returning nullptr here will just
+ // cause the shadow subtree not to be rendered.
+ if (!aContainerParameters.mForEventsAndPluginsOnly) {
+ NS_WARNING("Remote iframe not rendered");
+ }
+ return nullptr;
+ }
+
+ uint64_t id = GetLayerTreeId();
+ if (!id) {
+ return nullptr;
+ }
+
+ RefPtr<Layer> layer =
+ (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
+ if (!layer) {
+ layer = aManager->CreateRefLayer();
+ }
+ if (!layer) {
+ // Probably a temporary layer manager that doesn't know how to
+ // use ref layers.
+ return nullptr;
+ }
+ static_cast<RefLayer*>(layer.get())->SetReferentId(id);
+ nsIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder);
+ // We can only have an offset if we're a child of an inactive
+ // container, but our display item is LAYER_ACTIVE_FORCE which
+ // forces all layers above to be active.
+ MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint());
+ gfx::Matrix4x4 m = gfx::Matrix4x4::Translation(offset.x, offset.y, 0.0);
+ // Remote content can't be repainted by us, so we multiply down
+ // the resolution that our container expects onto our container.
+ m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0);
+ layer->SetBaseTransform(m);
+
+ return layer.forget();
+}
+
+void
+RenderFrameParent::OwnerContentChanged(nsIContent* aContent)
+{
+ MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent,
+ "Don't build new map if owner is same!");
+
+ RefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
+ // Perhaps the document containing this frame currently has no presentation?
+ if (lm && lm->AsClientLayerManager()) {
+ lm->AsClientLayerManager()->GetRemoteRenderer()->SendAdoptChild(mLayersId);
+ FrameLayerBuilder::InvalidateAllLayers(lm);
+ }
+}
+
+void
+RenderFrameParent::ActorDestroy(ActorDestroyReason why)
+{
+ if (mLayersId != 0) {
+ if (XRE_IsParentProcess()) {
+ GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, OtherPid());
+ } else if (XRE_IsContentProcess()) {
+ ContentChild::GetSingleton()->SendDeallocateLayerTreeId(mLayersId);
+ }
+ }
+
+ mFrameLoader = nullptr;
+}
+
+bool
+RenderFrameParent::RecvNotifyCompositorTransaction()
+{
+ TriggerRepaint();
+ return true;
+}
+
+void
+RenderFrameParent::TriggerRepaint()
+{
+ nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent();
+ if (!docFrame) {
+ // Bad, but nothing we can do about it (XXX/cjones: or is there?
+ // maybe bug 589337?). When the new frame is created, we'll
+ // probably still be the current render frame and will get to draw
+ // our content then. Or, we're shutting down and this update goes
+ // to /dev/null.
+ return;
+ }
+
+ docFrame->InvalidateLayer(nsDisplayItem::TYPE_REMOTE);
+}
+
+uint64_t
+RenderFrameParent::GetLayerTreeId() const
+{
+ return mLayersId;
+}
+
+void
+RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ nsSubDocumentFrame* aFrame,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists)
+{
+ // We're the subdoc for <browser remote="true"> and it has
+ // painted content. Display its shadow layer tree.
+ DisplayListClipState::AutoSaveRestore clipState(aBuilder);
+
+ nsPoint offset = aBuilder->ToReferenceFrame(aFrame);
+ nsRect bounds = aFrame->EnsureInnerView()->GetBounds() + offset;
+ clipState.ClipContentDescendants(bounds);
+
+ aLists.Content()->AppendToTop(
+ new (aBuilder) nsDisplayRemote(aBuilder, aFrame, this));
+}
+
+void
+RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier)
+{
+ RefPtr<LayerManager> lm = mFrameLoader ? GetFrom(mFrameLoader) : nullptr;
+ // Perhaps the document containing this frame currently has no presentation?
+ if (lm && lm->AsClientLayerManager()) {
+ *aTextureFactoryIdentifier = lm->AsClientLayerManager()->GetTextureFactoryIdentifier();
+ } else {
+ *aTextureFactoryIdentifier = TextureFactoryIdentifier();
+ }
+}
+
+void
+RenderFrameParent::TakeFocusForClickFromTap()
+{
+ nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+ if (!fm) {
+ return;
+ }
+ nsCOMPtr<nsIContent> owner = mFrameLoader->GetOwnerContent();
+ if (!owner) {
+ return;
+ }
+ nsCOMPtr<nsIDOMElement> element = do_QueryInterface(owner);
+ if (!element) {
+ return;
+ }
+ fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
+ nsIFocusManager::FLAG_BYTOUCH |
+ nsIFocusManager::FLAG_NOSCROLL);
+}
+
+void
+RenderFrameParent::EnsureLayersConnected()
+{
+ RefPtr<LayerManager> lm = GetFrom(mFrameLoader);
+ if (!lm) {
+ return;
+ }
+
+ ClientLayerManager* client = lm->AsClientLayerManager();
+ if (!client) {
+ return;
+ }
+
+ client->GetRemoteRenderer()->SendNotifyChildRecreated(mLayersId);
+}
+
+} // namespace layout
+} // namespace mozilla
+
+nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder,
+ nsSubDocumentFrame* aFrame,
+ RenderFrameParent* aRemoteFrame)
+ : nsDisplayItem(aBuilder, aFrame)
+ , mRemoteFrame(aRemoteFrame)
+ , mEventRegionsOverride(EventRegionsOverride::NoOverride)
+{
+ if (aBuilder->IsBuildingLayerEventRegions()) {
+ bool frameIsPointerEventsNone =
+ aFrame->StyleUserInterface()->GetEffectivePointerEvents(aFrame) ==
+ NS_STYLE_POINTER_EVENTS_NONE;
+ if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) {
+ mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion;
+ }
+ if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresContext()->PresShell())) {
+ mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent;
+ }
+ }
+}
+
+already_AddRefed<Layer>
+nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder,
+ LayerManager* aManager,
+ const ContainerLayerParameters& aContainerParameters)
+{
+ int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+ nsIntRect visibleRect = GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel);
+ visibleRect += aContainerParameters.mOffset;
+ RefPtr<Layer> layer = mRemoteFrame->BuildLayer(aBuilder, mFrame, aManager, visibleRect, this, aContainerParameters);
+ if (layer && layer->AsContainerLayer()) {
+ layer->AsContainerLayer()->SetEventRegionsOverride(mEventRegionsOverride);
+ }
+ return layer.forget();
+}
diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h
new file mode 100644
index 0000000000..274f8ff6df
--- /dev/null
+++ b/layout/ipc/RenderFrameParent.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_RenderFrameParent_h
+#define mozilla_layout_RenderFrameParent_h
+
+#include "mozilla/Attributes.h"
+#include <map>
+
+#include "mozilla/layers/APZUtils.h"
+#include "mozilla/layers/LayersTypes.h"
+#include "mozilla/layout/PRenderFrameParent.h"
+#include "nsDisplayList.h"
+
+class nsFrameLoader;
+class nsSubDocumentFrame;
+
+namespace mozilla {
+
+class InputEvent;
+
+namespace layers {
+class AsyncDragMetrics;
+class TargetConfig;
+struct TextureFactoryIdentifier;
+struct ScrollableLayerGuid;
+} // namespace layers
+
+namespace layout {
+
+class RenderFrameParent : public PRenderFrameParent
+{
+ typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics;
+ typedef mozilla::layers::FrameMetrics FrameMetrics;
+ typedef mozilla::layers::ContainerLayer ContainerLayer;
+ typedef mozilla::layers::Layer Layer;
+ typedef mozilla::layers::LayerManager LayerManager;
+ typedef mozilla::layers::TargetConfig TargetConfig;
+ typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
+ typedef mozilla::layers::TextureFactoryIdentifier TextureFactoryIdentifier;
+ typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
+ typedef mozilla::layers::TouchBehaviorFlags TouchBehaviorFlags;
+ typedef mozilla::layers::ZoomConstraints ZoomConstraints;
+ typedef FrameMetrics::ViewID ViewID;
+
+public:
+
+
+ /**
+ * Select the desired scrolling behavior. If ASYNC_PAN_ZOOM is
+ * chosen, then RenderFrameParent will watch input events and use
+ * them to asynchronously pan and zoom.
+ */
+ RenderFrameParent(nsFrameLoader* aFrameLoader, bool* aSuccess);
+ virtual ~RenderFrameParent();
+
+ bool Init(nsFrameLoader* aFrameLoader);
+ bool IsInitted();
+ void Destroy();
+
+ void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ nsSubDocumentFrame* aFrame,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists);
+
+ already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
+ nsIFrame* aFrame,
+ LayerManager* aManager,
+ const nsIntRect& aVisibleRect,
+ nsDisplayItem* aItem,
+ const ContainerLayerParameters& aContainerParameters);
+
+ void OwnerContentChanged(nsIContent* aContent);
+
+ bool HitTest(const nsRect& aRect);
+
+ void GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier);
+
+ inline uint64_t GetLayersId() { return mLayersId; }
+
+ void TakeFocusForClickFromTap();
+
+ void EnsureLayersConnected();
+
+protected:
+ void ActorDestroy(ActorDestroyReason why) override;
+
+ virtual bool RecvNotifyCompositorTransaction() override;
+
+private:
+ void TriggerRepaint();
+ void DispatchEventForPanZoomController(const InputEvent& aEvent);
+
+ uint64_t GetLayerTreeId() const;
+
+ // When our child frame is pushing transactions directly to the
+ // compositor, this is the ID of its layer tree in the compositor's
+ // context.
+ uint64_t mLayersId;
+
+ RefPtr<nsFrameLoader> mFrameLoader;
+ RefPtr<ContainerLayer> mContainer;
+
+ // True after Destroy() has been called, which is triggered
+ // originally by nsFrameLoader::Destroy(). After this point, we can
+ // no longer safely ask the frame loader to find its nearest layer
+ // manager, because it may have been disconnected from the DOM.
+ // It's still OK to *tell* the frame loader that we've painted after
+ // it's destroyed; it'll just ignore us, and we won't be able to
+ // find an nsIFrame to invalidate. See ShadowLayersUpdated().
+ //
+ // Prefer the extra bit of state to null'ing out mFrameLoader in
+ // Destroy() so that less code needs to be special-cased for after
+ // Destroy().
+ //
+ // It's possible for mFrameLoader==null and
+ // mFrameLoaderDestroyed==false.
+ bool mFrameLoaderDestroyed;
+
+ bool mAsyncPanZoomEnabled;
+ bool mInitted;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+/**
+ * A DisplayRemote exists solely to graft a child process's shadow
+ * layer tree (for a given RenderFrameParent) into its parent
+ * process's layer tree.
+ */
+class nsDisplayRemote : public nsDisplayItem
+{
+ typedef mozilla::layout::RenderFrameParent RenderFrameParent;
+
+public:
+ nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame,
+ RenderFrameParent* aRemoteFrame);
+
+ virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+ LayerManager* aManager,
+ const ContainerLayerParameters& aParameters) override
+ { return mozilla::LAYER_ACTIVE_FORCE; }
+
+ virtual already_AddRefed<Layer>
+ BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
+ const ContainerLayerParameters& aContainerParameters) override;
+
+ NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE)
+
+private:
+ RenderFrameParent* mRemoteFrame;
+ mozilla::layers::EventRegionsOverride mEventRegionsOverride;
+};
+
+
+#endif // mozilla_layout_RenderFrameParent_h
diff --git a/layout/ipc/VsyncChild.cpp b/layout/ipc/VsyncChild.cpp
new file mode 100644
index 0000000000..45372b89ab
--- /dev/null
+++ b/layout/ipc/VsyncChild.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VsyncChild.h"
+
+#include "mozilla/VsyncDispatcher.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace layout {
+
+VsyncChild::VsyncChild()
+ : mObservingVsync(false)
+ , mIsShutdown(false)
+ , mVsyncRate(TimeDuration::Forever())
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+VsyncChild::~VsyncChild()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+}
+
+bool
+VsyncChild::SendObserve()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!mObservingVsync && !mIsShutdown) {
+ mObservingVsync = true;
+ PVsyncChild::SendObserve();
+ }
+ return true;
+}
+
+bool
+VsyncChild::SendUnobserve()
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ if (mObservingVsync && !mIsShutdown) {
+ mObservingVsync = false;
+ PVsyncChild::SendUnobserve();
+ }
+ return true;
+}
+
+void
+VsyncChild::ActorDestroy(ActorDestroyReason aActorDestroyReason)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mIsShutdown);
+ mIsShutdown = true;
+ mObserver = nullptr;
+}
+
+bool
+VsyncChild::RecvNotify(const TimeStamp& aVsyncTimestamp)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!mIsShutdown);
+ if (mObservingVsync && mObserver) {
+ mObserver->NotifyVsync(aVsyncTimestamp);
+ }
+ return true;
+}
+
+void
+VsyncChild::SetVsyncObserver(VsyncObserver* aVsyncObserver)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ mObserver = aVsyncObserver;
+}
+
+TimeDuration
+VsyncChild::GetVsyncRate()
+{
+ if (mVsyncRate == TimeDuration::Forever()) {
+ PVsyncChild::SendRequestVsyncRate();
+ }
+
+ return mVsyncRate;
+}
+
+bool
+VsyncChild::RecvVsyncRate(const float& aVsyncRate)
+{
+ mVsyncRate = TimeDuration::FromMilliseconds(aVsyncRate);
+ return true;
+}
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/ipc/VsyncChild.h b/layout/ipc/VsyncChild.h
new file mode 100644
index 0000000000..88896d643b
--- /dev/null
+++ b/layout/ipc/VsyncChild.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_ipc_VsyncChild_h
+#define mozilla_layout_ipc_VsyncChild_h
+
+#include "mozilla/layout/PVsyncChild.h"
+#include "nsISupportsImpl.h"
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+
+class VsyncObserver;
+
+namespace ipc {
+class BackgroundChildImpl;
+} // namespace ipc
+
+namespace layout {
+
+// The PVsyncChild actor receives a vsync event from the main process and
+// delivers it to the child process. Currently this is restricted to the main
+// thread only. The actor will stay alive until the process dies or its
+// PVsyncParent actor dies.
+class VsyncChild final : public PVsyncChild
+{
+ NS_INLINE_DECL_REFCOUNTING(VsyncChild)
+
+ friend class mozilla::ipc::BackgroundChildImpl;
+
+public:
+ // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
+ // mObservingVsync to handle the race problem of unobserving vsync event.
+ bool SendObserve();
+ bool SendUnobserve();
+
+ // Bind a VsyncObserver into VsyncChild after ipc channel connected.
+ void SetVsyncObserver(VsyncObserver* aVsyncObserver);
+ TimeDuration GetVsyncRate();
+
+private:
+ VsyncChild();
+ virtual ~VsyncChild();
+
+ virtual bool RecvNotify(const TimeStamp& aVsyncTimestamp) override;
+ virtual bool RecvVsyncRate(const float& aVsyncRate) override;
+ virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
+
+ bool mObservingVsync;
+ bool mIsShutdown;
+
+ // The content side vsync observer.
+ RefPtr<VsyncObserver> mObserver;
+ TimeDuration mVsyncRate;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif // mozilla_layout_ipc_VsyncChild_h
diff --git a/layout/ipc/VsyncParent.cpp b/layout/ipc/VsyncParent.cpp
new file mode 100644
index 0000000000..8ffe8abc4c
--- /dev/null
+++ b/layout/ipc/VsyncParent.cpp
@@ -0,0 +1,121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "VsyncParent.h"
+
+#include "BackgroundParent.h"
+#include "BackgroundParentImpl.h"
+#include "gfxPlatform.h"
+#include "mozilla/Unused.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
+#include "VsyncSource.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace layout {
+
+/*static*/ already_AddRefed<VsyncParent>
+VsyncParent::Create()
+{
+ AssertIsOnBackgroundThread();
+ RefPtr<gfx::VsyncSource> vsyncSource = gfxPlatform::GetPlatform()->GetHardwareVsync();
+ RefPtr<VsyncParent> vsyncParent = new VsyncParent();
+ vsyncParent->mVsyncDispatcher = vsyncSource->GetRefreshTimerVsyncDispatcher();
+ return vsyncParent.forget();
+}
+
+VsyncParent::VsyncParent()
+ : mObservingVsync(false)
+ , mDestroyed(false)
+ , mBackgroundThread(NS_GetCurrentThread())
+{
+ MOZ_ASSERT(mBackgroundThread);
+ AssertIsOnBackgroundThread();
+}
+
+VsyncParent::~VsyncParent()
+{
+ // Since we use NS_INLINE_DECL_THREADSAFE_REFCOUNTING, we can't make sure
+ // VsyncParent is always released on the background thread.
+}
+
+bool
+VsyncParent::NotifyVsync(TimeStamp aTimeStamp)
+{
+ // Called on hardware vsync thread. We should post to current ipc thread.
+ MOZ_ASSERT(!IsOnBackgroundThread());
+ nsCOMPtr<nsIRunnable> vsyncEvent =
+ NewRunnableMethod<TimeStamp>(this,
+ &VsyncParent::DispatchVsyncEvent,
+ aTimeStamp);
+ MOZ_ALWAYS_SUCCEEDS(mBackgroundThread->Dispatch(vsyncEvent, NS_DISPATCH_NORMAL));
+ return true;
+}
+
+void
+VsyncParent::DispatchVsyncEvent(TimeStamp aTimeStamp)
+{
+ AssertIsOnBackgroundThread();
+
+ // If we call NotifyVsync() when we handle ActorDestroy() message, we might
+ // still call DispatchVsyncEvent().
+ // Similarly, we might also receive RecvUnobserveVsync() when call
+ // NotifyVsync(). We use mObservingVsync and mDestroyed flags to skip this
+ // notification.
+ if (mObservingVsync && !mDestroyed) {
+ Unused << SendNotify(aTimeStamp);
+ }
+}
+
+bool
+VsyncParent::RecvRequestVsyncRate()
+{
+ AssertIsOnBackgroundThread();
+ TimeDuration vsyncRate = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay().GetVsyncRate();
+ Unused << SendVsyncRate(vsyncRate.ToMilliseconds());
+ return true;
+}
+
+bool
+VsyncParent::RecvObserve()
+{
+ AssertIsOnBackgroundThread();
+ if (!mObservingVsync) {
+ mVsyncDispatcher->AddChildRefreshTimer(this);
+ mObservingVsync = true;
+ return true;
+ }
+ return false;
+}
+
+bool
+VsyncParent::RecvUnobserve()
+{
+ AssertIsOnBackgroundThread();
+ if (mObservingVsync) {
+ mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ mObservingVsync = false;
+ return true;
+ }
+ return false;
+}
+
+void
+VsyncParent::ActorDestroy(ActorDestroyReason aReason)
+{
+ MOZ_ASSERT(!mDestroyed);
+ AssertIsOnBackgroundThread();
+ if (mObservingVsync) {
+ mVsyncDispatcher->RemoveChildRefreshTimer(this);
+ }
+ mVsyncDispatcher = nullptr;
+ mDestroyed = true;
+}
+
+} // namespace layout
+} // namespace mozilla
diff --git a/layout/ipc/VsyncParent.h b/layout/ipc/VsyncParent.h
new file mode 100644
index 0000000000..33e96c4c60
--- /dev/null
+++ b/layout/ipc/VsyncParent.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layout_ipc_VsyncParent_h
+#define mozilla_layout_ipc_VsyncParent_h
+
+#include "mozilla/layout/PVsyncParent.h"
+#include "mozilla/VsyncDispatcher.h"
+#include "nsCOMPtr.h"
+#include "mozilla/RefPtr.h"
+
+class nsIThread;
+
+namespace mozilla {
+
+namespace ipc {
+class BackgroundParentImpl;
+} // namespace ipc
+
+namespace layout {
+
+// Use PBackground thread in the main process to send vsync notifications to
+// content process. This actor will be released when its parent protocol calls
+// DeallocPVsyncParent().
+class VsyncParent final : public PVsyncParent,
+ public VsyncObserver
+{
+ friend class mozilla::ipc::BackgroundParentImpl;
+
+private:
+ static already_AddRefed<VsyncParent> Create();
+
+ VsyncParent();
+ virtual ~VsyncParent();
+
+ virtual bool NotifyVsync(TimeStamp aTimeStamp) override;
+ virtual bool RecvRequestVsyncRate() override;
+
+ virtual bool RecvObserve() override;
+ virtual bool RecvUnobserve() override;
+ virtual void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;
+
+ void DispatchVsyncEvent(TimeStamp aTimeStamp);
+
+ bool mObservingVsync;
+ bool mDestroyed;
+ nsCOMPtr<nsIThread> mBackgroundThread;
+ RefPtr<RefreshTimerVsyncDispatcher> mVsyncDispatcher;
+};
+
+} // namespace layout
+} // namespace mozilla
+
+#endif //mozilla_layout_ipc_VsyncParent_h
diff --git a/layout/ipc/moz.build b/layout/ipc/moz.build
new file mode 100644
index 0000000000..d9cf962ca2
--- /dev/null
+++ b/layout/ipc/moz.build
@@ -0,0 +1,41 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files('**'):
+ BUG_COMPONENT = ('Core', 'Layout: View Rendering')
+
+EXPORTS.mozilla.layout += [
+ 'RenderFrameChild.h',
+ 'RenderFrameParent.h',
+ 'VsyncChild.h',
+ 'VsyncParent.h',
+]
+
+UNIFIED_SOURCES += [
+ 'RenderFrameChild.cpp',
+ 'RenderFrameParent.cpp',
+]
+
+SOURCES += [
+ 'VsyncChild.cpp',
+ 'VsyncParent.cpp',
+]
+
+IPDL_SOURCES = [
+ 'PRenderFrame.ipdl',
+ 'PVsync.ipdl',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '/dom/base',
+ '/layout/base',
+ '/layout/generic',
+ '/layout/xul',
+]