Bug 1048110 - Expand complex visible regions if we're going to be resampling when using tiling. r=Bas
authorMatt Woodrow <mwoodrow@mozilla.com>
Mon, 04 Aug 2014 15:29:55 +1200
changeset 220106 a287654390b194d5576d9f6536ef216208c9b611
parent 220105 23ea95cbd92f3d489d8dd2e0a1791105020875f7
child 220107 da90bd5e5145582e21926a6823f3a74102e311ab
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1048110
milestone34.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 1048110 - Expand complex visible regions if we're going to be resampling when using tiling. r=Bas
gfx/layers/Layers.h
gfx/layers/client/ClientTiledThebesLayer.cpp
gfx/layers/client/ClientTiledThebesLayer.h
gfx/layers/client/TiledContentClient.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/ContentHost.h
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/ImageHost.h
gfx/layers/composite/ThebesLayerComposite.cpp
gfx/layers/composite/ThebesLayerComposite.h
gfx/layers/composite/TiledContentHost.cpp
gfx/layers/composite/TiledContentHost.h
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1429,16 +1429,24 @@ public:
 
   void Mutated()
   {
     mManager->Mutated(this);
   }
 
   virtual int32_t GetMaxLayerSize() { return Manager()->GetMaxTextureSize(); }
 
+  /**
+   * Returns true if this layer's effective transform is not just
+   * a translation by integers, or if this layer or some ancestor layer
+   * is marked as having a transform that may change without a full layer
+   * transaction.
+   */
+  bool MayResample();
+
 protected:
   Layer(LayerManager* aManager, void* aImplData);
 
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~Layer();
 
   /**
    * We can snap layer transforms for two reasons:
@@ -1477,24 +1485,16 @@ protected:
    * boundaries in the destination surface.
    * @param aResidualTransform a transform to apply before the result transform
    * in order to get the results to completely match aTransform.
    */
   gfx::Matrix4x4 SnapTransform(const gfx::Matrix4x4& aTransform,
                                const gfxRect& aSnapRect,
                                gfx::Matrix* aResidualTransform);
 
-  /**
-   * Returns true if this layer's effective transform is not just
-   * a translation by integers, or if this layer or some ancestor layer
-   * is marked as having a transform that may change without a full layer
-   * transaction.
-   */
-  bool MayResample();
-
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
   gfx::UserData mUserData;
   nsIntRegion mVisibleRegion;
--- a/gfx/layers/client/ClientTiledThebesLayer.cpp
+++ b/gfx/layers/client/ClientTiledThebesLayer.cpp
@@ -190,16 +190,17 @@ ClientTiledThebesLayer::UseFastPath()
                                  || gfxPrefs::UseLowPrecisionBuffer()
                                  || !parentMetrics.mCriticalDisplayPort.IsEmpty();
   bool isFixed = GetIsFixedPosition() || GetParent()->GetIsFixedPosition();
   return !multipleTransactionsNeeded || isFixed || parentMetrics.mDisplayPort.IsEmpty();
 }
 
 bool
 ClientTiledThebesLayer::RenderHighPrecision(nsIntRegion& aInvalidRegion,
+                                            const nsIntRegion& aVisibleRegion,
                                             LayerManager::DrawThebesLayerCallback aCallback,
                                             void* aCallbackData)
 {
   // If we have no high-precision stuff to draw, or we have started drawing low-precision
   // already, then we shouldn't do anything there.
   if (aInvalidRegion.IsEmpty() || mPaintData.mLowPrecisionPaintCount != 0) {
     return false;
   }
@@ -208,70 +209,71 @@ ClientTiledThebesLayer::RenderHighPrecis
   // in a reftest scenario (that's what the HasShadowManager() check is for).
   if (gfxPrefs::UseProgressiveTilePainting() &&
       !ClientManager()->HasShadowTarget() &&
       mContentClient->mTiledBuffer.GetFrameResolution() == mPaintData.mResolution) {
     // Store the old valid region, then clear it before painting.
     // We clip the old valid region to the visible region, as it only gets
     // used to decide stale content (currently valid and previously visible)
     nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
-    oldValidRegion.And(oldValidRegion, mVisibleRegion);
+    oldValidRegion.And(oldValidRegion, aVisibleRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       oldValidRegion.And(oldValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
 
     TILING_LOG("TILING %p: Progressive update with old valid region %s\n", this, Stringify(oldValidRegion).c_str());
 
     return mContentClient->mTiledBuffer.ProgressiveUpdate(mValidRegion, aInvalidRegion,
                       oldValidRegion, &mPaintData, aCallback, aCallbackData);
   }
 
   // Otherwise do a non-progressive paint
 
-  mValidRegion = mVisibleRegion;
+  mValidRegion = aVisibleRegion;
   if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
     mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
   }
 
   TILING_LOG("TILING %p: Non-progressive paint invalid region %s\n", this, Stringify(aInvalidRegion).c_str());
   TILING_LOG("TILING %p: Non-progressive paint new valid region %s\n", this, Stringify(mValidRegion).c_str());
 
   mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
   mContentClient->mTiledBuffer.PaintThebes(mValidRegion, aInvalidRegion, aCallback, aCallbackData);
   return true;
 }
 
 bool
 ClientTiledThebesLayer::RenderLowPrecision(nsIntRegion& aInvalidRegion,
+                                           const nsIntRegion& aVisibleRegion,
                                            LayerManager::DrawThebesLayerCallback aCallback,
                                            void* aCallbackData)
 {
   // Render the low precision buffer, if the visible region is larger than the
   // critical display port.
-  if (!nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(mVisibleRegion)) {
+  if (!nsIntRegion(LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort)).Contains(aVisibleRegion)) {
     nsIntRegion oldValidRegion = mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
-    oldValidRegion.And(oldValidRegion, mVisibleRegion);
+    oldValidRegion.And(oldValidRegion, aVisibleRegion);
 
     bool updatedBuffer = false;
 
     // If the frame resolution or format have changed, invalidate the buffer
     if (mContentClient->mLowPrecisionTiledBuffer.GetFrameResolution() != mPaintData.mResolution ||
         mContentClient->mLowPrecisionTiledBuffer.HasFormatChanged()) {
       if (!mLowPrecisionValidRegion.IsEmpty()) {
         updatedBuffer = true;
       }
       oldValidRegion.SetEmpty();
       mLowPrecisionValidRegion.SetEmpty();
       mContentClient->mLowPrecisionTiledBuffer.SetFrameResolution(mPaintData.mResolution);
-      aInvalidRegion = mVisibleRegion;
+      aInvalidRegion = aVisibleRegion;
     }
 
     // Invalidate previously valid content that is no longer visible
     if (mPaintData.mLowPrecisionPaintCount == 1) {
-      mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, mVisibleRegion);
+      mLowPrecisionValidRegion.And(mLowPrecisionValidRegion, aVisibleRegion);
     }
     mPaintData.mLowPrecisionPaintCount++;
 
     // Remove the valid high-precision region from the invalid low-precision
     // region. We don't want to spend time drawing things twice.
     aInvalidRegion.Sub(aInvalidRegion, mValidRegion);
 
     TILING_LOG("TILING %p: Progressive paint: low-precision invalid region is %s\n", this, Stringify(aInvalidRegion).c_str());
@@ -330,50 +332,56 @@ ClientTiledThebesLayer::RenderLayer()
   if (mContentClient->mTiledBuffer.HasFormatChanged()) {
     mValidRegion = nsIntRegion();
   }
 
   TILING_LOG("TILING %p: Initial visible region %s\n", this, Stringify(mVisibleRegion).c_str());
   TILING_LOG("TILING %p: Initial valid region %s\n", this, Stringify(mValidRegion).c_str());
   TILING_LOG("TILING %p: Initial low-precision valid region %s\n", this, Stringify(mLowPrecisionValidRegion).c_str());
 
+  nsIntRegion neededRegion = mVisibleRegion;
+  if (neededRegion.GetNumRects() > 1 &&
+      MayResample()) {
+    neededRegion = neededRegion.GetBounds();
+  }
+
   nsIntRegion invalidRegion;
-  invalidRegion.Sub(mVisibleRegion, mValidRegion);
+  invalidRegion.Sub(neededRegion, mValidRegion);
   if (invalidRegion.IsEmpty()) {
     EndPaint();
     return;
   }
 
   if (!ClientManager()->IsRepeatTransaction()) {
     // Only paint the mask layer on the first transaction.
     if (GetMaskLayer()) {
       ToClientLayer(GetMaskLayer())->RenderLayer();
     }
 
     // In some cases we can take a fast path and just be done with it.
     if (UseFastPath()) {
       TILING_LOG("TILING %p: Taking fast-path\n", this);
-      mValidRegion = mVisibleRegion;
+      mValidRegion = neededRegion;
       mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
       ClientManager()->Hold(this);
       mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
       return;
     }
 
     // For more complex cases we need to calculate a bunch of metrics before we
     // can do the paint.
     BeginPaint();
     if (mPaintData.mPaintFinished) {
       return;
     }
 
     // Make sure that tiles that fall outside of the visible region or outside of the
     // critical displayport are discarded on the first update. Also make sure that we
     // only draw stuff inside the critical displayport on the first update.
-    mValidRegion.And(mValidRegion, mVisibleRegion);
+    mValidRegion.And(mValidRegion, neededRegion);
     if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
       mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
       invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
     }
 
     TILING_LOG("TILING %p: First-transaction valid region %s\n", this, Stringify(mValidRegion).c_str());
     TILING_LOG("TILING %p: First-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   } else {
@@ -382,22 +390,24 @@ ClientTiledThebesLayer::RenderLayer()
     }
     TILING_LOG("TILING %p: Repeat-transaction invalid region %s\n", this, Stringify(invalidRegion).c_str());
   }
 
   nsIntRegion lowPrecisionInvalidRegion;
   if (gfxPrefs::UseLowPrecisionBuffer()) {
     // Calculate the invalid region for the low precision buffer. Make sure
     // to remove the valid high-precision area so we don't double-paint it.
-    lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
+    lowPrecisionInvalidRegion.Sub(neededRegion, mLowPrecisionValidRegion);
     lowPrecisionInvalidRegion.Sub(lowPrecisionInvalidRegion, mValidRegion);
   }
   TILING_LOG("TILING %p: Low-precision invalid region %s\n", this, Stringify(lowPrecisionInvalidRegion).c_str());
 
-  bool updatedHighPrecision = RenderHighPrecision(invalidRegion, callback, data);
+  bool updatedHighPrecision = RenderHighPrecision(invalidRegion,
+                                                  neededRegion,
+                                                  callback, data);
   if (updatedHighPrecision) {
     ClientManager()->Hold(this);
     mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
 
     if (!mPaintData.mPaintFinished) {
       // There is still more high-res stuff to paint, so we're not
       // done yet. A subsequent transaction will take care of this.
       ClientManager()->SetRepeatTransaction();
@@ -418,17 +428,19 @@ ClientTiledThebesLayer::RenderLayer()
     // as high-precision updates.
     TILING_LOG("TILING %p: Scheduling repeat transaction for low-precision painting\n", this);
     ClientManager()->SetRepeatTransaction();
     mPaintData.mLowPrecisionPaintCount = 1;
     mPaintData.mPaintFinished = false;
     return;
   }
 
-  bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion, callback, data);
+  bool updatedLowPrecision = RenderLowPrecision(lowPrecisionInvalidRegion,
+                                                neededRegion,
+                                                callback, data);
   if (updatedLowPrecision) {
     ClientManager()->Hold(this);
     mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
 
     if (!mPaintData.mPaintFinished) {
       // There is still more low-res stuff to paint, so we're not
       // done yet. A subsequent transaction will take care of this.
       ClientManager()->SetRepeatTransaction();
--- a/gfx/layers/client/ClientTiledThebesLayer.h
+++ b/gfx/layers/client/ClientTiledThebesLayer.h
@@ -98,24 +98,26 @@ private:
    */
   bool UseFastPath();
 
   /**
    * Helper function to do the high-precision paint.
    * This function returns true if it updated the paint buffer.
    */
   bool RenderHighPrecision(nsIntRegion& aInvalidRegion,
+                           const nsIntRegion& aVisibleRegion,
                            LayerManager::DrawThebesLayerCallback aCallback,
                            void* aCallbackData);
 
   /**
    * Helper function to do the low-precision paint.
    * This function returns true if it updated the paint buffer.
    */
   bool RenderLowPrecision(nsIntRegion& aInvalidRegion,
+                          const nsIntRegion& aVisibleRegion,
                           LayerManager::DrawThebesLayerCallback aCallback,
                           void* aCallbackData);
 
   /**
    * This causes the paint to be marked as finished, and updates any data
    * necessary to persist until the next paint.
    */
   void EndPaint();
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -322,16 +322,22 @@ ClientTiledLayerBuffer::GetContentType(S
       if (!mThebesLayer->GetParent() ||
           !mThebesLayer->GetParent()->SupportsComponentAlphaChildren() ||
           !gfxPrefs::TiledDrawTargetEnabled()) {
         mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
       } else {
         content = gfxContentType::COLOR;
       }
 #endif
+  } else if (mode == SurfaceMode::SURFACE_OPAQUE) {
+    if (mThebesLayer->GetVisibleRegion().GetNumRects() > 1 &&
+        mThebesLayer->MayResample()) {
+      mode = SurfaceMode::SURFACE_SINGLE_CHANNEL_ALPHA;
+      content = gfxContentType::COLOR_ALPHA;
+    }
   }
 
   if (aMode) {
     *aMode = mode;
   }
   return content;
 }
 
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -32,24 +32,16 @@ struct nsIntRect;
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 class DataSourceSurface;
 }
 
 namespace layers {
 
-// Some properties of a Layer required for tiling
-struct TiledLayerProperties
-{
-  nsIntRegion mVisibleRegion;
-  nsIntRegion mValidRegion;
-  CSSToScreenScale mEffectiveResolution;
-};
-
 class Layer;
 class SurfaceDescriptor;
 class Compositor;
 class ISurfaceAllocator;
 class ThebesBufferData;
 class TiledLayerComposer;
 class CompositableParentManager;
 class PCompositableParent;
@@ -116,18 +108,17 @@ public:
   virtual void SetCompositor(Compositor* aCompositor);
 
   // composite the contents of this buffer host to the compositor's surface
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
-                         const nsIntRegion* aVisibleRegion = nullptr,
-                         TiledLayerProperties* aLayerProperties = nullptr) = 0;
+                         const nsIntRegion* aVisibleRegion = nullptr) = 0;
 
   /**
    * Update the content host.
    * aUpdated is the region which should be updated
    * aUpdatedRegionBack is the region in aNewBackResult which has been updated
    */
   virtual bool UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -22,32 +22,30 @@ namespace gfx {
 class Matrix4x4;
 }
 using namespace gfx;
 
 namespace layers {
 
 ContentHostBase::ContentHostBase(const TextureInfo& aTextureInfo)
   : ContentHost(aTextureInfo)
-  , mPaintWillResample(false)
   , mInitialised(false)
 {}
 
 ContentHostBase::~ContentHostBase()
 {
 }
 
 void
 ContentHostBase::Composite(EffectChain& aEffectChain,
                            float aOpacity,
                            const gfx::Matrix4x4& aTransform,
                            const Filter& aFilter,
                            const Rect& aClipRect,
-                           const nsIntRegion* aVisibleRegion,
-                           TiledLayerProperties* aLayerProperties)
+                           const nsIntRegion* aVisibleRegion)
 {
   NS_ASSERTION(aVisibleRegion, "Requires a visible region");
 
   AutoLockCompositableHost lock(this);
   if (lock.Failed()) {
     return;
   }
 
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -59,22 +59,26 @@ public:
   // tiling.
   virtual TiledLayerComposer* AsTiledLayerComposer() { return nullptr; }
 
   virtual bool UpdateThebes(const ThebesBufferData& aData,
                             const nsIntRegion& aUpdated,
                             const nsIntRegion& aOldValidRegionBack,
                             nsIntRegion* aUpdatedRegionBack) = 0;
 
-  virtual void SetPaintWillResample(bool aResample) { }
+  virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
+  bool PaintWillResample() { return mPaintWillResample; }
 
 protected:
   ContentHost(const TextureInfo& aTextureInfo)
     : CompositableHost(aTextureInfo)
+    , mPaintWillResample(false)
   {}
+
+  bool mPaintWillResample;
 };
 
 /**
  * Base class for non-tiled ContentHosts.
  *
  * Ownership of the SurfaceDescriptor and the resources it represents is passed
  * from the ContentClient to the ContentHost when the TextureClient/Hosts are
  * created, that is recevied here by SetTextureHosts which assigns one or two
@@ -92,37 +96,32 @@ public:
   ContentHostBase(const TextureInfo& aTextureInfo);
   virtual ~ContentHostBase();
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
-                         const nsIntRegion* aVisibleRegion = nullptr,
-                         TiledLayerProperties* aLayerProperties = nullptr);
-
-  virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }
+                         const nsIntRegion* aVisibleRegion = nullptr);
 
   virtual NewTextureSource* GetTextureSource() = 0;
   virtual NewTextureSource* GetTextureSourceOnWhite() = 0;
 
   virtual TemporaryRef<TexturedEffect> GenEffect(const gfx::Filter& aFilter) MOZ_OVERRIDE;
 
 protected:
   virtual nsIntPoint GetOriginOffset()
   {
     return mBufferRect.TopLeft() - mBufferRotation;
   }
 
-  bool PaintWillResample() { return mPaintWillResample; }
 
   nsIntRect mBufferRect;
   nsIntPoint mBufferRotation;
-  bool mPaintWillResample;
   bool mInitialised;
 };
 
 /**
  * Shared ContentHostBase implementation for content hosts that
  * use up to two TextureHosts.
  */
 class ContentHostTexture : public ContentHostBase
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -60,18 +60,17 @@ ImageHost::GetAsTextureHost()
 }
 
 void
 ImageHost::Composite(EffectChain& aEffectChain,
                      float aOpacity,
                      const gfx::Matrix4x4& aTransform,
                      const gfx::Filter& aFilter,
                      const gfx::Rect& aClipRect,
-                     const nsIntRegion* aVisibleRegion,
-                     TiledLayerProperties* aLayerProperties)
+                     const nsIntRegion* aVisibleRegion)
 {
   if (!GetCompositor()) {
     // should only happen when a tab is dragged to another window and
     // async-video is still sending frames but we haven't attached the
     // set the new compositor yet.
     return;
   }
   if (!mFrontBuffer) {
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -45,18 +45,17 @@ public:
 
   virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
-                         const nsIntRegion* aVisibleRegion = nullptr,
-                         TiledLayerProperties* aLayerProperties = nullptr) MOZ_OVERRIDE;
+                         const nsIntRegion* aVisibleRegion = nullptr) MOZ_OVERRIDE;
 
   virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
   virtual void RemoveTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
 
   virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
--- a/gfx/layers/composite/ThebesLayerComposite.cpp
+++ b/gfx/layers/composite/ThebesLayerComposite.cpp
@@ -33,17 +33,16 @@ namespace mozilla {
 namespace layers {
 
 class TiledLayerComposer;
 
 ThebesLayerComposite::ThebesLayerComposite(LayerManagerComposite *aManager)
   : ThebesLayer(aManager, nullptr)
   , LayerComposite(aManager)
   , mBuffer(nullptr)
-  , mRequiresTiledProperties(false)
 {
   MOZ_COUNT_CTOR(ThebesLayerComposite);
   mImplData = static_cast<LayerComposite*>(this);
 }
 
 ThebesLayerComposite::~ThebesLayerComposite()
 {
   MOZ_COUNT_DTOR(ThebesLayerComposite);
@@ -130,39 +129,26 @@ ThebesLayerComposite::RenderLayer(const 
 #endif
 
   EffectChain effectChain(this);
   LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain);
   AddBlendModeEffect(effectChain);
 
   const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
 
-  TiledLayerProperties tiledLayerProps;
-  if (mRequiresTiledProperties) {
-    tiledLayerProps.mVisibleRegion = visibleRegion;
-    tiledLayerProps.mEffectiveResolution = GetEffectiveResolution();
-    tiledLayerProps.mValidRegion = mValidRegion;
-  }
-
   mBuffer->SetPaintWillResample(MayResample());
 
   mBuffer->Composite(effectChain,
                      GetEffectiveOpacity(),
                      GetEffectiveTransform(),
                      GetEffectFilter(),
                      clipRect,
-                     &visibleRegion,
-                     mRequiresTiledProperties ? &tiledLayerProps
-                                              : nullptr);
+                     &visibleRegion);
   mBuffer->BumpFlashCounter();
 
-  if (mRequiresTiledProperties) {
-    mValidRegion = tiledLayerProps.mValidRegion;
-  }
-
   mCompositeManager->GetCompositor()->MakeCurrent();
 }
 
 CompositableHost*
 ThebesLayerComposite::GetCompositableHost()
 {
   if (mBuffer && mBuffer->IsAttached()) {
     return mBuffer.get();
--- a/gfx/layers/composite/ThebesLayerComposite.h
+++ b/gfx/layers/composite/ThebesLayerComposite.h
@@ -60,18 +60,16 @@ public:
   virtual void CleanupResources() MOZ_OVERRIDE;
 
   virtual void GenEffectChain(EffectChain& aEffect) MOZ_OVERRIDE;
 
   virtual bool SetCompositableHost(CompositableHost* aHost) MOZ_OVERRIDE;
 
   virtual LayerComposite* AsLayerComposite() MOZ_OVERRIDE { return this; }
 
-  void EnsureTiled() { mRequiresTiledProperties = true; }
-
   virtual void InvalidateRegion(const nsIntRegion& aRegion)
   {
     NS_RUNTIMEABORT("ThebesLayerComposites can't fill invalidated regions");
   }
 
   void SetValidRegion(const nsIntRegion& aRegion)
   {
     MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ValidRegion", this));
@@ -87,14 +85,13 @@ protected:
 
 private:
   gfx::Filter GetEffectFilter() { return gfx::Filter::LINEAR; }
 
   CSSToScreenScale GetEffectiveResolution();
 
 private:
   RefPtr<ContentHost> mBuffer;
-  bool mRequiresTiledProperties;
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_ThebesLayerComposite_H */
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -236,17 +236,16 @@ TiledContentHost::~TiledContentHost()
 }
 
 void
 TiledContentHost::Attach(Layer* aLayer,
                          Compositor* aCompositor,
                          AttachFlags aFlags /* = NO_FLAGS */)
 {
   CompositableHost::Attach(aLayer, aCompositor, aFlags);
-  static_cast<ThebesLayerComposite*>(aLayer)->EnsureTiled();
 }
 
 void
 TiledContentHost::Detach(Layer* aLayer,
                          AttachFlags aFlags /* = NO_FLAGS */)
 {
   if (!mKeepAttached || aLayer == mLayer || aFlags & FORCE_DETACH) {
 
@@ -319,21 +318,18 @@ TiledContentHost::UseTiledLayerBuffer(IS
 }
 
 void
 TiledContentHost::Composite(EffectChain& aEffectChain,
                             float aOpacity,
                             const gfx::Matrix4x4& aTransform,
                             const gfx::Filter& aFilter,
                             const gfx::Rect& aClipRect,
-                            const nsIntRegion* aVisibleRegion /* = nullptr */,
-                            TiledLayerProperties* aLayerProperties /* = nullptr */)
+                            const nsIntRegion* aVisibleRegion /* = nullptr */)
 {
-  MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost");
-
   if (mPendingUpload) {
     mTiledBuffer.SetCompositor(mCompositor);
     mTiledBuffer.Upload();
 
     // For a single-buffered tiled buffer, Upload will upload the shared memory
     // surface to texture memory and we no longer need to read from them.
     if (!mTiledBuffer.HasDoubleBufferedTiles()) {
       mTiledBuffer.ReadUnlock();
@@ -369,23 +365,35 @@ TiledContentHost::Composite(EffectChain&
         break;
       }
     }
   }
   float lowPrecisionOpacityReduction =
         (aOpacity == 1.0f && backgroundColor.a == 1.0f)
         ? gfxPrefs::LowPrecisionOpacity() : 1.0f;
 
+  nsIntRegion tmpRegion;
+  const nsIntRegion* renderRegion;
+  if (PaintWillResample()) {
+    // If we're resampling, then the texture image will contain exactly the
+    // entire visible region's bounds, and we should draw it all in one quad
+    // to avoid unexpected aliasing.
+    tmpRegion = aVisibleRegion->GetBounds();
+    renderRegion = &tmpRegion;
+  } else {
+    renderRegion = aVisibleRegion;
+  }
+
   // Render the low and high precision buffers.
   RenderLayerBuffer(mLowPrecisionTiledBuffer,
                     lowPrecisionOpacityReduction < 1.0f ? &backgroundColor : nullptr,
                     aEffectChain, lowPrecisionOpacityReduction * aOpacity,
-                    aFilter, aClipRect, aLayerProperties->mVisibleRegion, aTransform);
+                    aFilter, aClipRect, *renderRegion, aTransform);
   RenderLayerBuffer(mTiledBuffer, nullptr, aEffectChain, aOpacity, aFilter,
-                    aClipRect, aLayerProperties->mVisibleRegion, aTransform);
+                    aClipRect, *renderRegion, aTransform);
 
   // Now release the old buffer if it had double-buffered tiles, as we can
   // guarantee that they're no longer on the screen (and so any locks that may
   // have been held have been released).
   if (mPendingUpload && mOldTiledBuffer.HasDoubleBufferedTiles()) {
     mOldTiledBuffer.ReadUnlock();
     mOldTiledBuffer = TiledLayerBufferComposite();
   }
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -218,18 +218,17 @@ public:
   void UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
                            const SurfaceDescriptorTiles& aTiledDescriptor);
 
   void Composite(EffectChain& aEffectChain,
                  float aOpacity,
                  const gfx::Matrix4x4& aTransform,
                  const gfx::Filter& aFilter,
                  const gfx::Rect& aClipRect,
-                 const nsIntRegion* aVisibleRegion = nullptr,
-                 TiledLayerProperties* aLayerProperties = nullptr);
+                 const nsIntRegion* aVisibleRegion = nullptr);
 
   virtual CompositableType GetType() { return CompositableType::BUFFER_TILED; }
 
   virtual TiledLayerComposer* AsTiledLayerComposer() MOZ_OVERRIDE { return this; }
 
   virtual void Attach(Layer* aLayer,
                       Compositor* aCompositor,
                       AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;