Bug 561959. Replace solid-color ThebesLayers with ColorLayers. r=dbaron

This commit is contained in:
Robert O'Callahan
2010-05-13 12:56:11 +12:00
parent 371a289e0f
commit d01d529e1b
4 changed files with 59 additions and 14 deletions

View File

@@ -346,8 +346,9 @@ nsDisplayList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
// Record bounds of moving visible items in movingContentAccumulatedBounds. // Record bounds of moving visible items in movingContentAccumulatedBounds.
// We do not need to add items that are uniform across the entire visible // We do not need to add items that are uniform across the entire visible
// area, since they have no visible movement. // area, since they have no visible movement.
nscolor color;
if (isMoving && if (isMoving &&
!(item->IsUniform(aBuilder) && !(item->IsUniform(aBuilder, &color) &&
bounds.Contains(aVisibleRegion->GetBounds()) && bounds.Contains(aVisibleRegion->GetBounds()) &&
bounds.Contains(aVisibleRegionBeforeMove->GetBounds()))) { bounds.Contains(aVisibleRegionBeforeMove->GetBounds()))) {
if (movingContentAccumulatedBounds.IsEmpty()) { if (movingContentAccumulatedBounds.IsEmpty()) {
@@ -570,6 +571,28 @@ CreateEmptyThebesLayer(nsDisplayListBuilder* aBuilder,
return itemGroup; return itemGroup;
} }
static PRBool
IsAllUniform(nsDisplayListBuilder* aBuilder, nsDisplayList::ItemGroup* aGroup,
nscolor* aColor)
{
nsRect visibleRect = aGroup->mStartItem->GetVisibleRect();
nscolor finalColor = NS_RGBA(0,0,0,0);
for (nsDisplayList::ItemGroup* group = aGroup; group;
group = group->mNextItemsForLayer) {
for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem;
item = item->GetAbove()) {
nscolor color;
if (visibleRect != item->GetVisibleRect())
return PR_FALSE;
if (!item->IsUniform(aBuilder, &color))
return PR_FALSE;
finalColor = NS_ComposeColors(finalColor, color);
}
}
*aColor = finalColor;
return PR_TRUE;
}
/** /**
* This is the heart of layout's integration with layers. We * This is the heart of layout's integration with layers. We
* use a ClippedItemIterator to iterate through descendant display * use a ClippedItemIterator to iterate through descendant display
@@ -681,6 +704,15 @@ void nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
for (PRUint32 i = 0; i < aLayers->Length(); ++i) { for (PRUint32 i = 0; i < aLayers->Length(); ++i) {
LayerItems* layerItems = &aLayers->ElementAt(i); LayerItems* layerItems = &aLayers->ElementAt(i);
nscolor color;
if (layerItems->mThebesLayer &&
IsAllUniform(aBuilder, layerItems->mItems, &color)) {
layerItems->mThebesLayer = nsnull;
nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer();
layer->SetColor(gfxRGBA(color));
layerItems->mLayer = layer.forget();
}
gfxMatrix transform; gfxMatrix transform;
nsIntRect visibleRect = layerItems->mVisibleRect; nsIntRect visibleRect = layerItems->mVisibleRect;
if (layerItems->mLayer->GetTransform().Is2D(&transform)) { if (layerItems->mLayer->GetTransform().Is2D(&transform)) {
@@ -1099,7 +1131,7 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
} }
PRBool PRBool
nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) { nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
// theme background overrides any other background // theme background overrides any other background
if (mIsThemed) if (mIsThemed)
return PR_FALSE; return PR_FALSE;
@@ -1107,14 +1139,18 @@ nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) {
nsStyleContext *bgSC; nsStyleContext *bgSC;
PRBool hasBG = PRBool hasBG =
nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC); nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
if (!hasBG) if (!hasBG) {
aColor = NS_RGBA(0,0,0,0);
return PR_TRUE; return PR_TRUE;
}
const nsStyleBackground* bg = bgSC->GetStyleBackground(); const nsStyleBackground* bg = bgSC->GetStyleBackground();
if (bg->BottomLayer().mImage.IsEmpty() && if (bg->BottomLayer().mImage.IsEmpty() &&
bg->mImageCount == 1 && bg->mImageCount == 1 &&
!nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius) && !nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius) &&
bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER) bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER) {
*aColor = bg->mBackgroundColor;
return PR_TRUE; return PR_TRUE;
}
return PR_FALSE; return PR_FALSE;
} }
@@ -1426,7 +1462,7 @@ nsDisplayWrapList::IsOpaque(nsDisplayListBuilder* aBuilder) {
return PR_FALSE; return PR_FALSE;
} }
PRBool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder) { PRBool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
// We could try to do something but let's conservatively just return PR_FALSE. // We could try to do something but let's conservatively just return PR_FALSE.
return PR_FALSE; return PR_FALSE;
} }
@@ -1996,12 +2032,12 @@ PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder)
* wrapped list is uniform. See IsOpaque for discussion of why this * wrapped list is uniform. See IsOpaque for discussion of why this
* works. * works.
*/ */
PRBool nsDisplayTransform::IsUniform(nsDisplayListBuilder *aBuilder) PRBool nsDisplayTransform::IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor)
{ {
const nsStyleDisplay* disp = mFrame->GetStyleDisplay(); const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
return disp->mTransform.GetMainMatrixEntry(1) == 0.0f && return disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
disp->mTransform.GetMainMatrixEntry(2) == 0.0f && disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
mStoredList.IsUniform(aBuilder); mStoredList.IsUniform(aBuilder, aColor);
} }
/* If UNIFIED_CONTINUATIONS is defined, we can merge two display lists that /* If UNIFIED_CONTINUATIONS is defined, we can merge two display lists that

View File

@@ -544,10 +544,11 @@ public:
*/ */
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) { return PR_FALSE; } virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
/** /**
* If this returns true, then aColor is set to the uniform color
* @return PR_TRUE if the item is guaranteed to paint every pixel in its * @return PR_TRUE if the item is guaranteed to paint every pixel in its
* bounds with the same (possibly translucent) color * bounds with the same (possibly translucent) color
*/ */
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder) { return PR_FALSE; } virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return PR_FALSE; }
/** /**
* @return PR_FALSE if the painting performed by the item is invariant * @return PR_FALSE if the painting performed by the item is invariant
* when frame aFrame is moved relative to aBuilder->GetRootMovingFrame(). * when frame aFrame is moved relative to aBuilder->GetRootMovingFrame().
@@ -628,6 +629,8 @@ public:
* list. * list.
*/ */
virtual nsDisplayList* GetList() { return nsnull; } virtual nsDisplayList* GetList() { return nsnull; }
const nsRect& GetVisibleRect() { return mVisibleRect; }
#ifdef NS_DEBUG #ifdef NS_DEBUG
/** /**
@@ -1303,7 +1306,11 @@ public:
return (NS_GET_A(mColor) == 255); return (NS_GET_A(mColor) == 255);
} }
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder) { return PR_TRUE; } virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
{
*aColor = mColor;
return PR_TRUE;
}
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
@@ -1335,7 +1342,7 @@ public:
} }
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder); virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder); virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder); virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
NS_DISPLAY_DECL_NAME("Background") NS_DISPLAY_DECL_NAME("Background")
@@ -1468,7 +1475,7 @@ public:
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames); HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder); virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder); virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder); virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder); virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder);
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx); virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder, virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
@@ -1672,7 +1679,7 @@ public:
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames); HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder); virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder); virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder);
virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder); virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
virtual void Paint(nsDisplayListBuilder *aBuilder, virtual void Paint(nsDisplayListBuilder *aBuilder,
nsIRenderingContext *aCtx); nsIRenderingContext *aCtx);
virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder, virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder,

View File

@@ -172,11 +172,12 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
default: default:
break; break;
} }
nscolor color;
fprintf(aOutput, "%s %p(%s) (%d,%d,%d,%d)%s%s%s%s\n", i->Name(), fprintf(aOutput, "%s %p(%s) (%d,%d,%d,%d)%s%s%s%s\n", i->Name(),
(void*)f, NS_ConvertUTF16toUTF8(fName).get(), (void*)f, NS_ConvertUTF16toUTF8(fName).get(),
rect.x, rect.y, rect.width, rect.height, rect.x, rect.y, rect.width, rect.height,
i->IsOpaque(aBuilder) ? " opaque" : "", i->IsOpaque(aBuilder) ? " opaque" : "",
i->IsUniform(aBuilder) ? " uniform" : "", i->IsUniform(aBuilder, &color) ? " uniform" : "",
f && aBuilder->IsMovingFrame(f) ? " moving" : "", f && aBuilder->IsMovingFrame(f) ? " moving" : "",
f && aBuilder->IsMovingFrame(f) && !i->GetList() && f && aBuilder->IsMovingFrame(f) && !i->GetList() &&
i->IsVaryingRelativeToMovingFrame(aBuilder) ? " varying" : ""); i->IsVaryingRelativeToMovingFrame(aBuilder) ? " varying" : "");

View File

@@ -1388,7 +1388,8 @@ AddItemsToRegion(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
} }
} else { } else {
// not moving. // not moving.
if (item->IsUniform(aBuilder)) { nscolor color;
if (item->IsUniform(aBuilder, &color)) {
// If it's uniform, we don't need to invalidate where one part // If it's uniform, we don't need to invalidate where one part
// of the item was copied to another part. // of the item was copied to another part.
exclude.IntersectRect(r, r + aDelta); exclude.IntersectRect(r, r + aDelta);