mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 976412. Part 1: Fix logic for determining when a display item can be placed in a layer. r=mattwoodrow
--HG-- extra : rebase_source : c390532cb3f6252fa388dfbe8176f4f911dfbdb3
This commit is contained in:
parent
a139418d45
commit
b8d068bc09
@ -234,7 +234,9 @@ static inline MaskLayerImageCache* GetMaskLayerImageCache()
|
||||
class ThebesLayerData {
|
||||
public:
|
||||
ThebesLayerData() :
|
||||
mAnimatedGeometryRoot(nullptr), mReferenceFrame(nullptr),
|
||||
mAnimatedGeometryRoot(nullptr),
|
||||
mFixedPosFrameForLayerData(nullptr),
|
||||
mReferenceFrame(nullptr),
|
||||
mLayer(nullptr),
|
||||
mIsSolidColorInVisibleRegion(false),
|
||||
mSingleItemFixedToViewport(false),
|
||||
@ -321,11 +323,16 @@ public:
|
||||
mVisibleAboveRegion.SetEmpty();
|
||||
}
|
||||
|
||||
bool IsBelow(const nsIntRect& aRect)
|
||||
bool DrawAboveRegionIntersects(const nsIntRect& aRect)
|
||||
{
|
||||
return mAllDrawingAbove || mDrawAboveRegion.Intersects(aRect);
|
||||
}
|
||||
|
||||
bool DrawRegionIntersects(const nsIntRect& aRect)
|
||||
{
|
||||
return IsSubjectToAsyncTransforms() || mDrawRegion.Intersects(aRect);
|
||||
}
|
||||
|
||||
bool IntersectsVisibleAboveRegion(const nsIntRegion& aVisibleRegion)
|
||||
{
|
||||
if (mAllDrawingAbove) {
|
||||
@ -339,6 +346,11 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsSubjectToAsyncTransforms()
|
||||
{
|
||||
return mFixedPosFrameForLayerData != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* The region of visible content in the layer, relative to the
|
||||
* container layer (which is at the snapped top-left of the display
|
||||
@ -375,6 +387,12 @@ public:
|
||||
* active scrolled root.
|
||||
*/
|
||||
const nsIFrame* mAnimatedGeometryRoot;
|
||||
/**
|
||||
* If non-null, the frame from which we'll extract "fixed positioning"
|
||||
* metadata for this layer. This can be a position:fixed frame or a viewport
|
||||
* frame; the latter case is used for background-attachment:fixed content.
|
||||
*/
|
||||
const nsIFrame* mFixedPosFrameForLayerData;
|
||||
const nsIFrame* mReferenceFrame;
|
||||
ThebesLayer* mLayer;
|
||||
/**
|
||||
@ -620,10 +638,11 @@ protected:
|
||||
* are directly on the viewport (e.g. background-attachment:fixed backgrounds).
|
||||
*/
|
||||
const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
|
||||
bool aDisplayItemFixedToViewport,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion = nullptr);
|
||||
bool aDisplayItemFixedToViewport);
|
||||
void AdjustLayerDataForFixedPositioning(const nsIFrame* aFixedPosFrame,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion = nullptr);
|
||||
/**
|
||||
* Set fixed-pos layer metadata on aLayer according to the data for aFixedPosFrame.
|
||||
*/
|
||||
@ -1676,10 +1695,7 @@ ThebesLayerData::CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder)
|
||||
|
||||
const nsIFrame*
|
||||
ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
|
||||
bool aDisplayItemFixedToViewport,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion)
|
||||
bool aDisplayItemFixedToViewport)
|
||||
{
|
||||
if (!mManager->IsWidgetLayerManager()) {
|
||||
// Never attach any fixed-pos metadata to inactive layers, it's pointless!
|
||||
@ -1714,9 +1730,27 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::AdjustLayerDataForFixedPositioning(const nsIFrame* aFixedPosFrame,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion)
|
||||
{
|
||||
if (!aFixedPosFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRect displayPort;
|
||||
nsPresContext* presContext = aFixedPosFrame->PresContext();
|
||||
DebugOnly<bool> hasDisplayPort =
|
||||
nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort);
|
||||
NS_ASSERTION(hasDisplayPort, "No fixed-pos layer data if there's no displayport");
|
||||
// Display ports are relative to the viewport, convert it to be relative
|
||||
// to our reference frame.
|
||||
nsIFrame* viewport = presContext->PresShell()->GetRootFrame();
|
||||
displayPort += viewport->GetOffsetToCrossDoc(mContainerReferenceFrame);
|
||||
nsIntRegion newVisibleRegion;
|
||||
newVisibleRegion.And(ScaleToOutsidePixels(displayPort, false),
|
||||
@ -1727,7 +1761,6 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
|
||||
}
|
||||
*aVisibleRegion = newVisibleRegion;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1804,12 +1837,10 @@ ContainerState::PopThebesLayerData()
|
||||
int32_t lastIndex = mThebesLayerDataStack.Length() - 1;
|
||||
ThebesLayerData* data = mThebesLayerDataStack[lastIndex];
|
||||
|
||||
const nsIFrame* fixedPosFrameForLayerData =
|
||||
FindFixedPosFrameForLayerData(data->mAnimatedGeometryRoot,
|
||||
data->mSingleItemFixedToViewport,
|
||||
data->mDrawRegion,
|
||||
&data->mVisibleRegion,
|
||||
&data->mIsSolidColorInVisibleRegion);
|
||||
AdjustLayerDataForFixedPositioning(data->mFixedPosFrameForLayerData,
|
||||
data->mDrawRegion,
|
||||
&data->mVisibleRegion,
|
||||
&data->mIsSolidColorInVisibleRegion);
|
||||
nsRefPtr<Layer> layer;
|
||||
nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
|
||||
|
||||
@ -1935,7 +1966,7 @@ ContainerState::PopThebesLayerData()
|
||||
}
|
||||
layer->SetContentFlags(flags);
|
||||
|
||||
SetFixedPositionLayerData(layer, fixedPosFrameForLayerData);
|
||||
SetFixedPositionLayerData(layer, data->mFixedPosFrameForLayerData);
|
||||
|
||||
ThebesLayerData* containingThebesLayerData =
|
||||
mLayerBuilder->GetContainingThebesLayerData();
|
||||
@ -2138,7 +2169,7 @@ ThebesLayerData::Accumulate(ContainerState* aState,
|
||||
ThebesLayerData*
|
||||
ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
const nsIFrame* aActiveScrolledRoot,
|
||||
const nsIFrame* aAnimatedGeometryRoot,
|
||||
const nsPoint& aTopLeft,
|
||||
bool aShouldFixToViewport)
|
||||
{
|
||||
@ -2146,31 +2177,39 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
int32_t lowestUsableLayerWithScrolledRoot = -1;
|
||||
int32_t topmostLayerWithScrolledRoot = -1;
|
||||
for (i = mThebesLayerDataStack.Length() - 1; i >= 0; --i) {
|
||||
ThebesLayerData* data = mThebesLayerDataStack[i];
|
||||
// ThebesLayers for items returning true from ShouldFixToViewport should
|
||||
// not be added to (or have content moved below them),
|
||||
// since they will receive special treatment for async scrolling.
|
||||
// If the item is going to be fixed to the viewport, don't let it combine
|
||||
// with any existing layer.
|
||||
if (data->IsBelow(aVisibleRect) || data->mSingleItemFixedToViewport ||
|
||||
aShouldFixToViewport) {
|
||||
// Don't let should-fix-to-viewport items share a layer with any other items.
|
||||
if (aShouldFixToViewport) {
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
if (data->mAnimatedGeometryRoot == aActiveScrolledRoot) {
|
||||
ThebesLayerData* data = mThebesLayerDataStack[i];
|
||||
// Give up if there is content drawn above (in z-order) this layer that
|
||||
// intersects aItem's visible region; aItem must be placed in a
|
||||
// layer this layer.
|
||||
if (data->DrawAboveRegionIntersects(aVisibleRect)) {
|
||||
++i;
|
||||
break;
|
||||
}
|
||||
// If the animated scrolled roots are the same and we can share this layer
|
||||
// with the item, note this as a usable layer.
|
||||
if (data->mAnimatedGeometryRoot == aAnimatedGeometryRoot &&
|
||||
!data->mSingleItemFixedToViewport) {
|
||||
lowestUsableLayerWithScrolledRoot = i;
|
||||
if (topmostLayerWithScrolledRoot < 0) {
|
||||
topmostLayerWithScrolledRoot = i;
|
||||
}
|
||||
}
|
||||
if (data->mDrawRegion.Intersects(aVisibleRect))
|
||||
// If the layer's drawn region intersects the item, stop now since no
|
||||
// lower layer will be usable. Do the same if the layer is subject to
|
||||
// async transforms, since we don't know where it will really be drawn.
|
||||
if (data->DrawRegionIntersects(aVisibleRect))
|
||||
break;
|
||||
}
|
||||
if (topmostLayerWithScrolledRoot < 0) {
|
||||
--i;
|
||||
for (; i >= 0; --i) {
|
||||
ThebesLayerData* data = mThebesLayerDataStack[i];
|
||||
if (data->mAnimatedGeometryRoot == aActiveScrolledRoot) {
|
||||
if (data->mAnimatedGeometryRoot == aAnimatedGeometryRoot) {
|
||||
topmostLayerWithScrolledRoot = i;
|
||||
break;
|
||||
}
|
||||
@ -2186,12 +2225,14 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
ThebesLayerData* thebesLayerData = nullptr;
|
||||
if (lowestUsableLayerWithScrolledRoot < 0) {
|
||||
nsRefPtr<ThebesLayer> layer =
|
||||
CreateOrRecycleThebesLayer(aActiveScrolledRoot, aItem->ReferenceFrame(), aTopLeft);
|
||||
CreateOrRecycleThebesLayer(aAnimatedGeometryRoot, aItem->ReferenceFrame(), aTopLeft);
|
||||
|
||||
thebesLayerData = new ThebesLayerData();
|
||||
mThebesLayerDataStack.AppendElement(thebesLayerData);
|
||||
thebesLayerData->mLayer = layer;
|
||||
thebesLayerData->mAnimatedGeometryRoot = aActiveScrolledRoot;
|
||||
thebesLayerData->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
|
||||
thebesLayerData->mFixedPosFrameForLayerData =
|
||||
FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport);
|
||||
thebesLayerData->mReferenceFrame = aItem->ReferenceFrame();
|
||||
thebesLayerData->mSingleItemFixedToViewport = aShouldFixToViewport;
|
||||
|
||||
@ -2428,11 +2469,12 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
NS_ASSERTION(!ownLayer->AsThebesLayer(),
|
||||
"Should never have created a dedicated Thebes layer!");
|
||||
|
||||
nsIntRegion visibleRegion(itemVisibleRect);
|
||||
const nsIFrame* fixedPosFrame =
|
||||
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport,
|
||||
nsIntRegion(itemDrawRect), &visibleRegion);
|
||||
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport);
|
||||
if (fixedPosFrame) {
|
||||
nsIntRegion visibleRegion(itemVisibleRect);
|
||||
AdjustLayerDataForFixedPositioning(fixedPosFrame,
|
||||
nsIntRegion(itemDrawRect), &visibleRegion);
|
||||
itemVisibleRect = visibleRegion.GetBounds();
|
||||
}
|
||||
SetFixedPositionLayerData(ownLayer, fixedPosFrame);
|
||||
|
Loading…
Reference in New Issue
Block a user