mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 946952 - Run a 'compressed' paint up to 1 second after skipping the ColorLayer optimization. r=roc
This commit is contained in:
parent
ff3e7f88a3
commit
a3449e66b6
@ -1759,7 +1759,7 @@ ContainerState::PopThebesLayerData()
|
||||
nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
|
||||
|
||||
if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
|
||||
data->mLayer->GetValidRegion().IsEmpty()) {
|
||||
(data->mLayer->GetValidRegion().IsEmpty() || mLayerBuilder->CheckInLayerTreeCompressionMode())) {
|
||||
NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
|
||||
"Can't be a solid color as well as an image!");
|
||||
if (imageContainer) {
|
||||
@ -2817,6 +2817,20 @@ FrameLayerBuilder::SaveLastPaintOffset(ThebesLayer* aLayer)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FrameLayerBuilder::CheckInLayerTreeCompressionMode()
|
||||
{
|
||||
if (mInLayerTreeCompressionMode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we wanted to be in layer tree compression mode, but weren't, then scheduled
|
||||
// a delayed repaint where we will be.
|
||||
mRootPresContext->PresShell()->GetRootFrame()->SchedulePaint(nsIFrame::PAINT_DELAYED_COMPRESS);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ContainerState::CollectOldLayers()
|
||||
{
|
||||
|
@ -152,6 +152,7 @@ public:
|
||||
mRetainingManager(nullptr),
|
||||
mDetectedDOMModification(false),
|
||||
mInvalidateAllLayers(false),
|
||||
mInLayerTreeCompressionMode(false),
|
||||
mContainerLayerGeneration(0),
|
||||
mMaxContainerLayerGeneration(0)
|
||||
{
|
||||
@ -591,6 +592,13 @@ public:
|
||||
return mContainingThebesLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to build the most compressed layer tree possible, even if it means
|
||||
* throwing away existing retained buffers.
|
||||
*/
|
||||
void SetLayerTreeCompressionMode() { mInLayerTreeCompressionMode = true; }
|
||||
bool CheckInLayerTreeCompressionMode();
|
||||
|
||||
protected:
|
||||
void RemoveThebesItemsAndOwnerDataForLayerSubtree(Layer* aLayer,
|
||||
bool aRemoveThebesItems,
|
||||
@ -652,6 +660,8 @@ protected:
|
||||
*/
|
||||
bool mInvalidateAllLayers;
|
||||
|
||||
bool mInLayerTreeCompressionMode;
|
||||
|
||||
uint32_t mContainerLayerGeneration;
|
||||
uint32_t mMaxContainerLayerGeneration;
|
||||
};
|
||||
|
@ -1124,6 +1124,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||
FrameLayerBuilder *layerBuilder = new FrameLayerBuilder();
|
||||
layerBuilder->Init(aBuilder, layerManager);
|
||||
|
||||
if (aFlags & PAINT_COMPRESSED) {
|
||||
layerBuilder->SetLayerTreeCompressionMode();
|
||||
}
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
FrameLayerBuilder::InvalidateAllLayers(layerManager);
|
||||
}
|
||||
|
@ -1512,6 +1512,9 @@ public:
|
||||
* layer manager has already had BeginTransaction() called on it and
|
||||
* we should not call it again.
|
||||
*
|
||||
* If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
|
||||
* to avoid short cut optimizations.
|
||||
*
|
||||
* ComputeVisibility must be called before Paint.
|
||||
*
|
||||
* This must only be called on the root display list of the display list
|
||||
@ -1522,7 +1525,8 @@ public:
|
||||
PAINT_USE_WIDGET_LAYERS = 0x01,
|
||||
PAINT_FLUSH_LAYERS = 0x02,
|
||||
PAINT_EXISTING_TRANSACTION = 0x04,
|
||||
PAINT_NO_COMPOSITE = 0x08
|
||||
PAINT_NO_COMPOSITE = 0x08,
|
||||
PAINT_COMPRESSED = 0x10
|
||||
};
|
||||
void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||
uint32_t aFlags) const;
|
||||
|
@ -1322,8 +1322,15 @@ public:
|
||||
/**
|
||||
* Ensures that the refresh driver is running, and schedules a view
|
||||
* manager flush on the next tick.
|
||||
*
|
||||
* @param aType PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
|
||||
* put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
|
||||
*/
|
||||
virtual void ScheduleViewManagerFlush() = 0;
|
||||
enum PaintType {
|
||||
PAINT_DEFAULT,
|
||||
PAINT_DELAYED_COMPRESS
|
||||
};
|
||||
virtual void ScheduleViewManagerFlush(PaintType aType = PAINT_DEFAULT) = 0;
|
||||
virtual void ClearMouseCaptureOnView(nsView* aView) = 0;
|
||||
virtual bool IsVisible() = 0;
|
||||
virtual void DispatchSynthMouseMove(mozilla::WidgetGUIEvent* aEvent,
|
||||
|
@ -2335,6 +2335,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
|
||||
if (aFlags & PAINT_NO_COMPOSITE) {
|
||||
flags |= nsDisplayList::PAINT_NO_COMPOSITE;
|
||||
}
|
||||
if (aFlags & PAINT_COMPRESSED) {
|
||||
flags |= nsDisplayList::PAINT_COMPRESSED;
|
||||
}
|
||||
|
||||
list.PaintRoot(&builder, aRenderingContext, flags);
|
||||
|
||||
|
@ -768,7 +768,8 @@ public:
|
||||
PAINT_ALL_CONTINUATIONS = 0x40,
|
||||
PAINT_TO_WINDOW = 0x80,
|
||||
PAINT_EXISTING_TRANSACTION = 0x100,
|
||||
PAINT_NO_COMPOSITE = 0x200
|
||||
PAINT_NO_COMPOSITE = 0x200,
|
||||
PAINT_COMPRESSED = 0x400
|
||||
};
|
||||
|
||||
/**
|
||||
@ -799,6 +800,8 @@ public:
|
||||
* If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already
|
||||
* been called on aFrame's widget's layer manager and should not be
|
||||
* called again.
|
||||
* If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode
|
||||
* to avoid short cut optimizations.
|
||||
*
|
||||
* So there are three possible behaviours:
|
||||
* 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint
|
||||
|
@ -1056,6 +1056,11 @@ PresShell::Destroy()
|
||||
mReflowContinueTimer = nullptr;
|
||||
}
|
||||
|
||||
if (mDelayedPaintTimer) {
|
||||
mDelayedPaintTimer->Cancel();
|
||||
mDelayedPaintTimer = nullptr;
|
||||
}
|
||||
|
||||
mSynthMouseMoveEvent.Revoke();
|
||||
|
||||
mUpdateImageVisibilityEvent.Revoke();
|
||||
@ -3541,9 +3546,41 @@ PresShell::GetRectVisibility(nsIFrame* aFrame,
|
||||
return nsRectVisibility_kVisible;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::ScheduleViewManagerFlush()
|
||||
class PaintTimerCallBack MOZ_FINAL : public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
PaintTimerCallBack(PresShell* aShell) : mShell(aShell) {}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP Notify(nsITimer* aTimer) MOZ_FINAL
|
||||
{
|
||||
mShell->SetNextPaintCompressed();
|
||||
mShell->AddInvalidateHiddenPresShellObserver(mShell->GetPresContext()->RefreshDriver());
|
||||
mShell->ScheduleViewManagerFlush();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
PresShell* mShell;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(PaintTimerCallBack, nsITimerCallback)
|
||||
|
||||
void
|
||||
PresShell::ScheduleViewManagerFlush(PaintType aType)
|
||||
{
|
||||
if (aType == PAINT_DELAYED_COMPRESS) {
|
||||
// Delay paint for 1 second.
|
||||
static const uint32_t kPaintDelayPeriod = 1000;
|
||||
if (!mDelayedPaintTimer) {
|
||||
mDelayedPaintTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
nsRefPtr<PaintTimerCallBack> cb = new PaintTimerCallBack(this);
|
||||
mDelayedPaintTimer->InitWithCallback(cb, kPaintDelayPeriod, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->RefreshDriver()->ScheduleViewManagerFlush();
|
||||
@ -5800,7 +5837,8 @@ PresShell::Paint(nsView* aViewToPaint,
|
||||
layerManager->BeginTransaction();
|
||||
}
|
||||
|
||||
if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
|
||||
if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE) &&
|
||||
!mNextPaintCompressed) {
|
||||
NotifySubDocInvalidationFunc computeInvalidFunc =
|
||||
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;
|
||||
bool computeInvalidRect = computeInvalidFunc ||
|
||||
@ -5851,6 +5889,9 @@ PresShell::Paint(nsView* aViewToPaint,
|
||||
if (!(aFlags & PAINT_COMPOSITE)) {
|
||||
flags |= nsLayoutUtils::PAINT_NO_COMPOSITE;
|
||||
}
|
||||
if (mNextPaintCompressed) {
|
||||
flags |= nsLayoutUtils::PAINT_COMPRESSED;
|
||||
}
|
||||
|
||||
if (frame) {
|
||||
// We can paint directly into the widget using its layer manager.
|
||||
|
@ -201,7 +201,7 @@ public:
|
||||
virtual void WillPaint() MOZ_OVERRIDE;
|
||||
virtual void WillPaintWindow() MOZ_OVERRIDE;
|
||||
virtual void DidPaintWindow() MOZ_OVERRIDE;
|
||||
virtual void ScheduleViewManagerFlush() MOZ_OVERRIDE;
|
||||
virtual void ScheduleViewManagerFlush(PaintType aType = PAINT_DEFAULT) MOZ_OVERRIDE;
|
||||
virtual void DispatchSynthMouseMove(mozilla::WidgetGUIEvent* aEvent,
|
||||
bool aFlushOnHoverChange) MOZ_OVERRIDE;
|
||||
virtual void ClearMouseCaptureOnView(nsView* aView) MOZ_OVERRIDE;
|
||||
@ -351,6 +351,8 @@ public:
|
||||
|
||||
virtual void RestyleShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot);
|
||||
|
||||
void SetNextPaintCompressed() { mNextPaintCompressed = true; }
|
||||
|
||||
protected:
|
||||
virtual ~PresShell();
|
||||
|
||||
@ -762,6 +764,8 @@ protected:
|
||||
// moving/sizing loop is running, see bug 491700 for details.
|
||||
nsCOMPtr<nsITimer> mReflowContinueTimer;
|
||||
|
||||
nsCOMPtr<nsITimer> mDelayedPaintTimer;
|
||||
|
||||
// The `performance.now()` value when we last started to process reflows.
|
||||
DOMHighResTimeStamp mLastReflowStart;
|
||||
|
||||
@ -802,6 +806,8 @@ protected:
|
||||
|
||||
bool mImageVisibilityVisited : 1;
|
||||
|
||||
bool mNextPaintCompressed : 1;
|
||||
|
||||
static bool sDisableNonTestMouseEvents;
|
||||
};
|
||||
|
||||
|
@ -4886,7 +4886,7 @@ nsIFrame::IsInvalid(nsRect& aRect)
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::SchedulePaint(uint32_t aFlags)
|
||||
nsIFrame::SchedulePaint(PaintType aType)
|
||||
{
|
||||
nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this);
|
||||
nsPresContext *pres = displayRoot->PresContext()->GetRootPresContext();
|
||||
@ -4897,8 +4897,15 @@ nsIFrame::SchedulePaint(uint32_t aFlags)
|
||||
return;
|
||||
}
|
||||
|
||||
pres->PresShell()->ScheduleViewManagerFlush();
|
||||
if (!(aFlags & PAINT_COMPOSITE_ONLY)) {
|
||||
pres->PresShell()->ScheduleViewManagerFlush(aType == PAINT_DELAYED_COMPRESS ?
|
||||
nsIPresShell::PAINT_DELAYED_COMPRESS :
|
||||
nsIPresShell::PAINT_DEFAULT);
|
||||
|
||||
if (aType == PAINT_DELAYED_COMPRESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aType == PAINT_DEFAULT) {
|
||||
displayRoot->AddStateBits(NS_FRAME_UPDATE_LAYER_TREE);
|
||||
}
|
||||
nsIPresShell* shell = PresContext()->PresShell();
|
||||
|
@ -2328,15 +2328,18 @@ public:
|
||||
* do not trigger a reflow should have this called for them by
|
||||
* DoApplyRenderingChangeToTree.
|
||||
*
|
||||
* @param aFlags PAINT_COMPOSITE_ONLY : No changes have been made
|
||||
* @param aType PAINT_COMPOSITE_ONLY : No changes have been made
|
||||
* that require a layer tree update, so only schedule a layer
|
||||
* tree composite.
|
||||
* PAINT_DELAYED_COMPRESS : Schedule a paint to be executed after a delay, and
|
||||
* put FrameLayerBuilder in 'compressed' mode that avoids short cut optimizations.
|
||||
*/
|
||||
enum {
|
||||
enum PaintType {
|
||||
PAINT_DEFAULT = 0,
|
||||
PAINT_COMPOSITE_ONLY = 1 << 0
|
||||
PAINT_COMPOSITE_ONLY,
|
||||
PAINT_DELAYED_COMPRESS
|
||||
};
|
||||
void SchedulePaint(uint32_t aFlags = PAINT_DEFAULT);
|
||||
void SchedulePaint(PaintType aType = PAINT_DEFAULT);
|
||||
|
||||
/**
|
||||
* Checks if the layer tree includes a dedicated layer for this
|
||||
|
Loading…
Reference in New Issue
Block a user