Don't treat resampled layers as entirely opaque. (bug 1412078, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Mon, 06 Nov 2017 12:18:01 -0800
changeset 443665 02dd65e55fd1ea9d2639b32da9748047e6772564
parent 443650 4427e7f72c8eb1daf43ec2b20b3e3a49bfd7db0c
child 443676 ffd4e32a403a933d53a1aa84edf94aa4b7a76dfc
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1412078
milestone58.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
Don't treat resampled layers as entirely opaque. (bug 1412078, r=mattwoodrow)
gfx/layers/mlgpu/LayerMLGPU.h
gfx/layers/mlgpu/PaintedLayerMLGPU.cpp
gfx/layers/mlgpu/PaintedLayerMLGPU.h
gfx/layers/mlgpu/RenderPassMLGPU.cpp
--- a/gfx/layers/mlgpu/LayerMLGPU.h
+++ b/gfx/layers/mlgpu/LayerMLGPU.h
@@ -70,19 +70,18 @@ public:
   bool IsPrepared() const {
     return mFrameKey == sFrameKey && mPrepared;
   }
 
   // Return true if the content in this layer is opaque (not factoring in
   // blend modes or opacity), false otherwise.
   virtual bool IsContentOpaque();
 
-  // This is used by RenderPasses for deciding which rects to draw. This
-  // region factors in occulsion culling and any layer-specific adjustments,
-  // whereas the local/shadow visible region does not.
+  // Returns the region that this layer will draw pixels to. If the layer and
+  // its content are opaque, this is the layer's opaque region.
   const LayerIntRegion& GetRenderRegion() const {
     return mRenderRegion;
   }
 
   // Some layers have visible regions that extend beyond what is actually drawn.
   // When performing CPU-based occlusion culling we must clamp the visible region
   // to the actual area. Note that if a layer is opaque, it must not expand its
   // visible region such that it might include non-opaque pixels, as may be the
--- a/gfx/layers/mlgpu/PaintedLayerMLGPU.cpp
+++ b/gfx/layers/mlgpu/PaintedLayerMLGPU.cpp
@@ -44,32 +44,38 @@ PaintedLayerMLGPU::OnPrepareToRender(Fra
   return true;
 }
 
 void
 PaintedLayerMLGPU::SetRenderRegion(LayerIntRegion&& aRegion)
 {
   mRenderRegion = Move(aRegion);
 
+  LayerIntRect bounds(mRenderRegion.GetBounds().TopLeft(),
+                      ViewAs<LayerPixel>(mTexture->GetSize()));
+  mRenderRegion.AndWith(bounds);
+}
+
+const LayerIntRegion&
+PaintedLayerMLGPU::GetDrawRects()
+{
 #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
   // Note: we don't set PaintWillResample on our ContentTextureHost. The old
   // compositor must do this since ContentHost is responsible for issuing
   // draw calls, but in AL we can handle it directly here.
   //
   // Note that when AL performs CPU-based occlusion culling (the default
   // behavior), we might break up the visible region again. If that turns
   // out to be a problem, we can factor this into ForEachDrawRect instead.
   if (MayResample()) {
-    mRenderRegion = mRenderRegion.GetBounds();
+    mDrawRects = mRenderRegion.GetBounds();
+    return mDrawRects;
   }
 #endif
-
-  LayerIntRect bounds(mRenderRegion.GetBounds().TopLeft(),
-                      ViewAs<LayerPixel>(mTexture->GetSize()));
-  mRenderRegion.AndWith(bounds);
+  return mRenderRegion;
 }
 
 bool
 PaintedLayerMLGPU::SetCompositableHost(CompositableHost* aHost)
 {
   switch (aHost->GetType()) {
     case CompositableType::CONTENT_SINGLE:
     case CompositableType::CONTENT_DOUBLE:
--- a/gfx/layers/mlgpu/PaintedLayerMLGPU.h
+++ b/gfx/layers/mlgpu/PaintedLayerMLGPU.h
@@ -57,30 +57,36 @@ public:
     // simply wrap around the edge of the buffer texture.
     return MayResample()
            ? SamplerMode::LinearClamp
            : SamplerMode::LinearRepeat;
   }
 
   void SetRenderRegion(LayerIntRegion&& aRegion) override;
 
+  // To avoid sampling issues with complex regions and transforms, we
+  // squash the visible region for PaintedLayers into a single draw
+  // rect. RenderPasses should use this method instead of GetRenderRegion.
+  const LayerIntRegion& GetDrawRects();
+
   MOZ_LAYER_DECL_NAME("PaintedLayerMLGPU", TYPE_PAINTED)
 
   void CleanupCachedResources();
 
 protected:
   void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
   bool OnPrepareToRender(FrameBuilder* aBuilder) override;
 
   void CleanupResources();
 
 private:
   RefPtr<ContentHostTexture> mHost;
   RefPtr<TextureSource> mTexture;
   RefPtr<TextureSource> mTextureOnWhite;
-  gfx::IntRegion mLocalDrawRegion;
-  gfx::IntRegion mTextureRegion;
+#ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE
+  LayerIntRegion mDrawRects;
+#endif
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp
+++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp
@@ -619,17 +619,17 @@ SingleTexturePass::AddToPass(LayerMLGPU*
   }
 
   Txn txn(this);
 
   // Note: these are two separate cases since no Info constructor takes in a
   // base LayerMLGPU class.
   if (PaintedLayerMLGPU* layer = aLayer->AsPaintedLayerMLGPU()) {
     Info info(aItem, layer);
-    if (!AddItems(txn, info, layer->GetRenderRegion())) {
+    if (!AddItems(txn, info, layer->GetDrawRects())) {
       return false;
     }
   } else if (TexturedLayerMLGPU* layer = aLayer->AsTexturedLayerMLGPU()) {
     Info info(aItem, layer);
     if (!AddItems(txn, info, layer->GetRenderRegion())) {
       return false;
     }
   }
@@ -695,17 +695,17 @@ ComponentAlphaPass::AddToPass(LayerMLGPU
     mAssignedLayer = layer;
     mTextureOnBlack = layer->GetTexture();
     mTextureOnWhite = layer->GetTextureOnWhite();
   } 
 
   Txn txn(this);
 
   Info info(aItem, layer);
-  if (!AddItems(txn, info, layer->GetRenderRegion())) {
+  if (!AddItems(txn, info, layer->GetDrawRects())) {
     return false;
   }
   return txn.Commit();
 }
 
 float
 ComponentAlphaPass::GetOpacity() const
 {