Bug 1342246. Generate resource ids on the client side. r=lsalzman
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 22 Feb 2017 13:19:57 -0500
changeset 394751 c79c28db46db4e567f6c8fa918c31aa4f90ded86
parent 394750 3e6f3f29feeea936f222df376b0d7f706cd33a1f
child 394752 b323a395e46e436062971eda9b675c1dbbcfc55e
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)
reviewerslsalzman
bugs1342246
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
Bug 1342246. Generate resource ids on the client side. r=lsalzman
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp
gfx/layers/ipc/CrossProcessCompositorBridgeParent.h
gfx/layers/ipc/PCompositorBridge.ipdl
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/wr/WebRenderBridgeChild.cpp
gfx/layers/wr/WebRenderBridgeChild.h
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderBridgeParent.h
gfx/layers/wr/WebRenderCanvasLayer.cpp
gfx/layers/wr/WebRenderImageLayer.cpp
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderPaintedLayer.cpp
gfx/layers/wr/WebRenderTextLayer.cpp
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
layout/generic/nsBulletFrame.cpp
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -1125,19 +1125,19 @@ 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);
+  WebRenderBridgeChild* child = new WebRenderBridgeChild(aPipelineId, *aIdNamespace);
   child->AddIPDLReference();
   return child;
 }
 
 bool
 CompositorBridgeChild::DeallocPWebRenderBridgeChild(PWebRenderBridgeChild* aActor)
 {
   WebRenderBridgeChild* child = static_cast<WebRenderBridgeChild*>(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
@@ -1566,17 +1566,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);
@@ -1585,16 +1586,17 @@ 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);
+  *aIdNamespace = api->GetNamespace().mHandle;
   mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, Move(api), Move(holder));
 
   mCompositorScheduler = mWrBridge->CompositorScheduler();
   MOZ_ASSERT(mCompositorScheduler);
   mWrBridge.get()->AddRef(); // IPDL reference
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   auto pipelineHandle = aPipelineId.mHandle;
   MOZ_ASSERT(sIndirectLayerTrees[pipelineHandle].mWrBridge == nullptr);
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -446,17 +446,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();
 
--- 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())) {
@@ -222,16 +223,17 @@ CrossProcessCompositorBridgeParent::Allo
   RefPtr<wr::WebRenderAPI> api = root->GetWebRenderAPI();
   RefPtr<WebRenderCompositableHolder> holder = root->CompositableHolder();
   parent = new WebRenderBridgeParent(this, aPipelineId, nullptr, Move(api), Move(holder));
 
   parent->AddRef(); // IPDL reference
   sIndirectLayerTrees[pipelineHandle].mCrossProcessParent = this;
   sIndirectLayerTrees[pipelineHandle].mWrBridge = parent;
   *aTextureFactoryIdentifier = parent->GetTextureFactoryIdentifier();
+  *aIdNamespace = api->GetNamespace().mHandle;
   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
--- 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
@@ -26,22 +26,22 @@ 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(IntSize aSize, WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
   sync DPSyncEnd(IntSize aSize, WebRenderCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId);
   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);
--- 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;
@@ -101,30 +102,34 @@ struct OpDPPushExternalImageId {
   LayerIntRegion validBufferRegion;
   WrRect bounds;
   WrRect clip;
   MaybeImageMask mask;
   ImageRendering filter;
   uint64_t externalImageId;
 };
 
+struct OpAddExternalImage {
+  LayerIntRegion validBufferRegion;
+  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 +144,17 @@ union WebRenderCommand {
   OpDPPopStackingContext;
   OpDPPushScrollLayer;
   OpDPPopScrollLayer;
   OpDPPushRect;
   OpDPPushBorder;
   OpDPPushLinearGradient;
   OpDPPushRadialGradient;
   OpDPPushImage;
-  OpDPPushExternalImageId;
+  OpAddExternalImage;
   OpDPPushIframe;
   OpDPPushText;
   OpDPPushBoxShadow;
   CompositableOperation;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -10,18 +10,20 @@
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/PTextureChild.h"
 
 namespace mozilla {
 namespace layers {
 
-WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId)
+WebRenderBridgeChild::WebRenderBridgeChild(const wr::PipelineId& aPipelineId, uint32_t aIdNamespace)
   : mIsInTransaction(false)
+  , mIdNamespace(aIdNamespace)
+  , mResourceId(0)
   , mIPCOpen(false)
   , mDestroyed(false)
 {
 }
 
 void
 WebRenderBridgeChild::Destroy()
 {
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -23,17 +23,17 @@ class CompositorBridgeChild;
 class TextureForwarder;
 
 class WebRenderBridgeChild final : public PWebRenderBridgeChild
                                  , public CompositableForwarder
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild, override)
 
 public:
-  explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
+  explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId, uint32_t aIdNamespace);
 
   void AddWebRenderCommand(const WebRenderCommand& aCmd);
   void AddWebRenderCommands(const nsTArray<WebRenderCommand>& aCommands);
 
   bool DPBegin(const  gfx::IntSize& aSize);
   void DPEnd(const gfx::IntSize& aSize, bool aIsSync, uint64_t aTransactionId);
 
   CompositorBridgeChild* GetCompositorBridgeChild();
@@ -49,16 +49,19 @@ 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; }
+
 private:
   friend class CompositorBridgeChild;
 
   ~WebRenderBridgeChild() {}
 
   uint64_t GetNextExternalImageId();
 
   // CompositableForwarder
@@ -97,16 +100,18 @@ private:
   }
 
   bool AddOpDestroy(const OpDestroy& aOp);
 
   nsTArray<WebRenderCommand> mCommands;
   nsTArray<OpDestroy> mDestroyedActors;
   nsDataHashtable<nsUint64HashKey, CompositableClient*> mCompositables;
   bool mIsInTransaction;
+  uint32_t mIdNamespace;
+  uint32_t mResourceId;
 
   bool mIPCOpen;
   bool mDestroyed;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -134,34 +134,51 @@ WebRenderBridgeParent::Destroy()
     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();
   }
@@ -303,18 +320,18 @@ WebRenderBridgeParent::ProcessWebrenderC
         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 WebRenderCommand::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) {
@@ -343,21 +360,20 @@ WebRenderBridgeParent::ProcessWebrenderC
         }
 
         DataSourceSurface::MappedSurface map;
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           break;
         }
 
         wr::ImageDescriptor descriptor(validRect.Size(), map.mStride, SurfaceFormat::B8G8R8A8);
-        wr::ImageKey key;
+        wr::ImageKey key = op.key();
         auto slice = Range<uint8_t>(map.mData, validRect.height * map.mStride);
-        key = mApi->AddImageBuffer(descriptor, slice);
+        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;
       }
@@ -371,27 +387,22 @@ WebRenderBridgeParent::ProcessWebrenderC
           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,
+                           op.key(),
                            Range<const WrGlyphInstance>(glyphs.Elements(), glyphs.Length()),
                            op.glyph_size());
         }
 
         break;
       }
       case WebRenderCommand::TOpDPPushBoxShadow: {
         const OpDPPushBoxShadow& op = cmd.get_OpDPPushBoxShadow();
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -55,21 +55,24 @@ public:
   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(const gfx::IntSize& aSize,
                                     InfallibleTArray<WebRenderCommand>&& aCommands,
--- 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()->AddWebRenderCommand(OpAddExternalImage(LayerIntRegion(), 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/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()->AddWebRenderCommand(OpAddExternalImage(LayerIntRegion(), 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,18 +214,20 @@ 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);
   *aTextureFactoryIdentifier = textureFactoryIdentifier;
 }
 
--- 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()->AddWebRenderCommand(OpAddExternalImage(LayerIntRegion(), 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/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_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -130,16 +130,21 @@ 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);
@@ -204,23 +209,24 @@ 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,
                                      gfx::SurfaceFormat aFormat,
                                      uint64_t aHandle)
 {
   auto format = SurfaceFormatToWrImageFormat(aFormat).value();
@@ -241,20 +247,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");
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -43,38 +43,40 @@ public:
 
   void SetRootDisplayList(gfx::Color aBgColor,
                           wr::Epoch aEpoch,
                           LayerSize aViewportSize,
                           DisplayListBuilder& aBuilder);
 
   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 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)
--- 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;
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -5,17 +5,17 @@ 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::{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::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,16 +43,17 @@ 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 {
@@ -132,16 +133,22 @@ pub extern fn wr_renderer_current_epoch(
 }
 
 #[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_set_root_display_list(api: &mut RenderApi,
                                                   state: &mut WrState,
@@ -570,32 +577,36 @@ pub extern fn wr_dp_pop_scroll_layer(sta
 
 #[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)
     );
-    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 {
     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)))
 }
@@ -896,35 +907,40 @@ 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,
--- 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,16 +44,17 @@ 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
@@ -407,18 +408,18 @@ wr_window_new(WrWindowId window_id,
               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_FUNC;
 
 //TODO(Jerry): handle shmem in WR
@@ -444,18 +445,18 @@ WR_FUNC;
 WR_INLINE void
 wr_api_set_root_display_list(WrAPI* api, WrState* state, WrEpoch epoch, float w, float h)
 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(WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
 wr_state_delete(WrState* state)
@@ -541,13 +542,17 @@ 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;
+
 #undef WR_FUNC
 #undef WR_DESTRUCTOR_SAFE_FUNC
 } // extern "C"
 
 #endif // WR_h
--- 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;
@@ -455,23 +456,31 @@ 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(
+  WrImageKey key;
+  key.mNamespace = layer->WrBridge()->GetNamespace();
+  key.mHandle = layer->WrBridge()->GetNextResourceId();
+  aCommands.AppendElement(layers::OpAddExternalImage(
                             LayerIntRegion(),
+                            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 +500,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)