Bug 1022612. Part 43: Fix up SuppressComponentAlpha to allow component alpha in inactive layers over opaque parts of the chrome window. r=mattwoodrow
☠☠ backed out by d0676370cba9 ☠ ☠
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 15 Jul 2014 16:23:37 +1200
changeset 214832 cc1776b2606d9d7a00b467b0d1d309f6f83477b1
parent 214831 f12d7d68b685bb894d4f23efc6af638c789eb9e6
child 214833 60b9b810aa29725cdd6fff2b2656d6781991f1d7
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1022612
milestone33.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 1022612. Part 43: Fix up SuppressComponentAlpha to allow component alpha in inactive layers over opaque parts of the chrome window. r=mattwoodrow
layout/base/FrameLayerBuilder.cpp
layout/base/nsDisplayList.h
layout/base/nsLayoutUtils.cpp
layout/xul/nsBoxFrame.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2207,31 +2207,32 @@ ContainerState::PopThebesLayerData()
     ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1];
     nextData->CopyAboveRegion(data);
   }
 
   mThebesLayerDataStack.RemoveElementAt(lastIndex);
 }
 
 static bool
-SuppressComponentAlpha(nsDisplayListBuilder* aBuilder,
-                       nsDisplayItem* aItem)
+IsItemAreaInWindowOpaqueRegion(nsDisplayListBuilder* aBuilder,
+                               nsDisplayItem* aItem,
+                               const nsRect& aComponentAlphaBounds)
 {
-  // Suppress component alpha for items in the toplevel window chrome that
-  // aren't transformed.
-  nsIFrame* f = aItem->Frame();
-  nsIFrame* ref = aBuilder->RootReferenceFrame();
-  if (f->PresContext() != ref->PresContext())
+  if (!aItem->Frame()->PresContext()->IsChrome()) {
+    // Assume that Web content is always in the window opaque region.
+    return true;
+  }
+  if (aItem->ReferenceFrame() != aBuilder->RootReferenceFrame()) {
+    // aItem is probably in some transformed subtree.
+    // We're not going to bother figuring out where this landed, we're just
+    // going to assume it might have landed over a transparent part of
+    // the window.
     return false;
-
-  for (nsIFrame* t = f; t; t = t->GetParent()) {
-    if (t->IsTransformed())
-      return false;
   }
-  return true;
+  return aBuilder->GetWindowOpaqueRegion().Contains(aComponentAlphaBounds);
 }
 
 void
 ThebesLayerData::Accumulate(ContainerState* aState,
                             nsDisplayItem* aItem,
                             const nsIntRegion& aClippedOpaqueRegion,
                             const nsIntRect& aVisibleRect,
                             const nsIntRect& aDrawRect,
@@ -2333,20 +2334,21 @@ ThebesLayerData::Accumulate(ContainerSta
   }
 
   if (!aState->mParameters.mDisableSubpixelAntialiasingInDescendants) {
     nsRect componentAlpha = aItem->GetComponentAlphaBounds(aState->mBuilder);
     if (!componentAlpha.IsEmpty()) {
       nsIntRect componentAlphaRect =
         aState->ScaleToOutsidePixels(componentAlpha, false).Intersect(aVisibleRect);
       if (!mOpaqueRegion.Contains(componentAlphaRect)) {
-        if (SuppressComponentAlpha(aState->mBuilder, aItem)) {
+        if (IsItemAreaInWindowOpaqueRegion(aState->mBuilder, aItem,
+              componentAlpha.Intersect(aItem->GetVisibleRect()))) {
+          mNeedComponentAlpha = true;
+        } else {
           aItem->DisableComponentAlpha();
-        } else {
-          mNeedComponentAlpha = true;
         }
       }
     }
   }
 }
 
 ThebesLayerData*
 ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
@@ -2598,18 +2600,18 @@ ContainerState::ComputeOpaqueRect(nsDisp
         aFixedPosFrame == mContainerFixedPosFrame &&
         !aList->IsOpaque() &&
         opaqueClipped.Contains(mContainerBounds)) {
       aList->SetIsOpaque();
     }
     // Add opaque areas to the "exclude glass" region. Only do this for
     // ThebesLayers which are direct children of the root layer; this means
     // they can't have transforms or opacity wrapping them.
-    if (!mContainerLayer->GetParent() && mBuilder->HasGlass()) {
-      mBuilder->AddExcludedGlassRegion(opaqueClipped);
+    if (!mContainerLayer->GetParent()) {
+      mBuilder->AddWindowOpaqueRegion(opaqueClipped);
     }
     opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
     if (aFixedPosFrame && ItemCoversScrollableArea(aItem, opaque)) {
       *aHideAllLayersBelow = true;
     }
   }
   return opaquePixels;
 }
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -662,37 +662,37 @@ public:
     return CurrentPresShellState()->mPresShell->GetPresContext();
   }
 
   /**
    * Accumulates the bounds of box frames that have moz-appearance
    * -moz-win-exclude-glass style. Used in setting glass margins on
    * Windows.
    */  
-  void AddExcludedGlassRegion(const nsRegion& bounds) {
-    mExcludedGlassRegion.Or(mExcludedGlassRegion, bounds);
+  void AddWindowOpaqueRegion(const nsRegion& bounds) {
+    mWindowOpaqueRegion.Or(mWindowOpaqueRegion, bounds);
   }
-  const nsRegion& GetExcludedGlassRegion() {
-    return mExcludedGlassRegion;
+  /**
+   * Returns the window opaque region built so far. This may be incomplete
+   * since the opaque region is built during layer construction.
+   */
+  const nsRegion& GetWindowOpaqueRegion() {
+    return mWindowOpaqueRegion;
   }
   void SetGlassDisplayItem(nsDisplayItem* aItem) {
     if (mGlassDisplayItem) {
       // Web pages or extensions could trigger this by using
       // -moz-appearance:win-borderless-glass etc on their own elements.
       // Keep the first one, since that will be the background of the root
       // window
       NS_WARNING("Multiple glass backgrounds found?");
     } else {
       mGlassDisplayItem = aItem;
     }
   }
-  // Call this only after we've finished building the display list
-  bool HasGlass() {
-    return mGlassDisplayItem != nullptr;
-  }
   bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
     return aItem == mGlassDisplayItem;
   }
 
   void SetContainsPluginItem() { mContainsPluginItem = true; }
   bool ContainsPluginItem() { return mContainsPluginItem; }
 
   /**
@@ -742,17 +742,17 @@ private:
   // BuildDisplayList on.
   const nsIFrame*                mCurrentFrame;
   // The reference frame for mCurrentFrame.
   const nsIFrame*                mCurrentReferenceFrame;
   // The offset from mCurrentFrame to mCurrentReferenceFrame.
   nsPoint                        mCurrentOffsetToReferenceFrame;
   // Relative to mCurrentFrame.
   nsRect                         mDirtyRect;
-  nsRegion                       mExcludedGlassRegion;
+  nsRegion                       mWindowOpaqueRegion;
   // The display item for the Windows window glass background, if any
   nsDisplayItem*                 mGlassDisplayItem;
   nsTArray<DisplayItemClip*>     mDisplayItemClipsToDestroy;
   Mode                           mMode;
   ViewID                         mCurrentScrollParentId;
   ViewID                         mCurrentScrollbarTarget;
   uint32_t                       mCurrentScrollbarFlags;
   BlendModeSet                   mContainedBlendModes;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3016,17 +3016,17 @@ nsLayoutUtils::PaintFrame(nsRenderingCon
 
   // Update the widget's opaque region information. This sets
   // glass boundaries on Windows. Also set up plugin clip regions and bounds.
   if ((aFlags & PAINT_WIDGET_LAYERS) &&
       !willFlushRetainedLayers &&
       !(aFlags & PAINT_DOCUMENT_RELATIVE)) {
     nsIWidget *widget = aFrame->GetNearestWidget();
     if (widget) {
-      nsRegion excludedRegion = builder.GetExcludedGlassRegion();
+      nsRegion excludedRegion = builder.GetWindowOpaqueRegion();
       nsIntRegion windowRegion(excludedRegion.ToNearestPixels(presContext->AppUnitsPerDevPixel()));
       widget->UpdateOpaqueRegion(windowRegion);
     }
   }
 
   if (builder.WillComputePluginGeometry()) {
     nsRefPtr<LayerManager> layerManager;
     nsIWidget* widget = aFrame->GetNearestWidget();
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -1315,18 +1315,18 @@ nsBoxFrame::BuildDisplayList(nsDisplayLi
         forceLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
         nsLayoutUtils::SetScrollbarThumbLayerization(this, forceLayer);
       }
     }
     // Check for frames that are marked as a part of the region used
     // in calculating glass margins on Windows.
     const nsStyleDisplay* styles = StyleDisplay();
     if (styles && styles->mAppearance == NS_THEME_WIN_EXCLUDE_GLASS) {
-      nsRect rect = nsRect(aBuilder->ToReferenceFrame(this), GetSize());
-      aBuilder->AddExcludedGlassRegion(rect);
+      aBuilder->AddWindowOpaqueRegion(
+          nsRect(aBuilder->ToReferenceFrame(this), GetSize()));
     }
   }
 
   nsDisplayListCollection tempLists;
   const nsDisplayListSet& destination = forceLayer ? tempLists : aLists;
 
   DisplayBorderBackgroundOutline(aBuilder, destination);