Bug 539356 - Part 8b - Move painting of retained layers to the view manager flush, and only composite on the paint event. r=roc

This commit is contained in:
Matt Woodrow 2012-06-30 15:06:10 +12:00
parent 7aaf9816cd
commit 46e6f3d27b
13 changed files with 75 additions and 34 deletions

View File

@ -309,6 +309,9 @@ public:
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT) = 0;
virtual bool HasShadowManagerInternal() const { return false; }
bool HasShadowManager() const { return HasShadowManagerInternal(); }
bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; }
/**

View File

@ -148,8 +148,6 @@ public:
void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed);
virtual bool IsCompositingCheap() { return false; }
virtual bool HasShadowManagerInternal() const { return false; }
bool HasShadowManager() const { return HasShadowManagerInternal(); }
virtual PRInt32 GetMaxTextureSize() const { return PR_INT32_MAX; }
protected:

View File

@ -199,7 +199,7 @@ LayerManagerD3D10::Initialize(bool force)
mInputLayout = attachments->mInputLayout;
}
if (HasShadowManager()) {
if (LayerManager::HasShadowManager()) {
reporter.SetSuccessful();
return true;
}

View File

@ -648,7 +648,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
layerManager->SetRoot(root);
layerBuilder->WillEndTransaction(layerManager);
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
aBuilder);
aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
layerBuilder->DidEndTransaction(layerManager);
if (aFlags & PAINT_FLUSH_LAYERS) {

View File

@ -25,6 +25,7 @@
#include "FrameLayerBuilder.h"
#include "nsThemeConstants.h"
#include "ImageLayers.h"
#include "nsLayoutUtils.h"
#include "mozilla/StandardInteger.h"
@ -1155,7 +1156,8 @@ public:
PAINT_DEFAULT = 0,
PAINT_USE_WIDGET_LAYERS = 0x01,
PAINT_FLUSH_LAYERS = 0x02,
PAINT_EXISTING_TRANSACTION = 0x04
PAINT_EXISTING_TRANSACTION = 0x04,
PAINT_NO_COMPOSITE = 0x08
};
void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
PRUint32 aFlags) const;

View File

@ -1208,9 +1208,12 @@ public:
*/
virtual void SynthesizeMouseMove(bool aFromScroll) = 0;
virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
bool aWillSendDidPaint) = 0;
enum PaintType {
PaintType_Composite,
PaintType_NoComposite
};
virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
PaintType aType, bool aWillSendDidPaint) = 0;
virtual nsresult HandleEvent(nsIFrame* aFrame,
nsGUIEvent* aEvent,
bool aDontRetargetEvents,

View File

@ -1783,6 +1783,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
if (aFlags & PAINT_EXISTING_TRANSACTION) {
flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION;
}
if (aFlags & PAINT_NO_COMPOSITE) {
flags |= nsDisplayList::PAINT_NO_COMPOSITE;
}
list.PaintRoot(&builder, aRenderingContext, flags);

View File

@ -596,7 +596,8 @@ public:
PAINT_HIDE_CARET = 0x20,
PAINT_ALL_CONTINUATIONS = 0x40,
PAINT_TO_WINDOW = 0x80,
PAINT_EXISTING_TRANSACTION = 0x100
PAINT_EXISTING_TRANSACTION = 0x100,
PAINT_NO_COMPOSITE = 0x200
};
/**

View File

@ -5203,9 +5203,8 @@ private:
void
PresShell::Paint(nsIView* aViewToPaint,
nsIWidget* aWidgetToPaint,
const nsRegion& aDirtyRegion,
const nsIntRegion& aIntDirtyRegion,
PaintType aType,
bool aWillSendDidPaint)
{
#ifdef NS_FUNCTION_TIMER
@ -5222,7 +5221,6 @@ PresShell::Paint(nsIView* aViewToPaint,
SAMPLE_LABEL("Paint", "PresShell::Paint");
NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
NS_ASSERTION(aViewToPaint, "null view");
NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget");
nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint);
@ -5233,14 +5231,13 @@ PresShell::Paint(nsIView* aViewToPaint,
bool isRetainingManager;
LayerManager* layerManager =
aWidgetToPaint->GetLayerManager(&isRetainingManager);
aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager);
NS_ASSERTION(layerManager, "Must be in paint event");
if (mIsFirstPaint) {
layerManager->SetIsFirstPaint();
mIsFirstPaint = false;
}
layerManager->BeginTransaction();
if (frame && isRetainingManager) {
// Try to do an empty transaction, if the frame tree does not
@ -5249,21 +5246,32 @@ PresShell::Paint(nsIView* aViewToPaint,
// draws the window title bar on Mac), because a) it won't work
// and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE,
// that will cause us to forget to update the real layer manager!
if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) {
if (layerManager->EndEmptyTransaction()) {
frame->UpdatePaintCountForPaintedPresShells();
presContext->NotifyDidPaintForSubtree();
if (aType == PaintType_Composite) {
if (layerManager->HasShadowManager()) {
return;
}
layerManager->BeginTransaction();
if (layerManager->EndEmptyTransaction()) {
return;
}
NS_WARNING("Must complete empty transaction when compositing!");
} else {
layerManager->BeginTransaction();
}
frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE);
} else {
layerManager->BeginTransaction();
}
if (frame) {
frame->ClearPresShellsFromLastPaint();
}
nscolor bgcolor = ComputeBackstopColor(aViewToPaint);
PRUint32 flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION;
if (aType == PaintType_NoComposite) {
flags |= nsLayoutUtils::PAINT_NO_COMPOSITE;
}
if (frame) {
// Defer invalidates that are triggered during painting, and discard
@ -5273,12 +5281,12 @@ PresShell::Paint(nsIView* aViewToPaint,
frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion);
// We can paint directly into the widget using its layer manager.
nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor,
nsLayoutUtils::PAINT_WIDGET_LAYERS |
nsLayoutUtils::PAINT_EXISTING_TRANSACTION);
nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor, flags);
frame->EndDeferringInvalidatesForDisplayRoot();
presContext->NotifyDidPaintForSubtree();
if (aType != PaintType_Composite) {
presContext->NotifyDidPaintForSubtree();
}
return;
}
@ -5292,9 +5300,13 @@ PresShell::Paint(nsIView* aViewToPaint,
root->SetVisibleRegion(bounds);
layerManager->SetRoot(root);
}
layerManager->EndTransaction(NULL, NULL);
layerManager->EndTransaction(NULL, NULL, aType == PaintType_NoComposite ?
LayerManager::END_NO_COMPOSITE :
LayerManager::END_DEFAULT);
presContext->NotifyDidPaintForSubtree();
if (aType != PaintType_Composite) {
presContext->NotifyDidPaintForSubtree();
}
}
// static

View File

@ -184,9 +184,8 @@ public:
//nsIViewObserver interface
virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget,
const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion,
bool aWillSendDidPaint);
virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion,
PaintType aType, bool aWillSendDidPaint);
virtual nsresult HandleEvent(nsIFrame* aFrame,
nsGUIEvent* aEvent,
bool aDontRetargetEvents,

View File

@ -411,8 +411,14 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
}
if (mViewManagerFlushIsPending) {
#ifdef DEBUG_INVALIDATIONS
printf("Starting ProcessPendingUpdates\n");
#endif
mViewManagerFlushIsPending = false;
mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates();
#ifdef DEBUG_INVALIDATIONS
printf("Ending ProcessPendingUpdates\n");
#endif
}
if (mThrottled ||

View File

@ -300,11 +300,9 @@ nsIView* nsIViewManager::GetDisplayRootFor(nsIView* aView)
aContext may be null, in which case layers should be used for
rendering.
*/
void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
const nsIntRegion& aRegion,
void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion,
bool aWillSendDidPaint)
{
NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch");
NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
// damageRegion is the damaged area, in twips, relative to the view origin
@ -337,8 +335,14 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget,
"Widgets that we paint must all be display roots");
if (mPresShell) {
mPresShell->Paint(aView, aWidget, damageRegion, aRegion,
#ifdef DEBUG_INVALIDATIONS
printf("--COMPOSITE-- %p\n", mPresShell);
#endif
mPresShell->Paint(aView, damageRegion, nsIPresShell::PaintType_Composite,
aWillSendDidPaint);
#ifdef DEBUG_INVALIDATIONS
printf("--ENDCOMPOSITE--\n");
#endif
mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT);
}
@ -374,6 +378,17 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
// Push out updates after we've processed the children; ensures that
// damage is applied based on the final widget geometry
if (aFlushDirtyRegion) {
nsIWidget *widget = aView->GetWidget();
if (widget) {
#ifdef DEBUG_INVALIDATIONS
printf("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", mPresShell, aView, widget);
#endif
nsAutoScriptBlocker scriptBlocker;
mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, false);
#ifdef DEBUG_INVALIDATIONS
printf("---- PAINT END ----\n");
#endif
}
FlushDirtyRegionToWidget(aView);
}
}
@ -767,7 +782,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent,
break;
// Paint.
Refresh(view, event->widget, event->region, event->willSendDidPaint);
Refresh(view, event->region, event->willSendDidPaint);
break;
}

View File

@ -129,8 +129,7 @@ private:
void InvalidateViews(nsView *aView);
// aView is the view for aWidget and aRegion is relative to aWidget.
void Refresh(nsView *aView, nsIWidget *aWidget, const nsIntRegion& aRegion,
bool aWillSendDidPaint);
void Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint);
void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut);
void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,