Bug 974197 - Fire MozAfterPaint after the compositor has composited the frame. r=roc

This commit is contained in:
Matt Woodrow 2014-03-07 16:24:32 +13:00
parent 09e1cf2ed6
commit e1320c476a
17 changed files with 137 additions and 8 deletions

View File

@ -74,6 +74,7 @@
#include "nsILoadContext.h"
#include "ipc/nsGUIEventIPC.h"
#include "mozilla/gfx/Matrix.h"
#include "ClientLayerManager.h"
#include "nsColorPickerProxy.h"
@ -106,6 +107,9 @@ static bool sCpowsEnabled = false;
static int32_t sActiveDurationMs = 10;
static bool sActiveDurationMsSet = false;
typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
static TabChildMap* sTabChildren;
NS_IMETHODIMP
ContentListener::HandleEvent(nsIDOMEvent* aEvent)
{
@ -280,6 +284,7 @@ TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t
, mManager(aManager)
, mTabChildGlobal(nullptr)
, mChromeFlags(aChromeFlags)
, mLayersId(0)
, mOuterRect(0, 0, 0, 0)
, mInnerSize(0, 0)
, mActivePointerId(-1)
@ -1208,6 +1213,17 @@ TabChild::DestroyWindow()
mRemoteFrame->Destroy();
mRemoteFrame = nullptr;
}
if (mLayersId != 0) {
MOZ_ASSERT(sTabChildren);
sTabChildren->Remove(mLayersId);
if (!sTabChildren->Count()) {
delete sTabChildren;
sTabChildren = nullptr;
}
mLayersId = 0;
}
}
bool
@ -2427,6 +2443,13 @@ TabChild::InitRenderingState()
ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
mRemoteFrame = remoteFrame;
if (id != 0) {
if (!sTabChildren) {
sTabChildren = new TabChildMap;
}
sTabChildren->Put(id, this);
mLayersId = id;
}
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
@ -2629,6 +2652,26 @@ TabChild::GetFrom(nsIPresShell* aPresShell)
return GetFrom(docShell);
}
TabChild*
TabChild::GetFrom(uint64_t aLayersId)
{
if (!sTabChildren) {
return nullptr;
}
return sTabChildren->Get(aLayersId);
}
void
TabChild::DidComposite()
{
MOZ_ASSERT(mWidget);
MOZ_ASSERT(mWidget->GetLayerManager());
MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT);
ClientLayerManager *manager = static_cast<ClientLayerManager*>(mWidget->GetLayerManager());
manager->DidComposite();
}
NS_IMETHODIMP
TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
{

View File

@ -381,6 +381,9 @@ public:
}
static TabChild* GetFrom(nsIPresShell* aPresShell);
static TabChild* GetFrom(uint64_t aLayersId);
void DidComposite();
static inline TabChild*
GetFrom(nsIDOMWindow* aWindow)
@ -499,6 +502,7 @@ private:
nsRefPtr<ContentChild> mManager;
nsRefPtr<TabChildGlobal> mTabChildGlobal;
uint32_t mChromeFlags;
uint64_t mLayersId;
nsIntRect mOuterRect;
ScreenIntSize mInnerSize;
// When we're tracking a possible tap gesture, this is the "down"

View File

@ -22,6 +22,7 @@
#include "mozilla/layers/LayerTransactionChild.h"
#include "nsAString.h"
#include "nsIWidget.h" // for nsIWidget
#include "nsIWidgetListener.h"
#include "nsTArray.h" // for AutoInfallibleTArray
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
#ifdef MOZ_WIDGET_ANDROID
@ -264,6 +265,21 @@ ClientLayerManager::Composite()
}
}
void
ClientLayerManager::DidComposite()
{
MOZ_ASSERT(mWidget);
nsIWidgetListener *listener = mWidget->GetWidgetListener();
if (listener) {
listener->DidCompositeWindow();
} else {
listener = mWidget->GetAttachedWidgetListener();
if (listener) {
listener->DidCompositeWindow();
}
}
}
void
ClientLayerManager::MakeSnapshotIfRequired()
{

View File

@ -153,6 +153,8 @@ public:
virtual void Composite() MOZ_OVERRIDE;
virtual void DidComposite();
protected:
enum TransactionPhase {
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD

View File

@ -20,6 +20,7 @@
#include "nsTArray.h" // for nsTArray, nsTArray_Impl
#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop, etc
#include "FrameLayerBuilder.h"
#include "mozilla/dom/TabChild.h"
using mozilla::layers::LayerTransactionChild;
@ -120,6 +121,21 @@ CompositorChild::RecvInvalidateAll()
return true;
}
bool
CompositorChild::RecvDidComposite(const uint64_t& aId)
{
if (mLayerManager) {
MOZ_ASSERT(aId == 0);
mLayerManager->DidComposite();
} else if (aId != 0) {
dom::TabChild *child = dom::TabChild::GetFrom(aId);
if (child) {
child->DidComposite();
}
}
return true;
}
void
CompositorChild::ActorDestroy(ActorDestroyReason aWhy)
{

View File

@ -57,6 +57,8 @@ public:
virtual bool RecvInvalidateAll() MOZ_OVERRIDE;
virtual bool RecvDidComposite(const uint64_t& aId) MOZ_OVERRIDE;
protected:
virtual PLayerTransactionChild*
AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints,

View File

@ -51,6 +51,7 @@
#endif
#include "GeckoProfiler.h"
#include "mozilla/ipc/ProtocolTypes.h"
#include "mozilla/unused.h"
using namespace base;
using namespace mozilla;
@ -189,6 +190,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
, mResumeCompositionMonitor("ResumeCompositionMonitor")
, mOverrideComposeReadiness(false)
, mForceCompositionTask(nullptr)
, mWantDidCompositeEvent(false)
{
NS_ABORT_IF_FALSE(sCompositorThread != nullptr || sCompositorThreadID,
"The compositor thread must be Initialized before instanciating a COmpositorParent.");
@ -537,6 +539,8 @@ CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint,
if (aScheduleComposite) {
ScheduleComposition();
}
mWantDidCompositeEvent = true;
}
// Used when layout.frame_rate is -1. Needs to be kept in sync with
@ -663,6 +667,11 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget)
mLayerManager->SetDebugOverlayWantsNextFrame(false);
mLayerManager->EndEmptyTransaction();
if (!aTarget && mWantDidCompositeEvent) {
DidComposite();
mWantDidCompositeEvent = false;
}
if (mLayerManager->DebugOverlayWantsNextFrame()) {
ScheduleComposition();
}
@ -689,6 +698,20 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget)
profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END);
}
void
CompositorParent::DidComposite()
{
unused << SendDidComposite(0);
for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin();
it != sIndirectLayerTrees.end(); it++) {
LayerTreeState* lts = &it->second;
if (lts->mParent == this && lts->mCrossProcessParent) {
unused << lts->mCrossProcessParent->SendDidComposite(it->first);
}
}
}
void
CompositorParent::ForceComposeToTarget(DrawTarget* aTarget)
{
@ -765,6 +788,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
ScheduleComposition();
}
mLayerManager->NotifyShadowTreeTransaction();
mWantDidCompositeEvent = true;
}
void

View File

@ -297,6 +297,8 @@ private:
*/
bool CanComposite();
void DidComposite();
nsRefPtr<LayerManagerComposite> mLayerManager;
nsRefPtr<Compositor> mCompositor;
RefPtr<AsyncCompositionManager> mCompositionManager;
@ -325,6 +327,8 @@ private:
nsRefPtr<APZCTreeManager> mApzcTreeManager;
bool mWantDidCompositeEvent;
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
};

View File

@ -40,6 +40,11 @@ child:
// The child should invalidate everything so that the whole window is redrawn.
async InvalidateAll();
// The compositor completed a layers transaction. id is the layers id
// of the child layer tree that was composited (or 0 when notifying
// the root layer tree).
async DidComposite(uint64_t id);
parent:
// The child is about to be destroyed, so perform any necessary cleanup.

View File

@ -5838,11 +5838,7 @@ PresShell::Paint(nsView* aViewToPaint,
NS_ASSERTION(layerManager, "Must be in paint event");
bool shouldInvalidate = layerManager->NeedsWidgetInvalidation();
uint32_t didPaintFlags = aFlags;
if (!shouldInvalidate) {
didPaintFlags |= PAINT_COMPOSITE;
}
nsAutoNotifyDidPaint notifyDidPaint(this, didPaintFlags);
nsAutoNotifyDidPaint notifyDidPaint(this, aFlags);
AutoUpdateHitRegion updateHitRegion(this, frame);
// Whether or not we should set first paint when painting is

View File

@ -9,7 +9,6 @@
document.documentElement.className = '';
}
document.addEventListener("MozReftestInvalidate", setValue);
setTimeout(setValue, 2000); // useful when not running under reftest suite
</script>
<body>
<input type=range id='i' value=50 step=25 style='-moz-appearance:none'>

View File

@ -9,7 +9,6 @@
document.documentElement.className = '';
}
document.addEventListener("MozReftestInvalidate", setValue);
setTimeout(setValue, 2000); // useful when not running under reftest suite
</script>
<body>
<input type=range id='i' value=50 step=25>

View File

@ -12,7 +12,7 @@
};
setTimeout(function() {
document.documentElement.className = "reftest-print"
}, 0);
}, 100);
};
</script>
</head>

View File

@ -370,6 +370,7 @@ public:
virtual void WillPaintWindow(nsIWidget* aWidget) MOZ_OVERRIDE;
virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion) MOZ_OVERRIDE;
virtual void DidPaintWindow() MOZ_OVERRIDE;
virtual void DidCompositeWindow() MOZ_OVERRIDE;
virtual void RequestRepaint() MOZ_OVERRIDE;
virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
bool aUseAttachedEvents) MOZ_OVERRIDE;

View File

@ -16,6 +16,7 @@
#include "nsPresArena.h"
#include "nsXULPopupManager.h"
#include "nsIWidgetListener.h"
#include "nsContentUtils.h" // for nsAutoScriptBlocker
using namespace mozilla;
@ -1054,6 +1055,16 @@ nsView::DidPaintWindow()
vm->DidPaintWindow();
}
void
nsView::DidCompositeWindow()
{
nsIPresShell* presShell = mViewManager->GetPresShell();
if (presShell) {
nsAutoScriptBlocker scriptBlocker;
presShell->GetPresContext()->GetDisplayRootPresContext()->GetRootPresContext()->NotifyDidPaintForSubtree(nsIPresShell::PAINT_COMPOSITE);
}
}
void
nsView::RequestRepaint()
{

View File

@ -130,6 +130,8 @@ public:
*/
virtual void DidPaintWindow();
virtual void DidCompositeWindow();
/**
* Request that layout schedules a repaint on the next refresh driver tick.
*/

View File

@ -101,6 +101,11 @@ nsIWidgetListener::DidPaintWindow()
{
}
void
nsIWidgetListener::DidCompositeWindow()
{
}
void
nsIWidgetListener::RequestRepaint()
{