Bug 983169 - Fix up TiledLayerHost rendering method. r=BenWa, a=lsblakk
authorChris Lord <chrislord.net@gmail.com>
Thu, 27 Mar 2014 18:52:08 +0000
changeset 192323 35fe7342d5aa
parent 192322 4ffac6a8ab14
child 192324 fd3adb4a2d16
push id3568
push userryanvm@gmail.com
push date2014-05-20 16:00 +0000
treeherdermozilla-beta@26ba0b7f24ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBenWa, lsblakk
bugs983169
milestone30.0
Bug 983169 - Fix up TiledLayerHost rendering method. r=BenWa, a=lsblakk

A few parts of this function weren't quite right. The major change is to use
the TiledLayerBuffer's valid region instead of the layer's valid region.
These are the same, except when progressive rendering is enabled, where the
former may differ from the layyer (and will represent what has actually been
updated).
gfx/layers/composite/TiledContentHost.cpp
gfx/layers/composite/TiledContentHost.h
--- a/gfx/layers/composite/TiledContentHost.cpp
+++ b/gfx/layers/composite/TiledContentHost.cpp
@@ -281,19 +281,16 @@ TiledContentHost::Composite(EffectChain&
                             const gfx::Matrix4x4& aTransform,
                             const gfx::Filter& aFilter,
                             const gfx::Rect& aClipRect,
                             const nsIntRegion* aVisibleRegion /* = nullptr */,
                             TiledLayerProperties* aLayerProperties /* = nullptr */)
 {
   MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost");
 
-  // Render valid tiles.
-  nsIntRect visibleRect = aVisibleRegion->GetBounds();
-
   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();
@@ -303,21 +300,20 @@ TiledContentHost::Composite(EffectChain&
     mLowPrecisionTiledBuffer.SetCompositor(mCompositor);
     mLowPrecisionTiledBuffer.Upload();
 
     if (!mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
       mLowPrecisionTiledBuffer.ReadUnlock();
     }
   }
 
-  RenderLayerBuffer(mLowPrecisionTiledBuffer,
-                    mLowPrecisionTiledBuffer.GetValidRegion(), aEffectChain, aOpacity,
-                    aFilter, aClipRect, aLayerProperties->mValidRegion, visibleRect, aTransform);
-  RenderLayerBuffer(mTiledBuffer, aLayerProperties->mValidRegion, aEffectChain, aOpacity,
-                    aFilter, aClipRect, nsIntRegion(), visibleRect, aTransform);
+  RenderLayerBuffer(mLowPrecisionTiledBuffer, aEffectChain, aOpacity, aFilter,
+                    aClipRect, aLayerProperties->mVisibleRegion, aTransform);
+  RenderLayerBuffer(mTiledBuffer, aEffectChain, aOpacity, aFilter,
+                    aClipRect, aLayerProperties->mVisibleRegion, 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();
   }
@@ -386,90 +382,100 @@ TiledContentHost::RenderTile(const TileH
     mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform);
   }
   mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE,
                                aScreenRegion, aClipRect, aTransform);
 }
 
 void
 TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
-                                    const nsIntRegion& aValidRegion,
                                     EffectChain& aEffectChain,
                                     float aOpacity,
                                     const gfx::Filter& aFilter,
                                     const gfx::Rect& aClipRect,
-                                    const nsIntRegion& aMaskRegion,
-                                    nsIntRect aVisibleRect,
+                                    nsIntRegion aVisibleRegion,
                                     gfx::Matrix4x4 aTransform)
 {
   if (!mCompositor) {
     NS_WARNING("Can't render tiled content host - no compositor");
     return;
   }
   float resolution = aLayerBuffer.GetResolution();
   gfx::Size layerScale(1, 1);
-  // We assume that the current frame resolution is the one used in our primary
-  // layer buffer. Compensate for a changing frame resolution.
+
+  // We assume that the current frame resolution is the one used in our high
+  // precision layer buffer. Compensate for a changing frame resolution when
+  // rendering the low precision buffer.
   if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
     const CSSToParentLayerScale& layerResolution = aLayerBuffer.GetFrameResolution();
     const CSSToParentLayerScale& localResolution = mTiledBuffer.GetFrameResolution();
     layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
-    aVisibleRect.ScaleRoundOut(layerScale.width, layerScale.height);
+    aVisibleRegion.ScaleRoundOut(layerScale.width, layerScale.height);
   }
+
+  // If we're drawing the low precision buffer, make sure the high precision
+  // buffer is masked out to avoid overdraw and rendering artifacts with
+  // non-opaque layers.
+  nsIntRegion maskRegion;
+  if (resolution != mTiledBuffer.GetResolution()) {
+    maskRegion = mTiledBuffer.GetValidRegion();
+    // XXX This should be ScaleRoundIn, but there is no such function on
+    //     nsIntRegion.
+    maskRegion.ScaleRoundOut(layerScale.width, layerScale.height);
+  }
+
+  // Make sure the resolution and difference in frame resolution are accounted
+  // for in the layer transform.
   aTransform.Scale(1/(resolution * layerScale.width),
                    1/(resolution * layerScale.height), 1);
 
   uint32_t rowCount = 0;
   uint32_t tileX = 0;
-  for (int32_t x = aVisibleRect.x; x < aVisibleRect.x + aVisibleRect.width;) {
+  nsIntRect visibleRect = aVisibleRegion.GetBounds();
+  for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
     rowCount++;
     int32_t tileStartX = aLayerBuffer.GetTileStart(x);
     int32_t w = aLayerBuffer.GetScaledTileLength() - tileStartX;
-    if (x + w > aVisibleRect.x + aVisibleRect.width) {
-      w = aVisibleRect.x + aVisibleRect.width - x;
+    if (x + w > visibleRect.x + visibleRect.width) {
+      w = visibleRect.x + visibleRect.width - x;
     }
     int tileY = 0;
-    for (int32_t y = aVisibleRect.y; y < aVisibleRect.y + aVisibleRect.height;) {
+    for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
       int32_t tileStartY = aLayerBuffer.GetTileStart(y);
       int32_t h = aLayerBuffer.GetScaledTileLength() - tileStartY;
-      if (y + h > aVisibleRect.y + aVisibleRect.height) {
-        h = aVisibleRect.y + aVisibleRect.height - y;
+      if (y + h > visibleRect.y + visibleRect.height) {
+        h = visibleRect.y + visibleRect.height - y;
       }
 
       TileHost tileTexture = aLayerBuffer.
         GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
                            aLayerBuffer.RoundDownToTileEdge(y)));
       if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
         nsIntRegion tileDrawRegion;
-        tileDrawRegion.And(aValidRegion,
-                           nsIntRect(x * layerScale.width,
-                                     y * layerScale.height,
-                                     w * layerScale.width,
-                                     h * layerScale.height));
-        tileDrawRegion.Sub(tileDrawRegion, aMaskRegion);
+        tileDrawRegion.And(nsIntRect(x, y, w, h), aLayerBuffer.GetValidRegion());
+        tileDrawRegion.And(tileDrawRegion, aVisibleRegion);
+        tileDrawRegion.Sub(tileDrawRegion, maskRegion);
 
         if (!tileDrawRegion.IsEmpty()) {
-          tileDrawRegion.ScaleRoundOut(resolution / layerScale.width,
-                                       resolution / layerScale.height);
-
+          tileDrawRegion.ScaleRoundOut(resolution, resolution);
           nsIntPoint tileOffset((x - tileStartX) * resolution,
                                 (y - tileStartY) * resolution);
           uint32_t tileSize = aLayerBuffer.GetTileLength();
           RenderTile(tileTexture, aEffectChain, aOpacity, aTransform, aFilter, aClipRect, tileDrawRegion,
                      tileOffset, nsIntSize(tileSize, tileSize));
         }
       }
       tileY++;
       y += h;
     }
     tileX++;
     x += w;
   }
-  gfx::Rect rect(aVisibleRect.x, aVisibleRect.y,
-                 aVisibleRect.width, aVisibleRect.height);
+  gfx::Rect rect(visibleRect.x, visibleRect.y,
+                 visibleRect.width, visibleRect.height);
   GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTENT,
                                    rect, aClipRect, aTransform);
 }
 
 void
 TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
   aTo += aPrefix;
--- a/gfx/layers/composite/TiledContentHost.h
+++ b/gfx/layers/composite/TiledContentHost.h
@@ -264,23 +264,21 @@ public:
   {
     mTiledBuffer.SetReleaseFence(aReleaseFence);
     mLowPrecisionTiledBuffer.SetReleaseFence(aReleaseFence);
   }
 #endif
 
 private:
   void RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
-                         const nsIntRegion& aValidRegion,
                          EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
-                         const nsIntRegion& aMaskRegion,
-                         nsIntRect aVisibleRect,
+                         nsIntRegion aMaskRegion,
                          gfx::Matrix4x4 aTransform);
 
   void EnsureTileStore() {}
 
   TiledLayerBufferComposite    mTiledBuffer;
   TiledLayerBufferComposite    mLowPrecisionTiledBuffer;
   TiledLayerBufferComposite    mOldTiledBuffer;
   TiledLayerBufferComposite    mOldLowPrecisionTiledBuffer;