зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
ed0fd2fe79
Коммит
03a67e4d61
|
@ -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();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче