зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1364295. Walk the frame tree looking for a scrollframe to add a displayport to, or one that already has a displayport before displaylist building. r=mstange
And stop creating displayports during display list building. One thing we can investigate in the future is whether we should use the value of mHaveScrollableDisplayPort stored on the display list builder retained between paints. If it's true then we could potentially skip this pass. It would mean that if there are large changes to the page we wouldn't set a displayport. And we'd need to make sure the value is cleared when we load a new page.
This commit is contained in:
Родитель
718b6fff3e
Коммит
1402ea7c2d
|
@ -39,6 +39,7 @@
|
|||
#include "nsViewManager.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsRegion.h"
|
||||
|
@ -3425,13 +3426,15 @@ nsLayoutUtils::CalculateAndSetDisplayPortMargins(nsIScrollableFrame* aScrollFram
|
|||
content, presShell, displayportMargins, 0, aRepaintMode);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
nsLayoutUtils::MaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
|
||||
nsIFrame* aScrollFrame) {
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode)
|
||||
{
|
||||
nsIContent* content = aScrollFrame->GetContent();
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollFrame);
|
||||
if (!content || !scrollableFrame) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool haveDisplayPort = HasDisplayPort(content);
|
||||
|
@ -3447,7 +3450,7 @@ nsLayoutUtils::MaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
|
|||
|
||||
// If we don't already have a displayport, calculate and set one.
|
||||
if (!haveDisplayPort) {
|
||||
CalculateAndSetDisplayPortMargins(scrollableFrame, nsLayoutUtils::RepaintMode::DoNotRepaint);
|
||||
CalculateAndSetDisplayPortMargins(scrollableFrame, aRepaintMode);
|
||||
#ifdef DEBUG
|
||||
haveDisplayPort = HasDisplayPort(content);
|
||||
MOZ_ASSERT(haveDisplayPort, "should have a displayport after having just set it");
|
||||
|
@ -3456,7 +3459,9 @@ nsLayoutUtils::MaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
|
|||
|
||||
// Record that the we now have a scrollable display port.
|
||||
aBuilder.SetHaveScrollableDisplayPort();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIScrollableFrame*
|
||||
|
@ -3495,6 +3500,43 @@ nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(nsIFrame* aFra
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
||||
nsIFrame* aFrame, nsDisplayListBuilder& aBuilder)
|
||||
{
|
||||
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
|
||||
if (sf) {
|
||||
if (MaybeCreateDisplayPort(aBuilder, aFrame, RepaintMode::Repaint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (aFrame->IsPlaceholderFrame()) {
|
||||
nsPlaceholderFrame* placeholder = static_cast<nsPlaceholderFrame*>(aFrame);
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
||||
placeholder->GetOutOfFlowFrame(), aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (aFrame->IsSubDocumentFrame()) {
|
||||
nsIPresShell* presShell =
|
||||
static_cast<nsSubDocumentFrame*>(aFrame)->GetSubdocumentPresShellForPainting(0);
|
||||
nsIFrame* root = presShell ? presShell->GetRootFrame() : nullptr;
|
||||
if (root) {
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(root, aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (nsIFrame* child : aFrame->PrincipalChildList()) {
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(child, aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsLayoutUtils::ExpireDisplayPortOnAsyncScrollableAncestor(nsIFrame* aFrame)
|
||||
{
|
||||
|
@ -3685,6 +3727,11 @@ nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame,
|
|||
}
|
||||
}
|
||||
|
||||
builder.ClearHaveScrollableDisplayPort();
|
||||
if (builder.IsPaintingToWindow()) {
|
||||
MaybeCreateDisplayPortInFirstScrollFrameEncountered(aFrame, builder);
|
||||
}
|
||||
|
||||
nsRect dirtyRect = visibleRegion.GetBounds();
|
||||
|
||||
{
|
||||
|
|
|
@ -1066,6 +1066,10 @@ public:
|
|||
const nscoord aRadii[8],
|
||||
const nsRect& aTestRect);
|
||||
|
||||
static bool MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
||||
nsIFrame* aFrame, nsDisplayListBuilder& aBuilder);
|
||||
|
||||
|
||||
enum class PaintFrameFlags : uint32_t {
|
||||
PAINT_IN_TRANSFORM = 0x01,
|
||||
PAINT_SYNC_DECODE_IMAGES = 0x02,
|
||||
|
@ -2814,10 +2818,15 @@ public:
|
|||
* displayport yet (as tracked by |aBuilder|), calculate and set a
|
||||
* displayport.
|
||||
*
|
||||
* This is intended to be called during display list building.
|
||||
* If this is called during display list building pass DoNotRepaint in
|
||||
* aRepaintMode.
|
||||
*
|
||||
* Returns true if there is a displayport on an async scrollable scrollframe
|
||||
* after this call, either because one was just added or it already existed.
|
||||
*/
|
||||
static void MaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
|
||||
nsIFrame* aScrollFrame);
|
||||
static bool MaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder,
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode);
|
||||
|
||||
static nsIScrollableFrame* GetAsyncScrollableAncestorFrame(nsIFrame* aTarget);
|
||||
|
||||
|
|
|
@ -3621,8 +3621,6 @@ ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
|||
wasUsingDisplayPort = nsLayoutUtils::HasDisplayPort(content);
|
||||
|
||||
if (aAllowCreateDisplayPort) {
|
||||
nsLayoutUtils::MaybeCreateDisplayPort(*aBuilder, mOuter);
|
||||
|
||||
nsRect displayportBase = *aDirtyRect;
|
||||
nsPresContext* pc = mOuter->PresContext();
|
||||
if (mIsRoot && (pc->IsRootContentDocument() || !pc->GetParentPresContext())) {
|
||||
|
|
|
@ -586,6 +586,7 @@ public:
|
|||
|
||||
bool HaveScrollableDisplayPort() const { return mHaveScrollableDisplayPort; }
|
||||
void SetHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = true; }
|
||||
void ClearHaveScrollableDisplayPort() { mHaveScrollableDisplayPort = false; }
|
||||
|
||||
bool SetIsCompositingCheap(bool aCompositingCheap) {
|
||||
bool temp = mIsCompositingCheap;
|
||||
|
|
Загрузка…
Ссылка в новой задаче