mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-06 06:22:33 +00:00
Bug 728983. Part 2: When display items for multiple frames are merged, track the merged frames and mark them all as having an associated container layer. This ensures that invalidations are processed correctly. r=mattwoodrow
This commit is contained in:
parent
8de539221c
commit
ff25496dd5
@ -155,9 +155,9 @@ public:
|
||||
CollectOldLayers();
|
||||
}
|
||||
|
||||
void SetInvalidThebesContent(const nsIntRegion& aRegion)
|
||||
void AddInvalidThebesContent(const nsIntRegion& aRegion)
|
||||
{
|
||||
mInvalidThebesContent = aRegion;
|
||||
mInvalidThebesContent.Or(mInvalidThebesContent, aRegion);
|
||||
}
|
||||
void SetInvalidateAllThebesContent()
|
||||
{
|
||||
@ -207,6 +207,8 @@ public:
|
||||
mAppUnitsPerDevPixel);
|
||||
}
|
||||
|
||||
const FrameLayerBuilder::ContainerParameters& ScaleParameters() { return mParameters; };
|
||||
|
||||
protected:
|
||||
/**
|
||||
* We keep a stack of these to represent the ThebesLayers that are
|
||||
@ -500,6 +502,8 @@ FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder)
|
||||
bool
|
||||
FrameLayerBuilder::DisplayItemDataEntry::HasNonEmptyContainerLayer()
|
||||
{
|
||||
if (mIsSharingContainerLayer)
|
||||
return true;
|
||||
for (PRUint32 i = 0; i < mData.Length(); ++i) {
|
||||
if (mData[i].mLayer->GetType() == Layer::TYPE_CONTAINER &&
|
||||
mData[i].mLayerState != LAYER_ACTIVE_EMPTY)
|
||||
@ -1191,7 +1195,7 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
|
||||
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
|
||||
* we are the first visible item in the ThebesLayerData object.
|
||||
*/
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_IMAGE && mVisibleRegion.IsEmpty()) {
|
||||
if (mVisibleRegion.IsEmpty() && aItem->GetType() == nsDisplayItem::TYPE_IMAGE) {
|
||||
mImage = static_cast<nsDisplayImage*>(aItem);
|
||||
mImageClip = aClip;
|
||||
} else {
|
||||
@ -1829,6 +1833,40 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyThebesLayerInvalidation(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aContainerFrame,
|
||||
nsDisplayItem* aContainerItem,
|
||||
ContainerState& aState,
|
||||
nsPoint* aCurrentOffset)
|
||||
{
|
||||
FrameProperties props = aContainerFrame->Properties();
|
||||
nsPoint* offsetAtLastPaint = static_cast<nsPoint*>
|
||||
(props.Get(ThebesLayerLastPaintOffsetProperty()));
|
||||
*aCurrentOffset = aContainerItem ? aContainerItem->ToReferenceFrame()
|
||||
: aBuilder->ToReferenceFrame(aContainerFrame);
|
||||
|
||||
nsRegion* invalidThebesContent = static_cast<nsRegion*>
|
||||
(props.Get(ThebesLayerInvalidRegionProperty()));
|
||||
if (invalidThebesContent) {
|
||||
nsPoint offset = offsetAtLastPaint ? *offsetAtLastPaint : *aCurrentOffset;
|
||||
invalidThebesContent->MoveBy(offset);
|
||||
const FrameLayerBuilder::ContainerParameters& scaleParameters = aState.ScaleParameters();
|
||||
aState.AddInvalidThebesContent(invalidThebesContent->
|
||||
ScaleToOutsidePixels(scaleParameters.mXScale, scaleParameters.mYScale,
|
||||
aState.GetAppUnitsPerDevPixel()));
|
||||
// We have to preserve the current contents of invalidThebesContent
|
||||
// because there might be multiple container layers for the same
|
||||
// frame and we need to invalidate the ThebesLayer children of all
|
||||
// of them.
|
||||
invalidThebesContent->MoveBy(-offset);
|
||||
} else {
|
||||
// The region was deleted to indicate that everything should be
|
||||
// invalidated.
|
||||
aState.SetInvalidateAllThebesContent();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<ContainerLayer>
|
||||
FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
@ -1838,7 +1876,6 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
const ContainerParameters& aParameters,
|
||||
const gfx3DMatrix* aTransform)
|
||||
{
|
||||
FrameProperties props = aContainerFrame->Properties();
|
||||
PRUint32 containerDisplayItemKey =
|
||||
aContainerItem ? aContainerItem->GetPerFrameKey() : 0;
|
||||
NS_ASSERTION(aContainerFrame, "Container display items here should have a frame");
|
||||
@ -1893,30 +1930,27 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
entry->mData.AppendElement(
|
||||
DisplayItemData(containerLayer, containerDisplayItemKey, LAYER_ACTIVE));
|
||||
}
|
||||
|
||||
nsPoint* offsetAtLastPaint = static_cast<nsPoint*>
|
||||
(props.Get(ThebesLayerLastPaintOffsetProperty()));
|
||||
nsPoint currentOffset = aBuilder->ToReferenceFrame(aContainerFrame);
|
||||
|
||||
nsRegion* invalidThebesContent(static_cast<nsRegion*>
|
||||
(props.Get(ThebesLayerInvalidRegionProperty())));
|
||||
if (invalidThebesContent) {
|
||||
nsPoint offset = offsetAtLastPaint ? *offsetAtLastPaint : currentOffset;
|
||||
invalidThebesContent->MoveBy(offset);
|
||||
state.SetInvalidThebesContent(invalidThebesContent->
|
||||
ScaleToOutsidePixels(scaleParameters.mXScale, scaleParameters.mYScale,
|
||||
state.GetAppUnitsPerDevPixel()));
|
||||
// We have to preserve the current contents of invalidThebesContent
|
||||
// because there might be multiple container layers for the same
|
||||
// frame and we need to invalidate the ThebesLayer children of all
|
||||
// of them.
|
||||
invalidThebesContent->MoveBy(-offset);
|
||||
} else {
|
||||
// The region was deleted to indicate that everything should be
|
||||
// invalidated.
|
||||
state.SetInvalidateAllThebesContent();
|
||||
}
|
||||
nsPoint currentOffset;
|
||||
ApplyThebesLayerInvalidation(aBuilder, aContainerFrame, aContainerItem, state,
|
||||
¤tOffset);
|
||||
SetHasContainerLayer(aContainerFrame, currentOffset);
|
||||
|
||||
nsAutoTArray<nsIFrame*,4> mergedFrames;
|
||||
if (aContainerItem) {
|
||||
aContainerItem->GetMergedFrames(&mergedFrames);
|
||||
}
|
||||
for (PRUint32 i = 0; i < mergedFrames.Length(); ++i) {
|
||||
nsIFrame* mergedFrame = mergedFrames[i];
|
||||
DisplayItemDataEntry* entry = mNewDisplayItemData.PutEntry(mergedFrame);
|
||||
if (entry) {
|
||||
// Ensure that UpdateDisplayItemDataForFrame recognizes that we
|
||||
// still have a container layer associated with this frame.
|
||||
entry->mIsSharingContainerLayer = true;
|
||||
}
|
||||
ApplyThebesLayerInvalidation(aBuilder, mergedFrame, nsnull, state,
|
||||
¤tOffset);
|
||||
SetHasContainerLayer(mergedFrame, currentOffset);
|
||||
}
|
||||
}
|
||||
|
||||
Clip clip;
|
||||
|
@ -440,9 +440,9 @@ protected:
|
||||
*/
|
||||
class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
|
||||
public:
|
||||
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key) {}
|
||||
DisplayItemDataEntry(const nsIFrame *key) : nsPtrHashKey<nsIFrame>(key), mIsSharingContainerLayer(false) {}
|
||||
DisplayItemDataEntry(DisplayItemDataEntry &toCopy) :
|
||||
nsPtrHashKey<nsIFrame>(toCopy.mKey)
|
||||
nsPtrHashKey<nsIFrame>(toCopy.mKey), mIsSharingContainerLayer(toCopy.mIsSharingContainerLayer)
|
||||
{
|
||||
// This isn't actually a copy-constructor; notice that it steals toCopy's
|
||||
// array. Be careful.
|
||||
@ -452,6 +452,7 @@ protected:
|
||||
bool HasNonEmptyContainerLayer();
|
||||
|
||||
nsAutoTArray<DisplayItemData, 1> mData;
|
||||
bool mIsSharingContainerLayer;
|
||||
|
||||
enum { ALLOW_MEMMOVE = false };
|
||||
};
|
||||
|
21
layout/reftests/bugs/728983-1-ref.html
Normal file
21
layout/reftests/bugs/728983-1-ref.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
<div style="-moz-column-count:2; column-count:2; width:300px; height:100px;">
|
||||
<div id="o" style="opacity:0.5; width:100px; height:200px; background:lime;">
|
||||
<div id="d" style="height:50px; width:80px; background:green; padding:2px">Text</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var o = document.getElementById("o");
|
||||
var d = document.getElementById("d");
|
||||
document.body.getBoundingClientRect();
|
||||
o.style.opacity = 0.8;
|
||||
function doTest() {
|
||||
o.style.opacity = 0.9;
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
23
layout/reftests/bugs/728983-1.html
Normal file
23
layout/reftests/bugs/728983-1.html
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<body>
|
||||
<div style="-moz-column-count:2; column-count:2; width:300px; height:100px;">
|
||||
<div id="o" style="opacity:0.5; width:100px; height:200px; background:lime;">
|
||||
<div id="d" style="height:50px; width:80px; background:red; padding:2px">Text</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var o = document.getElementById("o");
|
||||
var d = document.getElementById("d");
|
||||
document.body.getBoundingClientRect();
|
||||
o.style.opacity = 0.8;
|
||||
function doTest() {
|
||||
o.style.opacity = 0.9;
|
||||
document.body.getBoundingClientRect();
|
||||
d.style.background = "green";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
window.addEventListener("MozReftestInvalidate", doTest, false);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1694,6 +1694,7 @@ fuzzy-if(d2d,1,19) fuzzy-if(cocoaWidget,1,170) == 718521.html 718521-ref.html
|
||||
== 720987.html 720987-ref.html
|
||||
== 722923-1.html 722923-1-ref.html
|
||||
== 723484-1.html 723484-1-ref.html
|
||||
== 728983-1.html 728983-1-ref.html
|
||||
== 729143-1.html 729143-1-ref.html
|
||||
== 731521-1.html 731521-1-ref.html
|
||||
needs-focus == 731726-1.html 731726-1-ref.html
|
||||
|
Loading…
x
Reference in New Issue
Block a user