Bug 1462672 - Part 7: Add FLBDisplayItemIterator support for flattening inactive transforms r=mattwoodrow

MozReview-Commit-ID: 8cv6qh1s4qy

--HG--
extra : rebase_source : 4c4a6e87bd2701c0ff047d8e41eee88830edadab
This commit is contained in:
Miko Mynttinen 2018-07-17 01:34:15 +02:00
Родитель ed0fd2fe79
Коммит 03a67e4d61
3 изменённых файлов: 170 добавлений и 118 удалений

Просмотреть файл

@ -133,6 +133,50 @@ struct DisplayItemEntry {
DisplayItemEntryType mType;
};
enum class MarkerType {
StartMarker,
EndMarker
};
template<MarkerType markerType>
static bool
AddMarkerIfNeeded(nsDisplayItem* aItem,
std::deque<DisplayItemEntry>& aMarkers)
{
const DisplayItemType type = aItem->GetType();
if (type != DisplayItemType::TYPE_OPACITY &&
type != DisplayItemType::TYPE_TRANSFORM) {
return false;
}
DisplayItemEntryType marker;
// Just a fancy way to avoid writing two separate functions to select between
// PUSH and POP markers. This is done during compile time based on |markerType|.
#define GET_MARKER(start_marker, end_marker)\
std::conditional<markerType == MarkerType::StartMarker,\
std::integral_constant<DisplayItemEntryType, start_marker>,\
std::integral_constant<DisplayItemEntryType, end_marker>\
>::type::value;
switch (type) {
case DisplayItemType::TYPE_OPACITY:
marker = GET_MARKER(DisplayItemEntryType::PUSH_OPACITY,
DisplayItemEntryType::POP_OPACITY);
break;
case DisplayItemType::TYPE_TRANSFORM:
marker = GET_MARKER(DisplayItemEntryType::PUSH_TRANSFORM,
DisplayItemEntryType::POP_TRANSFORM);
break;
default:
MOZ_ASSERT_UNREACHABLE("Invalid display item type!");
break;
}
aMarkers.emplace_back(aItem, marker);
return true;
}
class FLBDisplayItemIterator : protected FlattenedDisplayItemIterator
{
public:
@ -188,8 +232,7 @@ private:
return;
}
if (aItem->GetType() == DisplayItemType::TYPE_OPACITY) {
mMarkers.emplace_back(aItem, DisplayItemEntryType::PUSH_OPACITY);
if (AddMarkerIfNeeded<MarkerType::StartMarker>(aItem, mMarkers)) {
mActiveMarkers.AppendElement(aItem);
}
@ -203,12 +246,13 @@ private:
return;
}
if (aItem->GetType() == DisplayItemType::TYPE_OPACITY) {
mMarkers.emplace_back(aItem, DisplayItemEntryType::POP_OPACITY);
if (AddMarkerIfNeeded<MarkerType::EndMarker>(aItem, mMarkers)) {
mActiveMarkers.RemoveLastElement();
}
}
bool NextItemWantsInactiveLayer();
std::deque<DisplayItemEntry> mMarkers;
AutoTArray<nsDisplayItem*, 4> mActiveMarkers;
ContainerState* mState;
@ -1576,6 +1620,16 @@ protected:
CachedScrollMetadata mCachedScrollMetadata;
};
bool
FLBDisplayItemIterator::NextItemWantsInactiveLayer()
{
LayerState layerState = mNext->GetLayerState(mState->mBuilder,
mState->mManager,
mState->mParameters);
return layerState == LayerState::LAYER_INACTIVE;
}
bool
FLBDisplayItemIterator::ShouldFlattenNextItem()
{
@ -1587,7 +1641,13 @@ FLBDisplayItemIterator::ShouldFlattenNextItem()
return false;
}
if (mNext->GetType() == DisplayItemType::TYPE_OPACITY) {
const DisplayItemType type = mNext->GetType();
if (type != DisplayItemType::TYPE_OPACITY &&
type != DisplayItemType::TYPE_TRANSFORM) {
return true;
}
if (type == DisplayItemType::TYPE_OPACITY) {
nsDisplayOpacity* opacity = static_cast<nsDisplayOpacity*>(mNext);
if (opacity->OpacityAppliedToChildren()) {
@ -1595,25 +1655,16 @@ FLBDisplayItemIterator::ShouldFlattenNextItem()
// been applied to children.
return true;
}
if (!mState->mManager->IsWidgetLayerManager()) {
// Do not flatten opacity inside an inactive layer tree.
return false;
}
LayerState layerState = mNext->GetLayerState(mState->mBuilder,
mState->mManager,
mState->mParameters);
// Do not flatten opacity if child display items require an active layer.
if (layerState != LayerState::LAYER_NONE &&
layerState != LayerState::LAYER_INACTIVE) {
return false;
}
mStoreMarker = true;
}
if (mState->IsInInactiveLayer() || !NextItemWantsInactiveLayer()) {
// Do not flatten nested inactive display items, or display items that want
// an active layer.
return false;
}
// Flatten inactive nsDisplayOpacity and nsDisplayTransform.
mStoreMarker = true;
return true;
}

Просмотреть файл

@ -49,7 +49,9 @@ enum class DisplayItemEntryType {
ITEM,
PUSH_OPACITY,
PUSH_OPACITY_WITH_BG,
POP_OPACITY
POP_OPACITY,
PUSH_TRANSFORM,
POP_TRANSFORM
};
/**

Просмотреть файл

@ -2630,7 +2630,7 @@ public:
* system as this item (i.e., they have the same reference frame),
* return the list.
*/
virtual nsDisplayList* GetSameCoordinateSystemChildren() const
virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const
{
return nullptr;
}
@ -3273,92 +3273,6 @@ private:
bool mForceTransparentSurface;
};
class FlattenedDisplayItemIterator
{
public:
FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
const bool aResolveFlattening = true)
: mBuilder(aBuilder)
, mNext(aList->GetBottom())
{
if (aResolveFlattening) {
// This is done conditionally in case subclass overrides
// ShouldFlattenNextItem().
ResolveFlattening();
}
}
virtual ~FlattenedDisplayItemIterator()
{
MOZ_ASSERT(!HasNext());
}
nsDisplayItem* GetNext()
{
nsDisplayItem* next = mNext;
// Advance mNext to the following item
if (next) {
mNext = mNext->GetAbove();
ResolveFlattening();
}
return next;
}
bool HasNext() const
{
return mNext || !mStack.IsEmpty();
}
nsDisplayItem* PeekNext()
{
return mNext;
}
protected:
bool AtEndOfNestedList() const
{
return !mNext && mStack.Length() > 0;
}
virtual bool ShouldFlattenNextItem()
{
return mNext && mNext->ShouldFlattenAway(mBuilder);
}
void ResolveFlattening()
{
// Handle the case where we reach the end of a nested list, or the current
// item should start a new nested list. Repeat this until we find an actual
// item, or the very end of the outer list.
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
if (AtEndOfNestedList()) {
// Pop the last item off the stack.
mNext = mStack.LastElement();
EndNested(mNext);
mStack.RemoveElementAt(mStack.Length() - 1);
// We stored the item that was flattened, so advance to the next.
mNext = mNext->GetAbove();
} else {
// This item wants to be flattened. Store the current item on the stack,
// and use the first item in the child list instead.
mStack.AppendElement(mNext);
StartNested(mNext);
nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren();
mNext = childItems->GetBottom();
}
}
}
virtual void EndNested(nsDisplayItem* aItem) {}
virtual void StartNested(nsDisplayItem* aItem) {}
nsDisplayListBuilder* mBuilder;
nsDisplayItem* mNext;
AutoTArray<nsDisplayItem*, 10> mStack;
};
/**
* This is passed as a parameter to nsIFrame::BuildDisplayList. That method
* will put any generated items onto the appropriate list given here. It's
@ -3535,6 +3449,97 @@ public:
nsTArray<OldItemInfo> mOldItems;
};
class FlattenedDisplayItemIterator
{
public:
FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
const bool aResolveFlattening = true)
: mBuilder(aBuilder)
, mNext(aList->GetBottom())
{
if (aResolveFlattening) {
// This is done conditionally in case subclass overrides
// ShouldFlattenNextItem().
ResolveFlattening();
}
}
virtual ~FlattenedDisplayItemIterator()
{
MOZ_ASSERT(!HasNext());
}
nsDisplayItem* GetNext()
{
nsDisplayItem* next = mNext;
// Advance mNext to the following item
if (next) {
mNext = mNext->GetAbove();
ResolveFlattening();
}
return next;
}
bool HasNext() const
{
return mNext || !mStack.IsEmpty();
}
nsDisplayItem* PeekNext()
{
return mNext;
}
protected:
bool AtEndOfNestedList() const
{
return !mNext && mStack.Length() > 0;
}
virtual bool ShouldFlattenNextItem()
{
return mNext && mNext->ShouldFlattenAway(mBuilder);
}
void ResolveFlattening()
{
// Handle the case where we reach the end of a nested list, or the current
// item should start a new nested list. Repeat this until we find an actual
// item, or the very end of the outer list.
while (AtEndOfNestedList() || ShouldFlattenNextItem()) {
if (AtEndOfNestedList()) {
// Pop the last item off the stack.
mNext = mStack.LastElement();
EndNested(mNext);
mStack.RemoveElementAt(mStack.Length() - 1);
// We stored the item that was flattened, so advance to the next.
mNext = mNext->GetAbove();
} else {
// This item wants to be flattened. Store the current item on the stack,
// and use the first item in the child list instead.
mStack.AppendElement(mNext);
StartNested(mNext);
nsDisplayList* childItems =
mNext->GetType() != DisplayItemType::TYPE_TRANSFORM
? mNext->GetSameCoordinateSystemChildren()
: mNext->GetChildren();
mNext = childItems->GetBottom();
}
}
}
virtual void EndNested(nsDisplayItem* aItem) {}
virtual void StartNested(nsDisplayItem* aItem) {}
nsDisplayListBuilder* mBuilder;
nsDisplayItem* mNext;
AutoTArray<nsDisplayItem*, 10> mStack;
};
class nsDisplayImageContainer : public nsDisplayItem {
public:
typedef mozilla::LayerIntPoint LayerIntPoint;
@ -5043,7 +5048,7 @@ public:
virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) const override;
virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const override
{
NS_ASSERTION(mListPtr->IsEmpty() || !ReferenceFrame() ||
!mListPtr->GetBottom()->ReferenceFrame() ||
@ -6374,12 +6379,6 @@ public:
return mStoredList.GetChildren();
}
virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const override
{
return mShouldFlatten ? mStoredList.GetChildren()
: nullptr;
}
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override;
virtual void SetActiveScrolledRoot(const ActiveScrolledRoot* aActiveScrolledRoot) override
@ -6808,7 +6807,7 @@ public:
return true;
}
virtual nsDisplayList* GetSameCoordinateSystemChildren() const override
virtual RetainedDisplayList* GetSameCoordinateSystemChildren() const override
{
return mList.GetChildren();
}