merge graphics branch to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 03 Mar 2017 11:23:31 -0800
changeset 394779 942165e408f0241cf543c368db00fefe22a9997a
parent 394749 77d5a39a4677ed8e32a7ed46561c962d807fa7b1 (current diff)
parent 394778 aafcba25dee399d3390ea1fb4c2121e4e62b8b0d (diff)
child 394802 9a117f52a1371a223ff79a1f67a4b8cf08f9b69b
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge graphics branch to m-c a=merge MozReview-Commit-ID: 5GYHFV8IsKo
third_party/rust/core-foundation-0.2.3/.cargo-checksum.json
third_party/rust/core-foundation-0.2.3/.cargo-ok
third_party/rust/core-foundation-0.2.3/Cargo.toml
third_party/rust/core-foundation-0.2.3/src/array.rs
third_party/rust/core-foundation-0.2.3/src/base.rs
third_party/rust/core-foundation-0.2.3/src/boolean.rs
third_party/rust/core-foundation-0.2.3/src/bundle.rs
third_party/rust/core-foundation-0.2.3/src/data.rs
third_party/rust/core-foundation-0.2.3/src/dictionary.rs
third_party/rust/core-foundation-0.2.3/src/error.rs
third_party/rust/core-foundation-0.2.3/src/lib.rs
third_party/rust/core-foundation-0.2.3/src/number.rs
third_party/rust/core-foundation-0.2.3/src/propertylist.rs
third_party/rust/core-foundation-0.2.3/src/runloop.rs
third_party/rust/core-foundation-0.2.3/src/set.rs
third_party/rust/core-foundation-0.2.3/src/string.rs
third_party/rust/core-foundation-0.2.3/src/url.rs
third_party/rust/core-foundation-sys-0.2.3/.cargo-checksum.json
third_party/rust/core-foundation-sys-0.2.3/.cargo-ok
third_party/rust/core-foundation-sys-0.2.3/Cargo.toml
third_party/rust/core-foundation-sys-0.2.3/build.rs
third_party/rust/core-foundation-sys-0.2.3/src/array.rs
third_party/rust/core-foundation-sys-0.2.3/src/base.rs
third_party/rust/core-foundation-sys-0.2.3/src/bundle.rs
third_party/rust/core-foundation-sys-0.2.3/src/data.rs
third_party/rust/core-foundation-sys-0.2.3/src/date.rs
third_party/rust/core-foundation-sys-0.2.3/src/dictionary.rs
third_party/rust/core-foundation-sys-0.2.3/src/error.rs
third_party/rust/core-foundation-sys-0.2.3/src/lib.rs
third_party/rust/core-foundation-sys-0.2.3/src/messageport.rs
third_party/rust/core-foundation-sys-0.2.3/src/number.rs
third_party/rust/core-foundation-sys-0.2.3/src/propertylist.rs
third_party/rust/core-foundation-sys-0.2.3/src/runloop.rs
third_party/rust/core-foundation-sys-0.2.3/src/set.rs
third_party/rust/core-foundation-sys-0.2.3/src/string.rs
third_party/rust/core-foundation-sys-0.2.3/src/url.rs
--- a/editor/reftests/reftest.list
+++ b/editor/reftests/reftest.list
@@ -77,17 +77,17 @@ fails-if(Android) needs-focus != spellch
 needs-focus == spellcheck-non-latin-arabic.html spellcheck-non-latin-arabic-ref.html
 needs-focus == spellcheck-non-latin-chinese-simplified.html spellcheck-non-latin-chinese-simplified-ref.html
 needs-focus == spellcheck-non-latin-chinese-traditional.html spellcheck-non-latin-chinese-traditional-ref.html
 needs-focus == spellcheck-non-latin-hebrew.html spellcheck-non-latin-hebrew-ref.html
 needs-focus == spellcheck-non-latin-japanese.html spellcheck-non-latin-japanese-ref.html
 needs-focus == spellcheck-non-latin-korean.html spellcheck-non-latin-korean-ref.html
 == unneeded_scroll.html unneeded_scroll-ref.html
 == caret_on_presshell_reinit.html caret_on_presshell_reinit-ref.html
-fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-2) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html
+fuzzy-if(browserIsRemote,255,3) asserts-if(browserIsRemote,0-2) asserts-if(webrender&&!browserIsRemote,0-1) == caret_on_presshell_reinit-2.html caret_on_presshell_reinit-ref.html
 fuzzy-if(asyncPan&&!layersGPUAccelerated,102,2824) == 642800.html 642800-ref.html
 == selection_visibility_after_reframe.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-2.html selection_visibility_after_reframe-ref.html
 != selection_visibility_after_reframe-3.html selection_visibility_after_reframe-ref.html
 == 672709.html 672709-ref.html
 == 338427-1.html 338427-1-ref.html
 skip-if(Android) needs-focus == 674212-spellcheck.html 674212-spellcheck-ref.html
 skip-if(Android) needs-focus == 338427-2.html 338427-2-ref.html
--- a/gfx/doc/README.webrender
+++ b/gfx/doc/README.webrender
@@ -74,9 +74,9 @@ there is another crate in m-c called moz
 the same folder to store its rust dependencies. If one of the libraries that is
 required by both mozjs_sys and webrender is updated without updating the other
 project's Cargo.lock file, that results in build bustage.
 This means that any time you do this sort of manual update of packages, you need
 to make sure that mozjs_sys also has its Cargo.lock file updated if needed, hence
 the need to run the cargo update command in js/src as well. Hopefully this will
 be resolved soon.
 
-Latest Commit: edc74274d28b1fa1229a1d1ea05027f57172b992
+Latest Commit: 501e3d79c8a3019762bd8bd2d00eecf7811a84de
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -1125,17 +1125,17 @@ CompositorBridgeChild::WillEndTransactio
 
 void
 CompositorBridgeChild::HandleFatalError(const char* aName, const char* aMsg) const
 {
   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
 }
 
 PWebRenderBridgeChild*
-CompositorBridgeChild::AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*)
+CompositorBridgeChild::AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*, uint32_t *aIdNamespace)
 {
   WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId);
   child->AddIPDLReference();
   return child;
 }
 
 bool
 CompositorBridgeChild::DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor)
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -218,17 +218,18 @@ public:
 
   PAPZChild* AllocPAPZChild(const uint64_t& aLayersId) override;
   bool DeallocPAPZChild(PAPZChild* aActor) override;
 
   void ProcessingError(Result aCode, const char* aReason) override;
 
   void WillEndTransaction();
 
-  PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*) override;
+  PWebRenderBridgeChild* AllocPWebRenderBridgeChild(const wr::PipelineId& aPipelineId, TextureFactoryIdentifier*,
+                                                    uint32_t*) override;
   bool DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor) override;
 
   uint64_t DeviceResetSequenceNumber() const {
     return mDeviceResetSequenceNumber;
   }
 
 private:
   // Private destructor, to discourage deletion outside of Release():
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1567,17 +1567,18 @@ CompositorBridgeParent::RecvAdoptChild(c
   if (mApzcTreeManager && parent) {
     parent->ChildAdopted(mApzcTreeManager);
   }
   return IPC_OK();
 }
 
 PWebRenderBridgeParent*
 CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
-                                                    TextureFactoryIdentifier* aTextureFactoryIdentifier)
+                                                    TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                                    uint32_t* aIdNamespace)
 {
 #ifndef MOZ_ENABLE_WEBRENDER
   // Extra guard since this in the parent process and we don't want a malicious
   // child process invoking this codepath before it's ready
   MOZ_RELEASE_ASSERT(false);
 #endif
   MOZ_ASSERT(aPipelineId.mHandle == mRootLayerTreeID);
   MOZ_ASSERT(!mWrBridge);
@@ -1586,17 +1587,18 @@ CompositorBridgeParent::AllocPWebRenderB
 
 
   MOZ_ASSERT(mWidget);
   RefPtr<widget::CompositorWidget> widget = mWidget;
   RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(gfxPrefs::WebRenderProfilerEnabled(), this, Move(widget));
   RefPtr<WebRenderCompositableHolder> holder = new WebRenderCompositableHolder();
   MOZ_ASSERT(api); // TODO have a fallback
   api->SetRootPipeline(aPipelineId);
-  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, Move(api), Move(holder));
+  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, Move(api), Move(holder));
+  *aIdNamespace = mWrBridge->GetIdNameSpace();
 
   mCompositorScheduler = mWrBridge->CompositorScheduler();
   MOZ_ASSERT(mCompositorScheduler);
   mWrBridge.get()->AddRef(); // IPDL reference
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   auto pipelineHandle = aPipelineId.mHandle;
   MOZ_ASSERT(sIndirectLayerTrees[pipelineHandle].mWrBridge == nullptr);
   sIndirectLayerTrees[pipelineHandle].mWrBridge = mWrBridge;
@@ -1811,18 +1813,54 @@ CompositorBridgeParent::LayerTreeState::
 {
   return mParent;
 }
 
 void
 CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
                                      TimeStamp& aCompositeEnd)
 {
-  NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
-  mPendingTransaction = 0;
+  if (mWrBridge) {
+    NotifyDidComposite(mWrBridge->FlushPendingTransactionIds(), aCompositeStart, aCompositeEnd);
+  } else {
+    NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
+    mPendingTransaction = 0;
+  }
+}
+
+void
+CompositorBridgeParent::NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
+{
+  if (mPaused) {
+    return;
+  }
+  MOZ_ASSERT(mWrBridge);
+
+  if (mWrBridge->PipelineId() == aPipelineId) {
+    uint64_t transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch);
+    Unused << SendDidComposite(0, transactionId, aCompositeStart, aCompositeEnd);
+
+    nsTArray<ImageCompositeNotificationInfo> notifications;
+    mWrBridge->ExtractImageCompositeNotifications(&notifications);
+    if (!notifications.IsEmpty()) {
+      Unused << ImageBridgeParent::NotifyImageComposites(notifications);
+    }
+    return;
+  }
+
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
+    if (lts->mCrossProcessParent &&
+        lts->mWrBridge &&
+        lts->mWrBridge->PipelineId() == aPipelineId) {
+      CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
+      uint64_t transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch);
+      Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
+    }
+  });
 }
 
 void
 CompositorBridgeParent::NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
 {
   Unused << SendDidComposite(0, aTransactionId, aCompositeStart, aCompositeEnd);
 
   if (mLayerManager) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -31,16 +31,17 @@
 #include "mozilla/layers/CompositorOptions.h"
 #include "mozilla/layers/CompositorVsyncSchedulerOwner.h"
 #include "mozilla/layers/GeckoContentController.h"
 #include "mozilla/layers/ISurfaceAllocator.h" // for ShmemAllocator
 #include "mozilla/layers/LayersMessages.h"  // for TargetConfig
 #include "mozilla/layers/MetricsSharingController.h"
 #include "mozilla/layers/PCompositorBridgeParent.h"
 #include "mozilla/layers/APZTestData.h"
+#include "mozilla/webrender/WebRenderTypes.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "nsISupportsImpl.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
 class MessageLoop;
 class nsIWidget;
 
 namespace mozilla {
@@ -113,17 +114,17 @@ public:
   virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) {}
 
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
 
   virtual mozilla::ipc::IPCResult RecvSyncWithCompositor() override { return IPC_OK(); }
 
   virtual void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) = 0;
 
-  virtual void NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {}
+  virtual void NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) {}
 
   // HostIPCAllocator
   virtual base::ProcessId GetChildProcessId() override;
   virtual void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
 
   // ShmemAllocator
   virtual bool AllocShmem(size_t aSize,
@@ -446,17 +447,18 @@ public:
 
   RefPtr<APZCTreeManager> GetAPZCTreeManager();
 
   CompositorOptions GetOptions() const {
     return mOptions;
   }
 
   PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
-                                                      TextureFactoryIdentifier* aTextureFactoryIdentifier) override;
+                                                      TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                                      uint32_t* aIdNamespace) override;
   bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
   static void SetWebRenderProfilerEnabled(bool aEnabled);
 
   static CompositorBridgeParent* GetCompositorBridgeParentFromLayersId(const uint64_t& aLayersId);
 private:
 
   void Initialize();
 
@@ -544,17 +546,19 @@ protected:
   /**
    * Return true if current state allows compositing, that is
    * finishing a layers transaction.
    */
   bool CanComposite();
 
   void DidComposite(TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
 
-  virtual void NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) override;
+  virtual void NotifyDidCompositeToPipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd) override;
+
+  void NotifyDidComposite(uint64_t aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd);
 
   // The indirect layer tree lock must be held before calling this function.
   // Callback should take (LayerTreeState* aState, const uint64_t& aLayersId)
   template <typename Lambda>
   inline void ForEachIndirectLayerTree(const Lambda& aCallback);
 
   RefPtr<HostLayerManager> mLayerManager;
   RefPtr<Compositor> mCompositor;
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
@@ -193,17 +193,18 @@ CrossProcessCompositorBridgeParent::Deal
 {
   RemoteContentController* controller = static_cast<RemoteContentController*>(aActor);
   controller->Release();
   return true;
 }
 
 PWebRenderBridgeParent*
 CrossProcessCompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
-                                                                TextureFactoryIdentifier* aTextureFactoryIdentifier)
+                                                                TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                                                uint32_t *aIdNamespace)
 {
 #ifndef MOZ_ENABLE_WEBRENDER
   // Extra guard since this in the parent process and we don't want a malicious
   // child process invoking this codepath before it's ready
   MOZ_RELEASE_ASSERT(false);
 #endif
   // Check to see if this child process has access to this layer tree.
   if (!LayerTreeOwnerTracker::Get()->IsMapped(aPipelineId.mHandle, OtherPid())) {
@@ -216,22 +217,24 @@ CrossProcessCompositorBridgeParent::Allo
   MOZ_ASSERT(sIndirectLayerTrees.find(pipelineHandle) != sIndirectLayerTrees.end());
   MOZ_ASSERT(sIndirectLayerTrees[pipelineHandle].mWrBridge == nullptr);
   CompositorBridgeParent* cbp = sIndirectLayerTrees[pipelineHandle].mParent;
   WebRenderBridgeParent* root = sIndirectLayerTrees[cbp->RootLayerTreeId()].mWrBridge.get();
 
   WebRenderBridgeParent* parent = nullptr;
   RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI();
   RefPtr<WebRenderCompositableHolder> holder = root->CompositableHolder();
-  parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, Move(api), Move(holder));
+  parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, root->CompositorScheduler(), Move(api), Move(holder));
 
   parent->AddRef(); // IPDL reference
   sIndirectLayerTrees[pipelineHandle].mCrossProcessParent = this;
   sIndirectLayerTrees[pipelineHandle].mWrBridge = parent;
   *aTextureFactoryIdentifier = parent->GetTextureFactoryIdentifier();
+  *aIdNamespace = parent->GetIdNameSpace();
+
   return parent;
 }
 
 bool
 CrossProcessCompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
 {
 #ifndef MOZ_ENABLE_WEBRENDER
   // Extra guard since this in the parent process and we don't want a malicious
@@ -318,18 +321,17 @@ CrossProcessCompositorBridgeParent::DidC
   TimeStamp& aCompositeStart,
   TimeStamp& aCompositeEnd)
 {
   sIndirectLayerTreesLock->AssertCurrentThreadOwns();
   if (LayerTransactionParent *layerTree = sIndirectLayerTrees[aId].mLayerTree) {
     Unused << SendDidComposite(aId, layerTree->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
     layerTree->SetPendingTransactionId(0);
   } else if (WebRenderBridgeParent* wrbridge = sIndirectLayerTrees[aId].mWrBridge) {
-    Unused << SendDidComposite(aId, wrbridge->GetPendingTransactionId(), aCompositeStart, aCompositeEnd);
-    wrbridge->SetPendingTransactionId(0);
+    Unused << SendDidComposite(aId, wrbridge->FlushPendingTransactionIds(), aCompositeStart, aCompositeEnd);
   }
 }
 
 void
 CrossProcessCompositorBridgeParent::ForceComposite(LayerTransactionParent* aLayerTree)
 {
   uint64_t id = aLayerTree->GetId();
   MOZ_ASSERT(id != 0);
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
+++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
@@ -147,17 +147,18 @@ public:
   virtual bool DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor) override;
 
   virtual PAPZParent* AllocPAPZParent(const uint64_t& aLayersId) override;
   virtual bool DeallocPAPZParent(PAPZParent* aActor) override;
 
   virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override;
 
   PWebRenderBridgeParent* AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
-                                                      TextureFactoryIdentifier* aTextureFactoryIdentifier) override;
+                                                      TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                                      uint32_t* aIdNamespace) override;
   bool DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor) override;
 
   void ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive) override;
 
 protected:
   void OnChannelConnected(int32_t pid) override {
     mCompositorThreadHolder = CompositorThreadHolder::GetSingleton();
   }
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -238,17 +238,17 @@ parent:
   async AllPluginsCaptured();
 
   async PTexture(SurfaceDescriptor aSharedData, LayersBackend aBackend, TextureFlags aTextureFlags, uint64_t id, uint64_t aSerial);
 
   sync SyncWithCompositor();
 
   // The pipelineId is the same as the layersId
   sync PWebRenderBridge(PipelineId pipelineId)
-    returns (TextureFactoryIdentifier textureFactoryIdentifier);
+    returns (TextureFactoryIdentifier textureFactoryIdentifier, uint32_t idNamespace); //XXX: use the WrIdNamespace type
 
 child:
   // Send back Compositor Frame Metrics from APZCs so tiled layers can
   // update progressively.
   async SharedCompositorFrameMetrics(Handle metrics, CrossProcessMutexHandle mutex, uint64_t aLayersId, uint32_t aAPZCId);
   async ReleaseSharedCompositorFrameMetrics(ViewID aId, uint32_t aAPZCId);
 };
 
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -13,38 +13,42 @@ include "mozilla/layers/WebRenderMessage
 include WebRenderMessages;
 include protocol PCompositorBridge;
 include protocol PTexture;
 
 using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h";
 using mozilla::layers::CompositableHandle from "mozilla/layers/LayersTypes.h";
 using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
+using WrBuiltDisplayListDescriptor from "mozilla/webrender/webrender_ffi.h";
+using WrAuxiliaryListsDescriptor from "mozilla/webrender/webrender_ffi.h";
 
 namespace mozilla {
 namespace layers {
 
 sync protocol PWebRenderBridge
 {
   manager PCompositorBridge;
 
 parent:
   async NewCompositable(CompositableHandle handle, TextureInfo info);
   async ReleaseCompositable(CompositableHandle compositable);
 
   sync Create(IntSize aSize);
-  sync AddImage(IntSize aSize, uint32_t aStride,
-                SurfaceFormat aFormat, ByteBuffer aBytes)
-    returns (ImageKey aOutImageKey);
+  sync AddImage(ImageKey aImageKey, IntSize aSize, uint32_t aStride,
+                SurfaceFormat aFormat, ByteBuffer aBytes);
   sync UpdateImage(ImageKey aImageKey, IntSize aSize,
                    SurfaceFormat aFormat, ByteBuffer aBytes);
   sync DeleteImage(ImageKey aImageKey);
+  async AddRawFont(FontKey aFontKey, ByteBuffer aBytes, uint32_t aFontIndex);
   async DPBegin(IntSize aSize);
-  async DPEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
-  sync DPSyncEnd(WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
+  async DPEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+              ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc, ByteBuffer aAux, WrAuxiliaryListsDescriptor aAuxDesc);
+  sync DPSyncEnd(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
+                 ByteBuffer aDL, WrBuiltDisplayListDescriptor aDLDesc, ByteBuffer aAux, WrAuxiliaryListsDescriptor aAuxDesc);
   sync DPGetSnapshot(PTexture texture);
   async AddExternalImageId(uint64_t aImageId, CompositableHandle aHandle);
   async AddExternalImageIdForCompositable(uint64_t aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(uint64_t aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
 
   async Shutdown();
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -21,16 +21,17 @@ using WrGlyphArray from "mozilla/webrend
 using WrMixBlendMode from "mozilla/webrender/webrender_ffi.h";
 using WrBoxShadowClipMode from "mozilla/webrender/webrender_ffi.h";
 using MaybeImageMask from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
 using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ImageRendering from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::LayerIntRegion from "Units.h";
 
 namespace mozilla {
 namespace layers {
 
 struct OpDPPushStackingContext {
   WrRect bounds;
   WrRect overflow;
@@ -92,39 +93,33 @@ struct OpDPPushRadialGradient {
 struct OpDPPushImage {
   WrRect bounds;
   WrRect clip;
   MaybeImageMask mask;
   ImageRendering filter;
   ImageKey key;
 };
 
-struct OpDPPushExternalImageId {
-  LayerIntRegion validBufferRegion;
-  WrRect bounds;
-  WrRect clip;
-  MaybeImageMask mask;
-  ImageRendering filter;
+struct OpAddExternalImage {
   uint64_t externalImageId;
+  ImageKey key;
 };
 
 struct OpDPPushIframe {
   WrRect bounds;
   WrRect clip;
   PipelineId pipelineId;
 };
 
 struct OpDPPushText {
   WrRect bounds;
   WrRect clip;
   WrGlyphArray[] glyph_array;
-  uint32_t font_index;
   float glyph_size;
-  ByteBuffer font_buffer;
-  uint32_t font_buffer_length;
+  FontKey key;
 };
 
 struct OpDPPushBoxShadow {
   WrRect rect;
   WrRect clip;
   WrRect box_bounds;
   WrPoint offset;
   WrColor color;
@@ -139,17 +134,20 @@ union WebRenderCommand {
   OpDPPopStackingContext;
   OpDPPushScrollLayer;
   OpDPPopScrollLayer;
   OpDPPushRect;
   OpDPPushBorder;
   OpDPPushLinearGradient;
   OpDPPushRadialGradient;
   OpDPPushImage;
-  OpDPPushExternalImageId;
   OpDPPushIframe;
   OpDPPushText;
   OpDPPushBoxShadow;
+};
+
+union WebRenderParentCommand {
+  OpAddExternalImage;
   CompositableOperation;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -6,22 +6,26 @@
 
 #include "mozilla/layers/WebRenderBridgeChild.h"
 
 #include "gfxPlatform.h"
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/PTextureChild.h"
+#include "mozilla/webrender/WebRenderAPI.h"
 
 namespace mozilla {
 namespace layers {
 
 WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
   : mIsInTransaction(false)
+  , mIdNamespace(0)
+  , mResourceId(0)
+  , mPipelineId(aPipelineId)
   , mIPCOpen(false)
   , mDestroyed(false)
 {
 }
 
 void
 WebRenderBridgeChild::Destroy()
 {
@@ -50,40 +54,168 @@ WebRenderBridgeChild::AddWebRenderComman
 
 void
 WebRenderBridgeChild::AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands)
 {
   MOZ_ASSERT(mIsInTransaction);
   mCommands.AppendElements(aCommands);
 }
 
+void
+WebRenderBridgeChild::AddWebRenderParentCommand(const WebRenderParentCommand& aCmd)
+{
+  MOZ_ASSERT(mIsInTransaction);
+  mParentCommands.AppendElement(aCmd);
+}
+
+void
+WebRenderBridgeChild::AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands)
+{
+  MOZ_ASSERT(mIsInTransaction);
+  mParentCommands.AppendElements(aCommands);
+}
+
 bool
 WebRenderBridgeChild::DPBegin(const gfx::IntSize& aSize)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(!mIsInTransaction);
 
   UpdateFwdTransactionId();
   this->SendDPBegin(aSize);
   mIsInTransaction = true;
   return true;
 }
 
+wr::BuiltDisplayList
+WebRenderBridgeChild::ProcessWebrenderCommands(const gfx::IntSize &aSize,
+                                               InfallibleTArray<WebRenderCommand>& aCommands)
+{
+  wr::DisplayListBuilder builder(mPipelineId);
+  builder.Begin(ViewAs<LayerPixel>(aSize));
+
+  for (InfallibleTArray<WebRenderCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
+    const WebRenderCommand& cmd = aCommands[i];
+
+    switch (cmd.type()) {
+      case WebRenderCommand::TOpDPPushStackingContext: {
+        const OpDPPushStackingContext& op = cmd.get_OpDPPushStackingContext();
+        builder.PushStackingContext(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr), op.opacity(), op.matrix(), op.mixBlendMode());
+        break;
+      }
+      case WebRenderCommand::TOpDPPopStackingContext: {
+        builder.PopStackingContext();
+        break;
+      }
+      case WebRenderCommand::TOpDPPushScrollLayer: {
+        const OpDPPushScrollLayer& op = cmd.get_OpDPPushScrollLayer();
+        builder.PushScrollLayer(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr));
+        break;
+      }
+      case WebRenderCommand::TOpDPPopScrollLayer: {
+        builder.PopScrollLayer();
+        break;
+      }
+      case WebRenderCommand::TOpDPPushRect: {
+        const OpDPPushRect& op = cmd.get_OpDPPushRect();
+        builder.PushRect(op.bounds(), op.clip(), op.color());
+        break;
+      }
+      case WebRenderCommand::TOpDPPushBorder: {
+        const OpDPPushBorder& op = cmd.get_OpDPPushBorder();
+        builder.PushBorder(op.bounds(), op.clip(),
+                           op.top(), op.right(), op.bottom(), op.left(),
+                           op.radius());
+        break;
+      }
+      case WebRenderCommand::TOpDPPushLinearGradient: {
+        const OpDPPushLinearGradient& op = cmd.get_OpDPPushLinearGradient();
+        builder.PushLinearGradient(op.bounds(), op.clip(),
+                                   op.startPoint(), op.endPoint(),
+                                   op.stops(), op.extendMode());
+        break;
+      }
+      case WebRenderCommand::TOpDPPushRadialGradient: {
+        const OpDPPushRadialGradient& op = cmd.get_OpDPPushRadialGradient();
+        builder.PushRadialGradient(op.bounds(), op.clip(),
+                                   op.startCenter(), op.endCenter(),
+                                   op.startRadius(), op.endRadius(),
+                                   op.stops(), op.extendMode());
+        break;
+      }
+      case WebRenderCommand::TOpDPPushImage: {
+        const OpDPPushImage& op = cmd.get_OpDPPushImage();
+        builder.PushImage(op.bounds(), op.clip(),
+                          op.mask().ptrOr(nullptr), op.filter(), wr::ImageKey(op.key()));
+        break;
+      }
+      case WebRenderCommand::TOpDPPushIframe: {
+        const OpDPPushIframe& op = cmd.get_OpDPPushIframe();
+        builder.PushIFrame(op.bounds(), op.clip(), op.pipelineId());
+        break;
+      }
+      case WebRenderCommand::TOpDPPushText: {
+        const OpDPPushText& op = cmd.get_OpDPPushText();
+        const nsTArray<WrGlyphArray>& glyph_array = op.glyph_array();
+
+        for (size_t i = 0; i < glyph_array.Length(); i++) {
+          const nsTArray<WrGlyphInstance>& glyphs = glyph_array[i].glyphs;
+          builder.PushText(op.bounds(),
+                           op.clip(),
+                           glyph_array[i].color,
+                           op.key(),
+                           Range<const WrGlyphInstance>(glyphs.Elements(), glyphs.Length()),
+                           op.glyph_size());
+        }
+
+        break;
+      }
+      case WebRenderCommand::TOpDPPushBoxShadow: {
+        const OpDPPushBoxShadow& op = cmd.get_OpDPPushBoxShadow();
+        builder.PushBoxShadow(op.rect(),
+                              op.clip(),
+                              op.box_bounds(),
+                              op.offset(),
+                              op.color(),
+                              op.blur_radius(),
+                              op.spread_radius(),
+                              op.border_radius(),
+                              op.clip_mode());
+        break;
+      }
+      default:
+        NS_RUNTIMEABORT("not reached");
+    }
+  }
+  builder.End();
+  wr::BuiltDisplayList dl;
+  builder.Finalize(dl.dl_desc, dl.dl, dl.aux_desc, dl.aux);
+  return dl;
+}
+
 void
-WebRenderBridgeChild::DPEnd(bool aIsSync, uint64_t aTransactionId)
+WebRenderBridgeChild::DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
+
+  wr::BuiltDisplayList dl = ProcessWebrenderCommands(aSize, mCommands);
+  ByteBuffer dlData(Move(dl.dl));
+  ByteBuffer auxData(Move(dl.aux));
+
   if (aIsSync) {
-    this->SendDPSyncEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
+    this->SendDPSyncEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
+                        dlData, dl.dl_desc, auxData, dl.aux_desc);
   } else {
-    this->SendDPEnd(mCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId);
+    this->SendDPEnd(aSize, mParentCommands, mDestroyedActors, GetFwdTransactionId(), aTransactionId,
+                    dlData, dl.dl_desc, auxData, dl.aux_desc);
   }
 
   mCommands.Clear();
+  mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 uint64_t
 WebRenderBridgeChild::GetNextExternalImageId()
 {
   static uint32_t sNextID = 1;
@@ -216,17 +348,17 @@ WebRenderBridgeChild::RemoveTextureFromC
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aTexture->GetIPDLActor());
   MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() == GetIPCChannel());
   if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
     // We don't have an actor anymore, don't try to use it!
     return;
   }
 
-  AddWebRenderCommand(
+  AddWebRenderParentCommand(
     CompositableOperation(
       aCompositable->GetIPCHandle(),
       OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
 }
 
 void
 WebRenderBridgeChild::UseTextures(CompositableClient* aCompositable,
                                   const nsTArray<TimedTextureClient>& aTextures)
@@ -246,17 +378,17 @@ WebRenderBridgeChild::UseTextures(Compos
     ReadLockDescriptor readLock;
     t.mTextureClient->SerializeReadLock(readLock);
     textures.AppendElement(TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(),
                                         readLock,
                                         t.mTimeStamp, t.mPictureRect,
                                         t.mFrameID, t.mProducerID));
     GetCompositorBridgeChild()->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
   }
-  AddWebRenderCommand(CompositableOperation(aCompositable->GetIPCHandle(),
+  AddWebRenderParentCommand(CompositableOperation(aCompositable->GetIPCHandle(),
                                             OpUseTexture(textures)));
 }
 
 void
 WebRenderBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                                 TextureClient* aClientOnBlack,
                                                 TextureClient* aClientOnWhite)
 {
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -27,19 +27,21 @@ class WebRenderBridgeChild final : publi
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild, override)
 
 public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderCommand(const WebRenderCommand& aCmd);
   void AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands);
+  void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
+  void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
 
   bool DPBegin(const  gfx::IntSize& aSize);
-  void DPEnd(bool aIsSync, uint64_t aTransactionId);
+  void DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId);
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   // KnowsCompositor
   TextureForwarder* GetTextureForwarder() override;
   LayersIPCActor* GetLayersIPCActor() override;
 
   uint64_t AllocExternalImageId(const CompositableHandle& aHandle);
@@ -49,23 +51,33 @@ public:
   /**
    * Clean this up, finishing with SendShutDown() which will cause __delete__
    * to be sent from the parent side.
    */
   void Destroy();
   bool IPCOpen() const { return mIPCOpen && !mDestroyed; }
   bool IsDestroyed() const { return mDestroyed; }
 
+  uint32_t GetNextResourceId() { return ++mResourceId; }
+  uint32_t GetNamespace() { return mIdNamespace; }
+  void SetNamespace(uint32_t aIdNamespace)
+  {
+    mIdNamespace = aIdNamespace;
+  }
+
 private:
   friend class CompositorBridgeChild;
 
   ~WebRenderBridgeChild() {}
 
   uint64_t GetNextExternalImageId();
 
+  wr::BuiltDisplayList ProcessWebrenderCommands(const gfx::IntSize &aSize,
+                                                InfallibleTArray<WebRenderCommand>& aCommands);
+
   // CompositableForwarder
   void Connect(CompositableClient* aCompositable,
                ImageContainer* aImageContainer = nullptr) override;
   void UseTiledLayerBuffer(CompositableClient* aCompositable,
                            const SurfaceDescriptorTiles& aTiledDescriptor) override;
   void UpdateTextureRegion(CompositableClient* aCompositable,
                            const ThebesBufferData& aThebesBufferData,
                            const nsIntRegion& aUpdatedRegion) override;
@@ -94,19 +106,23 @@ private:
     MOZ_ASSERT(mIPCOpen == true);
     mIPCOpen = false;
     Release();
   }
 
   bool AddOpDestroy(const OpDestroy& aOp);
 
   nsTArray<WebRenderCommand> mCommands;
+  nsTArray<WebRenderParentCommand> mParentCommands;
   nsTArray<OpDestroy> mDestroyedActors;
   nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
   bool mIsInTransaction;
+  uint32_t mIdNamespace;
+  uint32_t mResourceId;
+  wr::PipelineId mPipelineId;
 
   bool mIPCOpen;
   bool mDestroyed;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -16,16 +16,21 @@
 #include "mozilla/layers/CompositorVsyncScheduler.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/WebRenderCompositableHolder.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/widget/CompositorWidget.h"
 
+bool is_in_main_thread()
+{
+  return NS_IsMainThread();
+}
+
 bool is_in_compositor_thread()
 {
   return mozilla::layers::CompositorThreadHolder::IsInCompositorThread();
 }
 
 bool is_in_render_thread()
 {
   return mozilla::wr::RenderThread::IsInRenderThread();
@@ -70,51 +75,52 @@ public:
       }
     }
   }
 private:
   WebRenderBridgeParent* mWebRenderBridgeParent;
   InfallibleTArray<OpDestroy>* mActorsToDestroy;
 };
 
+/* static */ uint32_t WebRenderBridgeParent::sIdNameSpace = 0;
+
 WebRenderBridgeParent::WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
                                              const wr::PipelineId& aPipelineId,
                                              widget::CompositorWidget* aWidget,
+                                             CompositorVsyncScheduler* aScheduler,
                                              RefPtr<wr::WebRenderAPI>&& aApi,
                                              RefPtr<WebRenderCompositableHolder>&& aHolder)
   : mCompositorBridge(aCompositorBridge)
   , mPipelineId(aPipelineId)
   , mWidget(aWidget)
-  , mBuilder(Nothing())
   , mApi(aApi)
   , mCompositableHolder(aHolder)
+  , mCompositorScheduler(aScheduler)
   , mChildLayerObserverEpoch(0)
   , mParentLayerObserverEpoch(0)
-  , mPendingTransactionId(0)
+  , mWrEpoch(0)
+  , mIdNameSpace(++sIdNameSpace)
   , mDestroyed(false)
 {
   MOZ_ASSERT(mCompositableHolder);
   if (mWidget) {
+    MOZ_ASSERT(!mCompositorScheduler);
     mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
   }
 }
 
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvCreate(const gfx::IntSize& aSize)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
 
-  if (mBuilder.isSome()) {
-    return IPC_OK();
-  }
   MOZ_ASSERT(mApi);
-  mBuilder.emplace(LayerIntSize(aSize.width, aSize.height), mPipelineId);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvShutdown()
 {
   if (mDestroyed) {
@@ -128,40 +134,56 @@ WebRenderBridgeParent::RecvShutdown()
 }
 
 void
 WebRenderBridgeParent::Destroy()
 {
   if (mDestroyed) {
     return;
   }
-  MOZ_ASSERT(mBuilder.isSome());
   mDestroyed = true;
   ClearResources();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvAddImage(const gfx::IntSize& aSize,
+WebRenderBridgeParent::RecvAddImage(const wr::ImageKey& aImageKey,
+				    const gfx::IntSize& aSize,
                                     const uint32_t& aStride,
                                     const gfx::SurfaceFormat& aFormat,
-                                    const ByteBuffer& aBuffer,
-                                    wr::ImageKey* aOutImageKey)
+                                    const ByteBuffer& aBuffer)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   MOZ_ASSERT(mApi);
   wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
-  *aOutImageKey = mApi->AddImageBuffer(descriptor,
-                                       aBuffer.AsSlice());
+  mApi->AddImage(aImageKey, descriptor,
+                 aBuffer.AsSlice());
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+WebRenderBridgeParent::RecvAddRawFont(const wr::FontKey& aFontKey,
+                                      const ByteBuffer& aBuffer,
+                                      const uint32_t& aFontIndex)
+{
+  if (mDestroyed) {
+    return IPC_OK();
+  }
+  MOZ_ASSERT(mApi);
+  auto slice = aBuffer.AsSlice();
+  mApi->AddRawFont(aFontKey, slice);
+
+  return IPC_OK();
+}
+
+
+
+mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvUpdateImage(const wr::ImageKey& aImageKey,
                                        const gfx::IntSize& aSize,
                                        const gfx::SurfaceFormat& aFormat,
                                        const ByteBuffer& aBuffer)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
@@ -184,234 +206,143 @@ WebRenderBridgeParent::RecvDeleteImage(c
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDPBegin(const gfx::IntSize& aSize)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
-  MOZ_ASSERT(mBuilder.isSome());
-  mBuilder.ref().Begin(LayerIntSize(aSize.width, aSize.height));
   return IPC_OK();
 }
 
 void
-WebRenderBridgeParent::HandleDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::HandleDPEnd(const gfx::IntSize& aSize,
+                                 InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
-                                 const uint64_t& aTransactionId)
+                                 const uint64_t& aTransactionId,
+                                 const ByteBuffer& dl,
+                                 const WrBuiltDisplayListDescriptor& dlDesc,
+                                 const ByteBuffer& aux,
+                                 const WrAuxiliaryListsDescriptor& auxDesc)
 {
   UpdateFwdTransactionId(aFwdTransactionId);
 
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
     }
     return;
   }
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
-  ProcessWebrenderCommands(aCommands, wr::NewEpoch(aTransactionId));
-
-  // The transaction ID might get reset to 1 if the page gets reloaded, see
-  // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
-  // Otherwise, it should be continually increasing.
-  MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransactionId);
-  mPendingTransactionId = aTransactionId;
+  ++mWrEpoch; // Update webrender epoch
+  ProcessWebrenderCommands(aSize, aCommands, wr::NewEpoch(mWrEpoch),
+                           dl, dlDesc, aux, auxDesc);
+  HoldPendingTransactionId(mWrEpoch, aTransactionId);
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::RecvDPEnd(const gfx::IntSize& aSize,
+                                 InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                  const uint64_t& aFwdTransactionId,
-                                 const uint64_t& aTransactionId)
+                                 const uint64_t& aTransactionId,
+                                 const ByteBuffer& dl,
+                                 const WrBuiltDisplayListDescriptor& dlDesc,
+                                 const ByteBuffer& aux,
+                                 const WrAuxiliaryListsDescriptor& auxDesc)
 {
-  HandleDPEnd(Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
+  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
+              dl, dlDesc, aux, auxDesc);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+WebRenderBridgeParent::RecvDPSyncEnd(const gfx::IntSize &aSize,
+                                     InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                      InfallibleTArray<OpDestroy>&& aToDestroy,
                                      const uint64_t& aFwdTransactionId,
-                                     const uint64_t& aTransactionId)
+                                     const uint64_t& aTransactionId,
+                                     const ByteBuffer& dl,
+                                     const WrBuiltDisplayListDescriptor& dlDesc,
+                                     const ByteBuffer& aux,
+                                     const WrAuxiliaryListsDescriptor& auxDesc)
 {
-  HandleDPEnd(Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId);
+  HandleDPEnd(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
+              dl, dlDesc, aux, auxDesc);
   return IPC_OK();
 }
 
 void
-WebRenderBridgeParent::ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& aCommands, const wr::Epoch& aEpoch)
+WebRenderBridgeParent::ProcessWebrenderCommands(const gfx::IntSize &aSize,
+                                                InfallibleTArray<WebRenderParentCommand>& aCommands, const wr::Epoch& aEpoch,
+                                                const ByteBuffer& dl,
+                                                const WrBuiltDisplayListDescriptor& dlDesc,
+                                                const ByteBuffer& aux,
+                                                const WrAuxiliaryListsDescriptor& auxDesc)
 {
-  MOZ_ASSERT(mBuilder.isSome());
-  wr::DisplayListBuilder& builder = mBuilder.ref();
   // XXX remove it when external image key is used.
   std::vector<wr::ImageKey> keysToDelete;
 
-  for (InfallibleTArray<WebRenderCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
-    const WebRenderCommand& cmd = aCommands[i];
+  for (InfallibleTArray<WebRenderParentCommand>::index_type i = 0; i < aCommands.Length(); ++i) {
+    const WebRenderParentCommand& cmd = aCommands[i];
 
     switch (cmd.type()) {
-      case WebRenderCommand::TOpDPPushStackingContext: {
-        const OpDPPushStackingContext& op = cmd.get_OpDPPushStackingContext();
-        builder.PushStackingContext(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr), op.opacity(), op.matrix(), op.mixBlendMode());
-        break;
-      }
-      case WebRenderCommand::TOpDPPopStackingContext: {
-        builder.PopStackingContext();
-        break;
-      }
-      case WebRenderCommand::TOpDPPushScrollLayer: {
-        const OpDPPushScrollLayer& op = cmd.get_OpDPPushScrollLayer();
-        builder.PushScrollLayer(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr));
-        break;
-      }
-      case WebRenderCommand::TOpDPPopScrollLayer: {
-        builder.PopScrollLayer();
-        break;
-      }
-      case WebRenderCommand::TOpDPPushRect: {
-        const OpDPPushRect& op = cmd.get_OpDPPushRect();
-        builder.PushRect(op.bounds(), op.clip(), op.color());
-        break;
-      }
-      case WebRenderCommand::TOpDPPushBorder: {
-        const OpDPPushBorder& op = cmd.get_OpDPPushBorder();
-        builder.PushBorder(op.bounds(), op.clip(),
-                           op.top(), op.right(), op.bottom(), op.left(),
-                           op.radius());
-        break;
-      }
-      case WebRenderCommand::TOpDPPushLinearGradient: {
-        const OpDPPushLinearGradient& op = cmd.get_OpDPPushLinearGradient();
-        builder.PushLinearGradient(op.bounds(), op.clip(),
-                                   op.startPoint(), op.endPoint(),
-                                   op.stops(), op.extendMode());
-        break;
-      }
-      case WebRenderCommand::TOpDPPushRadialGradient: {
-        const OpDPPushRadialGradient& op = cmd.get_OpDPPushRadialGradient();
-        builder.PushRadialGradient(op.bounds(), op.clip(),
-                                   op.startCenter(), op.endCenter(),
-                                   op.startRadius(), op.endRadius(),
-                                   op.stops(), op.extendMode());
-        break;
-      }
-      case WebRenderCommand::TOpDPPushImage: {
-        const OpDPPushImage& op = cmd.get_OpDPPushImage();
-        builder.PushImage(op.bounds(), op.clip(),
-                          op.mask().ptrOr(nullptr), op.filter(), wr::ImageKey(op.key()));
-        break;
-      }
-      case WebRenderCommand::TOpDPPushExternalImageId: {
-        const OpDPPushExternalImageId& op = cmd.get_OpDPPushExternalImageId();
+      case WebRenderParentCommand::TOpAddExternalImage: {
+        const OpAddExternalImage& op = cmd.get_OpAddExternalImage();
         MOZ_ASSERT(mExternalImageIds.Get(op.externalImageId()).get());
 
         RefPtr<CompositableHost> host = mExternalImageIds.Get(op.externalImageId());
         if (!host) {
           break;
         }
         RefPtr<DataSourceSurface> dSurf = host->GetAsSurface();
         if (!dSurf) {
           break;
         }
 
-        nsIntRegion validBufferRegion = op.validBufferRegion().ToUnknownRegion();
-        IntRect validRect = IntRect(IntPoint(0,0), dSurf->GetSize());
-        if (!validBufferRegion.IsEmpty()) {
-          IntPoint offset = validBufferRegion.GetBounds().TopLeft();
-          validBufferRegion.MoveBy(-offset);
-          validBufferRegion.AndWith(IntRect(IntPoint(0,0), dSurf->GetSize()));
-          validRect = validBufferRegion.GetBounds().ToUnknownRect();
-
-          // XXX Remove it when we can put subimage in WebRender.
-          RefPtr<DrawTarget> target =
-           gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, validRect.Size(), SurfaceFormat::B8G8R8A8);
-          for (auto iter = validBufferRegion.RectIter(); !iter.Done(); iter.Next()) {
-            IntRect regionRect = iter.Get();
-            Rect srcRect(regionRect.x + offset.x, regionRect.y + offset.y, regionRect.width, regionRect.height);
-            Rect dstRect(regionRect.x, regionRect.y, regionRect.width, regionRect.height);
-            target->DrawSurface(dSurf, dstRect, srcRect);
-          }
-          RefPtr<SourceSurface> surf = target->Snapshot();
-          dSurf = surf->GetDataSurface();
-        }
-
         DataSourceSurface::MappedSurface map;
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           break;
         }
 
-        wr::ImageDescriptor descriptor(validRect.Size(), map.mStride, SurfaceFormat::B8G8R8A8);
-        wr::ImageKey key;
-        auto slice = Range<uint8_t>(map.mData, validRect.height * map.mStride);
-        key = mApi->AddImageBuffer(descriptor, slice);
+        IntSize size = dSurf->GetSize();
+        wr::ImageDescriptor descriptor(size, map.mStride, SurfaceFormat::B8G8R8A8);
+        wr::ImageKey key = op.key();
+        auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
+        mApi->AddImage(key, descriptor, slice);
 
-        builder.PushImage(op.bounds(), op.clip(), op.mask().ptrOr(nullptr), op.filter(), key);
         keysToDelete.push_back(key);
         dSurf->Unmap();
         // XXX workaround for releasing Readlock. See Bug 1339625
         if(host->GetType() == CompositableType::CONTENT_SINGLE) {
           host->CleanupResources();
         }
         break;
       }
-      case WebRenderCommand::TOpDPPushIframe: {
-        const OpDPPushIframe& op = cmd.get_OpDPPushIframe();
-        builder.PushIFrame(op.bounds(), op.clip(), op.pipelineId());
-        break;
-      }
-      case WebRenderCommand::TCompositableOperation: {
+      case WebRenderParentCommand::TCompositableOperation: {
         if (!ReceiveCompositableUpdate(cmd.get_CompositableOperation())) {
           NS_ERROR("ReceiveCompositableUpdate failed");
         }
         break;
       }
-      case WebRenderCommand::TOpDPPushText: {
-        const OpDPPushText& op = cmd.get_OpDPPushText();
-        const nsTArray<WrGlyphArray>& glyph_array = op.glyph_array();
-
-        // TODO: We are leaking the key
-        wr::FontKey fontKey;
-        auto slice = Range<uint8_t>(op.font_buffer().mData, op.font_buffer_length());
-        fontKey = mApi->AddRawFont(slice);
-
-        for (size_t i = 0; i < glyph_array.Length(); i++) {
-          const nsTArray<WrGlyphInstance>& glyphs = glyph_array[i].glyphs;
-          builder.PushText(op.bounds(),
-                           op.clip(),
-                           glyph_array[i].color,
-                           fontKey,
-                           Range<const WrGlyphInstance>(glyphs.Elements(), glyphs.Length()),
-                           op.glyph_size());
-        }
-
+      default: {
+        // other commands are handle on the child
         break;
       }
-      case WebRenderCommand::TOpDPPushBoxShadow: {
-        const OpDPPushBoxShadow& op = cmd.get_OpDPPushBoxShadow();
-        builder.PushBoxShadow(op.rect(),
-                              op.clip(),
-                              op.box_bounds(),
-                              op.offset(),
-                              op.color(),
-                              op.blur_radius(),
-                              op.spread_radius(),
-                              op.border_radius(),
-                              op.clip_mode());
-        break;
-      }
-      default:
-        NS_RUNTIMEABORT("not reached");
     }
   }
-  builder.End(*mApi, aEpoch);
+  mApi->SetRootDisplayList(gfx::Color(0.3f, 0.f, 0.f, 1.f), aEpoch, LayerSize(aSize.width, aSize.height),
+                           mPipelineId,
+                           dlDesc, dl.mData, dl.mLength,
+                           auxDesc, aux.mData, aux.mLength);
 
   ScheduleComposition();
   DeleteOldImages();
 
   // XXX remove it when external image key is used.
   if (!keysToDelete.empty()) {
     mKeysToDelete.swap(keysToDelete);
   }
@@ -454,17 +385,21 @@ WebRenderBridgeParent::RecvDPGetSnapshot
   // We only support B8G8R8A8 for now.
   MOZ_ASSERT(buffer);
   MOZ_ASSERT(bufferTexture->GetFormat() == SurfaceFormat::B8G8R8A8);
   uint32_t buffer_size = size.width * size.height * 4;
 
   // Assert the stride of the buffer is what webrender expects
   MOZ_ASSERT((uint32_t)(size.width * 4) == stride);
 
-  MOZ_ASSERT(mBuilder.isSome());
+  if (mCompositorScheduler->NeedsComposite()) {
+    mCompositorScheduler->CancelCurrentCompositeTask();
+    mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
+  }
+
   mApi->Readback(size, buffer, buffer_size);
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvAddExternalImageId(const uint64_t& aImageId,
                                               const CompositableHandle& aHandle)
@@ -551,25 +486,69 @@ void
 WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   Destroy();
 }
 
 void
 WebRenderBridgeParent::CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect)
 {
-  // TODO(bug 1328602) With the RenderThread, calling SetRootStackingContext
-  // should trigger the composition on the render thread.
-  MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+  mApi->GenerateFrame();
 }
 
 void
-WebRenderBridgeParent::DidComposite(uint64_t aTransactionId, TimeStamp aStart, TimeStamp aEnd)
+WebRenderBridgeParent::HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId)
+{
+  // The transaction ID might get reset to 1 if the page gets reloaded, see
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
+  // Otherwise, it should be continually increasing.
+  MOZ_ASSERT(aTransactionId == 1 || aTransactionId > LastPendingTransactionId());
+  // Handle TransactionIdAllocator(RefreshDriver) change.
+  if (aTransactionId == 1) {
+    FlushPendingTransactionIds();
+  }
+  mPendingTransactionIds.push(PendingTransactionId(wr::NewEpoch(aWrEpoch), aTransactionId));
+}
+
+uint64_t
+WebRenderBridgeParent::LastPendingTransactionId()
 {
-  mCompositorBridge->NotifyDidComposite(aTransactionId, aStart, aEnd);
+  uint64_t id = 0;
+  if (!mPendingTransactionIds.empty()) {
+    id = mPendingTransactionIds.back().mId;
+  }
+  return id;
+}
+
+uint64_t
+WebRenderBridgeParent::FlushPendingTransactionIds()
+{
+  uint64_t id = 0;
+  while (!mPendingTransactionIds.empty()) {
+    id = mPendingTransactionIds.front().mId;
+    mPendingTransactionIds.pop();
+  }
+  return id;
+}
+
+
+
+uint64_t
+WebRenderBridgeParent::FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch)
+{
+  uint64_t id = 0;
+  while (!mPendingTransactionIds.empty()) {
+    id = mPendingTransactionIds.front().mId;
+    if (mPendingTransactionIds.front().mEpoch == aEpoch) {
+      mPendingTransactionIds.pop();
+      break;
+    }
+    mPendingTransactionIds.pop();
+  }
+  return id;
 }
 
 WebRenderBridgeParent::~WebRenderBridgeParent()
 {
 }
 
 void
 WebRenderBridgeParent::DeleteOldImages()
@@ -578,43 +557,37 @@ WebRenderBridgeParent::DeleteOldImages()
     mApi->DeleteImage(key);
   }
   mKeysToDelete.clear();
 }
 
 void
 WebRenderBridgeParent::ScheduleComposition()
 {
-  MOZ_ASSERT(mApi);
-  // TODO(bug 1328602) should probably send a message to the render
-  // thread and force rendering, although in most cases where this is
-  // called, rendering should be triggered automatically already (maybe
-  // not in the ImageBridge case).
+  if (mCompositorScheduler) {
+    mCompositorScheduler->ScheduleComposition();
+  }
 }
 
 void
 WebRenderBridgeParent::ClearResources()
 {
   DeleteOldImages();
   if (mCompositableHolder) {
     for (auto iter = mExternalImageIds.Iter(); !iter.Done(); iter.Next()) {
       uint64_t externalImageId = iter.Key();
       mCompositableHolder->RemoveExternalImageId(externalImageId);
     }
   }
   mExternalImageIds.Clear();
 
-  if (mBuilder.isSome()) {
-    mBuilder.reset();
+  if (mWidget && mCompositorScheduler) {
+    mCompositorScheduler->Destroy();
   }
-  if (mCompositorScheduler) {
-    mCompositorScheduler->Destroy();
-    mCompositorScheduler = nullptr;
-  }
-
+  mCompositorScheduler = nullptr;
   mApi = nullptr;
   mCompositorBridge = nullptr;
 }
 
 bool
 WebRenderBridgeParent::ShouldParentObserveEpoch()
 {
   if (mParentLayerObserverEpoch == mChildLayerObserverEpoch) {
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -41,131 +41,171 @@ class WebRenderCompositableHolder;
 class WebRenderBridgeParent final : public PWebRenderBridgeParent
                                   , public CompositorVsyncSchedulerOwner
                                   , public CompositableParentManager
 {
 public:
   WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge,
                         const wr::PipelineId& aPipelineId,
                         widget::CompositorWidget* aWidget,
+                        CompositorVsyncScheduler* aScheduler,
                         RefPtr<wr::WebRenderAPI>&& aApi,
                         RefPtr<WebRenderCompositableHolder>&& aHolder);
 
   wr::PipelineId PipelineId() { return mPipelineId; }
   wr::WebRenderAPI* GetWebRenderAPI() { return mApi; }
   WebRenderCompositableHolder* CompositableHolder() { return mCompositableHolder; }
   CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); }
 
   mozilla::ipc::IPCResult RecvNewCompositable(const CompositableHandle& aHandle,
                                               const TextureInfo& aInfo) override;
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   mozilla::ipc::IPCResult RecvCreate(const gfx::IntSize& aSize) override;
   mozilla::ipc::IPCResult RecvShutdown() override;
-  mozilla::ipc::IPCResult RecvAddImage(const gfx::IntSize& aSize,
+  mozilla::ipc::IPCResult RecvAddImage(const wr::ImageKey& aImageKey,
+                                       const gfx::IntSize& aSize,
                                        const uint32_t& aStride,
                                        const gfx::SurfaceFormat& aFormat,
-                                       const ByteBuffer& aBuffer,
-                                       wr::ImageKey* aOutImageKey) override;
+                                       const ByteBuffer& aBuffer) override;
+  mozilla::ipc::IPCResult RecvAddRawFont(const wr::FontKey& aFontKey,
+                                         const ByteBuffer& aBuffer,
+                                         const uint32_t& aFontIndex) override;
   mozilla::ipc::IPCResult RecvUpdateImage(const wr::ImageKey& aImageKey,
                                           const gfx::IntSize& aSize,
                                           const gfx::SurfaceFormat& aFormat,
                                           const ByteBuffer& aBuffer) override;
   mozilla::ipc::IPCResult RecvDeleteImage(const wr::ImageKey& a1) override;
   mozilla::ipc::IPCResult RecvDPBegin(const gfx::IntSize& aSize) override;
-  mozilla::ipc::IPCResult RecvDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+  mozilla::ipc::IPCResult RecvDPEnd(const gfx::IntSize& aSize,
+                                    InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                     InfallibleTArray<OpDestroy>&& aToDestroy,
                                     const uint64_t& aFwdTransactionId,
-                                    const uint64_t& aTransactionId) override;
-  mozilla::ipc::IPCResult RecvDPSyncEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+                                    const uint64_t& aTransactionId,
+                                    const ByteBuffer& dl,
+                                    const WrBuiltDisplayListDescriptor& dlDesc,
+                                    const ByteBuffer& aux,
+                                    const WrAuxiliaryListsDescriptor& auxDesc) override;
+  mozilla::ipc::IPCResult RecvDPSyncEnd(const gfx::IntSize& aSize,
+                                        InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                         InfallibleTArray<OpDestroy>&& aToDestroy,
                                         const uint64_t& aFwdTransactionId,
-                                        const uint64_t& aTransactionId) override;
+                                        const uint64_t& aTransactionId,
+                                        const ByteBuffer& dl,
+                                        const WrBuiltDisplayListDescriptor& dlDesc,
+                                        const ByteBuffer& aux,
+                                        const WrAuxiliaryListsDescriptor& auxDesc) override;
   mozilla::ipc::IPCResult RecvDPGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvAddExternalImageId(const uint64_t& aImageId,
                                                  const CompositableHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvAddExternalImageIdForCompositable(const uint64_t& aImageId,
                                                                 const CompositableHandle& aHandle) override;
   mozilla::ipc::IPCResult RecvRemoveExternalImageId(const uint64_t& aImageId) override;
   mozilla::ipc::IPCResult RecvSetLayerObserverEpoch(const uint64_t& aLayerObserverEpoch) override;
 
   mozilla::ipc::IPCResult RecvClearCachedResources() override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void SetWebRenderProfilerEnabled(bool aEnabled);
 
   void Destroy();
 
-  const uint64_t& GetPendingTransactionId() { return mPendingTransactionId; }
-  void SetPendingTransactionId(uint64_t aId) { mPendingTransactionId = aId; }
-
   // CompositorVsyncSchedulerOwner
   bool IsPendingComposite() override { return false; }
   void FinishPendingComposite() override { }
   void CompositeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr) override;
 
   // CompositableParentManager
   bool IsSameProcess() const override;
   base::ProcessId GetChildProcessId() override;
   void NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId) override;
   void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) override;
   void SendPendingAsyncMessages() override;
   void SetAboutToSendAsyncMessages() override;
 
-  void DidComposite(uint64_t aTransactionId, TimeStamp aStart, TimeStamp aEnd);
+  void HoldPendingTransactionId(uint32_t aWrEpoch, uint64_t aTransactionId);
+  uint64_t LastPendingTransactionId();
+  uint64_t FlushPendingTransactionIds();
+  uint64_t FlushTransactionIdsForEpoch(const wr::Epoch& aEpoch);
 
   TextureFactoryIdentifier GetTextureFactoryIdentifier();
 
   void AppendImageCompositeNotification(const ImageCompositeNotificationInfo& aNotification)
   {
     MOZ_ASSERT(mWidget);
     mImageCompositeNotifications.AppendElement(aNotification);
   }
 
   void ExtractImageCompositeNotifications(nsTArray<ImageCompositeNotificationInfo>* aNotifications)
   {
     MOZ_ASSERT(mWidget);
     aNotifications->AppendElements(Move(mImageCompositeNotifications));
   }
 
+  uint32_t GetIdNameSpace()
+  {
+    return mIdNameSpace;
+  }
+
 private:
   virtual ~WebRenderBridgeParent();
 
   void DeleteOldImages();
-  void ProcessWebrenderCommands(InfallibleTArray<WebRenderCommand>& commands, const wr::Epoch& aEpoch);
+  void ProcessWebrenderCommands(const gfx::IntSize &aSize, InfallibleTArray<WebRenderParentCommand>& commands, const wr::Epoch& aEpoch,
+                                    const ByteBuffer& dl,
+                                    const WrBuiltDisplayListDescriptor& dlDesc,
+                                    const ByteBuffer& aux,
+                                    const WrAuxiliaryListsDescriptor& auxDesc);
   void ScheduleComposition();
   void ClearResources();
   uint64_t GetChildLayerObserverEpoch() const { return mChildLayerObserverEpoch; }
   bool ShouldParentObserveEpoch();
-  void HandleDPEnd(InfallibleTArray<WebRenderCommand>&& aCommands,
+  void HandleDPEnd(const gfx::IntSize& aSize,
+                   InfallibleTArray<WebRenderParentCommand>&& aCommands,
                    InfallibleTArray<OpDestroy>&& aToDestroy,
                    const uint64_t& aFwdTransactionId,
-                   const uint64_t& aTransactionId);
+                   const uint64_t& aTransactionId,
+                   const ByteBuffer& dl,
+                   const WrBuiltDisplayListDescriptor& dlDesc,
+                   const ByteBuffer& aux,
+                   const WrAuxiliaryListsDescriptor& auxDesc);
 
 private:
+  struct PendingTransactionId {
+    PendingTransactionId(wr::Epoch aEpoch, uint64_t aId)
+      : mEpoch(aEpoch)
+      , mId(aId)
+    {}
+    wr::Epoch mEpoch;
+    uint64_t mId;
+  };
+
   CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
   wr::PipelineId mPipelineId;
   RefPtr<widget::CompositorWidget> mWidget;
-  Maybe<wr::DisplayListBuilder> mBuilder;
   RefPtr<wr::WebRenderAPI> mApi;
   RefPtr<WebRenderCompositableHolder> mCompositableHolder;
   RefPtr<CompositorVsyncScheduler> mCompositorScheduler;
   std::vector<wr::ImageKey> mKeysToDelete;
   nsDataHashtable<nsUint64HashKey, RefPtr<CompositableHost>> mExternalImageIds;
   nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications;
 
   // These fields keep track of the latest layer observer epoch values in the child and the
   // parent. mChildLayerObserverEpoch is the latest epoch value received from the child.
   // mParentLayerObserverEpoch is the latest epoch value that we have told TabParent about
   // (via ObserveLayerUpdate).
   uint64_t mChildLayerObserverEpoch;
   uint64_t mParentLayerObserverEpoch;
 
-  uint64_t mPendingTransactionId;
+  std::queue<PendingTransactionId> mPendingTransactionIds;
+  uint32_t mWrEpoch;
+  uint32_t mIdNameSpace;
 
   bool mDestroyed;
+
+  static uint32_t sIdNameSpace;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // mozilla_layers_WebRenderBridgeParent_h
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -102,17 +102,21 @@ WebRenderCanvasLayer::RenderLayer()
       OpDPPushStackingContext(wr::ToWrRect(relBounds),
                               wr::ToWrRect(overflow),
                               mask,
                               1.0f,
                               GetAnimations(),
                               transform,
                               mixBlendMode,
                               FrameMetrics::NULL_SCROLL_ID));
-  WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(LayerIntRegion(), wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, mExternalImageId));
+  WrImageKey key;
+  key.mNamespace = WrBridge()->GetNamespace();
+  key.mHandle = WrBridge()->GetNextResourceId();
+  WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
+  WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, key));
   WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
 }
 
 void
 WebRenderCanvasLayer::AttachCompositable()
 {
   mCanvasClient->Connect();
 }
--- a/gfx/layers/wr/WebRenderDisplayItemLayer.cpp
+++ b/gfx/layers/wr/WebRenderDisplayItemLayer.cpp
@@ -16,22 +16,24 @@ namespace mozilla {
 namespace layers {
 
 void
 WebRenderDisplayItemLayer::RenderLayer()
 {
   if (mItem) {
     // We might have recycled this layer. Throw away the old commands.
     mCommands.Clear();
-    mItem->CreateWebRenderCommands(mCommands, this);
+    mParentCommands.Clear();
+    mItem->CreateWebRenderCommands(mCommands, mParentCommands, this);
   }
   // else we have an empty transaction and just use the
   // old commands.
 
   WrBridge()->AddWebRenderCommands(mCommands);
+  WrBridge()->AddWebRenderParentCommands(mParentCommands);
 }
 
 uint64_t
 WebRenderDisplayItemLayer::SendImageContainer(ImageContainer* aContainer)
 {
   if (mImageContainer != aContainer) {
     AutoLockImage autoLock(aContainer);
     Image* image = autoLock.GetImage();
--- a/gfx/layers/wr/WebRenderDisplayItemLayer.h
+++ b/gfx/layers/wr/WebRenderDisplayItemLayer.h
@@ -34,18 +34,19 @@ protected:
   }
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer() override;
 
 private:
   nsTArray<WebRenderCommand> mCommands;
+  nsTArray<WebRenderParentCommand> mParentCommands;
   RefPtr<ImageClient> mImageClient;
   RefPtr<ImageContainer> mImageContainer;
   uint64_t mExternalImageId;
 
 };
 
 } // namespace layers
 } // namespace mozilla
 
-#endif // GFX_WEBRENDERDisplayItemLayer_H
\ No newline at end of file
+#endif // GFX_WEBRENDERDisplayItemLayer_H
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -169,16 +169,20 @@ WebRenderImageLayer::RenderLayer()
     OpDPPushStackingContext(wr::ToWrRect(relBounds),
                             wr::ToWrRect(overflow),
                             mask,
                             1.0f,
                             GetAnimations(),
                             transform,
                             mixBlendMode,
                             FrameMetrics::NULL_SCROLL_ID));
-  WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(LayerIntRegion(), wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, mExternalImageId));
+  WrImageKey key;
+  key.mNamespace = WrBridge()->GetNamespace();
+  key.mHandle = WrBridge()->GetNextResourceId();
+  WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
+  WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), filter, key));
   WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
 
   //mContainer->SetImageFactory(originalIF);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -124,18 +124,20 @@ WebRenderLayer::buildMaskLayer() {
       //XXX: let's assert that the mask transform is the same as the layer transform
       //transform.PostTranslate(-aDeviceOffset.x, -aDeviceOffset.y);
       {
           RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
           DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::MapType::READ);
           gfx::IntSize size = surface->GetSize();
           MOZ_RELEASE_ASSERT(surface->GetFormat() == SurfaceFormat::A8, "bad format");
           wr::ByteBuffer buf(size.height * map.GetStride(), map.GetData());
-          wr::ImageKey maskKey;
-          WrBridge()->SendAddImage(size, map.GetStride(), SurfaceFormat::A8, buf, &maskKey);
+          WrImageKey maskKey;
+          maskKey.mNamespace = WrBridge()->GetNamespace();
+          maskKey.mHandle = WrBridge()->GetNextResourceId();
+          WrBridge()->SendAddImage(maskKey, size, map.GetStride(), SurfaceFormat::A8, buf);
 
           imageMask.image = maskKey;
           imageMask.rect = wr::ToWrRect(Rect(0, 0, size.width, size.height));
           imageMask.repeat = false;
           WrManager()->AddImageKeyForDiscard(maskKey);
           mask = Some(imageMask);
       }
     }
@@ -212,23 +214,26 @@ void
 WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild,
                                   wr::PipelineId aLayersId,
                                   TextureFactoryIdentifier* aTextureFactoryIdentifier)
 {
   MOZ_ASSERT(mWrChild == nullptr);
   MOZ_ASSERT(aTextureFactoryIdentifier);
 
   TextureFactoryIdentifier textureFactoryIdentifier;
+  uint32_t id_namespace;
   PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
-                                                                            &textureFactoryIdentifier);
+                                                                            &textureFactoryIdentifier,
+                                                                            &id_namespace);
   MOZ_ASSERT(bridge);
   mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
   LayoutDeviceIntSize size = mWidget->GetClientSize();
   WrBridge()->SendCreate(size.ToUnknownSize());
   WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
+  WrBridge()->SetNamespace(id_namespace);
   *aTextureFactoryIdentifier = textureFactoryIdentifier;
 }
 
 void
 WebRenderLayerManager::Destroy()
 {
   if (IsDestroyed()) {
     return;
@@ -311,17 +316,17 @@ WebRenderLayerManager::EndTransaction(Dr
     return;
   }
 
   WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer();
 
   bool sync = mTarget != nullptr;
   mLatestTransactionId = mTransactionIdAllocator->GetTransactionId();
 
-  WrBridge()->DPEnd(sync, mLatestTransactionId);
+  WrBridge()->DPEnd(size.ToUnknownSize(), sync, mLatestTransactionId);
 
   MakeSnapshotIfRequired(size);
 
   // this may result in Layers being deleted, which results in
   // PLayer::Send__delete__() and DeallocShmem()
   mKeepAlive.Clear();
 }
 
--- a/gfx/layers/wr/WebRenderMessageUtils.h
+++ b/gfx/layers/wr/WebRenderMessageUtils.h
@@ -323,16 +323,55 @@ struct ParamTraits<WrImageMask>
   {
     return ReadParam(aMsg, aIter, &aResult->image)
         && ReadParam(aMsg, aIter, &aResult->rect)
         && ReadParam(aMsg, aIter, &aResult->repeat);
   }
 };
 
 template<>
+struct ParamTraits<WrBuiltDisplayListDescriptor>
+{
+  static void
+  Write(Message* aMsg, const WrBuiltDisplayListDescriptor& aParam)
+  {
+    WriteParam(aMsg, aParam.display_list_items_size);
+  }
+
+  static bool
+  Read(const Message* aMsg, PickleIterator* aIter, WrBuiltDisplayListDescriptor* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->display_list_items_size);
+  }
+};
+
+template<>
+struct ParamTraits<WrAuxiliaryListsDescriptor>
+{
+  static void
+  Write(Message* aMsg, const WrAuxiliaryListsDescriptor& aParam)
+  {
+    WriteParam(aMsg, aParam.gradient_stops_size);
+    WriteParam(aMsg, aParam.complex_clip_regions_size);
+    WriteParam(aMsg, aParam.filters_size);
+    WriteParam(aMsg, aParam.glyph_instances_size);
+  }
+
+  static bool
+  Read(const Message* aMsg, PickleIterator* aIter, WrAuxiliaryListsDescriptor* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->gradient_stops_size)
+        && ReadParam(aMsg, aIter, &aResult->complex_clip_regions_size)
+        && ReadParam(aMsg, aIter, &aResult->filters_size)
+        && ReadParam(aMsg, aIter, &aResult->glyph_instances_size);
+  }
+};
+
+
+template<>
 struct ParamTraits<WrImageRendering>
   : public ContiguousEnumSerializer<
         WrImageRendering,
         WrImageRendering::Auto,
         WrImageRendering::Sentinel>
 {
 };
 
--- a/gfx/layers/wr/WebRenderPaintedLayer.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp
@@ -228,15 +228,18 @@ WebRenderPaintedLayer::RenderLayer()
       OpDPPushStackingContext(wr::ToWrRect(relBounds),
                               wr::ToWrRect(overflow),
                               mask,
                               1.0f,
                               GetAnimations(),
                               transform,
                               mixBlendMode,
                               FrameMetrics::NULL_SCROLL_ID));
-  WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(LayerIntRegion(), wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), wr::ImageRendering::Auto, mExternalImageId));
-
+  WrImageKey key;
+  key.mNamespace = WrBridge()->GetNamespace();
+  key.mHandle = WrBridge()->GetNextResourceId();
+  WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId, key));
+  WrBridge()->AddWebRenderCommand(OpDPPushImage(wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), wr::ImageRendering::Auto, key));
   WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderTextLayer.cpp
+++ b/gfx/layers/wr/WebRenderTextLayer.cpp
@@ -35,15 +35,15 @@ WebRenderTextLayer::RenderLayer()
     if (gfxPrefs::LayersDump()) {
         printf_stderr("TextLayer %p using rect=%s, clip=%s\n",
                       this->GetLayer(),
                       Stringify(rect).c_str(),
                       Stringify(clip).c_str());
     }
 
     nsTArray<WebRenderCommand> commands;
-    mGlyphHelper.BuildWebRenderCommands(commands, mGlyphs, mFont,
+    mGlyphHelper.BuildWebRenderCommands(WrBridge(), commands, mGlyphs, mFont,
                                         GetOffsetToParent(), rect, clip);
     WrBridge()->AddWebRenderCommands(commands);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -458,16 +458,17 @@ private:
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram",  FPSPrintHistogram, bool, false);
   DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
   DECL_GFX_PREF(Once, "layers.acceleration.force-enabled",     LayersAccelerationForceEnabledDoNotUseDirectly, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.border-layers",         LayersAllowBorderLayers, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.text-layers",           LayersAllowTextLayers, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.bullet-layers",         LayersAllowBulletLayers, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.caret-layers",          LayersAllowCaretLayers, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.boxshadow-outer-layers", LayersAllowOuterBoxShadow, bool, false);
+  DECL_GFX_PREF(Live, "layers.advanced.boxshadow-inset-layers", LayersAllowInsetBoxShadow, bool, false);
   DECL_GFX_PREF(Live, "layers.advanced.outline-layers",        LayersAllowOutlineLayers, bool, false);
   DECL_GFX_PREF(Skip, "layers.allow-d3d9-fallback",            LayersAllowD3D9Fallback, bool, false);
   DECL_GFX_PREF(Once, "layers.amd-switchable-gfx.enabled",     LayersAMDSwitchableGfxEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled",         AsyncPanZoomEnabledDoNotUseDirectly, bool, true);
   DECL_GFX_PREF(Once, "layers.async-pan-zoom.separate-event-thread", AsyncPanZoomSeparateEventThread, bool, false);
   DECL_GFX_PREF(Live, "layers.bench.enabled",                  LayersBenchEnabled, bool, false);
   DECL_GFX_PREF(Once, "layers.bufferrotation.enabled",         BufferRotationEnabled, bool, true);
   DECL_GFX_PREF(Live, "layers.child-process-shutdown",         ChildProcessShutdown, bool, true);
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -22,16 +22,17 @@
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/gfx/Swizzle.h"
 #include "mozilla/layers/WebRenderMessages.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/Vector.h"
 #include "mozilla/webrender/WebRenderTypes.h"
+#include "mozilla/layers/WebRenderBridgeChild.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIClipboardHelper.h"
 #include "nsIFile.h"
 #include "nsIGfxInfo.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRegion.h"
 #include "nsServiceManagerUtils.h"
@@ -1453,31 +1454,38 @@ WriteFontFileData(const uint8_t* aData, 
 
   helper->mFontData = fontData;
   helper->mFontDataLength = aLength;
   helper->mIndex = aIndex;
   helper->mGlyphSize = aGlyphSize;
 }
 
 void
-WebRenderGlyphHelper::BuildWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+WebRenderGlyphHelper::BuildWebRenderCommands(WebRenderBridgeChild* aBridge,
+                                             nsTArray<WebRenderCommand>& aCommands,
                                              const nsTArray<GlyphArray>& aGlyphs,
                                              ScaledFont* aFont,
                                              const Point& aOffset,
                                              const Rect& aBounds,
                                              const Rect& aClip)
 {
   MOZ_ASSERT(aFont);
   MOZ_ASSERT(!aGlyphs.IsEmpty());
   MOZ_ASSERT((aFont->GetType() == gfx::FontType::DWRITE) ||
               (aFont->GetType() == gfx::FontType::MAC));
 
   aFont->GetFontFileData(&WriteFontFileData, this);
   wr::ByteBuffer fontBuffer(mFontDataLength, mFontData);
 
+  WrFontKey key;
+  key.mNamespace = aBridge->GetNamespace();
+  key.mHandle = aBridge->GetNextResourceId();
+
+  aBridge->SendAddRawFont(key, fontBuffer, mIndex);
+
   nsTArray<WrGlyphArray> wr_glyphs;
   wr_glyphs.SetLength(aGlyphs.Length());
 
   for (size_t i = 0; i < aGlyphs.Length(); i++) {
     GlyphArray glyph_array = aGlyphs[i];
     nsTArray<gfx::Glyph>& glyphs = glyph_array.glyphs();
 
     nsTArray<WrGlyphInstance>& wr_glyph_instances = wr_glyphs[i].glyphs;
@@ -1490,16 +1498,14 @@ WebRenderGlyphHelper::BuildWebRenderComm
       wr_glyph_instances[j].y = glyphs[j].mPosition.y - aOffset.y;
     }
   }
 
   aCommands.AppendElement(OpDPPushText(
                             wr::ToWrRect(aBounds),
                             wr::ToWrRect(aClip),
                             wr_glyphs,
-                            mIndex,
                             mGlyphSize,
-                            fontBuffer,
-                            mFontDataLength));
+                            key));
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -12,25 +12,27 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "nsColor.h"
 #include "nsPrintfCString.h"
 #include "nsRegionFwd.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/CheckedInt.h"
+#include "mozilla/webrender/webrender_ffi.h"
 
 class gfxASurface;
 class gfxDrawable;
 class nsIInputStream;
 class nsIGfxInfo;
 class nsIPresShell;
 
 namespace mozilla {
 namespace layers {
+class WebRenderBridgeChild;
 class GlyphArray;
 struct PlanarYCbCrData;
 class WebRenderCommand;
 } // namespace layers
 namespace image {
 class ImageRegion;
 } // namespace image
 } // namespace mozilla
@@ -320,17 +322,18 @@ public:
 
   ~WebRenderGlyphHelper()
   {
     if (mFontData) {
       free(mFontData);
     }
   }
 
-  void BuildWebRenderCommands(nsTArray<layers::WebRenderCommand>& aCommands,
+  void BuildWebRenderCommands(layers::WebRenderBridgeChild* aChild,
+                              nsTArray<layers::WebRenderCommand>& aCommands,
                               const nsTArray<layers::GlyphArray>& aGlyphs,
                               ScaledFont* aFont,
                               const Point& aOffset,
                               const Rect& aBounds,
                               const Rect& aClip);
 
 public:
   uint8_t* mFontData;
--- a/gfx/webrender/src/device.rs
+++ b/gfx/webrender/src/device.rs
@@ -1626,17 +1626,22 @@ impl Device {
             ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
         };
 
         let row_length = match stride {
             Some(value) => value / bpp,
             None => width,
         };
 
-        assert!(data.len() as u32 == bpp * row_length * height);
+        // Take the stride into account for all rows, except the last one.
+        let len = bpp * row_length * (height - 1)
+                + width * bpp;
+
+        assert!(data.len() as u32 >= len);
+        let data = &data[0..len as usize];
 
         if let Some(..) = stride {
             gl::pixel_store_i(gl::UNPACK_ROW_LENGTH, row_length as gl::GLint);
         }
 
         self.bind_texture(DEFAULT_TEXTURE, texture_id);
         self.update_image_for_2d_texture(texture_id.target,
                                          x0 as gl::GLint,
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -4,36 +4,38 @@
 
 use app_units::Au;
 use fnv::FnvHasher;
 use internal_types::{ANGLE_FLOAT_TO_FIXED, AxisDirection};
 use internal_types::{LowLevelFilterOp};
 use internal_types::{RendererFrame};
 use frame_builder::{FrameBuilder, FrameBuilderConfig};
 use clip_scroll_node::ClipScrollNode;
+use clip_scroll_tree::{ClipScrollTree, ScrollStates};
+use profiler::TextureCacheProfileCounters;
 use resource_cache::ResourceCache;
 use scene::{Scene, SceneProperties};
-use clip_scroll_tree::{ClipScrollTree, ScrollStates};
 use std::collections::HashMap;
 use std::hash::BuildHasherDefault;
 use tiling::{AuxiliaryListsMap, CompositeOps, PrimitiveFlags};
 use webrender_traits::{AuxiliaryLists, ClipRegion, ColorF, DisplayItem, Epoch, FilterOp};
-use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform};
+use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, LayoutTransform, TileOffset};
 use webrender_traits::{MixBlendMode, PipelineId, ScrollEventPhase, ScrollLayerId, ScrollLayerState};
 use webrender_traits::{ScrollLocation, ScrollPolicy, ServoScrollRootId, SpecificDisplayItem};
-use webrender_traits::{StackingContext, WorldPoint};
+use webrender_traits::{StackingContext, WorldPoint, ImageDisplayItem, DeviceUintSize};
 
 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
 pub struct FrameId(pub u32);
 
 static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, a: 0.6 };
 
 struct FlattenContext<'a> {
     scene: &'a Scene,
     builder: &'a mut FrameBuilder,
+    resource_cache: &'a mut ResourceCache,
 }
 
 // TODO: doc
 pub struct Frame {
     pub clip_scroll_tree: ClipScrollTree,
     pub pipeline_epoch_map: HashMap<PipelineId, Epoch, BuildHasherDefault<FnvHasher>>,
     pub pipeline_auxiliary_lists: AuxiliaryListsMap,
     id: FrameId,
@@ -221,17 +223,17 @@ impl Frame {
     pub fn tick_scrolling_bounce_animations(&mut self) {
         self.clip_scroll_tree.tick_scrolling_bounce_animations();
     }
 
     pub fn discard_frame_state_for_pipeline(&mut self, pipeline_id: PipelineId) {
         self.clip_scroll_tree.discard_frame_state_for_pipeline(pipeline_id);
     }
 
-    pub fn create(&mut self, scene: &Scene) {
+    pub fn create(&mut self, scene: &Scene, resource_cache: &mut ResourceCache) {
         let root_pipeline_id = match scene.root_pipeline_id {
             Some(root_pipeline_id) => root_pipeline_id,
             None => return,
         };
 
         let root_pipeline = match scene.pipeline_map.get(&root_pipeline_id) {
             Some(root_pipeline) => root_pipeline,
             None => return,
@@ -271,16 +273,17 @@ impl Frame {
         let mut frame_builder = FrameBuilder::new(root_pipeline.viewport_size,
                                                   background_color,
                                                   self.frame_builder_config);
 
         {
             let mut context = FlattenContext {
                 scene: scene,
                 builder: &mut frame_builder,
+                resource_cache: resource_cache
             };
 
             let mut traversal = DisplayListTraversal::new_skipping_first(display_list);
             let reference_frame_id = self.clip_scroll_tree.root_reference_frame_id();
             let topmost_scroll_layer_id = self.clip_scroll_tree.topmost_scroll_layer_id();
             debug_assert!(reference_frame_id != topmost_scroll_layer_id);
 
             let viewport_rect = LayerRect::new(LayerPoint::zero(), root_pipeline.viewport_size);
@@ -542,23 +545,32 @@ impl Frame {
                          level: i32) {
         while let Some(item) = traversal.next() {
             match item.item {
                 SpecificDisplayItem::WebGL(ref info) => {
                     context.builder.add_webgl_rectangle(item.rect,
                                                         &item.clip, info.context_id);
                 }
                 SpecificDisplayItem::Image(ref info) => {
-                    context.builder.add_image(item.rect,
-                                              &item.clip,
-                                              &info.stretch_size,
-                                              &info.tile_spacing,
-                                              None,
-                                              info.image_key,
-                                              info.image_rendering);
+                    let image = context.resource_cache.get_image_properties(info.image_key);
+                    if let Some(tile_size) = image.tiling {
+                        // The image resource is tiled. We have to generate an image primitive
+                        // for each tile.
+                        let image_size = DeviceUintSize::new(image.descriptor.width, image.descriptor.height);
+                        self.decompose_tiled_image(context, &item, info, image_size, tile_size as u32);
+                    } else {
+                        context.builder.add_image(item.rect,
+                                                  &item.clip,
+                                                  &info.stretch_size,
+                                                  &info.tile_spacing,
+                                                  None,
+                                                  info.image_key,
+                                                  info.image_rendering,
+                                                  None);
+                    }
                 }
                 SpecificDisplayItem::YuvImage(ref info) => {
                     context.builder.add_yuv_image(item.rect,
                                                   &item.clip,
                                                   info.y_image_key,
                                                   info.u_image_key,
                                                   info.v_image_key,
                                                   info.color_space);
@@ -641,39 +653,230 @@ impl Frame {
                                         layer_relative_transform);
                 }
                 SpecificDisplayItem::PopStackingContext |
                 SpecificDisplayItem::PopScrollLayer => return,
             }
         }
     }
 
+    fn decompose_tiled_image(&mut self,
+                             context: &mut FlattenContext,
+                             item: &DisplayItem,
+                             info: &ImageDisplayItem,
+                             image_size: DeviceUintSize,
+                             tile_size: u32) {
+        // The image resource is tiled. We have to generate an image primitive
+        // for each tile.
+        // We need to do this because the image is broken up into smaller tiles in the texture
+        // cache and the image shader is not able to work with this type of sparse representation.
+
+        // The tiling logic works as follows:
+        //
+        //  ###################-+  -+
+        //  #    |    |    |//# |   | image size
+        //  #    |    |    |//# |   |
+        //  #----+----+----+--#-+   |  -+ 
+        //  #    |    |    |//# |   |   | regular tile size
+        //  #    |    |    |//# |   |   |
+        //  #----+----+----+--#-+   |  -+-+
+        //  #////|////|////|//# |   |     | "leftover" height
+        //  ################### |  -+  ---+
+        //  #----+----+----+----+
+        //
+        // In the ascii diagram above, a large image is plit into tiles of almost regular size.
+        // The tiles on the right and bottom edges (hatched in the diagram) are smaller than
+        // the regular tiles and are handled separately in the code see leftover_width/height.
+        // each generated image primitive corresponds to a tile in the texture cache, with the
+        // assumption that the smaller tiles with leftover sizes are sized to fit their own
+        // irregular size in the texture cache.
+
+        // TODO(nical) supporting tiled repeated images isn't implemented yet.
+        // One way to implement this is to have another level of decomposition on top of this one,
+        // and generate a set of image primitive per repetition just like we have a primitive
+        // per tile here.
+        //
+        // For the case where we don't tile along an axis, we can still perform the repetition in
+        // the shader (for this particular axis), and it is worth special-casing for this to avoid
+        // generating many primitives.
+        // This can happen with very tall and thin images used as a repeating background.
+        // Apparently web authors do that...
+
+        let mut stretch_size = info.stretch_size;
+
+        let mut repeat_x = false;
+        let mut repeat_y = false;
+
+        if stretch_size.width < item.rect.size.width {
+            if image_size.width < tile_size {
+                // we don't actually tile in this dimmension so repeating can be done in the shader.
+                repeat_x = true;
+            } else {
+                println!("Unimplemented! repeating a tiled image (x axis)");
+                stretch_size.width = item.rect.size.width;
+            }
+        }
+
+        if stretch_size.height < item.rect.size.height {
+                // we don't actually tile in this dimmension so repeating can be done in the shader.
+            if image_size.height < tile_size {
+                repeat_y = true;
+            } else {
+                println!("Unimplemented! repeating a tiled image (y axis)");
+                stretch_size.height = item.rect.size.height;
+            }
+        }
+
+        let tile_size_f32 = tile_size as f32;
+
+        // Note: this rounds down so it excludes the partially filled tiles on the right and
+        // bottom edges (we handle them separately below).
+        let num_tiles_x = (image_size.width / tile_size) as u16;
+        let num_tiles_y = (image_size.height / tile_size) as u16;
+
+        // Ratio between (image space) tile size and image size.
+        let img_dw = tile_size_f32 / (image_size.width as f32);
+        let img_dh = tile_size_f32 / (image_size.height as f32);
+
+        // Strected size of the tile in layout space.
+        let stretched_tile_size = LayerSize::new(
+            img_dw * stretch_size.width,
+            img_dh * stretch_size.height
+        );
+
+        // The size in pixels of the tiles on the right and bottom edges, smaller
+        // than the regular tile size if the image is not a multiple of the tile size.
+        // Zero means the image size is a multiple of the tile size.
+        let leftover = DeviceUintSize::new(image_size.width % tile_size, image_size.height % tile_size);
+
+        for ty in 0..num_tiles_y {
+            for tx in 0..num_tiles_x {
+                self.add_tile_primitive(context, item, info,
+                                        TileOffset::new(tx, ty),
+                                        stretched_tile_size,
+                                        1.0, 1.0,
+                                        repeat_x, repeat_y);
+            }
+            if leftover.width != 0 {
+                // Tiles on the right edge that are smaller than the tile size.
+                self.add_tile_primitive(context, item, info,
+                                        TileOffset::new(num_tiles_x, ty),
+                                        stretched_tile_size,
+                                        (leftover.width as f32) / tile_size_f32,
+                                        1.0,
+                                        repeat_x, repeat_y);
+            }
+        }
+
+        if leftover.height != 0 {
+            for tx in 0..num_tiles_x {
+                // Tiles on the bottom edge that are smaller than the tile size.
+                self.add_tile_primitive(context, item, info,
+                                        TileOffset::new(tx, num_tiles_y),
+                                        stretched_tile_size,
+                                        1.0,
+                                        (leftover.height as f32) / tile_size_f32,
+                                        repeat_x, repeat_y);
+            }
+
+            if leftover.width != 0 {
+                // Finally, the bottom-right tile with a "leftover" size.
+                self.add_tile_primitive(context, item, info,
+                                        TileOffset::new(num_tiles_x, num_tiles_y),
+                                        stretched_tile_size,
+                                        (leftover.width as f32) / tile_size_f32,
+                                        (leftover.height as f32) / tile_size_f32,
+                                        repeat_x, repeat_y);
+            }
+        }
+    }
+
+    fn add_tile_primitive(&mut self,
+                          context: &mut FlattenContext,
+                          item: &DisplayItem,
+                          info: &ImageDisplayItem,
+                          tile_offset: TileOffset,
+                          stretched_tile_size: LayerSize,
+                          tile_ratio_width: f32,
+                          tile_ratio_height: f32,
+                          repeat_x: bool,
+                          repeat_y: bool) {
+        // If the the image is tiled along a given axis, we can't have the shader compute
+        // the image repetition pattern. In this case we base the primitive's rectangle size
+        // on the stretched tile size which effectively cancels the repetion (and repetition
+        // has to be emulated by generating more primitives).
+        // If the image is not tiling along this axis, we can perform the repetition in the
+        // shader. in this case we use the item's size in the primitive (on that particular
+        // axis).
+        // See the repeat_x/y code below.
+
+        let stretched_size = LayerSize::new(
+            stretched_tile_size.width * tile_ratio_width,
+            stretched_tile_size.height * tile_ratio_height,
+        );
+
+        let mut prim_rect = LayerRect::new(
+            item.rect.origin + LayerPoint::new(
+                tile_offset.x as f32 * stretched_tile_size.width,
+                tile_offset.y as f32 * stretched_tile_size.height,
+            ),
+            stretched_size,
+        );
+
+        if repeat_x {
+            assert_eq!(tile_offset.x, 0);
+            prim_rect.size.width = item.rect.size.width;
+        }
+
+        if repeat_y {
+            assert_eq!(tile_offset.y, 0);
+            prim_rect.size.height = item.rect.size.height;
+        }
+
+        // Fix up the primitive's rect if it overflows the original item rect.
+        if let Some(prim_rect) = prim_rect.intersection(&item.rect) {
+            context.builder.add_image(prim_rect,
+                                      &item.clip,
+                                      &stretched_size,
+                                      &info.tile_spacing,
+                                      None,
+                                      info.image_key,
+                                      info.image_rendering,
+                                      Some(tile_offset));
+        }
+    }
+
     pub fn build(&mut self,
                  resource_cache: &mut ResourceCache,
                  auxiliary_lists_map: &AuxiliaryListsMap,
-                 device_pixel_ratio: f32)
+                 device_pixel_ratio: f32,
+                 texture_cache_profile: &mut TextureCacheProfileCounters)
                  -> RendererFrame {
         self.clip_scroll_tree.update_all_node_transforms();
         let frame = self.build_frame(resource_cache,
                                      auxiliary_lists_map,
-                                     device_pixel_ratio);
+                                     device_pixel_ratio,
+                                     texture_cache_profile);
         resource_cache.expire_old_resources(self.id);
         frame
     }
 
     fn build_frame(&mut self,
                    resource_cache: &mut ResourceCache,
                    auxiliary_lists_map: &AuxiliaryListsMap,
-                   device_pixel_ratio: f32) -> RendererFrame {
+                   device_pixel_ratio: f32,
+                   texture_cache_profile: &mut TextureCacheProfileCounters)
+                   -> RendererFrame {
         let mut frame_builder = self.frame_builder.take();
         let frame = frame_builder.as_mut().map(|builder|
             builder.build(resource_cache,
                           self.id,
                           &self.clip_scroll_tree,
                           auxiliary_lists_map,
-                          device_pixel_ratio)
+                          device_pixel_ratio,
+                          texture_cache_profile)
         );
         self.frame_builder = frame_builder;
 
         let nodes_bouncing_back = self.clip_scroll_tree.collect_nodes_bouncing_back();
         RendererFrame::new(self.pipeline_epoch_map.clone(), nodes_bouncing_back, frame)
     }
 }
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -9,31 +9,31 @@ use gpu_store::GpuStoreAddress;
 use internal_types::{HardwareCompositeOp, SourceTexture};
 use mask_cache::{ClipSource, MaskCacheInfo};
 use prim_store::{BorderPrimitiveCpu, BorderPrimitiveGpu, BoxShadowPrimitiveGpu};
 use prim_store::{GradientPrimitiveCpu, GradientPrimitiveGpu, ImagePrimitiveCpu, ImagePrimitiveGpu};
 use prim_store::{ImagePrimitiveKind, PrimitiveContainer, PrimitiveGeometry, PrimitiveIndex};
 use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu, RadialGradientPrimitiveGpu};
 use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu, TextRunPrimitiveGpu};
 use prim_store::{TexelRect, YuvImagePrimitiveCpu, YuvImagePrimitiveGpu};
-use profiler::FrameProfileCounters;
+use profiler::{FrameProfileCounters, TextureCacheProfileCounters};
 use render_task::{AlphaRenderItem, MaskCacheKey, MaskResult, RenderTask, RenderTaskIndex};
 use render_task::RenderTaskLocation;
 use resource_cache::ResourceCache;
 use clip_scroll_tree::ClipScrollTree;
 use std::{cmp, f32, i32, mem, usize};
 use tiling::{AuxiliaryListsMap, ClipScrollGroup, ClipScrollGroupIndex, CompositeOps, Frame};
 use tiling::{PackedLayer, PackedLayerIndex, PrimitiveFlags, PrimitiveRunCmd, RenderPass};
 use tiling::{RenderTargetContext, RenderTaskCollection, ScrollbarPrimitive, ScrollLayer};
 use tiling::{ScrollLayerIndex, StackingContext, StackingContextIndex};
 use util::{self, pack_as_float, rect_from_points_f, subtract_rect, TransformedRect};
 use util::{RectHelpers, TransformedRectKind};
 use webrender_traits::{as_scroll_parent_rect, BorderDetails, BorderDisplayItem, BorderSide, BorderStyle};
 use webrender_traits::{BoxShadowClipMode, ClipRegion, ColorF, device_length, DeviceIntPoint};
-use webrender_traits::{DeviceIntRect, DeviceIntSize, DeviceUintSize, ExtendMode, FontKey};
+use webrender_traits::{DeviceIntRect, DeviceIntSize, DeviceUintSize, ExtendMode, FontKey, TileOffset};
 use webrender_traits::{FontRenderMode, GlyphOptions, ImageKey, ImageRendering, ItemRange};
 use webrender_traits::{LayerPoint, LayerRect, LayerSize, LayerToScrollTransform, PipelineId};
 use webrender_traits::{RepeatMode, ScrollLayerId, ScrollLayerPixel, WebGLContextId, YuvColorSpace};
 
 #[derive(Debug, Clone)]
 struct ImageBorderSegment {
     geom_rect: LayerRect,
     sub_rect: TexelRect,
@@ -412,17 +412,18 @@ impl FrameBuilder {
 
                 for segment in segments {
                     self.add_image(segment.geom_rect,
                                    clip_region,
                                    &segment.stretch_size,
                                    &segment.tile_spacing,
                                    Some(segment.sub_rect),
                                    border.image_key,
-                                   ImageRendering::Auto);
+                                   ImageRendering::Auto,
+                                   None);
                 }
             }
             BorderDetails::Normal(ref border) => {
                 let radius = &border.radius;
                 let left = &border.left;
                 let right = &border.right;
                 let top = &border.top;
                 let bottom = &border.bottom;
@@ -710,18 +711,23 @@ impl FrameBuilder {
                                      color,
                                      PrimitiveFlags::None);
             return;
         }
 
         // The local space box shadow rect. It is the element rect
         // translated by the box shadow offset and inflated by the
         // box shadow spread.
+        let inflate_amount = match clip_mode {
+            BoxShadowClipMode::Outset | BoxShadowClipMode::None => spread_radius,
+            BoxShadowClipMode::Inset => -spread_radius,
+        };
+
         let bs_rect = box_bounds.translate(box_offset)
-                                .inflate(spread_radius, spread_radius);
+                                .inflate(inflate_amount, inflate_amount);
 
         // Get the outer rectangle, based on the blur radius.
         let outside_edge_size = 2.0 * blur_radius;
         let inside_edge_size = outside_edge_size.max(border_radius);
         let edge_size = outside_edge_size + inside_edge_size;
         let outer_rect = bs_rect.inflate(outside_edge_size, outside_edge_size);
 
         // Box shadows are often used for things like text underline and other
@@ -828,20 +834,22 @@ impl FrameBuilder {
 
     pub fn add_image(&mut self,
                      rect: LayerRect,
                      clip_region: &ClipRegion,
                      stretch_size: &LayerSize,
                      tile_spacing: &LayerSize,
                      sub_rect: Option<TexelRect>,
                      image_key: ImageKey,
-                     image_rendering: ImageRendering) {
+                     image_rendering: ImageRendering,
+                     tile: Option<TileOffset>) {
         let prim_cpu = ImagePrimitiveCpu {
             kind: ImagePrimitiveKind::Image(image_key,
                                             image_rendering,
+                                            tile,
                                             *tile_spacing),
             color_texture_id: SourceTexture::Invalid,
             resource_address: GpuStoreAddress(0),
             sub_rect: sub_rect,
         };
 
         let prim_gpu = ImagePrimitiveGpu {
             stretch_size: *stretch_size,
@@ -1079,17 +1087,19 @@ impl FrameBuilder {
         (current_task, next_task_index.0)
     }
 
     pub fn build(&mut self,
                  resource_cache: &mut ResourceCache,
                  frame_id: FrameId,
                  clip_scroll_tree: &ClipScrollTree,
                  auxiliary_lists_map: &AuxiliaryListsMap,
-                 device_pixel_ratio: f32) -> Frame {
+                 device_pixel_ratio: f32,
+                 texture_cache_profile: &mut TextureCacheProfileCounters)
+                 -> Frame {
         profile_scope!("build");
 
         let mut profile_counters = FrameProfileCounters::new();
         profile_counters.total_primitives.set(self.prim_store.prim_count());
 
         resource_cache.begin_frame(frame_id);
 
         let screen_rect = DeviceIntRect::new(
@@ -1116,17 +1126,17 @@ impl FrameBuilder {
                                                       device_pixel_ratio);
 
         let (main_render_task, static_render_task_count) = self.build_render_task();
         let mut render_tasks = RenderTaskCollection::new(static_render_task_count);
 
         let mut required_pass_count = 0;
         main_render_task.max_depth(0, &mut required_pass_count);
 
-        resource_cache.block_until_all_resources_added();
+        resource_cache.block_until_all_resources_added(texture_cache_profile);
 
         for scroll_layer in self.scroll_layer_store.iter() {
             if let Some(ref clip_info) = scroll_layer.clip_cache_info {
                 self.prim_store.resolve_clip_cache(clip_info, resource_cache);
             }
         }
 
         let deferred_resolves = self.prim_store.resolve_primitives(resource_cache,
@@ -1356,17 +1366,17 @@ impl<'a> LayerRectCalculationAndCullingP
         clip_info.update(&scroll_layer.clip_source,
                          &packed_layer.transform,
                          &mut self.frame_builder.prim_store.gpu_data32,
                          self.device_pixel_ratio,
                          auxiliary_lists);
 
         if let Some(mask) = scroll_layer.clip_source.image_mask() {
             // We don't add the image mask for resolution, because layer masks are resolved later.
-            self.resource_cache.request_image(mask.image, ImageRendering::Auto);
+            self.resource_cache.request_image(mask.image, ImageRendering::Auto, None);
         }
     }
 
     fn handle_push_stacking_context(&mut self, stacking_context_index: StackingContextIndex) {
         self.stacking_context_stack.push(stacking_context_index);
 
         // Reset bounding rect to zero. We will calculate it as we collect primitives
         // from various scroll layers. In handle_pop_stacking_context , we use this to
--- a/gfx/webrender/src/freelist.rs
+++ b/gfx/webrender/src/freelist.rs
@@ -10,41 +10,63 @@ pub struct FreeListItemId(u32);
 impl FreeListItemId {
     #[inline]
     pub fn new(value: u32) -> FreeListItemId {
         FreeListItemId(value)
     }
 
     #[inline]
     pub fn value(&self) -> u32 {
-        let FreeListItemId(value) = *self;
-        value
+        self.0
     }
 }
 
 pub trait FreeListItem {
+    fn take(&mut self) -> Self;
     fn next_free_id(&self) -> Option<FreeListItemId>;
     fn set_next_free_id(&mut self, id: Option<FreeListItemId>);
 }
 
+struct FreeListIter<'a, T: 'a> {
+    items: &'a [T],
+    cur_index: Option<FreeListItemId>,
+}
+
+impl<'a, T: FreeListItem> Iterator for FreeListIter<'a, T> {
+    type Item = FreeListItemId;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.cur_index.map(|free_id| {
+            self.cur_index = self.items[free_id.0 as usize].next_free_id();
+            free_id
+        })
+    }
+}
+
 pub struct FreeList<T> {
     items: Vec<T>,
     first_free_index: Option<FreeListItemId>,
     alloc_count: usize,
 }
 
 impl<T: FreeListItem> FreeList<T> {
     pub fn new() -> FreeList<T> {
         FreeList {
             items: Vec::new(),
             first_free_index: None,
             alloc_count: 0,
         }
     }
 
+    fn free_iter(&self) -> FreeListIter<T> {
+        FreeListIter {
+            items: &self.items,
+            cur_index: self.first_free_index,
+        }
+    }
+
     pub fn insert(&mut self, item: T) -> FreeListItemId {
         self.alloc_count += 1;
         match self.first_free_index {
             Some(free_index) => {
                 let FreeListItemId(index) = free_index;
                 let free_item = &mut self.items[index as usize];
                 self.first_free_index = free_item.next_free_id();
                 *free_item = item;
@@ -53,69 +75,49 @@ impl<T: FreeListItem> FreeList<T> {
             None => {
                 let item_id = FreeListItemId(self.items.len() as u32);
                 self.items.push(item);
                 item_id
             }
         }
     }
 
-    #[allow(dead_code)]
-    fn assert_not_in_free_list(&self, id: FreeListItemId) {
-        let FreeListItemId(id) = id;
-        let mut next_free_id = self.first_free_index;
-
-        while let Some(free_id) = next_free_id {
-            let FreeListItemId(index) = free_id;
-            assert!(index != id);
-            let free_item = &self.items[index as usize];
-            next_free_id = free_item.next_free_id();
-        }
-    }
-
     pub fn get(&self, id: FreeListItemId) -> &T {
-        //self.assert_not_in_free_list(id);
-
-        let FreeListItemId(index) = id;
-        &self.items[index as usize]
+        debug_assert_eq!(self.free_iter().find(|&fid| fid==id), None);
+        &self.items[id.0 as usize]
     }
 
     pub fn get_mut(&mut self, id: FreeListItemId) -> &mut T {
-        //self.assert_not_in_free_list(id);
-
-        let FreeListItemId(index) = id;
-        &mut self.items[index as usize]
+        debug_assert_eq!(self.free_iter().find(|&fid| fid==id), None);
+        &mut self.items[id.0 as usize]
     }
 
     #[allow(dead_code)]
     pub fn len(&self) -> usize {
         self.alloc_count
     }
 
-    // TODO(gw): Actually free items from the texture cache!!
-    #[allow(dead_code)]
-    pub fn free(&mut self, id: FreeListItemId) {
+    pub fn free(&mut self, id: FreeListItemId) -> T {
         self.alloc_count -= 1;
         let FreeListItemId(index) = id;
         let item = &mut self.items[index as usize];
+        let data = item.take();
         item.set_next_free_id(self.first_free_index);
         self.first_free_index = Some(id);
+        data
     }
 
     pub fn for_each_item<F>(&mut self, f: F) where F: Fn(&mut T) {
-        let mut free_ids = HashSet::new();
-
-        let mut next_free_id = self.first_free_index;
-        while let Some(free_id) = next_free_id {
-            free_ids.insert(free_id);
-            let FreeListItemId(index) = free_id;
-            let free_item = &self.items[index as usize];
-            next_free_id = free_item.next_free_id();
-        }
+        //TODO: this could be done much faster. Instead of gathering the free
+        // indices into a set, we could re-order the free list to be ascending.
+        // That is an one-time operation with at most O(nf^2), where
+        //    nf = number of elements in the free list
+        // Then this code would just walk both `items` and the ascending free
+        // list, essentially skipping the free indices for free.
+        let free_ids: HashSet<_> = self.free_iter().collect();
 
         for (index, mut item) in self.items.iter_mut().enumerate() {
-            let id = FreeListItemId(index as u32);
-            if !free_ids.contains(&id) {
+            if !free_ids.contains(&FreeListItemId(index as u32)) {
                 f(&mut item);
             }
         }
     }
 }
--- a/gfx/webrender/src/internal_types.rs
+++ b/gfx/webrender/src/internal_types.rs
@@ -382,16 +382,17 @@ pub enum TextureUpdateOp {
     },
     Update {
         page_pos_x: u32,    // the texture page position which we want to upload
         page_pos_y: u32,
         width: u32,
         height: u32,
         data: Arc<Vec<u8>>,
         stride: Option<u32>,
+        offset: u32,
     },
     UpdateForExternalBuffer {
         rect: DeviceUintRect,
         id: ExternalImageId,
         stride: Option<u32>,
     },
     Grow {
         width: u32,
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -15,17 +15,17 @@ use std::usize;
 use util::TransformedRect;
 use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering, YuvColorSpace};
 use webrender_traits::{ClipRegion, ComplexClipRegion, ItemRange, GlyphKey};
 use webrender_traits::{FontKey, FontRenderMode, WebGLContextId};
 use webrender_traits::{device_length, DeviceIntRect, DeviceIntSize};
 use webrender_traits::{DeviceRect, DevicePoint, DeviceSize};
 use webrender_traits::{LayerRect, LayerSize, LayerPoint};
 use webrender_traits::{LayerToWorldTransform, GlyphInstance, GlyphOptions};
-use webrender_traits::{ExtendMode, GradientStop};
+use webrender_traits::{ExtendMode, GradientStop, TileOffset};
 
 pub const CLIP_DATA_GPU_SIZE: usize = 5;
 pub const MASK_DATA_GPU_SIZE: usize = 1;
 
 /// Stores two coordinates in texel space. The coordinates
 /// are stored in texel coordinates because the texture atlas
 /// may grow. Storing them as texel coords and normalizing
 /// the UVs in the vertex shader means nothing needs to be
@@ -131,17 +131,17 @@ pub struct PrimitiveMetadata {
 #[derive(Debug, Clone)]
 #[repr(C)]
 pub struct RectanglePrimitive {
     pub color: ColorF,
 }
 
 #[derive(Debug)]
 pub enum ImagePrimitiveKind {
-    Image(ImageKey, ImageRendering, LayerSize),
+    Image(ImageKey, ImageRendering, Option<TileOffset>, LayerSize),
     WebGL(WebGLContextId),
 }
 
 #[derive(Debug)]
 pub struct ImagePrimitiveCpu {
     pub kind: ImagePrimitiveKind,
     pub color_texture_id: SourceTexture,
     pub resource_address: GpuStoreAddress,
@@ -833,17 +833,17 @@ impl PrimitiveStore {
 
         PrimitiveIndex(prim_index)
     }
 
     fn resolve_clip_cache_internal(gpu_data32: &mut VertexDataStore<GpuBlock32>,
                                    clip_info: &MaskCacheInfo,
                                    resource_cache: &ResourceCache) {
         if let Some((ref mask, gpu_address)) = clip_info.image {
-            let cache_item = resource_cache.get_cached_image(mask.image, ImageRendering::Auto);
+            let cache_item = resource_cache.get_cached_image(mask.image, ImageRendering::Auto, None);
             let mask_data = gpu_data32.get_slice_mut(gpu_address, MASK_DATA_GPU_SIZE);
             mask_data[0] = GpuBlock32::from(ImageMaskData {
                 uv_rect: DeviceRect::new(cache_item.uv0,
                                          DeviceSize::new(cache_item.uv1.x - cache_item.uv0.x,
                                                          cache_item.uv1.y - cache_item.uv0.y)),
                 local_rect: mask.rect,
             });
         }
@@ -894,17 +894,17 @@ impl PrimitiveStore {
                     });
 
                     text.color_texture_id = texture_id;
                 }
                 PrimitiveKind::Image => {
                     let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0];
 
                     let (texture_id, cache_item) = match image_cpu.kind {
-                        ImagePrimitiveKind::Image(image_key, image_rendering, _) => {
+                        ImagePrimitiveKind::Image(image_key, image_rendering, tile_offset, _) => {
                             // Check if an external image that needs to be resolved
                             // by the render thread.
                             let image_properties = resource_cache.get_image_properties(image_key);
 
                             match image_properties.external_id {
                                 Some(external_id) => {
                                     // This is an external texture - we will add it to
                                     // the deferred resolves list to be patched by
@@ -912,17 +912,17 @@ impl PrimitiveStore {
                                     deferred_resolves.push(DeferredResolve {
                                         resource_address: image_cpu.resource_address,
                                         image_properties: image_properties,
                                     });
 
                                     (SourceTexture::External(external_id), None)
                                 }
                                 None => {
-                                    let cache_item = resource_cache.get_cached_image(image_key, image_rendering);
+                                    let cache_item = resource_cache.get_cached_image(image_key, image_rendering, tile_offset);
                                     (cache_item.texture_id, Some(cache_item))
                                 }
                             }
                         }
                         ImagePrimitiveKind::WebGL(context_id) => {
                             let cache_item = resource_cache.get_webgl_texture(&context_id);
                             (cache_item.texture_id, Some(cache_item))
                         }
@@ -947,31 +947,31 @@ impl PrimitiveStore {
                 }
                 PrimitiveKind::YuvImage => {
                     let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
                     let image_gpu: &mut YuvImagePrimitiveGpu = unsafe {
                         mem::transmute(self.gpu_data64.get_mut(metadata.gpu_prim_index))
                     };
 
                     if image_cpu.y_texture_id == SourceTexture::Invalid {
-                        let y_cache_item = resource_cache.get_cached_image(image_cpu.y_key, ImageRendering::Auto);
+                        let y_cache_item = resource_cache.get_cached_image(image_cpu.y_key, ImageRendering::Auto, None);
                         image_cpu.y_texture_id = y_cache_item.texture_id;
                         image_gpu.y_uv0 = y_cache_item.uv0;
                         image_gpu.y_uv1 = y_cache_item.uv1;
                     }
 
                     if image_cpu.u_texture_id == SourceTexture::Invalid {
-                        let u_cache_item = resource_cache.get_cached_image(image_cpu.u_key, ImageRendering::Auto);
+                        let u_cache_item = resource_cache.get_cached_image(image_cpu.u_key, ImageRendering::Auto, None);
                         image_cpu.u_texture_id = u_cache_item.texture_id;
                         image_gpu.u_uv0 = u_cache_item.uv0;
                         image_gpu.u_uv1 = u_cache_item.uv1;
                     }
 
                     if image_cpu.v_texture_id == SourceTexture::Invalid {
-                        let v_cache_item = resource_cache.get_cached_image(image_cpu.v_key, ImageRendering::Auto);
+                        let v_cache_item = resource_cache.get_cached_image(image_cpu.v_key, ImageRendering::Auto, None);
                         image_cpu.v_texture_id = v_cache_item.texture_id;
                         image_gpu.v_uv0 = v_cache_item.uv0;
                         image_gpu.v_uv1 = v_cache_item.uv1;
                     }
                 }
             }
         }
 
@@ -1039,17 +1039,17 @@ impl PrimitiveStore {
 
         if let Some(ref mut clip_info) = metadata.clip_cache_info {
             clip_info.update(&metadata.clip_source,
                              layer_transform,
                              &mut self.gpu_data32,
                              device_pixel_ratio,
                              auxiliary_lists);
             if let &ClipSource::Region(ClipRegion{ image_mask: Some(ref mask), .. }) = metadata.clip_source.as_ref() {
-                resource_cache.request_image(mask.image, ImageRendering::Auto);
+                resource_cache.request_image(mask.image, ImageRendering::Auto, None);
                 prim_needs_resolve = true;
             }
         }
 
         match metadata.prim_kind {
             PrimitiveKind::Rectangle |
             PrimitiveKind::Border  => {}
             PrimitiveKind::BoxShadow => {
@@ -1164,18 +1164,18 @@ impl PrimitiveStore {
                                               text.render_mode,
                                               text.glyph_options);
             }
             PrimitiveKind::Image => {
                 let image_cpu = &mut self.cpu_images[metadata.cpu_prim_index.0];
 
                 prim_needs_resolve = true;
                 match image_cpu.kind {
-                    ImagePrimitiveKind::Image(image_key, image_rendering, tile_spacing) => {
-                        resource_cache.request_image(image_key, image_rendering);
+                    ImagePrimitiveKind::Image(image_key, image_rendering, tile_offset, tile_spacing) => {
+                        resource_cache.request_image(image_key, image_rendering, tile_offset);
 
                         // TODO(gw): This doesn't actually need to be calculated each frame.
                         // It's cheap enough that it's not worth introducing a cache for images
                         // right now, but if we introduce a cache for images for some other
                         // reason then we might as well cache this with it.
                         let image_properties = resource_cache.get_image_properties(image_key);
                         metadata.is_opaque = image_properties.descriptor.is_opaque &&
                                              tile_spacing.width == 0.0 &&
@@ -1183,19 +1183,19 @@ impl PrimitiveStore {
                     }
                     ImagePrimitiveKind::WebGL(..) => {}
                 }
             }
             PrimitiveKind::YuvImage => {
                 let image_cpu = &mut self.cpu_yuv_images[metadata.cpu_prim_index.0];
                 prim_needs_resolve = true;
 
-                resource_cache.request_image(image_cpu.y_key, ImageRendering::Auto);
-                resource_cache.request_image(image_cpu.u_key, ImageRendering::Auto);
-                resource_cache.request_image(image_cpu.v_key, ImageRendering::Auto);
+                resource_cache.request_image(image_cpu.y_key, ImageRendering::Auto, None);
+                resource_cache.request_image(image_cpu.u_key, ImageRendering::Auto, None);
+                resource_cache.request_image(image_cpu.v_key, ImageRendering::Auto, None);
 
                 // TODO(nical): Currently assuming no tile_spacing for yuv images.
                 metadata.is_opaque = true;
             }
             PrimitiveKind::AlignedGradient => {
                 let gradient = &mut self.cpu_gradients[metadata.cpu_prim_index.0];
                 if gradient.cache_dirty {
                     let src_stops = auxiliary_lists.gradient_stops(&gradient.stops_range);
--- a/gfx/webrender/src/profiler.rs
+++ b/gfx/webrender/src/profiler.rs
@@ -252,28 +252,47 @@ impl FrameProfileCounters {
             visible_primitives: IntProfileCounter::new("Visible Primitives"),
             passes: IntProfileCounter::new("Passes"),
             targets: IntProfileCounter::new("Render Targets"),
         }
     }
 }
 
 #[derive(Clone)]
+pub struct TextureCacheProfileCounters {
+    pub pages_a8: ResourceProfileCounter,
+    pub pages_rgb8: ResourceProfileCounter,
+    pub pages_rgba8: ResourceProfileCounter,
+}
+
+impl TextureCacheProfileCounters {
+    pub fn new() -> TextureCacheProfileCounters {
+        TextureCacheProfileCounters {
+            pages_a8: ResourceProfileCounter::new("Texture A8 cached pages"),
+            pages_rgb8: ResourceProfileCounter::new("Texture RGB8 cached pages"),
+            pages_rgba8: ResourceProfileCounter::new("Texture RGBA8 cached pages"),
+        }
+    }
+}
+
+#[derive(Clone)]
 pub struct BackendProfileCounters {
     pub font_templates: ResourceProfileCounter,
     pub image_templates: ResourceProfileCounter,
     pub total_time: TimeProfileCounter,
+    pub texture_cache: TextureCacheProfileCounters,
 }
 
 impl BackendProfileCounters {
     pub fn new() -> BackendProfileCounters {
         BackendProfileCounters {
             font_templates: ResourceProfileCounter::new("Font Templates"),
             image_templates: ResourceProfileCounter::new("Image Templates"),
             total_time: TimeProfileCounter::new("Backend CPU Time", false),
+            texture_cache: TextureCacheProfileCounters::new(),
         }
     }
 
     pub fn reset(&mut self) {
         self.total_time.reset();
     }
 }
 
@@ -637,16 +656,22 @@ impl Profiler {
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &backend_profile.font_templates,
             &backend_profile.image_templates,
         ], debug_renderer, true);
 
         self.draw_counters(&[
+            &backend_profile.texture_cache.pages_a8,
+            &backend_profile.texture_cache.pages_rgb8,
+            &backend_profile.texture_cache.pages_rgba8,
+        ], debug_renderer, true);
+
+        self.draw_counters(&[
             &renderer_profile.draw_calls,
             &renderer_profile.vertices,
         ], debug_renderer, true);
 
         self.draw_counters(&[
             &backend_profile.total_time,
             &renderer_timers.cpu_time,
             &renderer_timers.gpu_time,
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 use byteorder::{LittleEndian, ReadBytesExt};
 use frame::Frame;
 use frame_builder::FrameBuilderConfig;
 use internal_types::{FontTemplate, GLContextHandleWrapper, GLContextWrapper};
 use internal_types::{SourceTexture, ResultMsg, RendererFrame};
-use profiler::BackendProfileCounters;
+use profiler::{BackendProfileCounters, TextureCacheProfileCounters};
 use record::ApiRecordingReceiver;
 use resource_cache::ResourceCache;
 use scene::Scene;
 use std::collections::HashMap;
 use std::io::{Cursor, Read};
 use std::sync::{Arc, Mutex};
 use std::sync::mpsc::Sender;
 use texture_cache::TextureCache;
@@ -91,18 +91,17 @@ impl RenderBackend {
             current_bound_webgl_context_id: None,
             recorder: recorder,
             main_thread_dispatcher: main_thread_dispatcher,
             next_webgl_id: 0,
             vr_compositor_handler: vr_compositor_handler
         }
     }
 
-    pub fn run(&mut self) {
-        let mut profile_counters = BackendProfileCounters::new();
+    pub fn run(&mut self, mut profile_counters: BackendProfileCounters) {
         let mut frame_counter: u32 = 0;
 
         loop {
             let msg = self.api_rx.recv();
             profile_scope!("handle_msg");
             match msg {
                 Ok(msg) => {
                     if let Some(ref mut r) = self.recorder {
@@ -121,21 +120,21 @@ impl RenderBackend {
                         ApiMsg::GetGlyphDimensions(glyph_keys, tx) => {
                             let mut glyph_dimensions = Vec::with_capacity(glyph_keys.len());
                             for glyph_key in &glyph_keys {
                                 let glyph_dim = self.resource_cache.get_glyph_dimensions(glyph_key);
                                 glyph_dimensions.push(glyph_dim);
                             };
                             tx.send(glyph_dimensions).unwrap();
                         }
-                        ApiMsg::AddImage(id, descriptor, data) => {
+                        ApiMsg::AddImage(id, descriptor, data, tiling) => {
                             if let ImageData::Raw(ref bytes) = data {
                                 profile_counters.image_templates.inc(bytes.len());
                             }
-                            self.resource_cache.add_image_template(id, descriptor, data);
+                            self.resource_cache.add_image_template(id, descriptor, data, tiling);
                         }
                         ApiMsg::UpdateImage(id, descriptor, bytes) => {
                             self.resource_cache.update_image_template(id, descriptor, bytes);
                         }
                         ApiMsg::DeleteImage(id) => {
                             self.resource_cache.delete_image_template(id);
                         }
                         ApiMsg::CloneApi(sender) => {
@@ -208,57 +207,66 @@ impl RenderBackend {
                             if self.scene.display_lists.get(&pipeline_id).is_none() {
                                 continue;
                             }
 
                             self.build_scene();
                         }
                         ApiMsg::Scroll(delta, cursor, move_phase) => {
                             profile_scope!("Scroll");
-                            let frame = profile_counters.total_time.profile(|| {
-                                if self.frame.scroll(delta, cursor, move_phase) {
-                                    Some(self.render())
-                                } else {
-                                    None
-                                }
-                            });
+                            let frame = {
+                                let counters = &mut profile_counters.texture_cache;
+                                profile_counters.total_time.profile(|| {
+                                    if self.frame.scroll(delta, cursor, move_phase) {
+                                        Some(self.render(counters))
+                                    } else {
+                                        None
+                                    }
+                                })
+                            };
 
                             match frame {
                                 Some(frame) => {
                                     self.publish_frame(frame, &mut profile_counters);
                                     self.notify_compositor_of_new_scroll_frame(true)
                                 }
                                 None => self.notify_compositor_of_new_scroll_frame(false),
                             }
                         }
                         ApiMsg::ScrollLayersWithScrollId(origin, pipeline_id, scroll_root_id) => {
                             profile_scope!("ScrollLayersWithScrollId");
-                            let frame = profile_counters.total_time.profile(|| {
-                                if self.frame.scroll_nodes(origin, pipeline_id, scroll_root_id) {
-                                    Some(self.render())
-                                } else {
-                                    None
-                                }
-                            });
+                            let frame = {
+                                let counters = &mut profile_counters.texture_cache;
+                                profile_counters.total_time.profile(|| {
+                                    if self.frame.scroll_nodes(origin, pipeline_id, scroll_root_id) {
+                                        Some(self.render(counters))
+                                    } else {
+                                        None
+                                    }
+                                })
+                            };
 
                             match frame {
                                 Some(frame) => {
                                     self.publish_frame(frame, &mut profile_counters);
                                     self.notify_compositor_of_new_scroll_frame(true)
                                 }
                                 None => self.notify_compositor_of_new_scroll_frame(false),
                             }
 
                         }
                         ApiMsg::TickScrollingBounce => {
                             profile_scope!("TickScrollingBounce");
-                            let frame = profile_counters.total_time.profile(|| {
-                                self.frame.tick_scrolling_bounce_animations();
-                                self.render()
-                            });
+                            let frame = {
+                                let counters = &mut profile_counters.texture_cache;
+                                profile_counters.total_time.profile(|| {
+                                    self.frame.tick_scrolling_bounce_animations();
+                                    self.render(counters)
+                                })
+                            };
 
                             self.publish_frame_and_notify_compositor(frame, &mut profile_counters);
                         }
                         ApiMsg::TranslatePointToLayerSpace(..) => {
                             panic!("unused api - remove from webrender_traits");
                         }
                         ApiMsg::GetScrollLayerState(tx) => {
                             profile_scope!("GetScrollLayerState");
@@ -341,19 +349,22 @@ impl RenderBackend {
                             //           are completed, optimize the internals of
                             //           animated properties to not require a full
                             //           rebuild of the frame!
                             if let Some(property_bindings) = property_bindings {
                                 self.scene.properties.set_properties(property_bindings);
                                 self.build_scene();
                             }
 
-                            let frame = profile_counters.total_time.profile(|| {
-                                self.render()
-                            });
+                            let frame = {
+                                let counters = &mut profile_counters.texture_cache;
+                                profile_counters.total_time.profile(|| {
+                                    self.render(counters)
+                                })
+                            };
                             if self.scene.root_pipeline_id.is_some() {
                                 self.publish_frame_and_notify_compositor(frame, &mut profile_counters);
                                 frame_counter += 1;
                             }
                         }
                         ApiMsg::ExternalEvent(evt) => {
                             let notifier = self.notifier.lock();
                             notifier.unwrap()
@@ -402,23 +413,26 @@ impl RenderBackend {
         // context at the start of a render frame should
         // incur minimal cost.
         for (_, webgl_context) in &self.webgl_contexts {
             webgl_context.make_current();
             webgl_context.apply_command(WebGLCommand::Flush);
             webgl_context.unbind();
         }
 
-        self.frame.create(&self.scene);
+        self.frame.create(&self.scene, &mut self.resource_cache);
     }
 
-    fn render(&mut self) -> RendererFrame {
+    fn render(&mut self,
+              texture_cache_profile: &mut TextureCacheProfileCounters)
+              -> RendererFrame {
         let frame = self.frame.build(&mut self.resource_cache,
                                      &self.scene.pipeline_auxiliary_lists,
-                                     self.device_pixel_ratio);
+                                     self.device_pixel_ratio,
+                                     texture_cache_profile);
 
         frame
     }
 
     fn publish_frame(&mut self,
                      frame: RendererFrame,
                      profile_counters: &mut BackendProfileCounters) {
         let pending_update = self.resource_cache.pending_updates();
--- a/gfx/webrender/src/render_task.rs
+++ b/gfx/webrender/src/render_task.rs
@@ -62,23 +62,22 @@ pub struct AlphaRenderTask {
     screen_origin: DeviceIntPoint,
     pub opaque_items: Vec<AlphaRenderItem>,
     pub alpha_items: Vec<AlphaRenderItem>,
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(C)]
 pub enum MaskSegment {
-    // This must match the SEGMENT_ values
-    // in clip_shared.glsl!
+    // This must match the SEGMENT_ values in clip_shared.glsl!
     All = 0,
-    Corner_TopLeft,
-    Corner_TopRight,
-    Corner_BottomLeft,
-    Corner_BottomRight,
+    TopLeftCorner,
+    TopRightCorner,
+    BottomLeftCorner,
+    BottomRightCorner,
 }
 
 #[derive(Debug, Copy, Clone)]
 #[repr(C)]
 pub enum MaskGeometryKind {
     Default,        // Draw the entire rect
     CornersOnly,    // Draw the corners (simple axis aligned mask)
     // TODO(gw): Add more types here (e.g. 4 rectangles outside the inner rect)
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -679,51 +679,42 @@ impl Renderer {
                                      &mut device,
                                      options.precache_shaders)
         };
 
         let device_max_size = device.max_texture_size();
         let max_texture_size = cmp::min(device_max_size, options.max_texture_size.unwrap_or(device_max_size));
 
         let mut texture_cache = TextureCache::new(max_texture_size);
+        let mut backend_profile_counters = BackendProfileCounters::new();
 
         let white_pixels: Vec<u8> = vec![
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
             0xff, 0xff, 0xff, 0xff,
         ];
         let mask_pixels: Vec<u8> = vec![
             0xff, 0xff,
             0xff, 0xff,
         ];
         // TODO: Ensure that the white texture can never get evicted when the cache supports LRU eviction!
         let white_image_id = texture_cache.new_item_id();
         texture_cache.insert(white_image_id,
-                             ImageDescriptor {
-                                width: 2,
-                                height: 2,
-                                stride: None,
-                                format: ImageFormat::RGBA8,
-                                is_opaque: false,
-                             },
+                             ImageDescriptor::new(2, 2, ImageFormat::RGBA8, false),
                              TextureFilter::Linear,
-                             ImageData::Raw(Arc::new(white_pixels)));
+                             ImageData::Raw(Arc::new(white_pixels)),
+                             &mut backend_profile_counters.texture_cache);
 
         let dummy_mask_image_id = texture_cache.new_item_id();
         texture_cache.insert(dummy_mask_image_id,
-                             ImageDescriptor {
-                                width: 2,
-                                height: 2,
-                                stride: None,
-                                format: ImageFormat::A8,
-                                is_opaque: false,
-                             },
+                             ImageDescriptor::new(2, 2, ImageFormat::A8, false),
                              TextureFilter::Linear,
-                             ImageData::Raw(Arc::new(mask_pixels)));
+                             ImageData::Raw(Arc::new(mask_pixels)),
+                             &mut backend_profile_counters.texture_cache);
 
         let dummy_cache_texture_id = device.create_texture_ids(1, TextureTarget::Array)[0];
         device.init_texture(dummy_cache_texture_id,
                             1,
                             1,
                             ImageFormat::RGBA8,
                             TextureFilter::Linear,
                             RenderTargetMode::LayerRenderTarget(1),
@@ -810,17 +801,17 @@ impl Renderer {
                                                  workers,
                                                  backend_notifier,
                                                  context_handle,
                                                  config,
                                                  recorder,
                                                  backend_main_thread_dispatcher,
                                                  blob_image_renderer,
                                                  backend_vr_compositor);
-            backend.run();
+            backend.run(backend_profile_counters);
         })};
 
         let renderer = Renderer {
             result_rx: result_rx,
             device: device,
             current_frame: None,
             pending_texture_updates: Vec::new(),
             pending_shader_updates: Vec::new(),
@@ -1118,23 +1109,23 @@ impl Renderer {
                         let texture_id = self.cache_texture_id_map[update.id.0];
                         self.device.resize_texture(texture_id,
                                                    width,
                                                    height,
                                                    format,
                                                    filter,
                                                    mode);
                     }
-                    TextureUpdateOp::Update { page_pos_x, page_pos_y, width, height, data, stride } => {
+                    TextureUpdateOp::Update { page_pos_x, page_pos_y, width, height, data, stride, offset } => {
                         let texture_id = self.cache_texture_id_map[update.id.0];
                         self.device.update_texture(texture_id,
                                                    page_pos_x,
                                                    page_pos_y,
                                                    width, height, stride,
-                                                   data.as_slice());
+                                                   &data[offset as usize..]);
                     }
                     TextureUpdateOp::UpdateForExternalBuffer { rect, id, stride } => {
                         let handler = self.external_image_handler
                                           .as_mut()
                                           .expect("Found external image, but no handler set!");
                         let device = &mut self.device;
                         let cached_id = self.cache_texture_id_map[update.id.0];
 
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -3,32 +3,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use device::TextureFilter;
 use fnv::FnvHasher;
 use frame::FrameId;
 use internal_types::{ExternalImageUpdateList, FontTemplate, SourceTexture, TextureUpdateList};
 use platform::font::{FontContext, RasterizedGlyph};
+use profiler::TextureCacheProfileCounters;
 use std::cell::RefCell;
 use std::collections::{HashMap, HashSet};
 use std::collections::hash_map::Entry::{self, Occupied, Vacant};
 use std::fmt::Debug;
 use std::hash::BuildHasherDefault;
 use std::hash::Hash;
 use std::mem;
 use std::sync::{Arc, Barrier, Mutex};
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::thread;
 use texture_cache::{TextureCache, TextureCacheItemId};
 use thread_profiler::register_thread_with_profiler;
 use webrender_traits::{Epoch, FontKey, GlyphKey, ImageKey, ImageFormat, ImageRendering};
 use webrender_traits::{FontRenderMode, ImageData, GlyphDimensions, WebGLContextId};
 use webrender_traits::{DevicePoint, DeviceIntSize, ImageDescriptor, ColorF};
-use webrender_traits::{ExternalImageId, GlyphOptions, GlyphInstance};
+use webrender_traits::{ExternalImageId, GlyphOptions, GlyphInstance, TileOffset, TileSize};
 use webrender_traits::{BlobImageRenderer, BlobImageDescriptor, BlobImageError};
 use threadpool::ThreadPool;
 use euclid::Point2D;
 
 thread_local!(pub static FONT_CONTEXT: RefCell<FontContext> = RefCell::new(FontContext::new()));
 
 type GlyphCache = ResourceClassCache<RenderedGlyphKey, Option<TextureCacheItemId>>;
 
@@ -87,29 +88,31 @@ impl RenderedGlyphKey {
             glyph_options: glyph_options,
         }
     }
 }
 
 pub struct ImageProperties {
     pub descriptor: ImageDescriptor,
     pub external_id: Option<ExternalImageId>,
+    pub tiling: Option<TileSize>,
 }
 
 #[derive(Debug, Copy, Clone, PartialEq)]
 enum State {
     Idle,
     AddResources,
     QueryResources,
 }
 
 struct ImageResource {
     data: ImageData,
     descriptor: ImageDescriptor,
     epoch: Epoch,
+    tiling: Option<TileSize>,
 }
 
 struct CachedImageInfo {
     texture_cache_id: TextureCacheItemId,
     epoch: Epoch,
 }
 
 pub struct ResourceClassCache<K,V> {
@@ -172,16 +175,17 @@ impl<K,V> ResourceClassCache<K,V> where 
         }
     }
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
 struct ImageRequest {
     key: ImageKey,
     rendering: ImageRendering,
+    tile: Option<TileOffset>,
 }
 
 struct GlyphRasterJob {
     key: RenderedGlyphKey,
     result: Option<RasterizedGlyph>,
 }
 
 struct WebGLTexture {
@@ -254,27 +258,29 @@ impl ResourceCache {
             .send(GlyphCacheMsg::AddFont(font_key, template.clone()))
             .unwrap();
         self.font_templates.insert(font_key, template);
     }
 
     pub fn add_image_template(&mut self,
                               image_key: ImageKey,
                               descriptor: ImageDescriptor,
-                              data: ImageData) {
+                              data: ImageData,
+                              mut tiling: Option<TileSize>) {
         if descriptor.width > self.max_texture_size() || descriptor.height > self.max_texture_size() {
-            // TODO: we need to support handle this case gracefully, cf. issue #620.
-            println!("Warning: texture size ({} {}) larger than the maximum size",
-                     descriptor.width, descriptor.height);
+            // We aren't going to be able to upload a texture this big, so tile it, even
+            // if tiling was not requested.
+            tiling = Some(512);
         }
 
         let resource = ImageResource {
             descriptor: descriptor,
             data: data,
             epoch: Epoch(0),
+            tiling: tiling,
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn update_image_template(&mut self,
                                  image_key: ImageKey,
                                  descriptor: ImageDescriptor,
@@ -296,16 +302,17 @@ impl ResourceCache {
                 Epoch(0)
             }
         };
 
         let resource = ImageResource {
             descriptor: descriptor,
             data: ImageData::new(bytes),
             epoch: next_epoch,
+            tiling: None,
         };
 
         self.image_templates.insert(image_key, resource);
     }
 
     pub fn delete_image_template(&mut self, image_key: ImageKey) {
         let value = self.image_templates.remove(&image_key);
 
@@ -334,21 +341,26 @@ impl ResourceCache {
     pub fn update_webgl_texture(&mut self, id: WebGLContextId, texture_id: SourceTexture, size: DeviceIntSize) {
         let webgl_texture = self.webgl_textures.get_mut(&id).unwrap();
 
         // Update new texture id and size
         webgl_texture.id = texture_id;
         webgl_texture.size = size;
     }
 
-    pub fn request_image(&mut self, key: ImageKey, rendering: ImageRendering) {
+    pub fn request_image(&mut self,
+                         key: ImageKey,
+                         rendering: ImageRendering,
+                         tile: Option<TileOffset>) {
+
         debug_assert!(self.state == State::AddResources);
         let request = ImageRequest {
             key: key,
             rendering: rendering,
+            tile: tile,
         };
 
         let template = self.image_templates.get(&key).unwrap();
         if let ImageData::Blob(ref data) = template.data {
             if let Some(ref mut renderer) = self.blob_image_renderer {
                 let same_epoch = match self.cached_images.resources.get(&request) {
                     Some(entry) => entry.epoch == template.epoch,
                     None => false,
@@ -467,21 +479,23 @@ impl ResourceCache {
                 *entry.insert(dimensions)
             }
         }
     }
 
     #[inline]
     pub fn get_cached_image(&self,
                             image_key: ImageKey,
-                            image_rendering: ImageRendering) -> CacheItem {
+                            image_rendering: ImageRendering,
+                            tile: Option<TileOffset>) -> CacheItem {
         debug_assert!(self.state == State::QueryResources);
         let key = ImageRequest {
             key: image_key,
             rendering: image_rendering,
+            tile: tile,
         };
         let image_info = &self.cached_images.get(&key, self.current_frame_id);
         let item = self.texture_cache.get(image_info.texture_cache_id);
         CacheItem {
             texture_id: SourceTexture::TextureCache(item.texture_id),
             uv0: DevicePoint::new(item.pixel_rect.top_left.x as f32,
                                   item.pixel_rect.top_left.y as f32),
             uv1: DevicePoint::new(item.pixel_rect.bottom_right.x as f32,
@@ -496,16 +510,17 @@ impl ResourceCache {
             ImageData::ExternalHandle(id) => Some(id),
             // raw and externalBuffer are all use resource_cache.
             ImageData::Raw(..) | ImageData::ExternalBuffer(..) | ImageData::Blob(..) => None,
         };
 
         ImageProperties {
             descriptor: image_template.descriptor,
             external_id: external_id,
+            tiling: image_template.tiling,
         }
     }
 
     #[inline]
     pub fn get_webgl_texture(&self, context_id: &WebGLContextId) -> CacheItem {
         let webgl_texture = &self.webgl_textures[context_id];
         CacheItem {
             texture_id: webgl_texture.id,
@@ -524,17 +539,18 @@ impl ResourceCache {
     pub fn begin_frame(&mut self, frame_id: FrameId) {
         debug_assert!(self.state == State::Idle);
         self.state = State::AddResources;
         self.current_frame_id = frame_id;
         let glyph_cache = self.cached_glyphs.take().unwrap();
         self.glyph_cache_tx.send(GlyphCacheMsg::BeginFrame(frame_id, glyph_cache)).ok();
     }
 
-    pub fn block_until_all_resources_added(&mut self) {
+    pub fn block_until_all_resources_added(&mut self,
+                                           texture_cache_profile: &mut TextureCacheProfileCounters) {
         profile_scope!("block_until_all_resources_added");
 
         debug_assert!(self.state == State::AddResources);
         self.state = State::QueryResources;
 
         // Tell the glyph cache thread that all glyphs have been requested
         // and block, waiting for any pending glyphs to be rasterized. In the
         // future, we will expand this to have a timeout. If the glyph rasterizing
@@ -558,19 +574,21 @@ impl ResourceCache {
                                 let image_id = self.texture_cache.new_item_id();
                                 self.texture_cache.insert(image_id,
                                                           ImageDescriptor {
                                                               width: glyph.width,
                                                               height: glyph.height,
                                                               stride: None,
                                                               format: ImageFormat::RGBA8,
                                                               is_opaque: false,
+                                                              offset: 0,
                                                           },
                                                           TextureFilter::Linear,
-                                                          ImageData::Raw(Arc::new(glyph.bytes)));
+                                                          ImageData::Raw(Arc::new(glyph.bytes)),
+                                                          texture_cache_profile);
                                 Some(image_id)
                             } else {
                                 None
                             }
                         });
 
                         cache.insert(job.key, image_id, self.current_frame_id);
                     }
@@ -578,26 +596,28 @@ impl ResourceCache {
                     self.cached_glyphs = Some(cache);
                     break;
                 }
             }
         }
 
         let mut image_requests = mem::replace(&mut self.pending_image_requests, Vec::new());
         for request in image_requests.drain(..) {
-            self.finalize_image_request(request, None);
+            self.finalize_image_request(request, None, texture_cache_profile);
         }
 
         let mut blob_image_requests = mem::replace(&mut self.blob_image_requests, HashSet::new());
         if self.blob_image_renderer.is_some() {
             for request in blob_image_requests.drain() {
                 match self.blob_image_renderer.as_mut().unwrap()
                                                 .resolve_blob_image(request.key) {
                     Ok(image) => {
-                        self.finalize_image_request(request, Some(ImageData::new(image.data)));
+                        self.finalize_image_request(request,
+                                                    Some(ImageData::new(image.data)),
+                                                    texture_cache_profile);
                     }
                     // TODO(nical): I think that we should handle these somewhat gracefully,
                     // at least in the out-of-memory scenario.
                     Err(BlobImageError::Oom) => {
                         // This one should be recoverable-ish.
                         panic!("Failed to render a vector image (OOM)");
                     }
                     Err(BlobImageError::InvalidKey) => {
@@ -610,17 +630,20 @@ impl ResourceCache {
                     Err(BlobImageError::Other(msg)) => {
                         panic!("Vector image error {}", msg);
                     }
                 }
             }
         }
     }
 
-    fn finalize_image_request(&mut self, request: ImageRequest, image_data: Option<ImageData>) {
+    fn finalize_image_request(&mut self,
+                              request: ImageRequest,
+                              image_data: Option<ImageData>,
+                              texture_cache_profile: &mut TextureCacheProfileCounters) {
         let image_template = &self.image_templates[&request.key];
         let image_data = image_data.unwrap_or_else(||{
             image_template.data.clone()
         });
 
         match image_template.data {
             ImageData::ExternalHandle(..) => {
                 // external handle doesn't need to update the texture_cache.
@@ -645,20 +668,60 @@ impl ResourceCache {
                     Vacant(entry) => {
                         let image_id = self.texture_cache.new_item_id();
 
                         let filter = match request.rendering {
                             ImageRendering::Pixelated => TextureFilter::Nearest,
                             ImageRendering::Auto | ImageRendering::CrispEdges => TextureFilter::Linear,
                         };
 
-                        self.texture_cache.insert(image_id,
-                                                  image_template.descriptor,
-                                                  filter,
-                                                  image_data);
+                        if let Some(tile) = request.tile {
+                            let tile_size = image_template.tiling.unwrap() as u32;
+                            let image_descriptor = image_template.descriptor.clone();
+                            let stride = image_descriptor.compute_stride();
+                            let bpp = image_descriptor.format.bytes_per_pixel().unwrap();
+
+                            // Storage for the tiles on the right and bottom edges is shrunk to
+                            // fit the image data (See decompose_tiled_image in frame.rs).
+                            let actual_width = if (tile.x as u32) < image_descriptor.width / tile_size {
+                                tile_size
+                            } else {
+                                image_descriptor.width % tile_size
+                            };
+
+                            let actual_height = if (tile.y as u32) < image_descriptor.height / tile_size {
+                                tile_size
+                            } else {
+                                image_descriptor.height % tile_size
+                            };
+
+                            let offset = image_descriptor.offset + tile.y as u32 * tile_size * stride
+                                                                 + tile.x as u32 * tile_size * bpp;
+
+                            let tile_descriptor = ImageDescriptor {
+                                width: actual_width,
+                                height: actual_height,
+                                stride: Some(stride),
+                                offset: offset,
+                                format: image_descriptor.format,
+                                is_opaque: image_descriptor.is_opaque,
+                            };
+
+                            self.texture_cache.insert(image_id,
+                                                      tile_descriptor,
+                                                      filter,
+                                                      image_data,
+                                                      texture_cache_profile);
+                        } else {
+                            self.texture_cache.insert(image_id,
+                                                      image_template.descriptor,
+                                                      filter,
+                                                      image_data,
+                                                      texture_cache_profile);
+                        }
 
                         entry.insert(CachedImageInfo {
                             texture_cache_id: image_id,
                             epoch: image_template.epoch,
                         });
                     }
                 }
             }
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -2,16 +2,17 @@
  * 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/. */
 
 use device::TextureFilter;
 use fnv::FnvHasher;
 use freelist::{FreeList, FreeListItem, FreeListItemId};
 use internal_types::{TextureUpdate, TextureUpdateOp};
 use internal_types::{CacheTextureId, RenderTargetMode, TextureUpdateList, RectUv};
+use profiler::TextureCacheProfileCounters;
 use std::cmp::{self, Ordering};
 use std::collections::HashMap;
 use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
 use std::mem;
 use std::slice::Iter;
 use time;
 use util;
@@ -89,65 +90,39 @@ impl TexturePage {
             let candidate_area = candidate_rect.size.width * candidate_rect.size.height;
             smallest_index_and_area = Some((candidate_index, candidate_area));
             break
         }
 
         smallest_index_and_area.map(|(index, _)| FreeListIndex(bin, index))
     }
 
+    /// Find a suitable rect in the free list. We choose the smallest such rect
+    /// in terms of area (Best-Area-Fit, BAF).
     fn find_index_of_best_rect(&self, requested_dimensions: &DeviceUintSize)
                                -> Option<FreeListIndex> {
-        match FreeListBin::for_size(requested_dimensions) {
-            FreeListBin::Large => {
-                self.find_index_of_best_rect_in_bin(FreeListBin::Large, requested_dimensions)
-            }
-            FreeListBin::Medium => {
-                match self.find_index_of_best_rect_in_bin(FreeListBin::Medium,
-                                                          requested_dimensions) {
-                    Some(index) => Some(index),
-                    None => {
-                        self.find_index_of_best_rect_in_bin(FreeListBin::Large,
-                                                            requested_dimensions)
-                    }
-                }
-            }
-            FreeListBin::Small => {
-                match self.find_index_of_best_rect_in_bin(FreeListBin::Small,
-                                                          requested_dimensions) {
-                    Some(index) => Some(index),
-                    None => {
-                        match self.find_index_of_best_rect_in_bin(FreeListBin::Medium,
-                                                                  requested_dimensions) {
-                            Some(index) => Some(index),
-                            None => {
-                                self.find_index_of_best_rect_in_bin(FreeListBin::Large,
-                                                                    requested_dimensions)
-                            }
-                        }
-                    }
+        let bin = FreeListBin::for_size(requested_dimensions);
+        for &target_bin in &[FreeListBin::Small, FreeListBin::Medium, FreeListBin::Large] {
+            if bin <= target_bin {
+                if let Some(index) = self.find_index_of_best_rect_in_bin(target_bin,
+                                                                         requested_dimensions) {
+                    return Some(index);
                 }
             }
         }
+        None
+    }
+
+    pub fn can_allocate(&self, requested_dimensions: &DeviceUintSize) -> bool {
+        self.find_index_of_best_rect(requested_dimensions).is_some()
     }
 
     pub fn allocate(&mut self,
                     requested_dimensions: &DeviceUintSize) -> Option<DeviceUintPoint> {
-        // First, try to find a suitable rect in the free list. We choose the smallest such rect
-        // in terms of area (Best-Area-Fit, BAF).
-        let mut index = self.find_index_of_best_rect(requested_dimensions);
-
-        // If one couldn't be found and we're dirty, coalesce rects and try again.
-        if index.is_none() && self.dirty {
-            self.coalesce();
-            index = self.find_index_of_best_rect(requested_dimensions)
-        }
-
-        // If a rect still can't be found, fail.
-        let index = match index {
+        let index = match self.find_index_of_best_rect(requested_dimensions) {
             None => return None,
             Some(index) => index,
         };
 
         // Remove the rect from the free list and decide how to guillotine it. We choose the split
         // that results in the single largest area (Min Area Split Rule, MINAS).
         let chosen_rect = self.free_list.remove(index);
         let candidate_free_rect_to_right =
@@ -194,17 +169,21 @@ impl TexturePage {
         // Bump the allocation counter.
         self.allocations += 1;
 
         // Return the result.
         Some(chosen_rect.origin)
     }
 
     #[inline(never)]
-    fn coalesce(&mut self) {
+    pub fn coalesce(&mut self) -> bool {
+        if !self.dirty {
+            return false
+        }
+
         // Iterate to a fixed point or until a timeout is reached.
         let deadline = time::precise_time_ns() + COALESCING_TIMEOUT;
         let mut free_list = mem::replace(&mut self.free_list, FreeRectList::new()).into_vec();
         let mut changed = false;
 
         // Combine rects that have the same width and are adjacent.
         let mut new_free_list = Vec::new();
         free_list.sort_by(|a, b| {
@@ -213,17 +192,17 @@ impl TexturePage {
                 ordering => ordering,
             }
         });
         for work_index in 0..free_list.len() {
             if work_index % COALESCING_TIMEOUT_CHECKING_INTERVAL == 0 &&
                     time::precise_time_ns() >= deadline {
                 self.free_list = FreeRectList::from_slice(&free_list[..]);
                 self.dirty = true;
-                return
+                return true
             }
 
             if free_list[work_index].size.width == 0 {
                 continue
             }
             for candidate_index in (work_index + 1)..free_list.len() {
                 if free_list[work_index].size.width != free_list[candidate_index].size.width ||
                         free_list[work_index].origin.x != free_list[candidate_index].origin.x {
@@ -250,17 +229,17 @@ impl TexturePage {
                 ordering => ordering,
             }
         });
         for work_index in 0..free_list.len() {
             if work_index % COALESCING_TIMEOUT_CHECKING_INTERVAL == 0 &&
                     time::precise_time_ns() >= deadline {
                 self.free_list = FreeRectList::from_slice(&free_list[..]);
                 self.dirty = true;
-                return
+                return true
             }
 
             if free_list[work_index].size.height == 0 {
                 continue
             }
             for candidate_index in (work_index + 1)..free_list.len() {
                 if free_list[work_index].size.height !=
                         free_list[candidate_index].size.height ||
@@ -275,17 +254,18 @@ impl TexturePage {
                     free_list[candidate_index].size.height = 0
                 }
             }
             new_free_list.push(free_list[work_index])
         }
         free_list = new_free_list;
 
         self.free_list = FreeRectList::from_slice(&free_list[..]);
-        self.dirty = changed
+        self.dirty = changed;
+        changed
     }
 
     pub fn clear(&mut self) {
         self.free_list = FreeRectList::new();
         self.free_list.push(&DeviceUintRect::new(
             DeviceUintPoint::zero(),
             self.texture_size));
         self.allocations = 0;
@@ -386,17 +366,17 @@ impl FreeRectList {
         self.small.extend(self.large.drain(..));
         self.small
     }
 }
 
 #[derive(Debug, Clone, Copy)]
 struct FreeListIndex(FreeListBin, usize);
 
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
 enum FreeListBin {
     Small,
     Medium,
     Large,
 }
 
 impl FreeListBin {
     pub fn for_size(size: &DeviceUintSize) -> FreeListBin {
@@ -423,16 +403,22 @@ pub struct TextureCacheItem {
     pub texture_size: DeviceUintSize,
 
     // The size of the allocated rectangle.
     pub allocated_rect: DeviceUintRect,
 }
 
 // Structure squat the width/height fields to maintain the free list information :)
 impl FreeListItem for TextureCacheItem {
+    fn take(&mut self) -> Self {
+        let data = self.clone();
+        self.texture_id = CacheTextureId(0);
+        data
+    }
+
     fn next_free_id(&self) -> Option<FreeListItemId> {
         if self.allocated_rect.size.width == 0 {
             debug_assert_eq!(self.allocated_rect.size.height, 0);
             None
         } else {
             debug_assert_eq!(self.allocated_rect.size.width, 1);
             Some(FreeListItemId::new(self.allocated_rect.size.height))
         }
@@ -575,36 +561,29 @@ impl TextureCache {
     pub fn pending_updates(&mut self) -> TextureUpdateList {
         mem::replace(&mut self.pending_updates, TextureUpdateList::new())
     }
 
     // TODO(gw): This API is a bit ugly (having to allocate an ID and
     //           then use it). But it has to be that way for now due to
     //           how the raster_jobs code works.
     pub fn new_item_id(&mut self) -> TextureCacheItemId {
-        let new_item = TextureCacheItem {
-            pixel_rect: RectUv {
-                top_left: DeviceIntPoint::zero(),
-                top_right: DeviceIntPoint::zero(),
-                bottom_left: DeviceIntPoint::zero(),
-                bottom_right: DeviceIntPoint::zero(),
-            },
-            allocated_rect: DeviceUintRect::zero(),
-            texture_size: DeviceUintSize::zero(),
-            texture_id: CacheTextureId(0),
-        };
+        let new_item = TextureCacheItem::new(CacheTextureId(0),
+                                             DeviceUintRect::zero(),
+                                             &DeviceUintSize::zero());
         self.items.insert(new_item)
     }
 
     pub fn allocate(&mut self,
                     image_id: TextureCacheItemId,
                     requested_width: u32,
                     requested_height: u32,
                     format: ImageFormat,
-                    filter: TextureFilter)
+                    filter: TextureFilter,
+                    profile: &mut TextureCacheProfileCounters)
                     -> AllocationResult {
         let requested_size = DeviceUintSize::new(requested_width, requested_height);
 
         // TODO(gw): For now, anything that requests nearest filtering
         //           just fails to allocate in a texture page, and gets a standalone
         //           texture. This isn't ideal, as it causes lots of batch breaks,
         //           but is probably rare enough that it can be fixed up later (it's also
         //           fairly trivial to implement, just tedious).
@@ -619,95 +598,113 @@ impl TextureCache {
 
             return AllocationResult {
                 item: self.items.get(image_id).clone(),
                 kind: AllocationKind::Standalone,
             }
         }
 
         let mode = RenderTargetMode::SimpleRenderTarget;
-        let page_list = match format {
-            ImageFormat::A8 => &mut self.arena.pages_a8,
-            ImageFormat::RGBA8 => &mut self.arena.pages_rgba8,
-            ImageFormat::RGB8 => &mut self.arena.pages_rgb8,
+        let (page_list, page_profile) = match format {
+            ImageFormat::A8 => (&mut self.arena.pages_a8, &mut profile.pages_a8),
+            ImageFormat::RGBA8 => (&mut self.arena.pages_rgba8, &mut profile.pages_rgba8),
+            ImageFormat::RGB8 => (&mut self.arena.pages_rgb8, &mut profile.pages_rgb8),
             ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
         };
 
         // TODO(gw): Handle this sensibly (support failing to render items that can't fit?)
         assert!(requested_size.width < self.max_texture_size);
         assert!(requested_size.height < self.max_texture_size);
 
-        // Loop until an allocation succeeds, growing or adding new
-        // texture pages as required.
-        loop {
-            let location = page_list.last_mut().and_then(|last_page| {
-                last_page.allocate(&requested_size)
-            });
-
-            if let Some(location) = location {
-                let page = page_list.last_mut().unwrap();
-
-                let requested_rect = DeviceUintRect::new(location, requested_size);
-                let cache_item = TextureCacheItem::new(page.texture_id,
-                                                       requested_rect,
-                                                       &page.texture_size);
-                *self.items.get_mut(image_id) = cache_item;
-
-                return AllocationResult {
-                    item: self.items.get(image_id).clone(),
-                    kind: AllocationKind::TexturePage,
-                }
+        let mut page_id = None; //using ID here to please the borrow checker
+        for (i, page) in page_list.iter_mut().enumerate() {
+            if page.can_allocate(&requested_size) {
+                page_id = Some(i);
+                break;
             }
-
-            if !page_list.is_empty() && page_list.last().unwrap().can_grow(self.max_texture_size) {
-                let last_page = page_list.last_mut().unwrap();
-                // Grow the texture.
-                let new_width = cmp::min(last_page.texture_size.width * 2, self.max_texture_size);
-                let new_height = cmp::min(last_page.texture_size.height * 2, self.max_texture_size);
+            // try to coalesce it
+            if page.coalesce() && page.can_allocate(&requested_size) {
+                page_id = Some(i);
+                break;
+            }
+            if page.can_grow(self.max_texture_size) {
+                // try to grow it
+                let new_width = cmp::min(page.texture_size.width * 2, self.max_texture_size);
+                let new_height = cmp::min(page.texture_size.height * 2, self.max_texture_size);
                 let texture_size = DeviceUintSize::new(new_width, new_height);
                 self.pending_updates.push(TextureUpdate {
-                    id: last_page.texture_id,
+                    id: page.texture_id,
                     op: texture_grow_op(texture_size, format, mode),
                 });
-                last_page.grow(texture_size);
+
+                let extra_texels = new_width * new_height - page.texture_size.width * page.texture_size.height;
+                let extra_bytes = extra_texels * format.bytes_per_pixel().unwrap_or(0);
+                page_profile.inc(extra_bytes as usize);
+
+                page.grow(texture_size);
 
                 self.items.for_each_item(|item| {
-                    if item.texture_id == last_page.texture_id {
+                    if item.texture_id == page.texture_id {
                         item.texture_size = texture_size;
                     }
                 });
 
-                continue;
+                if page.can_allocate(&requested_size) {
+                    page_id = Some(i);
+                    break;
+                }
             }
+        }
 
-            // We need a new page.
-            let texture_size = initial_texture_size(self.max_texture_size);
-            let free_texture_levels_entry = self.free_texture_levels.entry(format);
-            let mut free_texture_levels = match free_texture_levels_entry {
-                Entry::Vacant(entry) => entry.insert(Vec::new()),
-                Entry::Occupied(entry) => entry.into_mut(),
-            };
-            if free_texture_levels.is_empty() {
-                let texture_id = self.cache_id_list.allocate();
+        let mut page = match page_id {
+            Some(index) => &mut page_list[index],
+            None => {
+                let init_texture_size = initial_texture_size(self.max_texture_size);
+                let texture_size = DeviceUintSize::new(cmp::max(requested_width, init_texture_size.width),
+                                                       cmp::max(requested_height, init_texture_size.height));
+                let extra_bytes = texture_size.width * texture_size.height * format.bytes_per_pixel().unwrap_or(0);
+                page_profile.inc(extra_bytes as usize);
+
+                let free_texture_levels_entry = self.free_texture_levels.entry(format);
+                let mut free_texture_levels = match free_texture_levels_entry {
+                    Entry::Vacant(entry) => entry.insert(Vec::new()),
+                    Entry::Occupied(entry) => entry.into_mut(),
+                };
+                if free_texture_levels.is_empty() {
+                    let texture_id = self.cache_id_list.allocate();
 
-                let update_op = TextureUpdate {
-                    id: texture_id,
-                    op: texture_create_op(texture_size, format, mode),
-                };
-                self.pending_updates.push(update_op);
+                    let update_op = TextureUpdate {
+                        id: texture_id,
+                        op: texture_create_op(texture_size, format, mode),
+                    };
+                    self.pending_updates.push(update_op);
+
+                    free_texture_levels.push(FreeTextureLevel {
+                        texture_id: texture_id,
+                    });
+                }
+                let free_texture_level = free_texture_levels.pop().unwrap();
+                let texture_id = free_texture_level.texture_id;
 
-                free_texture_levels.push(FreeTextureLevel {
-                    texture_id: texture_id,
-                });
-            }
-            let free_texture_level = free_texture_levels.pop().unwrap();
-            let texture_id = free_texture_level.texture_id;
+                let page = TexturePage::new(texture_id, texture_size);
+                page_list.push(page);
+                page_list.last_mut().unwrap()
+            },
+        };
 
-            let page = TexturePage::new(texture_id, texture_size);
-            page_list.push(page);
+        let location = page.allocate(&requested_size)
+                           .expect("All the checks have passed till now, there is no way back.");
+        let cache_item = TextureCacheItem::new(page.texture_id,
+                                               DeviceUintRect::new(location, requested_size),
+                                               &page.texture_size);
+        *self.items.get_mut(image_id) = cache_item.clone();
+
+        AllocationResult {
+            item: cache_item,
+            kind: AllocationKind::TexturePage,
         }
     }
 
     pub fn update(&mut self,
                   image_id: TextureCacheItemId,
                   descriptor: ImageDescriptor,
                   data: ImageData) {
         let existing_item = self.items.get(image_id);
@@ -726,47 +723,50 @@ impl TextureCache {
             ImageData::Raw(bytes) => {
                 TextureUpdateOp::Update {
                     page_pos_x: existing_item.allocated_rect.origin.x,
                     page_pos_y: existing_item.allocated_rect.origin.y,
                     width: descriptor.width,
                     height: descriptor.height,
                     data: bytes,
                     stride: descriptor.stride,
+                    offset: descriptor.offset,
                 }
             }
         };
 
         let update_op = TextureUpdate {
             id: existing_item.texture_id,
             op: op,
         };
 
         self.pending_updates.push(update_op);
     }
 
     pub fn insert(&mut self,
                   image_id: TextureCacheItemId,
                   descriptor: ImageDescriptor,
                   filter: TextureFilter,
-                  data: ImageData) {
+                  data: ImageData,
+                  profile: &mut TextureCacheProfileCounters) {
         if let ImageData::Blob(..) = data {
             panic!("must rasterize the vector image before adding to the cache");
         }
 
         let width = descriptor.width;
         let height = descriptor.height;
         let format = descriptor.format;
         let stride = descriptor.stride;
 
         let result = self.allocate(image_id,
                                    width,
                                    height,
                                    format,
-                                   filter);
+                                   filter,
+                                   profile);
 
         match result.kind {
             AllocationKind::TexturePage => {
                 match data {
                     ImageData::ExternalHandle(..) => {
                         panic!("External handle should not go through texture_cache.");
                     }
                     ImageData::Blob(..) => {
@@ -777,16 +777,17 @@ impl TextureCache {
                             id: result.item.texture_id,
                             op: TextureUpdateOp::Update {
                                 page_pos_x: result.item.allocated_rect.origin.x,
                                 page_pos_y: result.item.allocated_rect.origin.y,
                                 width: result.item.allocated_rect.size.width,
                                 height: result.item.allocated_rect.size.height,
                                 data: bytes,
                                 stride: stride,
+                                offset: descriptor.offset,
                             },
                         };
 
                         self.pending_updates.push(update_op);
                     }
                     ImageData::ExternalBuffer(id) => {
                         let update_op = TextureUpdate {
                             id: result.item.texture_id,
@@ -826,33 +827,29 @@ impl TextureCache {
         }
     }
 
     pub fn get(&self, id: TextureCacheItemId) -> &TextureCacheItem {
         self.items.get(id)
     }
 
     pub fn free(&mut self, id: TextureCacheItemId) {
-        {
-            let item = self.items.get(id);
-            match self.arena.texture_page_for_id(item.texture_id) {
-                Some(texture_page) => texture_page.free(&item.allocated_rect),
-                None => {
-                    // This is a standalone texture allocation. Just push it back onto the free
-                    // list.
-                    self.pending_updates.push(TextureUpdate {
-                        id: item.texture_id,
-                        op: TextureUpdateOp::Free,
-                    });
-                    self.cache_id_list.free(item.texture_id);
-                }
+        let item = self.items.free(id);
+        match self.arena.texture_page_for_id(item.texture_id) {
+            Some(texture_page) => texture_page.free(&item.allocated_rect),
+            None => {
+                // This is a standalone texture allocation. Just push it back onto the free
+                // list.
+                self.pending_updates.push(TextureUpdate {
+                    id: item.texture_id,
+                    op: TextureUpdateOp::Free,
+                });
+                self.cache_id_list.free(item.texture_id);
             }
         }
-
-        self.items.free(id)
     }
 }
 
 fn texture_create_op(texture_size: DeviceUintSize, format: ImageFormat, mode: RenderTargetMode)
                      -> TextureUpdateOp {
     TextureUpdateOp::Create {
         width: texture_size.width,
         height: texture_size.height,
--- a/gfx/webrender/src/tiling.rs
+++ b/gfx/webrender/src/tiling.rs
@@ -803,41 +803,41 @@ impl ClipBatcher {
                             segment: MaskSegment::All as i32,
                             ..instance
                         });
                     }
                     MaskGeometryKind::CornersOnly => {
                         self.rectangles.extend(&[
                             CacheClipInstance {
                                 address: GpuStoreAddress(offset),
-                                segment: MaskSegment::Corner_TopLeft as i32,
+                                segment: MaskSegment::TopLeftCorner as i32,
                                 ..instance
                             },
                             CacheClipInstance {
                                 address: GpuStoreAddress(offset),
-                                segment: MaskSegment::Corner_TopRight as i32,
+                                segment: MaskSegment::TopRightCorner as i32,
                                 ..instance
                             },
                             CacheClipInstance {
                                 address: GpuStoreAddress(offset),
-                                segment: MaskSegment::Corner_BottomLeft as i32,
+                                segment: MaskSegment::BottomLeftCorner as i32,
                                 ..instance
                             },
                             CacheClipInstance {
                                 address: GpuStoreAddress(offset),
-                                segment: MaskSegment::Corner_BottomRight as i32,
+                                segment: MaskSegment::BottomRightCorner as i32,
                                 ..instance
                             },
                         ]);
                     }
                 }
             }
 
             if let Some((ref mask, address)) = info.image {
-                let cache_item = resource_cache.get_cached_image(mask.image, ImageRendering::Auto);
+                let cache_item = resource_cache.get_cached_image(mask.image, ImageRendering::Auto, None);
                 self.images.entry(cache_item.texture_id)
                            .or_insert(Vec::new())
                            .push(CacheClipInstance {
                     address: address,
                     ..instance
                 })
             }
         }
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -1,25 +1,17 @@
 [package]
 name = "webrender_bindings"
 version = "0.1.0"
 authors = ["The Mozilla Project Developers"]
 license = "MPL-2.0"
 
 [dependencies]
-webrender_traits = {path = "../webrender_traits", version = "0.19"}
+webrender_traits = {path = "../webrender_traits", version = "0.20.0"}
 euclid = "0.11"
 app_units = "0.4"
 gleam = "0.2"
-fnv="1.0"
 
 [dependencies.webrender]
 path = "../webrender"
-version = "0.19"
+version = "0.19.0"
 default-features = false
 features = ["codegen"]
-
-[target.'cfg(target_os = "macos")'.dependencies]
-core-foundation = "0.2.2"
-
-[target.'cfg(target_os = "windows")'.dependencies]
-kernel32-sys = "0.2"
-winapi = "0.2.8"
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -155,20 +155,17 @@ static void
 NotifyDidRender(layers::CompositorBridgeParentBase* aBridge,
                 WrRenderedEpochs* aEpochs,
                 TimeStamp aStart,
                 TimeStamp aEnd)
 {
   WrPipelineId pipeline;
   WrEpoch epoch;
   while (wr_rendered_epochs_next(aEpochs, &pipeline, &epoch)) {
-    // TODO - Currently each bridge seems to  only have one pipeline but at some
-    // point we should pass make sure we only notify bridges that have the
-    // corresponding pipeline id.
-    aBridge->NotifyDidComposite(epoch.mHandle, aStart, aEnd);
+    aBridge->NotifyDidCompositeToPipeline(pipeline, epoch, aStart, aEnd);
   }
   wr_rendered_epochs_delete(aEpochs);
 }
 
 void
 RenderThread::UpdateAndRender(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
--- a/gfx/webrender_bindings/RendererOGL.cpp
+++ b/gfx/webrender_bindings/RendererOGL.cpp
@@ -9,16 +9,29 @@
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/widget/CompositorWidget.h"
 
 namespace mozilla {
 namespace wr {
 
+WrExternalImage LockExternalImage(void* aObj, WrExternalImageId aId)
+{
+  return WrExternalImage { /*WrExternalImageIdType::TextureHandle, */0.0f, 0.0f, 0.0f, 0.0f, 0 };
+}
+
+void UnlockExternalImage(void* aObj, WrExternalImageId aId)
+{
+}
+
+void ReleaseExternalImage(void* aObj, WrExternalImageId aId)
+{
+}
+
 RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread,
                          RefPtr<gl::GLContext>&& aGL,
                          RefPtr<widget::CompositorWidget>&& aWidget,
                          wr::WindowId aWindowId,
                          WrRenderer* aWrRenderer,
                          layers::CompositorBridgeParentBase* aBridge)
   : mThread(aThread)
   , mGL(aGL)
@@ -36,16 +49,27 @@ RendererOGL::RendererOGL(RefPtr<RenderTh
 }
 
 RendererOGL::~RendererOGL()
 {
   MOZ_COUNT_DTOR(RendererOGL);
   wr_renderer_delete(mWrRenderer);
 }
 
+WrExternalImageHandler
+RendererOGL::GetExternalImageHandler()
+{
+  return WrExternalImageHandler {
+    this,
+    LockExternalImage,
+    UnlockExternalImage,
+    ReleaseExternalImage,
+  };
+}
+
 void
 RendererOGL::Update()
 {
   wr_renderer_update(mWrRenderer);
 }
 
 bool
 RendererOGL::Render()
--- a/gfx/webrender_bindings/RendererOGL.h
+++ b/gfx/webrender_bindings/RendererOGL.h
@@ -33,17 +33,23 @@ namespace wr {
 
 /// Owns the WebRender renderer and GL context.
 ///
 /// There is one renderer per window, all owned by the render thread.
 /// This class is a similar abstraction to CompositorOGL except that it is used
 /// on the render thread instead of the compositor thread.
 class RendererOGL
 {
+  friend WrExternalImage LockExternalImage(void* aObj, WrExternalImageId aId);
+  friend void UnlockExternalImage(void* aObj, WrExternalImageId aId);
+  friend void ReleaseExternalImage(void* aObj, WrExternalImageId aId);
+
 public:
+  WrExternalImageHandler GetExternalImageHandler();
+
   /// This can be called on the render thread only.
   void Update();
 
   /// This can be called on the render thread only.
   bool Render();
 
   /// This can be called on the render thread only.
   bool RenderToTarget(gfx::DrawTarget& aTarget);
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -46,28 +46,32 @@ public:
     if (!gl || !gl->MakeCurrent()) {
       return;
     }
 
     gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, mMaxTextureSize);
     *mUseANGLE = gl->IsANGLE();
 
     WrRenderer* wrRenderer = nullptr;
-    if (!wr_window_new(aWindowId, gl.get(), this->mEnableProfiler, nullptr, mWrApi, &wrRenderer)) {
+    if (!wr_window_new(aWindowId, gl.get(), this->mEnableProfiler, mWrApi, &wrRenderer)) {
       return;
     }
     MOZ_ASSERT(wrRenderer);
 
     RefPtr<RenderThread> thread = &aRenderThread;
     auto renderer = MakeUnique<RendererOGL>(Move(thread),
                                             Move(gl),
                                             Move(mCompositorWidget),
                                             aWindowId,
                                             wrRenderer,
                                             mBridge);
+    if (wrRenderer && renderer) {
+      WrExternalImageHandler handler = renderer->GetExternalImageHandler();
+      wr_renderer_set_external_image_handler(wrRenderer, &handler);
+    }
 
     aRenderThread.AddRenderer(aWindowId, Move(renderer));
   }
 
 private:
   WrAPI** mWrApi;
   GLint* mMaxTextureSize;
   bool* mUseANGLE;
@@ -130,35 +134,59 @@ WebRenderAPI::Create(bool aEnableProfile
 
   if (!wrApi) {
     return nullptr;
   }
 
   return RefPtr<WebRenderAPI>(new WebRenderAPI(wrApi, id, maxTextureSize, useANGLE)).forget();
 }
 
+WrIdNamespace
+WebRenderAPI::GetNamespace() {
+  return wr_api_get_namespace(mWrApi);
+}
+
 WebRenderAPI::~WebRenderAPI()
 {
   layers::SynchronousTask task("Destroy WebRenderAPI");
   auto event = MakeUnique<RemoveRenderer>(&task);
   RunOnRenderThread(Move(event));
   task.Wait();
 
   wr_api_delete(mWrApi);
 }
 
 void
+WebRenderAPI::GenerateFrame()
+{
+  wr_api_generate_frame(mWrApi);
+}
+
+void
 WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
                                  Epoch aEpoch,
                                  LayerSize aViewportSize,
-                                 DisplayListBuilder& aBuilder)
+				 WrPipelineId pipeline_id,
+				 WrBuiltDisplayListDescriptor dl_descriptor,
+				 uint8_t *dl_data,
+				 size_t dl_size,
+				 WrAuxiliaryListsDescriptor aux_descriptor,
+				 uint8_t *aux_data,
+				 size_t aux_size)
 {
-  wr_api_set_root_display_list(mWrApi, aBuilder.mWrState,
-                               aEpoch,
-                               aViewportSize.width, aViewportSize.height);
+    wr_api_set_root_display_list(mWrApi,
+				 aEpoch,
+				 aViewportSize.width, aViewportSize.height,
+                                 pipeline_id,
+                                 dl_descriptor,
+                                 dl_data,
+                                 dl_size,
+                                 aux_descriptor,
+                                 aux_data,
+                                 aux_size);
 }
 
 void
 WebRenderAPI::Readback(gfx::IntSize size,
                        uint8_t *buffer,
                        uint32_t buffer_size)
 {
     class Readback : public RendererEvent
@@ -204,34 +232,50 @@ WebRenderAPI::Readback(gfx::IntSize size
 }
 
 void
 WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
 {
   wr_api_set_root_pipeline(mWrApi, aPipeline);
 }
 
-ImageKey
-WebRenderAPI::AddImageBuffer(const ImageDescriptor& aDescritptor,
-                             Range<uint8_t> aBytes)
+void
+WebRenderAPI::AddImage(ImageKey key, const ImageDescriptor& aDescritptor,
+                       Range<uint8_t> aBytes)
 {
-  return ImageKey(wr_api_add_image(mWrApi,
-                                   &aDescritptor,
-                                   &aBytes[0], aBytes.length()));
+  wr_api_add_image(mWrApi,
+                   key,
+                   &aDescritptor,
+                   &aBytes[0], aBytes.length());
 }
 
-ImageKey
-WebRenderAPI::AddExternalImageHandle(gfx::IntSize aSize,
+void
+WebRenderAPI::AddExternalImageHandle(ImageKey key,
+                                     gfx::IntSize aSize,
                                      gfx::SurfaceFormat aFormat,
                                      uint64_t aHandle)
 {
   auto format = SurfaceFormatToWrImageFormat(aFormat).value();
-  return ImageKey(wr_api_add_external_image_texture(mWrApi,
-                                                    aSize.width, aSize.height, format,
-                                                    aHandle));
+  wr_api_add_external_image_handle(mWrApi,
+                                   key,
+                                   aSize.width, aSize.height, format,
+                                   aHandle);
+}
+
+void
+WebRenderAPI::AddExternalImageBuffer(ImageKey key,
+                                     gfx::IntSize aSize,
+                                     gfx::SurfaceFormat aFormat,
+                                     uint64_t aHandle)
+{
+  auto format = SurfaceFormatToWrImageFormat(aFormat).value();
+  wr_api_add_external_image_buffer(mWrApi,
+                                   key,
+                                   aSize.width, aSize.height, format,
+                                   aHandle);
 }
 
 void
 WebRenderAPI::UpdateImageBuffer(ImageKey aKey,
                                 const ImageDescriptor& aDescritptor,
                                 Range<uint8_t> aBytes)
 {
   wr_api_update_image(mWrApi,
@@ -241,20 +285,20 @@ WebRenderAPI::UpdateImageBuffer(ImageKey
 }
 
 void
 WebRenderAPI::DeleteImage(ImageKey aKey)
 {
   wr_api_delete_image(mWrApi, aKey);
 }
 
-wr::FontKey
-WebRenderAPI::AddRawFont(Range<uint8_t> aBytes)
+void
+WebRenderAPI::AddRawFont(wr::FontKey key, Range<uint8_t> aBytes)
 {
-  return wr::FontKey(wr_api_add_raw_font(mWrApi, &aBytes[0], aBytes.length()));
+  wr_api_add_raw_font(mWrApi, key, &aBytes[0], aBytes.length());
 }
 
 void
 WebRenderAPI::DeleteFont(wr::FontKey aKey)
 {
   printf("XXX - WebRender does not seem to implement deleting a font! Leaking it...\n");
 }
 
@@ -293,38 +337,51 @@ WebRenderAPI::SetProfilerEnabled(bool aE
 
 void
 WebRenderAPI::RunOnRenderThread(UniquePtr<RendererEvent> aEvent)
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mWrApi, event);
 }
 
-DisplayListBuilder::DisplayListBuilder(const LayerIntSize& aSize, PipelineId aId)
+DisplayListBuilder::DisplayListBuilder(PipelineId aId)
 {
   MOZ_COUNT_CTOR(DisplayListBuilder);
-  mWrState = wr_state_new(aSize.width, aSize.height, aId);
+  mWrState = wr_state_new(aId);
 }
 
 DisplayListBuilder::~DisplayListBuilder()
 {
   MOZ_COUNT_DTOR(DisplayListBuilder);
   wr_state_delete(mWrState);
 }
 
 void
 DisplayListBuilder::Begin(const LayerIntSize& aSize)
 {
   wr_dp_begin(mWrState, aSize.width, aSize.height);
 }
 
 void
-DisplayListBuilder::End(WebRenderAPI& aApi, Epoch aEpoch)
+DisplayListBuilder::End()
 {
-  wr_dp_end(mWrState, aApi.mWrApi, aEpoch);
+  wr_dp_end(mWrState);
+}
+
+void
+DisplayListBuilder::Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
+                             wr::VecU8& dl_data,
+                             WrAuxiliaryListsDescriptor& aux_descriptor,
+                             wr::VecU8& aux_data)
+{
+    wr_api_finalize_builder(mWrState,
+                            dl_descriptor,
+                            dl_data.inner,
+                            aux_descriptor,
+                            aux_data.inner);
 }
 
 void
 DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
                                         const WrRect& aOverflow,
                                         const WrImageMask* aMask,
                                         const float aOpacity,
                                         const gfx::Matrix4x4& aTransform,
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -24,57 +24,75 @@ class CompositorBridgeParentBase;
 }
 
 namespace wr {
 
 class DisplayListBuilder;
 class RendererOGL;
 class RendererEvent;
 
+
+
 class WebRenderAPI
 {
   NS_INLINE_DECL_REFCOUNTING(WebRenderAPI);
 
 public:
   /// This can be called on the compositor thread only.
   static already_AddRefed<WebRenderAPI> Create(bool aEnableProfiler,
                                                layers::CompositorBridgeParentBase* aBridge,
                                                RefPtr<widget::CompositorWidget>&& aWidget);
 
   wr::WindowId GetId() const { return mId; }
 
+  void GenerateFrame();
+
   void SetRootDisplayList(gfx::Color aBgColor,
-                          wr::Epoch aEpoch,
+                          Epoch aEpoch,
                           LayerSize aViewportSize,
-                          DisplayListBuilder& aBuilder);
+                          WrPipelineId pipeline_id,
+                          WrBuiltDisplayListDescriptor dl_descriptor,
+                          uint8_t *dl_data,
+                          size_t dl_size,
+                          WrAuxiliaryListsDescriptor aux_descriptor,
+                          uint8_t *aux_data,
+                          size_t aux_size);
 
   void SetRootPipeline(wr::PipelineId aPipeline);
 
-  wr::ImageKey AddImageBuffer(const ImageDescriptor& aDescriptor,
-                              Range<uint8_t> aBytes);
+  void AddImage(wr::ImageKey aKey,
+                const ImageDescriptor& aDescriptor,
+                Range<uint8_t> aBytes);
 
-  wr::ImageKey AddExternalImageHandle(gfx::IntSize aSize,
-                                      gfx::SurfaceFormat aFormat,
-                                      uint64_t aHandle);
+  void AddExternalImageHandle(ImageKey key,
+                              gfx::IntSize aSize,
+                              gfx::SurfaceFormat aFormat,
+                              uint64_t aHandle);
+
+  void AddExternalImageBuffer(ImageKey key,
+                              gfx::IntSize aSize,
+                              gfx::SurfaceFormat aFormat,
+                              uint64_t aHandle);
 
   void UpdateImageBuffer(wr::ImageKey aKey,
                          const ImageDescriptor& aDescriptor,
                          Range<uint8_t> aBytes);
 
   void DeleteImage(wr::ImageKey aKey);
 
-  wr::FontKey AddRawFont(Range<uint8_t> aBytes);
+  void AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes);
 
   void DeleteFont(wr::FontKey aKey);
 
   void SetProfilerEnabled(bool aEnabled);
 
   void RunOnRenderThread(UniquePtr<RendererEvent> aEvent);
   void Readback(gfx::IntSize aSize, uint8_t *aBuffer, uint32_t aBufferSize);
 
+  WrIdNamespace GetNamespace();
   GLint GetMaxTextureSize() const { return mMaxTextureSize; }
   bool GetUseANGLE() const { return mUseANGLE; }
 
 protected:
   WebRenderAPI(WrAPI* aRawApi, wr::WindowId aId, GLint aMaxTextureSize, bool aUseANGLE)
     : mWrApi(aRawApi)
     , mId(aId)
     , mMaxTextureSize(aMaxTextureSize)
@@ -91,24 +109,28 @@ protected:
   friend class DisplayListBuilder;
 };
 
 /// This is a simple C++ wrapper around WrState defined in the rust bindings.
 /// We may want to turn this into a direct wrapper on top of WebRenderFrameBuilder
 /// instead, so the interface may change a bit.
 class DisplayListBuilder {
 public:
-  DisplayListBuilder(const LayerIntSize& aSize, wr::PipelineId aId);
+  explicit DisplayListBuilder(wr::PipelineId aId);
   DisplayListBuilder(DisplayListBuilder&&) = default;
 
   ~DisplayListBuilder();
 
   void Begin(const LayerIntSize& aSize);
 
-  void End(WebRenderAPI& aApi, wr::Epoch aEpoch);
+  void End();
+  void Finalize(WrBuiltDisplayListDescriptor& dl_descriptor,
+                wr::VecU8& dl_data,
+                WrAuxiliaryListsDescriptor& aux_descriptor,
+                wr::VecU8& aux_data);
 
   void PushStackingContext(const WrRect& aBounds, // TODO: We should work with strongly typed rects
                            const WrRect& aOverflow,
                            const WrImageMask* aMask, // TODO: needs a wrapper.
                            const float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const WrMixBlendMode& aMixBlendMode);
 
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -5,16 +5,19 @@
 
 #ifndef GFX_WEBRENDERTYPES_H
 #define GFX_WEBRENDERTYPES_H
 
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/gfx/Types.h"
 #include "mozilla/gfx/Tools.h"
+#include "mozilla/Range.h"
+#include "Units.h"
+#include "nsStyleConsts.h"
 
 typedef mozilla::Maybe<WrImageMask> MaybeImageMask;
 
 namespace mozilla {
 namespace wr {
 
 typedef WrGradientExtendMode GradientExtendMode;
 typedef WrMixBlendMode MixBlendMode;
@@ -230,24 +233,68 @@ static inline WrRect ToWrRect(const gfx:
 static inline WrPoint ToWrPoint(const gfx::Point& point)
 {
   WrPoint p;
   p.x = point.x;
   p.y = point.y;
   return p;
 }
 
+static inline WrExternalImageId ToWrExternalImageId(uint64_t aID)
+{
+  WrExternalImageId id;
+  id.id = aID;
+  return id;
+}
+
+struct VecU8 {
+  WrVecU8 inner;
+  VecU8() {
+    inner.data = nullptr;
+    inner.capacity = 0;
+  }
+  VecU8(VecU8&) = delete;
+  VecU8(VecU8&& src) {
+    inner = src.inner;
+    src.inner.data = nullptr;
+    src.inner.capacity = 0;
+  }
+
+  ~VecU8() {
+    if (inner.data) {
+      wr_vec_u8_free(inner);
+    }
+  }
+};
+
 struct ByteBuffer
 {
   ByteBuffer(size_t aLength, uint8_t* aData)
     : mLength(aLength)
     , mData(aData)
     , mOwned(false)
   {}
 
+  // XXX: this is a bit of hack that assumes
+  // the allocators are the same
+  explicit ByteBuffer(VecU8&& vec)
+  {
+    if (vec.inner.capacity) {
+      mLength = vec.inner.length;
+      mData = vec.inner.data;
+      vec.inner.data = nullptr;
+      vec.inner.capacity = 0;
+      mOwned = true;
+    } else {
+      mOwned = false;
+      mData = nullptr;
+      mLength = 0;
+    }
+  }
+
   ByteBuffer()
     : mLength(0)
     , mData(nullptr)
     , mOwned(false)
   {}
 
   bool
   Allocate(size_t aLength)
@@ -278,12 +325,19 @@ struct ByteBuffer
           !(memcmp(mData, other.mData, mLength));
   }
 
   size_t mLength;
   uint8_t* mData;
   bool mOwned;
 };
 
+struct BuiltDisplayList {
+  VecU8 dl;
+  WrBuiltDisplayListDescriptor dl_desc;
+  VecU8 aux;
+  WrAuxiliaryListsDescriptor aux_desc;
+};
+
 } // namespace wr
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERTYPES_H */
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1,21 +1,23 @@
 use std::ffi::CString;
 use std::{mem, slice};
 use std::path::PathBuf;
 use std::os::raw::{c_void, c_char};
 use gleam::gl;
 use webrender_traits::{BorderSide, BorderStyle, BorderRadius, BorderWidths, BorderDetails, NormalBorder};
 use webrender_traits::{PipelineId, ClipRegion, PropertyBinding};
 use webrender_traits::{Epoch, ExtendMode, ColorF, GlyphInstance, GradientStop, ImageDescriptor};
-use webrender_traits::{FilterOp, ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind, MixBlendMode};
+use webrender_traits::{FilterOp, ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, MixBlendMode};
 use webrender_traits::{ExternalImageId, RenderApi, FontKey};
 use webrender_traits::{DeviceUintSize, ExternalEvent};
 use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
-use webrender_traits::{BoxShadowClipMode, LayerPixel, ServoScrollRootId};
+use webrender_traits::{BoxShadowClipMode, LayerPixel, ServoScrollRootId, IdNamespace};
+use webrender_traits::{BuiltDisplayListDescriptor, AuxiliaryListsDescriptor};
+use webrender_traits::{BuiltDisplayList, AuxiliaryLists};
 use webrender::renderer::{Renderer, RendererOptions};
 use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::{ApiRecordingReceiver, BinaryRecorder};
 use app_units::Au;
 use euclid::TypedPoint2D;
 
 extern crate webrender_traits;
 
@@ -43,31 +45,68 @@ macro_rules! check_ffi_type {
 
 check_ffi_type!(_pipeline_id_repr struct PipelineId as (u32, u32));
 check_ffi_type!(_image_key_repr struct ImageKey as (u32, u32));
 check_ffi_type!(_font_key_repr struct FontKey as (u32, u32));
 check_ffi_type!(_epoch_repr struct Epoch as (u32));
 check_ffi_type!(_image_format_repr enum ImageFormat as u32);
 check_ffi_type!(_border_style_repr enum BorderStyle as u32);
 check_ffi_type!(_image_rendering_repr enum ImageRendering as u32);
+check_ffi_type!(_namespace_id_repr struct IdNamespace as (u32));
 
 #[repr(C)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct WrWindowId(u64);
 
 #[repr(C)]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct WrImageDescriptor {
     pub format: ImageFormat,
     pub width: u32,
     pub height: u32,
     pub stride: u32,
     pub is_opaque: bool,
 }
 
+impl WrImageDescriptor {
+    pub fn to_descriptor(&self) -> ImageDescriptor {
+        ImageDescriptor {
+            width: self.width,
+            height: self.height,
+            stride: if self.stride != 0 { Some(self.stride) } else { None },
+            format: self.format,
+            is_opaque: self.is_opaque,
+            offset: 0,
+        }
+    }
+}
+
+#[repr(C)]
+pub struct WrVecU8 {
+    ptr: *mut u8,
+    length: usize,
+    capacity: usize
+}
+
+impl WrVecU8 {
+    fn to_vec(self) -> Vec<u8> {
+        unsafe { Vec::from_raw_parts(self.ptr, self.length, self.capacity) }
+    }
+    fn from_vec(mut v: Vec<u8>) -> WrVecU8 {
+        let w = WrVecU8{ptr: v.as_mut_ptr(), length: v.len(), capacity: v.capacity()};
+        mem::forget(v);
+        w
+    }
+}
+
+#[no_mangle]
+pub extern fn wr_vec_u8_free(v: WrVecU8) {
+    v.to_vec();
+}
+
 fn get_proc_address(glcontext_ptr: *mut c_void, name: &str) -> *const c_void{
 
     extern  {
         fn get_proc_address_from_glcontext(glcontext_ptr: *mut c_void, procname: *const c_char) -> *const c_void;
     }
 
     let symbol_name = CString::new(name).unwrap();
     let symbol = unsafe {
@@ -81,16 +120,17 @@ fn get_proc_address(glcontext_ptr: *mut 
     }
 
     symbol as *const _
 }
 
 extern  {
     fn is_in_compositor_thread() -> bool;
     fn is_in_render_thread() -> bool;
+    fn is_in_main_thread() -> bool;
 }
 
 #[no_mangle]
 pub extern fn wr_renderer_update(renderer: &mut Renderer) {
     renderer.update();
 }
 
 #[no_mangle]
@@ -116,65 +156,123 @@ pub unsafe extern fn wr_renderer_readbac
 }
 
 #[no_mangle]
 pub extern fn wr_renderer_set_profiler_enabled(renderer: &mut Renderer, enabled: bool) {
     renderer.set_profiler_enabled(enabled);
 }
 
 #[no_mangle]
+pub extern fn wr_renderer_set_external_image_handler(renderer: &mut Renderer,
+                                                     external_image_handler: *mut WrExternalImageHandler) {
+    if !external_image_handler.is_null() {
+        renderer.set_external_image_handler(Box::new(
+            unsafe {
+                WrExternalImageHandler {
+                    external_image_obj: (*external_image_handler).external_image_obj,
+                    lock_func: (*external_image_handler).lock_func,
+                    unlock_func: (*external_image_handler).unlock_func,
+                    release_func: (*external_image_handler).release_func,
+                }
+            }));
+    }
+}
+
+#[no_mangle]
 pub extern fn wr_renderer_current_epoch(renderer: &mut Renderer,
                                         pipeline_id: PipelineId,
                                         out_epoch: &mut Epoch) -> bool {
     if let Some(epoch) = renderer.current_epoch(pipeline_id) {
         *out_epoch = epoch;
         return true;
     }
     return false;
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_renderer_delete(renderer: *mut Renderer) {
     Box::from_raw(renderer);
 }
 
 #[no_mangle]
+pub unsafe extern fn wr_api_get_namespace(api: &mut RenderApi) -> IdNamespace
+{
+    api.id_namespace
+}
+
+#[no_mangle]
 pub unsafe extern fn wr_api_delete(api: *mut RenderApi) {
     let api = Box::from_raw(api);
     api.shut_down();
 }
 
 #[no_mangle]
+pub unsafe extern fn wr_api_finalize_builder(state: &mut WrState,
+                                             dl_descriptor: &mut BuiltDisplayListDescriptor,
+                                             dl_data: &mut WrVecU8,
+                                             aux_descriptor: &mut AuxiliaryListsDescriptor,
+                                             aux_data: &mut WrVecU8)
+{
+    let frame_builder = mem::replace(&mut state.frame_builder,
+                                     WebRenderFrameBuilder::new(state.pipeline_id));
+    let (_, dl, aux) = frame_builder.dl_builder.finalize();
+    //XXX: get rid of the copies here
+    *dl_data = WrVecU8::from_vec(dl.data().to_owned());
+    *dl_descriptor = dl.descriptor().clone();
+    *aux_data = WrVecU8::from_vec(aux.data().to_owned());
+    *aux_descriptor = aux.descriptor().clone();
+}
+
+#[no_mangle]
 pub unsafe extern fn wr_api_set_root_display_list(api: &mut RenderApi,
-                                                  state: &mut WrState,
                                                   epoch: Epoch,
                                                   viewport_width: f32,
-                                                  viewport_height: f32) {
+                                                  viewport_height: f32,
+                                                  pipeline_id: PipelineId,
+                                                  dl_descriptor: BuiltDisplayListDescriptor,
+                                                  dl_data: *mut u8,
+                                                  dl_size: usize,
+                                                  aux_descriptor: AuxiliaryListsDescriptor,
+                                                  aux_data: *mut u8,
+                                                  aux_size: usize) {
     let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
-    let frame_builder = mem::replace(&mut state.frame_builder,
-                                     WebRenderFrameBuilder::new(state.pipeline_id));
     // See the documentation of set_root_display_list in api.rs. I don't think
     // it makes a difference in gecko at the moment(until APZ is figured out)
     // but I suppose it is a good default.
     let preserve_frame_state = true;
-    //let (dl_builder, aux_builder) = fb.dl_builder.finalize();
+
+    let dl_slice = slice::from_raw_parts(dl_data, dl_size);
+    let mut dl_vec = Vec::new();
+    // XXX: see if we can get rid of the copy here
+    dl_vec.extend_from_slice(dl_slice);
+    let dl = BuiltDisplayList::from_data(dl_vec, dl_descriptor);
+
+    let aux_slice = slice::from_raw_parts(aux_data, aux_size);
+    let mut aux_vec = Vec::new();
+    // XXX: see if we can get rid of the copy here
+    aux_vec.extend_from_slice(aux_slice);
+    let aux = AuxiliaryLists::from_data(aux_vec, aux_descriptor);
+
     api.set_root_display_list(Some(root_background_color),
                               epoch,
                               LayoutSize::new(viewport_width, viewport_height),
-                              frame_builder.dl_builder,
+                              (pipeline_id, dl, aux),
                               preserve_frame_state);
-    api.generate_frame(None);
+}
+
+#[no_mangle]
+pub extern fn wr_api_generate_frame(api: &mut RenderApi) {
+  api.generate_frame(None);
 }
 
 // Call MakeCurrent before this.
 #[no_mangle]
 pub extern fn wr_window_new(window_id: WrWindowId,
                             gl_context: *mut c_void,
                             enable_profiler: bool,
-                            external_image_handler: *mut WrExternalImageHandler,
                             out_api: &mut *mut RenderApi,
                             out_renderer: &mut *mut Renderer) -> bool {
     assert!(unsafe { is_in_render_thread() });
 
     let recorder: Option<Box<ApiRecordingReceiver>> = if ENABLE_RECORDING {
         let name = format!("wr-record-{}.bin", window_id.0);
         Some(Box::new(BinaryRecorder::new(&PathBuf::from(name))))
     } else {
@@ -184,77 +282,64 @@ pub extern fn wr_window_new(window_id: W
     gl::load_with(|symbol| get_proc_address(gl_context, symbol));
     gl::clear_color(0.3, 0.0, 0.0, 1.0);
 
     let version = gl::get_string(gl::VERSION);
 
     println!("WebRender - OpenGL version new {}", version);
 
     let opts = RendererOptions {
-        enable_aa: false,
+        enable_aa: true,
+        enable_subpixel_aa: true,
         enable_profiler: enable_profiler,
         recorder: recorder,
         .. Default::default()
     };
 
-    let (mut renderer, sender) = match Renderer::new(opts) {
+    let (renderer, sender) = match Renderer::new(opts) {
         Ok((renderer, sender)) => { (renderer, sender) }
         Err(e) => {
             println!(" Failed to create a Renderer: {:?}", e);
             return false;
         }
     };
 
     renderer.set_render_notifier(Box::new(CppNotifier { window_id: window_id }));
 
-    if !external_image_handler.is_null() {
-        renderer.set_external_image_handler(Box::new(
-            unsafe {
-                WrExternalImageHandler {
-                    external_image_obj: (*external_image_handler).external_image_obj,
-                    lock_func: (*external_image_handler).lock_func,
-                    unlock_func: (*external_image_handler).unlock_func,
-                    release_func: (*external_image_handler).release_func,
-                }
-            }));
-    }
-
     *out_api = Box::into_raw(Box::new(sender.create_api()));
     *out_renderer = Box::into_raw(Box::new(renderer));
 
     return true;
 }
 
 #[no_mangle]
-pub extern fn wr_state_new(width: u32, height: u32, pipeline_id: PipelineId) -> *mut WrState {
-    assert!(unsafe { is_in_compositor_thread() });
+pub extern fn wr_state_new(pipeline_id: PipelineId) -> *mut WrState {
+    assert!(unsafe { is_in_main_thread() });
 
     let state = Box::new(WrState {
-        size: (width, height),
         pipeline_id: pipeline_id,
         z_index: 0,
         frame_builder: WebRenderFrameBuilder::new(pipeline_id),
     });
 
     Box::into_raw(state)
 }
 
 #[no_mangle]
 pub extern fn wr_state_delete(state:*mut WrState) {
-    assert!(unsafe { is_in_compositor_thread() });
+    assert!(unsafe { is_in_main_thread() });
 
     unsafe {
         Box::from_raw(state);
     }
 }
 
 #[no_mangle]
 pub extern fn wr_dp_begin(state: &mut WrState, width: u32, height: u32) {
-    assert!( unsafe { is_in_compositor_thread() });
-    state.size = (width, height);
+    assert!( unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.list.clear();
     state.z_index = 0;
 
     let bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0), LayoutSize::new(width as f32, height as f32));
 
     state.frame_builder.dl_builder.push_stacking_context(
         webrender_traits::ScrollPolicy::Scrollable,
         bounds,
@@ -263,33 +348,19 @@ pub extern fn wr_dp_begin(state: &mut Wr
         PropertyBinding::Value(LayoutTransform::identity()),
         LayoutTransform::identity(),
         webrender_traits::MixBlendMode::Normal,
         Vec::new(),
     );
 }
 
 #[no_mangle]
-pub extern fn wr_dp_end(state: &mut WrState, api: &mut RenderApi, epoch: u32) {
-    assert!( unsafe { is_in_compositor_thread() });
-    let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
-    let pipeline_id = state.pipeline_id;
-    let (width, height) = state.size;
-
+pub extern fn wr_dp_end(state: &mut WrState) {
+    assert!( unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.pop_stacking_context();
-
-    let fb = mem::replace(&mut state.frame_builder, WebRenderFrameBuilder::new(pipeline_id));
-
-    let preserve_frame_state = true;
-    api.set_root_display_list(Some(root_background_color),
-                              Epoch(epoch),
-                              LayoutSize::new(width as f32, height as f32),
-                              fb.dl_builder,
-                              preserve_frame_state);
-    api.generate_frame(None);
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_renderer_flush_rendered_epochs(renderer: &mut Renderer) -> *mut Vec<(PipelineId, Epoch)> {
     let map = renderer.flush_rendered_epochs();
     let pipeline_epochs = Box::new(map.into_iter().collect());
     return Box::into_raw(pipeline_epochs);
 }
@@ -365,33 +436,31 @@ impl WebRenderFrameBuilder {
         WebRenderFrameBuilder {
             root_pipeline_id: root_pipeline_id,
             dl_builder: webrender_traits::DisplayListBuilder::new(root_pipeline_id),
         }
     }
 }
 
 pub struct WrState {
-    size: (u32, u32),
     pipeline_id: PipelineId,
     z_index: i32,
     frame_builder: WebRenderFrameBuilder,
 }
 
-#[repr(C)]
-enum WrExternalImageType {
-    TEXTURE_HANDLE,
-
-    // TODO(Jerry): handle shmem or cpu raw buffers.
-    //// MEM_OR_SHMEM,
-}
+// TODO(Jerry): handle shmem or cpu raw buffers.
+//#[repr(C)]
+//enum WrExternalImageType {
+//    TextureHandle,
+//    MemOrShmem,
+//}
 
 #[repr(C)]
 struct WrExternalImageStruct {
-    image_type: WrExternalImageType,
+    //image_type: WrExternalImageType,
 
     // Texture coordinate
     u0: f32,
     v0: f32,
     u1: f32,
     v1: f32,
 
     // external buffer handle
@@ -413,26 +482,27 @@ pub struct WrExternalImageHandler {
     unlock_func: UnlockExternalImageCallback,
     release_func: ReleaseExternalImageCallback,
 }
 
 impl ExternalImageHandler for WrExternalImageHandler {
     fn lock(&mut self, id: ExternalImageId) -> ExternalImage {
         let image = (self.lock_func)(self.external_image_obj, id);
 
-        match image.image_type {
-            WrExternalImageType::TEXTURE_HANDLE =>
+        // TODO(Jerry): handle shmem or cpu raw buffers.
+        //match image.image_type {
+        //    WrExternalImageType::TextureHandle =>
                 ExternalImage {
                     u0: image.u0,
                     v0: image.v0,
                     u1: image.u1,
                     v1: image.v1,
                     source: ExternalImageSource::NativeTexture(image.handle)
-                },
-        }
+                }
+        //}
     }
 
     fn unlock(&mut self, id: ExternalImageId) {
         (self.unlock_func)(self.external_image_obj, id);
     }
 
     fn release(&mut self, id: ExternalImageId) {
         (self.release_func)(self.external_image_obj, id);
@@ -524,21 +594,21 @@ impl WrGradientExtendMode
             WrGradientExtendMode::Repeat => ExtendMode::Repeat,
         }
     }
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_stacking_context(state:&mut WrState, bounds: WrRect, overflow: WrRect, mask: *const WrImageMask, opacity: f32, transform: &LayoutTransform, mix_blend_mode: WrMixBlendMode)
 {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     state.z_index += 1;
 
     let bounds = bounds.to_rect();
-    let mut overflow = overflow.to_rect();
+    let overflow = overflow.to_rect();
     let mix_blend_mode = mix_blend_mode.to_mix_blend_mode();
     //println!("stacking context: {:?} {:?} {:?} {:?} {:?}", state.pipeline_id, bounds, overflow, mask, transform);
     // convert from the C type to the Rust type
     let mask = unsafe { mask.as_ref().map(|&WrImageMask{image, ref rect,repeat}| ImageMask{image: image, rect: rect.to_rect(), repeat: repeat}) };
 
     let clip_region2 = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], None);
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
 
@@ -557,17 +627,17 @@ pub extern fn wr_dp_push_stacking_contex
                                   filters);
     state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, ServoScrollRootId(1));
 
 }
 
 #[no_mangle]
 pub extern fn wr_dp_pop_stacking_context(state: &mut WrState)
 {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.pop_scroll_layer();
     state.frame_builder.dl_builder.pop_stacking_context();
     //println!("pop_stacking {:?}", state.pipeline_id);
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_scroll_layer(state: &mut WrState, bounds: WrRect, overflow: WrRect, mask: Option<&WrImageMask>)
 {
@@ -576,66 +646,72 @@ pub extern fn wr_dp_push_scroll_layer(st
     let mask = mask.map(|&WrImageMask{image, ref rect,repeat}| ImageMask{image: image, rect: rect.to_rect(), repeat: repeat});
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
     state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, ServoScrollRootId(1));
 }
 
 #[no_mangle]
 pub extern fn wr_dp_pop_scroll_layer(state: &mut WrState)
 {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     state.frame_builder.dl_builder.pop_scroll_layer();
 }
 
 #[no_mangle]
 pub extern fn wr_api_set_root_pipeline(api: &mut RenderApi, pipeline_id: PipelineId) {
     api.set_root_pipeline(pipeline_id);
     api.generate_frame(None);
 }
 
 #[no_mangle]
-pub extern fn wr_api_add_image(api: &mut RenderApi, descriptor: &WrImageDescriptor, bytes: * const u8, size: usize) -> ImageKey {
+pub extern fn wr_api_generate_image_key(api: &mut RenderApi) -> ImageKey
+{
+    api.generate_image_key()
+}
+
+#[no_mangle]
+pub extern fn wr_api_add_image(api: &mut RenderApi, image_key: ImageKey, descriptor: &WrImageDescriptor, bytes: * const u8, size: usize) {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
-    let image_key = api.generate_image_key();
     api.add_image(
         image_key,
-        ImageDescriptor {
-            width: descriptor.width,
-            height: descriptor.height,
-            stride: if descriptor.stride != 0 { Some(descriptor.stride) } else { None },
-            format: descriptor.format,
-            is_opaque: descriptor.is_opaque,
-        },
-        ImageData::new(bytes)
+        descriptor.to_descriptor(),
+        ImageData::new(bytes),
+        None
     );
-    image_key
 }
 
 #[no_mangle]
-pub extern fn wr_api_add_external_image_texture(api: &mut RenderApi, width: u32, height: u32, format: ImageFormat, external_image_id: u64) -> ImageKey {
+pub extern fn wr_api_add_external_image_handle(api: &mut RenderApi, image_key: ImageKey, width: u32, height: u32, format: ImageFormat, external_image_id: u64) {
     assert!( unsafe { is_in_compositor_thread() });
-    unimplemented!(); // TODO
-    //api.add_image(ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false}, ImageData::External(ExternalImageId(external_image_id)))
+    api.add_image(image_key,
+                  ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false, offset: 0},
+                  ImageData::ExternalHandle(ExternalImageId(external_image_id)),
+                  None
+    );
+}
+
+#[no_mangle]
+pub extern fn wr_api_add_external_image_buffer(api: &mut RenderApi, image_key: ImageKey, width: u32, height: u32, format: ImageFormat, external_image_id: u64) {
+    assert!( unsafe { is_in_compositor_thread() });
+    api.add_image(image_key,
+                  ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false, offset: 0},
+                  ImageData::ExternalBuffer(ExternalImageId(external_image_id)),
+                  None
+    );
 }
 
 #[no_mangle]
 pub extern fn wr_api_update_image(api: &mut RenderApi, key: ImageKey, descriptor: &WrImageDescriptor, bytes: * const u8, size: usize) {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
 
     api.update_image(
         key,
-        ImageDescriptor {
-            width: descriptor.width,
-            height: descriptor.height,
-            stride: if descriptor.stride != 0 { Some(descriptor.stride) } else { None },
-            format: descriptor.format,
-            is_opaque: descriptor.is_opaque,
-        },
+        descriptor.to_descriptor(),
         bytes
     );
 }
 #[no_mangle]
 pub extern fn wr_api_delete_image(api: &mut RenderApi, key: ImageKey) {
     assert!( unsafe { is_in_compositor_thread() });
     api.delete_image(key)
 }
@@ -645,48 +721,48 @@ pub extern fn wr_api_send_external_event
     assert!(unsafe { is_in_compositor_thread() });
 
     api.send_external_event(ExternalEvent::from_raw(evt));
 }
 
 
 #[no_mangle]
 pub extern fn wr_dp_push_rect(state: &mut WrState, rect: WrRect, clip: WrRect, color: WrColor) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
 
     state.frame_builder.dl_builder.push_rect(
                                     rect.to_rect(),
                                     clip_region,
                                     color.to_color());
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_box_shadow(state: &mut WrState, rect: WrRect, clip: WrRect,
                                     box_bounds: WrRect, offset: WrPoint, color: WrColor,
                                     blur_radius: f32, spread_radius: f32, border_radius: f32,
                                     clip_mode: WrBoxShadowClipMode) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
     state.frame_builder.dl_builder.push_box_shadow(rect.to_rect(),
                                                    clip_region,
                                                    box_bounds.to_rect(),
                                                    offset.to_point(),
                                                    color.to_color(),
                                                    blur_radius,
                                                    spread_radius,
                                                    border_radius,
                                                    clip_mode.to_box_shadow_clip_mode());
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_border(state: &mut WrState, rect: WrRect, clip: WrRect,
                                 top: WrBorderSide, right: WrBorderSide, bottom: WrBorderSide, left: WrBorderSide,
                                 radius: WrBorderRadius) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
     let border_widths = BorderWidths {
         left: left.width,
         top: top.width,
         right: right.width,
         bottom: bottom.width
     };
     let border_details = BorderDetails::Normal(NormalBorder {
@@ -703,17 +779,17 @@ pub extern fn wr_dp_push_border(state: &
                                     border_details);
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_linear_gradient(state: &mut WrState, rect: WrRect, clip: WrRect,
                                          start_point: WrPoint, end_point: WrPoint,
                                          stops: * const WrGradientStop, stops_count: usize,
                                          extend_mode: WrGradientExtendMode) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
 
     let stops = WrGradientStop::to_gradient_stops(unsafe { slice::from_raw_parts(stops, stops_count) });
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
 
     state.frame_builder.dl_builder.push_gradient(
                                     rect.to_rect(),
                                     clip_region,
                                     start_point.to_point(),
@@ -724,17 +800,17 @@ pub extern fn wr_dp_push_linear_gradient
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_radial_gradient(state: &mut WrState, rect: WrRect, clip: WrRect,
                                          start_center: WrPoint, end_center: WrPoint,
                                          start_radius: f32, end_radius: f32,
                                          stops: * const WrGradientStop, stops_count: usize,
                                          extend_mode: WrGradientExtendMode) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
 
     let stops = WrGradientStop::to_gradient_stops(unsafe { slice::from_raw_parts(stops, stops_count) });
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
 
     state.frame_builder.dl_builder.push_radial_gradient(
                                     rect.to_rect(),
                                     clip_region,
                                     start_center.to_point(),
@@ -743,17 +819,17 @@ pub extern fn wr_dp_push_radial_gradient
                                     end_radius,
                                     stops,
                                     extend_mode.to_gradient_extend_mode()
                                     );
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_iframe(state: &mut WrState, rect: WrRect, clip: WrRect, pipeline_id: PipelineId) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
 
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(),
                                                                      Vec::new(),
                                                                      None);
     state.frame_builder.dl_builder.push_iframe(rect.to_rect(),
                                                clip_region,
                                                pipeline_id);
 }
@@ -893,17 +969,17 @@ impl WrImageMask
     pub fn to_image_mask(&self) -> ImageMask
     {
         ImageMask { image: self.image, rect: self.rect.to_rect(), repeat: self.repeat }
     }
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_image(state:&mut WrState, bounds: WrRect, clip : WrRect, mask: *const WrImageMask, filter: ImageRendering, key: ImageKey) {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
 
     let bounds = bounds.to_rect();
     let clip = clip.to_rect();
 
     //println!("push_image bounds {:?} clip {:?}", bounds, clip);
     // convert from the C type to the Rust type, mapping NULL to None
     let mask = unsafe { mask.as_ref().map(|m| m.to_image_mask()) };
     let image_rendering = filter;
@@ -913,46 +989,51 @@ pub extern fn wr_dp_push_image(state:&mu
         bounds,
         clip_region,
         bounds.size,
         bounds.size,
         image_rendering,
         key
     );
 }
+#[no_mangle]
+pub extern fn wr_api_generate_font_key(api: &mut RenderApi) -> FontKey
+{
+    api.generate_font_key()
+}
 
 #[no_mangle]
 pub extern fn wr_api_add_raw_font(api: &mut RenderApi,
+                                  key: FontKey,
                                   font_buffer: *mut u8,
-                                  buffer_size: usize) -> FontKey
+                                  buffer_size: usize)
 {
     assert!( unsafe { is_in_compositor_thread() });
 
     let font_slice = unsafe {
         slice::from_raw_parts(font_buffer, buffer_size as usize)
     };
     let mut font_vector = Vec::new();
     font_vector.extend_from_slice(font_slice);
 
-    let font_key = api.generate_font_key();
-    api.add_raw_font(font_key, font_vector);
-    font_key
+    api.add_raw_font(key, font_vector);
 }
 
+
 #[no_mangle]
 pub extern fn wr_dp_push_text(state: &mut WrState,
                               bounds: WrRect,
                               clip: WrRect,
                               color: WrColor,
                               font_key: FontKey,
                               glyphs: *mut GlyphInstance,
                               glyph_count: u32,
                               glyph_size: f32)
 {
-    assert!( unsafe { is_in_compositor_thread() });
+    assert!( unsafe { is_in_main_thread() });
 
     let glyph_slice = unsafe {
         slice::from_raw_parts(glyphs, glyph_count as usize)
     };
     let mut glyph_vector = Vec::new();
     glyph_vector.extend_from_slice(&glyph_slice);
 
     let colorf = ColorF::new(color.r, color.g, color.b, color.a);
--- a/gfx/webrender_bindings/src/lib.rs
+++ b/gfx/webrender_bindings/src/lib.rs
@@ -1,21 +1,14 @@
 /* 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/. */
 
+#![deny(warnings)]
+
 extern crate webrender;
 extern crate webrender_traits;
 extern crate euclid;
 extern crate app_units;
 extern crate gleam;
-extern crate fnv;
-
-#[cfg(target_os="macos")]
-extern crate core_foundation;
-
-#[cfg(target_os="windows")]
-extern crate kernel32;
-#[cfg(target_os="windows")]
-extern crate winapi;
 
 #[allow(non_snake_case)]
 pub mod bindings;
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -2,19 +2,19 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 WR_h
 #define WR_h
 
-#include "mozilla/layers/LayersMessages.h"
 #include "mozilla/gfx/Types.h"
-
+#include "nsTArray.h"
+#include "mozilla/gfx/Point.h"
 // ---
 #define WR_DECL_FFI_1(WrType, t1)                 \
 struct WrType {                                   \
   t1 mHandle;                                     \
   bool operator==(const WrType& rhs) const {      \
     return mHandle == rhs.mHandle;                \
   }                                               \
   bool operator!=(const WrType& rhs) const {      \
@@ -44,30 +44,32 @@ struct WrType {                         
 
 
 extern "C" {
 
 // If you modify any of the declarations below, make sure to update the
 // serialization code in WebRenderMessageUtils.h and the rust bindings.
 
 WR_DECL_FFI_1(WrEpoch, uint32_t)
+WR_DECL_FFI_1(WrIdNamespace, uint32_t)
 WR_DECL_FFI_1(WrWindowId, uint64_t)
 
 WR_DECL_FFI_2(WrPipelineId, uint32_t, uint32_t)
 WR_DECL_FFI_2(WrImageKey, uint32_t, uint32_t)
 WR_DECL_FFI_2(WrFontKey, uint32_t, uint32_t)
 
 #undef WR_DECL_FFI_1
 #undef WR_DECL_FFI_2
 
 // ----
 // Functions invoked from Rust code
 // ----
 
 bool is_in_compositor_thread();
+bool is_in_main_thread();
 bool is_in_render_thread();
 void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname);
 
 // -----
 // Enums used in C++ code with corresponding enums in Rust code
 // -----
 enum class WrBoxShadowClipMode: uint32_t {
   None,
@@ -108,22 +110,24 @@ enum class WrImageRendering: uint32_t
 {
   Auto        = 0,
   CrispEdges  = 1,
   Pixelated   = 2,
 
   Sentinel /* this must be last, for IPC serialization purposes */
 };
 
-enum class WrExternalImageIdType
-{
-  TEXTURE_HANDLE, // Currently, we only support gl texture handle.
-  // TODO(Jerry): handle shmem or cpu raw buffers.
-  //// MEM_OR_SHMEM,
-};
+// TODO(Jerry): handle shmem or cpu raw buffers.
+//enum class WrExternalImageIdType: uint32_t
+//{
+//  TextureHandle = 0,
+//  MemOrShmem    = 1,
+//
+//  Sentinel /* this must be last, for IPC serialization purposes */
+//};
 
 enum class WrMixBlendMode: uint32_t
 {
   Normal      = 0,
   Multiply    = 1,
   Screen      = 2,
   Overlay     = 3,
   Darken      = 4,
@@ -293,58 +297,75 @@ struct WrImageMask
   bool repeat;
 
   bool operator==(const WrImageMask& aRhs) const
   {
     return image == aRhs.image && rect == aRhs.rect && repeat == aRhs.repeat;
   }
 };
 
-struct WrExternalImageIdId
+struct WrExternalImageId
 {
   WrImageIdType id;
 };
 
-struct WrExternalImageId
+struct WrExternalImage
 {
-  WrExternalImageIdType type;
+  //WrExternalImageIdType type;
 
   // Texture coordinate
   float u0, v0;
   float u1, v1;
 
   // external buffer handle
   uint32_t handle;
 
   // TODO(Jerry): handle shmem or cpu raw buffers.
   //// shmem or memory buffer
   //// uint8_t* buff;
   //// size_t size;
 };
 
-typedef WrExternalImageId (*LockExternalImageCallback)(void*, WrExternalImageIdId);
-typedef void (*UnlockExternalImageCallback)(void*, WrExternalImageIdId);
-typedef void (*ReleaseExternalImageCallback)(void*, WrExternalImageIdId);
+typedef WrExternalImage (*LockExternalImageCallback)(void*, WrExternalImageId);
+typedef void (*UnlockExternalImageCallback)(void*, WrExternalImageId);
+typedef void (*ReleaseExternalImageCallback)(void*, WrExternalImageId);
 
-struct WrExternalImageIdHandler
+struct WrExternalImageHandler
 {
-  void* ExternalImageObj;
+  void* renderer_obj;
   LockExternalImageCallback lock_func;
   UnlockExternalImageCallback unlock_func;
   ReleaseExternalImageCallback release_func;
 };
 
 struct WrImageDescriptor {
     WrImageFormat format;
     uint32_t width;
     uint32_t height;
     uint32_t stride;
     bool is_opaque;
 };
 
+struct WrBuiltDisplayListDescriptor {
+    size_t display_list_items_size;
+};
+
+struct WrAuxiliaryListsDescriptor {
+    size_t gradient_stops_size;
+    size_t complex_clip_regions_size;
+    size_t filters_size;
+    size_t glyph_instances_size;
+};
+
+struct WrVecU8 {
+    uint8_t *data;
+    size_t length;
+    size_t capacity;
+};
+
 // -----
 // Functions exposed by the webrender API
 // -----
 
 // Some useful defines to stub out webrender binding functions for when we
 // build gecko without webrender. We try to tell the compiler these functions
 // are unreachable in that case, but VC++ emits a warning if it finds any
 // unreachable functions invoked from destructors. That warning gets turned into
@@ -363,16 +384,21 @@ struct WrImageDescriptor {
 
 // Structs defined in Rust, but opaque to C++ code.
 struct WrRenderedEpochs;
 struct WrRenderer;
 struct WrState;
 struct WrAPI;
 
 WR_INLINE void
+wr_renderer_set_external_image_handler(WrRenderer* renderer,
+                                       WrExternalImageHandler* handler)
+WR_FUNC;
+
+WR_INLINE void
 wr_renderer_update(WrRenderer* renderer)
 WR_FUNC;
 
 WR_INLINE void
 wr_renderer_render(WrRenderer* renderer, uint32_t width, uint32_t height)
 WR_FUNC;
 
 WR_INLINE void
@@ -398,68 +424,77 @@ wr_rendered_epochs_next(WrRenderedEpochs
 
 WR_INLINE void
 wr_rendered_epochs_delete(WrRenderedEpochs* pipeline_epochs) WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE bool
 wr_window_new(WrWindowId window_id,
               void* aGLContext,
               bool enable_profiler,
-              WrExternalImageIdHandler* handler,
               WrAPI** out_api,
               WrRenderer** out_renderer)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_delete(WrAPI* api)
 WR_DESTRUCTOR_SAFE_FUNC;
 
-WR_INLINE WrImageKey
-wr_api_add_image(WrAPI* api, const WrImageDescriptor* descriptor, uint8_t *buffer, size_t buffer_size)
+WR_INLINE void
+wr_api_add_image(WrAPI* api, WrImageKey key, const WrImageDescriptor* descriptor, uint8_t *buffer, size_t buffer_size)
 WR_FUNC;
 
-WR_INLINE WrImageKey
-wr_api_add_external_image_texture(WrAPI* api, uint32_t width, uint32_t height,
-                                  WrImageFormat format, uint64_t external_image_id)
+WR_INLINE void
+wr_api_add_external_image_handle(WrAPI* api, WrImageKey key, uint32_t width, uint32_t height,
+                                 WrImageFormat format, uint64_t external_image_id)
 WR_FUNC;
 
-//TODO(Jerry): handle shmem in WR
-//// WR_INLINE WrImageKey
-//// wr_api_add_external_image_buffer(WrAPI* api, uint32_t width, uint32_t height, uint32_t stride,
-////                                  WrImageFormat format, uint8_t *bytes, size_t size)
-//// WR_FUNC;
+WR_INLINE void
+wr_api_add_external_image_buffer(WrAPI* api, WrImageKey key, uint32_t width, uint32_t height,
+                                 WrImageFormat format, uint64_t external_image_id)
+WR_FUNC;
 
 WR_INLINE void
 wr_api_update_image(WrAPI* api, WrImageKey key,
                     const WrImageDescriptor* descriptor,
                     uint8_t *bytes, size_t size)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_delete_image(WrAPI* api, WrImageKey key)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_set_root_pipeline(WrAPI* api, WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_set_root_display_list(WrAPI* api, WrState* state, WrEpoch epoch, float w, float h)
+wr_api_set_root_display_list(WrAPI* api, WrEpoch epoch, float w, float h,
+                             WrPipelineId pipeline_id,
+                             WrBuiltDisplayListDescriptor dl_descriptor,
+                             uint8_t *dl_data,
+                             size_t dl_size,
+                             WrAuxiliaryListsDescriptor aux_descriptor,
+                             uint8_t *aux_data,
+                             size_t aux_size)
+WR_FUNC;
+
+WR_INLINE void
+wr_api_generate_frame(WrAPI* api)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_send_external_event(WrAPI* api, uintptr_t evt)
 WR_DESTRUCTOR_SAFE_FUNC;
 
-WR_INLINE WrFontKey
-wr_api_add_raw_font(WrAPI* api, uint8_t* font_buffer, size_t buffer_size)
+WR_INLINE void
+wr_api_add_raw_font(WrAPI* api, WrFontKey key, uint8_t* font_buffer, size_t buffer_size)
 WR_FUNC;
 
 WR_INLINE WrState*
-wr_state_new(uint32_t width, uint32_t height, WrPipelineId pipeline_id)
+wr_state_new(WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
 wr_state_delete(WrState* state)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE void
 wr_dp_push_stacking_context(WrState *wrState, WrRect bounds,
@@ -483,17 +518,17 @@ wr_dp_pop_scroll_layer(WrState *wrState)
 WR_FUNC;
 
 
 WR_INLINE void
 wr_dp_begin(WrState* wrState, uint32_t width, uint32_t height)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_end(WrState* builder, WrAPI* api, WrEpoch epoch)
+wr_dp_end(WrState* wrState)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_rect(WrState* wrState, WrRect bounds, WrRect clip,
                 WrColor color)
 WR_FUNC;
 
 WR_INLINE void
@@ -541,13 +576,29 @@ WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_box_shadow(WrState* wrState, WrRect rect, WrRect clip,
                       WrRect box_bounds, WrPoint offset, WrColor color,
                       float blur_radius, float spread_radius, float border_radius,
                       WrBoxShadowClipMode clip_mode)
 WR_FUNC;
 
+WR_INLINE WrIdNamespace
+wr_api_get_namespace(WrAPI* api)
+WR_FUNC;
+
+WR_INLINE void
+wr_api_finalize_builder(WrState* wrState,
+                        WrBuiltDisplayListDescriptor& dl_descriptor,
+                        WrVecU8& dl_data,
+                        WrAuxiliaryListsDescriptor& aux_descriptor,
+                        WrVecU8& aux_data)
+WR_FUNC;
+
+WR_INLINE void
+wr_vec_u8_free(WrVecU8 dl_data)
+WR_FUNC;
+
 #undef WR_FUNC
 #undef WR_DESTRUCTOR_SAFE_FUNC
 } // extern "C"
 
 #endif // WR_h
--- a/gfx/webrender_traits/Cargo.toml
+++ b/gfx/webrender_traits/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 name = "webrender_traits"
-version = "0.19.0"
+version = "0.20.0"
 authors = ["Glenn Watson <gw@intuitionlibrary.com>"]
 license = "MPL-2.0"
 repository = "https://github.com/servo/webrender"
 build = "build.rs"
 
 [features]
 default = ["codegen"]
 nightly = ["euclid/unstable", "serde/unstable"]
--- a/gfx/webrender_traits/src/api.rs
+++ b/gfx/webrender_traits/src/api.rs
@@ -4,18 +4,19 @@
 
 use byteorder::{LittleEndian, WriteBytesExt};
 use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
 use offscreen_gl_context::{GLContextAttributes, GLLimits};
 use std::cell::Cell;
 use {ApiMsg, ColorF, DisplayListBuilder, Epoch, ImageDescriptor};
 use {FontKey, IdNamespace, ImageKey, NativeFontHandle, PipelineId};
 use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId};
-use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};
+use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand, TileSize};
 use {DeviceIntSize, DynamicProperties, LayoutPoint, LayoutSize, WorldPoint, PropertyBindingKey, PropertyBindingId};
+use {BuiltDisplayList, AuxiliaryLists};
 use VRCompositorCommand;
 use ExternalEvent;
 use std::marker::PhantomData;
 
 impl RenderApiSender {
     pub fn new(api_sender: MsgSender<ApiMsg>,
                payload_sender: PayloadSender)
                -> RenderApiSender {
@@ -87,18 +88,19 @@ impl RenderApi {
         let new_id = self.next_unique_id();
         ImageKey::new(new_id.0, new_id.1)
     }
 
     /// Adds an image identified by the `ImageKey`.
     pub fn add_image(&self,
                      key: ImageKey,
                      descriptor: ImageDescriptor,
-                     data: ImageData) {
-        let msg = ApiMsg::AddImage(key, descriptor, data);
+                     data: ImageData,
+                     tiling: Option<TileSize>) {
+        let msg = ApiMsg::AddImage(key, descriptor, data, tiling);
         self.api_sender.send(msg).unwrap();
     }
 
     /// Updates a specific image.
     ///
     /// Currently doesn't support changing dimensions or format by updating.
     // TODO: Support changing dimensions (and format) during image update?
     pub fn update_image(&self,
@@ -151,20 +153,18 @@ impl RenderApi {
     ///                           id, this setting determines if frame state (such as scrolling
     ///                           position) should be preserved for this new display list.
     ///
     /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
     pub fn set_root_display_list(&self,
                                  background_color: Option<ColorF>,
                                  epoch: Epoch,
                                  viewport_size: LayoutSize,
-                                 builder: DisplayListBuilder,
+                                 (pipeline_id, display_list, auxiliary_lists): (PipelineId, BuiltDisplayList, AuxiliaryLists),
                                  preserve_frame_state: bool) {
-        let pipeline_id = builder.pipeline_id;
-        let (display_list, auxiliary_lists) = builder.finalize();
         let msg = ApiMsg::SetRootDisplayList(background_color,
                                              epoch,
                                              pipeline_id,
                                              viewport_size,
                                              display_list.descriptor().clone(),
                                              *auxiliary_lists.descriptor(),
                                              preserve_frame_state);
         self.api_sender.send(msg).unwrap();
--- a/gfx/webrender_traits/src/display_list.rs
+++ b/gfx/webrender_traits/src/display_list.rs
@@ -3,28 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use std::mem;
 use std::slice;
 use {AuxiliaryLists, AuxiliaryListsDescriptor, BorderDisplayItem};
 use {BoxShadowClipMode, BoxShadowDisplayItem, BuiltDisplayList};
 use {BuiltDisplayListDescriptor, ClipRegion, ComplexClipRegion, ColorF};
-use {DisplayItem, DisplayListMode, ExtendMode, FilterOp, YuvColorSpace};
+use {DisplayItem, ExtendMode, FilterOp, YuvColorSpace};
 use {FontKey, GlyphInstance, GradientDisplayItem, RadialGradientDisplayItem, GradientStop, IframeDisplayItem};
 use {ImageDisplayItem, ImageKey, ImageMask, ImageRendering, ItemRange, MixBlendMode, PipelineId};
 use {PushScrollLayerItem, PushStackingContextDisplayItem, RectangleDisplayItem, ScrollLayerId};
 use {ScrollPolicy, ServoScrollRootId, SpecificDisplayItem, StackingContext, TextDisplayItem};
 use {WebGLContextId, WebGLDisplayItem, YuvImageDisplayItem};
 use {LayoutTransform, LayoutPoint, LayoutRect, LayoutSize};
 use {BorderDetails, BorderWidths, GlyphOptions, PropertyBinding};
 
 impl BuiltDisplayListDescriptor {
     pub fn size(&self) -> usize {
-        self.display_list_items_size + self.display_items_size
+        self.display_list_items_size
     }
 }
 
 impl BuiltDisplayList {
     pub fn from_data(data: Vec<u8>, descriptor: BuiltDisplayListDescriptor) -> BuiltDisplayList {
         BuiltDisplayList {
             data: data,
             descriptor: descriptor,
@@ -43,27 +43,25 @@ impl BuiltDisplayList {
         unsafe {
             convert_blob_to_pod(&self.data[0..self.descriptor.display_list_items_size])
         }
     }
 }
 
 #[derive(Clone)]
 pub struct DisplayListBuilder {
-    pub mode: DisplayListMode,
     pub list: Vec<DisplayItem>,
     auxiliary_lists_builder: AuxiliaryListsBuilder,
     pub pipeline_id: PipelineId,
     next_scroll_layer_id: usize,
 }
 
 impl DisplayListBuilder {
     pub fn new(pipeline_id: PipelineId) -> DisplayListBuilder {
         DisplayListBuilder {
-            mode: DisplayListMode::Default,
             list: Vec::new(),
             auxiliary_lists_builder: AuxiliaryListsBuilder::new(),
             pipeline_id: pipeline_id,
             next_scroll_layer_id: 0,
         }
     }
 
     pub fn print_display_list(&mut self) {
@@ -360,26 +358,25 @@ impl DisplayListBuilder {
     pub fn new_clip_region(&mut self,
                            rect: &LayoutRect,
                            complex: Vec<ComplexClipRegion>,
                            image_mask: Option<ImageMask>)
                            -> ClipRegion {
         ClipRegion::new(rect, complex, image_mask, &mut self.auxiliary_lists_builder)
     }
 
-    pub fn finalize(self) -> (BuiltDisplayList, AuxiliaryLists) {
+    pub fn finalize(self) -> (PipelineId, BuiltDisplayList, AuxiliaryLists) {
         unsafe {
             let blob = convert_pod_to_blob(&self.list).to_vec();
             let display_list_items_size = blob.len();
 
-            (BuiltDisplayList {
+            (self.pipeline_id,
+             BuiltDisplayList {
                  descriptor: BuiltDisplayListDescriptor {
-                     mode: self.mode,
                      display_list_items_size: display_list_items_size,
-                     display_items_size: 0,
                  },
                  data: blob,
              },
              self.auxiliary_lists_builder.finalize())
         }
     }
 }
 
--- a/gfx/webrender_traits/src/types.rs
+++ b/gfx/webrender_traits/src/types.rs
@@ -19,24 +19,26 @@ use std::sync::Arc;
 #[cfg(target_os = "windows")] use dwrote::FontDescriptor;
 
 #[derive(Debug, Copy, Clone)]
 pub enum RendererKind {
     Native,
     OSMesa,
 }
 
+pub type TileSize = u16;
+
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
     AddRawFont(FontKey, Vec<u8>),
     AddNativeFont(FontKey, NativeFontHandle),
     /// Gets the glyph dimensions
     GetGlyphDimensions(Vec<GlyphKey>, MsgSender<Vec<Option<GlyphDimensions>>>),
     /// Adds an image from the resource cache.
-    AddImage(ImageKey, ImageDescriptor, ImageData),
+    AddImage(ImageKey, ImageDescriptor, ImageData, Option<TileSize>),
     /// Updates the the resource cache with the new image data.
     UpdateImage(ImageKey, ImageDescriptor, Vec<u8>),
     /// Drops an image from the resource cache.
     DeleteImage(ImageKey),
     CloneApi(MsgSender<IdNamespace>),
     /// Supplies a new frame to WebRender.
     ///
     /// After receiving this message, WebRender will read the display list, followed by the
@@ -161,16 +163,17 @@ pub struct AuxiliaryLists {
     data: Vec<u8>,
     descriptor: AuxiliaryListsDescriptor,
 }
 
 /// Describes the memory layout of the auxiliary lists.
 ///
 /// Auxiliary lists consist of some number of gradient stops, complex clip regions, filters, and
 /// glyph instances, in that order.
+#[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Serialize)]
 pub struct AuxiliaryListsDescriptor {
     gradient_stops_size: usize,
     complex_clip_regions_size: usize,
     filters_size: usize,
     glyph_instances_size: usize,
 }
 
@@ -282,24 +285,21 @@ pub struct BuiltDisplayList {
     data: Vec<u8>,
     descriptor: BuiltDisplayListDescriptor,
 }
 
 /// Describes the memory layout of a display list.
 ///
 /// A display list consists of some number of display list items, followed by a number of display
 /// items.
+#[repr(C)]
 #[derive(Copy, Clone, Deserialize, Serialize)]
 pub struct BuiltDisplayListDescriptor {
-    pub mode: DisplayListMode,
-
     /// The size in bytes of the display list items in this display list.
     display_list_items_size: usize,
-    /// The size in bytes of the display items in this display list.
-    display_items_size: usize,
 }
 
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ColorF {
     pub r: f32,
     pub g: f32,
     pub b: f32,
@@ -358,19 +358,37 @@ impl ColorU {
 }
 
 #[derive(Copy, Clone, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ImageDescriptor {
     pub format: ImageFormat,
     pub width: u32,
     pub height: u32,
     pub stride: Option<u32>,
+    pub offset: u32,
     pub is_opaque: bool,
 }
 
+impl ImageDescriptor {
+    pub fn new(width: u32, height: u32, format: ImageFormat, is_opaque: bool) -> Self {
+        ImageDescriptor {
+            width: width,
+            height: height,
+            format: format,
+            stride: None,
+            offset: 0,
+            is_opaque: is_opaque,
+        }
+    }
+
+    pub fn compute_stride(&self) -> u32 {
+        self.stride.unwrap_or(self.width * self.format.bytes_per_pixel().unwrap())
+    }
+}
+
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ImageMask {
     pub image: ImageKey,
     pub rect: LayoutRect,
     pub repeat: bool,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@@ -390,24 +408,16 @@ pub struct ComplexClipRegion {
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct DisplayItem {
     pub item: SpecificDisplayItem,
     pub rect: LayoutRect,
     pub clip: ClipRegion,
 }
 
-#[repr(u32)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
-pub enum DisplayListMode {
-    Default                 = 0,
-    PseudoFloat             = 1,
-    PseudoPositionedContent = 2,
-}
-
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
 pub struct Epoch(pub u32);
 
 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
 pub enum ExtendMode {
     Clamp,
     Repeat,
--- a/gfx/webrender_traits/src/units.rs
+++ b/gfx/webrender_traits/src/units.rs
@@ -68,16 +68,20 @@ pub type ScrollLayerSize = TypedSize2D<f
 #[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct WorldPixel;
 
 pub type WorldRect = TypedRect<f32, WorldPixel>;
 pub type WorldPoint = TypedPoint2D<f32, WorldPixel>;
 pub type WorldSize = TypedSize2D<f32, WorldPixel>;
 pub type WorldPoint4D = TypedPoint4D<f32, WorldPixel>;
 
+/// Offset in number of tiles.
+#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
+pub struct Tiles;
+pub type TileOffset = TypedPoint2D<u16, Tiles>;
 
 pub type LayoutTransform = TypedMatrix4D<f32, LayoutPixel, LayoutPixel>;
 pub type LayerTransform = TypedMatrix4D<f32, LayerPixel, LayerPixel>;
 pub type LayerToScrollTransform = TypedMatrix4D<f32, LayerPixel, ScrollLayerPixel>;
 pub type ScrollToLayerTransform = TypedMatrix4D<f32, ScrollLayerPixel, LayerPixel>;
 pub type LayerToWorldTransform = TypedMatrix4D<f32, LayerPixel, WorldPixel>;
 pub type WorldToLayerTransform = TypedMatrix4D<f32, WorldPixel, LayerPixel>;
 pub type ScrollToWorldTransform = TypedMatrix4D<f32, ScrollLayerPixel, WorldPixel>;
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -31,16 +31,17 @@
 #include "nsBidiUtils.h"
 #include "CounterStyleManager.h"
 
 #include "imgIContainer.h"
 #include "ImageLayers.h"
 #include "imgRequestProxy.h"
 #include "nsIURI.h"
 #include "SVGImageContext.h"
+#include "mozilla/layers/WebRenderBridgeChild.h"
 
 #include <algorithm>
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
 using namespace mozilla;
@@ -223,16 +224,17 @@ public:
     , mListStyleType(listStyleType)
   {
     MOZ_ASSERT(IsTextType());
   }
 
   void
   CreateWebRenderCommands(nsDisplayItem* aItem,
                           nsTArray<layers::WebRenderCommand>& aCommands,
+                          nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                           layers::WebRenderDisplayItemLayer* aLayer);
 
   DrawResult
   Paint(nsRenderingContext& aRenderingContext, nsPoint aPt,
         const nsRect& aDirtyRect, uint32_t aFlags,
         bool aDisableSubpixelAA, nsIFrame* aFrame);
 
   bool
@@ -269,16 +271,17 @@ public:
 
   bool
   IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags);
 
 private:
   void
   CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
                                   nsTArray<layers::WebRenderCommand>& aCommands,
+                                  nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                   layers::WebRenderDisplayItemLayer* aLayer);
 
   void
   CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
                                  nsTArray<layers::WebRenderCommand>& aCommands,
                                  layers::WebRenderDisplayItemLayer* aLayer);
 
   void
@@ -310,20 +313,21 @@ private:
 
   // Store the type of list-style-type.
   int32_t mListStyleType;
 };
 
 void
 BulletRenderer::CreateWebRenderCommands(nsDisplayItem* aItem,
                                         nsTArray<layers::WebRenderCommand>& aCommands,
+                                        nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                         layers::WebRenderDisplayItemLayer* aLayer)
 {
   if (IsImageType()) {
-    CreateWebRenderCommandsForImage(aItem, aCommands, aLayer);
+    CreateWebRenderCommandsForImage(aItem, aCommands, aParentCommands, aLayer);
   } else if (IsPathType()) {
     CreateWebRenderCommandsForPath(aItem, aCommands, aLayer);
   } else {
     MOZ_ASSERT(IsTextType());
     CreateWebRenderCommandsForText(aItem, aCommands, aLayer);
   }
 }
 
@@ -427,16 +431,17 @@ BulletRenderer::IsImageContainerAvailabl
   MOZ_ASSERT(IsImageType());
 
   return mImage->IsImageContainerAvailable(aManager, aFlags);
 }
 
 void
 BulletRenderer::CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
                                                 nsTArray<layers::WebRenderCommand>& aCommands,
+                                                nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                                 layers::WebRenderDisplayItemLayer* aLayer)
 {
   MOZ_ASSERT(IsImageType());
 
   if (!mImage) {
      return;
   }
 
@@ -455,23 +460,30 @@ BulletRenderer::CreateWebRenderCommandsF
   uint64_t externalImageId = layer->SendImageContainer(container);
 
   const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
   Rect destRect =
     NSRectToRect(mDest, appUnitsPerDevPixel);
   Rect destRectTransformed = aLayer->RelativeToParent(destRect);
   IntRect dest = RoundedToInt(destRectTransformed);
 
-  aCommands.AppendElement(layers::OpDPPushExternalImageId(
-                            LayerIntRegion(),
+  WrImageKey key;
+  key.mNamespace = layer->WrBridge()->GetNamespace();
+  key.mHandle = layer->WrBridge()->GetNextResourceId();
+  aParentCommands.AppendElement(layers::OpAddExternalImage(
+                                externalImageId,
+                                key));
+  aCommands.AppendElement(layers::OpDPPushImage(
                             wr::ToWrRect(dest),
                             wr::ToWrRect(dest),
                             Nothing(),
                             WrImageRendering::Auto,
-                            externalImageId));
+                            key));
+
+
 }
 
 void
 BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
                                                nsTArray<layers::WebRenderCommand>& aCommands,
                                                layers::WebRenderDisplayItemLayer* aLayer)
 {
   MOZ_ASSERT(IsPathType());
@@ -491,17 +503,17 @@ BulletRenderer::CreateWebRenderCommandsF
   layers::WebRenderDisplayItemLayer* layer = static_cast<layers::WebRenderDisplayItemLayer*>(aLayer);
   nsDisplayListBuilder* builder = layer->GetDisplayListBuilder();
   const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
   bool dummy;
   Rect destRect =
     NSRectToRect(aItem->GetBounds(builder, &dummy), appUnitsPerDevPixel);
   Rect destRectTransformed = aLayer->RelativeToParent(destRect);
 
-  mGlyphHelper.BuildWebRenderCommands(aCommands, mGlyphs, mFont, aLayer->GetOffsetToParent(),
+  mGlyphHelper.BuildWebRenderCommands(layer->WrBridge(), aCommands, mGlyphs, mFont, aLayer->GetOffsetToParent(),
                                       destRectTransformed, destRectTransformed);
 }
 
 class nsDisplayBullet final : public nsDisplayItem {
 public:
   nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
     , mDisableSubpixelAA(false)
@@ -525,16 +537,17 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aParameters) override;
 
   virtual void CreateWebRenderCommands(nsTArray<layers::WebRenderCommand>& aCommands,
+                                       nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                        layers::WebRenderDisplayItemLayer* aLayer) override;
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) override {
     aOutFrames->AppendElement(mFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder,
@@ -638,22 +651,23 @@ nsDisplayBullet::BuildLayer(nsDisplayLis
     return nullptr;
   }
 
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 void
 nsDisplayBullet::CreateWebRenderCommands(nsTArray<layers::WebRenderCommand>& aCommands,
+                                         nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                          layers::WebRenderDisplayItemLayer* aLayer)
 {
   if (!mBulletRenderer)
     return;
 
-  mBulletRenderer->CreateWebRenderCommands(this, aCommands, aLayer);
+  mBulletRenderer->CreateWebRenderCommands(this, aCommands, aParentCommands, aLayer);
 }
 
 void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
                             nsRenderingContext* aCtx)
 {
   uint32_t flags = imgIContainer::FLAG_NONE;
   if (aBuilder->ShouldSyncDecodeImages()) {
     flags |= imgIContainer::FLAG_SYNC_DECODE;
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -1436,16 +1436,35 @@ nsCSSRendering::GetShadowRect(const nsRe
   Sides skipSides = aForFrame->GetSkipSides();
   frameRect = ::BoxDecorationRectForBorder(aForFrame, frameRect, skipSides);
 
   // Explicitly do not need to account for the spread radius here
   // Webrender does it for us or PaintBoxShadow will for non-WR
   return frameRect;
 }
 
+bool
+nsCSSRendering::GetBorderRadii(const nsRect& aFrameRect,
+                               const nsRect& aBorderRect,
+                               nsIFrame* aFrame,
+                               RectCornerRadii& aOutRadii)
+{
+  const nscoord twipsPerPixel = aFrame->PresContext()->DevPixelsToAppUnits(1);
+  nscoord twipsRadii[8];
+  NS_ASSERTION(aBorderRect.Size() == aFrame->VisualBorderRectRelativeToSelf().Size(),
+              "unexpected size");
+  nsSize sz = aFrameRect.Size();
+  bool hasBorderRadius = aFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii);
+  if (hasBorderRadius) {
+    ComputePixelRadii(twipsRadii, twipsPerPixel, &aOutRadii);
+  }
+
+  return hasBorderRadius;
+}
+
 void
 nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
                                     nsRenderingContext& aRenderingContext,
                                     nsIFrame* aForFrame,
                                     const nsRect& aFrameArea,
                                     const nsRect& aDirtyRect,
                                     float aOpacity)
 {
@@ -1654,83 +1673,121 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr
                                       aDirtyRect,
                                       skipGfxRect);
       renderContext->Restore();
     }
 
   }
 }
 
+nsRect
+nsCSSRendering::GetBoxShadowInnerPaddingRect(nsIFrame* aFrame,
+                                             const nsRect& aFrameArea)
+{
+  Sides skipSides = aFrame->GetSkipSides();
+  nsRect frameRect =
+    ::BoxDecorationRectForBorder(aFrame, aFrameArea, skipSides);
+
+  nsRect paddingRect = frameRect;
+  nsMargin border = aFrame->GetUsedBorder();
+  paddingRect.Deflate(border);
+  return paddingRect;
+}
+
+bool
+nsCSSRendering::CanPaintBoxShadowInner(nsIFrame* aFrame)
+{
+  nsCSSShadowArray* shadows = aFrame->StyleEffects()->mBoxShadow;
+  if (!shadows)
+    return false;
+
+  if (aFrame->IsThemed() && aFrame->GetContent() &&
+      !nsContentUtils::IsChromeDoc(aFrame->GetContent()->GetUncomposedDoc())) {
+    // There's no way of getting hold of a shape corresponding to a
+    // "padding-box" for native-themed widgets, so just don't draw
+    // inner box-shadows for them. But we allow chrome to paint inner
+    // box shadows since chrome can be aware of the platform theme.
+    return false;
+  }
+
+  return true;
+}
+
+bool
+nsCSSRendering::GetShadowInnerRadii(nsIFrame* aFrame,
+                                    const nsRect& aFrameArea,
+                                    RectCornerRadii& aOutInnerRadii)
+{
+  // Get any border radius, since box-shadow must also have rounded corners
+  // if the frame does.
+  nscoord twipsRadii[8];
+  nsRect frameRect =
+    ::BoxDecorationRectForBorder(aFrame, aFrameArea, aFrame->GetSkipSides());
+  nsSize sz = frameRect.Size();
+  nsMargin border = aFrame->GetUsedBorder();
+  bool hasBorderRadius = aFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii);
+  const nscoord twipsPerPixel = aFrame->PresContext()->DevPixelsToAppUnits(1);
+
+  RectCornerRadii borderRadii;
+
+  hasBorderRadius = GetBorderRadii(frameRect, aFrameArea, aFrame, borderRadii);
+  if (hasBorderRadius) {
+    ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
+
+    Float borderSizes[4] = {
+      Float(border.top / twipsPerPixel),
+      Float(border.right / twipsPerPixel),
+      Float(border.bottom / twipsPerPixel),
+      Float(border.left / twipsPerPixel)
+    };
+    nsCSSBorderRenderer::ComputeInnerRadii(borderRadii,
+                                           borderSizes,
+                                           &aOutInnerRadii);
+  }
+
+  return hasBorderRadius;
+}
+
 void
 nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
                                     nsRenderingContext& aRenderingContext,
                                     nsIFrame* aForFrame,
                                     const nsRect& aFrameArea)
 {
-  nsCSSShadowArray* shadows = aForFrame->StyleEffects()->mBoxShadow;
-  if (!shadows)
+  if (!CanPaintBoxShadowInner(aForFrame)) {
     return;
-  if (aForFrame->IsThemed() && aForFrame->GetContent() &&
-      !nsContentUtils::IsChromeDoc(aForFrame->GetContent()->GetUncomposedDoc())) {
-    // There's no way of getting hold of a shape corresponding to a
-    // "padding-box" for native-themed widgets, so just don't draw
-    // inner box-shadows for them. But we allow chrome to paint inner
-    // box shadows since chrome can be aware of the platform theme.
-    return;
-  }
-
+  }
+
+  nsCSSShadowArray* shadows = aForFrame->StyleEffects()->mBoxShadow;
   NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
                aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
 
-  Sides skipSides = aForFrame->GetSkipSides();
-  nsRect frameRect =
-    ::BoxDecorationRectForBorder(aForFrame, aFrameArea, skipSides);
-  nsRect paddingRect = frameRect;
-  nsMargin border = aForFrame->GetUsedBorder();
-  paddingRect.Deflate(border);
-
-  // Get any border radius, since box-shadow must also have rounded corners
-  // if the frame does.
-  nscoord twipsRadii[8];
-  nsSize sz = frameRect.Size();
-  bool hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, Sides(), twipsRadii);
-  const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
+  nsRect paddingRect = GetBoxShadowInnerPaddingRect(aForFrame, aFrameArea);
 
   RectCornerRadii innerRadii;
-  if (hasBorderRadius) {
-    RectCornerRadii borderRadii;
-
-    ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
-    Float borderSizes[4] = {
-      Float(border.top / twipsPerPixel),
-      Float(border.right / twipsPerPixel),
-      Float(border.bottom / twipsPerPixel),
-      Float(border.left / twipsPerPixel)
-    };
-    nsCSSBorderRenderer::ComputeInnerRadii(borderRadii, borderSizes,
-                                           &innerRadii);
-  }
+  bool hasBorderRadius = GetShadowInnerRadii(aForFrame,
+                                             aFrameArea,
+                                             innerRadii);
+
+  const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
 
   for (uint32_t i = shadows->Length(); i > 0; --i) {
     nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
     if (!shadowItem->mInset)
       continue;
 
     // shadowPaintRect: the area to paint on the temp surface
     // shadowClipRect: the area on the temporary surface within shadowPaintRect
     //                 that we will NOT paint in
     nscoord blurRadius = shadowItem->mRadius;
     nsMargin blurMargin =
       nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel);
     nsRect shadowPaintRect = paddingRect;
     shadowPaintRect.Inflate(blurMargin);
 
-    Rect shadowPaintGfxRect = NSRectToRect(shadowPaintRect, twipsPerPixel);
-    shadowPaintGfxRect.RoundOut();
-
     // Round the spread radius to device pixels (by truncation).
     // This mostly matches what we do for borders, except that we don't round
     // up values between zero and one device pixels to one device pixel.
     // This way of rounding is symmetric around zero, which makes sense for
     // the spread radius.
     int32_t spreadDistance = shadowItem->mSpread / twipsPerPixel;
     nscoord spreadDistanceAppUnits = aPresContext->DevPixelsToAppUnits(spreadDistance);
 
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -370,21 +370,31 @@ struct nsCSSRendering {
    */
   static void Init();
   
   /**
    * Clean up any static variables used by nsCSSRendering.
    */
   static void Shutdown();
   
+  static bool GetShadowInnerRadii(nsIFrame* aFrame,
+                                  const nsRect& aFrameArea,
+                                  RectCornerRadii& aOutInnerRadii);
+  static nsRect GetBoxShadowInnerPaddingRect(nsIFrame* aFrame,
+                                             const nsRect& aFrameArea);
+  static bool CanPaintBoxShadowInner(nsIFrame* aFrame);
   static void PaintBoxShadowInner(nsPresContext* aPresContext,
                                   nsRenderingContext& aRenderingContext,
                                   nsIFrame* aForFrame,
                                   const nsRect& aFrameArea);
 
+  static bool GetBorderRadii(const nsRect& aFrameRect,
+                             const nsRect& aBorderRect,
+                             nsIFrame* aFrame,
+                             RectCornerRadii& aOutRadii);
   static nsRect GetShadowRect(const nsRect aFrameArea,
                               bool aNativeTheme,
                               nsIFrame* aForFrame);
   static mozilla::gfx::Color GetShadowColor(nsCSSShadowItem* aShadow,
                                    nsIFrame* aFrame,
                                    float aOpacity);
   // Returns if the frame has a themed frame.
   // aMaybeHasBorderRadius will return false if we can early detect
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -4143,16 +4143,17 @@ nsDisplayOutline::BuildLayer(nsDisplayLi
                              LayerManager* aManager,
                              const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 void
 nsDisplayOutline::CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                          nsTArray<WebRenderParentCommand>& aParentCommands,
                                           WebRenderDisplayItemLayer* aLayer)
 {
   MOZ_ASSERT(mBorderRenderer.isSome());
 
   Rect outlineTransformedRect = aLayer->RelativeToParent(mBorderRenderer->mOuterRect);
 
   nsCSSBorderRenderer* br = mBorderRenderer.ptr();
   WrBorderSide side[4];
@@ -4422,16 +4423,17 @@ nsDisplayCaret::Paint(nsDisplayListBuild
                       nsRenderingContext* aCtx) {
   // Note: Because we exist, we know that the caret is visible, so we don't
   // need to check for the caret's visibility.
   mCaret->PaintCaret(*aCtx->GetDrawTarget(), mFrame, ToReferenceFrame());
 }
 
 void
 nsDisplayCaret::CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                         WebRenderDisplayItemLayer* aLayer) {
   using namespace mozilla::layers;
   int32_t contentOffset;
   nsIFrame* frame = mCaret->GetFrame(&contentOffset);
   if (!frame) {
     return;
   }
   NS_ASSERTION(frame == mFrame, "We're referring different frame");
@@ -4830,16 +4832,17 @@ nsDisplayBoxShadowOuter::BuildLayer(nsDi
                                     LayerManager* aManager,
                                     const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 void
 nsDisplayBoxShadowOuter::CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                                 nsTArray<WebRenderParentCommand>& aParentCommands,
                                                  WebRenderDisplayItemLayer* aLayer)
 {
   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   nsPoint offset = ToReferenceFrame();
   nsRect borderRect = mFrame->VisualBorderRectRelativeToSelf() + offset;
   //nsPresContext* presContext = mFrame->PresContext();
   AutoTArray<nsRect,10> rects;
   nsRegion visible = aLayer->GetVisibleRegion().ToAppUnits(appUnitsPerDevPixel);
@@ -4849,48 +4852,60 @@ nsDisplayBoxShadowOuter::CreateWebRender
   nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
   if (!shadows)
     return;
 
   bool hasBorderRadius;
   bool nativeTheme = nsCSSRendering::HasBoxShadowNativeTheme(mFrame,
                                                              hasBorderRadius);
 
+  // Don't need the full size of the shadow rect like we do in
+  // nsCSSRendering since WR takes care of calculations for blur
+  // and spread radius.
+  nsRect shadowRect = nsCSSRendering::GetShadowRect(borderRect,
+                                                    nativeTheme,
+                                                    mFrame);
+
+  RectCornerRadii borderRadii;
+  if (hasBorderRadius) {
+    hasBorderRadius = nsCSSRendering::GetBorderRadii(shadowRect,
+                                                     borderRect,
+                                                     mFrame,
+                                                     borderRadii);
+    MOZ_ASSERT(borderRadii.AreRadiiSame(), "WR only supports uniform borders");
+  }
+
   // Everything here is in app units, change to device units.
   for (uint32_t i = 0; i < rects.Length(); ++i) {
     Rect clipRect = NSRectToRect(rects[i], appUnitsPerDevPixel);
     nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
 
     for (uint32_t j = shadows->Length(); j  > 0; j--) {
       nsCSSShadowItem* shadow = shadows->ShadowAt(j - 1);
-      // Don't need the full size of the shadow rect like we do in
-      // nsCSSRendering since WR takes care of calculations for blur
-      // and spread radius.
-      nsRect shadowRect = nsCSSRendering::GetShadowRect(borderRect,
-                                                        nativeTheme,
-                                                        mFrame);
+
       gfx::Color shadowColor = nsCSSRendering::GetShadowColor(shadow,
                                                               mFrame,
                                                               mOpacity);
       shadowRect.MoveBy(shadow->mXOffset, shadow->mYOffset);
 
       // Now translate everything to device pixels.
       Point shadowOffset;
       shadowOffset.x = (shadow->mXOffset / appUnitsPerDevPixel);
       shadowOffset.y = (shadow->mYOffset / appUnitsPerDevPixel);
 
       Rect deviceBoxRect = NSRectToRect(shadowRect, appUnitsPerDevPixel);
       deviceBoxRect = aLayer->RelativeToParent(deviceBoxRect);
 
       Rect deviceClipRect = aLayer->RelativeToParent(clipRect + shadowOffset);
 
-      float blurRadius = shadow->mRadius / appUnitsPerDevPixel;
-      // TODO: Calculate the border radius here.
-      float borderRadius = 0.0;
-      float spreadRadius = shadow->mSpread / appUnitsPerDevPixel;
+      float blurRadius = float(shadow->mRadius) / float(appUnitsPerDevPixel);
+      // TODO: support non-uniform border radius.
+      float borderRadius = hasBorderRadius ? borderRadii.TopLeft().width
+                                           : 0.0;
+      float spreadRadius = float(shadow->mSpread) / float(appUnitsPerDevPixel);
 
       aCommands.AppendElement(OpDPPushBoxShadow(
                               wr::ToWrRect(deviceBoxRect),
                               wr::ToWrRect(deviceClipRect),
                               wr::ToWrRect(deviceBoxRect),
                               wr::ToWrPoint(shadowOffset),
                               wr::ToWrColor(shadowColor),
                               blurRadius,
@@ -4949,16 +4964,99 @@ nsDisplayBoxShadowInner::Paint(nsDisplay
   for (uint32_t i = 0; i < rects.Length(); ++i) {
     gfx->Save();
     gfx->Clip(NSRectToSnappedRect(rects[i], appUnitsPerDevPixel, *drawTarget));
     nsCSSRendering::PaintBoxShadowInner(presContext, *aCtx, mFrame, borderRect);
     gfx->Restore();
   }
 }
 
+LayerState
+nsDisplayBoxShadowInner::GetLayerState(nsDisplayListBuilder* aBuilder,
+                                       LayerManager* aManager,
+                                       const ContainerLayerParameters& aParameters)
+{
+  if (gfxPrefs::LayersAllowInsetBoxShadow()) {
+    return LAYER_ACTIVE;
+  }
+
+  return LAYER_NONE;
+}
+
+already_AddRefed<Layer>
+nsDisplayBoxShadowInner::BuildLayer(nsDisplayListBuilder* aBuilder,
+                                    LayerManager* aManager,
+                                    const ContainerLayerParameters& aContainerParameters)
+{
+  return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
+}
+
+void
+nsDisplayBoxShadowInner::CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                                 nsTArray<WebRenderParentCommand>& aParentCommands,
+                                                 WebRenderDisplayItemLayer* aLayer)
+{
+  if (!nsCSSRendering::CanPaintBoxShadowInner(mFrame)) {
+    return;
+  }
+
+  int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
+  nsPoint offset = ToReferenceFrame();
+  nsRect borderRect = nsRect(offset, mFrame->GetSize());
+
+  AutoTArray<nsRect,10> rects;
+  nsRegion visible = aLayer->GetVisibleRegion().ToAppUnits(appUnitsPerDevPixel);
+  ComputeDisjointRectangles(visible, &rects);
+
+  nsCSSShadowArray* shadows = mFrame->StyleEffects()->mBoxShadow;
+
+  for (uint32_t i = 0; i < rects.Length(); ++i) {
+    Rect clipRect = NSRectToRect(rects[i], appUnitsPerDevPixel);
+
+    for (uint32_t i = shadows->Length(); i > 0; --i) {
+      nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
+      if (!shadowItem->mInset) {
+        continue;
+      }
+
+      nsRect shadowRect =
+        nsCSSRendering::GetBoxShadowInnerPaddingRect(mFrame, borderRect);
+      RectCornerRadii innerRadii;
+      nsCSSRendering::GetShadowInnerRadii(mFrame, borderRect, innerRadii);
+
+      // Now translate everything to device pixels.
+      Rect deviceBoxRect = NSRectToRect(shadowRect, appUnitsPerDevPixel);
+      Rect deviceClipRect = aLayer->RelativeToParent(clipRect);
+      Color shadowColor = nsCSSRendering::GetShadowColor(shadowItem, mFrame, 1.0);
+
+      Point shadowOffset;
+      shadowOffset.x = (shadowItem->mXOffset / appUnitsPerDevPixel);
+      shadowOffset.y = (shadowItem->mYOffset / appUnitsPerDevPixel);
+
+      float blurRadius = float(shadowItem->mRadius) / float(appUnitsPerDevPixel);
+      // TODO: WR doesn't support non-uniform border radii
+      float borderRadius = innerRadii.TopLeft().width;
+      // NOTE: Any spread radius > 0 will render nothing. WR Bug.
+      float spreadRadius = float(shadowItem->mSpread) / float(appUnitsPerDevPixel);
+
+      aCommands.AppendElement(OpDPPushBoxShadow(
+                              wr::ToWrRect(deviceBoxRect),
+                              wr::ToWrRect(deviceClipRect),
+                              wr::ToWrRect(deviceBoxRect),
+                              wr::ToWrPoint(shadowOffset),
+                              wr::ToWrColor(shadowColor),
+                              blurRadius,
+                              spreadRadius,
+                              borderRadius,
+                              WrBoxShadowClipMode::Inset
+                              ));
+    }
+  }
+}
+
 bool
 nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                            nsRegion* aVisibleRegion) {
   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion)) {
     return false;
   }
 
   // Store the actual visible region
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -54,16 +54,17 @@ class nsCaret;
 
 namespace mozilla {
 class FrameLayerBuilder;
 namespace layers {
 class Layer;
 class ImageLayer;
 class ImageContainer;
 class WebRenderCommand;
+class WebRenderParentCommand;
 class WebRenderDisplayItemLayer;
 } // namespace layers
 } // namespace mozilla
 
 // A set of blend modes, that never includes OP_OVER (since it's
 // considered the default, rather than a specific blend mode).
 typedef mozilla::EnumSet<mozilla::gfx::CompositionOp> BlendModeSet;
 
@@ -1580,16 +1581,17 @@ public:
   typedef mozilla::DisplayItemClipChain DisplayItemClipChain;
   typedef mozilla::ActiveScrolledRoot ActiveScrolledRoot;
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::ScrollMetadata ScrollMetadata;
   typedef mozilla::layers::FrameMetrics::ViewID ViewID;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::WebRenderCommand WebRenderCommand;
+  typedef mozilla::layers::WebRenderParentCommand WebRenderParentCommand;
   typedef mozilla::layers::WebRenderDisplayItemLayer WebRenderDisplayItemLayer;
   typedef mozilla::LayerState LayerState;
   typedef class mozilla::gfx::DrawTarget DrawTarget;
 
   // This is never instantiated directly (it has pure virtual methods), so no
   // need to count constructors and destructors.
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
   nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
@@ -1921,16 +1923,17 @@ public:
   { return nullptr; }
 
   /**
     * Create the WebRenderCommands required to paint this display item.
     * The layer this item is in is passed in as rects must be relative
     * to their parent.
     */
    virtual void CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                         WebRenderDisplayItemLayer* aLayer) {}
   /**
    * Builds a DisplayItemLayer and sets the display item to this.
    */
    already_AddRefed<Layer>
    BuildDisplayItemLayer(nsDisplayListBuilder* aBuilder,
                          LayerManager* aManager,
                          const ContainerLayerParameters& aContainerParameters);
@@ -2817,16 +2820,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual void CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                       nsTArray<WebRenderParentCommand>& aParentCommands,
                                         WebRenderDisplayItemLayer* aLayer) override;
 
 protected:
   RefPtr<nsCaret> mCaret;
   nsRect mBounds;
 };
 
 /**
@@ -3379,16 +3383,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual void CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                       nsTArray<WebRenderParentCommand>& aParentCommands,
                                        WebRenderDisplayItemLayer* aLayer) override;
 
   nsRect GetBoundsInternal();
 
 private:
   nsRegion mVisibleRegion;
   nsRect mBounds;
   float mOpacity;
@@ -3427,16 +3432,26 @@ public:
     if (!geometry->mPaddingRect.IsEqualInterior(GetPaddingRect())) {
       // nsDisplayBoxShadowInner is based around the padding rect, but it can
       // touch pixels outside of this. We should invalidate the entire bounds.
       bool snap;
       aInvalidRegion->Or(geometry->mBounds, GetBounds(aBuilder, &snap));
     }
   }
 
+  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager,
+                                   const ContainerLayerParameters& aParameters) override;
+  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
+                                             LayerManager* aManager,
+                                             const ContainerLayerParameters& aContainerParameters) override;
+  virtual void CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                       nsTArray<WebRenderParentCommand>& aParentCommand,
+                                       WebRenderDisplayItemLayer* aLayer) override;
+
 private:
   nsRegion mVisibleRegion;
 };
 
 /**
  * The standard display item to paint the CSS outline of a frame.
  */
 class nsDisplayOutline : public nsDisplayItem {
@@ -3453,16 +3468,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual void CreateWebRenderCommands(nsTArray<WebRenderCommand>& aCommands,
+                                       nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderDisplayItemLayer* aLayer) override;
   virtual bool IsInvisibleInRect(const nsRect& aRect) override;
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override;
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
 
   mozilla::Maybe<nsCSSBorderRenderer> mBorderRenderer;
 };
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4683,18 +4683,16 @@ pref("layers.offmainthreadcomposition.as
 // Whether to log information about off main thread animations to stderr
 pref("layers.offmainthreadcomposition.log-animations", false);
 
 pref("layers.bufferrotation.enabled", true);
 
 pref("layers.componentalpha.enabled", true);
 pref("layers.draw-mask-debug", false);
 
-pref("layers.advanced.border-layers", false);
-
 pref("gfx.content.always-paint", false);
 
 #ifdef ANDROID
 pref("gfx.apitrace.enabled",false);
 #endif
 
 #ifdef MOZ_X11
 #ifdef MOZ_WIDGET_GTK
@@ -5625,8 +5623,16 @@ pref("dom.moduleScripts.enabled", false)
 
 // Maximum number of setTimeout()/setInterval() callbacks to run in a single
 // event loop runnable. Minimum value of 1.
 pref("dom.timeout.max_consecutive_callbacks", 5);
 
 #ifdef FUZZING
 pref("fuzzing.enabled", false);
 #endif
+
+// Set advanced layers preferences here.
+pref("layers.advanced.border-layers", false);
+#ifdef MOZ_ENABLE_WEBRENDER
+pref("layers.advanced.caret-layers", true);
+#else
+pref("layers.advanced.caret-layers", false);
+#endif
--- a/taskcluster/ci/test/test-sets.yml
+++ b/taskcluster/ci/test/test-sets.yml
@@ -74,16 +74,17 @@ stylo-tests:
 qr-tests:
     - cppunit
     - crashtest
     - gtest
     - jittest
     - jsreftest
     - mochitest-a11y
     - mochitest-gpu
+    - mochitest-webgl
     - reftest
     - reftest-no-accel
     - xpcshell
 
 ccov-code-coverage-tests:
     - crashtest
     - gtest
     - jsreftest
--- a/taskcluster/ci/test/tests.yml
+++ b/taskcluster/ci/test/tests.yml
@@ -833,16 +833,20 @@ mochitest-valgrind:
         extra-options:
             - --mochitest-suite=valgrind-plain
 
 mochitest-webgl:
     description: "Mochitest webgl run"
     suite: mochitest/mochitest-gl
     treeherder-symbol: tc-M(gl)
     docker-image: {"in-tree": "desktop1604-test"}
+    run-on-projects:
+        by-test-platform:
+            linux64-qr/.*: ['graphics', 'mozilla-central']
+            default: ['all']
     chunks:
         by-test-platform:
             android.*: 10
             default: 3
     e10s:
       by-test-platform:
         macosx.*: true
         default: both
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"35ac94f7615ebe24f1285927f03712dde336117e666cfa7cf595d0524bc47b8d","src/array.rs":"ceeb3298fb939ead81914a0e6a555098e59f97c47e62adb625273bde2bb299a4","src/base.rs":"540c85a6600503e2bdf34087e7e921615b094f7493099c7e319c76f34ab97a02","src/boolean.rs":"112adb640ded232cba59eb27edafcf4a3c045cca6f4b0ecb53bb48b741c2139a","src/bundle.rs":"bd172a5e0cc1dffc80edf17da59b90120d0a110181f50f212589b0334fcba72c","src/data.rs":"fc44b08e644b66ae471bb7c8141ec6be7cf5f35eb985dbca5924668a67f0efe5","src/dictionary.rs":"0f3129629db02ea233d08fd937e8290c40f401d644f6a8afc13717094a767559","src/error.rs":"0edbf66bcaa8a68f1de77b9056696b6be4f2dc773f4561f4279e6494cc38453a","src/lib.rs":"71ee7a83a7012138b5a86897f5617d2742c668ccc69664a8c5b4cf080486ddd8","src/number.rs":"262db248c88ac08a3d28d0940ef25fe796fd4ebcf1eeea7bb8a6caa3abdc97f9","src/propertylist.rs":"ec814aa190bc6cf8c2bb3f2d5c65e1a706a770701c8589d29fc01bddad6a11c6","src/runloop.rs":"10e35be9104db16c064dfcb3454a71d00c498fda6145eba53f6e43cb37ee9c15","src/set.rs":"f98fbd31b107f27680727676ab7a3725d6b4370f428e58759ca680eb339a5ea3","src/string.rs":"ec5420a3916e5ebd2cc487ffc605d8fe8de7d09cae8c9fecbf20aa21595f4bee","src/url.rs":"2bdc580d8fa4556c9466923aeccc845257fee9fb5e960b8ff84d6bfead994335"},"package":"25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "core-foundation"
-description = "Bindings to Core Foundation for OS X"
-homepage = "https://github.com/servo/core-foundation-rs"
-repository = "https://github.com/servo/core-foundation-rs"
-version = "0.2.3"
-authors = ["The Servo Project Developers"]
-license = "MIT / Apache-2.0"
-
-[dependencies.core-foundation-sys]
-path = "../core-foundation-sys"
-version = "0.2.3"
-
-[dependencies]
-libc = "0.2"
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/array.rs
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Heterogeneous immutable arrays.
-
-pub use core_foundation_sys::array::*;
-pub use core_foundation_sys::base::{CFIndex, CFRelease};
-use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault};
-use libc::c_void;
-use std::mem;
-
-use base::{CFIndexConvertible, TCFType, CFRange};
-
-/// A heterogeneous immutable array.
-pub struct CFArray(CFArrayRef);
-
-impl Drop for CFArray {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-pub struct CFArrayIterator<'a> {
-    array: &'a CFArray,
-    index: CFIndex,
-}
-
-impl<'a> Iterator for CFArrayIterator<'a> {
-    type Item = *const c_void;
-
-    fn next(&mut self) -> Option<*const c_void> {
-        if self.index >= self.array.len() {
-            None
-        } else {
-            let value = self.array.get(self.index);
-            self.index += 1;
-            Some(value)
-        }
-    }
-}
-
-impl_TCFType!(CFArray, CFArrayRef, CFArrayGetTypeID);
-
-impl CFArray {
-    /// Creates a new `CFArray` with the given elements, which must be `CFType` objects.
-    pub fn from_CFTypes<R, T>(elems: &[T]) -> CFArray where T: TCFType<R> {
-        unsafe {
-            let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
-            let array_ref = CFArrayCreate(kCFAllocatorDefault,
-                                          mem::transmute(elems.as_ptr()),
-                                          elems.len().to_CFIndex(),
-                                          &kCFTypeArrayCallBacks);
-            TCFType::wrap_under_create_rule(array_ref)
-        }
-    }
-
-    /// Iterates over the elements of this `CFArray`.
-    ///
-    /// Careful; the loop body must wrap the reference properly. Generally, when array elements are
-    /// Core Foundation objects (not always true), they need to be wrapped with
-    /// `TCFType::wrap_under_get_rule()`.
-    #[inline]
-    pub fn iter<'a>(&'a self) -> CFArrayIterator<'a> {
-        CFArrayIterator {
-            array: self,
-            index: 0
-        }
-    }
-
-    #[inline]
-    pub fn len(&self) -> CFIndex {
-        unsafe {
-            CFArrayGetCount(self.0)
-        }
-    }
-
-    #[inline]
-    pub fn get(&self, index: CFIndex) -> *const c_void {
-        assert!(index < self.len());
-        unsafe {
-            CFArrayGetValueAtIndex(self.0, index)
-        }
-    }
-
-    pub fn get_values(&self, range: CFRange) -> Vec<*const c_void> {
-        let mut vec = Vec::with_capacity(range.length as usize);
-        unsafe {
-            CFArrayGetValues(self.0, range, vec.as_mut_ptr());
-            vec.set_len(range.length as usize);
-            vec
-        }
-    }
-
-    pub fn get_all_values(&self) -> Vec<*const c_void> {
-        self.get_values(CFRange {
-            location: 0,
-            length: self.len()
-        })
-    }
-}
-
-impl<'a> IntoIterator for &'a CFArray {
-    type Item = *const c_void;
-    type IntoIter = CFArrayIterator<'a>;
-
-    fn into_iter(self) -> CFArrayIterator<'a> {
-        self.iter()
-    }
-}
-
-#[test]
-fn should_box_and_unbox() {
-    use number::{CFNumber, number};
-
-    let n1 = number(1);
-    let n2 = number(2);
-    let n3 = number(3);
-    let n4 = number(4);
-    let n5 = number(5);
-
-    let arr = CFArray::from_CFTypes(&[
-        n1.as_CFType(),
-        n2.as_CFType(),
-        n3.as_CFType(),
-        n4.as_CFType(),
-        n5.as_CFType(),
-    ]);
-
-    assert!(arr.get_all_values() == &[n1.as_CFTypeRef(),
-                                      n2.as_CFTypeRef(),
-                                      n3.as_CFTypeRef(),
-                                      n4.as_CFTypeRef(),
-                                      n5.as_CFTypeRef()]);
-
-    unsafe {
-        let mut sum = 0;
-
-        for elem in arr.iter() {
-            let number: CFNumber = TCFType::wrap_under_get_rule(mem::transmute(elem));
-            sum += number.to_i64().unwrap()
-        }
-
-        assert!(sum == 15);
-
-        for elem in arr.iter() {
-            let number: CFNumber = TCFType::wrap_under_get_rule(mem::transmute(elem));
-            sum += number.to_i64().unwrap()
-        }
-
-        assert!(sum == 30);
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/base.rs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub use core_foundation_sys::base::*;
-
-pub trait CFIndexConvertible {
-    /// Always use this method to construct a `CFIndex` value. It performs bounds checking to
-    /// ensure the value is in range.
-    fn to_CFIndex(self) -> CFIndex;
-}
-
-impl CFIndexConvertible for usize {
-    #[inline]
-    fn to_CFIndex(self) -> CFIndex {
-        let max_CFIndex = CFIndex::max_value();
-        if self > (max_CFIndex as usize) {
-            panic!("value out of range")
-        }
-        self as CFIndex
-    }
-}
-
-/// Superclass of all Core Foundation objects.
-pub struct CFType(CFTypeRef);
-
-impl Clone for CFType {
-    #[inline]
-    fn clone(&self) -> CFType {
-        unsafe {
-            TCFType::wrap_under_get_rule(self.0)
-        }
-    }
-}
-
-impl Drop for CFType {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.0)
-        }
-    }
-}
-
-/// All Core Foundation types implement this trait. The type parameter `TypeRef` specifies the
-/// associated Core Foundation type: e.g. for `CFType` this is `CFTypeRef`; for `CFArray` this is
-/// `CFArrayRef`.
-pub trait TCFType<ConcreteTypeRef> {
-    /// Returns the object as its concrete TypeRef.
-    fn as_concrete_TypeRef(&self) -> ConcreteTypeRef;
-
-    /// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
-    /// when following Core Foundation's "Create Rule". The reference count is *not* bumped.
-    unsafe fn wrap_under_create_rule(obj: ConcreteTypeRef) -> Self;
-
-    /// Returns the type ID for this class.
-    fn type_id() -> CFTypeID;
-
-    /// Returns the object as a wrapped `CFType`. The reference count is incremented by one.
-    #[inline]
-    fn as_CFType(&self) -> CFType {
-        unsafe {
-            TCFType::wrap_under_get_rule(self.as_CFTypeRef())
-        }
-    }
-
-    /// Returns the object as a raw `CFTypeRef`. The reference count is not adjusted.
-    fn as_CFTypeRef(&self) -> CFTypeRef;
-
-    /// Returns an instance of the object, wrapping the underlying `CFTypeRef` subclass. Use this
-    /// when following Core Foundation's "Get Rule". The reference count *is* bumped.
-    unsafe fn wrap_under_get_rule(reference: ConcreteTypeRef) -> Self;
-
-    /// Returns the reference count of the object. It is unwise to do anything other than test
-    /// whether the return value of this method is greater than zero.
-    #[inline]
-    fn retain_count(&self) -> CFIndex {
-        unsafe {
-            CFGetRetainCount(self.as_CFTypeRef())
-        }
-    }
-
-    /// Returns the type ID of this object.
-    #[inline]
-    fn type_of(&self) -> CFTypeID {
-        unsafe {
-            CFGetTypeID(self.as_CFTypeRef())
-        }
-    }
-
-    /// Writes a debugging version of this object on standard error.
-    fn show(&self) {
-        unsafe {
-            CFShow(self.as_CFTypeRef())
-        }
-    }
-
-    /// Returns true if this value is an instance of another type.
-    #[inline]
-    fn instance_of<OtherConcreteTypeRef,OtherCFType:TCFType<OtherConcreteTypeRef>>(&self) -> bool {
-        self.type_of() == <OtherCFType as TCFType<_>>::type_id()
-    }
-}
-
-impl TCFType<CFTypeRef> for CFType {
-    #[inline]
-    fn as_concrete_TypeRef(&self) -> CFTypeRef {
-        self.0
-    }
-
-    #[inline]
-    unsafe fn wrap_under_get_rule(reference: CFTypeRef) -> CFType {
-        let reference: CFTypeRef = CFRetain(reference);
-        TCFType::wrap_under_create_rule(reference)
-    }
-
-    #[inline]
-    fn as_CFTypeRef(&self) -> CFTypeRef {
-        self.as_concrete_TypeRef()
-    }
-
-    #[inline]
-    unsafe fn wrap_under_create_rule(obj: CFTypeRef) -> CFType {
-        CFType(obj)
-    }
-
-    #[inline]
-    fn type_id() -> CFTypeID {
-        // FIXME(pcwalton): Is this right?
-        0
-    }
-
-    #[inline]
-    fn instance_of<OtherConcreteTypeRef,OtherCFType:TCFType<OtherConcreteTypeRef>>(&self) -> bool {
-        // Since this is the root of the type hierarchy, we always answer yes.
-        true
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/boolean.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A Boolean type.
-
-use core_foundation_sys::base::{CFRelease};
-pub use core_foundation_sys::number::{CFBooleanRef, CFBooleanGetTypeID, kCFBooleanTrue, kCFBooleanFalse};
-
-use base::TCFType;
-
-/// A Boolean type.
-///
-/// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug.
-pub struct CFBoolean(CFBooleanRef);
-
-impl Drop for CFBoolean {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFBoolean, CFBooleanRef, CFBooleanGetTypeID);
-
-impl CFBoolean {
-    pub fn true_value() -> CFBoolean {
-        unsafe {
-            TCFType::wrap_under_get_rule(kCFBooleanTrue)
-        }
-    }
-
-    pub fn false_value() -> CFBoolean {
-        unsafe {
-            TCFType::wrap_under_get_rule(kCFBooleanFalse)
-        }
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/bundle.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Core Foundation Bundle Type
-
-pub use core_foundation_sys::bundle::*;
-use core_foundation_sys::base::CFRelease;
-
-use base::{TCFType};
-use dictionary::CFDictionary;
-
-/// A Bundle type.
-pub struct CFBundle(CFBundleRef);
-
-impl Drop for CFBundle {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl CFBundle {
-    pub fn main_bundle() -> CFBundle {
-        unsafe {
-            let bundle_ref = CFBundleGetMainBundle();
-            TCFType::wrap_under_get_rule(bundle_ref)
-        }
-    }
-
-    pub fn info_dictionary(&self) -> CFDictionary {
-        unsafe {
-            let info_dictionary = CFBundleGetInfoDictionary(self.0);
-            TCFType::wrap_under_get_rule(info_dictionary)
-        }
-    }
-}
-
-impl_TCFType!(CFBundle, CFBundleRef, CFBundleGetTypeID);
-
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/data.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Core Foundation byte buffers.
-
-pub use core_foundation_sys::data::*;
-use core_foundation_sys::base::{CFIndex, CFRelease};
-use core_foundation_sys::base::{kCFAllocatorDefault};
-use std::ops::Deref;
-use std::slice;
-
-use base::{CFIndexConvertible, TCFType};
-
-/// A byte buffer.
-pub struct CFData(CFDataRef);
-
-impl Drop for CFData {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFData, CFDataRef, CFDataGetTypeID);
-
-impl CFData {
-    pub fn from_buffer(buffer: &[u8]) -> CFData {
-        unsafe {
-            let data_ref = CFDataCreate(kCFAllocatorDefault,
-                                        buffer.as_ptr(),
-                                        buffer.len().to_CFIndex());
-            TCFType::wrap_under_create_rule(data_ref)
-        }
-    }
-
-    /// Returns a pointer to the underlying bytes in this data. Note that this byte buffer is
-    /// read-only.
-    #[inline]
-    pub fn bytes<'a>(&'a self) -> &'a [u8] {
-        unsafe {
-            slice::from_raw_parts(CFDataGetBytePtr(self.0), self.len() as usize)
-        }
-    }
-
-    /// Returns the length of this byte buffer.
-    #[inline]
-    pub fn len(&self) -> CFIndex {
-        unsafe {
-            CFDataGetLength(self.0)
-        }
-    }
-}
-
-impl Deref for CFData {
-    type Target = [u8];
-
-    #[inline]
-    fn deref(&self) -> &[u8] {
-        self.bytes()
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/dictionary.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Dictionaries of key-value pairs.
-
-pub use core_foundation_sys::dictionary::*;
-use core_foundation_sys::base::CFRelease;
-use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault};
-use libc::c_void;
-use std::mem;
-use std::ptr;
-
-use base::{CFType, CFIndexConvertible, TCFType};
-
-/// An immutable dictionary of key-value pairs.
-pub struct CFDictionary(CFDictionaryRef);
-
-impl Drop for CFDictionary {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFDictionary, CFDictionaryRef, CFDictionaryGetTypeID);
-
-impl CFDictionary {
-    pub fn from_CFType_pairs<R1, R2, K, V>(pairs: &[(K, V)]) -> CFDictionary
-            where K: TCFType<R1>, V: TCFType<R2> {
-        let (keys, values): (Vec<CFTypeRef>,Vec<CFTypeRef>) =
-            pairs.iter()
-            .map(|&(ref key, ref value)| (key.as_CFTypeRef(), value.as_CFTypeRef()))
-            .unzip();
-
-        unsafe {
-            let dictionary_ref = CFDictionaryCreate(kCFAllocatorDefault,
-                                                    mem::transmute(keys.as_ptr()),
-                                                    mem::transmute(values.as_ptr()),
-                                                    keys.len().to_CFIndex(),
-                                                    &kCFTypeDictionaryKeyCallBacks,
-                                                    &kCFTypeDictionaryValueCallBacks);
-            TCFType::wrap_under_create_rule(dictionary_ref)
-        }
-    }
-
-    #[inline]
-    pub fn len(&self) -> usize {
-        unsafe {
-            CFDictionaryGetCount(self.0) as usize
-        }
-    }
-
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.len() == 0
-    }
-
-    #[inline]
-    pub fn contains_key(&self, key: *const c_void) -> bool {
-        unsafe {
-            CFDictionaryContainsKey(self.0, key) != 0
-        }
-    }
-
-    #[inline]
-    pub fn find(&self, key: *const c_void) -> Option<*const c_void> {
-        unsafe {
-            let mut value: *const c_void = ptr::null();
-            if CFDictionaryGetValueIfPresent(self.0, key, &mut value) != 0 {
-                Some(value)
-            } else {
-                None
-            }
-        }
-    }
-
-    #[inline]
-    pub fn get(&self, key: *const c_void) -> *const c_void {
-        let value = self.find(key);
-        if value.is_none() {
-            panic!("No entry found for key {:p}", key);
-        }
-        value.unwrap()
-    }
-
-    /// A convenience function to retrieve `CFType` instances.
-    #[inline]
-    pub unsafe fn get_CFType(&self, key: *const c_void) -> CFType {
-        let value: CFTypeRef = mem::transmute(self.get(key));
-        TCFType::wrap_under_get_rule(value)
-    }
-
-    #[inline]
-    pub unsafe fn set_value(&self, key: *const c_void, value: *const c_void) {
-        CFDictionarySetValue(self.0, key, value)
-    }
-
-    pub fn get_keys_and_values(&self) -> (Vec<*const c_void>, Vec<*const c_void>) {
-        let length = self.len();
-        let mut keys = Vec::with_capacity(length);
-        let mut values = Vec::with_capacity(length);
-
-        unsafe {
-            CFDictionaryGetKeysAndValues(self.0, keys.as_mut_ptr(), values.as_mut_ptr());
-            keys.set_len(length);
-            values.set_len(length);
-        }
-
-        (keys, values)
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/error.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Core Foundation errors.
-
-use core_foundation_sys::error::*;
-use core_foundation_sys::base::CFRelease;
-use std::error::Error;
-use std::fmt;
-
-use base::{CFIndex, TCFType};
-use string::CFString;
-
-/// An error value.
-pub struct CFError(CFErrorRef);
-
-impl Drop for CFError {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFError, CFErrorRef, CFErrorGetTypeID);
-
-impl fmt::Debug for CFError {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        fmt.debug_struct("CFError")
-           .field("domain", &self.domain())
-           .field("code", &self.code())
-           .field("description", &self.description())
-           .finish()
-    }
-}
-
-impl fmt::Display for CFError {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        write!(fmt, "{}", self.description())
-    }
-}
-
-impl Error for CFError {
-    fn description(&self) -> &str {
-        "a Core Foundation error"
-    }
-}
-
-impl CFError {
-    /// Returns a string identifying the domain with which this error is
-    /// associated.
-    pub fn domain(&self) -> CFString {
-        unsafe {
-            let s = CFErrorGetDomain(self.0);
-            CFString::wrap_under_get_rule(s)
-        }
-    }
-
-    /// Returns the code identifying this type of error.
-    pub fn code(&self) -> CFIndex {
-        unsafe { CFErrorGetCode(self.0) }
-    }
-
-    /// Returns a human-presentable description of the error.
-    pub fn description(&self) -> CFString {
-        unsafe {
-            let s = CFErrorCopyDescription(self.0);
-            CFString::wrap_under_create_rule(s)
-        }
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/lib.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#![allow(non_snake_case)]
-
-extern crate core_foundation_sys;
-extern crate libc;
-
-#[macro_export]
-macro_rules! impl_TCFType {
-    ($ty:ident, $raw:ident, $ty_id:ident) => {
-        impl $crate::base::TCFType<$raw> for $ty {
-            #[inline]
-            fn as_concrete_TypeRef(&self) -> $raw {
-                self.0
-            }
-
-            #[inline]
-            unsafe fn wrap_under_get_rule(reference: $raw) -> $ty {
-                let reference = ::std::mem::transmute(::core_foundation_sys::base::CFRetain(::std::mem::transmute(reference)));
-                $crate::base::TCFType::wrap_under_create_rule(reference)
-            }
-
-            #[inline]
-            fn as_CFTypeRef(&self) -> ::core_foundation_sys::base::CFTypeRef {
-                unsafe {
-                    ::std::mem::transmute(self.as_concrete_TypeRef())
-                }
-            }
-
-            #[inline]
-            unsafe fn wrap_under_create_rule(obj: $raw) -> $ty {
-                $ty(obj)
-            }
-
-            #[inline]
-            fn type_id() -> ::core_foundation_sys::base::CFTypeID {
-                unsafe {
-                    $ty_id()
-                }
-            }
-        }
-    }
-}
-
-pub mod array;
-pub mod base;
-pub mod boolean;
-pub mod data;
-pub use core_foundation_sys::date; // back compat
-pub mod dictionary;
-pub mod error;
-pub mod number;
-pub mod set;
-pub mod string;
-pub mod url;
-pub mod bundle;
-pub mod propertylist;
-pub mod runloop;
-
-#[cfg(test)]
-pub mod test {
-    #[test]
-    fn test_stuff() {
-        use base::TCFType;
-        use boolean::CFBoolean;
-        use number::number;
-        use dictionary::CFDictionary;
-        use string::CFString;
-
-        /*let n = CFNumber::new_number(42 as i32);
-        io::println(format!("%d", (&n).retain_count() as int));
-        (&n).show();*/
-
-        let bar = CFString::from_static_string("Bar");
-        let baz = CFString::from_static_string("Baz");
-        let boo = CFString::from_static_string("Boo");
-        let foo = CFString::from_static_string("Foo");
-        let tru = CFBoolean::true_value();
-        let n42 = number(42);
-
-        let d = CFDictionary::from_CFType_pairs(&[
-            (bar.as_CFType(), boo.as_CFType()),
-            (baz.as_CFType(), tru.as_CFType()),
-            (foo.as_CFType(), n42.as_CFType()),
-        ]);
-
-        let (v1, v2) = d.get_keys_and_values();
-
-        assert!(v1 == &[bar.as_CFTypeRef(), baz.as_CFTypeRef(), foo.as_CFTypeRef()]);
-        assert!(v2 == &[boo.as_CFTypeRef(), tru.as_CFTypeRef(), n42.as_CFTypeRef()]);
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/number.rs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Immutable numbers.
-
-use core_foundation_sys::base::{CFRelease, kCFAllocatorDefault};
-pub use core_foundation_sys::number::*;
-use std::mem;
-
-use base::{TCFType};
-
-/// An immutable numeric value.
-pub struct CFNumber(CFNumberRef);
-
-impl Drop for CFNumber {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFNumber, CFNumberRef, CFNumberGetTypeID);
-
-// TODO(pcwalton): Floating point.
-impl CFNumber {
-    #[inline]
-    pub fn from_i32(value: i32) -> CFNumber {
-        unsafe {
-            let number_ref = CFNumberCreate(kCFAllocatorDefault,
-                                            kCFNumberSInt32Type,
-                                            mem::transmute(&value));
-            TCFType::wrap_under_create_rule(number_ref)
-        }
-    }
-
-    #[inline]
-    pub fn to_i64(&self) -> Option<i64> {
-        unsafe {
-            let mut value: i64 = 0;
-            let ok = CFNumberGetValue(self.0, kCFNumberSInt64Type, mem::transmute(&mut value));
-            if ok { Some(value) } else { None }
-        }
-    }
-
-    #[inline]
-    pub fn to_f64(&self) -> Option<f64> {
-        unsafe {
-            let mut value: f64 = 0.0;
-            let ok = CFNumberGetValue(self.0, kCFNumberFloat64Type, mem::transmute(&mut value));
-            if ok { Some(value) } else { None }
-        }
-    }
-
-    #[inline]
-    pub fn from_i64(value: i64) -> CFNumber {
-        unsafe {
-            let number_ref = CFNumberCreate(kCFAllocatorDefault,
-                                            kCFNumberSInt64Type,
-                                            mem::transmute(&value));
-            TCFType::wrap_under_create_rule(number_ref)
-        }
-    }
-
-    #[inline]
-    pub fn from_f64(value: f64) -> CFNumber {
-        unsafe {
-            let number_ref = CFNumberCreate(kCFAllocatorDefault,
-                                            kCFNumberFloat64Type,
-                                            mem::transmute(&value));
-            TCFType::wrap_under_create_rule(number_ref)
-        }
-    }
-}
-
-/// A convenience function to create CFNumbers.
-pub fn number(value: i64) -> CFNumber {
-    CFNumber::from_i64(value)
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/propertylist.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Core Foundation property lists
-
-use std::ptr;
-
-use libc::c_void;
-
-use error::CFError;
-use data::CFData;
-use base::{TCFType};
-
-pub use core_foundation_sys::propertylist::*;
-use core_foundation_sys::error::CFErrorRef;
-use core_foundation_sys::base::{kCFAllocatorDefault};
-
-pub fn create_with_data(data: CFData,
-                        options: CFPropertyListMutabilityOptions)
-                        -> Result<(*const c_void, CFPropertyListFormat), CFError> {
-    unsafe {
-        let mut error: CFErrorRef = ptr::null_mut();
-        let mut format: CFPropertyListFormat = 0;
-        let property_list = CFPropertyListCreateWithData(kCFAllocatorDefault,
-                                                         data.as_concrete_TypeRef(),
-                                                         options,
-                                                         &mut format,
-                                                         &mut error);
-        if property_list.is_null() {
-            Err(TCFType::wrap_under_create_rule(error))
-        } else {
-            Ok((property_list, format))
-        }
-    }
-}
-
-pub fn create_data(property_list: *const c_void, format: CFPropertyListFormat) -> Result<CFData, CFError> {
-    unsafe {
-        let mut error: CFErrorRef = ptr::null_mut();
-        let data_ref = CFPropertyListCreateData(kCFAllocatorDefault,
-                                                property_list,
-                                                format,
-                                                0,
-                                                &mut error);
-        if data_ref.is_null() {
-            Err(TCFType::wrap_under_create_rule(error))
-        } else {
-            Ok(TCFType::wrap_under_create_rule(data_ref))
-        }
-    }
-}
-
-#[cfg(test)]
-pub mod test {
-    #[test]
-    fn test_property_list_serialization() {
-        use base::{TCFType, CFEqual};
-        use boolean::CFBoolean;
-        use number::number;
-        use dictionary::CFDictionary;
-        use string::CFString;
-        use super::*;
-
-        let bar = CFString::from_static_string("Bar");
-        let baz = CFString::from_static_string("Baz");
-        let boo = CFString::from_static_string("Boo");
-        let foo = CFString::from_static_string("Foo");
-        let tru = CFBoolean::true_value();
-        let n42 = number(42);
-
-        let dict1 = CFDictionary::from_CFType_pairs(&[(bar.as_CFType(), boo.as_CFType()),
-                                                      (baz.as_CFType(), tru.as_CFType()),
-                                                      (foo.as_CFType(), n42.as_CFType())]);
-
-        let data = create_data(dict1.as_CFTypeRef(), kCFPropertyListXMLFormat_v1_0).unwrap();
-        let (dict2, _) = create_with_data(data, kCFPropertyListImmutable).unwrap();
-        unsafe {
-            assert!(CFEqual(dict1.as_CFTypeRef(), dict2) == 1);
-        }
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/runloop.rs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![allow(non_upper_case_globals)]
-
-pub use core_foundation_sys::runloop::*;
-use core_foundation_sys::base::{CFIndex, CFRelease};
-use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
-use core_foundation_sys::string::CFStringRef;
-use core_foundation_sys::date::{CFAbsoluteTime, CFTimeInterval};
-
-use base::{TCFType};
-use string::{CFString};
-
-pub struct CFRunLoop(CFRunLoopRef);
-
-impl Drop for CFRunLoop {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
-
-impl CFRunLoop {
-    pub fn get_current() -> CFRunLoop {
-        unsafe {
-            let run_loop_ref = CFRunLoopGetCurrent();
-            TCFType::wrap_under_get_rule(run_loop_ref)
-        }
-    }
-
-    pub fn get_main() -> CFRunLoop {
-        unsafe {
-            let run_loop_ref = CFRunLoopGetMain();
-            TCFType::wrap_under_get_rule(run_loop_ref)
-        }
-    }
-
-    pub fn run_current() {
-        unsafe {
-            CFRunLoopRun();
-        }
-    }
-
-    pub fn stop(&self) {
-        unsafe {
-            CFRunLoopStop(self.0);
-        }
-    }
-
-    pub fn current_mode(&self) -> Option<String> {
-        unsafe {
-            let string_ref = CFRunLoopCopyCurrentMode(self.0);
-            if string_ref.is_null() {
-                return None;
-            }
-
-            let cf_string: CFString = TCFType::wrap_under_create_rule(string_ref);
-            Some(cf_string.to_string())
-        }
-    }
-
-    pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFStringRef) -> bool {
-        unsafe {
-            CFRunLoopContainsTimer(self.0, timer.0, mode) != 0
-        }
-    }
-
-    pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFStringRef) {
-        unsafe {
-            CFRunLoopAddTimer(self.0, timer.0, mode);
-        }
-    }
-
-}
-
-pub struct CFRunLoopTimer(CFRunLoopTimerRef);
-
-impl Drop for CFRunLoopTimer {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID);
-
-impl CFRunLoopTimer {
-    pub fn new(fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimer {
-        unsafe {
-            let timer_ref = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, interval, flags, order, callout, context);
-            TCFType::wrap_under_create_rule(timer_ref)
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use core_foundation_sys::date::{CFAbsoluteTime, CFAbsoluteTimeGetCurrent};
-    use std::mem;
-    use libc::c_void;
-
-    #[test]
-    fn wait_200_milliseconds() {
-        let run_loop = CFRunLoop::get_current();
-        let mut now = unsafe { CFAbsoluteTimeGetCurrent() };
-        let mut context = unsafe { CFRunLoopTimerContext {
-            version: 0,
-            info: mem::transmute(&mut now),
-            retain: mem::zeroed(),
-            release: mem::zeroed(),
-            copyDescription: mem::zeroed(),
-        } };
-
-
-        let run_loop_timer = CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
-        run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode);
-
-        CFRunLoop::run_current();
-    }
-
-    extern "C" fn timer_popped(_timer: CFRunLoopTimerRef, _info: *mut c_void) {
-        let previous_now_ptr: *const CFAbsoluteTime = unsafe { mem::transmute(_info) };
-        let previous_now = unsafe { *previous_now_ptr };
-        let now = unsafe { CFAbsoluteTimeGetCurrent() };
-        assert!(now - previous_now > 0.19 && now - previous_now < 0.21);
-        CFRunLoop::get_current().stop();
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/set.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! An immutable bag of elements.
-
-pub use core_foundation_sys::set::*;
-use core_foundation_sys::base::CFRelease;
-use core_foundation_sys::base::{CFTypeRef, kCFAllocatorDefault};
-
-use base::{CFIndexConvertible, TCFType};
-
-use std::mem;
-
-/// An immutable bag of elements.
-pub struct CFSet(CFSetRef);
-
-impl Drop for CFSet {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFSet, CFSetRef, CFSetGetTypeID);
-
-impl CFSet {
-    /// Creates a new set from a list of `CFType` instances.
-    pub fn from_slice<R, T>(elems: &[T]) -> CFSet where T: TCFType<R> {
-        unsafe {
-            let elems: Vec<CFTypeRef> = elems.iter().map(|elem| elem.as_CFTypeRef()).collect();
-            let set_ref = CFSetCreate(kCFAllocatorDefault,
-                                      mem::transmute(elems.as_ptr()),
-                                      elems.len().to_CFIndex(),
-                                      &kCFTypeSetCallBacks);
-            TCFType::wrap_under_create_rule(set_ref)
-        }
-    }
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/string.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Immutable strings.
-
-pub use core_foundation_sys::string::*;
-
-use base::{CFIndexConvertible, TCFType};
-
-use core_foundation_sys::base::{Boolean, CFIndex, CFRange, CFRelease};
-use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
-use std::fmt;
-use std::str::{self, FromStr};
-use std::ptr;
-use std::ffi::CStr;
-
-/// An immutable string in one of a variety of encodings.
-pub struct CFString(CFStringRef);
-
-impl Clone for CFString {
-    #[inline]
-    fn clone(&self) -> CFString {
-        unsafe {
-            TCFType::wrap_under_get_rule(self.0)
-        }
-    }
-}
-
-impl Drop for CFString {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID);
-
-impl FromStr for CFString {
-    type Err = ();
-
-    /// See also CFString::new for a variant of this which does not return a Result
-    #[inline]
-    fn from_str(string: &str) -> Result<CFString, ()> {
-        Ok(CFString::new(string))
-    }
-}
-
-impl fmt::Display for CFString {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        unsafe {
-            // Do this without allocating if we can get away with it
-            let c_string = CFStringGetCStringPtr(self.0, kCFStringEncodingUTF8);
-            if c_string != ptr::null() {
-                let c_str = CStr::from_ptr(c_string);
-                fmt.write_str(str::from_utf8_unchecked(c_str.to_bytes()))
-            } else {
-                let char_len = self.char_len();
-
-                // First, ask how big the buffer ought to be.
-                let mut bytes_required: CFIndex = 0;
-                CFStringGetBytes(self.0,
-                                 CFRange { location: 0, length: char_len },
-                                 kCFStringEncodingUTF8,
-                                 0,
-                                 false as Boolean,
-                                 ptr::null_mut(),
-                                 0,
-                                 &mut bytes_required);
-
-                // Then, allocate the buffer and actually copy.
-                let mut buffer = vec![b'\x00'; bytes_required as usize];
-
-                let mut bytes_used: CFIndex = 0;
-                let chars_written = CFStringGetBytes(self.0,
-                                                     CFRange { location: 0, length: char_len },
-                                                     kCFStringEncodingUTF8,
-                                                     0,
-                                                     false as Boolean,
-                                                     buffer.as_mut_ptr(),
-                                                     buffer.len().to_CFIndex(),
-                                                     &mut bytes_used) as usize;
-                assert!(chars_written.to_CFIndex() == char_len);
-
-                // This is dangerous; we over-allocate and null-terminate the string (during
-                // initialization).
-                assert!(bytes_used == buffer.len().to_CFIndex());
-                fmt.write_str(str::from_utf8_unchecked(&buffer))
-            }
-        }
-    }
-}
-
-impl fmt::Debug for CFString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "\"{}\"", self)
-    }
-}
-
-
-impl CFString {
-    /// Creates a new `CFString` instance from a Rust string.
-    #[inline]
-    pub fn new(string: &str) -> CFString {
-        unsafe {
-            let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault,
-                                                     string.as_ptr(),
-                                                     string.len().to_CFIndex(),
-                                                     kCFStringEncodingUTF8,
-                                                     false as Boolean,
-                                                     kCFAllocatorNull);
-            CFString::wrap_under_create_rule(string_ref)
-        }
-    }
-
-    /// Like `CFString::new`, but references a string that can be used as a backing store
-    /// by virtue of being statically allocated.
-    #[inline]
-    pub fn from_static_string(string: &'static str) -> CFString {
-        unsafe {
-            let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
-                                                           string.as_ptr(),
-                                                           string.len().to_CFIndex(),
-                                                           kCFStringEncodingUTF8,
-                                                           false as Boolean,
-                                                           kCFAllocatorNull);
-            TCFType::wrap_under_create_rule(string_ref)
-        }
-    }
-
-    /// Returns the number of characters in the string.
-    #[inline]
-    pub fn char_len(&self) -> CFIndex {
-        unsafe {
-            CFStringGetLength(self.0)
-        }
-    }
-}
-
-#[test]
-fn string_and_back() {
-    let original = "The quick brown fox jumped over the slow lazy dog.";
-    let cfstr = CFString::from_static_string(original);
-    let converted = cfstr.to_string();
-    assert!(converted == original);
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-0.2.3/src/url.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A URL type for Core Foundation.
-
-pub use core_foundation_sys::url::*;
-
-use base::{TCFType};
-use string::{CFString};
-
-use core_foundation_sys::base::{kCFAllocatorDefault, CFRelease};
-use std::fmt;
-
-pub struct CFURL(CFURLRef);
-
-impl Drop for CFURL {
-    fn drop(&mut self) {
-        unsafe {
-            CFRelease(self.as_CFTypeRef())
-        }
-    }
-}
-
-impl_TCFType!(CFURL, CFURLRef, CFURLGetTypeID);
-
-impl fmt::Debug for CFURL {
-    #[inline]
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        unsafe {
-            let string: CFString = TCFType::wrap_under_get_rule(CFURLGetString(self.0));
-            write!(f, "{}", string.to_string())
-        }
-    }
-}
-
-impl CFURL {
-    pub fn from_file_system_path(filePath: CFString, pathStyle: CFURLPathStyle, isDirectory: bool) -> CFURL {
-        unsafe {
-            let url_ref = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath.as_concrete_TypeRef(), pathStyle, isDirectory as u8);
-            TCFType::wrap_under_create_rule(url_ref)
-        }
-    }
-
-    pub fn get_string(&self) -> CFString {
-        unsafe {
-            TCFType::wrap_under_get_rule(CFURLGetString(self.0))
-        }
-    }
-}
-
-#[test]
-fn file_url_from_path() {
-    let path = "/usr/local/foo/";
-    let cfstr_path = CFString::from_static_string(path);
-    let cfurl = CFURL::from_file_system_path(cfstr_path, kCFURLPOSIXPathStyle, true);
-    assert!(cfurl.get_string().to_string() == "file:///usr/local/foo/");
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","Cargo.toml":"f99593f6c99ed02fd0bd95592e27fd84e0e7508f5ad4c27a185d0c29c1bc38e2","build.rs":"4dbf3e5a423e5eba48fc7f11e4f7638c054e53a3750c888059a96d96f8923ef2","src/array.rs":"d648ed8cf0ccb72c3ca0d9e018a3db804edad9685739eba13f8f515e04f3708b","src/base.rs":"36e8ba1ef798331679972e532a61447a327c2af7697631cb25040b581839410c","src/bundle.rs":"ff5f5253f331b7fa054414a3f256d74760e3ce805b720cdb735a2e46cc66dce6","src/data.rs":"21e968951fe56e080d33474f4438de2dfb7e0c8af426a6dfb100efdd6c530eec","src/date.rs":"f6cdcb94658fafc5bacb83cfbd20ad97502b8ddf6bd1c0c0d6a2545a4f7b7420","src/dictionary.rs":"97c40c1afc719b970968179112ad76c3c89b6b4eb4ea18f7ac3f059d98cce736","src/error.rs":"61bc31a401ec6c8495668175eade9284e257da056fc666af74a5555af5daf33f","src/lib.rs":"8bdbc6ed8fcbbc5b69d7634031ff44d50b9ac789279eb89b80c280ea156c98b3","src/messageport.rs":"59ba92ca90bb9b3162b6df44188fac18cd979250f33a52361144c902e86529bd","src/number.rs":"8881c7cd1b510c654c445485de898f83abda91557fd3e6f9daccf2d1b9c4c57e","src/propertylist.rs":"cc2b27f8f8ebc80c03871b7b1ad50ee348539b016078ce721c86b8cd5f9d75bd","src/runloop.rs":"7feab3bbb9913c3b40285bc37b920f9fe4d937d1db08d8ae69a2ec9597713598","src/set.rs":"51e978fc81d4c55013dfc6df4e76c58daaf5deedf9aafda0f6a9e04e7575272c","src/string.rs":"27b92e8e5d3fc95a521dc6447ccfefd9eb28ec5f42bd8571defd124d950b133f","src/url.rs":"bd9f162e2e3e316267b0d36c4d0551dbf2435a40bd1e69bbe0efafd72d232432"},"package":"065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d"}
\ No newline at end of file
deleted file mode 100644
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "core-foundation-sys"
-description = "Bindings to Core Foundation for OS X"
-homepage = "https://github.com/servo/core-foundation-rs"
-repository = "https://github.com/servo/core-foundation-rs"
-version = "0.2.3"
-authors = ["The Servo Project Developers"]
-license = "MIT / Apache-2.0"
-build = "build.rs"
-links = "CoreFoundation.framework"
-
-[dependencies]
-libc = "0.2"
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/build.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    println!("cargo:rustc-link-lib=framework=CoreFoundation");
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/array.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::{CFRange, CFIndex, CFAllocatorRef, CFTypeID};
-
-/// FIXME(pcwalton): This is wrong.
-pub type CFArrayRetainCallBack = *const u8;
-
-/// FIXME(pcwalton): This is wrong.
-pub type CFArrayReleaseCallBack = *const u8;
-
-/// FIXME(pcwalton): This is wrong.
-pub type CFArrayCopyDescriptionCallBack = *const u8;
-
-/// FIXME(pcwalton): This is wrong.
-pub type CFArrayEqualCallBack = *const u8;
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct CFArrayCallBacks {
-    pub version: CFIndex,
-    pub retain: CFArrayRetainCallBack,
-    pub release: CFArrayReleaseCallBack,
-    pub copyDescription: CFArrayCopyDescriptionCallBack,
-    pub equal: CFArrayEqualCallBack,
-}
-
-#[repr(C)]
-pub struct __CFArray(c_void);
-
-pub type CFArrayRef = *const __CFArray;
-
-extern {
-    /*
-     * CFArray.h
-     */
-    pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
-
-    pub fn CFArrayCreate(allocator: CFAllocatorRef, values: *const *const c_void,
-                     numValues: CFIndex, callBacks: *const CFArrayCallBacks) -> CFArrayRef;
-    pub fn CFArrayCreateCopy(allocator: CFAllocatorRef , theArray: CFArrayRef) -> CFArrayRef;
-    
-    // CFArrayBSearchValues
-    // CFArrayContainsValue
-    pub fn CFArrayGetCount(theArray: CFArrayRef) -> CFIndex;
-    // CFArrayGetCountOfValue
-    // CFArrayGetFirstIndexOfValue
-    // CFArrayGetLastIndexOfValue
-    pub fn CFArrayGetValues(theArray: CFArrayRef, range: CFRange, values: *mut *const c_void);
-    pub fn CFArrayGetValueAtIndex(theArray: CFArrayRef, idx: CFIndex) -> *const c_void;
-    // CFArrayApplyFunction
-    pub fn CFArrayGetTypeID() -> CFTypeID;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/base.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::{c_uint, c_long, c_ulong, c_void};
-
-pub type Boolean = u8;
-pub type CFIndex = c_long;
-pub type mach_port_t = c_uint;
-pub type CFAllocatorRef = *const c_void;
-pub type CFNullRef = *const c_void;
-pub type CFHashCode = c_ulong;
-pub type CFTypeID = c_ulong;
-pub type CFTypeRef = *const c_void;
-pub type CFOptionFlags = u32;
-pub type OSStatus = i32;
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct CFRange {
-    pub location: CFIndex,
-    pub length: CFIndex
-}
-
-// for back-compat
-impl CFRange {
-    pub fn init(location: CFIndex, length: CFIndex) -> CFRange {
-        CFRange {
-            location: location,
-            length: length,
-        }
-    }
-}
-
-extern {
-    /*
-     * CFBase.h
-     */
-
-    /* CFAllocator Reference */
-    // N.B. Many CFAllocator functions and constants are omitted here.
-    pub static kCFAllocatorDefault: CFAllocatorRef;
-    pub static kCFAllocatorSystemDefault: CFAllocatorRef;
-    pub static kCFAllocatorMalloc: CFAllocatorRef;
-    pub static kCFAllocatorMallocZone: CFAllocatorRef;
-    pub static kCFAllocatorNull: CFAllocatorRef;
-    pub static kCFAllocatorUseContext: CFAllocatorRef;
-
-    /* CFNull Reference */
-
-    pub static kCFNull: CFNullRef;
-
-    /* CFType Reference */
-
-    //fn CFCopyDescription
-    //fn CFCopyTypeIDDescription
-    //fn CFEqual
-    //fn CFGetAllocator
-    pub fn CFEqual(cf1: CFTypeRef, cf2: CFTypeRef) -> Boolean;
-    pub fn CFGetRetainCount(cf: CFTypeRef) -> CFIndex;
-    pub fn CFGetTypeID(cf: CFTypeRef) -> CFTypeID;
-    pub fn CFHash(cf: CFTypeRef) -> CFHashCode;
-    //fn CFMakeCollectable
-    pub fn CFRelease(cf: CFTypeRef);
-    pub fn CFRetain(cf: CFTypeRef) -> CFTypeRef;
-    pub fn CFShow(obj: CFTypeRef);
-
-    /* Base Utilities Reference */
-    // N.B. Some things missing here.
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/bundle.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::CFTypeID;
-use dictionary::CFDictionaryRef;
-use string::CFStringRef;
-
-#[repr(C)]
-pub struct __CFBundle(c_void);
-
-pub type CFBundleRef = *const __CFBundle;
-
-extern {
-    /*
-     * CFBundle.h
-     */
-    pub fn CFBundleGetBundleWithIdentifier(bundleID: CFStringRef) -> CFBundleRef;
-    pub fn CFBundleGetFunctionPointerForName(bundle: CFBundleRef, function_name: CFStringRef) -> *const c_void;
-    pub fn CFBundleGetMainBundle() -> CFBundleRef;
-    pub fn CFBundleGetInfoDictionary(bundle: CFBundleRef) -> CFDictionaryRef;
-
-    pub fn CFBundleGetTypeID() -> CFTypeID;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/data.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-use libc::c_void;
-
-use base::{CFAllocatorRef, CFTypeID, CFIndex};
-
-#[repr(C)]
-pub struct __CFData(c_void);
-
-pub type CFDataRef = *const __CFData;
-
-extern {
-    /*
-     * CFData.h
-     */
-
-    pub fn CFDataCreate(allocator: CFAllocatorRef,
-                        bytes: *const u8, length: CFIndex) -> CFDataRef;
-    //fn CFDataFind
-    pub fn CFDataGetBytePtr(theData: CFDataRef) -> *const u8;
-    pub fn CFDataGetLength(theData: CFDataRef) -> CFIndex;
-
-    pub fn CFDataGetTypeID() -> CFTypeID;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/date.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub type CFTimeInterval = f64;
-pub type CFAbsoluteTime = CFTimeInterval;
-
-extern {
-    pub fn CFAbsoluteTimeGetCurrent() -> CFAbsoluteTime;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/dictionary.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::{c_void};
-
-use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean};
-
-pub type CFDictionaryApplierFunction = extern "C" fn (key: *const c_void,
-                                                      value: *const c_void,
-                                                      context: *mut c_void);
-pub type CFDictionaryCopyDescriptionCallBack = *const u8;
-pub type CFDictionaryEqualCallBack = *const u8;
-pub type CFDictionaryHashCallBack = *const u8;
-pub type CFDictionaryReleaseCallBack = *const u8;
-pub type CFDictionaryRetainCallBack = *const u8;
-
-#[allow(dead_code)]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct CFDictionaryKeyCallBacks {
-    pub version: CFIndex,
-    pub retain: CFDictionaryRetainCallBack,
-    pub release: CFDictionaryReleaseCallBack,
-    pub copyDescription: CFDictionaryCopyDescriptionCallBack,
-    pub equal: CFDictionaryEqualCallBack,
-    pub hash: CFDictionaryHashCallBack
-}
-
-#[allow(dead_code)]
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct CFDictionaryValueCallBacks {
-    pub version: CFIndex,
-    pub retain: CFDictionaryRetainCallBack,
-    pub release: CFDictionaryReleaseCallBack,
-    pub copyDescription: CFDictionaryCopyDescriptionCallBack,
-    pub equal: CFDictionaryEqualCallBack
-}
-
-#[repr(C)]
-pub struct __CFDictionary(c_void);
-
-pub type CFDictionaryRef = *const __CFDictionary;
-pub type CFMutableDictionaryRef = *const __CFDictionary;
-
-extern {
-    /*
-     * CFDictionary.h
-     */
-
-    pub static kCFTypeDictionaryKeyCallBacks: CFDictionaryKeyCallBacks;
-    pub static kCFTypeDictionaryValueCallBacks: CFDictionaryValueCallBacks;
-
-    pub fn CFDictionaryContainsKey(theDict: CFDictionaryRef, key: *const c_void) -> Boolean;
-    pub fn CFDictionaryCreate(allocator: CFAllocatorRef, keys: *const *const c_void, values: *const *const c_void,
-                              numValues: CFIndex, keyCallBacks: *const CFDictionaryKeyCallBacks,
-                              valueCallBacks: *const CFDictionaryValueCallBacks)
-                              -> CFDictionaryRef;
-    pub fn CFDictionaryGetCount(theDict: CFDictionaryRef) -> CFIndex;
-    pub fn CFDictionaryGetTypeID() -> CFTypeID;
-    pub fn CFDictionaryGetValueIfPresent(theDict: CFDictionaryRef, key: *const c_void, value: *mut *const c_void)
-                                         -> Boolean;
-    pub fn CFDictionaryApplyFunction(theDict: CFDictionaryRef,
-                                     applier: CFDictionaryApplierFunction,
-                                     context: *mut c_void);
-    pub fn CFDictionarySetValue(theDict: CFMutableDictionaryRef,
-                                key: *const c_void,
-                                value: *const c_void);
-    pub fn CFDictionaryGetKeysAndValues(theDict: CFDictionaryRef,
-                                        keys: *mut *const c_void,
-                                        values: *mut *const c_void);
-
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/error.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::{CFTypeID, CFIndex};
-use string::CFStringRef;
-
-#[repr(C)]
-pub struct __CFError(c_void);
-
-pub type CFErrorRef = *mut __CFError;
-
-extern "C" {
-    pub fn CFErrorGetTypeID() -> CFTypeID;
-
-    pub static kCFErrorDomainPOSIX: CFStringRef;
-    pub static kCFErrorDomainOSStatus: CFStringRef;
-    pub static kCFErrorDomainMach: CFStringRef;
-    pub static kCFErrorDomainCocoa: CFStringRef;
-
-    pub fn CFErrorGetDomain(err: CFErrorRef) -> CFStringRef;
-    pub fn CFErrorGetCode(err: CFErrorRef) -> CFIndex;
-
-    pub fn CFErrorCopyDescription(err: CFErrorRef) -> CFStringRef;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/lib.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals, improper_ctypes)]
-
-extern crate libc;
-
-pub mod array;
-pub mod base;
-pub mod bundle;
-pub mod data;
-pub mod date;
-pub mod dictionary;
-pub mod error;
-pub mod messageport;
-pub mod number;
-pub mod propertylist;
-pub mod runloop;
-pub mod set;
-pub mod string;
-pub mod url;
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/messageport.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::{CFAllocatorRef, CFIndex, CFTypeID, Boolean};
-use data::CFDataRef;
-use date::CFTimeInterval;
-use runloop::CFRunLoopSourceRef;
-use string::CFStringRef;
-
-#[repr(C)]
-#[derive(Copy, Clone)]
-#[derive(Debug)]
-pub struct CFMessagePortContext {
-    pub version: CFIndex,
-    pub info: *mut c_void,
-    pub retain: Option<unsafe extern fn(info: *const c_void) -> *const c_void>,
-    pub release: Option<unsafe extern fn(info: *const c_void)>,
-    pub copyDescription: Option<unsafe extern fn(info: *const c_void)
-        -> CFStringRef>,
-}
-
-pub type CFMessagePortCallBack = Option<
-    unsafe extern fn(local: CFMessagePortRef,
-                     msgid: i32,
-                     data: CFDataRef,
-                     info: *mut c_void) -> CFDataRef>;
-
-pub type CFMessagePortInvalidationCallBack = Option<
-    unsafe extern "C" fn(ms: CFMessagePortRef, info: *mut c_void)>;
-
-#[repr(C)]
-pub struct __CFMessagePort(c_void);
-pub type CFMessagePortRef = *const __CFMessagePort;
-
-extern {
-    /*
-     * CFMessagePort.h
-     */
-    pub fn CFMessagePortGetTypeID() -> CFTypeID;
-    pub fn CFMessagePortCreateLocal(allocator: CFAllocatorRef,
-                                    name: CFStringRef,
-                                    callout: CFMessagePortCallBack,
-                                    context: *const CFMessagePortContext,
-                                    shouldFreeInfo: *mut Boolean)
-        -> CFMessagePortRef;
-    pub fn CFMessagePortCreateRemote(allocator: CFAllocatorRef,
-                                     name: CFStringRef) -> CFMessagePortRef;
-    pub fn CFMessagePortIsRemote(ms: CFMessagePortRef) -> Boolean;
-    pub fn CFMessagePortGetName(ms: CFMessagePortRef) -> CFStringRef;
-    pub fn CFMessagePortSetName(ms: CFMessagePortRef, newName: CFStringRef)
-        -> Boolean;
-    pub fn CFMessagePortGetContext(ms: CFMessagePortRef,
-                                   context: *mut CFMessagePortContext);
-    pub fn CFMessagePortInvalidate(ms: CFMessagePortRef);
-    pub fn CFMessagePortIsValid(ms: CFMessagePortRef) -> Boolean;
-    pub fn CFMessagePortGetInvalidationCallBack(ms: CFMessagePortRef)
-        -> CFMessagePortInvalidationCallBack;
-    pub fn CFMessagePortSetInvalidationCallBack(ms: CFMessagePortRef,
-                                                callout: CFMessagePortInvalidationCallBack);
-    pub fn CFMessagePortSendRequest(remote: CFMessagePortRef, msgid: i32,
-                                    data: CFDataRef,
-                                    sendTimeout: CFTimeInterval,
-                                    rcvTimeout: CFTimeInterval,
-                                    replyMode: CFStringRef,
-                                    returnData: *mut CFDataRef) -> i32;
-    pub fn CFMessagePortCreateRunLoopSource(allocator: CFAllocatorRef,
-                                            local: CFMessagePortRef,
-                                            order: CFIndex)
-        -> CFRunLoopSourceRef;
-    // CFMessagePortSetDispatchQueue
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/number.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::{CFAllocatorRef, CFTypeID};
-
-#[repr(C)]
-pub struct __CFBoolean(c_void);
-
-pub type CFBooleanRef = *const __CFBoolean;
-
-pub type CFNumberType = u32;
-
-// members of enum CFNumberType
-// static kCFNumberSInt8Type:     CFNumberType = 1;
-// static kCFNumberSInt16Type:    CFNumberType = 2;
-pub static kCFNumberSInt32Type:    CFNumberType = 3;
-pub static kCFNumberSInt64Type:    CFNumberType = 4;
-// static kCFNumberFloat32Type:   CFNumberType = 5;
-pub static kCFNumberFloat64Type:   CFNumberType = 6;
-// static kCFNumberCharType:      CFNumberType = 7;
-// static kCFNumberShortType:     CFNumberType = 8;
-// static kCFNumberIntType:       CFNumberType = 9;
-// static kCFNumberLongType:      CFNumberType = 10;
-// static kCFNumberLongLongType:  CFNumberType = 11;
-// static kCFNumberFloatType:     CFNumberType = 12;
-// static kCFNumberDoubleType:    CFNumberType = 13;
-// static kCFNumberCFIndexType:   CFNumberType = 14;
-// static kCFNumberNSIntegerType: CFNumberType = 15;
-// static kCFNumberCGFloatType:   CFNumberType = 16;
-// static kCFNumberMaxType:       CFNumberType = 16;
-
-#[repr(C)]
-pub struct __CFNumber;
-
-pub type CFNumberRef = *const __CFNumber;
-
-extern {
-    /*
-     * CFNumber.h
-     */
-    pub static kCFBooleanTrue: CFBooleanRef;
-    pub static kCFBooleanFalse: CFBooleanRef;
-
-    pub fn CFBooleanGetTypeID() -> CFTypeID;
-    pub fn CFNumberCreate(allocator: CFAllocatorRef, theType: CFNumberType, valuePtr: *const c_void)
-                          -> CFNumberRef;
-    //fn CFNumberGetByteSize
-    pub fn CFNumberGetValue(number: CFNumberRef, theType: CFNumberType, valuePtr: *mut c_void) -> bool;
-    //fn CFNumberCompare
-    pub fn CFNumberGetTypeID() -> CFTypeID;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/propertylist.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-use base::{CFAllocatorRef, CFIndex, CFOptionFlags, CFTypeRef};
-use data::CFDataRef;
-use error::CFErrorRef;
-
-pub type CFPropertyListRef = CFTypeRef;
-
-pub type CFPropertyListFormat = CFIndex;
-pub const kCFPropertyListOpenStepFormat: CFPropertyListFormat = 1;
-pub const kCFPropertyListXMLFormat_v1_0: CFPropertyListFormat = 100;
-pub const kCFPropertyListBinaryFormat_v1_0: CFPropertyListFormat = 200;
-
-pub type CFPropertyListMutabilityOptions = CFOptionFlags;
-pub const kCFPropertyListImmutable: CFPropertyListMutabilityOptions = 0;
-pub const kCFPropertyListMutableContainers: CFPropertyListMutabilityOptions = 1;
-pub const kCFPropertyListMutableContainersAndLeaves: CFPropertyListMutabilityOptions = 2;
-
-extern "C" {
-    // CFPropertyList.h
-    //
-
-    // fn CFPropertyListCreateDeepCopy
-    // fn CFPropertyListIsValid
-    pub fn CFPropertyListCreateWithData(allocator: CFAllocatorRef,
-                                        data: CFDataRef,
-                                        options: CFPropertyListMutabilityOptions,
-                                        format: *mut CFPropertyListFormat,
-                                        error: *mut CFErrorRef)
-                                        -> CFPropertyListRef;
-    // fn CFPropertyListCreateWithStream
-    // fn CFPropertyListWrite
-    pub fn CFPropertyListCreateData(allocator: CFAllocatorRef,
-                                    propertyList: CFPropertyListRef,
-                                    format: CFPropertyListFormat,
-                                    options: CFOptionFlags,
-                                    error: *mut CFErrorRef)
-                                    -> CFDataRef;
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/runloop.rs
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use array::CFArrayRef;
-use base::{Boolean, CFIndex, CFTypeID, CFAllocatorRef, CFOptionFlags, CFHashCode, mach_port_t};
-use date::{CFAbsoluteTime, CFTimeInterval};
-use string::CFStringRef;
-
-#[repr(C)]
-pub struct __CFRunLoop(c_void);
-
-pub type CFRunLoopRef = *const __CFRunLoop;
-
-#[repr(C)]
-pub struct __CFRunLoopSource(c_void);
-
-pub type CFRunLoopSourceRef = *const __CFRunLoopSource;
-
-#[repr(C)]
-pub struct __CFRunLoopObserver(c_void);
-
-pub type CFRunLoopObserverRef = *const __CFRunLoopObserver;
-
-// Reasons for CFRunLoopRunInMode() to Return
-pub const kCFRunLoopRunFinished: i32      = 1;
-pub const kCFRunLoopRunStopped: i32       = 2;
-pub const kCFRunLoopRunTimedOut: i32      = 3;
-pub const kCFRunLoopRunHandledSource: i32 = 4;
-
-// Run Loop Observer Activities
-//typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
-pub type CFRunLoopActivity = CFOptionFlags;
-pub const kCFRunLoopEntry: CFOptionFlags         = 1 << 0;
-pub const kCFRunLoopBeforeTimers: CFOptionFlags  = 1 << 1;
-pub const kCFRunLoopBeforeSources: CFOptionFlags = 1 << 2;
-pub const kCFRunLoopBeforeWaiting: CFOptionFlags = 1 << 5;
-pub const kCFRunLoopAfterWaiting: CFOptionFlags  = 1 << 6;
-pub const kCFRunLoopExit: CFOptionFlags          = 1 << 7;
-pub const kCFRunLoopAllActivities: CFOptionFlags = 0x0FFFFFFF;
-
-#[repr(C)]
-pub struct CFRunLoopSourceContext {
-    pub version: CFIndex,
-    pub info: *mut c_void,
-    pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
-    pub release: extern "C" fn (info: *const c_void),
-    pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
-    pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean,
-    pub hash: extern "C" fn (info: *const c_void) -> CFHashCode,
-    pub schedule: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef),
-    pub cancel: extern "C" fn (info: *const c_void, rl: CFRunLoopRef, mode: CFStringRef),
-    pub perform: extern "C" fn (info: *const c_void),
-}
-
-#[repr(C)]
-pub struct CFRunLoopSourceContext1 {
-    pub version: CFIndex,
-    pub info: *mut c_void,
-    pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
-    pub release: extern "C" fn (info: *const c_void),
-    pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
-    pub equal: extern "C" fn (info1: *const c_void, info2: *const c_void) -> Boolean,
-    pub hash: extern "C" fn (info: *const c_void) -> CFHashCode,
-    // note that the following two fields are platform dependent in the C header, the ones here are for OS X
-    pub getPort: extern "C" fn (info: *mut c_void) -> mach_port_t,
-    pub perform: extern "C" fn (msg: *mut c_void, size: CFIndex, allocator: CFAllocatorRef, info: *mut c_void) -> *mut c_void,
-}
-
-#[repr(C)]
-pub struct CFRunLoopObserverContext {
-    pub version: CFIndex,
-    pub info: *mut c_void,
-    pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
-    pub release: extern "C" fn (info: *const c_void),
-    pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
-}
-
-pub type CFRunLoopObserverCallBack = extern "C" fn (observer: CFRunLoopObserverRef, activity: CFRunLoopActivity, info: *mut c_void);
-
-#[repr(C)]
-pub struct CFRunLoopTimerContext {
-    pub version: CFIndex,
-    pub info: *mut c_void,
-    pub retain: extern "C" fn (info: *const c_void) -> *const c_void,
-    pub release: extern "C" fn (info: *const c_void),
-    pub copyDescription: extern "C" fn (info: *const c_void) -> CFStringRef,
-}
-
-pub type CFRunLoopTimerCallBack = extern "C" fn (timer: CFRunLoopTimerRef, info: *mut c_void);
-
-#[repr(C)]
-pub struct __CFRunLoopTimer;
-
-pub type CFRunLoopTimerRef = *const __CFRunLoopTimer;
-
-extern {
-    /*
-     * CFRunLoop.h
-     */
-    pub static kCFRunLoopDefaultMode: CFStringRef;
-    pub static kCFRunLoopCommonModes: CFStringRef;
-    pub fn CFRunLoopGetTypeID() -> CFTypeID;
-    pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;
-    pub fn CFRunLoopGetMain() -> CFRunLoopRef;
-    pub fn CFRunLoopCopyCurrentMode(rl: CFRunLoopRef) -> CFStringRef;
-    pub fn CFRunLoopCopyAllModes(rl: CFRunLoopRef) -> CFArrayRef;
-    pub fn CFRunLoopAddCommonMode(rl: CFRunLoopRef, mode: CFStringRef);
-    pub fn CFRunLoopGetNextTimerFireDate(rl: CFRunLoopRef, mode: CFStringRef) -> CFAbsoluteTime;
-    pub fn CFRunLoopRun();
-    pub fn CFRunLoopRunInMode(mode: CFStringRef, seconds: CFTimeInterval, returnAfterSourceHandled: Boolean) -> i32;
-    pub fn CFRunLoopIsWaiting(rl: CFRunLoopRef) -> Boolean;
-    pub fn CFRunLoopWakeUp(rl: CFRunLoopRef);
-    pub fn CFRunLoopStop(rl: CFRunLoopRef);
-    // fn CFRunLoopPerformBlock(rl: CFRunLoopRef, mode: CFTypeRef, block: void (^)(void));
-    pub fn CFRunLoopContainsSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef) -> Boolean;
-    pub fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
-    pub fn CFRunLoopRemoveSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef);
-    pub fn CFRunLoopContainsObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef) -> Boolean;
-    pub fn CFRunLoopAddObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
-    pub fn CFRunLoopRemoveObserver(rl: CFRunLoopRef, observer: CFRunLoopObserverRef, mode: CFStringRef);
-    pub fn CFRunLoopContainsTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef) -> Boolean;
-    pub fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
-    pub fn CFRunLoopRemoveTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef);
-
-    pub fn CFRunLoopSourceGetTypeID() -> CFTypeID;
-    pub fn CFRunLoopSourceCreate(allocator: CFAllocatorRef, order: CFIndex, context: *mut CFRunLoopSourceContext) -> CFRunLoopSourceRef;
-    pub fn CFRunLoopSourceGetOrder(source: CFRunLoopSourceRef) -> CFIndex;
-    pub fn CFRunLoopSourceInvalidate(source: CFRunLoopSourceRef);
-    pub fn CFRunLoopSourceIsValid(source: CFRunLoopSourceRef) -> Boolean;
-    pub fn CFRunLoopSourceGetContext(source: CFRunLoopSourceRef, context: *mut CFRunLoopSourceContext);
-    pub fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef);
-
-    pub fn CFRunLoopObserverGetTypeID() -> CFTypeID;
-    pub fn CFRunLoopObserverCreate(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, callout: CFRunLoopObserverCallBack, context: *mut CFRunLoopObserverContext) -> CFRunLoopObserverRef;
-    // fn CFRunLoopObserverCreateWithHandler(allocator: CFAllocatorRef, activities: CFOptionFlags, repeats: Boolean, order: CFIndex, block: void (^) (CFRunLoopObserverRef observer, CFRunLoopActivity activity)) -> CFRunLoopObserverRef;
-    pub fn CFRunLoopObserverGetActivities(observer: CFRunLoopObserverRef) -> CFOptionFlags;
-    pub fn CFRunLoopObserverDoesRepeat(observer: CFRunLoopObserverRef) -> Boolean;
-    pub fn CFRunLoopObserverGetOrder(observer: CFRunLoopObserverRef) -> CFIndex;
-    pub fn CFRunLoopObserverInvalidate(observer: CFRunLoopObserverRef);
-    pub fn CFRunLoopObserverIsValid(observer: CFRunLoopObserverRef) -> Boolean;
-    pub fn CFRunLoopObserverGetContext(observer: CFRunLoopObserverRef, context: *mut CFRunLoopObserverContext);
-
-    pub fn CFRunLoopTimerGetTypeID() -> CFTypeID;
-    pub fn CFRunLoopTimerCreate(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimerRef;
-    // fn CFRunLoopTimerCreateWithHandler(allocator: CFAllocatorRef, fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, block: void (^) (CFRunLoopTimerRef timer)) -> CFRunLoopTimerRef;
-    pub fn CFRunLoopTimerGetNextFireDate(timer: CFRunLoopTimerRef) -> CFAbsoluteTime;
-    pub fn CFRunLoopTimerSetNextFireDate(timer: CFRunLoopTimerRef, fireDate: CFAbsoluteTime);
-    pub fn CFRunLoopTimerGetInterval(timer: CFRunLoopTimerRef) -> CFTimeInterval;
-    pub fn CFRunLoopTimerDoesRepeat(timer: CFRunLoopTimerRef) -> Boolean;
-    pub fn CFRunLoopTimerGetOrder(timer: CFRunLoopTimerRef) -> CFIndex;
-    pub fn CFRunLoopTimerInvalidate(timer: CFRunLoopTimerRef);
-    pub fn CFRunLoopTimerIsValid(timer: CFRunLoopTimerRef) -> Boolean;
-    pub fn CFRunLoopTimerGetContext(timer: CFRunLoopTimerRef, context: *mut CFRunLoopTimerContext);
-    pub fn CFRunLoopTimerGetTolerance(timer: CFRunLoopTimerRef) -> CFTimeInterval;
-    pub fn CFRunLoopTimerSetTolerance(timer: CFRunLoopTimerRef, tolerance: CFTimeInterval);
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/set.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::c_void;
-
-use base::{CFAllocatorRef, CFIndex, CFTypeID};
-
-pub type CFSetRetainCallBack = *const u8;
-pub type CFSetReleaseCallBack = *const u8;
-pub type CFSetCopyDescriptionCallBack = *const u8;
-pub type CFSetEqualCallBack = *const u8;
-pub type CFSetHashCallBack = *const u8;
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct CFSetCallBacks {
-    pub version: CFIndex,
-    pub retain: CFSetRetainCallBack,
-    pub release: CFSetReleaseCallBack,
-    pub copyDescription: CFSetCopyDescriptionCallBack,
-    pub equal: CFSetEqualCallBack,
-    pub hash: CFSetHashCallBack,
-}
-
-#[repr(C)]
-pub struct __CFSet(c_void);
-
-pub type CFSetRef = *const __CFSet;
-
-extern {
-    /*
-     * CFSet.h
-     */
-
-    pub static kCFTypeSetCallBacks: CFSetCallBacks;
-
-    /* Creating Sets */
-    pub fn CFSetCreate(allocator: CFAllocatorRef, values: *const *const c_void, numValues: CFIndex,
-                       callBacks: *const CFSetCallBacks) -> CFSetRef;
-
-    /* Applying a Function to Set Members */
-    //fn CFSetApplyFunction
-
-    pub fn CFSetGetTypeID() -> CFTypeID;
-}
-
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/string.rs
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use libc::{c_char, c_ushort, c_void};
-
-use base::{Boolean, CFOptionFlags, CFIndex, CFAllocatorRef, CFRange, CFTypeID};
-
-pub type UniChar = c_ushort;
-
-// CFString.h
-
-pub type CFStringCompareFlags = CFOptionFlags;
-//static kCFCompareCaseInsensitive: CFStringCompareFlags = 1;
-//static kCFCompareBackwards: CFStringCompareFlags = 4;
-//static kCFCompareAnchored: CFStringCompareFlags = 8;
-//static kCFCompareNonliteral: CFStringCompareFlags = 16;
-//static kCFCompareLocalized: CFStringCompareFlags = 32;
-//static kCFCompareNumerically: CFStringCompareFlags = 64;
-//static kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128;
-//static kCFCompareWidthInsensitive: CFStringCompareFlags = 256;
-//static kCFCompareForcedOrdering: CFStringCompareFlags = 512;
-
-pub type CFStringEncoding = u32;
-
-// OS X built-in encodings.
-
-//static kCFStringEncodingMacRoman: CFStringEncoding = 0;
-//static kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500;
-//static kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201;
-//static kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01;
-//static kCFStringEncodingASCII: CFStringEncoding = 0x0600;
-//static kCFStringEncodingUnicode: CFStringEncoding = 0x0100;
-pub static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100;
-//static kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF;
-
-//static kCFStringEncodingUTF16: CFStringEncoding = 0x0100;
-//static kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100;
-//static kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100;
-//static kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100;
-//static kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100;
-//static kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100;
-
-
-// CFStringEncodingExt.h
-
-pub type CFStringEncodings = CFIndex;
-
-// External encodings, except those defined above.
-// Defined above: kCFStringEncodingMacRoman = 0
-//static kCFStringEncodingMacJapanese: CFStringEncoding = 1;
-//static kCFStringEncodingMacChineseTrad: CFStringEncoding = 2;
-//static kCFStringEncodingMacKorean: CFStringEncoding = 3;
-//static kCFStringEncodingMacArabic: CFStringEncoding = 4;
-//static kCFStringEncodingMacHebrew: CFStringEncoding = 5;
-//static kCFStringEncodingMacGreek: CFStringEncoding = 6;
-//static kCFStringEncodingMacCyrillic: CFStringEncoding = 7;
-//static kCFStringEncodingMacDevanagari: CFStringEncoding = 9;
-//static kCFStringEncodingMacGurmukhi: CFStringEncoding = 10;
-//static kCFStringEncodingMacGujarati: CFStringEncoding = 11;
-//static kCFStringEncodingMacOriya: CFStringEncoding = 12;
-//static kCFStringEncodingMacBengali: CFStringEncoding = 13;
-//static kCFStringEncodingMacTamil: CFStringEncoding = 14;
-//static kCFStringEncodingMacTelugu: CFStringEncoding = 15;
-//static kCFStringEncodingMacKannada: CFStringEncoding = 16;
-//static kCFStringEncodingMacMalayalam: CFStringEncoding = 17;
-//static kCFStringEncodingMacSinhalese: CFStringEncoding = 18;
-//static kCFStringEncodingMacBurmese: CFStringEncoding = 19;
-//static kCFStringEncodingMacKhmer: CFStringEncoding = 20;
-//static kCFStringEncodingMacThai: CFStringEncoding = 21;
-//static kCFStringEncodingMacLaotian: CFStringEncoding = 22;
-//static kCFStringEncodingMacGeorgian: CFStringEncoding = 23;
-//static kCFStringEncodingMacArmenian: CFStringEncoding = 24;
-//static kCFStringEncodingMacChineseSimp: CFStringEncoding = 25;
-//static kCFStringEncodingMacTibetan: CFStringEncoding = 26;
-//static kCFStringEncodingMacMongolian: CFStringEncoding = 27;
-//static kCFStringEncodingMacEthiopic: CFStringEncoding = 28;
-//static kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29;
-//static kCFStringEncodingMacVietnamese: CFStringEncoding = 30;
-//static kCFStringEncodingMacExtArabic: CFStringEncoding = 31;
-//static kCFStringEncodingMacSymbol: CFStringEncoding = 33;
-//static kCFStringEncodingMacDingbats: CFStringEncoding = 34;
-//static kCFStringEncodingMacTurkish: CFStringEncoding = 35;
-//static kCFStringEncodingMacCroatian: CFStringEncoding = 36;
-//static kCFStringEncodingMacIcelandic: CFStringEncoding = 37;
-//static kCFStringEncodingMacRomanian: CFStringEncoding = 38;
-//static kCFStringEncodingMacCeltic: CFStringEncoding = 39;
-//static kCFStringEncodingMacGaelic: CFStringEncoding = 40;
-//static kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C;
-//static kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98;
-//static kCFStringEncodingMacInuit: CFStringEncoding = 0xEC;
-//static kCFStringEncodingMacVT100: CFStringEncoding = 0xFC;
-//static kCFStringEncodingMacHFS: CFStringEncoding = 0xFF;
-// Defined above: kCFStringEncodingISOLatin1 = 0x0201
-//static kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202;
-//static kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203;
-//static kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204;
-//static kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205;
-//static kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206;
-//static kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207;
-//static kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208;
-//static kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209;
-//static kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A;
-//static kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B;
-//static kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D;
-//static kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E;
-//static kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F;
-//static kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210;
-//static kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400;
-//static kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405;
-//static kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406;
-//static kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410;
-//static kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411;
-//static kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412;
-//static kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413;
-//static kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414;
-//static kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415;
-//static kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416;
-//static kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417;
-//static kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418;
-//static kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419;
-//static kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A;
-//static kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B;
-//static kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C;
-//static kCFStringEncodingDOSThai: CFStringEncoding = 0x041D;
-//static kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420;
-//static kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421;
-//static kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422;
-//static kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423;
-// Defined above: kCFStringEncodingWindowsLatin1 = 0x0500
-//static kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501;
-//static kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502;
-//static kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503;
-//static kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504;
-//static kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505;
-//static kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506;
-//static kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507;
-//static kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508;
-//static kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510;
-// Defined above: kCFStringEncodingASCII = 0x0600
-//static kCFStringEncodingANSEL: CFStringEncoding = 0x0601;
-//static kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620;
-//static kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621;
-//static kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622;
-//static kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623;
-//static kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624;
-//static kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628;
-//static kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629;
-//static kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630;
-//static kCFStringEncodingGBK_95: CFStringEncoding = 0x0631;
-//static kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632;
-//static kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640;
-//static kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641;
-//static kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651;
-//static kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652;
-//static kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653;
-//static kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820;
-//static kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821;
-//static kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822;
-//static kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823;
-//static kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830;
-//static kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831;
-//static kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840;
-//static kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920;
-//static kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930;
-//static kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931;
-//static kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940;
-//static kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01;
-//static kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02;
-//static kCFStringEncodingBig5: CFStringEncoding = 0x0A03;
-//static kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04;
-//static kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05;
-//static kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06;
-//static kCFStringEncodingVISCII: CFStringEncoding = 0x0A07;
-//static kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08;
-//static kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09;
-// Defined above: kCFStringEncodingNextStepLatin = 0x0B01
-//static kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02;
-//static kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01;
-//static kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02;
-//static kCFStringEncodingUTF7: CFStringEncoding = 0x04000100;
-//static kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10;
-//static kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */
-
-#[repr(C)]
-pub struct __CFString(c_void);
-
-pub type CFStringRef = *const __CFString;
-
-extern {
-    /*
-     * CFString.h
-     */
-
-    // N.B. organized according to "Functions by task" in docs
-
-    /* Creating a CFString */
-    //fn CFSTR
-    //fn CFStringCreateArrayBySeparatingStrings
-    //fn CFStringCreateByCombiningStrings
-    //fn CFStringCreateCopy
-    //fn CFStringCreateFromExternalRepresentation
-    pub fn CFStringCreateWithBytes(alloc: CFAllocatorRef,
-                                   bytes: *const u8,
-                                   numBytes: CFIndex,
-                                   encoding: CFStringEncoding,
-                                   isExternalRepresentation: Boolean,
-                                   contentsDeallocator: CFAllocatorRef)
-                                   -> CFStringRef;
-    pub fn CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef,
-                                         bytes: *const u8,
-                                         numBytes: CFIndex,
-                                         encoding: CFStringEncoding,
-                                         isExternalRepresentation: Boolean,
-                                         contentsDeallocator: CFAllocatorRef)
-                                         -> CFStringRef;
-    //fn CFStringCreateWithCharacters
-    //fn CFStringCreateWithCharactersNoCopy
-    pub fn CFStringCreateWithCString(alloc: CFAllocatorRef,
-                                     cStr: *const c_char,
-                                     encoding: CFStringEncoding)
-                                     -> CFStringRef;
-    //fn CFStringCreateWithCStringNoCopy
-    //fn CFStringCreateWithFormat
-    //fn CFStringCreateWithFormatAndArguments
-    //fn CFStringCreateWithPascalString
-    //fn CFStringCreateWithPascalStringNoCopy
-    //fn CFStringCreateWithSubstring
-
-    /* Searching Strings */
-    //fn CFStringCreateArrayWithFindResults
-    //fn CFStringFind
-    //fn CFStringFindCharacterFromSet
-    //fn CFStringFindWithOptions
-    //fn CFStringFindWithOptionsAndLocale
-    //fn CFStringGetLineBounds
-
-    /* Comparing Strings */
-    //fn CFStringCompare
-    //fn CFStringCompareWithOptions
-    //fn CFStringCompareWithOptionsAndLocale
-    //fn CFStringHasPrefix
-    //fn CFStringHasSuffix
-
-    /* Accessing Characters */
-    //fn CFStringCreateExternalRepresentation
-    pub fn CFStringGetBytes(theString: CFStringRef,
-                            range: CFRange,
-                            encoding: CFStringEncoding,
-                            lossByte: u8,
-                            isExternalRepresentation: Boolean,
-                            buffer: *mut u8,
-                            maxBufLen: CFIndex,
-                            usedBufLen: *mut CFIndex)
-                            -> CFIndex;
-    //fn CFStringGetCharacterAtIndex
-    //fn CFStringGetCharacters
-    //fn CFStringGetCharactersPtr
-    //fn CFStringGetCharacterFromInlineBuffer
-    pub fn CFStringGetCString(theString: CFStringRef,
-                              buffer: *mut c_char,
-                              bufferSize: CFIndex,
-                              encoding: CFStringEncoding)
-                              -> Boolean;
-    pub fn CFStringGetCStringPtr(theString: CFStringRef,
-                                 encoding: CFStringEncoding)
-                                 -> *const c_char;
-    pub fn CFStringGetLength(theString: CFStringRef) -> CFIndex;
-    //fn CFStringGetPascalString
-    //fn CFStringGetPascalStringPtr
-    //fn CFStringGetRangeOfComposedCharactersAtIndex
-    //fn CFStringInitInlineBuffer
-
-    /* Working With Hyphenation */
-    //fn CFStringGetHyphenationLocationBeforeIndex
-    //fn CFStringIsHyphenationAvailableForLocale
-
-    /* Working With Encodings */
-    //fn CFStringConvertEncodingToIANACharSetName
-    //fn CFStringConvertEncodingToNSStringEncoding
-    //fn CFStringConvertEncodingToWindowsCodepage
-    //fn CFStringConvertIANACharSetNameToEncoding
-    //fn CFStringConvertNSStringEncodingToEncoding
-    //fn CFStringConvertWindowsCodepageToEncoding
-    //fn CFStringGetFastestEncoding
-    //fn CFStringGetListOfAvailableEncodings
-    //fn CFStringGetMaximumSizeForEncoding
-    //fn CFStringGetMostCompatibleMacStringEncoding
-    //fn CFStringGetNameOfEncoding
-    //fn CFStringGetSmallestEncoding
-    //fn CFStringGetSystemEncoding
-    //fn CFStringIsEncodingAvailable
-
-    /* Getting Numeric Values */
-    //fn CFStringGetDoubleValue
-    //fn CFStringGetIntValue
-
-    /* Getting String Properties */
-    //fn CFShowStr
-    pub fn CFStringGetTypeID() -> CFTypeID;
-
-    /* String File System Representations */
-    //fn CFStringCreateWithFileSystemRepresentation
-    //fn CFStringGetFileSystemRepresentation
-    //fn CFStringGetMaximumSizeOfFileSystemRepresentation
-
-    /* Getting Paragraph Bounds */
-    //fn CFStringGetParagraphBounds
-
-    /* Managing Surrogates */
-    //fn CFStringGetLongCharacterForSurrogatePair
-    //fn CFStringGetSurrogatePairForLongCharacter
-    //fn CFStringIsSurrogateHighCharacter
-    //fn CFStringIsSurrogateLowCharacter
-}
deleted file mode 100644
--- a/third_party/rust/core-foundation-sys-0.2.3/src/url.rs
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2013-2015 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-use libc::c_void;
-
-use base::{CFOptionFlags, CFIndex, CFAllocatorRef, Boolean, CFTypeID};
-use string::CFStringRef;
-
-#[repr(C)]
-pub struct __CFURL(c_void);
-
-pub type CFURLRef = *const __CFURL;
-
-pub type CFURLBookmarkCreationOptions = CFOptionFlags;
-
-pub type CFURLPathStyle = CFIndex;
-
-/* typedef CF_ENUM(CFIndex, CFURLPathStyle) */
-pub const kCFURLPOSIXPathStyle: CFURLPathStyle   = 0;
-pub const kCFURLHFSPathStyle: CFURLPathStyle     = 1;
-pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;
-
-// static kCFURLBookmarkCreationPreferFileIDResolutionMask: CFURLBookmarkCreationOptions =
-//     (1 << 8) as u32;
-// static kCFURLBookmarkCreationMinimalBookmarkMask: CFURLBookmarkCreationOptions =
-//     (1 << 9) as u32;
-// static kCFURLBookmarkCreationSuitableForBookmarkFile: CFURLBookmarkCreationOptions =
-//     (1 << 10) as u32;
-// static kCFURLBookmarkCreationWithSecurityScope: CFURLBookmarkCreationOptions =
-//     (1 << 11) as u32;
-// static kCFURLBookmarkCreationSecurityScopeAllowOnlyReadAccess: CFURLBookmarkCreationOptions =
-//     (1 << 12) as u32;
-
-// TODO: there are a lot of missing keys and constants. Add if you are bored or need them.
-
-extern {
-    /*
-     * CFURL.h
-     */
-
-    /* Common File System Resource Keys */
-    // static kCFURLAttributeModificationDateKey: CFStringRef;
-    // static kCFURLContentAccessDateKey: CFStringRef;
-    // static kCFURLContentModificationDateKey: CFStringRef;
-    // static kCFURLCreationDateKey: CFStringRef;
-    // static kCFURLCustomIconKey: CFStringRef;
-    // static kCFURLEffectiveIconKey: CFStringRef;
-    // static kCFURLFileResourceIdentifierKey: CFStringRef;
-    // static kCFURLFileSecurityKey: CFStringRef;
-    // static kCFURLHasHiddenExtensionKey: CFStringRef;
-    // static kCFURLIsDirectoryKey: CFStringRef;
-    // static kCFURLIsExecutableKey: CFStringRef;
-    // static kCFURLIsHiddenKey: CFStringRef;
-    // static kCFURLIsPackageKey: CFStringRef;
-    // static kCFURLIsReadableKey: CFStringRef;
-    // static kCFURLIsRegularFileKey: CFStringRef;
-    // static kCFURLIsSymbolicLinkKey: CFStringRef;
-    // static kCFURLIsSystemImmutableKey: CFStringRef;
-    // static kCFURLIsUserImmutableKey: CFStringRef;
-    // static kCFURLIsVolumeKey: CFStringRef;
-    // static kCFURLIsWritableKey: CFStringRef;
-    // static kCFURLLabelColorKey: CFStringRef;
-    // static kCFURLLabelNumberKey: CFStringRef;
-    // static kCFURLLinkCountKey: CFStringRef;
-    // static kCFURLLocalizedLabelKey: CFStringRef;
-    // static kCFURLLocalizedNameKey: CFStringRef;
-    // static kCFURLLocalizedTypeDescriptionKey: CFStringRef;
-    // static kCFURLNameKey: CFStringRef;
-    // static kCFURLParentDirectoryURLKey: CFStringRef;
-    // static kCFURLPreferredIOBlockSizeKey: CFStringRef;
-    // static kCFURLTypeIdentifierKey: CFStringRef;
-    // static kCFURLVolumeIdentifierKey: CFStringRef;
-    // static kCFURLVolumeURLKey: CFStringRef;
-    // static kCFURLIsExcludedFromBackupKey: CFStringRef;
-    // static kCFURLFileResourceTypeKey: CFStringRef;
-
-    /* Creating a CFURL */
-    //fn CFURLCopyAbsoluteURL
-    //fn CFURLCreateAbsoluteURLWithBytes
-    //fn CFURLCreateByResolvingBookmarkData
-    //fn CFURLCreateCopyAppendingPathComponent
-    //fn CFURLCreateCopyAppendingPathExtension
-    //fn CFURLCreateCopyDeletingLastPathComponent
-    //fn CFURLCreateCopyDeletingPathExtension
-    //fn CFURLCreateFilePathURL
-    //fn CFURLCreateFileReferenceURL
-    //fn CFURLCreateFromFileSystemRepresentation
-    //fn CFURLCreateFromFileSystemRepresentationRelativeToBase
-    //fn CFURLCreateFromFSRef
-    //fn CFURLCreateWithBytes
-    //fn CFURLCreateWithFileSystemPath
-    pub fn CFURLCreateWithFileSystemPath(allocator: CFAllocatorRef, filePath: CFStringRef, pathStyle: CFURLPathStyle, isDirectory: Boolean) -> CFURLRef;
-    //fn CFURLCreateWithFileSystemPathRelativeToBase
-    //fn CFURLCreateWithString(allocator: CFAllocatorRef, urlString: CFStringRef,
-    //                         baseURL: CFURLRef) -> CFURLRef;
-
-    /* Accessing the Parts of a URL */
-    //fn CFURLCanBeDecomposed
-    //fn CFURLCopyFileSystemPath
-    //fn CFURLCopyFragment
-    //fn CFURLCopyHostName
-    //fn CFURLCopyLastPathComponent
-    //fn CFURLCopyNetLocation
-    //fn CFURLCopyParameterString
-    //fn CFURLCopyPassword
-    //fn CFURLCopyPath
-    //fn CFURLCopyPathExtension
-    //fn CFURLCopyQueryString
-    //fn CFURLCopyResourceSpecifier
-    //fn CFURLCopyScheme
-    //fn CFURLCopyStrictPath
-    //fn CFURLCopyUserName
-    //fn CFURLGetPortNumber
-    //fn CFURLHasDirectoryPath
-
-    /* Converting URLs to Other Representations */
-    //fn CFURLCreateData(allocator: CFAllocatorRef, url: CFURLRef,
-    //                   encoding: CFStringEncoding, escapeWhitespace: bool) -> CFDataRef;
-    //fn CFURLCreateStringByAddingPercentEscapes
-    //fn CFURLCreateStringByReplacingPercentEscapes
-    //fn CFURLCreateStringByReplacingPercentEscapesUsingEncoding
-    //fn CFURLGetFileSystemRepresentation
-    //fn CFURLGetFSRef
-    pub fn CFURLGetString(anURL: CFURLRef) -> CFStringRef;
-
-    /* Getting URL Properties */
-    //fn CFURLGetBaseURL(anURL: CFURLRef) -> CFURLRef;
-    //fn CFURLGetBytes
-    //fn CFURLGetByteRangeForComponent
-    pub fn CFURLGetTypeID() -> CFTypeID;
-    //fn CFURLResourceIsReachable
-
-    /* Getting and Setting File System Resource Properties */
-    //fn CFURLClearResourcePropertyCache
-    //fn CFURLClearResourcePropertyCacheForKey
-    //fn CFURLCopyResourcePropertiesForKeys
-    //fn CFURLCopyResourcePropertyForKey
-    //fn CFURLCreateResourcePropertiesForKeysFromBookmarkData
-    //fn CFURLCreateResourcePropertyForKeyFromBookmarkData
-    //fn CFURLSetResourcePropertiesForKeys
-    //fn CFURLSetResourcePropertyForKey
-    //fn CFURLSetTemporaryResourcePropertyForKey
-
-    /* Working with Bookmark Data */
-    //fn CFURLCreateBookmarkData
-    //fn CFURLCreateBookmarkDataFromAliasRecord
-    //fn CFURLCreateBookmarkDataFromFile
-    //fn CFURLWriteBook