mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
817a8eed36
- Bug 1248105 - Move CSSPseudoElement::GetParentObject out of header, r=boris (b851c3806d) - Bug 1248581 - Fix build bustage on WakeLock.h and CSSPseudoElement.h. r=khuey (fb47a96889) - Bug 1249230 - Prepend an extra colon to the pseudo type string. r=birtles (6af63f00de) - fix build on Mac > 10.5 (1ae9402eaf) - Bug 1241118 - Add gc = GetGeneralCategory(ch) when sc == MOZ_SCRIPT_COMMON. r=jfkthame (51dfbede47) - minor crash rep (1e7e5bc97e) - Bug 1240904 - Remove ParamTraits for NPString and NPVariant. r=bsmedberg (1850d10374) - bug 1170584 - fix PluginMessageUtils on iOS. r=jimm (c624cbe92d) - Bug 1170343 - Use release-mode asserts when plugins making NPAPI calls on the wrong thread, r=mccr8 (15c71250f4) - Bug 1239525 - Make sure async plugin initialization is off if e10s is on. r=aklotz (07e73ce74d) - Bug 1128454 - When plugin bridging fails, propagate the error back to the content process without aborting tabs. r=billm (e1547c00ab) - Bug 1222169 - remove unused function from PluginProcessChild.cpp; r=aklotz (11a8fc32e1) - Bug 1239749 - Remove extra space from PermissionSettings.js debug message. r=gwagner (abe2ac7574) - Bug 1221104 - Revoke 'midi' permission queries with TypeError. r=baku (cce673498f) - Bug 1221104 - Throw NS_ERROR_NOT_IMPLEMENTED instead of NS_ERROR_UNEXPECTED for PushPermissionDescriptor.userVisible. r=baku (face32ed7b) - Bug 1228723 - Avoid a promise worker proxy deadlock caused by synchronous Push callbacks. r=catalinb (bd564a0483) - Bug 1191931, Part 1 - Use tasks in the Push subscription tests. r=mt (3109fdf2af) - Bug 1191931, Part 2 - Test resubscribing from a worker. r=m (9527fa2672) - Bug 1243781 - Push methods called from a worker should reject with a `DOMException`. r=mt (f66818b161) - Bug 1219064 - Add test for extendable pushsubscriptionchange event. r=mt (12af4b59dd) - Bug 1176449 - Enter an update here to avoid assertions on startup. r=dbaron (1109cce81d) - Bug 1239743: Do not allow windows to be resized to sizes above the maximum texture size. We don't know how to draw to these anyway. r=jimm (694dafd544) - Remove some static_casting in CompositorParent. (bug 1245765 part 5, r=mattwoodrow) (4c7f39b18e) - Bug 1133615 - Don't assert about the contents of RestyleData::mDescendants when in a full style rebuild. r=dbaron (2b071b90d2) - Bug 1237902 (part 1) - Remove unneeded gfxContext ops in DrawTableBorderSegment(). r=roc. (8490ab67ca) - Bug 1237902 (part 2) - Pass a DrawTarget to DrawTableBorderSegment(). r=roc. (c602535af0) - Bug 1237902 (part 3) - Change the gfxContextMatrixAutoSaveRestore in PaintTableBorderBackground() to an AutoRestoreTransform. r=roc. (0b2412e7d6) - Bug 1242164 - Remove the implementation of colspan=0 (which is now dead code). r=dbaron (88555a04a4) - Bug 1235478 - Part 1: Rename eAdjustingTimer to eForceAdjustTimer. r=mchang (113a98fa28) - Bug 1235478 - Part 2: Don't update mMostRecentRefresh when nsRefreshDriver::ScheduleViewManagerFlush is called. r=mchang (7fd8599b7b) - Bug 1235478 - Part 3: Make weightmapping-12579.html fuzzy on MacOS 10.10. r=jdaggett (559683f95d) - Bug 1234049 - Ensure we always invalidate new PresShells that are created for an inactive DocShell upon reactivating them. r=smaug (aeca3e08d9) - Re-backout c216ff19d690 (bug 1059014 part 3) because the removed code is less dead than it first appears. (2cce434c50)
444 lines
15 KiB
C++
444 lines
15 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* Code to notify things that animate before a refresh, at an appropriate
|
|
* refresh rate. (Perhaps temporary, until replaced by compositor.)
|
|
*/
|
|
|
|
#ifndef nsRefreshDriver_h_
|
|
#define nsRefreshDriver_h_
|
|
|
|
#include "mozilla/TimeStamp.h"
|
|
#include "mozilla/Vector.h"
|
|
|
|
#include "mozFlushType.h"
|
|
#include "nsTObserverArray.h"
|
|
#include "nsTArray.h"
|
|
#include "nsTHashtable.h"
|
|
#include "nsTObserverArray.h"
|
|
#include "nsClassHashtable.h"
|
|
#include "nsHashKeys.h"
|
|
#include "mozilla/Attributes.h"
|
|
#include "mozilla/Maybe.h"
|
|
#include "GeckoProfiler.h"
|
|
#include "mozilla/layers/TransactionIdAllocator.h"
|
|
|
|
class nsPresContext;
|
|
class nsIPresShell;
|
|
class nsIDocument;
|
|
class imgIRequest;
|
|
|
|
namespace mozilla {
|
|
class RefreshDriverTimer;
|
|
namespace layout {
|
|
class VsyncChild;
|
|
} // namespace layout
|
|
} // namespace mozilla
|
|
|
|
/**
|
|
* An abstract base class to be implemented by callers wanting to be
|
|
* notified at refresh times. When nothing needs to be painted, callers
|
|
* may not be notified.
|
|
*/
|
|
class nsARefreshObserver {
|
|
public:
|
|
// AddRef and Release signatures that match nsISupports. Implementors
|
|
// must implement reference counting, and those that do implement
|
|
// nsISupports will already have methods with the correct signature.
|
|
//
|
|
// The refresh driver does NOT hold references to refresh observers
|
|
// except while it is notifying them.
|
|
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
|
|
NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
|
|
|
|
virtual void WillRefresh(mozilla::TimeStamp aTime) = 0;
|
|
};
|
|
|
|
/**
|
|
* An abstract base class to be implemented by callers wanting to be notified
|
|
* that a refresh has occurred. Callers must ensure an observer is removed
|
|
* before it is destroyed.
|
|
*/
|
|
class nsAPostRefreshObserver {
|
|
public:
|
|
virtual void DidRefresh() = 0;
|
|
};
|
|
|
|
class nsRefreshDriver final : public mozilla::layers::TransactionIdAllocator,
|
|
public nsARefreshObserver
|
|
{
|
|
public:
|
|
explicit nsRefreshDriver(nsPresContext *aPresContext);
|
|
~nsRefreshDriver();
|
|
|
|
static void InitializeStatics();
|
|
static void Shutdown();
|
|
|
|
/**
|
|
* Methods for testing, exposed via nsIDOMWindowUtils. See
|
|
* nsIDOMWindowUtils.advanceTimeAndRefresh for description.
|
|
*/
|
|
void AdvanceTimeAndRefresh(int64_t aMilliseconds);
|
|
void RestoreNormalRefresh();
|
|
void DoTick();
|
|
bool IsTestControllingRefreshesEnabled() const
|
|
{
|
|
return mTestControllingRefreshes;
|
|
}
|
|
|
|
/**
|
|
* Return the time of the most recent refresh. This is intended to be
|
|
* used by callers who want to start an animation now and want to know
|
|
* what time to consider the start of the animation. (This helps
|
|
* ensure that multiple animations started during the same event off
|
|
* the main event loop have the same start time.)
|
|
*/
|
|
mozilla::TimeStamp MostRecentRefresh() const;
|
|
/**
|
|
* Same thing, but in microseconds since the epoch.
|
|
*/
|
|
int64_t MostRecentRefreshEpochTime() const;
|
|
|
|
/**
|
|
* Add / remove refresh observers. Returns whether the operation
|
|
* succeeded.
|
|
*
|
|
* The flush type affects:
|
|
* + the order in which the observers are notified (lowest flush
|
|
* type to highest, in order registered)
|
|
* + (in the future) which observers are suppressed when the display
|
|
* doesn't require current position data or isn't currently
|
|
* painting, and, correspondingly, which get notified when there
|
|
* is a flush during such suppression
|
|
* and it must be either Flush_Style, Flush_Layout, or Flush_Display.
|
|
*
|
|
* The refresh driver does NOT own a reference to these observers;
|
|
* they must remove themselves before they are destroyed.
|
|
*
|
|
* The observer will be called even if there is no other activity.
|
|
*/
|
|
bool AddRefreshObserver(nsARefreshObserver *aObserver,
|
|
mozFlushType aFlushType);
|
|
bool RemoveRefreshObserver(nsARefreshObserver *aObserver,
|
|
mozFlushType aFlushType);
|
|
|
|
/**
|
|
* Add an observer that will be called after each refresh. The caller
|
|
* must remove the observer before it is deleted. This does not trigger
|
|
* refresh driver ticks.
|
|
*/
|
|
void AddPostRefreshObserver(nsAPostRefreshObserver *aObserver);
|
|
void RemovePostRefreshObserver(nsAPostRefreshObserver *aObserver);
|
|
|
|
/**
|
|
* Add/Remove imgIRequest versions of observers.
|
|
*
|
|
* These are used for hooking into the refresh driver for
|
|
* controlling animated images.
|
|
*
|
|
* @note The refresh driver owns a reference to these listeners.
|
|
*
|
|
* @note Technically, imgIRequest objects are not nsARefreshObservers, but
|
|
* for controlling animated image repaint events, we subscribe the
|
|
* imgIRequests to the nsRefreshDriver for notification of paint events.
|
|
*
|
|
* @returns whether the operation succeeded, or void in the case of removal.
|
|
*/
|
|
bool AddImageRequest(imgIRequest* aRequest);
|
|
void RemoveImageRequest(imgIRequest* aRequest);
|
|
|
|
/**
|
|
* Add / remove presshells that we should flush style and layout on
|
|
*/
|
|
bool AddStyleFlushObserver(nsIPresShell* aShell) {
|
|
NS_ASSERTION(!mStyleFlushObservers.Contains(aShell),
|
|
"Double-adding style flush observer");
|
|
// We only get the cause for the first observer each frame because capturing
|
|
// a stack is expensive. This is still useful if (1) you're trying to remove
|
|
// all flushes for a particial frame or (2) the costly flush is triggered
|
|
// near the call site where the first observer is triggered.
|
|
if (!mStyleCause) {
|
|
mStyleCause = profiler_get_backtrace();
|
|
}
|
|
bool appended = mStyleFlushObservers.AppendElement(aShell) != nullptr;
|
|
EnsureTimerStarted();
|
|
|
|
return appended;
|
|
}
|
|
void RemoveStyleFlushObserver(nsIPresShell* aShell) {
|
|
mStyleFlushObservers.RemoveElement(aShell);
|
|
}
|
|
bool AddLayoutFlushObserver(nsIPresShell* aShell) {
|
|
NS_ASSERTION(!IsLayoutFlushObserver(aShell),
|
|
"Double-adding layout flush observer");
|
|
// We only get the cause for the first observer each frame because capturing
|
|
// a stack is expensive. This is still useful if (1) you're trying to remove
|
|
// all flushes for a particial frame or (2) the costly flush is triggered
|
|
// near the call site where the first observer is triggered.
|
|
if (!mReflowCause) {
|
|
mReflowCause = profiler_get_backtrace();
|
|
}
|
|
bool appended = mLayoutFlushObservers.AppendElement(aShell) != nullptr;
|
|
EnsureTimerStarted();
|
|
return appended;
|
|
}
|
|
void RemoveLayoutFlushObserver(nsIPresShell* aShell) {
|
|
mLayoutFlushObservers.RemoveElement(aShell);
|
|
}
|
|
bool IsLayoutFlushObserver(nsIPresShell* aShell) {
|
|
return mLayoutFlushObservers.Contains(aShell);
|
|
}
|
|
bool AddPresShellToInvalidateIfHidden(nsIPresShell* aShell) {
|
|
NS_ASSERTION(!mPresShellsToInvalidateIfHidden.Contains(aShell),
|
|
"Double-adding style flush observer");
|
|
bool appended = mPresShellsToInvalidateIfHidden.AppendElement(aShell) != nullptr;
|
|
EnsureTimerStarted();
|
|
return appended;
|
|
}
|
|
void RemovePresShellToInvalidateIfHidden(nsIPresShell* aShell) {
|
|
mPresShellsToInvalidateIfHidden.RemoveElement(aShell);
|
|
}
|
|
|
|
/**
|
|
* Remember whether our presshell's view manager needs a flush
|
|
*/
|
|
void ScheduleViewManagerFlush();
|
|
void RevokeViewManagerFlush() {
|
|
mViewManagerFlushIsPending = false;
|
|
}
|
|
bool ViewManagerFlushIsPending() {
|
|
return mViewManagerFlushIsPending;
|
|
}
|
|
|
|
/**
|
|
* Add a document for which we have FrameRequestCallbacks
|
|
*/
|
|
void ScheduleFrameRequestCallbacks(nsIDocument* aDocument);
|
|
|
|
/**
|
|
* Remove a document for which we have FrameRequestCallbacks
|
|
*/
|
|
void RevokeFrameRequestCallbacks(nsIDocument* aDocument);
|
|
|
|
/**
|
|
* Tell the refresh driver that it is done driving refreshes and
|
|
* should stop its timer and forget about its pres context. This may
|
|
* be called from within a refresh.
|
|
*/
|
|
void Disconnect() {
|
|
StopTimer();
|
|
mPresContext = nullptr;
|
|
}
|
|
|
|
bool IsFrozen() { return mFreezeCount > 0; }
|
|
|
|
/**
|
|
* Freeze the refresh driver. It should stop delivering future
|
|
* refreshes until thawed. Note that the number of calls to Freeze() must
|
|
* match the number of calls to Thaw() in order for the refresh driver to
|
|
* be un-frozen.
|
|
*/
|
|
void Freeze();
|
|
|
|
/**
|
|
* Thaw the refresh driver. If the number of calls to Freeze() matches the
|
|
* number of calls to this function, the refresh driver should start
|
|
* delivering refreshes again.
|
|
*/
|
|
void Thaw();
|
|
|
|
/**
|
|
* Throttle or unthrottle the refresh driver. This is done if the
|
|
* corresponding presshell is hidden or shown.
|
|
*/
|
|
void SetThrottled(bool aThrottled);
|
|
|
|
/**
|
|
* Return the prescontext we were initialized with
|
|
*/
|
|
nsPresContext* PresContext() const { return mPresContext; }
|
|
|
|
/**
|
|
* PBackgroundChild actor is created asynchronously in content process.
|
|
* We can't create vsync-based timers during PBackground startup. This
|
|
* function will be called when PBackgroundChild actor is created. Then we can
|
|
* do the pending vsync-based timer creation.
|
|
*/
|
|
static void PVsyncActorCreated(mozilla::layout::VsyncChild* aVsyncChild);
|
|
|
|
#ifdef DEBUG
|
|
/**
|
|
* Check whether the given observer is an observer for the given flush type
|
|
*/
|
|
bool IsRefreshObserver(nsARefreshObserver *aObserver,
|
|
mozFlushType aFlushType);
|
|
#endif
|
|
|
|
/**
|
|
* Default interval the refresh driver uses, in ms.
|
|
*/
|
|
static int32_t DefaultInterval();
|
|
|
|
bool IsInRefresh() { return mInRefresh; }
|
|
|
|
/**
|
|
* The latest value of process-wide jank levels.
|
|
*
|
|
* For each i, sJankLevels[i] counts the number of times delivery of
|
|
* vsync to the main thread has been delayed by at least 2^i
|
|
* ms. This data structure has been designed to make it easy to
|
|
* determine how much jank has taken place between two instants in
|
|
* time.
|
|
*
|
|
* Return `false` if `aJank` needs to be grown to accomodate the
|
|
* data but we didn't have enough memory.
|
|
*/
|
|
static bool GetJankLevels(mozilla::Vector<uint64_t>& aJank);
|
|
|
|
// mozilla::layers::TransactionIdAllocator
|
|
virtual uint64_t GetTransactionId() override;
|
|
void NotifyTransactionCompleted(uint64_t aTransactionId) override;
|
|
void RevokeTransactionId(uint64_t aTransactionId) override;
|
|
mozilla::TimeStamp GetTransactionStart() override;
|
|
|
|
bool IsWaitingForPaint(mozilla::TimeStamp aTime);
|
|
|
|
// nsARefreshObserver
|
|
NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return TransactionIdAllocator::AddRef(); }
|
|
NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return TransactionIdAllocator::Release(); }
|
|
virtual void WillRefresh(mozilla::TimeStamp aTime) override;
|
|
private:
|
|
typedef nsTObserverArray<nsARefreshObserver*> ObserverArray;
|
|
typedef nsTHashtable<nsISupportsHashKey> RequestTable;
|
|
struct ImageStartData {
|
|
ImageStartData()
|
|
{
|
|
}
|
|
|
|
mozilla::Maybe<mozilla::TimeStamp> mStartTime;
|
|
RequestTable mEntries;
|
|
};
|
|
typedef nsClassHashtable<nsUint32HashKey, ImageStartData> ImageStartTable;
|
|
|
|
void DispatchAnimationEvents();
|
|
void RunFrameRequestCallbacks(mozilla::TimeStamp aNowTime);
|
|
|
|
void Tick(int64_t aNowEpoch, mozilla::TimeStamp aNowTime);
|
|
|
|
enum EnsureTimerStartedFlags {
|
|
eNone = 0,
|
|
eForceAdjustTimer = 1 << 0,
|
|
eAllowTimeToGoBackwards = 1 << 1,
|
|
eNeverAdjustTimer = 1 << 2,
|
|
};
|
|
void EnsureTimerStarted(EnsureTimerStartedFlags aFlags = eNone);
|
|
void StopTimer();
|
|
|
|
uint32_t ObserverCount() const;
|
|
uint32_t ImageRequestCount() const;
|
|
ObserverArray& ArrayFor(mozFlushType aFlushType);
|
|
// Trigger a refresh immediately, if haven't been disconnected or frozen.
|
|
void DoRefresh();
|
|
|
|
double GetRefreshTimerInterval() const;
|
|
double GetRegularTimerInterval(bool *outIsDefault = nullptr) const;
|
|
static double GetThrottledTimerInterval();
|
|
|
|
static mozilla::TimeDuration GetMinRecomputeVisibilityInterval();
|
|
|
|
bool HaveFrameRequestCallbacks() const {
|
|
return mFrameRequestCallbackDocs.Length() != 0;
|
|
}
|
|
|
|
void FinishedWaitingForTransaction();
|
|
|
|
mozilla::RefreshDriverTimer* ChooseTimer() const;
|
|
mozilla::RefreshDriverTimer* mActiveTimer;
|
|
|
|
ProfilerBacktrace* mReflowCause;
|
|
ProfilerBacktrace* mStyleCause;
|
|
|
|
nsPresContext *mPresContext; // weak; pres context passed in constructor
|
|
// and unset in Disconnect
|
|
|
|
RefPtr<nsRefreshDriver> mRootRefresh;
|
|
|
|
// The most recently allocated transaction id.
|
|
uint64_t mPendingTransaction;
|
|
// The most recently completed transaction id.
|
|
uint64_t mCompletedTransaction;
|
|
|
|
uint32_t mFreezeCount;
|
|
|
|
// How long we wait between ticks for throttled (which generally means
|
|
// non-visible) documents registered with a non-throttled refresh driver.
|
|
const mozilla::TimeDuration mThrottledFrameRequestInterval;
|
|
|
|
// How long we wait, at a minimum, before recomputing image visibility
|
|
// information. This is a minimum because, regardless of this interval, we
|
|
// only recompute visibility when we've seen a layout or style flush since the
|
|
// last time we did it.
|
|
const mozilla::TimeDuration mMinRecomputeVisibilityInterval;
|
|
|
|
bool mThrottled;
|
|
bool mNeedToRecomputeVisibility;
|
|
bool mTestControllingRefreshes;
|
|
bool mViewManagerFlushIsPending;
|
|
bool mRequestedHighPrecision;
|
|
bool mInRefresh;
|
|
|
|
// True if the refresh driver is suspended waiting for transaction
|
|
// id's to be returned and shouldn't do any work during Tick().
|
|
bool mWaitingForTransaction;
|
|
// True if Tick() was skipped because of mWaitingForTransaction and
|
|
// we should schedule a new Tick immediately when resumed instead
|
|
// of waiting until the next interval.
|
|
bool mSkippedPaints;
|
|
|
|
int64_t mMostRecentRefreshEpochTime;
|
|
mozilla::TimeStamp mMostRecentRefresh;
|
|
mozilla::TimeStamp mMostRecentTick;
|
|
mozilla::TimeStamp mTickStart;
|
|
mozilla::TimeStamp mNextThrottledFrameRequestTick;
|
|
mozilla::TimeStamp mNextRecomputeVisibilityTick;
|
|
|
|
// separate arrays for each flush type we support
|
|
ObserverArray mObservers[3];
|
|
RequestTable mRequests;
|
|
ImageStartTable mStartTable;
|
|
|
|
AutoTArray<nsIPresShell*, 16> mStyleFlushObservers;
|
|
AutoTArray<nsIPresShell*, 16> mLayoutFlushObservers;
|
|
AutoTArray<nsIPresShell*, 16> mPresShellsToInvalidateIfHidden;
|
|
// nsTArray on purpose, because we want to be able to swap.
|
|
nsTArray<nsIDocument*> mFrameRequestCallbackDocs;
|
|
nsTArray<nsIDocument*> mThrottledFrameRequestCallbackDocs;
|
|
nsTObserverArray<nsAPostRefreshObserver*> mPostRefreshObservers;
|
|
|
|
void BeginRefreshingImages(RequestTable& aEntries,
|
|
mozilla::TimeStamp aDesired);
|
|
|
|
friend class mozilla::RefreshDriverTimer;
|
|
|
|
// turn on or turn off high precision based on various factors
|
|
void ConfigureHighPrecision();
|
|
void SetHighPrecisionTimersEnabled(bool aEnable);
|
|
|
|
// `true` if we are currently in jank-critical mode.
|
|
//
|
|
// In jank-critical mode, any iteration of the event loop that takes
|
|
// more than 16ms to compute will cause an ongoing animation to miss
|
|
// frames.
|
|
//
|
|
// For simplicity, the current implementation assumes that we are
|
|
// in jank-critical mode if and only if the vsync driver has at least
|
|
// one observer.
|
|
static bool IsJankCritical();
|
|
};
|
|
|
|
#endif /* !defined(nsRefreshDriver_h_) */
|