Bug 1200063 - Share a paint throttler between APZCs in the same layers id. r=kats

In this process, TaskThrottler is made reference-counted.

--HG--
extra : source : 68295d4d1616e257732b8f2e8dd46c24debc8626
extra : intermediate-source : 2cd0c4caec06689c5325e23006d2cb14d40c5b5c
This commit is contained in:
Botond Ballo 2015-09-16 14:45:07 -04:00
Родитель d84490b7db
Коммит 3ec0663f3b
6 изменённых файлов: 55 добавлений и 24 удалений

Просмотреть файл

@ -28,6 +28,7 @@
#include "UnitTransforms.h" // for ViewAs
#include "gfxPrefs.h" // for gfxPrefs
#include "OverscrollHandoffState.h" // for OverscrollHandoffState
#include "TaskThrottler.h" // for TaskThrottler
#include "TreeTraversal.h" // for generic tree traveral algorithms
#include "LayersLogging.h" // for Stringify
#include "Units.h" // for ParentlayerPixel
@ -108,10 +109,11 @@ APZCTreeManager::~APZCTreeManager()
AsyncPanZoomController*
APZCTreeManager::MakeAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController)
GeckoContentController* aController,
TaskThrottler* aPaintThrottler)
{
return new AsyncPanZoomController(aLayersId, this, mInputQueue,
aController, AsyncPanZoomController::USE_GESTURE_DETECTOR);
aController, aPaintThrottler, AsyncPanZoomController::USE_GESTURE_DETECTOR);
}
TimeStamp
@ -419,7 +421,17 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
// a destroyed APZC and so we need to throw that out and make a new one.
bool newApzc = (apzc == nullptr || apzc->IsDestroyed());
if (newApzc) {
apzc = MakeAPZCInstance(aLayersId, state->mController);
// Look up the paint throttler for this layers id, or create it if
// this is the first APZC for this layers id.
auto throttlerInsertResult = mPaintThrottlerMap.insert(
std::make_pair(aLayersId, nsRefPtr<TaskThrottler>()));
if (throttlerInsertResult.second) {
throttlerInsertResult.first->second = new TaskThrottler(
GetFrameTime(), TimeDuration::FromMilliseconds(500));
}
apzc = MakeAPZCInstance(aLayersId, state->mController,
throttlerInsertResult.first->second);
apzc->SetCompositorParent(aState.mCompositor);
if (state->mCrossProcessParent != nullptr) {
apzc->ShareFrameMetricsAcrossProcesses();

Просмотреть файл

@ -49,6 +49,7 @@ class LayerMetricsWrapper;
class InputQueue;
class GeckoContentController;
class HitTestingTreeNode;
class TaskThrottler;
/**
* ****************** NOTE ON LOCK ORDERING IN APZ **************************
@ -394,7 +395,7 @@ protected:
// Protected hooks for gtests subclass
virtual AsyncPanZoomController* MakeAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler& aPaintThrottler);
TaskThrottler* aPaintThrottler);
public:
// Public hooks for gtests subclass
virtual TimeStamp GetFrameTime();
@ -510,7 +511,10 @@ private:
/* Holds the zoom constraints for scrollable layers, as determined by the
* the main-thread gecko code. */
std::map<ScrollableLayerGuid, ZoomConstraints> mZoomConstraints;
/* Stores a paint throttler for each layers id. There is one for each layers
* id to ensure that one child process painting slowly doesn't hold up
* another. */
std::map<uint64_t, nsRefPtr<TaskThrottler>> mPaintThrottlerMap;
/* This tracks the APZC that should receive all inputs for the current input event block.
* This allows touch points to move outside the thing they started on, but still have the
* touch events delivered to the same initial APZC. This will only ever be touched on the

Просмотреть файл

@ -808,9 +808,10 @@ AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
APZCTreeManager* aTreeManager,
const nsRefPtr<InputQueue>& aInputQueue,
GeckoContentController* aGeckoContentController,
TaskThrottler* aPaintThrottler,
GestureBehavior aGestures)
: mLayersId(aLayersId),
mPaintThrottler(GetFrameTime(), TimeDuration::FromMilliseconds(500)),
mPaintThrottler(aPaintThrottler),
mGeckoContentController(aGeckoContentController),
mRefPtrMonitor("RefPtrMonitor"),
// mTreeManager must be initialized before GetFrameTime() is called
@ -2487,7 +2488,7 @@ void AsyncPanZoomController::ScheduleComposite() {
void AsyncPanZoomController::ScheduleCompositeAndMaybeRepaint() {
ScheduleComposite();
TimeDuration timePaintDelta = mPaintThrottler.TimeSinceLastRequest(GetFrameTime());
TimeDuration timePaintDelta = mPaintThrottler->TimeSinceLastRequest(GetFrameTime());
if (timePaintDelta.ToMilliseconds() > gfxPrefs::APZPanRepaintInterval()) {
RequestContentRepaint();
}
@ -2508,7 +2509,7 @@ void AsyncPanZoomController::FlushRepaintForNewInputBlock() {
// Therefore we should clear out the pending task and restore the
// state of mLastPaintRequestMetrics to what it was before the
// pending task was queued.
mPaintThrottler.CancelPendingTask();
mPaintThrottler->CancelPendingTask();
mLastPaintRequestMetrics = mLastDispatchedPaintMetrics;
RequestContentRepaint(mFrameMetrics, false /* not throttled */);
@ -2519,7 +2520,7 @@ void AsyncPanZoomController::FlushRepaintIfPending() {
// Just tell the paint throttler to send the pending repaint request if
// there is one.
ReentrantMonitorAutoEnter lock(mMonitor);
mPaintThrottler.TaskComplete(GetFrameTime());
mPaintThrottler->TaskComplete(GetFrameTime());
}
bool AsyncPanZoomController::SnapBackIfOverscrolled() {
@ -2562,7 +2563,7 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics,
aFrameMetrics.SetDisplayPortMargins(
CalculatePendingDisplayPort(aFrameMetrics,
GetVelocityVector(),
mPaintThrottler.AverageDuration().ToSeconds()));
mPaintThrottler->AverageDuration().ToSeconds()));
aFrameMetrics.SetUseDisplayPortMargins();
// If we're trying to paint what we already think is painted, discard this
@ -2585,7 +2586,7 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics,
SendAsyncScrollEvent();
if (aThrottled) {
mPaintThrottler.PostTask(
mPaintThrottler->PostTask(
FROM_HERE,
UniquePtr<CancelableTask>(NewRunnableMethod(this,
&AsyncPanZoomController::DispatchRepaintRequest,
@ -2656,7 +2657,7 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
bool continueAnimation = mAnimation->Sample(mFrameMetrics, sampleTimeDelta);
*aOutDeferredTasks = mAnimation->TakeDeferredTasks();
if (continueAnimation) {
if (mPaintThrottler.TimeSinceLastRequest(aSampleTime) >
if (mPaintThrottler->TimeSinceLastRequest(aSampleTime) >
mAnimation->mRepaintInterval) {
RequestContentRepaint();
}
@ -2897,7 +2898,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
aLayerMetrics.GetCriticalDisplayPort() + aLayerMetrics.GetScrollOffset());
}
mPaintThrottler.TaskComplete(GetFrameTime());
mPaintThrottler->TaskComplete(GetFrameTime());
bool needContentRepaint = false;
bool viewportUpdated = false;
if (FuzzyEqualsAdditive(aLayerMetrics.GetCompositionBounds().width, mFrameMetrics.GetCompositionBounds().width) &&
@ -2925,8 +2926,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
if (aIsFirstPaint || isDefault) {
// Initialize our internal state to something sane when the content
// that was just painted is something we knew nothing about previously
mPaintThrottler.ClearHistory();
mPaintThrottler.SetMaxDurations(gfxPrefs::APZNumPaintDurationSamples());
mPaintThrottler->ClearHistory();
mPaintThrottler->SetMaxDurations(gfxPrefs::APZNumPaintDurationSamples());
CancelAnimation();

Просмотреть файл

@ -103,6 +103,7 @@ public:
APZCTreeManager* aTreeManager,
const nsRefPtr<InputQueue>& aInputQueue,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler,
GestureBehavior aGestures = DEFAULT_GESTURES);
// --------------------------------------------------------------------------
@ -648,7 +649,7 @@ protected:
uint64_t mLayersId;
nsRefPtr<CompositorParent> mCompositorParent;
TaskThrottler mPaintThrottler;
nsRefPtr<TaskThrottler> mPaintThrottler;
/* Access to the following two fields is protected by the mRefPtrMonitor,
since they are accessed on the UI thread but can be cleared on the

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/RollingMean.h" // for RollingMean
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
#include "nsTArray.h" // for nsTArray
namespace tracked_objects {
@ -45,6 +46,8 @@ class TaskThrottler {
public:
TaskThrottler(const TimeStamp& aTimeStamp, const TimeDuration& aMaxWait);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TaskThrottler)
/** Post a task to be run as soon as there are no outstanding tasks, or
* post it immediately if it has been more than the max-wait time since
* the last task was posted.
@ -107,6 +110,8 @@ private:
TimeStamp mStartTime;
TimeDuration mMaxWait;
RollingMean<TimeDuration, TimeDuration> mMean;
~TaskThrottler();
};
} // namespace layers

Просмотреть файл

@ -154,7 +154,9 @@ public:
}
protected:
AsyncPanZoomController* MakeAPZCInstance(uint64_t aLayersId, GeckoContentController* aController) override;
AsyncPanZoomController* MakeAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler) override;
TimeStamp GetFrameTime() override {
return mcc->Time();
@ -168,8 +170,10 @@ class TestAsyncPanZoomController : public AsyncPanZoomController {
public:
TestAsyncPanZoomController(uint64_t aLayersId, MockContentControllerDelayed* aMcc,
TestAPZCTreeManager* aTreeManager,
TaskThrottler* aPaintThrottler,
GestureBehavior aBehavior = DEFAULT_GESTURES)
: AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(), aMcc, aBehavior)
: AsyncPanZoomController(aLayersId, aTreeManager, aTreeManager->GetInputQueue(),
aMcc, aPaintThrottler, aBehavior)
, mWaitForMainThread(false)
, mcc(aMcc)
{}
@ -257,10 +261,12 @@ private:
};
AsyncPanZoomController*
TestAPZCTreeManager::MakeAPZCInstance(uint64_t aLayersId, GeckoContentController* aController)
TestAPZCTreeManager::MakeAPZCInstance(uint64_t aLayersId,
GeckoContentController* aController,
TaskThrottler* aPaintThrottler)
{
MockContentControllerDelayed* mcc = static_cast<MockContentControllerDelayed*>(aController);
return new TestAsyncPanZoomController(aLayersId, mcc, this,
return new TestAsyncPanZoomController(aLayersId, mcc, this, aPaintThrottler,
AsyncPanZoomController::USE_GESTURE_DETECTOR);
}
@ -292,8 +298,9 @@ protected:
APZThreadUtils::SetControllerThread(MessageLoop::current());
mcc = new NiceMock<MockContentControllerDelayed>();
mPaintThrottler = new TaskThrottler(mcc->Time(), TimeDuration::FromMilliseconds(500));
tm = new TestAPZCTreeManager(mcc);
apzc = new TestAsyncPanZoomController(0, mcc, tm, mGestureBehavior);
apzc = new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler, mGestureBehavior);
apzc->SetFrameMetrics(TestFrameMetrics());
}
@ -376,6 +383,7 @@ protected:
AsyncPanZoomController::GestureBehavior mGestureBehavior;
nsRefPtr<MockContentControllerDelayed> mcc;
nsRefPtr<TaskThrottler> mPaintThrottler;
nsRefPtr<TestAPZCTreeManager> tm;
nsRefPtr<TestAsyncPanZoomController> apzc;
};
@ -970,7 +978,7 @@ TEST_F(APZCBasicTester, ComplexTransform) {
// sides.
nsRefPtr<TestAsyncPanZoomController> childApzc =
new TestAsyncPanZoomController(0, mcc, tm);
new TestAsyncPanZoomController(0, mcc, tm, mPaintThrottler);
const char* layerTreeSyntax = "c(c)";
// LayerID 0 1
@ -3239,7 +3247,7 @@ public:
APZTaskThrottlerTester()
{
now = TimeStamp::Now();
throttler = MakeUnique<TaskThrottler>(now, TimeDuration::FromMilliseconds(100));
throttler = new TaskThrottler(now, TimeDuration::FromMilliseconds(100));
}
protected:
@ -3255,7 +3263,7 @@ protected:
}
TimeStamp now;
UniquePtr<TaskThrottler> throttler;
nsRefPtr<TaskThrottler> throttler;
TaskRunMetrics metrics;
};