Bug 786817; Check multiple masks properly and invalidate after removing a mask layer. r=roc

This commit is contained in:
Nicholas Cameron 2012-09-03 18:58:07 +12:00
parent bf62bdbc2a
commit 219d6ac104

View File

@ -497,11 +497,19 @@ public:
mXScale(1.f), mYScale(1.f),
mActiveScrolledRootPosition(0, 0) {}
/**
* Record the number of clips in the Thebes layer's mask layer.
* Should not be reset when the layer is recycled since it is used to track
* changes in the use of mask layers.
*/
uint32_t mMaskClipCount;
/**
* A color that should be painted over the bounds of the layer's visible
* region before any other content is painted.
*/
nscolor mForcedBackgroundColor;
/**
* The resolution scale used.
*/
@ -1675,6 +1683,10 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
layer = thebesLayerData->mLayer;
}
// check to see if the new item has rounded rect clips in common with
// other items in the layer
thebesLayerData->UpdateCommonClipCount(aClip);
thebesLayerData->Accumulate(this, aItem, aVisibleRect, aDrawRect, aClip);
return thebesLayerData;
@ -3202,7 +3214,7 @@ FrameLayerBuilder::Clip::RemoveRoundedCorners()
}
gfxRect
CalculateBounds(nsTArray<FrameLayerBuilder::Clip::RoundedRect> aRects, int32_t A2D)
CalculateBounds(const nsTArray<FrameLayerBuilder::Clip::RoundedRect>& aRects, int32_t A2D)
{
nsRect bounds = aRects[0].mRect;
for (uint32_t i = 1; i < aRects.Length(); ++i) {
@ -3211,16 +3223,36 @@ CalculateBounds(nsTArray<FrameLayerBuilder::Clip::RoundedRect> aRects, int32_t A
return nsLayoutUtils::RectToGfxRect(bounds, A2D);
}
static void
SetClipCount(ThebesDisplayItemLayerUserData* aThebesData,
uint32_t aClipCount)
{
if (aThebesData) {
aThebesData->mMaskClipCount = aClipCount;
}
}
void
ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aClip,
uint32_t aRoundedRectClipCount)
{
// if the number of clips we are going to mask has decreased, then aLayer might have
// cached graphics which assume the existence of a soon-to-be non-existent mask layer
// in that case, invalidate the whole layer.
ThebesDisplayItemLayerUserData* thebesData = GetThebesDisplayItemLayerUserData(aLayer);
if (thebesData &&
aRoundedRectClipCount < thebesData->mMaskClipCount) {
ThebesLayer* thebes = aLayer->AsThebesLayer();
thebes->InvalidateRegion(thebes->GetValidRegion().GetBounds());
}
// don't build an unnecessary mask
nsIntRect layerBounds = aLayer->GetVisibleRegion().GetBounds();
if (aClip.mRoundedClipRects.IsEmpty() ||
aRoundedRectClipCount <= 0 ||
aRoundedRectClipCount == 0 ||
layerBounds.IsEmpty()) {
SetClipCount(thebesData, 0);
return;
}
@ -3238,6 +3270,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
if (*userData == newData) {
aLayer->SetMaskLayer(maskLayer);
SetClipCount(thebesData, aRoundedRectClipCount);
return;
}
@ -3292,6 +3325,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
// fail if we can't get the right surface
if (!surface || surface->CairoStatus()) {
NS_WARNING("Could not create surface for mask layer.");
SetClipCount(thebesData, 0);
return;
}
@ -3327,6 +3361,7 @@ ContainerState::SetupMaskLayer(Layer *aLayer, const FrameLayerBuilder::Clip& aCl
userData->mImageKey = key;
aLayer->SetMaskLayer(maskLayer);
SetClipCount(thebesData, aRoundedRectClipCount);
return;
}