Bug 1393031 - Use shared memory to pass resource update data. r=jrmuizel
authorNicolas Silva <nsilva@mozilla.com>
Thu, 14 Sep 2017 18:48:55 +0200
changeset 430472 0b78bddcd706d1c029699a304cc33a5e73b8188b
parent 430471 131084e007d62aa8a8bc147c3563dba56fa77ef9
child 430475 267e6c477d860f121b5e8cc0c27b141fb6143269
push id7768
push userryanvm@gmail.com
push dateSat, 16 Sep 2017 16:13:49 +0000
treeherdermozilla-beta@3b375d85383a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1393031
milestone57.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 1393031 - Use shared memory to pass resource update data. r=jrmuizel
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/ipc/PWebRenderBridge.ipdl
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/moz.build
gfx/layers/wr/AsyncImagePipelineManager.cpp
gfx/layers/wr/IpcResourceUpdateQueue.cpp
gfx/layers/wr/IpcResourceUpdateQueue.h
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/WebRenderCanvasLayer.h
gfx/layers/wr/WebRenderColorLayer.cpp
gfx/layers/wr/WebRenderColorLayer.h
gfx/layers/wr/WebRenderContainerLayer.cpp
gfx/layers/wr/WebRenderContainerLayer.h
gfx/layers/wr/WebRenderDisplayItemLayer.cpp
gfx/layers/wr/WebRenderDisplayItemLayer.h
gfx/layers/wr/WebRenderImageLayer.cpp
gfx/layers/wr/WebRenderImageLayer.h
gfx/layers/wr/WebRenderLayer.h
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
gfx/layers/wr/WebRenderMessageUtils.h
gfx/layers/wr/WebRenderPaintedLayer.cpp
gfx/layers/wr/WebRenderPaintedLayer.h
gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
gfx/layers/wr/WebRenderPaintedLayerBlob.h
gfx/layers/wr/WebRenderTextLayer.cpp
gfx/layers/wr/WebRenderTextLayer.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_generated.h
layout/forms/nsButtonFrameRenderer.cpp
layout/generic/nsBulletFrame.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsColumnSetFrame.cpp
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsImageFrame.cpp
layout/generic/nsImageFrame.h
layout/generic/nsPluginFrame.cpp
layout/generic/nsPluginFrame.h
layout/generic/nsTextFrame.cpp
layout/generic/nsVideoFrame.cpp
layout/ipc/RenderFrameParent.cpp
layout/ipc/RenderFrameParent.h
layout/painting/nsCSSRenderingBorders.cpp
layout/painting/nsCSSRenderingBorders.h
layout/painting/nsDisplayList.cpp
layout/painting/nsDisplayList.h
layout/tables/nsTableFrame.cpp
layout/xul/nsImageBoxFrame.cpp
layout/xul/nsImageBoxFrame.h
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
widget/nsIWidget.h
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -1321,16 +1321,18 @@ DXGIYCbCrTextureHostD3D11::GetWRImageKey
   MOZ_ASSERT(aImageKeys.Length() == 1);
 }
 
 void
 DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
                                       Range<const wr::ImageKey>& aImageKeys,
                                       const wr::ExternalImageId& aExtID)
 {
+  // TODO - This implementation is very slow (read-back, copy on the copy and re-upload).
+
   MOZ_ASSERT(mTextures[0] && mTextures[1] && mTextures[2]);
   MOZ_ASSERT(aImageKeys.length() == 1);
 
   // There are 3 A8 channel data in DXGIYCbCrTextureHostD3D11, but ANGLE doesn't
   // support for converting the D3D A8 texture to OpenGL texture handle. So, we
   // use the DataSourceSurface to get the raw buffer and push that raw buffer
   // into WR using AddImage().
   NS_WARNING("WR doesn't support DXGIYCbCrTextureHostD3D11 directly. It's a slower path.");
@@ -1341,18 +1343,19 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr
   }
   DataSourceSurface::MappedSurface map;
   if (!dataSourceSurface->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
     return;
   }
 
   IntSize size = dataSourceSurface->GetSize();
   wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat());
-  auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
-  aResources.AddImage(aImageKeys[0], descriptor, slice);
+  wr::Vec_u8 imgBytes;
+  imgBytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
+  aResources.AddImage(aImageKeys[0], descriptor, imgBytes);
 
   dataSourceSurface->Unmap();
 }
 
 void
 DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder,
                                              const wr::LayoutRect& aBounds,
                                              const wr::LayoutRect& aClip,
--- a/gfx/layers/ipc/PWebRenderBridge.ipdl
+++ b/gfx/layers/ipc/PWebRenderBridge.ipdl
@@ -46,24 +46,24 @@ parent:
   // next Update call.
   async InitReadLocks(ReadLockInit[] locks);
 
   sync Create(IntSize aSize);
   async DeleteCompositorAnimations(uint64_t[] aIds);
   async SetDisplayList(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
                        LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
                        WebRenderScrollData aScrollData,
-                       ByteBuffer aResourceUpdates,
+                       OpUpdateResource[] aResourceUpdates, Shmem[] aResourceData,
                        IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
   sync SetDisplayListSync(IntSize aSize, WebRenderParentCommand[] commands, OpDestroy[] toDestroy, uint64_t fwdTransactionId, uint64_t transactionId,
                           LayoutSize aContentSize, ByteBuffer aDL, BuiltDisplayListDescriptor aDLDesc,
                           WebRenderScrollData aScrollData,
-                          ByteBuffer aResourceUpdates,
+                          OpUpdateResource[] aResourceUpdates, Shmem[] aResourceData,
                           IdNamespace aIdNamespace, TimeStamp txnStartTime, TimeStamp fwdTime);
-  async UpdateResources(ByteBuffer aResourceUpdates);
+  async UpdateResources(OpUpdateResource[] aResourceUpdates, Shmem[] aResourceData);
   async ParentCommands(WebRenderParentCommand[] commands);
   sync GetSnapshot(PTexture texture);
   async AddPipelineIdForCompositable(PipelineId aImageId, CompositableHandle aHandle, bool aAsync);
   async RemovePipelineIdForCompositable(PipelineId aPipelineId);
   async AddExternalImageIdForCompositable(ExternalImageId aImageId, CompositableHandle aHandle);
   async RemoveExternalImageId(ExternalImageId aImageId);
   async SetLayerObserverEpoch(uint64_t layerObserverEpoch);
   async ClearCachedResources();
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -4,21 +4,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include LayersMessages;
 include protocol PTexture;
 
+using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::LayoutSize from "mozilla/webrender/webrender_ffi.h";
+using mozilla::wr::ImageDescriptor from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::ImageRendering from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::MixBlendMode from "mozilla/webrender/webrender_ffi.h";
 using mozilla::wr::MaybeImageMask from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::MaybeFontInstanceOptions from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::MaybeFontInstancePlatformOptions from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::FontInstanceKey from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::FontKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::gfx::MaybeIntSize from "mozilla/gfx/Point.h";
 using mozilla::LayerPoint from "Units.h";
 using mozilla::layers::MaybeLayerRect from "mozilla/layers/LayersTypes.h";
 using class mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
@@ -57,10 +63,79 @@ struct OpUpdateAsyncImagePipeline {
 
 union WebRenderParentCommand {
   OpAddExternalImage;
   OpUpdateAsyncImagePipeline;
   CompositableOperation;
   OpAddCompositorAnimations;
 };
 
+struct OffsetRange {
+  uint32_t start;
+  uint32_t length;
+};
+
+struct OpAddImage {
+  ImageDescriptor descriptor;
+  OffsetRange bytes;
+  uint16_t tiling;
+  ImageKey key;
+};
+
+struct OpAddBlobImage {
+  ImageDescriptor descriptor;
+  OffsetRange bytes;
+  uint16_t tiling;
+  ImageKey key;
+};
+
+struct OpUpdateImage {
+  ImageDescriptor descriptor;
+  OffsetRange bytes;
+  ImageKey key;
+};
+
+struct OpUpdateBlobImage {
+  ImageDescriptor descriptor;
+  OffsetRange bytes;
+  ImageKey key;
+};
+
+struct OpDeleteImage {
+  ImageKey key;
+};
+
+struct OpAddRawFont {
+  OffsetRange bytes;
+  uint32_t fontIndex;
+  FontKey key;
+};
+
+struct OpDeleteFont {
+  FontKey key;
+};
+
+struct OpAddFontInstance {
+  MaybeFontInstanceOptions options;
+  MaybeFontInstancePlatformOptions platformOptions ;
+  FontInstanceKey instanceKey;
+  FontKey fontKey;
+  float glyphSize;
+};
+
+struct OpDeleteFontInstance {
+  FontInstanceKey key;
+};
+
+union OpUpdateResource {
+  OpAddImage;
+  OpAddBlobImage;
+  OpUpdateImage;
+  OpUpdateBlobImage;
+  OpDeleteImage;
+  OpAddRawFont;
+  OpDeleteFont;
+  OpAddFontInstance;
+  OpDeleteFontInstance;
+};
+
 } // namespace
 } // namespace
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -225,16 +225,17 @@ EXPORTS.mozilla.layers += [
     'SourceSurfaceSharedData.h',
     'SourceSurfaceVolatileData.h',
     'SyncObject.h',
     'TextureSourceProvider.h',
     'TextureWrapperImage.h',
     'TransactionIdAllocator.h',
     'UpdateImageHelper.h',
     'wr/AsyncImagePipelineManager.h',
+    'wr/IpcResourceUpdateQueue.h',
     'wr/ScrollingLayersHelper.h',
     'wr/StackingContextHelper.h',
     'wr/WebRenderBridgeChild.h',
     'wr/WebRenderBridgeParent.h',
     'wr/WebRenderCanvasRenderer.h',
     'wr/WebRenderDisplayItemLayer.h',
     'wr/WebRenderImageHost.h',
     'wr/WebRenderLayer.h',
@@ -456,16 +457,17 @@ UNIFIED_SOURCES += [
     'RotatedBuffer.cpp',
     'ShareableCanvasRenderer.cpp',
     'SourceSurfaceSharedData.cpp',
     'SourceSurfaceVolatileData.cpp',
     'SyncObject.cpp',
     'TextureSourceProvider.cpp',
     'TextureWrapperImage.cpp',
     'wr/AsyncImagePipelineManager.cpp',
+    'wr/IpcResourceUpdateQueue.cpp',
     'wr/ScrollingLayersHelper.cpp',
     'wr/StackingContextHelper.cpp',
     'wr/WebRenderBridgeChild.cpp',
     'wr/WebRenderBridgeParent.cpp',
     'wr/WebRenderCanvasLayer.cpp',
     'wr/WebRenderCanvasRenderer.cpp',
     'wr/WebRenderColorLayer.cpp',
     'wr/WebRenderContainerLayer.cpp',
--- a/gfx/layers/wr/AsyncImagePipelineManager.cpp
+++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp
@@ -185,22 +185,23 @@ AsyncImagePipelineManager::GenerateImage
       return false;
     }
     gfx::DataSourceSurface::MappedSurface map;
     if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
       NS_ERROR("DataSourceSurface failed to map");
       return false;
     }
     gfx::IntSize size = dSurf->GetSize();
+    wr::Vec_u8 imgBytes;
+    imgBytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
     wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
-    auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
 
     wr::ImageKey key = GenerateImageKey();
     aKeys.AppendElement(key);
-    aResources.AddImage(key, descriptor, slice);
+    aResources.AddImage(key, descriptor, imgBytes);
     dSurf->Unmap();
   }
   return false;
 }
 
 bool
 AsyncImagePipelineManager::UpdateImageKeys(wr::ResourceUpdateQueue& aResources,
                                            bool& aUseExternalImage,
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.cpp
@@ -0,0 +1,250 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "IpcResourceUpdateQueue.h"
+#include <string.h>
+#include <algorithm>
+#include "mozilla/Maybe.h"
+#include "mozilla/ipc/SharedMemory.h"
+
+namespace mozilla {
+namespace wr {
+
+ShmSegmentsWriter::ShmSegmentsWriter(ipc::IShmemAllocator* aAllocator, size_t aChunkSize)
+: mShmAllocator(aAllocator)
+, mCursor(0)
+, mChunkSize(aChunkSize)
+{
+  MOZ_ASSERT(mShmAllocator);
+}
+
+ShmSegmentsWriter::~ShmSegmentsWriter()
+{
+  Clear();
+}
+
+layers::OffsetRange
+ShmSegmentsWriter::Write(Range<uint8_t> aBytes)
+{
+  const size_t start = mCursor;
+  const size_t length = aBytes.length();
+
+  int remainingBytesToCopy = length;
+
+  size_t srcCursor = 0;
+  size_t dstCursor = mCursor;
+
+  while (remainingBytesToCopy > 0) {
+    if (dstCursor >= mData.Length() * mChunkSize) {
+      AllocChunk();
+      continue;
+    }
+
+    const size_t dstMaxOffset = mChunkSize * mData.Length();
+    const size_t dstBaseOffset = mChunkSize * (mData.Length() - 1);
+
+    MOZ_ASSERT(dstCursor >= dstBaseOffset);
+    MOZ_ASSERT(dstCursor <= dstMaxOffset);
+
+    size_t availableRange = dstMaxOffset - dstCursor;
+    size_t copyRange = std::min<int>(availableRange, remainingBytesToCopy);
+
+    uint8_t* srcPtr = &aBytes[srcCursor];
+    uint8_t* dstPtr = mData.LastElement().get<uint8_t>() + (dstCursor - dstBaseOffset);
+
+    memcpy(dstPtr, srcPtr, copyRange);
+
+    srcCursor += copyRange;
+    dstCursor += copyRange;
+    remainingBytesToCopy -= copyRange;
+
+    // sanity check
+    MOZ_ASSERT(remainingBytesToCopy >= 0);
+  }
+
+  mCursor += length;
+
+  return layers::OffsetRange(start, length);
+}
+
+void
+ShmSegmentsWriter::AllocChunk()
+{
+  ipc::Shmem shm;
+  auto shmType = ipc::SharedMemory::SharedMemoryType::TYPE_BASIC;
+  if (!mShmAllocator->AllocShmem(mChunkSize, shmType, &shm)) {
+    MOZ_CRASH("Shared memory allocation failed");
+  }
+  mData.AppendElement(shm);
+}
+
+void
+ShmSegmentsWriter::Flush(nsTArray<ipc::Shmem>& aInto)
+{
+  aInto.Clear();
+  mData.SwapElements(aInto);
+}
+
+void
+ShmSegmentsWriter::Clear()
+{
+  if (mShmAllocator) {
+    for (auto& shm : mData) {
+      mShmAllocator->DeallocShmem(shm);
+    }
+  }
+  mData.Clear();
+  mCursor = 0;
+}
+
+ShmSegmentsReader::ShmSegmentsReader(const nsTArray<ipc::Shmem>& aShmems)
+: mData(aShmems)
+, mChunkSize(0)
+{
+  if (mData.IsEmpty()) {
+    return;
+  }
+
+  mChunkSize = mData[0].Size<uint8_t>();
+
+  // Check that all shmems are readable and have the same size. If anything
+  // isn't right, set mChunkSize to zero which signifies that the reader is
+  // in an invalid state and Read calls will return false;
+  for (const auto& shm : mData) {
+    if (!shm.IsReadable()
+        || shm.Size<uint8_t>() != mChunkSize
+        || shm.get<uint8_t>() == nullptr) {
+      mChunkSize = 0;
+      return;
+    }
+  }
+}
+
+bool
+ShmSegmentsReader::Read(layers::OffsetRange aRange, wr::Vec_u8& aInto)
+{
+  if (mChunkSize == 0) {
+    return false;
+  }
+
+  if (aRange.start() + aRange.length() > mChunkSize * mData.Length()) {
+    return false;
+  }
+
+  size_t initialLength = aInto.Length();
+
+  size_t srcCursor = aRange.start();
+  int remainingBytesToCopy = aRange.length();
+  while (remainingBytesToCopy > 0) {
+    const size_t shm_idx = srcCursor / mChunkSize;
+    const size_t ptrOffset = srcCursor % mChunkSize;
+    const size_t copyRange = std::min<int>(remainingBytesToCopy, mChunkSize - ptrOffset);
+    uint8_t* srcPtr = mData[shm_idx].get<uint8_t>() + ptrOffset;
+
+    aInto.PushBytes(Range<uint8_t>(srcPtr, copyRange));
+
+    srcCursor += copyRange;
+    remainingBytesToCopy -= copyRange;
+  }
+
+  return aInto.Length() - initialLength == aRange.length();
+}
+
+IpcResourceUpdateQueue::IpcResourceUpdateQueue(ipc::IShmemAllocator* aAllocator,
+                                               size_t aChunkSize)
+: mWriter(Move(aAllocator), aChunkSize)
+{}
+
+void
+IpcResourceUpdateQueue::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
+                                 Range<uint8_t> aBytes)
+{
+  auto bytes = mWriter.Write(aBytes);
+  mUpdates.AppendElement(layers::OpAddImage(aDescriptor, bytes, 0, key));
+}
+
+void
+IpcResourceUpdateQueue::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
+                                     Range<uint8_t> aBytes)
+{
+  auto bytes = mWriter.Write(aBytes);
+  mUpdates.AppendElement(layers::OpAddBlobImage(aDescriptor, bytes, 0, key));
+}
+
+void
+IpcResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey,
+                                          const ImageDescriptor& aDescriptor,
+                                          Range<uint8_t> aBytes)
+{
+  auto bytes = mWriter.Write(aBytes);
+  mUpdates.AppendElement(layers::OpUpdateImage(aDescriptor, bytes, aKey));
+}
+
+void
+IpcResourceUpdateQueue::UpdateBlobImage(ImageKey aKey,
+                                        const ImageDescriptor& aDescriptor,
+                                        Range<uint8_t> aBytes)
+{
+  auto bytes = mWriter.Write(aBytes);
+  mUpdates.AppendElement(layers::OpUpdateBlobImage(aDescriptor, bytes, aKey));
+}
+
+void
+IpcResourceUpdateQueue::DeleteImage(ImageKey aKey)
+{
+  mUpdates.AppendElement(layers::OpDeleteImage(aKey));
+}
+
+void
+IpcResourceUpdateQueue::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
+{
+  auto bytes = mWriter.Write(aBytes);
+  mUpdates.AppendElement(layers::OpAddRawFont(bytes, aIndex, aKey));
+}
+
+void
+IpcResourceUpdateQueue::DeleteFont(wr::FontKey aKey)
+{
+  mUpdates.AppendElement(layers::OpDeleteFont(aKey));
+}
+
+void
+IpcResourceUpdateQueue::AddFontInstance(wr::FontInstanceKey aKey,
+                                        wr::FontKey aFontKey,
+                                        float aGlyphSize,
+                                        const wr::FontInstanceOptions* aOptions,
+                                        const wr::FontInstancePlatformOptions* aPlatformOptions)
+{
+  mUpdates.AppendElement(layers::OpAddFontInstance(
+    aOptions ? Some(*aOptions) : Nothing(),
+    aPlatformOptions ? Some(*aPlatformOptions) : Nothing(),
+    aKey, aFontKey,
+    aGlyphSize
+  ));
+}
+
+void
+IpcResourceUpdateQueue::DeleteFontInstance(wr::FontInstanceKey aKey)
+{
+  mUpdates.AppendElement(layers::OpDeleteFontInstance(aKey));
+}
+
+void
+IpcResourceUpdateQueue::Flush(nsTArray<layers::OpUpdateResource>& aUpdates,
+                              nsTArray<ipc::Shmem>& aResourceData)
+{
+  aUpdates.Clear();
+  mUpdates.SwapElements(aUpdates);
+  mWriter.Flush(aResourceData);
+}
+
+void
+IpcResourceUpdateQueue::Clear()
+{
+  mWriter.Clear();
+  mUpdates.Clear();
+}
+
+} // namespace
+} // namespace
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.h
@@ -0,0 +1,107 @@
+/* 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 GFX_WR_IPCRESOURCEUPDATEQUEUE_H
+#define GFX_WR_IPCRESOURCEUPDATEQUEUE_H
+
+#include "mozilla/layers/WebRenderMessages.h"
+#include "mozilla/webrender/WebRenderTypes.h"
+
+namespace mozilla {
+namespace ipc {
+class IShmemAllocator;
+}
+namespace wr {
+
+class ShmSegmentsWriter {
+public:
+  ShmSegmentsWriter(ipc::IShmemAllocator* aAllocator, size_t aChunkSize);
+  ~ShmSegmentsWriter();
+
+  layers::OffsetRange Write(Range<uint8_t> aBytes);
+
+  void Flush(nsTArray<ipc::Shmem>& aData);
+
+  void Clear();
+
+protected:
+  void AllocChunk();
+
+  nsTArray<ipc::Shmem> mData;
+  ipc::IShmemAllocator* mShmAllocator;
+  size_t mCursor;
+  size_t mChunkSize;
+};
+
+class ShmSegmentsReader {
+public:
+  explicit ShmSegmentsReader(const nsTArray<ipc::Shmem>& aShmems);
+
+  bool Read(layers::OffsetRange aRange, wr::Vec_u8& aInto);
+
+protected:
+  void AllocChunk();
+
+  const nsTArray<ipc::Shmem>& mData;
+  size_t mChunkSize;
+};
+
+class IpcResourceUpdateQueue {
+public:
+  // TODO: 8192 is completely arbitrary, needs some adjustments.
+  // Because we are using shmems, the size should be a multiple of the page size, and keep in mind
+  // that each shmem has guard pages, one of which contains meta-data so at least an extra page
+  // is mapped under the hood (so having a lot of smaller shmems = overhead).
+  explicit IpcResourceUpdateQueue(ipc::IShmemAllocator* aAllocator, size_t aChunkSize = 8192);
+
+  void AddImage(wr::ImageKey aKey,
+                const ImageDescriptor& aDescriptor,
+                Range<uint8_t> aBytes);
+
+  void AddBlobImage(wr::ImageKey aKey,
+                    const ImageDescriptor& aDescriptor,
+                    Range<uint8_t> aBytes);
+
+  void UpdateImageBuffer(wr::ImageKey aKey,
+                         const ImageDescriptor& aDescriptor,
+                         Range<uint8_t> aBytes);
+
+  void UpdateBlobImage(wr::ImageKey aKey,
+                       const ImageDescriptor& aDescriptor,
+                       Range<uint8_t> aBytes);
+
+  void UpdateExternalImage(ImageKey aKey,
+                           const ImageDescriptor& aDescriptor,
+                           ExternalImageId aExtID,
+                           wr::WrExternalImageBufferType aBufferType,
+                           uint8_t aChannelIndex = 0);
+
+  void DeleteImage(wr::ImageKey aKey);
+
+  void AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
+
+  void DeleteFont(wr::FontKey aKey);
+
+  void AddFontInstance(wr::FontInstanceKey aKey,
+                       wr::FontKey aFontKey,
+                       float aGlyphSize,
+                       const wr::FontInstanceOptions* aOptions,
+                       const wr::FontInstancePlatformOptions* aPlatformOptions);
+
+  void DeleteFontInstance(wr::FontInstanceKey aKey);
+
+  void Clear();
+
+  void Flush(nsTArray<layers::OpUpdateResource>& aUpdates,
+             nsTArray<ipc::Shmem>& aResources);
+
+protected:
+  ShmSegmentsWriter mWriter;
+  nsTArray<layers::OpUpdateResource> mUpdates;
+};
+
+} // namespace
+} // namespace
+
+#endif
--- a/gfx/layers/wr/WebRenderBridgeChild.cpp
+++ b/gfx/layers/wr/WebRenderBridgeChild.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/layers/WebRenderBridgeChild.h"
 
 #include "gfxPlatform.h"
 #include "mozilla/layers/CompositableClient.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/PTextureChild.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
@@ -93,28 +94,33 @@ WebRenderBridgeChild::ClearReadLocks()
       }
     }
   }
 
   mReadLocks.Clear();
 }
 
 void
-WebRenderBridgeChild::UpdateResources(wr::ResourceUpdateQueue& aResources)
+WebRenderBridgeChild::UpdateResources(wr::IpcResourceUpdateQueue& aResources)
 {
   if (!IPCOpen()) {
     aResources.Clear();
     return;
   }
-  wr::ByteBuffer serializedUpdates(Move(aResources.Serialize()));
-  this->SendUpdateResources(serializedUpdates);
+
+  nsTArray<OpUpdateResource> resourceUpdates;
+  nsTArray<ipc::Shmem> resourceData;
+  aResources.Flush(resourceUpdates, resourceData);
+
+  this->SendUpdateResources(resourceUpdates, resourceData);
 }
 
 void
 WebRenderBridgeChild::EndTransaction(wr::DisplayListBuilder &aBuilder,
+                                     wr::IpcResourceUpdateQueue& aResources,
                                      const gfx::IntSize& aSize,
                                      bool aIsSync,
                                      uint64_t aTransactionId,
                                      const WebRenderScrollData& aScrollData,
                                      const mozilla::TimeStamp& aTxnStartTime)
 {
   MOZ_ASSERT(!mDestroyed);
   MOZ_ASSERT(mIsInTransaction);
@@ -124,28 +130,32 @@ WebRenderBridgeChild::EndTransaction(wr:
   aBuilder.Finalize(contentSize, dl);
   ByteBuffer dlData(Move(dl.dl));
 
   TimeStamp fwdTime;
 #if defined(ENABLE_FRAME_LATENCY_LOG)
   fwdTime = TimeStamp::Now();
 #endif
 
-  wr::ByteBuffer resourceUpdates(Move(aBuilder.Resources().Serialize()));
+  nsTArray<OpUpdateResource> resourceUpdates;
+  nsTArray<ipc::Shmem> resourceData;
+  aResources.Flush(resourceUpdates, resourceData);
 
   if (aIsSync) {
     this->SendSetDisplayListSync(aSize, mParentCommands, mDestroyedActors,
                                  GetFwdTransactionId(), aTransactionId,
                                  contentSize, dlData, dl.dl_desc, aScrollData,
-                                 resourceUpdates, mIdNamespace, aTxnStartTime, fwdTime);
+                                 Move(resourceUpdates), Move(resourceData),
+                                 mIdNamespace, aTxnStartTime, fwdTime);
   } else {
     this->SendSetDisplayList(aSize, mParentCommands, mDestroyedActors,
                              GetFwdTransactionId(), aTransactionId,
                              contentSize, dlData, dl.dl_desc, aScrollData,
-                             resourceUpdates, mIdNamespace, aTxnStartTime, fwdTime);
+                             Move(resourceUpdates), Move(resourceData),
+                             mIdNamespace, aTxnStartTime, fwdTime);
   }
 
   mParentCommands.Clear();
   mDestroyedActors.Clear();
   mIsInTransaction = false;
 }
 
 void
@@ -267,17 +277,17 @@ WebRenderBridgeChild::GetFontKeyForScale
   wr::FontInstanceKey instanceKey = { wr::IdNamespace { 0 }, 0 };
   if (mFontInstanceKeys.Get(aScaledFont, &instanceKey)) {
     return instanceKey;
   }
 
   RefPtr<gfx::UnscaledFont> unscaled = aScaledFont->GetUnscaledFont();
   MOZ_ASSERT(unscaled);
 
-  wr::ResourceUpdateQueue resources;
+  wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
 
   wr::FontKey fontKey = { wr::IdNamespace { 0 }, 0};
   if (!mFontKeys.Get(unscaled, &fontKey)) {
     FontFileData data;
     if (!unscaled->GetFontFileData(WriteFontFileData, &data) ||
         !data.mFontBuffer.mData) {
       return instanceKey;
     }
@@ -300,17 +310,17 @@ WebRenderBridgeChild::GetFontKeyForScale
 
   return instanceKey;
 }
 
 void
 WebRenderBridgeChild::RemoveExpiredFontKeys()
 {
   uint32_t counter = gfx::ScaledFont::DeletionCounter();
-  wr::ResourceUpdateQueue resources;
+  wr::IpcResourceUpdateQueue resources(GetShmemAllocator());
   if (mFontInstanceKeysDeleted != counter) {
     mFontInstanceKeysDeleted = counter;
     for (auto iter = mFontInstanceKeys.Iter(); !iter.Done(); iter.Next()) {
       if (!iter.Key()) {
         resources.DeleteFontInstance(iter.Data());
         iter.Remove();
       }
     }
@@ -516,10 +526,16 @@ WebRenderBridgeChild::BeginClearCachedRe
 void
 WebRenderBridgeChild::EndClearCachedResources()
 {
   ProcessWebRenderParentCommands();
   SendClearCachedResources();
   mIsInClearCachedResources = false;
 }
 
+ipc::IShmemAllocator*
+WebRenderBridgeChild::GetShmemAllocator()
+{
+  return static_cast<CompositorBridgeChild*>(Manager());
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -14,16 +14,17 @@ namespace mozilla {
 
 namespace widget {
 class CompositorWidget;
 }
 
 namespace wr {
 class DisplayListBuilder;
 class ResourceUpdateQueue;
+class IpcResourceUpdateQueue;
 }
 
 namespace layers {
 
 class CompositableClient;
 class CompositorBridgeChild;
 class StackingContextHelper;
 class TextureForwarder;
@@ -60,19 +61,21 @@ class WebRenderBridgeChild final : publi
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild, override)
 
 public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
   void AddWebRenderParentCommands(const nsTArray<WebRenderParentCommand>& aCommands);
 
-  void UpdateResources(wr::ResourceUpdateQueue& aResources);
+  void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
   bool BeginTransaction(const  gfx::IntSize& aSize);
-  void EndTransaction(wr::DisplayListBuilder &aBuilder, const gfx::IntSize& aSize,
+  void EndTransaction(wr::DisplayListBuilder &aBuilder,
+                      wr::IpcResourceUpdateQueue& aResources,
+                      const gfx::IntSize& aSize,
                       bool aIsSync, uint64_t aTransactionId,
                       const WebRenderScrollData& aScrollData,
                       const mozilla::TimeStamp& aTxnStartTime);
   void ProcessWebRenderParentCommands();
 
   CompositorBridgeChild* GetCompositorBridgeChild();
 
   wr::PipelineId GetPipeline() { return mPipelineId; }
@@ -118,16 +121,18 @@ public:
   wr::FontInstanceKey GetFontKeyForScaledFont(gfx::ScaledFont* aScaledFont);
 
   void RemoveExpiredFontKeys();
   void ClearReadLocks();
 
   void BeginClearCachedResources();
   void EndClearCachedResources();
 
+  ipc::IShmemAllocator* GetShmemAllocator();
+
 private:
   friend class CompositorBridgeChild;
 
   ~WebRenderBridgeChild() {}
 
   wr::ExternalImageId GetNextExternalImageId();
 
   // CompositableForwarder
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/layers/AnimationHelper.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/Compositor.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/CompositorVsyncScheduler.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/ImageDataSerializer.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/TextureHost.h"
 #include "mozilla/layers/AsyncImagePipelineManager.h"
 #include "mozilla/layers/WebRenderImageHost.h"
 #include "mozilla/layers/WebRenderTextureHost.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "mozilla/webrender/RenderThread.h"
 #include "mozilla/widget/CompositorWidget.h"
@@ -216,25 +217,129 @@ WebRenderBridgeParent::Destroy()
 {
   if (mDestroyed) {
     return;
   }
   mDestroyed = true;
   ClearResources();
 }
 
+void
+WebRenderBridgeParent::DeallocShmems(nsTArray<ipc::Shmem>& aShmems)
+{
+  if (IPCOpen()) {
+    for (auto& shm : aShmems) {
+      DeallocShmem(shm);
+    }
+  }
+  aShmems.Clear();
+}
+
+bool
+WebRenderBridgeParent::UpdateResources(const nsTArray<OpUpdateResource>& aResourceUpdates,
+                                       const nsTArray<ipc::Shmem>& aResourceData,
+                                       wr::ResourceUpdateQueue& aUpdates)
+{
+  wr::ShmSegmentsReader reader(aResourceData);
+
+  for (const auto& cmd : aResourceUpdates) {
+    switch (cmd.type()) {
+      case OpUpdateResource::TOpAddImage: {
+        const auto& op = cmd.get_OpAddImage();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.AddImage(op.key(), op.descriptor(), bytes);
+        break;
+      }
+      case OpUpdateResource::TOpUpdateImage: {
+        const auto& op = cmd.get_OpUpdateImage();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.UpdateImageBuffer(op.key(), op.descriptor(), bytes);
+        break;
+      }
+      case OpUpdateResource::TOpAddBlobImage: {
+        const auto& op = cmd.get_OpAddBlobImage();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.AddBlobImage(op.key(), op.descriptor(), bytes);
+        break;
+      }
+      case OpUpdateResource::TOpUpdateBlobImage: {
+        const auto& op = cmd.get_OpUpdateBlobImage();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.UpdateBlobImage(op.key(), op.descriptor(), bytes);
+        break;
+      }
+      case OpUpdateResource::TOpAddRawFont: {
+        const auto& op = cmd.get_OpAddRawFont();
+        wr::Vec_u8 bytes;
+        if (!reader.Read(op.bytes(), bytes)) {
+          return false;
+        }
+        aUpdates.AddRawFont(op.key(), bytes, op.fontIndex());
+        break;
+      }
+      case OpUpdateResource::TOpAddFontInstance: {
+        const auto& op = cmd.get_OpAddFontInstance();
+        aUpdates.AddFontInstance(op.instanceKey(), op.fontKey(),
+                                 op.glyphSize(),
+                                 op.options().ptrOr(nullptr),
+                                 op.platformOptions().ptrOr(nullptr));
+        break;
+      }
+      case OpUpdateResource::TOpDeleteImage: {
+        const auto& op = cmd.get_OpDeleteImage();
+        aUpdates.DeleteImage(op.key());
+        break;
+      }
+      case OpUpdateResource::TOpDeleteFont: {
+        const auto& op = cmd.get_OpDeleteFont();
+        aUpdates.DeleteFont(op.key());
+        break;
+      }
+      case OpUpdateResource::TOpDeleteFontInstance: {
+        const auto& op = cmd.get_OpDeleteFontInstance();
+        aUpdates.DeleteFontInstance(op.key());
+        break;
+      }
+      case OpUpdateResource::T__None: break;
+    }
+  }
+
+  return true;
+}
+
 mozilla::ipc::IPCResult
-WebRenderBridgeParent::RecvUpdateResources(const wr::ByteBuffer& aUpdates)
+WebRenderBridgeParent::RecvUpdateResources(nsTArray<OpUpdateResource>&& aResourceUpdates,
+                                           nsTArray<ipc::Shmem>&& aResourceData)
 {
   if (mDestroyed) {
+    DeallocShmems(aResourceData);
     return IPC_OK();
   }
 
-  wr::ResourceUpdateQueue updates = wr::ResourceUpdateQueue::Deserialize(aUpdates.AsSlice());
+  wr::ResourceUpdateQueue updates;
+
+  if (!UpdateResources(aResourceUpdates, aResourceData, updates)) {
+    DeallocShmems(aResourceData);
+    IPC_FAIL(this, "Invalid WebRender resource data shmem or address.");
+  }
+
   mApi->UpdateResources(updates);
+  DeallocShmems(aResourceData);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds)
 {
   if (mDestroyed) {
     return IPC_OK();
@@ -329,73 +434,80 @@ WebRenderBridgeParent::RecvSetDisplayLis
                                           InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                           InfallibleTArray<OpDestroy>&& aToDestroy,
                                           const uint64_t& aFwdTransactionId,
                                           const uint64_t& aTransactionId,
                                           const wr::LayoutSize& aContentSize,
                                           const wr::ByteBuffer& dl,
                                           const wr::BuiltDisplayListDescriptor& dlDesc,
                                           const WebRenderScrollData& aScrollData,
-                                          const wr::ByteBuffer& aResourceUpdates,
+                                          nsTArray<OpUpdateResource>&& aResourceUpdates,
+                                          nsTArray<ipc::Shmem>&& aResourceData,
                                           const wr::IdNamespace& aIdNamespace,
                                           const TimeStamp& aTxnStartTime,
                                           const TimeStamp& aFwdTime)
 {
   if (mDestroyed) {
     for (const auto& op : aToDestroy) {
       DestroyActor(op);
     }
+    DeallocShmems(aResourceData);
     return IPC_OK();
   }
 
   AutoProfilerTracing tracing("Paint", "SetDisplayList");
   UpdateFwdTransactionId(aFwdTransactionId);
   AutoClearReadLocks clearLocks(mReadLocks);
 
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
-  wr::ResourceUpdateQueue resources = wr::ResourceUpdateQueue::Deserialize(aResourceUpdates.AsSlice());
+  wr::ResourceUpdateQueue resources;
+  UpdateResources(aResourceUpdates, aResourceData, resources);
 
   uint32_t wrEpoch = GetNextWrEpoch();
   ProcessWebRenderCommands(aSize, aCommands, wr::NewEpoch(wrEpoch),
                            aContentSize, dl, dlDesc, resources, aIdNamespace);
   HoldPendingTransactionId(wrEpoch, aTransactionId, aTxnStartTime, aFwdTime);
 
   mScrollData = aScrollData;
   UpdateAPZ();
 
   if (mIdNamespace != aIdNamespace) {
     // Pretend we composited since someone is wating for this event,
     // though DisplayList was not pushed to webrender.
     TimeStamp now = TimeStamp::Now();
     mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now);
   }
 
+  DeallocShmems(aResourceData);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvSetDisplayListSync(const gfx::IntSize &aSize,
                                               InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                               InfallibleTArray<OpDestroy>&& aToDestroy,
                                               const uint64_t& aFwdTransactionId,
                                               const uint64_t& aTransactionId,
                                               const wr::LayoutSize& aContentSize,
                                               const wr::ByteBuffer& dl,
                                               const wr::BuiltDisplayListDescriptor& dlDesc,
                                               const WebRenderScrollData& aScrollData,
-                                              const wr::ByteBuffer& aResourceUpdates,
+                                              nsTArray<OpUpdateResource>&& aResourceUpdates,
+                                              nsTArray<ipc::Shmem>&& aResourceData,
                                               const wr::IdNamespace& aIdNamespace,
                                               const TimeStamp& aTxnStartTime,
                                               const TimeStamp& aFwdTime)
 {
-  return RecvSetDisplayList(aSize, Move(aCommands), Move(aToDestroy), aFwdTransactionId, aTransactionId,
-                            aContentSize, dl, dlDesc, aScrollData, aResourceUpdates,
+  return RecvSetDisplayList(aSize, Move(aCommands), Move(aToDestroy),
+                            aFwdTransactionId, aTransactionId,
+                            aContentSize, dl, dlDesc, aScrollData,
+                            Move(aResourceUpdates), Move(aResourceData),
                             aIdNamespace, aTxnStartTime, aFwdTime);
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvParentCommands(nsTArray<WebRenderParentCommand>&& aCommands)
 {
   if (mDestroyed) {
     return IPC_OK();
@@ -448,18 +560,19 @@ WebRenderBridgeParent::ProcessWebRenderP
         DataSourceSurface::MappedSurface map;
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           NS_ERROR("DataSourceSurface failed to map");
           break;
         }
 
         IntSize size = dSurf->GetSize();
         wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
-        auto slice = Range<uint8_t>(map.mData, size.height * map.mStride);
-        aResources.AddImage(keys[0], descriptor, slice);
+        wr::Vec_u8 data;
+        data.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
+        aResources.AddImage(keys[0], descriptor, data);
 
         dSurf->Unmap();
         break;
       }
       case WebRenderParentCommand::TOpUpdateAsyncImagePipeline: {
         const OpUpdateAsyncImagePipeline& op = cmd.get_OpUpdateAsyncImagePipeline();
         mAsyncImageManager->UpdateAsyncImagePipeline(op.pipelineId(),
                                                       op.scBounds(),
--- a/gfx/layers/wr/WebRenderBridgeParent.h
+++ b/gfx/layers/wr/WebRenderBridgeParent.h
@@ -68,40 +68,43 @@ public:
   mozilla::ipc::IPCResult RecvReleaseCompositable(const CompositableHandle& aHandle) override;
 
   mozilla::ipc::IPCResult RecvInitReadLocks(ReadLockArray&& aReadLocks) override;
 
   mozilla::ipc::IPCResult RecvCreate(const gfx::IntSize& aSize) override;
   mozilla::ipc::IPCResult RecvShutdown() override;
   mozilla::ipc::IPCResult RecvShutdownSync() override;
   mozilla::ipc::IPCResult RecvDeleteCompositorAnimations(InfallibleTArray<uint64_t>&& aIds) override;
-  mozilla::ipc::IPCResult RecvUpdateResources(const ByteBuffer& aUpdates) override;
+  mozilla::ipc::IPCResult RecvUpdateResources(nsTArray<OpUpdateResource>&& aUpdates,
+                                              nsTArray<ipc::Shmem>&& aResourceData) override;
   mozilla::ipc::IPCResult RecvSetDisplayList(const gfx::IntSize& aSize,
                                              InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                              InfallibleTArray<OpDestroy>&& aToDestroy,
                                              const uint64_t& aFwdTransactionId,
                                              const uint64_t& aTransactionId,
                                              const wr::LayoutSize& aContentSize,
                                              const wr::ByteBuffer& dl,
                                              const wr::BuiltDisplayListDescriptor& dlDesc,
                                              const WebRenderScrollData& aScrollData,
-                                             const wr::ByteBuffer& aResourceUpdates,
+                                             nsTArray<OpUpdateResource>&& aResourceUpdates,
+                                             nsTArray<ipc::Shmem>&& aResourceData,
                                              const wr::IdNamespace& aIdNamespace,
                                              const TimeStamp& aTxnStartTime,
                                              const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvSetDisplayListSync(const gfx::IntSize& aSize,
                                                  InfallibleTArray<WebRenderParentCommand>&& aCommands,
                                                  InfallibleTArray<OpDestroy>&& aToDestroy,
                                                  const uint64_t& aFwdTransactionId,
                                                  const uint64_t& aTransactionId,
                                                  const wr::LayoutSize& aContentSize,
                                                  const wr::ByteBuffer& dl,
                                                  const wr::BuiltDisplayListDescriptor& dlDesc,
                                                  const WebRenderScrollData& aScrollData,
-                                                 const wr::ByteBuffer& aResourceUpdates,
+                                                 nsTArray<OpUpdateResource>&& aResourceUpdates,
+                                                 nsTArray<ipc::Shmem>&& aResourceData,
                                                  const wr::IdNamespace& aIdNamespace,
                                                  const TimeStamp& aTxnStartTime,
                                                  const TimeStamp& aFwdTime) override;
   mozilla::ipc::IPCResult RecvParentCommands(nsTArray<WebRenderParentCommand>&& commands) override;
   mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture) override;
 
   mozilla::ipc::IPCResult RecvAddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds,
                                                            const CompositableHandle& aHandle,
@@ -176,19 +179,25 @@ public:
   void ScheduleComposition();
 
   void UpdateWebRender(CompositorVsyncScheduler* aScheduler,
                        wr::WebRenderAPI* aApi,
                        AsyncImagePipelineManager* aImageMgr,
                        CompositorAnimationStorage* aAnimStorage);
 
 private:
+  void DeallocShmems(nsTArray<ipc::Shmem>& aShmems);
+
   explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
   virtual ~WebRenderBridgeParent();
 
+  bool UpdateResources(const nsTArray<OpUpdateResource>& aResourceUpdates,
+                       const nsTArray<ipc::Shmem>& aResourceData,
+                       wr::ResourceUpdateQueue& aUpdates);
+
   uint64_t GetLayersId() const;
   void ProcessWebRenderParentCommands(const InfallibleTArray<WebRenderParentCommand>& aCommands,
                                       wr::ResourceUpdateQueue& aResources);
   void ProcessWebRenderCommands(const gfx::IntSize &aSize,
                                 InfallibleTArray<WebRenderParentCommand>& commands,
                                 const wr::Epoch& aEpoch,
                                 const wr::LayoutSize& aContentSize,
                                 const wr::ByteBuffer& dl,
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -33,16 +33,17 @@ WebRenderCanvasLayer::~WebRenderCanvasLa
 CanvasRenderer*
 WebRenderCanvasLayer::CreateCanvasRendererInternal()
 {
   return new WebRenderCanvasRendererSync(mManager->AsWebRenderLayerManager());
 }
 
 void
 WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                  wr::IpcResourceUpdateQueue& aResources,
                                   const StackingContextHelper& aSc)
 {
   WebRenderCanvasRendererSync* canvasRenderer = mCanvasRenderer->AsWebRenderCanvasRendererSync();
   MOZ_ASSERT(canvasRenderer);
   canvasRenderer->UpdateCompositableClient();
 
   Maybe<gfx::Matrix4x4> transform;
   if (canvasRenderer->NeedsYFlip()) {
--- a/gfx/layers/wr/WebRenderCanvasLayer.h
+++ b/gfx/layers/wr/WebRenderCanvasLayer.h
@@ -32,15 +32,16 @@ public:
   virtual void ClearCachedResources() override;
 
 protected:
   virtual ~WebRenderCanvasLayer();
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // GFX_WEBRENDERCANVASLAYER_H
--- a/gfx/layers/wr/WebRenderColorLayer.cpp
+++ b/gfx/layers/wr/WebRenderColorLayer.cpp
@@ -15,16 +15,17 @@
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 void
 WebRenderColorLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                 wr::IpcResourceUpdateQueue& aResources,
                                  const StackingContextHelper& aSc)
 {
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
   StackingContextHelper sc(aSc, aBuilder, this);
 
   LayerRect rect = Bounds();
   DumpLayerInfo("ColorLayer", rect);
 
--- a/gfx/layers/wr/WebRenderColorLayer.h
+++ b/gfx/layers/wr/WebRenderColorLayer.h
@@ -26,15 +26,16 @@ protected:
   virtual ~WebRenderColorLayer()
   {
     MOZ_COUNT_DTOR(WebRenderColorLayer);
   }
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // GFX_WEBRENDERCOLORLAYER_H
--- a/gfx/layers/wr/WebRenderContainerLayer.cpp
+++ b/gfx/layers/wr/WebRenderContainerLayer.cpp
@@ -28,16 +28,17 @@ WebRenderContainerLayer::UpdateTransform
       transformData.hasPerspectiveParent() =
         GetParent() && GetParent()->GetTransformIsPerspective();
     }
   }
 }
 
 void
 WebRenderContainerLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                     wr::IpcResourceUpdateQueue& aResources,
                                      const StackingContextHelper& aSc)
 {
   nsTArray<LayerPolygon> children = SortChildrenBy3DZOrder(SortMode::WITHOUT_GEOMETRY);
 
   gfx::Matrix4x4 transform = GetTransform();
   gfx::Matrix4x4* transformForSC = &transform;
   float opacity = GetLocalOpacity();
   float* opacityForSC = &opacity;
@@ -111,22 +112,23 @@ WebRenderContainerLayer::RenderLayer(wr:
 
   LayerRect rect = Bounds();
   DumpLayerInfo("ContainerLayer", rect);
 
   for (LayerPolygon& child : children) {
     if (child.layer->IsBackfaceHidden()) {
       continue;
     }
-    ToWebRenderLayer(child.layer)->RenderLayer(aBuilder, sc);
+    ToWebRenderLayer(child.layer)->RenderLayer(aBuilder, aResources, sc);
   }
 }
 
 void
 WebRenderRefLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                               wr::IpcResourceUpdateQueue& aResources,
                                const StackingContextHelper& aSc)
 {
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
 
   ParentLayerRect bounds = GetLocalTransformTyped().TransformBounds(Bounds());
   // As with WebRenderTextLayer, because we don't push a stacking context for
   // this layer, WR doesn't know about the transform on this layer. Therefore
   // we need to apply that transform to the bounds before we pass it on to WR.
--- a/gfx/layers/wr/WebRenderContainerLayer.h
+++ b/gfx/layers/wr/WebRenderContainerLayer.h
@@ -36,16 +36,17 @@ protected:
     MOZ_COUNT_DTOR(WebRenderContainerLayer);
   }
 
   void UpdateTransformDataForAnimation();
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 };
 
@@ -62,16 +63,17 @@ protected:
   virtual ~WebRenderRefLayer()
   {
     MOZ_COUNT_DTOR(WebRenderRefLayer);
   }
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
 
   virtual void ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) override
   {
     DefaultComputeEffectiveTransforms(aTransformToSurface);
   }
 };
 
--- a/gfx/layers/wr/WebRenderDisplayItemLayer.cpp
+++ b/gfx/layers/wr/WebRenderDisplayItemLayer.cpp
@@ -20,31 +20,32 @@ namespace layers {
 
 WebRenderDisplayItemLayer::~WebRenderDisplayItemLayer()
 {
   MOZ_COUNT_DTOR(WebRenderDisplayItemLayer);
 }
 
 void
 WebRenderDisplayItemLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                       wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc)
 {
   if (mVisibleRegion.IsEmpty()) {
     return;
   }
 
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
 
   if (mItem) {
     wr::LayoutSize contentSize; // this won't actually be used by anything
     wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
     // We might have recycled this layer. Throw away the old commands.
     mParentCommands.Clear();
 
-    mItem->CreateWebRenderCommands(builder, aSc, mParentCommands, WrManager(),
+    mItem->CreateWebRenderCommands(builder, aResources, aSc, mParentCommands, WrManager(),
                                    GetDisplayListBuilder());
     builder.Finalize(contentSize, mBuiltDisplayList);
   } else {
     // else we have an empty transaction and just use the
     // old commands.
     WebRenderLayerManager* manager = WrManager();
     MOZ_ASSERT(manager);
 
--- a/gfx/layers/wr/WebRenderDisplayItemLayer.h
+++ b/gfx/layers/wr/WebRenderDisplayItemLayer.h
@@ -27,16 +27,17 @@ public:
   }
 
 protected:
   virtual ~WebRenderDisplayItemLayer();
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aHelper) override;
 
 private:
   wr::BuiltDisplayList mBuiltDisplayList;
   nsTArray<WebRenderParentCommand> mParentCommands;
 };
 
 } // namespace layers
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -105,16 +105,17 @@ WebRenderImageLayer::SupportsAsyncUpdate
       mPipelineId.isSome()) {
     return true;
   }
   return false;
 }
 
 void
 WebRenderImageLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                 wr::IpcResourceUpdateQueue& aResources,
                                  const StackingContextHelper& aSc)
 {
   if (!mContainer) {
      return;
   }
 
   CompositableType type = GetImageClientType();
   if (type == CompositableType::UNKNOWN) {
--- a/gfx/layers/wr/WebRenderImageLayer.h
+++ b/gfx/layers/wr/WebRenderImageLayer.h
@@ -27,16 +27,17 @@ public:
   virtual bool SupportsAsyncUpdate() override;
 
 protected:
   virtual ~WebRenderImageLayer();
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
   Maybe<wr::WrImageMask> RenderMaskLayer(const StackingContextHelper& aSc,
                                          const gfx::Matrix4x4& aTransform) override;
 
 protected:
   CompositableType GetImageClientType();
   void ClearWrResources();
 
--- a/gfx/layers/wr/WebRenderLayer.h
+++ b/gfx/layers/wr/WebRenderLayer.h
@@ -20,16 +20,17 @@ class WebRenderLayerManager;
 
 typedef gfx::Matrix4x4Typed<LayerPixel, LayerPixel> BoundsTransformMatrix;
 
 class WebRenderLayer
 {
 public:
   virtual Layer* GetLayer() = 0;
   virtual void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                           wr::IpcResourceUpdateQueue& aResources,
                            const StackingContextHelper& aSc) = 0;
   virtual Maybe<wr::WrImageMask> RenderMaskLayer(const StackingContextHelper& aSc,
                                              const gfx::Matrix4x4& aTransform)
   {
     MOZ_ASSERT(false);
     return Nothing();
   }
 
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -6,16 +6,17 @@
 #include "WebRenderLayerManager.h"
 
 #include "BasicLayers.h"
 #include "gfxPrefs.h"
 #include "GeckoProfiler.h"
 #include "LayersLogging.h"
 #include "mozilla/gfx/DrawEventRecorder.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/layers/UpdateImageHelper.h"
 #include "nsDisplayList.h"
 #include "WebRenderCanvasLayer.h"
 #include "WebRenderCanvasRenderer.h"
 #include "WebRenderColorLayer.h"
@@ -92,18 +93,16 @@ WebRenderLayerManager::Destroy()
 
 void
 WebRenderLayerManager::DoDestroy(bool aIsSync)
 {
   if (IsDestroyed()) {
     return;
   }
 
-  mWidget->CleanupWebRenderWindowOverlay(WrBridge());
-
   LayerManager::Destroy();
 
   if (WrBridge()) {
     // Just clear ImageKeys, they are deleted during WebRenderAPI destruction.
     mImageKeysToDelete.Clear();
     // CompositorAnimations are cleared by WebRenderBridgeParent.
     mDiscardedCompositorAnimationsIds.Clear();
     WrBridge()->Destroy(aIsSync);
@@ -201,17 +200,18 @@ PopulateScrollData(WebRenderScrollData& 
   aTarget.GetLayerDataMutable(index)->Initialize(aTarget, aLayer, descendants);
   return descendants + 1;
 }
 
 void
 WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
                                                               nsDisplayListBuilder* aDisplayListBuilder,
                                                               const StackingContextHelper& aSc,
-                                                              wr::DisplayListBuilder& aBuilder)
+                                                              wr::DisplayListBuilder& aBuilder,
+                                                              wr::IpcResourceUpdateQueue& aResources)
 {
   bool apzEnabled = AsyncPanZoomEnabled();
   EventRegions eventRegions;
 
   nsDisplayList savedItems;
   nsDisplayItem* item;
   while ((item = aDisplayList->RemoveBottom()) != nullptr) {
     DisplayItemType itemType = item->GetType();
@@ -333,19 +333,19 @@ WebRenderLayerManager::CreateWebRenderCo
       }
     }
 
     { // scope the ScrollingLayersHelper
       ScrollingLayersHelper clip(item, aBuilder, aSc, mClipIdCache, AsyncPanZoomEnabled());
 
       // Note: this call to CreateWebRenderCommands can recurse back into
       // this function if the |item| is a wrapper for a sublist.
-      if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
+      if (!item->CreateWebRenderCommands(aBuilder, aResources, aSc, mParentCommands, this,
                                          aDisplayListBuilder)) {
-        PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
+        PushItemAsImage(item, aBuilder, aResources, aSc, aDisplayListBuilder);
       }
     }
 
     if (apzEnabled && forceNewLayerData) {
       // Pop the thing we pushed before the recursion, so the topmost item on
       // the stack is enclosing display item's ASR (or the stack is empty)
       mAsrStack.pop_back();
       const ActiveScrolledRoot* stopAtAsr =
@@ -507,16 +507,17 @@ PaintItemByDrawTarget(nsDisplayItem* aIt
     float b = float(rand()) / RAND_MAX;
     aDT->FillRect(Rect(0, 0, aImageRect.Width(), aImageRect.Height()), ColorPattern(Color(r, g, b, 0.5)));
   }
 }
 
 already_AddRefed<WebRenderFallbackData>
 WebRenderLayerManager::GenerateFallbackData(nsDisplayItem* aItem,
                                             wr::DisplayListBuilder& aBuilder,
+                                            wr::IpcResourceUpdateQueue& aResources,
                                             nsDisplayListBuilder* aDisplayListBuilder,
                                             LayerRect& aImageRect,
                                             LayerPoint& aOffset)
 {
   RefPtr<WebRenderFallbackData> fallbackData = CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
 
   bool snap;
   nsRect itemBounds = aItem->GetBounds(aDisplayListBuilder, &snap);
@@ -583,17 +584,17 @@ WebRenderLayerManager::GenerateFallbackD
         gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8A8);
       RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
       PaintItemByDrawTarget(aItem, dt, aImageRect, aOffset, aDisplayListBuilder);
       recorder->Finish();
 
       Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
       wr::ImageKey key = WrBridge()->GetNextImageKey();
       wr::ImageDescriptor descriptor(imageSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
-      aBuilder.Resources().AddBlobImage(key, descriptor, bytes);
+      aResources.AddBlobImage(key, descriptor, bytes);
       fallbackData->SetKey(key);
     } else {
       fallbackData->CreateImageClientIfNeeded();
       RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
       RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
 
       {
         UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize(), format);
@@ -628,44 +629,48 @@ WebRenderLayerManager::GenerateFallbackD
   MOZ_ASSERT(fallbackData->GetKey());
 
   return fallbackData.forget();
 }
 
 Maybe<wr::WrImageMask>
 WebRenderLayerManager::BuildWrMaskImage(nsDisplayItem* aItem,
                                         wr::DisplayListBuilder& aBuilder,
+                                        wr::IpcResourceUpdateQueue& aResources,
                                         const StackingContextHelper& aSc,
                                         nsDisplayListBuilder* aDisplayListBuilder,
                                         const LayerRect& aBounds)
 {
   LayerRect imageRect;
   LayerPoint offset;
-  RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aDisplayListBuilder,
+  RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
+                                                                    aDisplayListBuilder,
                                                                     imageRect, offset);
   if (!fallbackData) {
     return Nothing();
   }
 
   wr::WrImageMask imageMask;
   imageMask.image = fallbackData->GetKey().value();
   imageMask.rect = aSc.ToRelativeLayoutRect(aBounds);
   imageMask.repeat = false;
   return Some(imageMask);
 }
 
 bool
 WebRenderLayerManager::PushItemAsImage(nsDisplayItem* aItem,
                                        wr::DisplayListBuilder& aBuilder,
+                                       wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsDisplayListBuilder* aDisplayListBuilder)
 {
   LayerRect imageRect;
   LayerPoint offset;
-  RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aDisplayListBuilder,
+  RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
+                                                                    aDisplayListBuilder,
                                                                     imageRect, offset);
   if (!fallbackData) {
     return false;
   }
 
   wr::LayoutRect dest = aSc.ToRelativeLayoutRect(imageRect + offset);
   SamplingFilter sampleFilter = nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
   aBuilder.PushImage(dest,
@@ -708,33 +713,34 @@ WebRenderLayerManager::EndTransactionInt
   LayoutDeviceIntSize size = mWidget->GetClientSize();
   if (!WrBridge()->BeginTransaction(size.ToUnknownSize())) {
     return false;
   }
   DiscardCompositorAnimations();
 
   wr::LayoutSize contentSize { (float)size.width, (float)size.height };
   wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
+  wr::IpcResourceUpdateQueue resourceUpdates(WrBridge()->GetShmemAllocator());
 
   if (mEndTransactionWithoutLayers) {
     // Reset the notification flag at the begin of the EndTransaction.
     mShouldNotifyInvalidation = false;
 
     // aDisplayList being null here means this is an empty transaction following a layers-free
     // transaction, so we reuse the previously built displaylist and scroll
     // metadata information
     if (aDisplayList && aDisplayListBuilder) {
       StackingContextHelper sc;
       mParentCommands.Clear();
       mScrollData = WebRenderScrollData();
       MOZ_ASSERT(mLayerScrollData.empty());
       mLastCanvasDatas.Clear();
       mLastAsr = nullptr;
 
-      CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
+      CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder, resourceUpdates);
 
       builder.Finalize(contentSize, mBuiltDisplayList);
 
       // Make a "root" layer data that has everything else as descendants
       mLayerScrollData.emplace_back();
       mLayerScrollData.back().InitializeRoot(mLayerScrollData.size() - 1);
       if (aDisplayListBuilder->IsBuildingLayerEventRegions()) {
         nsIPresShell* shell = aDisplayListBuilder->RootReferenceFrame()->PresContext()->PresShell();
@@ -772,24 +778,24 @@ WebRenderLayerManager::EndTransactionInt
     builder.PushBuiltDisplayList(mBuiltDisplayList);
     WrBridge()->AddWebRenderParentCommands(mParentCommands);
   } else {
     mScrollData = WebRenderScrollData();
 
     mRoot->StartPendingAnimations(mAnimationReadyTime);
     StackingContextHelper sc;
 
-    WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
+    WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, resourceUpdates, sc);
 
     // Need to do this after RenderLayer because the compositor animation IDs
     // get populated during RenderLayer and we need those.
     PopulateScrollData(mScrollData, mRoot.get());
   }
 
-  mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
+  mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder, resourceUpdates);
   WrBridge()->ClearReadLocks();
 
   // We can't finish this transaction so return. This usually
   // happens in an empty transaction where we can't repaint a painted layer.
   // In this case, leave the transaction open and let a full transaction happen.
   if (mTransactionIncomplete) {
     DiscardLocalImages();
     WrBridge()->ProcessWebRenderParentCommands();
@@ -817,17 +823,17 @@ WebRenderLayerManager::EndTransactionInt
     if (WrBridge()->GetSyncObject() &&
         WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
       WrBridge()->GetSyncObject()->Synchronize();
     }
   }
   {
     AutoProfilerTracing
       tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
-    WrBridge()->EndTransaction(builder, size.ToUnknownSize(), sync,
+    WrBridge()->EndTransaction(builder, resourceUpdates, size.ToUnknownSize(), sync,
                                mLatestTransactionId, mScrollData, transactionStart);
   }
 
   MakeSnapshotIfRequired(size);
   mNeedsComposite = false;
 
   ClearDisplayItemLayers();
 
@@ -911,23 +917,28 @@ WebRenderLayerManager::MakeSnapshotIfReq
   dt->FillRect(dst, pattern);
 
   mTarget = nullptr;
 }
 
 void
 WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
 {
-  mImageKeysToDelete.DeleteImage(key);
+  mImageKeysToDelete.AppendElement(key);
 }
 
 void
 WebRenderLayerManager::DiscardImages()
 {
-  WrBridge()->UpdateResources(mImageKeysToDelete);
+  wr::IpcResourceUpdateQueue resources(WrBridge()->GetShmemAllocator());
+  for (const auto& key : mImageKeysToDelete) {
+    resources.DeleteImage(key);
+  }
+  mImageKeysToDelete.Clear();
+  WrBridge()->UpdateResources(resources);
 }
 
 void
 WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
 {
   mDiscardedCompositorAnimationsIds.AppendElement(aId);
 }
 
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -22,16 +22,17 @@
 #include "nsDisplayList.h"
 
 class nsIWidget;
 
 namespace mozilla {
 
 struct ActiveScrolledRoot;
 
+
 namespace layers {
 
 class CompositorBridgeChild;
 class KnowsCompositor;
 class PCompositorBridgeChild;
 class WebRenderBridgeChild;
 class WebRenderParentCommand;
 
@@ -65,34 +66,41 @@ public:
                                      mozilla::wr::DisplayListBuilder& aBuilder,
                                      const StackingContextHelper& aSc,
                                      gfx::IntSize& aSize);
   bool PushImage(nsDisplayItem* aItem,
                  ImageContainer* aContainer,
                  mozilla::wr::DisplayListBuilder& aBuilder,
                  const StackingContextHelper& aSc,
                  const LayerRect& aRect);
-  already_AddRefed<WebRenderFallbackData> GenerateFallbackData(nsDisplayItem* aItem,
-                                                               wr::DisplayListBuilder& aBuilder,
-                                                               nsDisplayListBuilder* aDisplayListBuilder,
-                                                               LayerRect& aImageRect,
-                                                               LayerPoint& aOffset);
+
+  already_AddRefed<WebRenderFallbackData>
+  GenerateFallbackData(nsDisplayItem* aItem,
+                       wr::DisplayListBuilder& aBuilder,
+                       wr::IpcResourceUpdateQueue& aResourceUpdates,
+                       nsDisplayListBuilder* aDisplayListBuilder,
+                       LayerRect& aImageRect,
+                       LayerPoint& aOffset);
+
   Maybe<wr::WrImageMask> BuildWrMaskImage(nsDisplayItem* aItem,
                                           wr::DisplayListBuilder& aBuilder,
+                                          wr::IpcResourceUpdateQueue& aResources,
                                           const StackingContextHelper& aSc,
                                           nsDisplayListBuilder* aDisplayListBuilder,
                                           const LayerRect& aBounds);
   bool PushItemAsImage(nsDisplayItem* aItem,
                        wr::DisplayListBuilder& aBuilder,
+                       wr::IpcResourceUpdateQueue& aResources,
                        const StackingContextHelper& aSc,
                        nsDisplayListBuilder* aDisplayListBuilder);
   void CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
                                               nsDisplayListBuilder* aDisplayListBuilder,
                                               const StackingContextHelper& aSc,
-                                              wr::DisplayListBuilder& aBuilder);
+                                              wr::DisplayListBuilder& aBuilder,
+                                              wr::IpcResourceUpdateQueue& aResources);
   void EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
                                   nsDisplayListBuilder* aDisplayListBuilder);
   bool IsLayersFreeTransaction() { return mEndTransactionWithoutLayers; }
   virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags = END_DEFAULT) override;
 
   virtual LayersBackend GetBackendType() override { return LayersBackend::LAYERS_WR; }
@@ -236,17 +244,17 @@ private:
   bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
                               void* aCallbackData,
                               EndTransactionFlags aFlags,
                               nsDisplayList* aDisplayList = nullptr,
                               nsDisplayListBuilder* aDisplayListBuilder = nullptr);
 
 private:
   nsIWidget* MOZ_NON_OWNING_REF mWidget;
-  wr::ResourceUpdateQueue mImageKeysToDelete;
+  nsTArray<wr::ImageKey> mImageKeysToDelete;
   nsTArray<uint64_t> mDiscardedCompositorAnimationsIds;
 
   /* PaintedLayer callbacks; valid at the end of a transaciton,
    * while rendering */
   DrawPaintedLayerCallback mPaintedLayerCallback;
   void *mPaintedLayerCallbackData;
 
   RefPtr<WebRenderBridgeChild> mWrChild;
--- a/gfx/layers/wr/WebRenderMessageUtils.h
+++ b/gfx/layers/wr/WebRenderMessageUtils.h
@@ -31,16 +31,42 @@ struct ParamTraits<mozilla::wr::ByteBuff
     size_t length;
     return ReadParam(aMsg, aIter, &length)
         && aResult->Allocate(length)
         && aMsg->ReadBytesInto(aIter, aResult->mData, length);
   }
 };
 
 template<>
+struct ParamTraits<mozilla::wr::ImageDescriptor>
+{
+  typedef mozilla::wr::ImageDescriptor paramType;
+
+  static void
+  Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.format);
+    WriteParam(aMsg, aParam.width);
+    WriteParam(aMsg, aParam.height);
+    WriteParam(aMsg, aParam.stride);
+    WriteParam(aMsg, aParam.is_opaque);
+  }
+
+  static bool
+  Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->format)
+        && ReadParam(aMsg, aIter, &aResult->width)
+        && ReadParam(aMsg, aIter, &aResult->height)
+        && ReadParam(aMsg, aIter, &aResult->stride)
+        && ReadParam(aMsg, aIter, &aResult->is_opaque);
+  }
+};
+
+template<>
 struct ParamTraits<mozilla::wr::IdNamespace>
   : public PlainOldDataSerializer<mozilla::wr::IdNamespace>
 {
 };
 
 template<>
 struct ParamTraits<mozilla::wr::ImageKey>
   : public PlainOldDataSerializer<mozilla::wr::ImageKey>
--- a/gfx/layers/wr/WebRenderPaintedLayer.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp
@@ -104,16 +104,17 @@ WebRenderPaintedLayer::CreateWebRenderDi
   WrManager()->AddImageKeyForDiscard(key);
 
   wr::LayoutRect r = sc.ToRelativeLayoutRect(rect);
   aBuilder.PushImage(r, r, wr::ImageRendering::Auto, key);
 }
 
 void
 WebRenderPaintedLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                   wr::IpcResourceUpdateQueue& aResources,
                                    const StackingContextHelper& aSc)
 {
   if (!SetupExternalImages()) {
     return;
   }
 
   if (GetVisibleRegion().IsEmpty()) {
     if (gfxPrefs::LayersDump()) {
--- a/gfx/layers/wr/WebRenderPaintedLayer.h
+++ b/gfx/layers/wr/WebRenderPaintedLayer.h
@@ -41,16 +41,17 @@ public:
   virtual void InvalidateRegion(const nsIntRegion& aRegion) override
   {
     mInvalidRegion.Add(aRegion);
     UpdateValidRegionAfterInvalidRegionChanged();
   }
 
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
   virtual void ClearCachedResources() override;
 
   RefPtr<ImageContainer> mImageContainer;
   RefPtr<ImageClient> mImageClient;
 
 private:
   bool SetupExternalImages();
--- a/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayerBlob.cpp
@@ -8,26 +8,28 @@
 #include "gfxPrefs.h"
 #include "gfxUtils.h"
 #include "LayersLogging.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/gfx/DrawEventRecorder.h"
 #include "mozilla/layers/ScrollingLayersHelper.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/UpdateImageHelper.h"
 #include "mozilla/webrender/WebRenderTypes.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 void
 WebRenderPaintedLayerBlob::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                       wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc)
 {
   LayerIntRegion visibleRegion = GetVisibleRegion();
   LayerIntRect bounds = visibleRegion.GetBounds();
   LayerIntSize size = bounds.Size();
 
   if (visibleRegion.IsEmpty()) {
     if (gfxPrefs::LayersDump()) {
@@ -70,22 +72,22 @@ WebRenderPaintedLayerBlob::RenderLayer(w
     recorder->Finish();
 
     AddToValidRegion(regionToPaint);
 
     wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
 
     if (mImageKey.isSome()) {
       //XXX: We should switch to updating the blob image instead of adding a new one
-      aBuilder.Resources().DeleteImage(mImageKey.value());
+      aResources.DeleteImage(mImageKey.value());
     }
     mImageKey = Some(GenerateImageKey());
 
     wr::ImageDescriptor descriptor(imageSize, 0, dt->GetFormat());
-    aBuilder.Resources().AddBlobImage(mImageKey.value(), descriptor, bytes.AsSlice());
+    aResources.AddBlobImage(mImageKey.value(), descriptor, bytes.AsSlice());
     mImageBounds = visibleRegion.GetBounds();
   }
 
   ScrollingLayersHelper scroller(this, aBuilder, aSc);
   StackingContextHelper sc(aSc, aBuilder, this);
   LayerRect rect = Bounds();
   DumpLayerInfo("PaintedLayer", rect);
 
--- a/gfx/layers/wr/WebRenderPaintedLayerBlob.h
+++ b/gfx/layers/wr/WebRenderPaintedLayerBlob.h
@@ -55,16 +55,17 @@ public:
     UpdateValidRegionAfterInvalidRegionChanged();
   }
   virtual void ClearCachedResources() override
   {
     ClearWrResources();
   }
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResourceUpdates,
                    const StackingContextHelper& aSc) override;
 private:
   Maybe<wr::WrImageKey> mImageKey;
   LayerIntRect mImageBounds;
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderTextLayer.cpp
+++ b/gfx/layers/wr/WebRenderTextLayer.cpp
@@ -15,16 +15,17 @@
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 void
 WebRenderTextLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
+                                wr::IpcResourceUpdateQueue& aResources,
                                 const StackingContextHelper& aSc)
 {
     if (mBounds.IsEmpty()) {
         return;
     }
 
     ScrollingLayersHelper scroller(this, aBuilder, aSc);
 
--- a/gfx/layers/wr/WebRenderTextLayer.h
+++ b/gfx/layers/wr/WebRenderTextLayer.h
@@ -28,16 +28,17 @@ protected:
     virtual ~WebRenderTextLayer()
     {
         MOZ_COUNT_DTOR(WebRenderTextLayer);
     }
 
 public:
   Layer* GetLayer() override { return this; }
   void RenderLayer(wr::DisplayListBuilder& aBuilder,
+                   wr::IpcResourceUpdateQueue& aResources,
                    const StackingContextHelper& aSc) override;
 
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // GFX_WEBRENDERTEXTLAYER_H
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -451,58 +451,40 @@ ResourceUpdateQueue::operator=(ResourceU
 
 ResourceUpdateQueue::~ResourceUpdateQueue()
 {
   if (mUpdates) {
     wr_resource_updates_delete(mUpdates);
   }
 }
 
-ByteBuffer
-ResourceUpdateQueue::Serialize()
-{
-  VecU8 data;
-  wr_resource_updates_serialize(mUpdates, &data);
-  ByteBuffer result(Move(data));
-  return result;
-}
-
-//static
-ResourceUpdateQueue
-ResourceUpdateQueue::Deserialize(Range<uint8_t> aData)
-{
-  auto slice = wr::RangeToByteSlice(aData);
-  ResourceUpdateQueue result(wr_resource_updates_deserialize(slice));
-  return result;
-}
-
 void
 ResourceUpdateQueue::Clear()
 {
   wr_resource_updates_clear(mUpdates);
 }
 
 void
 ResourceUpdateQueue::AddImage(ImageKey key, const ImageDescriptor& aDescriptor,
-                              Range<uint8_t> aBytes)
+                              wr::Vec_u8& aBytes)
 {
   wr_resource_updates_add_image(mUpdates,
                                 key,
                                 &aDescriptor,
-                                RangeToByteSlice(aBytes));
+                                &aBytes.inner);
 }
 
 void
 ResourceUpdateQueue::AddBlobImage(ImageKey key, const ImageDescriptor& aDescriptor,
-                                  Range<uint8_t> aBytes)
+                                  wr::Vec_u8& aBytes)
 {
   wr_resource_updates_add_blob_image(mUpdates,
                                      key,
                                      &aDescriptor,
-                                     RangeToByteSlice(aBytes));
+                                     &aBytes.inner);
 }
 
 void
 ResourceUpdateQueue::AddExternalImage(ImageKey key,
                                       const ImageDescriptor& aDescriptor,
                                       ExternalImageId aExtID,
                                       wr::WrExternalImageBufferType aBufferType,
                                       uint8_t aChannelIndex)
@@ -524,33 +506,33 @@ ResourceUpdateQueue::AddExternalImageBuf
   AddExternalImage(aKey, aDescriptor, aHandle,
                    wr::WrExternalImageBufferType::ExternalBuffer,
                    channelIndex);
 }
 
 void
 ResourceUpdateQueue::UpdateImageBuffer(ImageKey aKey,
                                        const ImageDescriptor& aDescriptor,
-                                       Range<uint8_t> aBytes)
+                                       wr::Vec_u8& aBytes)
 {
   wr_resource_updates_update_image(mUpdates,
                                    aKey,
                                    &aDescriptor,
-                                   RangeToByteSlice(aBytes));
+                                   &aBytes.inner);
 }
 
 void
 ResourceUpdateQueue::UpdateBlobImage(ImageKey aKey,
                                      const ImageDescriptor& aDescriptor,
-                                     Range<uint8_t> aBytes)
+                                     wr::Vec_u8& aBytes)
 {
   wr_resource_updates_update_blob_image(mUpdates,
                                         aKey,
                                         &aDescriptor,
-                                        RangeToByteSlice(aBytes));
+                                        &aBytes.inner);
 }
 
 void
 ResourceUpdateQueue::UpdateExternalImage(ImageKey aKey,
                                          const ImageDescriptor& aDescriptor,
                                          ExternalImageId aExtID,
                                          wr::WrExternalImageBufferType aBufferType,
                                          uint8_t aChannelIndex)
@@ -565,19 +547,19 @@ ResourceUpdateQueue::UpdateExternalImage
 
 void
 ResourceUpdateQueue::DeleteImage(ImageKey aKey)
 {
   wr_resource_updates_delete_image(mUpdates, aKey);
 }
 
 void
-ResourceUpdateQueue::AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex)
+ResourceUpdateQueue::AddRawFont(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex)
 {
-  wr_resource_updates_add_raw_font(mUpdates, aKey, &aBytes[0], aBytes.length(), aIndex);
+  wr_resource_updates_add_raw_font(mUpdates, aKey, &aBytes.inner, aIndex);
 }
 
 void
 ResourceUpdateQueue::DeleteFont(wr::FontKey aKey)
 {
   wr_resource_updates_delete_font(mUpdates, aKey);
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -54,56 +54,51 @@ class ResourceUpdateQueue {
 public:
   ResourceUpdateQueue();
   ~ResourceUpdateQueue();
   ResourceUpdateQueue(ResourceUpdateQueue&&);
   ResourceUpdateQueue(const ResourceUpdateQueue&) = delete;
   ResourceUpdateQueue& operator=(ResourceUpdateQueue&&);
   ResourceUpdateQueue& operator=(const ResourceUpdateQueue&) = delete;
 
-  /// Serializes into a buffer of bytes and clears the queue.
-  ByteBuffer Serialize();
-
-  static ResourceUpdateQueue Deserialize(Range<uint8_t> aData);
-
   void AddImage(wr::ImageKey aKey,
                 const ImageDescriptor& aDescriptor,
-                Range<uint8_t> aBytes);
+                wr::Vec_u8& aBytes);
 
   void AddBlobImage(wr::ImageKey aKey,
                     const ImageDescriptor& aDescriptor,
-                    Range<uint8_t> aBytes);
+                    wr::Vec_u8& aBytes);
 
   void AddExternalImageBuffer(ImageKey key,
                               const ImageDescriptor& aDescriptor,
                               ExternalImageId aHandle);
 
   void AddExternalImage(ImageKey key,
                         const ImageDescriptor& aDescriptor,
                         ExternalImageId aExtID,
                         WrExternalImageBufferType aBufferType,
                         uint8_t aChannelIndex = 0);
 
   void UpdateImageBuffer(wr::ImageKey aKey,
                          const ImageDescriptor& aDescriptor,
-                         Range<uint8_t> aBytes);
+                         wr::Vec_u8& aBytes);
 
   void UpdateBlobImage(wr::ImageKey aKey,
                        const ImageDescriptor& aDescriptor,
-                       Range<uint8_t> aBytes);
+                       wr::Vec_u8& aBytes);
 
   void UpdateExternalImage(ImageKey aKey,
                            const ImageDescriptor& aDescriptor,
                            ExternalImageId aExtID,
                            wr::WrExternalImageBufferType aBufferType,
                            uint8_t aChannelIndex = 0);
 
   void DeleteImage(wr::ImageKey aKey);
 
-  void AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
+  void AddRawFont(wr::FontKey aKey, wr::Vec_u8& aBytes, uint32_t aIndex);
 
   void DeleteFont(wr::FontKey aKey);
 
   void AddFontInstance(wr::FontInstanceKey aKey,
                        wr::FontKey aFontKey,
                        float aGlyphSize,
                        const wr::FontInstanceOptions* aOptions,
                        const wr::FontInstancePlatformOptions* aPlatformOptions);
@@ -362,36 +357,32 @@ public:
                      const wr::LayoutRect& aBoxBounds,
                      const wr::LayoutVector2D& aOffset,
                      const wr::ColorF& aColor,
                      const float& aBlurRadius,
                      const float& aSpreadRadius,
                      const float& aBorderRadius,
                      const wr::BoxShadowClipMode& aClipMode);
 
-  ResourceUpdateQueue& Resources() { return mResourceUpdates; }
-
   // Returns the clip id that was most recently pushed with PushClip and that
   // has not yet been popped with PopClip. Return Nothing() if the clip stack
   // is empty.
   Maybe<wr::WrClipId> TopmostClipId();
   // Same as TopmostClipId() but for scroll layers.
   layers::FrameMetrics::ViewID TopmostScrollId();
   // Returns the scroll id that was pushed just before the given scroll id. This
   // function returns Nothing() if the given scrollid has not been encountered,
   // or if it is the rootmost scroll id (and therefore has no ancestor).
   Maybe<layers::FrameMetrics::ViewID> ParentScrollIdFor(layers::FrameMetrics::ViewID aScrollId);
 
   // Try to avoid using this when possible.
   wr::WrState* Raw() { return mWrState; }
 protected:
   wr::WrState* mWrState;
 
-  ResourceUpdateQueue mResourceUpdates;
-
   // Track the stack of clip ids and scroll layer ids that have been pushed
   // (by PushClip and PushScrollLayer, respectively) and are still active.
   // This is helpful for knowing e.g. what the ancestor scroll id of a particular
   // scroll id is, and doing other "queries" of current state.
   std::vector<wr::WrClipId> mClipIdStack;
   std::vector<layers::FrameMetrics::ViewID> mScrollIdStack;
 
   // Track the parent scroll id of each scroll id that we encountered. A
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -90,16 +90,26 @@ ImageFormatToSurfaceFormat(ImageFormat a
     case ImageFormat::RGB8:
       return gfx::SurfaceFormat::B8G8R8;
     default:
       return gfx::SurfaceFormat::UNKNOWN;
   }
 }
 
 struct ImageDescriptor: public wr::WrImageDescriptor {
+  // We need a default constructor for ipdl serialization.
+  ImageDescriptor()
+  {
+    format = wr::ImageFormat::Invalid;
+    width = 0;
+    height = 0;
+    stride = 0;
+    is_opaque = false;
+  }
+
   ImageDescriptor(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat)
   {
     format = wr::SurfaceFormatToImageFormat(aFormat).value();
     width = aSize.width;
     height = aSize.height;
     stride = 0;
     is_opaque = gfx::IsOpaqueFormat(aFormat);
   }
@@ -528,16 +538,28 @@ static inline wr::WrExternalImage Native
 {
   return wr::WrExternalImage {
     wr::WrExternalImageType::NativeTexture,
     aHandle, u0, v0, u1, v1,
     nullptr, 0
   };
 }
 
+inline wr::ByteSlice RangeToByteSlice(mozilla::Range<uint8_t> aRange) {
+  return wr::ByteSlice { aRange.begin().get(), aRange.length() };
+}
+
+inline mozilla::Range<const uint8_t> ByteSliceToRange(wr::ByteSlice aWrSlice) {
+  return mozilla::Range<const uint8_t>(aWrSlice.buffer, aWrSlice.len);
+}
+
+inline mozilla::Range<uint8_t> MutByteSliceToRange(wr::MutByteSlice aWrSlice) {
+  return mozilla::Range<uint8_t>(aWrSlice.buffer, aWrSlice.len);
+}
+
 struct Vec_u8 {
   wr::WrVecU8 inner;
   Vec_u8() {
     SetEmpty();
   }
   Vec_u8(Vec_u8&) = delete;
   Vec_u8(Vec_u8&& src) {
     inner = src.inner;
@@ -560,16 +582,23 @@ struct Vec_u8 {
 
   void
   SetEmpty() {
     inner.data = (uint8_t*)1;
     inner.capacity = 0;
     inner.length = 0;
   }
 
+  size_t Length() { return inner.length; }
+
+  void PushBytes(Range<uint8_t> aBytes)
+  {
+    wr_vec_u8_push_bytes(&inner, RangeToByteSlice(aBytes));
+  }
+
   ~Vec_u8() {
     if (inner.data) {
       wr_vec_u8_free(inner);
     }
   }
 };
 
 struct ByteBuffer
@@ -602,16 +631,27 @@ struct ByteBuffer
   , mData(aFrom.mData)
   , mOwned(aFrom.mOwned)
   {
     aFrom.mLength = 0;
     aFrom.mData = nullptr;
     aFrom.mOwned = false;
   }
 
+  ByteBuffer(ByteBuffer& aFrom)
+  : mLength(aFrom.mLength)
+  , mData(aFrom.mData)
+  , mOwned(aFrom.mOwned)
+  {
+    aFrom.mLength = 0;
+    aFrom.mData = nullptr;
+    aFrom.mOwned = false;
+  }
+
+
   ByteBuffer()
     : mLength(0)
     , mData(nullptr)
     , mOwned(false)
   {}
 
   bool
   Allocate(size_t aLength)
@@ -642,28 +682,16 @@ struct ByteBuffer
           !(memcmp(mData, other.mData, mLength));
   }
 
   size_t mLength;
   uint8_t* mData;
   bool mOwned;
 };
 
-inline wr::ByteSlice RangeToByteSlice(mozilla::Range<uint8_t> aRange) {
-  return wr::ByteSlice { aRange.begin().get(), aRange.length() };
-}
-
-inline mozilla::Range<const uint8_t> ByteSliceToRange(wr::ByteSlice aWrSlice) {
-  return mozilla::Range<const uint8_t>(aWrSlice.buffer, aWrSlice.len);
-}
-
-inline mozilla::Range<uint8_t> MutByteSliceToRange(wr::MutByteSlice aWrSlice) {
-  return mozilla::Range<uint8_t>(aWrSlice.buffer, aWrSlice.len);
-}
-
 struct BuiltDisplayList {
   wr::VecU8 dl;
   wr::BuiltDisplayListDescriptor dl_desc;
 };
 
 static inline wr::WrFilterOpType ToWrFilterOpType(const layers::CSSFilterType type) {
   switch (type) {
     case layers::CSSFilterType::BLUR:
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1,11 +1,12 @@
 use std::ffi::CString;
 use std::{mem, slice};
 use std::path::PathBuf;
+use std::ptr;
 use std::sync::Arc;
 use std::os::raw::{c_void, c_char, c_float};
 use gleam::gl;
 
 use webrender_api::*;
 use webrender::{ReadPixelsFormat, Renderer, RendererOptions};
 use webrender::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use webrender::DebugFlags;
@@ -80,25 +81,47 @@ pub struct WrVecU8 {
     length: usize,
     capacity: usize,
 }
 
 impl WrVecU8 {
     fn to_vec(self) -> Vec<u8> {
         unsafe { Vec::from_raw_parts(self.data, self.length, self.capacity) }
     }
+
+    // Equivalent to `to_vec` but clears self instead of consuming the value.
+    fn flush_into_vec(&mut self) -> Vec<u8> {
+        let vec = unsafe { Vec::from_raw_parts(self.data, self.length, self.capacity) };
+        self.data = ptr::null_mut();
+        self.length = 0;
+        self.capacity = 0;
+        return vec;
+    }
+
     fn from_vec(mut v: Vec<u8>) -> WrVecU8 {
         let w = WrVecU8 {
             data: v.as_mut_ptr(),
             length: v.len(),
             capacity: v.capacity(),
         };
         mem::forget(v);
         w
     }
+
+    fn push_bytes(&mut self, bytes: &[u8]) {
+        let mut vec = self.flush_into_vec();
+        vec.extend_from_slice(bytes);
+        *self = Self::from_vec(vec);
+    }
+}
+
+
+#[no_mangle]
+pub extern "C" fn wr_vec_u8_push_bytes(v: &mut WrVecU8, bytes: ByteSlice) {
+    v.push_bytes(bytes.as_slice());
 }
 
 #[no_mangle]
 pub extern "C" fn wr_vec_u8_free(v: WrVecU8) {
     v.to_vec();
 }
 
 #[repr(C)]
@@ -661,39 +684,37 @@ pub unsafe extern "C" fn wr_api_delete(d
     }
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_add_image(
     resources: &mut ResourceUpdates,
     image_key: WrImageKey,
     descriptor: &WrImageDescriptor,
-    bytes: ByteSlice
+    bytes: &mut WrVecU8,
 ) {
-    let copied_bytes = bytes.as_slice().to_owned();
     resources.add_image(
         image_key,
         descriptor.into(),
-        ImageData::new(copied_bytes),
+        ImageData::new(bytes.flush_into_vec()),
         None
     );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_add_blob_image(
     resources: &mut ResourceUpdates,
     image_key: WrImageKey,
     descriptor: &WrImageDescriptor,
-    bytes: ByteSlice
+    bytes: &mut WrVecU8,
 ) {
-    let copied_bytes = bytes.as_slice().to_owned();
     resources.add_image(
         image_key,
         descriptor.into(),
-        ImageData::new_blob_image(copied_bytes),
+        ImageData::new_blob_image(bytes.flush_into_vec()),
         None
     );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_add_external_image(
     resources: &mut ResourceUpdates,
     image_key: WrImageKey,
@@ -716,20 +737,24 @@ pub extern "C" fn wr_resource_updates_ad
     );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_update_image(
     resources: &mut ResourceUpdates,
     key: WrImageKey,
     descriptor: &WrImageDescriptor,
-    bytes: ByteSlice
+    bytes: &mut WrVecU8,
 ) {
-    let copied_bytes = bytes.as_slice().to_owned();
-    resources.update_image(key, descriptor.into(), ImageData::new(copied_bytes), None);
+    resources.update_image(
+        key,
+        descriptor.into(),
+        ImageData::new(bytes.flush_into_vec()),
+        None
+    );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_update_external_image(
     resources: &mut ResourceUpdates,
     key: WrImageKey,
     descriptor: &WrImageDescriptor,
     external_image_id: WrExternalImageId,
@@ -750,23 +775,22 @@ pub extern "C" fn wr_resource_updates_up
     );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_update_blob_image(
     resources: &mut ResourceUpdates,
     image_key: WrImageKey,
     descriptor: &WrImageDescriptor,
-    bytes: ByteSlice
+    bytes: &mut WrVecU8,
 ) {
-    let copied_bytes = bytes.as_slice().to_owned();
     resources.update_image(
         image_key,
         descriptor.into(),
-        ImageData::new_blob_image(copied_bytes),
+        ImageData::new_blob_image(bytes.flush_into_vec()),
         None
     );
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_delete_image(
     resources: &mut ResourceUpdates,
     key: WrImageKey
@@ -912,25 +936,20 @@ pub extern "C" fn wr_api_send_external_e
 
     dh.api.send_external_event(ExternalEvent::from_raw(evt));
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_add_raw_font(
     resources: &mut ResourceUpdates,
     key: WrFontKey,
-    font_buffer: *mut u8,
-    buffer_size: usize,
+    bytes: &mut WrVecU8,
     index: u32
 ) {
-    let font_slice = make_slice(font_buffer, buffer_size);
-    let mut font_vector = Vec::new();
-    font_vector.extend_from_slice(font_slice);
-
-    resources.add_raw_font(key, font_vector, index);
+    resources.add_raw_font(key, bytes.flush_into_vec(), index);
 }
 
 #[no_mangle]
 pub extern "C" fn wr_resource_updates_delete_font(
     resources: &mut ResourceUpdates,
     key: WrFontKey
 ) {
     resources.delete_font(key);
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -1163,17 +1163,17 @@ WR_FUNC;
 WR_INLINE
 void wr_renderer_update(Renderer *aRenderer)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_add_blob_image(ResourceUpdates *aResources,
                                         WrImageKey aImageKey,
                                         const WrImageDescriptor *aDescriptor,
-                                        ByteSlice aBytes)
+                                        WrVecU8 *aBytes)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_add_external_image(ResourceUpdates *aResources,
                                             WrImageKey aImageKey,
                                             const WrImageDescriptor *aDescriptor,
                                             WrExternalImageId aExternalImageId,
                                             WrExternalImageBufferType aBufferType,
@@ -1188,24 +1188,23 @@ void wr_resource_updates_add_font_instan
                                            const FontInstanceOptions *aOptions,
                                            const FontInstancePlatformOptions *aPlatformOptions)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_add_image(ResourceUpdates *aResources,
                                    WrImageKey aImageKey,
                                    const WrImageDescriptor *aDescriptor,
-                                   ByteSlice aBytes)
+                                   WrVecU8 *aBytes)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_add_raw_font(ResourceUpdates *aResources,
                                       WrFontKey aKey,
-                                      uint8_t *aFontBuffer,
-                                      size_t aBufferSize,
+                                      WrVecU8 *aBytes,
                                       uint32_t aIndex)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_clear(ResourceUpdates *aResources)
 WR_FUNC;
 
 WR_INLINE
@@ -1239,33 +1238,33 @@ WR_INLINE
 void wr_resource_updates_serialize(ResourceUpdates *aResources,
                                    VecU8 *aInto)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_update_blob_image(ResourceUpdates *aResources,
                                            WrImageKey aImageKey,
                                            const WrImageDescriptor *aDescriptor,
-                                           ByteSlice aBytes)
+                                           WrVecU8 *aBytes)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_update_external_image(ResourceUpdates *aResources,
                                                WrImageKey aKey,
                                                const WrImageDescriptor *aDescriptor,
                                                WrExternalImageId aExternalImageId,
                                                WrExternalImageBufferType aImageType,
                                                uint8_t aChannelIndex)
 WR_FUNC;
 
 WR_INLINE
 void wr_resource_updates_update_image(ResourceUpdates *aResources,
                                       WrImageKey aKey,
                                       const WrImageDescriptor *aDescriptor,
-                                      ByteSlice aBytes)
+                                      WrVecU8 *aBytes)
 WR_FUNC;
 
 WR_INLINE
 void wr_scroll_layer_with_id(DocumentHandle *aDh,
                              WrPipelineId aPipelineId,
                              uint64_t aScrollId,
                              LayoutPoint aNewScrollOrigin)
 WR_FUNC;
@@ -1287,16 +1286,21 @@ WR_INLINE
 WrThreadPool *wr_thread_pool_new()
 WR_FUNC;
 
 WR_INLINE
 void wr_vec_u8_free(WrVecU8 aV)
 WR_FUNC;
 
 WR_INLINE
+void wr_vec_u8_push_bytes(WrVecU8 *aV,
+                          ByteSlice aBytes)
+WR_FUNC;
+
+WR_INLINE
 bool wr_window_new(WrWindowId aWindowId,
                    uint32_t aWindowWidth,
                    uint32_t aWindowHeight,
                    void *aGlContext,
                    WrThreadPool *aThreadPool,
                    DocumentHandle **aOutHandle,
                    Renderer **aOutRenderer,
                    uint32_t *aOutMaxTextureSize)
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -85,16 +85,17 @@ public:
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayButtonBoxShadowOuter() {
     MOZ_COUNT_DTOR(nsDisplayButtonBoxShadowOuter);
   }
 #endif
 
   virtual bool CreateWebRenderCommands(
     mozilla::wr::DisplayListBuilder& aBuilder,
+    mozilla::wr::IpcResourceUpdateQueue& aResources,
     const StackingContextHelper& aSc,
     nsTArray<WebRenderParentCommand>& aParentCommands,
     mozilla::layers::WebRenderLayerManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) override;
 
   virtual LayerState GetLayerState(
     nsDisplayListBuilder* aBuilder,
     LayerManager* aManager,
@@ -191,16 +192,17 @@ nsDisplayButtonBoxShadowOuter::BuildLaye
   const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayButtonBoxShadowOuter::CreateWebRenderCommands(
   mozilla::wr::DisplayListBuilder& aBuilder,
+  mozilla::wr::IpcResourceUpdateQueue& aResources,
   const StackingContextHelper& aSc,
   nsTArray<WebRenderParentCommand>& aParentCommands,
   mozilla::layers::WebRenderLayerManager* aManager,
   nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) !=
@@ -291,16 +293,17 @@ public:
                                          nsRegion *aInvalidRegion) const override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   NS_DISPLAY_DECL_NAME("ButtonBorderBackground", TYPE_BUTTON_BORDER_BACKGROUND)
 private:
   nsButtonFrameRenderer* mBFR;
   Maybe<nsCSSBorderRenderer> mBorderRenderer;
@@ -358,16 +361,17 @@ nsDisplayButtonBorder::BuildLayer(nsDisp
                                   LayerManager* aManager,
                                   const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayButtonBorder::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                               mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                const StackingContextHelper& aSc,
                                                nsTArray<WebRenderParentCommand>& aParentCommands,
                                                mozilla::layers::WebRenderLayerManager* aManager,
                                                nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -382,17 +386,17 @@ nsDisplayButtonBorder::CreateWebRenderCo
   nsRect buttonRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
   bool snap;
   nsRegion visible = GetBounds(aDisplayListBuilder, &snap);
   nsDisplayBoxShadowInner::CreateInsetBoxShadowWebRenderCommands(aBuilder,
                                                                  aSc,
                                                                  visible,
                                                                  mFrame,
                                                                  buttonRect);
-  mBorderRenderer->CreateWebRenderCommands(aBuilder, aSc);
+  mBorderRenderer->CreateWebRenderCommands(aBuilder, aResources, aSc);
 
   return true;
 }
 
 void
 nsDisplayButtonBorder::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                                  const nsDisplayItemGeometry* aGeometry,
                                                  nsRegion *aInvalidRegion) const
@@ -454,16 +458,17 @@ public:
                      gfxContext* aCtx) override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
    virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                         const StackingContextHelper& aSc,
                                         nsTArray<WebRenderParentCommand>& aParentCommands,
                                         mozilla::layers::WebRenderLayerManager* aManager,
                                         nsDisplayListBuilder* aDisplayListBuilder) override;
   NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND)
 private:
   nsButtonFrameRenderer* mBFR;
   Maybe<nsCSSBorderRenderer> mBorderRenderer;
@@ -540,29 +545,30 @@ nsDisplayButtonForeground::BuildLayer(ns
                                       LayerManager* aManager,
                                       const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayButtonForeground::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                    const StackingContextHelper& aSc,
                                                    nsTArray<WebRenderParentCommand>& aParentCommands,
                                                    mozilla::layers::WebRenderLayerManager* aManager,
                                                    nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
       return false;
     }
   }
 
-  mBorderRenderer->CreateWebRenderCommands(aBuilder, aSc);
+  mBorderRenderer->CreateWebRenderCommands(aBuilder, aResources, aSc);
   return true;
 }
 
 nsresult
 nsButtonFrameRenderer::DisplayButton(nsDisplayListBuilder* aBuilder,
                                      nsDisplayList* aBackground,
                                      nsDisplayList* aForeground)
 {
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -222,16 +222,17 @@ public:
     , mListStyleType(listStyleType)
   {
     MOZ_ASSERT(IsTextType());
   }
 
   void
   CreateWebRenderCommands(nsDisplayItem* aItem,
                           wr::DisplayListBuilder& aBuilder,
+                          wr::IpcResourceUpdateQueue& aResources,
                           const layers::StackingContextHelper& aSc,
                           nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                           mozilla::layers::WebRenderLayerManager* aManager,
                           nsDisplayListBuilder* aDisplayListBuilder);
 
   DrawResult
   Paint(gfxContext& aRenderingContext, nsPoint aPt,
         const nsRect& aDirtyRect, uint32_t aFlags,
@@ -271,32 +272,35 @@ public:
 
   bool
   IsImageContainerAvailable(layers::LayerManager* aManager, uint32_t aFlags);
 
 private:
   void
   CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
                                   wr::DisplayListBuilder& aBuilder,
+                                  wr::IpcResourceUpdateQueue& aResources,
                                   const layers::StackingContextHelper& aSc,
                                   nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                   mozilla::layers::WebRenderLayerManager* aManager,
                                   nsDisplayListBuilder* aDisplayListBuilder);
 
   void
   CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
                                  wr::DisplayListBuilder& aBuilder,
+                                 wr::IpcResourceUpdateQueue& aResources,
                                  const layers::StackingContextHelper& aSc,
                                  nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                  mozilla::layers::WebRenderLayerManager* aManager,
                                  nsDisplayListBuilder* aDisplayListBuilder);
 
   void
   CreateWebRenderCommandsForText(nsDisplayItem* aItem,
                                  wr::DisplayListBuilder& aBuilder,
+                                 wr::IpcResourceUpdateQueue& aResources,
                                  const layers::StackingContextHelper& aSc,
                                  mozilla::layers::WebRenderLayerManager* aManager,
                                  nsDisplayListBuilder* aDisplayListBuilder);
 
 private:
   // mImage and mDest are the properties for list-style-image.
   // mImage is the image content and mDest is the image position.
   RefPtr<imgIContainer> mImage;
@@ -319,30 +323,33 @@ private:
 
   // Store the type of list-style-type.
   int32_t mListStyleType;
 };
 
 void
 BulletRenderer::CreateWebRenderCommands(nsDisplayItem* aItem,
                                         wr::DisplayListBuilder& aBuilder,
+                                        wr::IpcResourceUpdateQueue& aResources,
                                         const layers::StackingContextHelper& aSc,
                                         nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                         mozilla::layers::WebRenderLayerManager* aManager,
                                         nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (IsImageType()) {
-    CreateWebRenderCommandsForImage(aItem, aBuilder, aSc, aParentCommands,
+    CreateWebRenderCommandsForImage(aItem, aBuilder, aResources,
+                                    aSc, aParentCommands,
                                     aManager, aDisplayListBuilder);
   } else if (IsPathType()) {
-    CreateWebRenderCommandsForPath(aItem, aBuilder, aSc, aParentCommands,
+    CreateWebRenderCommandsForPath(aItem, aBuilder, aResources,
+                                   aSc, aParentCommands,
                                    aManager, aDisplayListBuilder);
   } else {
     MOZ_ASSERT(IsTextType());
-    CreateWebRenderCommandsForText(aItem, aBuilder, aSc,
+    CreateWebRenderCommandsForText(aItem, aBuilder, aResources, aSc,
                                    aManager, aDisplayListBuilder);
   }
 }
 
 DrawResult
 BulletRenderer::Paint(gfxContext& aRenderingContext, nsPoint aPt,
                       const nsRect& aDirtyRect, uint32_t aFlags,
                       bool aDisableSubpixelAA, nsIFrame* aFrame)
@@ -444,16 +451,17 @@ BulletRenderer::IsImageContainerAvailabl
   MOZ_ASSERT(IsImageType());
 
   return mImage->IsImageContainerAvailable(aManager, aFlags);
 }
 
 void
 BulletRenderer::CreateWebRenderCommandsForImage(nsDisplayItem* aItem,
                                                 wr::DisplayListBuilder& aBuilder,
+                                                wr::IpcResourceUpdateQueue& aResources,
                                                 const layers::StackingContextHelper& aSc,
                                                 nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                                 mozilla::layers::WebRenderLayerManager* aManager,
                                                 nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(IsImageType());
 
   if (!mImage) {
@@ -484,31 +492,33 @@ BulletRenderer::CreateWebRenderCommandsF
                      dest,
                      wr::ImageRendering::Auto,
                      key.value());
 }
 
 void
 BulletRenderer::CreateWebRenderCommandsForPath(nsDisplayItem* aItem,
                                                wr::DisplayListBuilder& aBuilder,
+                                               wr::IpcResourceUpdateQueue& aResources,
                                                const layers::StackingContextHelper& aSc,
                                                nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                                mozilla::layers::WebRenderLayerManager* aManager,
                                                nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(IsPathType());
 
-  if (!aManager->PushItemAsImage(aItem, aBuilder, aSc, aDisplayListBuilder)) {
+  if (!aManager->PushItemAsImage(aItem, aBuilder, aResources, aSc, aDisplayListBuilder)) {
     NS_WARNING("Fail to create WebRender commands for Bullet path.");
   }
 }
 
 void
 BulletRenderer::CreateWebRenderCommandsForText(nsDisplayItem* aItem,
                                                wr::DisplayListBuilder& aBuilder,
+                                               wr::IpcResourceUpdateQueue& aResources,
                                                const layers::StackingContextHelper& aSc,
                                                mozilla::layers::WebRenderLayerManager* aManager,
                                                nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(IsTextType());
   MOZ_ASSERT(mFont);
   MOZ_ASSERT(!mGlyphs.IsEmpty());
 
@@ -550,16 +560,17 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aParameters) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue&,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState,
                        nsTArray<nsIFrame*> *aOutFrames) override {
@@ -654,32 +665,33 @@ nsDisplayBullet::BuildLayer(nsDisplayLis
     return nullptr;
   }
 
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayBullet::CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
+                                         wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          nsTArray<layers::WebRenderParentCommand>& aParentCommands,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
       return false;
     }
   }
 
   if (!mBulletRenderer)
     return false;
 
-  mBulletRenderer->CreateWebRenderCommands(this, aBuilder, aSc, aParentCommands,
+  mBulletRenderer->CreateWebRenderCommands(this, aBuilder, aResources, aSc, aParentCommands,
                                            aManager, aDisplayListBuilder);
   return true;
 }
 
 void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
                             gfxContext* aCtx)
 {
   uint32_t flags = imgIContainer::FLAG_NONE;
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -302,16 +302,17 @@ nsDisplayCanvasBackgroundColor::BuildLay
   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
                                                       aContainerParameters.mOffset.y, 0));
 
   return layer.forget();
 }
 
 bool
 nsDisplayCanvasBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                         const StackingContextHelper& aSc,
                                                         nsTArray<WebRenderParentCommand>& aParentCommands,
                                                         WebRenderLayerManager* aManager,
                                                         nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -154,16 +154,17 @@ public:
   {
     // We need to override so we don't consider border-radius.
     aOutFrames->AppendElement(mFrame);
   }
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
--- a/layout/generic/nsColumnSetFrame.cpp
+++ b/layout/generic/nsColumnSetFrame.cpp
@@ -39,16 +39,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override;
 
   NS_DISPLAY_DECL_NAME("ColumnRule", TYPE_COLUMN_RULE);
@@ -100,16 +101,17 @@ nsDisplayColumnRule::BuildLayer(nsDispla
                                 LayerManager* aManager,
                                 const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayColumnRule::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
                                              const StackingContextHelper& aSc,
                                              nsTArray<WebRenderParentCommand>& aParentCommands,
                                              mozilla::layers::WebRenderLayerManager* aManager,
                                              nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     RefPtr<gfxContext> screenRefCtx = gfxContext::CreateOrNull(
       gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget().get());
@@ -124,17 +126,17 @@ nsDisplayColumnRule::CreateWebRenderComm
     for (auto iter = mBorderRenderers.begin(); iter != mBorderRenderers.end(); iter++) {
       if (!iter->CanCreateWebRenderCommands()) {
         return false;
       }
     }
   }
 
   for (auto iter = mBorderRenderers.begin(); iter != mBorderRenderers.end(); iter++) {
-    iter->CreateWebRenderCommands(aBuilder, aSc);
+    iter->CreateWebRenderCommands(aBuilder, aResources, aSc);
   }
 
   return true;
 }
 
 /**
  * Tracking issues:
  *
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -120,16 +120,17 @@ public:
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override
   {
     return static_cast<nsHTMLCanvasFrame*>(mFrame)->
       BuildLayer(aBuilder, aManager, this, aContainerParameters);
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override
   {
     HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(mFrame->GetContent());
     switch(element->GetCurrentContextType()) {
       case CanvasContextType::Canvas2D:
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -1696,16 +1696,17 @@ nsDisplayImage::BuildLayer(nsDisplayList
   }
   layer->SetContainer(container);
   ConfigureLayer(layer, aParameters);
   return layer.forget();
 }
 
 bool
 nsDisplayImage::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                         const StackingContextHelper& aSc,
                                         nsTArray<WebRenderParentCommand>& aParentCommands,
                                         WebRenderLayerManager* aManager,
                                         nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (!CanOptimizeToImageLayer(aManager, aDisplayListBuilder)) {
     return false;
   }
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -455,16 +455,17 @@ public:
 
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   NS_DISPLAY_DECL_NAME("Image", TYPE_IMAGE)
 private:
   nsCOMPtr<imgIContainer> mImage;
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -1043,23 +1043,25 @@ nsDisplayPlugin::GetOpaqueRegion(nsDispl
     }
   }
 
   return result;
 }
 
 bool
 nsDisplayPlugin::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          nsTArray<WebRenderParentCommand>& aParentCommands,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayListBuilder* aDisplayListBuilder)
 {
   return static_cast<nsPluginFrame*>(mFrame)->CreateWebRenderCommands(this,
                                                                       aBuilder,
+                                                                      aResources,
                                                                       aSc,
                                                                       aManager,
                                                                       aDisplayListBuilder);
 }
 
 nsresult
 nsPluginFrame::PluginEventNotifier::Run() {
   nsCOMPtr<nsIObserverService> obsSvc =
@@ -1408,16 +1410,17 @@ nsPluginFrame::GetBounds(nsDisplayItem* 
   aRect.Round();
 
   return true;
 }
 
 bool
 nsPluginFrame::CreateWebRenderCommands(nsDisplayItem* aItem,
                                        mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder)
 {
   IntSize size;
   gfxRect r;
   if (!GetBounds(aItem, size, r)) {
     return true;
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -223,16 +223,17 @@ public:
   /**
    * WantsToHandleWheelEventAsDefaultAction() returns true if the plugin
    * may want to handle wheel events as default action.
    */
   bool WantsToHandleWheelEventAsDefaultAction() const;
 
   bool CreateWebRenderCommands(nsDisplayItem* aItem,
                                mozilla::wr::DisplayListBuilder& aBuilder,
+                               mozilla::wr::IpcResourceUpdateQueue& aResources,
                                const StackingContextHelper& aSc,
                                mozilla::layers::WebRenderLayerManager* aManager,
                                nsDisplayListBuilder* aDisplayListBuilder);
 protected:
   explicit nsPluginFrame(nsStyleContext* aContext);
   virtual ~nsPluginFrame();
 
   // NOTE:  This frame class does not inherit from |nsLeafFrame|, so
@@ -386,15 +387,16 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override
   {
     return static_cast<nsPluginFrame*>(mFrame)->GetLayerState(aBuilder,
                                                               aManager);
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 };
 
 #endif /* nsPluginFrame_h___ */
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4969,16 +4969,17 @@ public:
   }
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT)
 
@@ -5168,16 +5169,17 @@ nsDisplayText::Paint(nsDisplayListBuilde
 
   DrawTargetAutoDisableSubpixelAntialiasing disable(aCtx->GetDrawTarget(),
                                                     mDisableSubpixelAA);
   RenderToContext(aCtx, nullptr, aBuilder);
 }
 
 bool
 nsDisplayText::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -428,16 +428,17 @@ public:
   virtual ~nsDisplayVideo() {
     MOZ_COUNT_DTOR(nsDisplayVideo);
   }
 #endif
 
   NS_DISPLAY_DECL_NAME("Video", TYPE_VIDEO)
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const mozilla::layers::StackingContextHelper& aSc,
                                        nsTArray<mozilla::layers::WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override
   {
     nsRect area = Frame()->GetContentRectRelativeToSelf() + ToReferenceFrame();
     HTMLVideoElement* element = static_cast<HTMLVideoElement*>(Frame()->GetContent());
 
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -378,16 +378,17 @@ nsDisplayRemote::BuildLayer(nsDisplayLis
   if (layer && layer->AsContainerLayer()) {
     layer->AsContainerLayer()->SetEventRegionsOverride(mEventRegionsOverride);
   }
   return layer.forget();
 }
 
 bool
 nsDisplayRemote::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          nsTArray<WebRenderParentCommand>& aParentCommands,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayListBuilder* aDisplayListBuilder)
 {
   MOZ_ASSERT(aManager->IsLayersFreeTransaction());
 
   mOffset = mozilla::layout::GetContentRectLayerOffset(mFrame, aDisplayListBuilder);
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -157,16 +157,17 @@ public:
                                    const ContainerLayerParameters& aParameters) override
   { return mozilla::LAYER_ACTIVE_FORCE; }
 
   virtual already_AddRefed<Layer>
   BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
              const ContainerLayerParameters& aContainerParameters) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
                                 mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
 
   uint64_t GetRemoteLayersId() const;
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -3606,16 +3606,17 @@ nsCSSBorderRenderer::CanCreateWebRenderC
     }
   }
 
   return true;
 }
 
 void
 nsCSSBorderRenderer::CreateWebRenderCommands(wr::DisplayListBuilder& aBuilder,
+                                             wr::IpcResourceUpdateQueue& aResources,
                                              const layers::StackingContextHelper& aSc)
 {
   LayoutDeviceRect outerRect = LayoutDeviceRect::FromUnknownRect(mOuterRect);
   wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(outerRect);
   wr::BorderSide side[4];
   NS_FOR_CSS_SIDES(i) {
     side[i] = wr::ToBorderSide(ToDeviceColor(mBorderColors[i]), mBorderStyles[i]);
   }
--- a/layout/painting/nsCSSRenderingBorders.h
+++ b/layout/painting/nsCSSRenderingBorders.h
@@ -103,16 +103,17 @@ public:
                       nsBorderColors* const* aCompositeColors,
                       nscolor aBackgroundColor);
 
   // draw the entire border
   void DrawBorders();
 
   bool CanCreateWebRenderCommands();
   void CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                               mozilla::wr::IpcResourceUpdateQueue& aResources,
                                const mozilla::layers::StackingContextHelper& aSc);
 
   // utility function used for background painting as well as borders
   static void ComputeInnerRadii(const RectCornerRadii& aRadii,
                                 const Float* aBorderSizes,
                                 RectCornerRadii* aInnerRadiiRet);
 
   // Given aRadii as the border radii for a rectangle, compute the
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2923,16 +2923,17 @@ nsDisplaySolidColor::WriteDebugInfo(std:
           << (int)NS_GET_R(mColor) << ","
           << (int)NS_GET_G(mColor) << ","
           << (int)NS_GET_B(mColor) << ","
           << (int)NS_GET_A(mColor) << ")";
 }
 
 bool
 nsDisplaySolidColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                             mozilla::wr::IpcResourceUpdateQueue& aResources,
                                              const StackingContextHelper& aSc,
                                              nsTArray<WebRenderParentCommand>& aParentCommands,
                                              mozilla::layers::WebRenderLayerManager* aManager,
                                              nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -2980,16 +2981,17 @@ nsDisplaySolidColorRegion::WriteDebugInf
           << int(mColor.r * 255) << ","
           << int(mColor.g * 255) << ","
           << int(mColor.b * 255) << ","
           << mColor.a << ")";
 }
 
 bool
 nsDisplaySolidColorRegion::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                   mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                    const StackingContextHelper& aSc,
                                                    nsTArray<WebRenderParentCommand>& aParentCommands,
                                                    mozilla::layers::WebRenderLayerManager* aManager,
                                                    nsDisplayListBuilder* aDisplayListBuilder)
 {
   for (auto iter = mRegion.RectIter(); !iter.Done(); iter.Next()) {
     nsRect rect = iter.Get();
     LayoutDeviceRect layerRects = LayoutDeviceRect::FromAppUnits(
@@ -3615,16 +3617,17 @@ nsDisplayBackgroundImage::CanBuildWebRen
                                                                          *StyleFrame()->PresContext(),
                                                                          StyleFrame(),
                                                                          mBackgroundStyle,
                                                                          mLayer);
 }
 
 bool
 nsDisplayBackgroundImage::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                   const StackingContextHelper& aSc,
                                                   nsTArray<WebRenderParentCommand>& aParentCommands,
                                                   WebRenderLayerManager* aManager,
                                                   nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -4246,16 +4249,17 @@ nsDisplayBackgroundColor::BuildLayer(nsD
   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
                                                       aContainerParameters.mOffset.y, 0));
 
   return layer.forget();
 }
 
 bool
 nsDisplayBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                  mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                   const StackingContextHelper& aSc,
                                                   nsTArray<WebRenderParentCommand>& aParentCommands,
                                                   mozilla::layers::WebRenderLayerManager* aManager,
                                                   nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -4466,29 +4470,30 @@ nsDisplayOutline::BuildLayer(nsDisplayLi
                              LayerManager* aManager,
                              const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayOutline::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                          mozilla::wr::IpcResourceUpdateQueue& aResources,
                                           const StackingContextHelper& aSc,
                                           nsTArray<WebRenderParentCommand>& aParentCommands,
                                           mozilla::layers::WebRenderLayerManager* aManager,
                                           nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
       return false;
     }
   }
 
-  mBorderRenderer->CreateWebRenderCommands(aBuilder, aSc);
+  mBorderRenderer->CreateWebRenderCommands(aBuilder, aResources, aSc);
   return true;
 }
 
 bool
 nsDisplayOutline::IsInvisibleInRect(const nsRect& aRect) const
 {
   const nsStyleOutline* outline = mFrame->StyleOutline();
   nsRect borderBox(ToReferenceFrame(), mFrame->GetSize());
@@ -4749,16 +4754,17 @@ nsDisplayCaret::Paint(nsDisplayListBuild
                       gfxContext* aCtx) {
   // Note: Because we exist, we know that the caret is visible, so we don't
   // need to check for the caret's visibility.
   mCaret->PaintCaret(*aCtx->GetDrawTarget(), mFrame, ToReferenceFrame());
 }
 
 bool
 nsDisplayCaret::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                         const StackingContextHelper& aSc,
                                         nsTArray<WebRenderParentCommand>& aParentCommands,
                                         mozilla::layers::WebRenderLayerManager* aManager,
                                         nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -5014,33 +5020,34 @@ nsDisplayBorder::BuildLayer(nsDisplayLis
     layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
                                                         aContainerParameters.mOffset.y, 0));
     return layer.forget();
   }
 }
 
 bool
 nsDisplayBorder::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          nsTArray<WebRenderParentCommand>& aParentCommands,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
       return false;
     }
   }
 
   if (mBorderImageRenderer) {
     CreateBorderImageWebRenderCommands(aBuilder, aSc, aParentCommands,
                                        aManager, aDisplayListBuilder);
   } else if (mBorderRenderer) {
-    mBorderRenderer->CreateWebRenderCommands(aBuilder, aSc);
+    mBorderRenderer->CreateWebRenderCommands(aBuilder, aResources, aSc);
   }
 
   return true;
 };
 
 void
 nsDisplayBorder::CreateBorderImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                                     const StackingContextHelper& aSc,
@@ -5381,16 +5388,17 @@ nsDisplayBoxShadowOuter::CanBuildWebRend
     }
   }
 
   return true;
 }
 
 bool
 nsDisplayBoxShadowOuter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                  const StackingContextHelper& aSc,
                                                  nsTArray<WebRenderParentCommand>& aParentCommands,
                                                  mozilla::layers::WebRenderLayerManager* aManager,
                                                  nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -5626,16 +5634,17 @@ nsDisplayBoxShadowInner::CreateInsetBoxS
                              wr::BoxShadowClipMode::Inset
                              );
     }
   }
 }
 
 bool
 nsDisplayBoxShadowInner::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                  const StackingContextHelper& aSc,
                                                  nsTArray<WebRenderParentCommand>& aParentCommands,
                                                  mozilla::layers::WebRenderLayerManager* aManager,
                                                  nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -5891,31 +5900,33 @@ void
 nsDisplayWrapList::SetReferenceFrame(const nsIFrame* aFrame)
 {
   mReferenceFrame = aFrame;
   mToReferenceFrame = mFrame->GetOffsetToCrossDoc(mReferenceFrame);
 }
 
 bool
 nsDisplayWrapList::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                           mozilla::wr::IpcResourceUpdateQueue& aResources,
                                            const StackingContextHelper& aSc,
                                            nsTArray<WebRenderParentCommand>& aParentCommands,
                                            mozilla::layers::WebRenderLayerManager* aManager,
                                            nsDisplayListBuilder* aDisplayListBuilder)
 {
   // If this function is called in layers mode that means we created a
   // WebRenderDisplayItemLayer for a display item that is a subclass of
   // nsDisplayWrapList, but we didn't actually implement the overridden
   // CreateWebRenderCommandsFromDisplayList on it. That doesn't seem correct.
   MOZ_ASSERT(aManager->IsLayersFreeTransaction());
 
   aManager->CreateWebRenderCommandsFromDisplayList(GetChildren(),
                                                    aDisplayListBuilder,
                                                    aSc,
-                                                   aBuilder);
+                                                   aBuilder,
+                                                   aResources);
   return true;
 }
 
 static nsresult
 WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                 nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
   if (!aList->GetTop())
     return NS_OK;
@@ -6224,16 +6235,17 @@ nsDisplayOpacity::ComputeVisibility(nsDi
 void
 nsDisplayOpacity::WriteDebugInfo(std::stringstream& aStream)
 {
   aStream << " (opacity " << mOpacity << ")";
 }
 
 bool
 nsDisplayOpacity::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                          mozilla::wr::IpcResourceUpdateQueue& aResources,
                                           const StackingContextHelper& aSc,
                                           nsTArray<WebRenderParentCommand>& aParentCommands,
                                           mozilla::layers::WebRenderLayerManager* aManager,
                                           nsDisplayListBuilder* aDisplayListBuilder)
 {
   float* opacityForSC = &mOpacity;
 
   RefPtr<WebRenderAnimationData> animationData = aManager->CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
@@ -6266,17 +6278,18 @@ nsDisplayOpacity::CreateWebRenderCommand
                            opacityForSC,
                            nullptr,
                            nullptr,
                            filters);
 
   aManager->CreateWebRenderCommandsFromDisplayList(&mList,
                                                    aDisplayListBuilder,
                                                    sc,
-                                                   aBuilder);
+                                                   aBuilder,
+                                                   aResources);
   return true;
 }
 
 nsDisplayBlendMode::nsDisplayBlendMode(nsDisplayListBuilder* aBuilder,
                                              nsIFrame* aFrame, nsDisplayList* aList,
                                              uint8_t aBlendMode,
                                              const ActiveScrolledRoot* aActiveScrolledRoot,
                                              uint32_t aIndex)
@@ -6306,27 +6319,28 @@ nsDisplayBlendMode::GetLayerState(nsDisp
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters)
 {
   return LAYER_ACTIVE;
 }
 
 bool
 nsDisplayBlendMode::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                            mozilla::wr::IpcResourceUpdateQueue& aResources,
                                             const StackingContextHelper& aSc,
                                             nsTArray<WebRenderParentCommand>& aParentCommands,
                                             mozilla::layers::WebRenderLayerManager* aManager,
                                             nsDisplayListBuilder* aDisplayListBuilder)
 {
   nsTArray<mozilla::wr::WrFilterOp> filters;
   StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
                            &mList, nullptr, 0, nullptr, nullptr, nullptr,
                            filters, nsCSSRendering::GetGFXBlendMode(mBlendMode));
 
-  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder,aResources, sc, aParentCommands,
                                                     aManager, aDisplayListBuilder);
 }
 
 // nsDisplayBlendMode uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayBlendMode::BuildLayer(nsDisplayListBuilder* aBuilder,
                                   LayerManager* aManager,
                                   const ContainerLayerParameters& aContainerParameters) {
@@ -6437,25 +6451,26 @@ nsDisplayBlendContainer::GetLayerState(n
                                        LayerManager* aManager,
                                        const ContainerLayerParameters& aParameters)
 {
   return RequiredLayerStateForChildren(aBuilder, aManager, aParameters, mList, GetAnimatedGeometryRoot());
 }
 
 bool
 nsDisplayBlendContainer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
                                                  const StackingContextHelper& aSc,
                                                  nsTArray<WebRenderParentCommand>& aParentCommands,
                                                  mozilla::layers::WebRenderLayerManager* aManager,
                                                  nsDisplayListBuilder* aDisplayListBuilder)
 {
   StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
                            &mList, nullptr, 0, nullptr, nullptr);
 
-  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+  return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aParentCommands,
                                                     aManager, aDisplayListBuilder);
 }
 
 nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
                                      nsIFrame* aFrame, nsDisplayList* aList,
                                      const ActiveScrolledRoot* aActiveScrolledRoot,
                                      uint32_t aFlags, ViewID aScrollTarget,
                                      const ScrollThumbData& aThumbData,
@@ -6530,39 +6545,40 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayL
   if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
     mFrame->PresContext()->SetNotifySubDocInvalidationData(layer);
   }
   return layer.forget();
 }
 
 bool
 nsDisplayOwnLayer::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                           mozilla::wr::IpcResourceUpdateQueue& aResources,
                                            const StackingContextHelper& aSc,
                                            nsTArray<WebRenderParentCommand>& aParentCommands,
                                            WebRenderLayerManager* aManager,
                                            nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (!aManager->AsyncPanZoomEnabled() ||
       mThumbData.mDirection == ScrollDirection::NONE) {
-    return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aSc,
+    return nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, aSc,
         aParentCommands, aManager, aDisplayListBuilder);
   }
 
   // APZ is enabled and this is a scroll thumb, so we need to create and
   // set an animation id. That way APZ can move this scrollthumb around as
   // needed.
   RefPtr<WebRenderAnimationData> animationData = aManager->CreateOrRecycleWebRenderUserData<WebRenderAnimationData>(this);
   AnimationInfo& animationInfo = animationData->GetAnimationInfo();
   animationInfo.EnsureAnimationsId();
   mWrAnimationId = animationInfo.GetCompositorAnimationsId();
 
   StackingContextHelper sc(aSc, aBuilder, aDisplayListBuilder, this,
                            &mList, nullptr, mWrAnimationId, nullptr, nullptr);
 
-  nsDisplayWrapList::CreateWebRenderCommands(aBuilder, sc,
+  nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc,
       aParentCommands, aManager, aDisplayListBuilder);
   return true;
 }
 
 bool
 nsDisplayOwnLayer::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
                                     mozilla::layers::WebRenderLayerScrollData* aLayerData)
 {
@@ -7870,16 +7886,17 @@ nsDisplayTransform::ShouldBuildLayerEven
   // The visible rect of a Preserves-3D frame is just an intermediate
   // result.  It should always build a layer to make sure it is
   // rendering correctly.
   return MayBeAnimated(aBuilder) || mFrame->Combines3DTransformWithAncestors();
 }
 
 bool
 nsDisplayTransform::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                            mozilla::wr::IpcResourceUpdateQueue& aResources,
                                             const StackingContextHelper& aSc,
                                             nsTArray<WebRenderParentCommand>& aParentCommands,
                                             WebRenderLayerManager* aManager,
                                             nsDisplayListBuilder* aDisplayListBuilder)
 {
   Matrix4x4 newTransformMatrix = GetTransformForRendering();
   gfx::Matrix4x4* transformForSC = &newTransformMatrix;
   if (newTransformMatrix.IsIdentity()) {
@@ -7947,17 +7964,17 @@ nsDisplayTransform::CreateWebRenderComma
     aManager->WrBridge()->AddWebRenderParentCommand(anim);
 
     // Since we passed a nullptr transformForSC to the StackingContextHelper,
     // we now set up the correct inherited scale for the stacking context.
     newTransformMatrix.PostScale(scale.width, scale.height, 1.0f);
     sc.SetInheritedScale(newTransformMatrix.As2D().ScaleFactors(true));
 
   }
-  return mStoredList.CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+  return mStoredList.CreateWebRenderCommands(aBuilder, aResources, sc, aParentCommands,
                                              aManager, aDisplayListBuilder);
 }
 
 bool
 nsDisplayTransform::UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
                                      mozilla::layers::WebRenderLayerScrollData* aLayerData)
 {
   if (aLayerData) {
@@ -8503,16 +8520,17 @@ nsDisplayPerspective::GetLayerState(nsDi
                                     LayerManager* aManager,
                                     const ContainerLayerParameters& aParameters)
 {
   return LAYER_ACTIVE_FORCE;
 }
 
 bool
 nsDisplayPerspective::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                              mozilla::wr::IpcResourceUpdateQueue& aResources,
                                               const StackingContextHelper& aSc,
                                               nsTArray<WebRenderParentCommand>& aParentCommands,
                                               WebRenderLayerManager* aManager,
                                               nsDisplayListBuilder* aDisplayListBuilder)
 {
   float appUnitsPerPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   Matrix4x4 perspectiveMatrix;
   DebugOnly<bool> hasPerspective =
@@ -8552,17 +8570,17 @@ nsDisplayPerspective::CreateWebRenderCom
                            mList.GetChildren(),
                            nullptr,
                            0,
                            nullptr,
                            &transformForSC,
                            &perspectiveMatrix,
                            filters);
 
-  return mList.CreateWebRenderCommands(aBuilder, sc, aParentCommands,
+  return mList.CreateWebRenderCommands(aBuilder, aResources, sc, aParentCommands,
                                        aManager, aDisplayListBuilder);
 }
 
 int32_t
 nsDisplayPerspective::ZIndex() const
 {
   return ZIndexForFrame(mTransformFrame);
 }
@@ -9016,38 +9034,40 @@ nsDisplayMask::PaintAsLayer(nsDisplayLis
 
   context->PopClip();
 
   nsDisplayMaskGeometry::UpdateDrawResult(this, imgParams.result);
 }
 
 bool
 nsDisplayMask::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder)
 {
   bool snap;
   float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
   nsRect displayBound = GetBounds(aDisplayListBuilder, &snap);
   LayerRect bounds = ViewAs<LayerPixel>(LayoutDeviceRect::FromAppUnits(displayBound, appUnitsPerDevPixel),
                                         PixelCastJustification::WebRenderHasUnitResolution);
 
-  Maybe<wr::WrImageMask> mask = aManager->BuildWrMaskImage(this, aBuilder, aSc, aDisplayListBuilder, bounds);
+  Maybe<wr::WrImageMask> mask = aManager->BuildWrMaskImage(this, aBuilder, aResources,
+                                                           aSc, aDisplayListBuilder, bounds);
   if (mask) {
     wr::WrClipId clipId = aBuilder.DefineClip(
         aSc.ToRelativeLayoutRect(bounds), nullptr, mask.ptr());
     // Don't record this clip push in aBuilder's internal clip stack, because
     // otherwise any nested ScrollingLayersHelper instances that are created
     // will get confused about which clips are pushed.
     aBuilder.PushClip(clipId, /*aRecordInStack*/ false);
   }
 
-  nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aSc, aParentCommands, aManager, aDisplayListBuilder);
+  nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, aSc, aParentCommands, aManager, aDisplayListBuilder);
 
   if (mask) {
     aBuilder.PopClip(/*aRecordInStack*/ false);
   }
 
   return true;
 }
 
@@ -9241,16 +9261,17 @@ nsDisplayFilter::PaintAsLayer(nsDisplayL
                                                   aManager,
                                                   mHandleOpacity, imgParams);
   nsSVGIntegrationUtils::PaintFilter(params);
   nsDisplayFilterGeometry::UpdateDrawResult(this, imgParams.result);
 }
 
 bool
 nsDisplayFilter::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          nsTArray<WebRenderParentCommand>& aParentCommands,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -9273,17 +9294,17 @@ nsDisplayFilter::CreateWebRenderCommands
                            &mList,
                            nullptr,
                            0,
                            nullptr,
                            nullptr,
                            nullptr,
                            wrFilters);
 
-  nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, sc, aParentCommands, aManager, aDisplayListBuilder);
+  nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, sc, aParentCommands, aManager, aDisplayListBuilder);
   return true;
 }
 
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayFilter::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2050,16 +2050,17 @@ public:
    * should be false to prevent doing GetLayerState again. For
    * layers-free mode, we should check if the layer state is
    * active first and have an early return if the layer state is
    * not active.
    *
    * @return true if successfully creating webrender commands.
    */
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) { return false; }
 
   /**
    * Updates the provided aLayerData with any APZ-relevant scroll data
    * that is specific to this display item. This is stuff that would normally
@@ -3018,16 +3019,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
 protected:
   RefPtr<nsCaret> mCaret;
   nsRect mBounds;
@@ -3052,16 +3054,17 @@ public:
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
 
   NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
@@ -3180,16 +3183,17 @@ public:
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
 
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
 
 private:
@@ -3232,16 +3236,17 @@ public:
     if (mColor == geometry->mColor) {
       aInvalidRegion->Xor(geometry->mRegion, mRegion);
     } else {
       aInvalidRegion->Or(geometry->mRegion.GetBounds(), mRegion.GetBounds());
     }
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   NS_DISPLAY_DECL_NAME("SolidColorRegion", TYPE_SOLID_COLOR_REGION)
 
 protected:
@@ -3316,16 +3321,17 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                  nsRegion* aVisibleRegion) override;
@@ -3552,16 +3558,17 @@ public:
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap) const override;
   virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder* aBuilder) const override;
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
@@ -3722,16 +3729,17 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
 
   bool CanBuildWebRenderDisplayItems();
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   nsRect GetBoundsInternal();
 
 private:
   nsRegion mVisibleRegion;
@@ -3787,16 +3795,17 @@ public:
                                                     const nsRect aBorderRect);
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
 private:
   nsRegion mVisibleRegion;
 };
@@ -3818,16 +3827,17 @@ public:
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool IsInvisibleInRect(const nsRect& aRect) const override;
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) const override;
   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
   NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
@@ -4134,16 +4144,17 @@ public:
    */
   virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
                                            nsDisplayItem* aItem) {
     NS_NOTREACHED("We never returned nullptr for GetUnderlyingFrame!");
     return nullptr;
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
 protected:
   nsDisplayWrapList() = delete;
 
@@ -4253,16 +4264,17 @@ public:
   virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
   static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
   virtual void WriteDebugInfo(std::stringstream& aStream) override;
 
   bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
 private:
   float mOpacity;
   bool mForEventsAndPluginsOnly;
@@ -4298,16 +4310,17 @@ public:
   }
   virtual uint32_t GetPerFrameKey() const override {
     return (mIndex << TYPE_BITS) | nsDisplayItem::GetPerFrameKey();
   }
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                               mozilla::wr::IpcResourceUpdateQueue& aResources,
                                const StackingContextHelper& aSc,
                                nsTArray<WebRenderParentCommand>& aParentCommands,
                                mozilla::layers::WebRenderLayerManager* aManager,
                                nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                  nsRegion* aVisibleRegion) override;
 
   virtual bool CanMerge(const nsDisplayItem* aItem) const override;
@@ -4348,16 +4361,17 @@ public:
 
     virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                                LayerManager* aManager,
                                                const ContainerLayerParameters& aContainerParameters) override;
     virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      const ContainerLayerParameters& aParameters) override;
     bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                 mozilla::wr::IpcResourceUpdateQueue& aResources,
                                  const StackingContextHelper& aSc,
                                  nsTArray<WebRenderParentCommand>& aParentCommands,
                                  mozilla::layers::WebRenderLayerManager* aManager,
                                  nsDisplayListBuilder* aDisplayListBuilder) override;
 
     virtual bool CanMerge(const nsDisplayItem* aItem) const override
     {
       // Items for the same content element should be merged into a single
@@ -4435,16 +4449,17 @@ public:
     MOZ_COUNT_CTOR(nsDisplayOwnLayer);
   }
 
   virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
                                 mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
@@ -4875,16 +4890,17 @@ public:
   bool PaintMask(nsDisplayListBuilder* aBuilder, gfxContext* aMaskContext);
 
   const nsTArray<nsRect>& GetDestRects()
   {
     return mDestRects;
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 private:
   // According to mask property and the capability of aManager, determine
   // whether paint mask onto a dedicate mask layer.
   bool ShouldPaintOnMaskLayer(LayerManager* aManager);
@@ -4953,16 +4969,17 @@ public:
   void PrintEffects(nsACString& aTo);
 #endif
 
   void PaintAsLayer(nsDisplayListBuilder* aBuilder,
                     gfxContext* aCtx,
                     LayerManager* aManager);
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
 private:
   // relative to mFrame
   nsRect mEffectsBounds;
@@ -5089,16 +5106,17 @@ public:
   virtual mozilla::Maybe<nscolor> IsUniform(nsDisplayListBuilder *aBuilder) const override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData,
                                 mozilla::layers::WebRenderLayerScrollData* aLayerData) override;
   virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override;
   virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
@@ -5423,16 +5441,17 @@ public:
   {
     return mList.IsUniform(aBuilder);
   }
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                               mozilla::wr::IpcResourceUpdateQueue& aResources,
                                const StackingContextHelper& aSc,
                                nsTArray<WebRenderParentCommand>& aParentCommands,
                                mozilla::layers::WebRenderLayerManager* aManager,
                                nsDisplayListBuilder* aDisplayListBuilder) override;
 
   virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) const override
   {
     if (!mList.GetChildren()->GetTop()) {
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -1270,16 +1270,17 @@ public:
 #endif
 
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      gfxContext* aCtx) override;
   virtual already_AddRefed<layers::Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                                      LayerManager* aManager,
                                                      const ContainerLayerParameters& aContainerParameters) override;
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
   NS_DISPLAY_DECL_NAME("TableBorderCollapse", TYPE_TABLE_BORDER_COLLAPSE)
@@ -1309,16 +1310,17 @@ nsDisplayTableBorderCollapse::BuildLayer
                                          LayerManager* aManager,
                                          const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayTableBorderCollapse::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                                      wr::IpcResourceUpdateQueue& aResources,
                                                       const StackingContextHelper& aSc,
                                                       nsTArray<WebRenderParentCommand>& aParentCommands,
                                                       mozilla::layers::WebRenderLayerManager* aManager,
                                                       nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
--- a/layout/xul/nsImageBoxFrame.cpp
+++ b/layout/xul/nsImageBoxFrame.cpp
@@ -413,16 +413,17 @@ nsImageBoxFrame::PaintImage(gfxContext& 
            dest, dirty,
            svgContext, aFlags,
            anchorPoint.ptrOr(nullptr),
            hasSubRect ? &mSubRect : nullptr);
 }
 
 DrawResult
 nsImageBoxFrame::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                         mozilla::wr::IpcResourceUpdateQueue& aResources,
                                          const StackingContextHelper& aSc,
                                          mozilla::layers::WebRenderLayerManager* aManager,
                                          nsDisplayItem* aItem,
                                          nsPoint aPt,
                                          uint32_t aFlags)
 {
   DrawResult result;
   Maybe<nsPoint> anchorPoint;
@@ -545,16 +546,17 @@ nsDisplayXULImage::BuildLayer(nsDisplayL
                            LayerManager* aManager,
                            const ContainerLayerParameters& aContainerParameters)
 {
   return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
 }
 
 bool
 nsDisplayXULImage::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                           mozilla::wr::IpcResourceUpdateQueue& aResources,
                                            const StackingContextHelper& aSc,
                                            nsTArray<WebRenderParentCommand>& aParentCommands,
                                            mozilla::layers::WebRenderLayerManager* aManager,
                                            nsDisplayListBuilder* aDisplayListBuilder)
 {
   if (aManager->IsLayersFreeTransaction()) {
     ContainerLayerParameters parameter;
     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
@@ -566,17 +568,17 @@ nsDisplayXULImage::CreateWebRenderComman
   if (aDisplayListBuilder->ShouldSyncDecodeImages()) {
     flags |= imgIContainer::FLAG_SYNC_DECODE;
   }
   if (aDisplayListBuilder->IsPaintingToWindow()) {
     flags |= imgIContainer::FLAG_HIGH_QUALITY_SCALING;
   }
 
   DrawResult result = static_cast<nsImageBoxFrame*>(mFrame)->
-    CreateWebRenderCommands(aBuilder, aSc, aManager, this, ToReferenceFrame(), flags);
+    CreateWebRenderCommands(aBuilder, aResources, aSc, aManager, this, ToReferenceFrame(), flags);
 
   nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result);
   return true;
 }
 
 nsDisplayItemGeometry*
 nsDisplayXULImage::AllocateGeometry(nsDisplayListBuilder* aBuilder)
 {
--- a/layout/xul/nsImageBoxFrame.h
+++ b/layout/xul/nsImageBoxFrame.h
@@ -95,16 +95,17 @@ public:
                                                                Maybe<nsPoint>& aAnchorPoint,
                                                                nsRect& aDest);
 
   DrawResult PaintImage(gfxContext& aRenderingContext,
                         const nsRect& aDirtyRect,
                         nsPoint aPt, uint32_t aFlags);
 
   DrawResult CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                     mozilla::wr::IpcResourceUpdateQueue& aResources,
                                      const mozilla::layers::StackingContextHelper& aSc,
                                      mozilla::layers::WebRenderLayerManager* aManager,
                                      nsDisplayItem* aItem,
                                      nsPoint aPt,
                                      uint32_t aFlags);
 
   bool CanOptimizeToImageLayer();
 
@@ -176,16 +177,17 @@ public:
                                    LayerManager* aManager,
                                    const ContainerLayerParameters& aParameters) override;
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) override;
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
+                                       mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        nsTArray<WebRenderParentCommand>& aParentCommands,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
 
   NS_DISPLAY_DECL_NAME("XULImage", TYPE_XUL_IMAGE)
 };
 
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -452,19 +452,21 @@ public:
   already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor() override;
   virtual void PrepareWindowEffects() override;
   virtual void CleanupWindowEffects() override;
 
   virtual void AddWindowOverlayWebRenderCommands(mozilla::layers::WebRenderBridgeChild* aWrBridge,
-                                                  mozilla::wr::DisplayListBuilder& aBuilder) override;
+                                                 mozilla::wr::DisplayListBuilder& aBuilder,
+                                                 mozilla::wr::IpcResourceUpdateQueue& aResourceUpdates) override;
 
-  virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge) override;
+  virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge,
+                                             mozilla::wr::IpcResourceUpdateQueue& aResources) override;
 
   virtual bool PreRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual void PostRender(mozilla::widget::WidgetRenderingContext* aContext) override;
   virtual void DrawWindowOverlay(mozilla::widget::WidgetRenderingContext* aManager,
                                  LayoutDeviceIntRect aRect) override;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -64,16 +64,17 @@
 #include "HeapCopyOfStackArray.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/GLManager.h"
 #include "mozilla/layers/CompositorOGL.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/BasicCompositor.h"
 #include "mozilla/layers/InputAPZContext.h"
+#include "mozilla/layers/IpcResourceUpdateQueue.h"
 #include "mozilla/layers/WebRenderBridgeChild.h"
 #include "mozilla/webrender/WebRenderAPI.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "gfxUtils.h"
 #include "gfxPrefs.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/BorrowedContext.h"
 #include "mozilla/gfx/MacIOSurface.h"
@@ -2074,17 +2075,18 @@ nsChildView::CleanupWindowEffects()
 {
   mResizerImage = nullptr;
   mCornerMaskImage = nullptr;
   mTitlebarImage = nullptr;
 }
 
 void
 nsChildView::AddWindowOverlayWebRenderCommands(layers::WebRenderBridgeChild* aWrBridge,
-                                               wr::DisplayListBuilder& aBuilder)
+                                               wr::DisplayListBuilder& aBuilder,
+                                               wr::IpcResourceUpdateQueue& aResources)
 {
   PrepareWindowEffects();
 
   bool needUpdate = mUpdatedTitlebarRegion.Intersects(mTitlebarRect);
   mUpdatedTitlebarRegion.SetEmpty();
 
   if (mTitlebarCGContext) {
     gfx::IntSize size(CGBitmapContextGetWidth(mTitlebarCGContext),
@@ -2095,46 +2097,46 @@ nsChildView::AddWindowOverlayWebRenderCo
     Range<uint8_t> buffer(
       static_cast<uint8_t *>(CGBitmapContextGetData(mTitlebarCGContext)),
       titlebarCGContextDataLength
     );
 
     if (mTitlebarImageKey &&
         mTitlebarImageSize != size) {
       // Delete wr::ImageKey. wr::ImageKey does not support size change.
-      CleanupWebRenderWindowOverlay(aWrBridge);
+      // TODO: that's not true anymore! (size change is now supported).
+      CleanupWebRenderWindowOverlay(aWrBridge, aResources);
       MOZ_ASSERT(mTitlebarImageKey.isNothing());
     }
 
     if (!mTitlebarImageKey) {
       mTitlebarImageKey = Some(aWrBridge->GetNextImageKey());
       wr::ImageDescriptor descriptor(size, stride, format);
-      aBuilder.Resources().AddImage(*mTitlebarImageKey, descriptor, buffer);
+      aResources.AddImage(*mTitlebarImageKey, descriptor, buffer);
       mTitlebarImageSize = size;
       needUpdate = false;
     }
 
     if (needUpdate) {
       wr::ImageDescriptor descriptor(size, stride, format);
-      aBuilder.Resources().UpdateImageBuffer(*mTitlebarImageKey, descriptor, buffer);
+      aResources.UpdateImageBuffer(*mTitlebarImageKey, descriptor, buffer);
     }
 
     wr::LayoutRect rect = wr::ToLayoutRect(mTitlebarRect);
     aBuilder.PushImage(wr::LayoutRect{ rect.origin, { float(size.width), float(size.height) } },
                        rect, wr::ImageRendering::Auto, *mTitlebarImageKey);
   }
 }
 
 void
-nsChildView::CleanupWebRenderWindowOverlay(layers::WebRenderBridgeChild* aWrBridge)
+nsChildView::CleanupWebRenderWindowOverlay(layers::WebRenderBridgeChild* aWrBridge,
+                                           wr::IpcResourceUpdateQueue& aResources)
 {
   if (mTitlebarImageKey) {
-    wr::ResourceUpdateQueue resources;
-    resources.DeleteImage(*mTitlebarImageKey);
-    aWrBridge->UpdateResources(resources);
+    aResources.DeleteImage(*mTitlebarImageKey);
     mTitlebarImageKey = Nothing();
   }
 }
 
 bool
 nsChildView::PreRender(WidgetRenderingContext* aContext)
 {
   UniquePtr<GLManager> manager(GLManager::CreateGLManager(aContext->mLayerManager));
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -71,16 +71,17 @@ class SourceSurface;
 namespace widget {
 class TextEventDispatcher;
 class TextEventDispatcherListener;
 class CompositorWidget;
 class CompositorWidgetInitData;
 } // namespace widget
 namespace wr {
 class DisplayListBuilder;
+class IpcResourceUpdateQueue;
 } // namespace wr
 } // namespace mozilla
 
 /**
  * Callback function that processes events.
  *
  * The argument is actually a subtype (subclass) of WidgetEvent which carries
  * platform specific information about the event. Platform specific code
@@ -1289,23 +1290,25 @@ class nsIWidget : public nsISupports
      * Always called on the main thread.
      */
     virtual void PrepareWindowEffects() = 0;
 
     /**
      * Called on the main thread at the end of WebRender display list building.
      */
     virtual void AddWindowOverlayWebRenderCommands(mozilla::layers::WebRenderBridgeChild* aWrBridge,
-                                                   mozilla::wr::DisplayListBuilder& aBuilder) {}
+                                                   mozilla::wr::DisplayListBuilder& aBuilder,
+                                                   mozilla::wr::IpcResourceUpdateQueue& aResources) {}
 
     /**
      * Called on the main thread when WebRender resources used for
      * AddWindowOverlayWebRenderCommands need to be destroyed.
      */
-    virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge) {}
+    virtual void CleanupWebRenderWindowOverlay(mozilla::layers::WebRenderBridgeChild* aWrBridge,
+                                               mozilla::wr::IpcResourceUpdateQueue& aResources) {}
 
     /**
      * Called when Gecko knows which themed widgets exist in this window.
      * The passed array contains an entry for every themed widget of the right
      * type (currently only NS_THEME_TOOLBAR) within the window, except for
      * themed widgets which are transformed or have effects applied to them
      * (e.g. CSS opacity or filters).
      * This could sometimes be called during display list construction