Bug 1335799 - Update WR layers and FFI/bindings code for the webrender update. r=jrmuizel
authorNicolas Silva <nsilva@mozilla.com>
Tue, 14 Feb 2017 13:34:15 -0500
changeset 343964 5b1a780d4aa94e4e0e5e2d8a70127d037da2848c
parent 343963 ca2b6dc909b31499974dc17041ce96181579206f
child 343965 2dfcdea58f5dfa0a6eb61b8d6403f859e2765775
push id31395
push userkwierso@gmail.com
push dateTue, 21 Feb 2017 18:17:00 +0000
treeherdermozilla-central@c7b015c488cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1335799
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1335799 - Update WR layers and FFI/bindings code for the webrender update. r=jrmuizel MozReview-Commit-ID: Hv3MwSr97Op
dom/ipc/TabChild.cpp
gfx/layers/ipc/WebRenderMessages.ipdlh
gfx/layers/wr/WebRenderBridgeParent.cpp
gfx/layers/wr/WebRenderCanvasLayer.cpp
gfx/layers/wr/WebRenderContainerLayer.cpp
gfx/layers/wr/WebRenderImageLayer.cpp
gfx/layers/wr/WebRenderLayerManager.cpp
gfx/layers/wr/WebRenderLayerManager.h
gfx/layers/wr/WebRenderLayersLogging.cpp
gfx/layers/wr/WebRenderLayersLogging.h
gfx/layers/wr/WebRenderMessageUtils.h
gfx/layers/wr/WebRenderPaintedLayer.cpp
gfx/webrender_bindings/Cargo.toml
gfx/webrender_bindings/RenderThread.cpp
gfx/webrender_bindings/WebRenderAPI.cpp
gfx/webrender_bindings/WebRenderAPI.h
gfx/webrender_bindings/WebRenderTypes.h
gfx/webrender_bindings/src/bindings.rs
gfx/webrender_bindings/webrender_ffi.h
widget/nsBaseWidget.cpp
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2609,17 +2609,17 @@ TabChild::InitRenderingState(const Textu
     ShadowLayerForwarder* lf =
         mPuppetWidget->GetLayerManager(
             nullptr, mTextureFactoryIdentifier.mParentBackend)
                 ->AsShadowForwarder();
 
     LayerManager* lm = mPuppetWidget->GetLayerManager();
     if (lm->AsWebRenderLayerManager()) {
       lm->AsWebRenderLayerManager()->Initialize(compositorChild,
-                                                aLayersId,
+                                                wr::AsPipelineId(aLayersId),
                                                 &mTextureFactoryIdentifier);
       ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
       gfx::VRManagerChild::IdentifyTextureHost(mTextureFactoryIdentifier);
       InitAPZState();
     }
 
     if (lf) {
       nsTArray<LayersBackend> backends;
--- a/gfx/layers/ipc/WebRenderMessages.ipdlh
+++ b/gfx/layers/ipc/WebRenderMessages.ipdlh
@@ -7,26 +7,26 @@
 
 include LayersSurfaces;
 include LayersMessages;
 include protocol PTexture;
 
 using WrBorderRadius from "mozilla/webrender/webrender_ffi.h";
 using WrBorderSide from "mozilla/webrender/webrender_ffi.h";
 using WrColor from "mozilla/webrender/webrender_ffi.h";
-using WrImageKey from "mozilla/webrender/webrender_ffi.h";
-using WrTextureFilter from "mozilla/webrender/webrender_ffi.h";
 using WrLayoutSize from "mozilla/webrender/webrender_ffi.h";
 using WrRect from "mozilla/webrender/webrender_ffi.h";
 using WrGlyphArray from "mozilla/webrender/webrender_ffi.h";
 using WrMixBlendMode from "mozilla/webrender/webrender_ffi.h";
 using MaybeImageMask from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h";
 using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::wr::PipelineId from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::ImageRendering from "mozilla/webrender/WebRenderTypes.h";
+using mozilla::wr::ImageKey from "mozilla/webrender/WebRenderTypes.h";
 using mozilla::LayerIntRegion from "Units.h";
 
 namespace mozilla {
 namespace layers {
 
 struct OpDPPushStackingContext {
   WrRect bounds;
   WrRect overflow;
@@ -35,16 +35,25 @@ struct OpDPPushStackingContext {
   Animation[] animations;
   Matrix4x4 matrix;
   WrMixBlendMode mixBlendMode;
   uint64_t scrollid;
 };
 
 struct OpDPPopStackingContext { };
 
+struct OpDPPushScrollLayer {
+  WrRect bounds;
+  WrRect overflow;
+  MaybeImageMask mask;
+  uint64_t scrollid;
+};
+
+struct OpDPPopScrollLayer { };
+
 struct OpDPPushRect {
   WrRect bounds;
   WrRect clip;
   WrColor color;
 };
 
 struct OpDPPushBorder {
   WrRect bounds;
@@ -55,26 +64,26 @@ struct OpDPPushBorder {
   WrBorderSide left;
   WrBorderRadius radius;
 };
 
 struct OpDPPushImage {
   WrRect bounds;
   WrRect clip;
   MaybeImageMask mask;
-  WrTextureFilter filter;
-  WrImageKey key;
+  ImageRendering filter;
+  ImageKey key;
 };
 
 struct OpDPPushExternalImageId {
   LayerIntRegion validBufferRegion;
   WrRect bounds;
   WrRect clip;
   MaybeImageMask mask;
-  WrTextureFilter filter;
+  ImageRendering filter;
   uint64_t externalImageId;
 };
 
 struct OpDPPushIframe {
   WrRect bounds;
   WrRect clip;
   PipelineId pipelineId;
 };
@@ -87,16 +96,18 @@ struct OpDPPushText {
   float glyph_size;
   ByteBuffer font_buffer;
   uint32_t font_buffer_length;
 };
 
 union WebRenderCommand {
   OpDPPushStackingContext;
   OpDPPopStackingContext;
+  OpDPPushScrollLayer;
+  OpDPPopScrollLayer;
   OpDPPushRect;
   OpDPPushBorder;
   OpDPPushImage;
   OpDPPushExternalImageId;
   OpDPPushIframe;
   OpDPPushText;
   CompositableOperation;
 };
--- a/gfx/layers/wr/WebRenderBridgeParent.cpp
+++ b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -145,33 +145,35 @@ WebRenderBridgeParent::RecvAddImage(cons
                                     const gfx::SurfaceFormat& aFormat,
                                     const ByteBuffer& aBuffer,
                                     wr::ImageKey* aOutImageKey)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   MOZ_ASSERT(mApi);
-  *aOutImageKey = mApi->AddImageBuffer(aSize, aStride, aFormat,
+  wr::ImageDescriptor descriptor(aSize, aStride, aFormat);
+  *aOutImageKey = mApi->AddImageBuffer(descriptor,
                                        aBuffer.AsSlice());
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvUpdateImage(const wr::ImageKey& aImageKey,
                                        const gfx::IntSize& aSize,
                                        const gfx::SurfaceFormat& aFormat,
                                        const ByteBuffer& aBuffer)
 {
   if (mDestroyed) {
     return IPC_OK();
   }
   MOZ_ASSERT(mApi);
-  mApi->UpdateImageBuffer(aImageKey, aSize, aFormat, aBuffer.AsSlice());
+  wr::ImageDescriptor descriptor(aSize, aFormat);
+  mApi->UpdateImageBuffer(aImageKey, descriptor, aBuffer.AsSlice());
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDeleteImage(const wr::ImageKey& aImageKey)
 {
   if (mDestroyed) {
@@ -209,17 +211,17 @@ WebRenderBridgeParent::HandleDPEnd(Infal
       DestroyActor(op);
     }
     return;
   }
   // This ensures that destroy operations are always processed. It is not safe
   // to early-return from RecvDPEnd without doing so.
   AutoWebRenderBridgeParentAsyncMessageSender autoAsyncMessageSender(this, &aToDestroy);
 
-  ProcessWebrenderCommands(aCommands, wr::Epoch(aTransactionId));
+  ProcessWebrenderCommands(aCommands, wr::NewEpoch(aTransactionId));
 
   // The transaction ID might get reset to 1 if the page gets reloaded, see
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
   // Otherwise, it should be continually increasing.
   MOZ_ASSERT(aTransactionId == 1 || aTransactionId > mPendingTransactionId);
   mPendingTransactionId = aTransactionId;
 }
 
@@ -259,16 +261,25 @@ WebRenderBridgeParent::ProcessWebrenderC
         const OpDPPushStackingContext& op = cmd.get_OpDPPushStackingContext();
         builder.PushStackingContext(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr), op.opacity(), op.matrix(), op.mixBlendMode());
         break;
       }
       case WebRenderCommand::TOpDPPopStackingContext: {
         builder.PopStackingContext();
         break;
       }
+      case WebRenderCommand::TOpDPPushScrollLayer: {
+        const OpDPPushScrollLayer& op = cmd.get_OpDPPushScrollLayer();
+        builder.PushScrollLayer(op.bounds(), op.overflow(), op.mask().ptrOr(nullptr));
+        break;
+      }
+      case WebRenderCommand::TOpDPPopScrollLayer: {
+        builder.PopScrollLayer();
+        break;
+      }
       case WebRenderCommand::TOpDPPushRect: {
         const OpDPPushRect& op = cmd.get_OpDPPushRect();
         builder.PushRect(op.bounds(), op.clip(), op.color());
         break;
       }
       case WebRenderCommand::TOpDPPushBorder: {
         const OpDPPushBorder& op = cmd.get_OpDPPushBorder();
         builder.PushBorder(op.bounds(), op.clip(),
@@ -316,19 +327,20 @@ WebRenderBridgeParent::ProcessWebrenderC
           dSurf = surf->GetDataSurface();
         }
 
         DataSourceSurface::MappedSurface map;
         if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
           break;
         }
 
+        wr::ImageDescriptor descriptor(validRect.Size(), map.mStride, SurfaceFormat::B8G8R8A8);
         wr::ImageKey key;
         auto slice = Range<uint8_t>(map.mData, validRect.height * map.mStride);
-        key = mApi->AddImageBuffer(validRect.Size(), map.mStride, SurfaceFormat::B8G8R8A8, slice);
+        key = mApi->AddImageBuffer(descriptor, slice);
 
         builder.PushImage(op.bounds(), op.clip(), op.mask().ptrOr(nullptr), op.filter(), key);
         keysToDelete.push_back(key);
         dSurf->Unmap();
         break;
       }
       case WebRenderCommand::TOpDPPushIframe: {
         const OpDPPushIframe& op = cmd.get_OpDPPushIframe();
@@ -374,17 +386,17 @@ WebRenderBridgeParent::ProcessWebrenderC
   DeleteOldImages();
 
   // XXX remove it when external image key is used.
   if (!keysToDelete.empty()) {
     mKeysToDelete.swap(keysToDelete);
   }
 
   if (ShouldParentObserveEpoch()) {
-    mCompositorBridge->ObserveLayerUpdate(mPipelineId.mHandle, GetChildLayerObserverEpoch(), true);
+    mCompositorBridge->ObserveLayerUpdate(wr::AsUint64(mPipelineId), GetChildLayerObserverEpoch(), true);
   }
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvDPGetSnapshot(PTextureParent* aTexture)
 {
   if (mDestroyed) {
     return IPC_OK();
@@ -500,17 +512,17 @@ WebRenderBridgeParent::RecvSetLayerObser
 {
   mChildLayerObserverEpoch = aLayerObserverEpoch;
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 WebRenderBridgeParent::RecvClearCachedResources()
 {
-  mCompositorBridge->ObserveLayerUpdate(mPipelineId.mHandle, GetChildLayerObserverEpoch(), false);
+  mCompositorBridge->ObserveLayerUpdate(wr::AsUint64(mPipelineId), GetChildLayerObserverEpoch(), false);
   return IPC_OK();
 }
 
 void
 WebRenderBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   Destroy();
 }
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -68,17 +68,17 @@ WebRenderCanvasLayer::RenderLayer()
       clip = RelativeToTransformedVisible(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
   } else {
       clip = rect;
   }
 
   gfx::Rect relBounds = TransformedVisibleBoundsRelativeToParent();
   gfx::Rect overflow(0, 0, relBounds.width, relBounds.height);
   Maybe<WrImageMask> mask = buildMaskLayer();
-  WrTextureFilter filter = (mSamplingFilter == gfx::SamplingFilter::POINT) ? WrTextureFilter::Point : WrTextureFilter::Linear;
+  wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
   WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
 
   if (gfxPrefs::LayersDump()) {
     printf_stderr("CanvasLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, texture-filter=%s, mix-blend-mode=%s\n",
                   this->GetLayer(),
                   Stringify(relBounds).c_str(),
                   Stringify(overflow).c_str(),
                   Stringify(transform).c_str(),
--- a/gfx/layers/wr/WebRenderContainerLayer.cpp
+++ b/gfx/layers/wr/WebRenderContainerLayer.cpp
@@ -65,13 +65,13 @@ WebRenderRefLayer::RenderLayer()
   if (gfxPrefs::LayersDump()) {
     printf_stderr("RefLayer %p (%" PRIu64 ") using bounds/overflow=%s, transform=%s\n",
                   this->GetLayer(),
                   mId,
                   Stringify(relBounds).c_str(),
                   Stringify(transform).c_str());
   }
 
-  WrBridge()->AddWebRenderCommand(OpDPPushIframe(wr::ToWrRect(relBounds), wr::ToWrRect(relBounds), wr::PipelineId(mId)));
+  WrBridge()->AddWebRenderCommand(OpDPPushIframe(wr::ToWrRect(relBounds), wr::ToWrRect(relBounds), wr::AsPipelineId(mId)));
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderImageLayer.cpp
+++ b/gfx/layers/wr/WebRenderImageLayer.cpp
@@ -136,17 +136,17 @@ WebRenderImageLayer::RenderLayer()
   } else {
       clip = rect;
   }
 
   Rect relBounds = TransformedVisibleBoundsRelativeToParent();
   Rect overflow(0, 0, relBounds.width, relBounds.height);
   Matrix4x4 transform;// = GetTransform();
   Maybe<WrImageMask> mask = buildMaskLayer();
-  WrTextureFilter filter = (mSamplingFilter == gfx::SamplingFilter::POINT) ? WrTextureFilter::Point : WrTextureFilter::Linear;
+  wr::ImageRendering filter = wr::ToImageRendering(mSamplingFilter);
   WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
 
   if (gfxPrefs::LayersDump()) {
     printf_stderr("ImageLayer %p using bounds=%s, overflow=%s, transform=%s, rect=%s, clip=%s, texture-filter=%s, mix-blend-mode=%s\n",
                   this->GetLayer(),
                   Stringify(relBounds).c_str(),
                   Stringify(overflow).c_str(),
                   Stringify(transform).c_str(),
--- a/gfx/layers/wr/WebRenderLayerManager.cpp
+++ b/gfx/layers/wr/WebRenderLayerManager.cpp
@@ -112,17 +112,17 @@ WebRenderLayer::buildMaskLayer() {
           RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
           DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::MapType::READ);
           gfx::IntSize size = surface->GetSize();
           MOZ_RELEASE_ASSERT(surface->GetFormat() == SurfaceFormat::A8, "bad format");
           wr::ByteBuffer buf(size.height * map.GetStride(), map.GetData());
           wr::ImageKey maskKey;
           WrBridge()->SendAddImage(size, map.GetStride(), SurfaceFormat::A8, buf, &maskKey);
 
-          imageMask.image = maskKey.mHandle;
+          imageMask.image = maskKey;
           imageMask.rect = wr::ToWrRect(Rect(0, 0, size.width, size.height));
           imageMask.repeat = false;
           WrManager()->AddImageKeyForDiscard(maskKey);
           mask = Some(imageMask);
       }
     }
   }
   return mask;
@@ -190,24 +190,24 @@ WebRenderLayerManager::WebRenderLayerMan
 KnowsCompositor*
 WebRenderLayerManager::AsKnowsCompositor()
 {
   return mWrChild;
 }
 
 void
 WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild,
-                                  uint64_t aLayersId,
+                                  wr::PipelineId aLayersId,
                                   TextureFactoryIdentifier* aTextureFactoryIdentifier)
 {
   MOZ_ASSERT(mWrChild == nullptr);
   MOZ_ASSERT(aTextureFactoryIdentifier);
 
   TextureFactoryIdentifier textureFactoryIdentifier;
-  PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(wr::PipelineId(aLayersId),
+  PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
                                                                             &textureFactoryIdentifier);
   MOZ_ASSERT(bridge);
   mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
   LayoutDeviceIntSize size = mWidget->GetClientSize();
   WrBridge()->SendCreate(size.ToUnknownSize());
   WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
   *aTextureFactoryIdentifier = textureFactoryIdentifier;
 }
--- a/gfx/layers/wr/WebRenderLayerManager.h
+++ b/gfx/layers/wr/WebRenderLayerManager.h
@@ -60,17 +60,17 @@ private:
 };
 
 class WebRenderLayerManager final : public LayerManager
 {
   typedef nsTArray<RefPtr<Layer> > LayerRefArray;
 
 public:
   explicit WebRenderLayerManager(nsIWidget* aWidget);
-  void Initialize(PCompositorBridgeChild* aCBChild, uint64_t aLayersId, TextureFactoryIdentifier* aTextureFactoryIdentifier);
+  void Initialize(PCompositorBridgeChild* aCBChild, wr::PipelineId aLayersId, TextureFactoryIdentifier* aTextureFactoryIdentifier);
 
   virtual void Destroy() override;
 
 protected:
   virtual ~WebRenderLayerManager();
 
 public:
   virtual KnowsCompositor* AsKnowsCompositor() override;
--- a/gfx/layers/wr/WebRenderLayersLogging.cpp
+++ b/gfx/layers/wr/WebRenderLayersLogging.cpp
@@ -8,71 +8,73 @@
 #include "WebRenderLayersLogging.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 void
-AppendToString(std::stringstream& aStream, WrMixBlendMode aMixBlendMode,
+AppendToString(std::stringstream& aStream, wr::MixBlendMode aMixBlendMode,
                const char* pfx, const char* sfx)
 {
   aStream << pfx;
   switch (aMixBlendMode) {
-  case WrMixBlendMode::Normal:
-    aStream << "WrMixBlendMode::Normal"; break;
-  case WrMixBlendMode::Multiply:
-    aStream << "WrMixBlendMode::Multiply"; break;
-  case WrMixBlendMode::Screen:
-    aStream << "WrMixBlendMode::Screen"; break;
-  case WrMixBlendMode::Overlay:
-    aStream << "WrMixBlendMode::Overlay"; break;
-  case WrMixBlendMode::Darken:
-    aStream << "WrMixBlendMode::Darken"; break;
-  case WrMixBlendMode::Lighten:
-    aStream << "WrMixBlendMode::Lighten"; break;
-  case WrMixBlendMode::ColorDodge:
-    aStream << "WrMixBlendMode::ColorDodge"; break;
-  case WrMixBlendMode::ColorBurn:
-    aStream << "WrMixBlendMode::ColorBurn"; break;
-  case WrMixBlendMode::HardLight:
-    aStream << "WrMixBlendMode::HardLight"; break;
-  case WrMixBlendMode::SoftLight:
-    aStream << "WrMixBlendMode::SoftLight"; break;
-  case WrMixBlendMode::Difference:
-    aStream << "WrMixBlendMode::Difference"; break;
-  case WrMixBlendMode::Exclusion:
-    aStream << "WrMixBlendMode::Exclusion"; break;
-  case WrMixBlendMode::Hue:
-    aStream << "WrMixBlendMode::Hue"; break;
-  case WrMixBlendMode::Saturation:
-    aStream << "WrMixBlendMode::Saturation"; break;
-  case WrMixBlendMode::Color:
-    aStream << "WrMixBlendMode::Color"; break;
-  case WrMixBlendMode::Luminosity:
-    aStream << "WrMixBlendMode::Luminosity"; break;
-  case WrMixBlendMode::Sentinel:
+  case wr::MixBlendMode::Normal:
+    aStream << "wr::MixBlendMode::Normal"; break;
+  case wr::MixBlendMode::Multiply:
+    aStream << "wr::MixBlendMode::Multiply"; break;
+  case wr::MixBlendMode::Screen:
+    aStream << "wr::MixBlendMode::Screen"; break;
+  case wr::MixBlendMode::Overlay:
+    aStream << "wr::MixBlendMode::Overlay"; break;
+  case wr::MixBlendMode::Darken:
+    aStream << "wr::MixBlendMode::Darken"; break;
+  case wr::MixBlendMode::Lighten:
+    aStream << "wr::MixBlendMode::Lighten"; break;
+  case wr::MixBlendMode::ColorDodge:
+    aStream << "wr::MixBlendMode::ColorDodge"; break;
+  case wr::MixBlendMode::ColorBurn:
+    aStream << "wr::MixBlendMode::ColorBurn"; break;
+  case wr::MixBlendMode::HardLight:
+    aStream << "wr::MixBlendMode::HardLight"; break;
+  case wr::MixBlendMode::SoftLight:
+    aStream << "wr::MixBlendMode::SoftLight"; break;
+  case wr::MixBlendMode::Difference:
+    aStream << "wr::MixBlendMode::Difference"; break;
+  case wr::MixBlendMode::Exclusion:
+    aStream << "wr::MixBlendMode::Exclusion"; break;
+  case wr::MixBlendMode::Hue:
+    aStream << "wr::MixBlendMode::Hue"; break;
+  case wr::MixBlendMode::Saturation:
+    aStream << "wr::MixBlendMode::Saturation"; break;
+  case wr::MixBlendMode::Color:
+    aStream << "wr::MixBlendMode::Color"; break;
+  case wr::MixBlendMode::Luminosity:
+    aStream << "wr::MixBlendMode::Luminosity"; break;
+  case wr::MixBlendMode::Sentinel:
     NS_ERROR("unknown mix blend mode");
     aStream << "???";
   }
   aStream << sfx;
 }
 
 void
-AppendToString(std::stringstream& aStream, WrTextureFilter aTextureFilter,
+AppendToString(std::stringstream& aStream, wr::ImageRendering aTextureFilter,
                const char* pfx, const char* sfx)
 {
   aStream << pfx;
   switch (aTextureFilter) {
-  case WrTextureFilter::Linear:
-    aStream << "WrTextureFilter::Linear"; break;
-  case WrTextureFilter::Point:
-    aStream << "WrTextureFilter::Point"; break;
-  case WrTextureFilter::Sentinel:
+  case wr::ImageRendering::Auto:
+    aStream << "ImageRendering::Auto"; break;
+  case wr::ImageRendering::CrispEdges:
+    aStream << "ImageRendering::CrispEdges"; break;
+  case wr::ImageRendering::Pixelated:
+    aStream << "ImageRendering::Pixelated"; break;
+  case wr::ImageRendering::Sentinel:
     NS_ERROR("unknown texture filter");
     aStream << "???";
   }
   aStream << sfx;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/wr/WebRenderLayersLogging.h
+++ b/gfx/layers/wr/WebRenderLayersLogging.h
@@ -8,21 +8,21 @@
 #define GFX_WEBRENDERLAYERSLOGGING_H
 
 #include "mozilla/webrender/WebRenderTypes.h"
 
 namespace mozilla {
 namespace layers {
 
 void
-AppendToString(std::stringstream& aStream, WrMixBlendMode aMixBlendMode,
+AppendToString(std::stringstream& aStream, wr::MixBlendMode aMixBlendMode,
                const char* pfx="", const char* sfx="");
 
 void
-AppendToString(std::stringstream& aStream, WrTextureFilter aTextureFilter,
+AppendToString(std::stringstream& aStream, wr::ImageRendering aTextureFilter,
                const char* pfx="", const char* sfx="");
 
 } // namespace layers
 } // namespace mozilla
 
 // this ensures that the WebRender AppendToString's are in scope for Stringify
 #include "LayersLogging.h"
 
--- a/gfx/layers/wr/WebRenderMessageUtils.h
+++ b/gfx/layers/wr/WebRenderMessageUtils.h
@@ -36,55 +36,61 @@ struct ParamTraits<mozilla::wr::ByteBuff
 };
 
 template<>
 struct ParamTraits<mozilla::wr::ImageKey>
 {
   static void
   Write(Message* aMsg, const mozilla::wr::ImageKey& aParam)
   {
+    WriteParam(aMsg, aParam.mNamespace);
     WriteParam(aMsg, aParam.mHandle);
   }
 
   static bool
   Read(const Message* aMsg, PickleIterator* aIter, mozilla::wr::ImageKey* aResult)
   {
-    return ReadParam(aMsg, aIter, &aResult->mHandle);
+    return ReadParam(aMsg, aIter, &aResult->mNamespace)
+        && ReadParam(aMsg, aIter, &aResult->mHandle);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::wr::FontKey>
 {
   static void
   Write(Message* aMsg, const mozilla::wr::FontKey& aParam)
   {
+    WriteParam(aMsg, aParam.mNamespace);
     WriteParam(aMsg, aParam.mHandle);
   }
 
   static bool
   Read(const Message* aMsg, PickleIterator* aIter, mozilla::wr::FontKey* aResult)
   {
-    return ReadParam(aMsg, aIter, &aResult->mHandle);
+    return ReadParam(aMsg, aIter, &aResult->mNamespace)
+        && ReadParam(aMsg, aIter, &aResult->mHandle);
   }
 };
 
 template<>
 struct ParamTraits<mozilla::wr::PipelineId>
 {
   static void
   Write(Message* aMsg, const mozilla::wr::PipelineId& aParam)
   {
+    WriteParam(aMsg, aParam.mNamespace);
     WriteParam(aMsg, aParam.mHandle);
   }
 
   static bool
   Read(const Message* aMsg, PickleIterator* aIter, mozilla::wr::PipelineId* aResult)
   {
-    return ReadParam(aMsg, aIter, &aResult->mHandle);
+    return ReadParam(aMsg, aIter, &aResult->mNamespace)
+        && ReadParam(aMsg, aIter, &aResult->mHandle);
   }
 };
 
 template<>
 struct ParamTraits<WrImageFormat>
   : public ContiguousEnumSerializer<
         WrImageFormat,
         WrImageFormat::Invalid,
@@ -281,21 +287,21 @@ struct ParamTraits<WrImageMask>
   {
     return ReadParam(aMsg, aIter, &aResult->image)
         && ReadParam(aMsg, aIter, &aResult->rect)
         && ReadParam(aMsg, aIter, &aResult->repeat);
   }
 };
 
 template<>
-struct ParamTraits<WrTextureFilter>
+struct ParamTraits<WrImageRendering>
   : public ContiguousEnumSerializer<
-        WrTextureFilter,
-        WrTextureFilter::Linear,
-        WrTextureFilter::Sentinel>
+        WrImageRendering,
+        WrImageRendering::Auto,
+        WrImageRendering::Sentinel>
 {
 };
 
 template<>
 struct ParamTraits<WrMixBlendMode>
   : public ContiguousEnumSerializer<
         WrMixBlendMode,
         WrMixBlendMode::Normal,
--- a/gfx/layers/wr/WebRenderPaintedLayer.cpp
+++ b/gfx/layers/wr/WebRenderPaintedLayer.cpp
@@ -162,14 +162,14 @@ WebRenderPaintedLayer::RenderLayer()
       OpDPPushStackingContext(wr::ToWrRect(relBounds),
                               wr::ToWrRect(overflow),
                               mask,
                               1.0f,
                               GetAnimations(),
                               transform,
                               mixBlendMode,
                               FrameMetrics::NULL_SCROLL_ID));
-  WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(visibleRegion, wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), WrTextureFilter::Linear, mExternalImageId));
+  WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(visibleRegion, wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), wr::ImageRendering::Auto, mExternalImageId));
   WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/webrender_bindings/Cargo.toml
+++ b/gfx/webrender_bindings/Cargo.toml
@@ -1,24 +1,24 @@
 [package]
 name = "webrender_bindings"
 version = "0.1.0"
 authors = ["The Mozilla Project Developers"]
 license = "MPL-2.0"
 
 [dependencies]
-webrender_traits = {path = "../webrender_traits", version = "0.11.0"}
+webrender_traits = {path = "../webrender_traits", version = "0.14"}
 euclid = "0.10"
 app_units = "0.3"
 gleam = "0.2"
 fnv="1.0"
 
 [dependencies.webrender]
 path = "../webrender"
-version = "0.11.0"
+version = "0.15"
 default-features = false
 features = ["codegen"]
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.2.2"
 
 [target.'cfg(target_os = "windows")'.dependencies]
 kernel32-sys = "0.2"
--- a/gfx/webrender_bindings/RenderThread.cpp
+++ b/gfx/webrender_bindings/RenderThread.cpp
@@ -132,30 +132,16 @@ RenderThread::NewScrollFrameReady(wr::Wi
     ));
     return;
   }
 
   UpdateAndRender(aWindowId);
 }
 
 void
-RenderThread::PipelineSizeChanged(wr::WindowId aWindowId, uint64_t aPipelineId, float aWidth, float aHeight)
-{
-  if (!IsInRenderThread()) {
-    Loop()->PostTask(NewRunnableMethod<wr::WindowId, uint64_t, float, float>(
-      this, &RenderThread::PipelineSizeChanged,
-      aWindowId, aPipelineId, aWidth, aHeight
-    ));
-    return;
-  }
-
-  UpdateAndRender(aWindowId);
-}
-
-void
 RenderThread::RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent)
 {
   if (!IsInRenderThread()) {
     Loop()->PostTask(NewRunnableMethod<wr::WindowId, UniquePtr<RendererEvent>&&>(
       this, &RenderThread::RunEvent,
       aWindowId, Move(aEvent)
     ));
     return;
@@ -172,17 +158,17 @@ NotifyDidRender(layers::CompositorBridge
                 TimeStamp aEnd)
 {
   WrPipelineId pipeline;
   WrEpoch epoch;
   while (wr_rendered_epochs_next(aEpochs, &pipeline, &epoch)) {
     // TODO - Currently each bridge seems to  only have one pipeline but at some
     // point we should pass make sure we only notify bridges that have the
     // corresponding pipeline id.
-    aBridge->NotifyDidComposite(epoch, aStart, aEnd);
+    aBridge->NotifyDidComposite(epoch.mHandle, aStart, aEnd);
   }
   wr_rendered_epochs_delete(aEpochs);
 }
 
 void
 RenderThread::UpdateAndRender(wr::WindowId aWindowId)
 {
   MOZ_ASSERT(IsInRenderThread());
@@ -222,25 +208,16 @@ void wr_notifier_new_frame_ready(WrWindo
 }
 
 void wr_notifier_new_scroll_frame_ready(WrWindowId aWindowId, bool aCompositeNeeded)
 {
   mozilla::wr::RenderThread::Get()->NewScrollFrameReady(mozilla::wr::WindowId(aWindowId),
                                                         aCompositeNeeded);
 }
 
-void wr_notifier_pipeline_size_changed(WrWindowId aWindowId,
-                                       uint64_t aPipelineId,
-                                       float aWidth,
-                                       float aHeight)
-{
-  mozilla::wr::RenderThread::Get()->PipelineSizeChanged(mozilla::wr::WindowId(aWindowId),
-                                                        aPipelineId, aWidth, aHeight);
-}
-
 void wr_notifier_external_event(WrWindowId aWindowId, size_t aRawEvent)
 {
   mozilla::UniquePtr<mozilla::wr::RendererEvent> evt(
     reinterpret_cast<mozilla::wr::RendererEvent*>(aRawEvent));
   mozilla::wr::RenderThread::Get()->RunEvent(mozilla::wr::WindowId(aWindowId),
                                              mozilla::Move(evt));
 }
 
--- a/gfx/webrender_bindings/WebRenderAPI.cpp
+++ b/gfx/webrender_bindings/WebRenderAPI.cpp
@@ -8,35 +8,16 @@
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "mozilla/widget/CompositorWidget.h"
 #include "mozilla/layers/SynchronousTask.h"
 
 namespace mozilla {
 namespace wr {
 
-Maybe<WrImageFormat>
-SurfaceFormatToWrImageFormat(gfx::SurfaceFormat aFormat) {
-  switch (aFormat) {
-    case gfx::SurfaceFormat::B8G8R8X8:
-      // TODO: WebRender will have a BGRA + opaque flag for this but does not
-      // have it yet (cf. issue #732).
-    case gfx::SurfaceFormat::B8G8R8A8:
-      return Some(WrImageFormat::RGBA8);
-    case gfx::SurfaceFormat::B8G8R8:
-      return Some(WrImageFormat::RGB8);
-    case gfx::SurfaceFormat::A8:
-      return Some(WrImageFormat::A8);
-    case gfx::SurfaceFormat::UNKNOWN:
-      return Some(WrImageFormat::Invalid);
-    default:
-      return Nothing();
-  }
-}
-
 class NewRenderer : public RendererEvent
 {
 public:
   NewRenderer(WrAPI** aApi, layers::CompositorBridgeParentBase* aBridge,
               GLint* aMaxTextureSize,
               RefPtr<widget::CompositorWidget>&& aWidget,
               layers::SynchronousTask* aTask,
               bool aEnableProfiler)
@@ -64,17 +45,19 @@ public:
       return;
     }
 
     gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, mMaxTextureSize);
 
     wr_gl_init(gl.get());
 
     WrRenderer* wrRenderer = nullptr;
-    wr_window_new(aWindowId.mHandle, this->mEnableProfiler, mWrApi, &wrRenderer);
+    if (!wr_window_new(aWindowId, this->mEnableProfiler, mWrApi, &wrRenderer)) {
+      return;
+    }
     MOZ_ASSERT(wrRenderer);
 
     RefPtr<RenderThread> thread = &aRenderThread;
     auto renderer = MakeUnique<RendererOGL>(Move(thread),
                                             Move(gl),
                                             Move(mCompositorWidget),
                                             aWindowId,
                                             wrRenderer,
@@ -122,17 +105,17 @@ already_AddRefed<WebRenderAPI>
 WebRenderAPI::Create(bool aEnableProfiler,
                      layers::CompositorBridgeParentBase* aBridge,
                      RefPtr<widget::CompositorWidget>&& aWidget)
 {
   MOZ_ASSERT(aBridge);
   MOZ_ASSERT(aWidget);
 
   static uint64_t sNextId = 1;
-  WindowId id(sNextId++);
+  auto id = NewWindowId(sNextId++);
 
   WrAPI* wrApi = nullptr;
   GLint maxTextureSize = 0;
 
   // Dispatch a synchronous task because the WrApi object needs to be created
   // on the render thread. If need be we could delay waiting on this task until
   // the next time we need to access the WrApi object.
   layers::SynchronousTask task("Create Renderer");
@@ -161,17 +144,17 @@ WebRenderAPI::~WebRenderAPI()
 
 void
 WebRenderAPI::SetRootDisplayList(gfx::Color aBgColor,
                                  Epoch aEpoch,
                                  LayerSize aViewportSize,
                                  DisplayListBuilder& aBuilder)
 {
   wr_api_set_root_display_list(mWrApi, aBuilder.mWrState,
-                               aEpoch.mHandle,
+                               aEpoch,
                                aViewportSize.width, aViewportSize.height);
 }
 
 void
 WebRenderAPI::Readback(gfx::IntSize size,
                        uint8_t *buffer,
                        uint32_t buffer_size)
 {
@@ -211,60 +194,54 @@ WebRenderAPI::Readback(gfx::IntSize size
     RunOnRenderThread(Move(event));
 
     task.Wait();
 }
 
 void
 WebRenderAPI::SetRootPipeline(PipelineId aPipeline)
 {
-  wr_api_set_root_pipeline(mWrApi, aPipeline.mHandle);
+  wr_api_set_root_pipeline(mWrApi, aPipeline);
 }
 
 ImageKey
-WebRenderAPI::AddImageBuffer(gfx::IntSize aSize,
-                             uint32_t aStride,
-                             gfx::SurfaceFormat aFormat,
+WebRenderAPI::AddImageBuffer(const ImageDescriptor& aDescritptor,
                              Range<uint8_t> aBytes)
 {
-  auto format = SurfaceFormatToWrImageFormat(aFormat).value();
   return ImageKey(wr_api_add_image(mWrApi,
-                                   aSize.width, aSize.height,
-                                   aStride, format,
+                                   &aDescritptor,
                                    &aBytes[0], aBytes.length()));
 }
 
 ImageKey
 WebRenderAPI::AddExternalImageHandle(gfx::IntSize aSize,
                                      gfx::SurfaceFormat aFormat,
                                      uint64_t aHandle)
 {
   auto format = SurfaceFormatToWrImageFormat(aFormat).value();
   return ImageKey(wr_api_add_external_image_texture(mWrApi,
                                                     aSize.width, aSize.height, format,
                                                     aHandle));
 }
 
 void
 WebRenderAPI::UpdateImageBuffer(ImageKey aKey,
-                                gfx::IntSize aSize,
-                                gfx::SurfaceFormat aFormat,
+                                const ImageDescriptor& aDescritptor,
                                 Range<uint8_t> aBytes)
 {
-  auto format = SurfaceFormatToWrImageFormat(aFormat).value();
   wr_api_update_image(mWrApi,
-                      aKey.mHandle,
-                      aSize.width, aSize.height, format,
+                      aKey,
+                      &aDescritptor,
                       &aBytes[0], aBytes.length());
 }
 
 void
 WebRenderAPI::DeleteImage(ImageKey aKey)
 {
-  wr_api_delete_image(mWrApi, aKey.mHandle);
+  wr_api_delete_image(mWrApi, aKey);
 }
 
 wr::FontKey
 WebRenderAPI::AddRawFont(Range<uint8_t> aBytes)
 {
   return wr::FontKey(wr_api_add_raw_font(mWrApi, &aBytes[0], aBytes.length()));
 }
 
@@ -312,17 +289,17 @@ WebRenderAPI::RunOnRenderThread(UniquePt
 {
   auto event = reinterpret_cast<uintptr_t>(aEvent.release());
   wr_api_send_external_event(mWrApi, event);
 }
 
 DisplayListBuilder::DisplayListBuilder(const LayerIntSize& aSize, PipelineId aId)
 {
   MOZ_COUNT_CTOR(DisplayListBuilder);
-  mWrState = wr_state_new(aSize.width, aSize.height, aId.mHandle);
+  mWrState = wr_state_new(aSize.width, aSize.height, aId);
 }
 
 DisplayListBuilder::~DisplayListBuilder()
 {
   MOZ_COUNT_DTOR(DisplayListBuilder);
   wr_state_delete(mWrState);
 }
 
@@ -330,17 +307,17 @@ void
 DisplayListBuilder::Begin(const LayerIntSize& aSize)
 {
   wr_dp_begin(mWrState, aSize.width, aSize.height);
 }
 
 void
 DisplayListBuilder::End(WebRenderAPI& aApi, Epoch aEpoch)
 {
-  wr_dp_end(mWrState, aApi.mWrApi, aEpoch.mHandle);
+  wr_dp_end(mWrState, aApi.mWrApi, aEpoch);
 }
 
 void
 DisplayListBuilder::PushStackingContext(const WrRect& aBounds,
                                         const WrRect& aOverflow,
                                         const WrImageMask* aMask,
                                         const float aOpacity,
                                         const gfx::Matrix4x4& aTransform,
@@ -352,39 +329,53 @@ DisplayListBuilder::PushStackingContext(
 
 void
 DisplayListBuilder::PopStackingContext()
 {
   wr_dp_pop_stacking_context(mWrState);
 }
 
 void
+DisplayListBuilder::PushScrollLayer(const WrRect& aBounds,
+                                    const WrRect& aOverflow,
+                                    const WrImageMask* aMask)
+{
+  wr_dp_push_scroll_layer(mWrState, aBounds, aOverflow, aMask);
+}
+
+void
+DisplayListBuilder::PopScrollLayer()
+{
+  wr_dp_pop_scroll_layer(mWrState);
+}
+
+void
 DisplayListBuilder::PushRect(const WrRect& aBounds,
                              const WrRect& aClip,
                              const WrColor& aColor)
 {
   wr_dp_push_rect(mWrState, aBounds, aClip, aColor);
 }
 
 void
 DisplayListBuilder::PushImage(const WrRect& aBounds,
                               const WrRect& aClip,
                               const WrImageMask* aMask,
-                              const WrTextureFilter aFilter,
+                              wr::ImageRendering aFilter,
                               wr::ImageKey aImage)
 {
-  wr_dp_push_image(mWrState, aBounds, aClip, aMask, aFilter, aImage.mHandle);
+  wr_dp_push_image(mWrState, aBounds, aClip, aMask, aFilter, aImage);
 }
 
 void
 DisplayListBuilder::PushIFrame(const WrRect& aBounds,
                                const WrRect& aClip,
                                PipelineId aPipeline)
 {
-  wr_dp_push_iframe(mWrState, aBounds, aClip, aPipeline.mHandle);
+  wr_dp_push_iframe(mWrState, aBounds, aClip, aPipeline);
 }
 
 void
 DisplayListBuilder::PushBorder(const WrRect& aBounds,
                                const WrRect& aClip,
                                const WrBorderSide& aTop,
                                const WrBorderSide& aRight,
                                const WrBorderSide& aBottom,
@@ -401,15 +392,15 @@ DisplayListBuilder::PushText(const WrRec
                              const WrRect& aClip,
                              const gfx::Color& aColor,
                              wr::FontKey aFontKey,
                              Range<const WrGlyphInstance> aGlyphBuffer,
                              float aGlyphSize)
 {
   wr_dp_push_text(mWrState, aBounds, aClip,
                   ToWrColor(aColor),
-                  aFontKey.mHandle,
+                  aFontKey,
                   &aGlyphBuffer[0], aGlyphBuffer.length(),
                   aGlyphSize);
 }
 
 } // namespace wr
 } // namespace mozilla
--- a/gfx/webrender_bindings/WebRenderAPI.h
+++ b/gfx/webrender_bindings/WebRenderAPI.h
@@ -43,28 +43,25 @@ public:
 
   void SetRootDisplayList(gfx::Color aBgColor,
                           wr::Epoch aEpoch,
                           LayerSize aViewportSize,
                           DisplayListBuilder& aBuilder);
 
   void SetRootPipeline(wr::PipelineId aPipeline);
 
-  wr::ImageKey AddImageBuffer(gfx::IntSize aSize,
-                              uint32_t aStride,
-                              gfx::SurfaceFormat aFormat,
+  wr::ImageKey AddImageBuffer(const ImageDescriptor& aDescriptor,
                               Range<uint8_t> aBytes);
 
   wr::ImageKey AddExternalImageHandle(gfx::IntSize aSize,
                                       gfx::SurfaceFormat aFormat,
                                       uint64_t aHandle);
 
   void UpdateImageBuffer(wr::ImageKey aKey,
-                         gfx::IntSize aSize,
-                         gfx::SurfaceFormat aFormat,
+                         const ImageDescriptor& aDescriptor,
                          Range<uint8_t> aBytes);
 
   void DeleteImage(wr::ImageKey aKey);
 
   wr::FontKey AddRawFont(Range<uint8_t> aBytes);
 
   void DeleteFont(wr::FontKey aKey);
 
@@ -109,24 +106,31 @@ public:
                            const WrRect& aOverflow,
                            const WrImageMask* aMask, // TODO: needs a wrapper.
                            const float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const WrMixBlendMode& aMixBlendMode);
 
   void PopStackingContext();
 
+  void PushScrollLayer(const WrRect& aBounds, // TODO: We should work with strongly typed rects
+                       const WrRect& aOverflow,
+                       const WrImageMask* aMask); // TODO: needs a wrapper.
+
+  void PopScrollLayer();
+
+
   void PushRect(const WrRect& aBounds,
                 const WrRect& aClip,
                 const WrColor& aColor);
 
   void PushImage(const WrRect& aBounds,
                  const WrRect& aClip,
                  const WrImageMask* aMask,
-                 const WrTextureFilter aFilter,
+                 wr::ImageRendering aFilter,
                  wr::ImageKey aImage);
 
   void PushIFrame(const WrRect& aBounds,
                   const WrRect& aClip,
                   wr::PipelineId aPipeline);
 
   void PushBorder(const WrRect& aBounds,
                   const WrRect& aClip,
--- a/gfx/webrender_bindings/WebRenderTypes.h
+++ b/gfx/webrender_bindings/WebRenderTypes.h
@@ -4,58 +4,138 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_WEBRENDERTYPES_H
 #define GFX_WEBRENDERTYPES_H
 
 #include "mozilla/webrender/webrender_ffi.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/gfx/Types.h"
+#include "mozilla/gfx/Tools.h"
 
 typedef mozilla::Maybe<WrImageMask> MaybeImageMask;
 
 namespace mozilla {
 namespace wr {
 
-static inline WrMixBlendMode ToWrMixBlendMode(gfx::CompositionOp compositionOp)
+typedef WrMixBlendMode MixBlendMode;
+typedef WrImageRendering ImageRendering;
+typedef WrImageFormat ImageFormat;
+typedef WrWindowId WindowId;
+typedef WrPipelineId PipelineId;
+typedef WrImageKey ImageKey;
+typedef WrFontKey FontKey;
+typedef WrEpoch Epoch;
+
+inline WindowId NewWindowId(uint64_t aId) {
+  WindowId id;
+  id.mHandle = aId;
+  return id;
+}
+
+inline Epoch NewEpoch(uint32_t aEpoch) {
+  Epoch e;
+  e.mHandle = aEpoch;
+  return e;
+}
+
+inline Maybe<WrImageFormat>
+SurfaceFormatToWrImageFormat(gfx::SurfaceFormat aFormat) {
+  switch (aFormat) {
+    case gfx::SurfaceFormat::B8G8R8X8:
+      // TODO: WebRender will have a BGRA + opaque flag for this but does not
+      // have it yet (cf. issue #732).
+    case gfx::SurfaceFormat::B8G8R8A8:
+      return Some(WrImageFormat::RGBA8);
+    case gfx::SurfaceFormat::B8G8R8:
+      return Some(WrImageFormat::RGB8);
+    case gfx::SurfaceFormat::A8:
+      return Some(WrImageFormat::A8);
+    case gfx::SurfaceFormat::UNKNOWN:
+      return Some(WrImageFormat::Invalid);
+    default:
+      return Nothing();
+  }
+}
+
+struct ImageDescriptor: public WrImageDescriptor {
+  ImageDescriptor(const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat)
+  {
+    format = SurfaceFormatToWrImageFormat(aFormat).value();
+    width = aSize.width;
+    height = aSize.height;
+    stride = 0;
+    is_opaque = gfx::IsOpaqueFormat(aFormat);
+  }
+
+  ImageDescriptor(const gfx::IntSize& aSize, uint32_t aByteStride, gfx::SurfaceFormat aFormat)
+  {
+    format = SurfaceFormatToWrImageFormat(aFormat).value();
+    width = aSize.width;
+    height = aSize.height;
+    stride = aByteStride;
+    is_opaque = gfx::IsOpaqueFormat(aFormat);
+  }
+};
+
+// Whenever possible, use wr::PipelineId instead of manipulating uint64_t.
+inline uint64_t AsUint64(const PipelineId& aId) {
+  return (static_cast<uint64_t>(aId.mNamespace) << 32)
+        + static_cast<uint64_t>(aId.mHandle);
+}
+
+inline PipelineId AsPipelineId(const uint64_t& aId) {
+  PipelineId pipeline;
+  pipeline.mNamespace = aId >> 32;
+  pipeline.mHandle = aId;
+  return pipeline;
+}
+
+inline ImageRendering ToImageRendering(gfx::SamplingFilter aFilter)
+{
+  return aFilter == gfx::SamplingFilter::POINT ? ImageRendering::Pixelated
+                                               : ImageRendering::Auto;
+}
+
+static inline MixBlendMode ToWrMixBlendMode(gfx::CompositionOp compositionOp)
 {
   switch (compositionOp)
   {
       case gfx::CompositionOp::OP_MULTIPLY:
-        return WrMixBlendMode::Multiply;
+        return MixBlendMode::Multiply;
       case gfx::CompositionOp::OP_SCREEN:
-        return WrMixBlendMode::Screen;
+        return MixBlendMode::Screen;
       case gfx::CompositionOp::OP_OVERLAY:
-        return WrMixBlendMode::Overlay;
+        return MixBlendMode::Overlay;
       case gfx::CompositionOp::OP_DARKEN:
-        return WrMixBlendMode::Darken;
+        return MixBlendMode::Darken;
       case gfx::CompositionOp::OP_LIGHTEN:
-        return WrMixBlendMode::Lighten;
+        return MixBlendMode::Lighten;
       case gfx::CompositionOp::OP_COLOR_DODGE:
-        return WrMixBlendMode::ColorDodge;
+        return MixBlendMode::ColorDodge;
       case gfx::CompositionOp::OP_COLOR_BURN:
-        return WrMixBlendMode::ColorBurn;
+        return MixBlendMode::ColorBurn;
       case gfx::CompositionOp::OP_HARD_LIGHT:
-        return WrMixBlendMode::HardLight;
+        return MixBlendMode::HardLight;
       case gfx::CompositionOp::OP_SOFT_LIGHT:
-        return WrMixBlendMode::SoftLight;
+        return MixBlendMode::SoftLight;
       case gfx::CompositionOp::OP_DIFFERENCE:
-        return WrMixBlendMode::Difference;
+        return MixBlendMode::Difference;
       case gfx::CompositionOp::OP_EXCLUSION:
-        return WrMixBlendMode::Exclusion;
+        return MixBlendMode::Exclusion;
       case gfx::CompositionOp::OP_HUE:
-        return WrMixBlendMode::Hue;
+        return MixBlendMode::Hue;
       case gfx::CompositionOp::OP_SATURATION:
-        return WrMixBlendMode::Saturation;
+        return MixBlendMode::Saturation;
       case gfx::CompositionOp::OP_COLOR:
-        return WrMixBlendMode::Color;
+        return MixBlendMode::Color;
       case gfx::CompositionOp::OP_LUMINOSITY:
-        return WrMixBlendMode::Luminosity;
+        return MixBlendMode::Luminosity;
       default:
-        return WrMixBlendMode::Normal;
+        return MixBlendMode::Normal;
   }
 }
 
 static inline WrColor ToWrColor(const gfx::Color& color)
 {
   WrColor c;
   c.r = color.r;
   c.g = color.g;
@@ -181,59 +261,12 @@ struct ByteBuffer
           !(memcmp(mData, other.mData, mLength));
   }
 
   size_t mLength;
   uint8_t* mData;
   bool mOwned;
 };
 
-struct WindowId {
-  explicit WindowId(WrWindowId aHandle) : mHandle(aHandle) {}
-  WindowId() : mHandle(0) {}
-  bool operator<(const WindowId& aOther) const { return mHandle < aOther.mHandle; }
-  bool operator==(const WindowId& aOther) const { return mHandle == aOther.mHandle; }
-
-  WrWindowId mHandle;
-};
-
-struct PipelineId {
-  explicit PipelineId(WrPipelineId aHandle) : mHandle(aHandle) {}
-  PipelineId() : mHandle(0) {}
-  bool operator<(const PipelineId& aOther) const { return mHandle < aOther.mHandle; }
-  bool operator==(const PipelineId& aOther) const { return mHandle == aOther.mHandle; }
-
-  WrPipelineId mHandle;
-};
-
-// TODO: We need to merge this with the notion of transaction id.
-struct Epoch {
-  explicit Epoch(WrEpoch aHandle) : mHandle(aHandle) {}
-  Epoch() : mHandle(0) {}
-  bool operator<(const Epoch& aOther) const { return mHandle < aOther.mHandle; }
-  bool operator==(const Epoch& aOther) const { return mHandle == aOther.mHandle; }
-
-  WrEpoch mHandle;
-};
-
-struct FontKey {
-  explicit FontKey(WrFontKey aHandle) : mHandle(aHandle) {}
-  FontKey() : mHandle(0) {}
-  bool operator<(const FontKey& aOther) const { return mHandle < aOther.mHandle; }
-  bool operator==(const FontKey& aOther) const { return mHandle == aOther.mHandle; }
-
-  WrFontKey mHandle;
-};
-
-struct ImageKey {
-  explicit ImageKey(WrImageKey aHandle) : mHandle(aHandle) {}
-  ImageKey() : mHandle(0) {}
-  bool operator<(const ImageKey& aOther) const { return mHandle < aOther.mHandle; }
-  bool operator==(const ImageKey& aOther) const { return mHandle == aOther.mHandle; }
-
-  WrImageKey mHandle;
-};
-
-
 } // namespace wr
 } // namespace mozilla
 
 #endif /* GFX_WEBRENDERTYPES_H */
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -1,30 +1,67 @@
 use std::ffi::CString;
 use std::{mem, slice};
 use std::os::raw::{c_void, c_char};
 use gleam::gl;
 use webrender_traits::{BorderSide, BorderStyle, BorderRadius};
-use webrender_traits::{PipelineId, ClipRegion};
+use webrender_traits::{PipelineId, ClipRegion, PropertyBinding};
 use webrender_traits::{Epoch, ColorF, GlyphInstance, ImageDescriptor};
 use webrender_traits::{FilterOp, ImageData, ImageFormat, ImageKey, ImageMask, ImageRendering, RendererKind, MixBlendMode};
 use webrender_traits::{ExternalImageId, RenderApi, FontKey};
 use webrender_traits::{DeviceUintSize, ExternalEvent};
 use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, LayoutTransform};
+use webrender_traits::ServoScrollRootId;
 use webrender::renderer::{Renderer, RendererOptions};
 use webrender::renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource};
 use app_units::Au;
 
 extern crate webrender_traits;
 
-fn pipeline_id_to_u64(id: PipelineId) -> u64 { ((id.0 as u64) << 32) + id.1 as u64 }
-fn u64_to_pipeline_id(id: u64) -> PipelineId { PipelineId((id >> 32) as u32, id as u32) }
+// This macro adds some checks to make sure we notice when the memory representation of
+// types change.
+macro_rules! check_ffi_type {
+    ($check_sizes_match:ident struct $TypeName:ident as ($T1:ident, $T2:ident)) => (
+        fn $check_sizes_match() {
+            #[repr(C)] struct TestType($T1, $T2);
+            let _ = mem::transmute::<$TypeName, TestType>;
+        }
+    );
+    ($check_sizes_match:ident struct $TypeName:ident as ($T:ident)) => (
+        fn $check_sizes_match() {
+            #[repr(C)] struct TestType($T);
+            let _ = mem::transmute::<$TypeName, TestType>;
+        }
+    );
+    ($check_sizes_match:ident enum $TypeName:ident as $T:ident) => (
+        fn $check_sizes_match() { let _ = mem::transmute::<$TypeName, $T>; }
+    );
+}
+ 
+check_ffi_type!(_pipeline_id_repr struct PipelineId as (u32, u32));
+check_ffi_type!(_image_key_repr struct ImageKey as (u32, u32));
+check_ffi_type!(_font_key_repr struct FontKey as (u32, u32));
+check_ffi_type!(_epoch_repr struct Epoch as (u32));
+check_ffi_type!(_image_format_repr enum ImageFormat as u32);
+check_ffi_type!(_border_style_repr enum BorderStyle as u32);
+check_ffi_type!(_image_rendering_repr enum ImageRendering as u32);
 
-fn font_key_to_u64(key: FontKey) -> u64 { unsafe { mem::transmute(key) } }
-fn u64_to_font_key(key: u64) -> FontKey { unsafe { mem::transmute(key) } }
+#[repr(C)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct WrWindowId(u64);
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub struct WrImageDescriptor {
+    pub format: ImageFormat,
+    pub width: u32,
+    pub height: u32,
+    pub stride: u32,
+    pub is_opaque: bool,
+} 
 
 fn get_proc_address(glcontext_ptr: *mut c_void, name: &str) -> *const c_void{
 
     extern  {
         fn get_proc_address_from_glcontext(glcontext_ptr: *mut c_void, procname: *const c_char) -> *const c_void;
     }
 
     let symbol_name = CString::new(name).unwrap();
@@ -104,70 +141,84 @@ pub unsafe extern fn wr_api_delete(api: 
 pub unsafe extern fn wr_api_set_root_display_list(api: &mut RenderApi,
                                                   state: &mut WrState,
                                                   epoch: Epoch,
                                                   viewport_width: f32,
                                                   viewport_height: f32) {
     let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
     let frame_builder = mem::replace(&mut state.frame_builder,
                                      WebRenderFrameBuilder::new(state.pipeline_id));
+    // See the documentation of set_root_display_list in api.rs. I don't think
+    // it makes a difference in gecko at the moment(until APZ is figured out)
+    // but I suppose it is a good default.
+    let preserve_frame_state = true;
     //let (dl_builder, aux_builder) = fb.dl_builder.finalize();
     api.set_root_display_list(Some(root_background_color),
                               epoch,
                               LayoutSize::new(viewport_width, viewport_height),
-                              frame_builder.dl_builder);
-    api.generate_frame();
+                              frame_builder.dl_builder,
+                              preserve_frame_state);
+    api.generate_frame(None);
 }
 #[no_mangle]
-pub extern fn wr_window_new(window_id: u64,
+pub extern fn wr_window_new(window_id: WrWindowId,
                             enable_profiler: bool,
                             out_api: &mut *mut RenderApi,
-                            out_renderer: &mut *mut Renderer) {
+                            out_renderer: &mut *mut Renderer) -> bool {
     assert!(unsafe { is_in_render_thread() });
 
     let opts = RendererOptions {
         device_pixel_ratio: 1.0,
         resource_override_path: None,
         enable_aa: false,
         enable_subpixel_aa: false,
         enable_profiler: enable_profiler,
-        enable_recording: false,
         enable_scrollbars: false,
         precache_shaders: false,
         renderer_kind: RendererKind::Native,
         debug: false,
         clear_framebuffer: true,
         render_target_debug: false,
         clear_color: ColorF::new(1.0, 1.0, 1.0, 1.0),
+        recorder: None,
+        workers: None,
     };
 
-    let (renderer, sender) = Renderer::new(opts);
+    let (renderer, sender) = match Renderer::new(opts) {
+        Ok((renderer, sender)) => { (renderer, sender) }
+        Err(e) => {
+            println!(" Failed to create a Renderer: {:?}", e);
+            return false;
+        }
+    };
+
     renderer.set_render_notifier(Box::new(CppNotifier { window_id: window_id }));
 
     *out_api = Box::into_raw(Box::new(sender.create_api()));
     *out_renderer = Box::into_raw(Box::new(renderer));
+
+    return true;
 }
 
 // Call MakeCurrent before this.
 #[no_mangle]
 pub extern fn wr_gl_init(gl_context: *mut c_void) {
     assert!(unsafe { is_in_render_thread() });
 
     gl::load_with(|symbol| get_proc_address(gl_context, symbol));
     gl::clear_color(0.3, 0.0, 0.0, 1.0);
 
     let version = gl::get_string(gl::VERSION);
 
     println!("WebRender - OpenGL version new {}", version);
 }
 
 #[no_mangle]
-pub extern fn wr_state_new(width: u32, height: u32, pipeline: u64) -> *mut WrState {
+pub extern fn wr_state_new(width: u32, height: u32, pipeline_id: PipelineId) -> *mut WrState {
     assert!(unsafe { is_in_compositor_thread() });
-    let pipeline_id = u64_to_pipeline_id(pipeline);
 
     let state = Box::new(WrState {
         size: (width, height),
         pipeline_id: pipeline_id,
         z_index: 0,
         frame_builder: WebRenderFrameBuilder::new(pipeline_id),
     });
 
@@ -192,106 +243,93 @@ pub extern fn wr_dp_begin(state: &mut Wr
 
     let bounds = LayoutRect::new(LayoutPoint::new(0.0, 0.0), LayoutSize::new(width as f32, height as f32));
 
     state.frame_builder.dl_builder.push_stacking_context(
         webrender_traits::ScrollPolicy::Scrollable,
         bounds,
         ClipRegion::simple(&bounds),
         0,
-        &LayoutTransform::identity(),
-        &LayoutTransform::identity(),
+        PropertyBinding::Value(LayoutTransform::identity()),
+        LayoutTransform::identity(),
         webrender_traits::MixBlendMode::Normal,
         Vec::new(),
     );
 }
 
 #[no_mangle]
 pub extern fn wr_dp_end(state: &mut WrState, api: &mut RenderApi, epoch: u32) {
     assert!( unsafe { is_in_compositor_thread() });
     let root_background_color = ColorF::new(0.3, 0.0, 0.0, 1.0);
     let pipeline_id = state.pipeline_id;
     let (width, height) = state.size;
 
     state.frame_builder.dl_builder.pop_stacking_context();
 
     let fb = mem::replace(&mut state.frame_builder, WebRenderFrameBuilder::new(pipeline_id));
 
+    let preserve_frame_state = true;
     api.set_root_display_list(Some(root_background_color),
                               Epoch(epoch),
                               LayoutSize::new(width as f32, height as f32),
-                              fb.dl_builder);
-    api.generate_frame();
+                              fb.dl_builder,
+                              preserve_frame_state);
+    api.generate_frame(None);
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_renderer_flush_rendered_epochs(renderer: &mut Renderer) -> *mut Vec<(PipelineId, Epoch)> {
     let map = renderer.flush_rendered_epochs();
     let pipeline_epochs = Box::new(map.into_iter().collect());
     return Box::into_raw(pipeline_epochs);
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_rendered_epochs_next(pipeline_epochs: &mut Vec<(PipelineId, Epoch)>,
-                                         out_pipeline: &mut u64,
-                                         out_epoch: &mut u32) -> bool {
+                                             out_pipeline: &mut PipelineId,
+                                             out_epoch: &mut Epoch) -> bool {
     if let Some((pipeline, epoch)) = pipeline_epochs.pop() {
-        *out_pipeline = mem::transmute(pipeline);
-        *out_epoch = mem::transmute(epoch);
+        *out_pipeline = pipeline;
+        *out_epoch = epoch;
         return true;
     }
     return false;
 }
 
 #[no_mangle]
 pub unsafe extern fn wr_rendered_epochs_delete(pipeline_epochs: *mut Vec<(PipelineId, Epoch)>) {
     Box::from_raw(pipeline_epochs);
 }
 
 
 struct CppNotifier {
-    window_id: u64,
+    window_id: WrWindowId,
 }
 
 unsafe impl Send for CppNotifier {}
 
 extern {
-    fn wr_notifier_new_frame_ready(window_id: u64);
-    fn wr_notifier_new_scroll_frame_ready(window_id: u64, composite_needed: bool);
-    fn wr_notifier_pipeline_size_changed(window_id: u64, pipeline: u64, new_width: f32, new_height: f32);
-    fn wr_notifier_external_event(window_id: u64, raw_event: usize);
+    fn wr_notifier_new_frame_ready(window_id: WrWindowId);
+    fn wr_notifier_new_scroll_frame_ready(window_id: WrWindowId, composite_needed: bool);
+    fn wr_notifier_external_event(window_id: WrWindowId, raw_event: usize);
 }
 
 impl webrender_traits::RenderNotifier for CppNotifier {
     fn new_frame_ready(&mut self) {
         unsafe {
             wr_notifier_new_frame_ready(self.window_id);
         }
     }
 
     fn new_scroll_frame_ready(&mut self, composite_needed: bool) {
         unsafe {
             wr_notifier_new_scroll_frame_ready(self.window_id, composite_needed);
         }
     }
 
-    fn pipeline_size_changed(&mut self,
-                             pipeline_id: PipelineId,
-                             new_size: Option<LayoutSize>) {
-        let (w, h) = if let Some(size) = new_size {
-            (size.width, size.height)
-        } else {
-            (0.0, 0.0)
-        };
-        unsafe {
-            let id = pipeline_id_to_u64(pipeline_id);
-            wr_notifier_pipeline_size_changed(self.window_id, id, w, h);
-        }
-    }
-
     fn external_event(&mut self, event: ExternalEvent) {
         unsafe {
             wr_notifier_external_event(self.window_id, event.unwrap());
         }
     }
 }
 
 // RenderThread WIP notes:
@@ -438,75 +476,113 @@ impl WrMixBlendMode
 
 #[no_mangle]
 pub extern fn wr_dp_push_stacking_context(state:&mut WrState, bounds: WrRect, overflow: WrRect, mask: *const WrImageMask, opacity: f32, transform: &LayoutTransform, mix_blend_mode: WrMixBlendMode)
 {
     assert!( unsafe { is_in_compositor_thread() });
     state.z_index += 1;
 
     let bounds = bounds.to_rect();
-    let overflow = overflow.to_rect();
+    let mut overflow = overflow.to_rect();
     let mix_blend_mode = mix_blend_mode.to_mix_blend_mode();
+    //println!("stacking context: {:?} {:?} {:?} {:?} {:?}", state.pipeline_id, bounds, overflow, mask, transform);
     // convert from the C type to the Rust type
     let mask = unsafe { mask.as_ref().map(|&WrImageMask{image, ref rect,repeat}| ImageMask{image: image, rect: rect.to_rect(), repeat: repeat}) };
 
+    let clip_region2 = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], None);
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
 
     let mut filters: Vec<FilterOp> = Vec::new();
     if opacity < 1.0 {
-        filters.push(FilterOp::Opacity(opacity));
+        filters.push(FilterOp::Opacity(PropertyBinding::Value(opacity)));
     }
 
     state.frame_builder.dl_builder.push_stacking_context(webrender_traits::ScrollPolicy::Scrollable,
                                   bounds,
-                                  clip_region,
+                                  clip_region2,
                                   state.z_index,
-                                  transform,
-                                  &LayoutTransform::identity(),
+                                  PropertyBinding::Value(*transform),
+                                  LayoutTransform::identity(),
                                   mix_blend_mode,
                                   filters);
+    state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, ServoScrollRootId(1));
 
 }
 
 #[no_mangle]
 pub extern fn wr_dp_pop_stacking_context(state: &mut WrState)
 {
     assert!( unsafe { is_in_compositor_thread() });
-    state.frame_builder.dl_builder.pop_stacking_context()
+    state.frame_builder.dl_builder.pop_scroll_layer();
+    state.frame_builder.dl_builder.pop_stacking_context();
+    //println!("pop_stacking {:?}", state.pipeline_id);
 }
 
 #[no_mangle]
-pub extern fn wr_api_set_root_pipeline(api: &mut RenderApi, pipeline_id: u64) {
-    api.set_root_pipeline(u64_to_pipeline_id(pipeline_id));
-    api.generate_frame();
+pub extern fn wr_dp_push_scroll_layer(state: &mut WrState, bounds: WrRect, overflow: WrRect, mask: Option<&WrImageMask>)
+{
+    let bounds = bounds.to_rect();
+    let overflow = overflow.to_rect();
+    let mask = mask.map(|&WrImageMask{image, ref rect,repeat}| ImageMask{image: image, rect: rect.to_rect(), repeat: repeat});
+    let clip_region = state.frame_builder.dl_builder.new_clip_region(&overflow, vec![], mask);
+    state.frame_builder.dl_builder.push_scroll_layer(clip_region, bounds.size, ServoScrollRootId(1));
 }
 
 #[no_mangle]
-pub extern fn wr_api_add_image(api: &mut RenderApi, width: u32, height: u32, stride: u32, format: ImageFormat, bytes: * const u8, size: usize) -> ImageKey {
+pub extern fn wr_dp_pop_scroll_layer(state: &mut WrState)
+{
+    assert!( unsafe { is_in_compositor_thread() });
+    state.frame_builder.dl_builder.pop_scroll_layer();
+}
+
+#[no_mangle]
+pub extern fn wr_api_set_root_pipeline(api: &mut RenderApi, pipeline_id: PipelineId) {
+    api.set_root_pipeline(pipeline_id);
+    api.generate_frame(None);
+}
+
+#[no_mangle]
+pub extern fn wr_api_add_image(api: &mut RenderApi, descriptor: &WrImageDescriptor, bytes: * const u8, size: usize) -> ImageKey {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
-    let stride_option = match stride {
-        0 => None,
-        _ => Some(stride),
-    };
-
-    api.add_image(ImageDescriptor{width: width, height: height, stride: stride_option, format: format, is_opaque: false}, ImageData::new(bytes))
+    return api.add_image(
+        ImageDescriptor {
+            width: descriptor.width,
+            height: descriptor.height,
+            stride: if descriptor.stride != 0 { Some(descriptor.stride) } else { None },
+            format: descriptor.format,
+            is_opaque: descriptor.is_opaque,
+        },
+        ImageData::new(bytes)
+    );
 }
 
 #[no_mangle]
 pub extern fn wr_api_add_external_image_texture(api: &mut RenderApi, width: u32, height: u32, format: ImageFormat, external_image_id: u64) -> ImageKey {
     assert!( unsafe { is_in_compositor_thread() });
-    api.add_image(ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false}, ImageData::External(ExternalImageId(external_image_id)))
+    unimplemented!(); // TODO
+    //api.add_image(ImageDescriptor{width:width, height:height, stride:None, format: format, is_opaque: false}, ImageData::External(ExternalImageId(external_image_id)))
 }
 
 #[no_mangle]
-pub extern fn wr_api_update_image(api: &mut RenderApi, key: ImageKey, width: u32, height: u32, format: ImageFormat, bytes: * const u8, size: usize) {
+pub extern fn wr_api_update_image(api: &mut RenderApi, key: ImageKey, descriptor: &WrImageDescriptor, bytes: * const u8, size: usize) {
     assert!( unsafe { is_in_compositor_thread() });
     let bytes = unsafe { slice::from_raw_parts(bytes, size).to_owned() };
-    api.update_image(key, ImageDescriptor{width:width, height:height, stride:None, format:format, is_opaque: false}, bytes);
+
+    api.update_image(
+        key,
+        ImageDescriptor {
+            width: descriptor.width,
+            height: descriptor.height,
+            stride: if descriptor.stride != 0 { Some(descriptor.stride) } else { None },
+            format: descriptor.format,
+            is_opaque: descriptor.is_opaque,
+        },
+        bytes
+    );
 }
 #[no_mangle]
 pub extern fn wr_api_delete_image(api: &mut RenderApi, key: ImageKey) {
     assert!( unsafe { is_in_compositor_thread() });
     api.delete_image(key)
 }
 
 #[no_mangle]
@@ -540,23 +616,22 @@ pub extern fn wr_dp_push_border(state: &
                                     left.to_border_side(),
                                     top.to_border_side(),
                                     right.to_border_side(),
                                     bottom.to_border_side(),
                                     radius.to_border_radius());
 }
 
 #[no_mangle]
-pub extern fn wr_dp_push_iframe(state: &mut WrState, rect: WrRect, clip: WrRect, layers_id: u64) {
+pub extern fn wr_dp_push_iframe(state: &mut WrState, rect: WrRect, clip: WrRect, pipeline_id: PipelineId) {
     assert!( unsafe { is_in_compositor_thread() });
 
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(),
                                                                      Vec::new(),
                                                                      None);
-    let pipeline_id = u64_to_pipeline_id(layers_id);
     state.frame_builder.dl_builder.push_iframe(rect.to_rect(),
                                                clip_region,
                                                pipeline_id);
 }
 
 #[repr(C)]
 pub struct WrColor
 {
@@ -652,97 +727,80 @@ pub struct WrImageMask
 impl WrImageMask
 {
     pub fn to_image_mask(&self) -> ImageMask
     {
         ImageMask { image: self.image, rect: self.rect.to_rect(), repeat: self.repeat }
     }
 }
 
-#[repr(C)]
-pub enum WrTextureFilter
-{
-    Linear,
-    Point,
-}
-impl WrTextureFilter
-{
-    pub fn to_image_rendering(self) -> ImageRendering
-    {
-        match self
-        {
-            WrTextureFilter::Linear => ImageRendering::Auto,
-            WrTextureFilter::Point => ImageRendering::Pixelated,
-        }
-    }
-}
-
 #[no_mangle]
-pub extern fn wr_dp_push_image(state:&mut WrState, bounds: WrRect, clip : WrRect, mask: *const WrImageMask, filter: WrTextureFilter, key: ImageKey) {
+pub extern fn wr_dp_push_image(state:&mut WrState, bounds: WrRect, clip : WrRect, mask: *const WrImageMask, filter: ImageRendering, key: ImageKey) {
     assert!( unsafe { is_in_compositor_thread() });
 
     let bounds = bounds.to_rect();
     let clip = clip.to_rect();
 
+    //println!("push_image bounds {:?} clip {:?}", bounds, clip);
     // convert from the C type to the Rust type, mapping NULL to None
     let mask = unsafe { mask.as_ref().map(|m| m.to_image_mask()) };
-    let image_rendering = filter.to_image_rendering();
+    let image_rendering = filter;
 
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip, Vec::new(), mask);
     state.frame_builder.dl_builder.push_image(
         bounds,
         clip_region,
         bounds.size,
         bounds.size,
         image_rendering,
         key
     );
 }
 
 #[no_mangle]
 pub extern fn wr_api_add_raw_font(api: &mut RenderApi,
                                   font_buffer: *mut u8,
-                                  buffer_size: usize) -> u64
+                                  buffer_size: usize) -> FontKey
 {
     assert!( unsafe { is_in_compositor_thread() });
 
     let font_slice = unsafe {
         slice::from_raw_parts(font_buffer, buffer_size as usize)
     };
     let mut font_vector = Vec::new();
     font_vector.extend_from_slice(font_slice);
 
-    return font_key_to_u64(api.add_raw_font(font_vector));
+    return api.add_raw_font(font_vector);
 }
 
 #[no_mangle]
 pub extern fn wr_dp_push_text(state: &mut WrState,
                               bounds: WrRect,
                               clip: WrRect,
                               color: WrColor,
-                              font_key: u64,
+                              font_key: FontKey,
                               glyphs: *mut GlyphInstance,
                               glyph_count: u32,
                               glyph_size: f32)
 {
     assert!( unsafe { is_in_compositor_thread() });
 
-    let font_key = u64_to_font_key(font_key);
-
     let glyph_slice = unsafe {
         slice::from_raw_parts(glyphs, glyph_count as usize)
     };
     let mut glyph_vector = Vec::new();
     glyph_vector.extend_from_slice(&glyph_slice);
 
     let colorf = ColorF::new(color.r, color.g, color.b, color.a);
 
     let clip_region = state.frame_builder.dl_builder.new_clip_region(&clip.to_rect(), Vec::new(), None);
 
+    let glyph_options = None; // TODO
     state.frame_builder.dl_builder.push_text(bounds.to_rect(),
                                              clip_region,
                                              glyph_vector,
                                              font_key,
                                              colorf,
                                              Au::from_f32_px(glyph_size),
-                                             Au::from_px(0));
+                                             Au::from_px(0),
+                                             glyph_options);
 }
 
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -5,125 +5,145 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WR_h
 #define WR_h
 
 #include "mozilla/layers/LayersMessages.h"
 #include "mozilla/gfx/Types.h"
 
+// ---
+#define WR_DECL_FFI_1(WrType, t1)                 \
+struct WrType {                                   \
+  t1 mHandle;                                     \
+  bool operator==(const WrType& rhs) const {      \
+    return mHandle == rhs.mHandle;                \
+  }                                               \
+  bool operator!=(const WrType& rhs) const {      \
+    return mHandle != rhs.mHandle;                \
+  }                                               \
+  bool operator<(const WrType& rhs) const {       \
+    return mHandle < rhs.mHandle;                 \
+  }                                               \
+};                                                \
+// ---
+
+// ---
+#define WR_DECL_FFI_2(WrType, t1, t2)             \
+struct WrType {                                   \
+  t1 mNamespace;                                  \
+  t2 mHandle;                                     \
+  bool operator==(const WrType& rhs) const {      \
+    return mNamespace == rhs.mNamespace           \
+        && mHandle == rhs.mHandle;                \
+  }                                               \
+  bool operator!=(const WrType& rhs) const {      \
+    return mNamespace != rhs.mNamespace           \
+        || mHandle != rhs.mHandle;                \
+  }                                               \
+};                                                \
+// ---
+
+
 extern "C" {
 
+// If you modify any of the declarations below, make sure to update the
+// serialization code in WebRenderMessageUtils.h and the rust bindings.
+
+WR_DECL_FFI_1(WrEpoch, uint32_t)
+WR_DECL_FFI_1(WrWindowId, uint64_t)
+
+WR_DECL_FFI_2(WrPipelineId, uint32_t, uint32_t)
+WR_DECL_FFI_2(WrImageKey, uint32_t, uint32_t)
+WR_DECL_FFI_2(WrFontKey, uint32_t, uint32_t)
+
+#undef WR_DECL_FFI_1
+#undef WR_DECL_FFI_2
+
 // ----
 // Functions invoked from Rust code
 // ----
 
 bool is_in_compositor_thread();
 bool is_in_render_thread();
 void* get_proc_address_from_glcontext(void* glcontext_ptr, const char* procname);
 
 // -----
 // Enums used in C++ code with corresponding enums in Rust code
 // -----
 
-enum class WrImageFormat
+enum class WrImageFormat: uint32_t
 {
-  Invalid,
-  A8,
-  RGB8,
-  RGBA8,
-  RGBAF32,
+  Invalid = 0,
+  A8      = 1,
+  RGB8    = 2,
+  RGBA8   = 3,
+  RGBAF32 = 4,
 
   Sentinel /* this must be last, for IPC serialization purposes */
 };
 
-enum class WrBorderStyle
+enum class WrBorderStyle: uint32_t
 {
-  None,
-  Solid,
-  Double,
-  Dotted,
-  Dashed,
-  Hidden,
-  Groove,
-  Ridge,
-  Inset,
-  Outset,
+  None    = 0,
+  Solid   = 1,
+  Double  = 2,
+  Dotted  = 3,
+  Dashed  = 4,
+  Hidden  = 5,
+  Groove  = 6,
+  Ridge   = 7,
+  Inset   = 8,
+  Outset  = 9,
 
   Sentinel /* this must be last, for IPC serialization purposes */
 };
 
-enum class WrTextureFilter
+enum class WrImageRendering: uint32_t
 {
-  Linear,
-  Point,
+  Auto        = 0,
+  CrispEdges  = 1,
+  Pixelated   = 2,
 
   Sentinel /* this must be last, for IPC serialization purposes */
 };
 
 enum class WrExternalImageIdType
 {
   TEXTURE_HANDLE, // Currently, we only support gl texture handle.
   // TODO(Jerry): handle shmem or cpu raw buffers.
   //// MEM_OR_SHMEM,
 };
 
-enum class WrMixBlendMode
+enum class WrMixBlendMode: uint32_t
 {
-  Normal,
-  Multiply,
-  Screen,
-  Overlay,
-  Darken,
-  Lighten,
-  ColorDodge,
-  ColorBurn,
-  HardLight,
-  SoftLight,
-  Difference,
-  Exclusion,
-  Hue,
-  Saturation,
-  Color,
-  Luminosity,
+  Normal      = 0,
+  Multiply    = 1,
+  Screen      = 2,
+  Overlay     = 3,
+  Darken      = 4,
+  Lighten     = 5,
+  ColorDodge  = 6,
+  ColorBurn   = 7,
+  HardLight   = 8,
+  SoftLight   = 9,
+  Difference  = 10,
+  Exclusion   = 11,
+  Hue         = 12,
+  Saturation  = 13,
+  Color       = 14,
+  Luminosity  = 15,
 
   Sentinel /* this must be last, for IPC serialization purposes */
 };
 
-#ifdef DEBUG
-// This ensures that the size of |enum class| and |enum| are the same, because
-// we use |enum class| in this file (to avoid polluting the global namespace)
-// but Rust assumes |enum|. If there is a size mismatch that could lead to
-// problems with values being corrupted across the language boundary.
-class DebugEnumSizeChecker
-{ // scope the enum to the class
-  enum DummyWrImageFormatEnum
-  {
-    Invalid,
-    A8,
-    RGB8,
-    RGBA8,
-    RGBAF32,
-    Sentinel
-  };
-
-  static_assert(sizeof(WrImageFormat) == sizeof(DummyWrImageFormatEnum),
-    "Size of enum doesn't match size of enum class!");
-};
-#endif
-
 // -----
 // Typedefs for struct fields and function signatures below.
 // -----
 
-typedef uint64_t WrWindowId;
-typedef uint64_t WrImageKey;
-typedef uint64_t WrFontKey;
-typedef uint64_t WrPipelineId;
-typedef uint32_t WrEpoch;
 typedef uint64_t WrImageIdType;
 
 // -----
 // Structs used in C++ code with corresponding types in Rust code
 // -----
 
 struct WrColor
 {
@@ -270,16 +290,24 @@ typedef void (*ReleaseExternalImageCallb
 struct WrExternalImageIdHandler
 {
   void* ExternalImageObj;
   LockExternalImageCallback lock_func;
   UnlockExternalImageCallback unlock_func;
   ReleaseExternalImageCallback release_func;
 };
 
+struct WrImageDescriptor {
+    WrImageFormat format;
+    uint32_t width;
+    uint32_t height;
+    uint32_t stride;
+    bool is_opaque;
+};
+
 // -----
 // Functions exposed by the webrender API
 // -----
 
 // Some useful defines to stub out webrender binding functions for when we
 // build gecko without webrender. We try to tell the compiler these functions
 // are unreachable in that case, but VC++ emits a warning if it finds any
 // unreachable functions invoked from destructors. That warning gets turned into
@@ -333,57 +361,56 @@ wr_rendered_epochs_next(WrRenderedEpochs
 
 WR_INLINE void
 wr_rendered_epochs_delete(WrRenderedEpochs* pipeline_epochs) WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE void
 wr_gl_init(void* aGLContext)
 WR_FUNC;
 
-WR_INLINE void
+WR_INLINE bool
 wr_window_new(WrWindowId window_id, bool enable_profiler, WrAPI** out_api,
               WrRenderer** out_renderer)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_delete(WrAPI* api)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE WrImageKey
-wr_api_add_image(WrAPI* api, uint32_t width, uint32_t height,
-                 uint32_t stride, WrImageFormat format, uint8_t *bytes,
-                 size_t size)
+wr_api_add_image(WrAPI* api, const WrImageDescriptor* descriptor, uint8_t *buffer, size_t buffer_size)
 WR_FUNC;
 
 WR_INLINE WrImageKey
 wr_api_add_external_image_texture(WrAPI* api, uint32_t width, uint32_t height,
                                   WrImageFormat format, uint64_t external_image_id)
 WR_FUNC;
 
 //TODO(Jerry): handle shmem in WR
 //// WR_INLINE WrImageKey
 //// wr_api_add_external_image_buffer(WrAPI* api, uint32_t width, uint32_t height, uint32_t stride,
 ////                                  WrImageFormat format, uint8_t *bytes, size_t size)
 //// WR_FUNC;
 
 WR_INLINE void
-wr_api_update_image(WrAPI* api, WrImageKey key, uint32_t width, uint32_t height,
-                    WrImageFormat format, uint8_t *bytes, size_t size)
+wr_api_update_image(WrAPI* api, WrImageKey key,
+                    const WrImageDescriptor* descriptor,
+                    uint8_t *bytes, size_t size)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_delete_image(WrAPI* api, WrImageKey key)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_set_root_pipeline(WrAPI* api, WrPipelineId pipeline_id)
 WR_FUNC;
 
 WR_INLINE void
-wr_api_set_root_display_list(WrAPI* api, WrState* state, uint32_t epoch, float w, float h)
+wr_api_set_root_display_list(WrAPI* api, WrState* state, WrEpoch epoch, float w, float h)
 WR_FUNC;
 
 WR_INLINE void
 wr_api_send_external_event(WrAPI* api, uintptr_t evt)
 WR_DESTRUCTOR_SAFE_FUNC;
 
 WR_INLINE WrFontKey
 wr_api_add_raw_font(WrAPI* api, uint8_t* font_buffer, size_t buffer_size)
@@ -405,21 +432,31 @@ wr_dp_push_stacking_context(WrState *wrS
 WR_FUNC;
 
 //XXX: matrix should use a proper type
 WR_INLINE void
 wr_dp_pop_stacking_context(WrState *wrState)
 WR_FUNC;
 
 WR_INLINE void
+wr_dp_push_scroll_layer(WrState *wrState, WrRect bounds,
+                        WrRect overflow, const WrImageMask *mask)
+WR_FUNC;
+
+WR_INLINE void
+wr_dp_pop_scroll_layer(WrState *wrState)
+WR_FUNC;
+
+
+WR_INLINE void
 wr_dp_begin(WrState* wrState, uint32_t width, uint32_t height)
 WR_FUNC;
 
 WR_INLINE void
-wr_dp_end(WrState* builder, WrAPI* api, uint32_t epoch)
+wr_dp_end(WrState* builder, WrAPI* api, WrEpoch epoch)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_rect(WrState* wrState, WrRect bounds, WrRect clip,
                 WrColor color)
 WR_FUNC;
 
 WR_INLINE void
@@ -431,17 +468,17 @@ WR_FUNC;
 WR_INLINE void
 wr_dp_push_border(WrState* wrState, WrRect bounds, WrRect clip,
                   WrBorderSide top, WrBorderSide right, WrBorderSide bottom, WrBorderSide left,
                   WrBorderRadius radius)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_image(WrState* wrState, WrRect bounds, WrRect clip,
-                 const WrImageMask* mask, WrTextureFilter filter, WrImageKey key)
+                 const WrImageMask* mask, WrImageRendering filter, WrImageKey key)
 WR_FUNC;
 
 WR_INLINE void
 wr_dp_push_iframe(WrState* wrState, WrRect bounds, WrRect clip, WrPipelineId layers_id)
 WR_FUNC;
 
 // It is the responsibility of the caller to manage the dst_buffer memory
 // and also free it at the proper time.
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1340,17 +1340,17 @@ void nsBaseWidget::CreateCompositor(int 
                           mInitialZoomConstraints->mViewID,
                           Some(mInitialZoomConstraints->mConstraints));
     mInitialZoomConstraints.reset();
   }
 
   if (lm->AsWebRenderLayerManager()) {
     TextureFactoryIdentifier textureFactoryIdentifier;
     lm->AsWebRenderLayerManager()->Initialize(mCompositorBridgeChild,
-                                              mCompositorSession->RootLayerTreeId(),
+                                              wr::AsPipelineId(mCompositorSession->RootLayerTreeId()),
                                               &textureFactoryIdentifier);
     ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier);
     gfx::VRManagerChild::IdentifyTextureHost(textureFactoryIdentifier);
   }
 
   ShadowLayerForwarder* lf = lm->AsShadowForwarder();
   if (lf) {
     // lf is non-null if we are creating a ClientLayerManager above