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 374801 c79c28db46db4e567f6c8fa918c31aa4f90ded86
parent 374800 3e6f3f29feeea936f222df376b0d7f706cd33a1f
child 374802 b323a395e46e436062971eda9b675c1dbbcfc55e
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslsalzman
bugs1342246
milestone54.0a1
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)