зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1487903. Fix invalidation of filter and mask items. r=mstange
Differential Revision: https://phabricator.services.mozilla.com/D5073
This commit is contained in:
Родитель
ed6f913e5d
Коммит
050bab0d8b
|
@ -112,6 +112,7 @@ struct BlobItemData
|
||||||
Matrix mMatrix; // updated to track the current transform to device space
|
Matrix mMatrix; // updated to track the current transform to device space
|
||||||
Matrix4x4Flagged mTransform; // only used with nsDisplayTransform items to detect transform changes
|
Matrix4x4Flagged mTransform; // only used with nsDisplayTransform items to detect transform changes
|
||||||
float mOpacity; // only used with nsDisplayOpacity items to detect change to opacity
|
float mOpacity; // only used with nsDisplayOpacity items to detect change to opacity
|
||||||
|
RefPtr<BasicLayerManager> mLayerManager;
|
||||||
|
|
||||||
IntRect mImageRect;
|
IntRect mImageRect;
|
||||||
LayerIntPoint mGroupOffset;
|
LayerIntPoint mGroupOffset;
|
||||||
|
@ -449,7 +450,7 @@ struct DIGroup
|
||||||
GP("mRect %d %d %d %d\n", aData->mRect.x, aData->mRect.y, aData->mRect.width, aData->mRect.height);
|
GP("mRect %d %d %d %d\n", aData->mRect.x, aData->mRect.y, aData->mRect.width, aData->mRect.height);
|
||||||
InvalidateRect(aData->mRect);
|
InvalidateRect(aData->mRect);
|
||||||
aData->mInvalid = true;
|
aData->mInvalid = true;
|
||||||
} else if (/*aData->mIsInvalid || XXX: handle image load invalidation */ (aItem->IsInvalid(invalid) && invalid.IsEmpty())) {
|
} else if (aData->mInvalid || /* XXX: handle image load invalidation */ (aItem->IsInvalid(invalid) && invalid.IsEmpty())) {
|
||||||
MOZ_RELEASE_ASSERT(imageRect.IsEqualEdges(aData->mImageRect));
|
MOZ_RELEASE_ASSERT(imageRect.IsEqualEdges(aData->mImageRect));
|
||||||
MOZ_RELEASE_ASSERT(mLayerBounds.TopLeft() == aData->mGroupOffset);
|
MOZ_RELEASE_ASSERT(mLayerBounds.TopLeft() == aData->mGroupOffset);
|
||||||
UniquePtr<nsDisplayItemGeometry> geometry(aItem->AllocateGeometry(aBuilder));
|
UniquePtr<nsDisplayItemGeometry> geometry(aItem->AllocateGeometry(aBuilder));
|
||||||
|
@ -806,6 +807,32 @@ struct DIGroup
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If we have an item we need to make sure it matches the current group
|
||||||
|
// otherwise it means the item switched groups and we need to invalidate
|
||||||
|
// it and recreate the data.
|
||||||
|
static BlobItemData*
|
||||||
|
GetBlobItemDataForGroup(nsDisplayItem* aItem, DIGroup* aGroup)
|
||||||
|
{
|
||||||
|
BlobItemData* data = GetBlobItemData(aItem);
|
||||||
|
if (data) {
|
||||||
|
MOZ_RELEASE_ASSERT(data->mGroup->mDisplayItems.Contains(data));
|
||||||
|
if (data->mGroup != aGroup) {
|
||||||
|
GP("group don't match %p %p\n", data->mGroup, aGroup);
|
||||||
|
data->ClearFrame();
|
||||||
|
// the item is for another group
|
||||||
|
// it should be cleared out as being unused at the end of this paint
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!data) {
|
||||||
|
GP("Allocating blob data\n");
|
||||||
|
data = new BlobItemData(aGroup, aItem);
|
||||||
|
aGroup->mDisplayItems.PutEntry(data);
|
||||||
|
}
|
||||||
|
data->mUsed = true;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, const IntRect& aItemBounds,
|
Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, const IntRect& aItemBounds,
|
||||||
nsDisplayList* aChildren, gfxContext* aContext,
|
nsDisplayList* aChildren, gfxContext* aContext,
|
||||||
|
@ -872,26 +899,32 @@ Grouper::PaintContainerItem(DIGroup* aGroup, nsDisplayItem* aItem, const IntRect
|
||||||
GP("Paint Mask\n");
|
GP("Paint Mask\n");
|
||||||
// We don't currently support doing invalidation inside nsDisplayMask
|
// We don't currently support doing invalidation inside nsDisplayMask
|
||||||
// for now just paint it as a single item
|
// for now just paint it as a single item
|
||||||
gfx::Size scale(1, 1);
|
BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
|
||||||
RefPtr<BasicLayerManager> blm = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
|
if (data->mLayerManager->GetRoot()) {
|
||||||
PaintByLayer(aItem, mDisplayListBuilder, blm, aContext, scale, [&]() {
|
data->mLayerManager->BeginTransaction();
|
||||||
static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(mDisplayListBuilder,
|
static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(mDisplayListBuilder,
|
||||||
aContext, blm);
|
aContext, data->mLayerManager);
|
||||||
});
|
if (data->mLayerManager->InTransaction()) {
|
||||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
data->mLayerManager->AbortTransaction();
|
||||||
|
}
|
||||||
|
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DisplayItemType::TYPE_FILTER: {
|
case DisplayItemType::TYPE_FILTER: {
|
||||||
GP("Paint Filter\n");
|
GP("Paint Filter\n");
|
||||||
// We don't currently support doing invalidation inside nsDisplayFilter
|
// We don't currently support doing invalidation inside nsDisplayFilter
|
||||||
// for now just paint it as a single item
|
// for now just paint it as a single item
|
||||||
RefPtr<BasicLayerManager> blm = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
|
BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
|
||||||
gfx::Size scale(1, 1);
|
if (data->mLayerManager->GetRoot()) {
|
||||||
PaintByLayer(aItem, mDisplayListBuilder, blm, aContext, scale, [&]() {
|
data->mLayerManager->BeginTransaction();
|
||||||
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(mDisplayListBuilder,
|
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(mDisplayListBuilder,
|
||||||
aContext, blm);
|
aContext, data->mLayerManager);
|
||||||
});
|
if (data->mLayerManager->InTransaction()) {
|
||||||
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
data->mLayerManager->AbortTransaction();
|
||||||
|
}
|
||||||
|
aContext->GetDrawTarget()->FlushItem(aItemBounds);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,32 +998,6 @@ IsItemProbablyActive(nsDisplayItem* aItem, nsDisplayListBuilder* aDisplayListBui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have an item we need to make sure it matches the current group
|
|
||||||
// otherwise it means the item switched groups and we need to invalidate
|
|
||||||
// it and recreate the data.
|
|
||||||
static BlobItemData*
|
|
||||||
GetBlobItemDataForGroup(nsDisplayItem* aItem, DIGroup* aGroup)
|
|
||||||
{
|
|
||||||
BlobItemData* data = GetBlobItemData(aItem);
|
|
||||||
if (data) {
|
|
||||||
MOZ_RELEASE_ASSERT(data->mGroup->mDisplayItems.Contains(data));
|
|
||||||
if (data->mGroup != aGroup) {
|
|
||||||
GP("group don't match %p %p\n", data->mGroup, aGroup);
|
|
||||||
data->ClearFrame();
|
|
||||||
// the item is for another group
|
|
||||||
// it should be cleared out as being unused at the end of this paint
|
|
||||||
data = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!data) {
|
|
||||||
GP("Allocating blob data\n");
|
|
||||||
data = new BlobItemData(aGroup, aItem);
|
|
||||||
aGroup->mDisplayItems.PutEntry(data);
|
|
||||||
}
|
|
||||||
data->mUsed = true;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This does a pass over the display lists and will join the display items
|
// This does a pass over the display lists and will join the display items
|
||||||
// into groups as well as paint them
|
// into groups as well as paint them
|
||||||
void
|
void
|
||||||
|
@ -1076,6 +1083,10 @@ Grouper::ConstructGroupInsideInactive(WebRenderCommandBuilder* aCommandBuilder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BuildLayer(nsDisplayItem* aItem, BlobItemData* aData,
|
||||||
|
nsDisplayListBuilder* aDisplayListBuilder,
|
||||||
|
const gfx::Size& aScale);
|
||||||
|
|
||||||
void
|
void
|
||||||
Grouper::ConstructItemInsideInactive(WebRenderCommandBuilder* aCommandBuilder,
|
Grouper::ConstructItemInsideInactive(WebRenderCommandBuilder* aCommandBuilder,
|
||||||
wr::DisplayListBuilder& aBuilder,
|
wr::DisplayListBuilder& aBuilder,
|
||||||
|
@ -1084,8 +1095,15 @@ Grouper::ConstructItemInsideInactive(WebRenderCommandBuilder* aCommandBuilder,
|
||||||
const StackingContextHelper& aSc)
|
const StackingContextHelper& aSc)
|
||||||
{
|
{
|
||||||
nsDisplayList* children = aItem->GetChildren();
|
nsDisplayList* children = aItem->GetChildren();
|
||||||
|
BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
|
||||||
|
|
||||||
if (aItem->GetType() == DisplayItemType::TYPE_TRANSFORM) {
|
if (aItem->GetType() == DisplayItemType::TYPE_FILTER ||
|
||||||
|
aItem->GetType() == DisplayItemType::TYPE_MASK) {
|
||||||
|
gfx::Size scale(1, 1);
|
||||||
|
// If ComputeDifferences finds any change, we invalidate the entire container item.
|
||||||
|
// This is needed because blob merging requires the entire item to be within the invalid region.
|
||||||
|
data->mInvalid = BuildLayer(aItem, data, mDisplayListBuilder, scale);
|
||||||
|
} else if (aItem->GetType() == DisplayItemType::TYPE_TRANSFORM) {
|
||||||
nsDisplayTransform* transformItem = static_cast<nsDisplayTransform*>(aItem);
|
nsDisplayTransform* transformItem = static_cast<nsDisplayTransform*>(aItem);
|
||||||
const Matrix4x4Flagged& t = transformItem->GetTransform();
|
const Matrix4x4Flagged& t = transformItem->GetTransform();
|
||||||
Matrix t2d;
|
Matrix t2d;
|
||||||
|
@ -1101,12 +1119,13 @@ Grouper::ConstructItemInsideInactive(WebRenderCommandBuilder* aCommandBuilder,
|
||||||
|
|
||||||
mTransform = m;
|
mTransform = m;
|
||||||
} else if (children) {
|
} else if (children) {
|
||||||
|
sIndent++;
|
||||||
ConstructGroupInsideInactive(aCommandBuilder, aBuilder, aResources, aGroup, children, aSc);
|
ConstructGroupInsideInactive(aCommandBuilder, aBuilder, aResources, aGroup, children, aSc);
|
||||||
|
sIndent--;
|
||||||
}
|
}
|
||||||
|
|
||||||
GP("Including %s of %d\n", aItem->Name(), aGroup->mDisplayItems.Count());
|
GP("Including %s of %d\n", aItem->Name(), aGroup->mDisplayItems.Count());
|
||||||
|
|
||||||
BlobItemData* data = GetBlobItemDataForGroup(aItem, aGroup);
|
|
||||||
aGroup->ComputeGeometryChange(aItem, data, mTransform, mDisplayListBuilder); // we compute the geometry change here because we have the transform around still
|
aGroup->ComputeGeometryChange(aItem, data, mTransform, mDisplayListBuilder); // we compute the geometry change here because we have the transform around still
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1556,6 +1575,50 @@ WebRenderCommandBuilder::PushImage(nsDisplayItem* aItem,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
BuildLayer(nsDisplayItem* aItem,
|
||||||
|
BlobItemData* aData,
|
||||||
|
nsDisplayListBuilder* aDisplayListBuilder,
|
||||||
|
const gfx::Size& aScale)
|
||||||
|
{
|
||||||
|
if (!aData->mLayerManager) {
|
||||||
|
aData->mLayerManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
|
||||||
|
}
|
||||||
|
RefPtr<BasicLayerManager> blm = aData->mLayerManager;
|
||||||
|
UniquePtr<LayerProperties> props;
|
||||||
|
if (blm->GetRoot()) {
|
||||||
|
props = LayerProperties::CloneFrom(blm->GetRoot());
|
||||||
|
}
|
||||||
|
FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
|
||||||
|
layerBuilder->Init(aDisplayListBuilder, blm, nullptr, true);
|
||||||
|
layerBuilder->DidBeginRetainedLayerTransaction(blm);
|
||||||
|
|
||||||
|
blm->BeginTransaction();
|
||||||
|
bool isInvalidated = false;
|
||||||
|
|
||||||
|
ContainerLayerParameters param(aScale.width, aScale.height);
|
||||||
|
RefPtr<Layer> root = aItem->BuildLayer(aDisplayListBuilder, blm, param);
|
||||||
|
|
||||||
|
if (root) {
|
||||||
|
blm->SetRoot(root);
|
||||||
|
layerBuilder->WillEndTransaction();
|
||||||
|
|
||||||
|
// Check if there is any invalidation region.
|
||||||
|
nsIntRegion invalid;
|
||||||
|
if (props) {
|
||||||
|
props->ComputeDifferences(root, invalid, nullptr);
|
||||||
|
if (!invalid.IsEmpty()) {
|
||||||
|
isInvalidated = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
isInvalidated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blm->AbortTransaction();
|
||||||
|
|
||||||
|
return isInvalidated;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
PaintByLayer(nsDisplayItem* aItem,
|
PaintByLayer(nsDisplayItem* aItem,
|
||||||
nsDisplayListBuilder* aDisplayListBuilder,
|
nsDisplayListBuilder* aDisplayListBuilder,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче