Bug 612840. Part 4: Invert the meaning of CONTENT_NO_TEXT_OVER_TRANSPARENT and rename it. r=vlad
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 20 Dec 2010 14:26:14 +1300
changeset 59482 8019b50e514c708e3b633da8b4c394edd4a27f0b
parent 59481 bc423fb0aa13fb9c2d261c9993ccf6021fe85ff0
child 59483 f1ac5add876dcc639fe7b5eff6186514df88e356
push id17638
push userrocallahan@mozilla.com
push dateMon, 20 Dec 2010 01:39:18 +0000
treeherdermozilla-central@302d1d3e2817 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvlad
bugs612840
milestone2.0b9pre
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 612840. Part 4: Invert the meaning of CONTENT_NO_TEXT_OVER_TRANSPARENT and rename it. r=vlad
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicLayers.cpp
layout/base/FrameLayerBuilder.cpp
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -199,17 +199,16 @@ Layer::CanUseOpaqueSurface()
   // doesn't need an alpha channel, we can use an opaque surface for this
   // layer too. Any transparent areas must be covered by something else
   // in the container.
   ContainerLayer* parent = GetParent();
   return parent && parent->GetFirstChild() == this &&
     parent->CanUseOpaqueSurface();
 }
 
-
 #ifdef MOZ_IPC
 // NB: eventually these methods will be defined unconditionally, and
 // can be moved into Layers.h
 const nsIntRect*
 Layer::GetEffectiveClipRect()
 {
   if (ShadowLayer* shadow = AsShadowLayer()) {
     return shadow->GetShadowClipRect();
@@ -438,18 +437,18 @@ Layer::PrintInfo(nsACString& aTo, const 
     AppendToString(aTo, mVisibleRegion, " [visible=", "]");
   }
   if (1.0 != mOpacity) {
     aTo.AppendPrintf(" [opacity=%g]", mOpacity);
   }
   if (GetContentFlags() & CONTENT_OPAQUE) {
     aTo += " [opaqueContent]";
   }
-  if (GetContentFlags() & CONTENT_NO_TEXT_OVER_TRANSPARENT) {
-    aTo += " [noTextOverTransparent]";
+  if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
+    aTo += " [componentAlpha]";
   }
 
   return aTo;
 }
 
 nsACString&
 ThebesLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
 {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -477,30 +477,35 @@ public:
   enum {
     /**
      * If this is set, the caller is promising that by the end of this
      * transaction the entire visible region (as specified by
      * SetVisibleRegion) will be filled with opaque content.
      */
     CONTENT_OPAQUE = 0x01,
     /**
-     * If this is set, the caller is promising that the visible region
-     * contains no text over transparent pixels (any text, if present,
-     * is over fully opaque pixels).
+     * If this is set, the caller is notifying that the contents of this layer
+     * require per-component alpha for optimal fidelity. However, there is no
+     * guarantee that component alpha will be supported for this layer at
+     * paint time.
+     * This should never be set at the same time as CONTENT_OPAQUE.
      */
-    CONTENT_NO_TEXT_OVER_TRANSPARENT = 0x02
+    CONTENT_COMPONENT_ALPHA = 0x02
   };
   /**
    * CONSTRUCTION PHASE ONLY
    * This lets layout make some promises about what will be drawn into the
    * visible region of the ThebesLayer. This enables internal quality
    * and performance optimizations.
    */
   void SetContentFlags(PRUint32 aFlags)
   {
+    NS_ASSERTION((aFlags & (CONTENT_OPAQUE | CONTENT_COMPONENT_ALPHA)) !=
+                 (CONTENT_OPAQUE | CONTENT_COMPONENT_ALPHA),
+                 "Can't be opaque and require component alpha");
     mContentFlags = aFlags;
     Mutated();
   }
   /**
    * CONSTRUCTION PHASE ONLY
    * Tell this layer which region will be visible. The visible region
    * is a region which contains all the contents of the layer that can
    * actually affect the rendering of the window. It can exclude areas
@@ -732,17 +737,17 @@ public:
 protected:
   Layer(LayerManager* aManager, void* aImplData) :
     mManager(aManager),
     mParent(nsnull),
     mNextSibling(nsnull),
     mPrevSibling(nsnull),
     mImplData(aImplData),
     mOpacity(1.0),
-    mContentFlags(CONTENT_NO_TEXT_OVER_TRANSPARENT),
+    mContentFlags(0),
     mUseClipRect(PR_FALSE)
     {}
 
   void Mutated() { mManager->Mutated(this); }
 
   // Print interesting information about this into aTo.  Internally
   // used to implement Dump*() and Log*().  If subclasses have
   // additional interesting properties, they should override this with
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -464,17 +464,17 @@ BasicThebesLayer::Paint(gfxContext* aCon
   PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
   Buffer::ContentType contentType =
     canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
                           gfxASurface::CONTENT_COLOR_ALPHA;
   float opacity = GetEffectiveOpacity();
 
   if (!BasicManager()->IsRetained() ||
       (!canUseOpaqueSurface &&
-       !(mContentFlags & CONTENT_NO_TEXT_OVER_TRANSPARENT) &&
+       (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
        !MustRetainContent())) {
     mValidRegion.SetEmpty();
     mBuffer.Clear();
 
     nsIntRegion toDraw = IntersectWithClip(mVisibleRegion, target);
     if (!toDraw.IsEmpty()) {
       target->Save();
       gfxUtils::ClipToRegionSnapped(target, toDraw);
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -143,19 +143,18 @@ public:
    */
   void ProcessDisplayItems(const nsDisplayList& aList,
                            const FrameLayerBuilder::Clip& aClip);
   /**
    * This finalizes all the open ThebesLayers by popping every element off
    * mThebesLayerDataStack, then sets the children of the container layer
    * to be all the layers in mNewChildLayers in that order and removes any
    * layers as children of the container that aren't in mNewChildLayers.
-   * @param aTextContentFlags if all child layers have CONTENT_NO_TEXT, adds
-   * CONTENT_NO_TEXT to *aTextContentFlags.
-   * Likewise for CONTENT_NO_TEXT_OVER_TRANSPARENT.
+   * @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
+   * set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
    */
   void Finish(PRUint32 *aTextContentFlags);
 
 protected:
   /**
    * We keep a stack of these to represent the ThebesLayers that are
    * currently available to have display items added to.
    * We use a stack here because as much as possible we want to
@@ -164,17 +163,17 @@ protected:
    * makes it more likely a display item will be rendered to an opaque
    * layer, giving us the best chance of getting subpixel AA.
    */
   class ThebesLayerData {
   public:
     ThebesLayerData() :
       mActiveScrolledRoot(nsnull), mLayer(nsnull),
       mIsSolidColorInVisibleRegion(PR_FALSE),
-      mHasTextOverTransparent(PR_FALSE),
+      mNeedComponentAlpha(PR_FALSE),
       mForceTransparentSurface(PR_FALSE) {}
     /**
      * Record that an item has been added to the ThebesLayer, so we
      * need to update our regions.
      * @param aVisibleRect the area of the item that's visible
      * @param aDrawRect the area of the item that would be drawn if it
      * was completely visible
      * @param aOpaqueRect if non-null, the area of the item that's opaque.
@@ -238,17 +237,17 @@ protected:
     /**
      * True if every pixel in mVisibleRegion will have color mSolidColor.
      */
     PRPackedBool mIsSolidColorInVisibleRegion;
     /**
      * True if there is any text visible in the layer that's over
      * transparent pixels in the layer.
      */
-    PRPackedBool mHasTextOverTransparent;
+    PRPackedBool mNeedComponentAlpha;
     /**
      * Set if the layer should be treated as transparent, even if its entire
      * area is covered by opaque display items. For example, this needs to
      * be set if something is going to "punch holes" in the layer by clearing
      * part of its surface.
      */
     PRPackedBool mForceTransparentSurface;
   };
@@ -863,19 +862,24 @@ ContainerState::PopThebesLayerData()
     NS_ASSERTION(userData, "where did our user data go?");
     if (userData->mForcedBackgroundColor != backgroundColor) {
       // Invalidate the entire target ThebesLayer since we're changing
       // the background color
       data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion());
     }
     userData->mForcedBackgroundColor = backgroundColor;
   }
-  PRUint32 flags =
-    ((isOpaque && !data->mForceTransparentSurface) ? Layer::CONTENT_OPAQUE : 0) |
-    (data->mHasTextOverTransparent ? 0 : Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT);
+  PRUint32 flags;
+  if (isOpaque && !data->mForceTransparentSurface) {
+    flags = Layer::CONTENT_OPAQUE;
+  } else if (data->mNeedComponentAlpha) {
+    flags = Layer::CONTENT_COMPONENT_ALPHA;
+  } else {
+    flags = 0;
+  }
   layer->SetContentFlags(flags);
 
   if (lastIndex > 0) {
     // Since we're going to pop off the last ThebesLayerData, the
     // mVisibleAboveRegion of the second-to-last item will need to include
     // the regions of the last item.
     ThebesLayerData* nextData = mThebesLayerDataStack[lastIndex - 1];
     nextData->mVisibleAboveRegion.Or(nextData->mVisibleAboveRegion,
@@ -928,17 +932,17 @@ ContainerState::ThebesLayerData::Accumul
     // we see doesn't get discarded.
     nsIntRegion tmp;
     tmp.Or(mOpaqueRegion, aDrawRect);
     if (tmp.GetNumRects() <= 4) {
       mOpaqueRegion = tmp;
     }
   } else if (aItem->HasText()) {
     if (!mOpaqueRegion.Contains(aVisibleRect)) {
-      mHasTextOverTransparent = PR_TRUE;
+      mNeedComponentAlpha = PR_TRUE;
     }
   }
   mForceTransparentSurface = mForceTransparentSurface || forceTransparentSurface;
 }
 
 already_AddRefed<ThebesLayer>
 ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
                                    const nsIntRect& aVisibleRect,
@@ -1271,26 +1275,26 @@ ContainerState::CollectOldLayers()
 
 void
 ContainerState::Finish(PRUint32* aTextContentFlags)
 {
   while (!mThebesLayerDataStack.IsEmpty()) {
     PopThebesLayerData();
   }
 
-  PRUint32 textContentFlags = Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT;
+  PRUint32 textContentFlags = 0;
 
   for (PRUint32 i = 0; i <= mNewChildLayers.Length(); ++i) {
     // An invariant of this loop is that the layers in mNewChildLayers
     // with index < i are the first i child layers of mContainerLayer.
     Layer* layer;
     if (i < mNewChildLayers.Length()) {
       layer = mNewChildLayers[i];
       if (!layer->GetVisibleRegion().IsEmpty()) {
-        textContentFlags &= layer->GetContentFlags();
+        textContentFlags |= layer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA;
       }
       if (!layer->GetParent()) {
         // This is not currently a child of the container, so just add it
         // now.
         Layer* prevChild = i == 0 ? nsnull : mNewChildLayers[i - 1].get();
         mContainerLayer->InsertAfter(layer, prevChild);
         continue;
       }
@@ -1401,24 +1405,25 @@ FrameLayerBuilder::BuildContainerLayerFo
       state.SetInvalidateAllThebesContent();
     }
     SetHasContainerLayer(aContainerFrame);
   }
 
   Clip clip;
   state.ProcessDisplayItems(aChildren, clip);
 
-  // Set CONTENT_NO_TEXT_OVER_TRANSPARENT if any of our children have it.
+  // Set CONTENT_COMPONENT_ALPHA if any of our children have it.
   // This is suboptimal ... a child could have text that's over transparent
   // pixels in its own layer, but over opaque parts of previous siblings.
   PRUint32 flags;
   state.Finish(&flags);
 
   if (aChildren.IsOpaque() && !aChildren.NeedsTransparentSurface()) {
-    flags |= Layer::CONTENT_OPAQUE;
+    // Clear CONTENT_COMPONENT_ALPHA
+    flags = Layer::CONTENT_OPAQUE;
   }
   containerLayer->SetContentFlags(flags);
 
   return containerLayer.forget();
 }
 
 Layer*
 FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,