зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1738971 - Part 1. Split out plumbing for AnimationFrameProvider from Document. r=dom-worker-reviewers,smaug
This patch splits out AnimationFrameProvider from the Document WebIDL to allow the workers to implement it. It also splits out a helper class to manage the requestAnimationFrame callbacks which may be reused on a worker thread. Differential Revision: https://phabricator.services.mozilla.com/D130262
This commit is contained in:
Родитель
36dee676de
Коммит
ce897c182a
|
@ -0,0 +1,53 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/AnimationFrameProvider.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
FrameRequest::FrameRequest(FrameRequestCallback& aCallback, int32_t aHandle)
|
||||
: mCallback(&aCallback), mHandle(aHandle) {
|
||||
LogFrameRequestCallback::LogDispatch(mCallback);
|
||||
}
|
||||
|
||||
FrameRequest::~FrameRequest() = default;
|
||||
|
||||
nsresult FrameRequestManager::Schedule(FrameRequestCallback& aCallback,
|
||||
int32_t* aHandle) {
|
||||
if (mCallbackCounter == INT32_MAX) {
|
||||
// Can't increment without overflowing; bail out
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
int32_t newHandle = ++mCallbackCounter;
|
||||
|
||||
mCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
|
||||
|
||||
*aHandle = newHandle;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool FrameRequestManager::Cancel(int32_t aHandle) {
|
||||
// mCallbacks is stored sorted by handle
|
||||
if (mCallbacks.RemoveElementSorted(aHandle)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Unused << mCanceledCallbacks.put(aHandle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void FrameRequestManager::Unlink() { mCallbacks.Clear(); }
|
||||
|
||||
void FrameRequestManager::Traverse(nsCycleCollectionTraversalCallback& aCB) {
|
||||
for (auto& i : mCallbacks) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCB,
|
||||
"FrameRequestManager::mCallbacks[i]");
|
||||
aCB.NoteXPCOMChild(i.mCallback);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_AnimationFrameProvider_h
|
||||
#define mozilla_dom_AnimationFrameProvider_h
|
||||
|
||||
#include "mozilla/dom/AnimationFrameProviderBinding.h"
|
||||
#include "mozilla/HashTable.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
struct FrameRequest {
|
||||
FrameRequest(FrameRequestCallback& aCallback, int32_t aHandle);
|
||||
~FrameRequest();
|
||||
|
||||
// Comparator operators to allow RemoveElementSorted with an
|
||||
// integer argument on arrays of FrameRequest
|
||||
bool operator==(int32_t aHandle) const { return mHandle == aHandle; }
|
||||
bool operator<(int32_t aHandle) const { return mHandle < aHandle; }
|
||||
|
||||
RefPtr<FrameRequestCallback> mCallback;
|
||||
int32_t mHandle;
|
||||
};
|
||||
|
||||
class FrameRequestManager {
|
||||
public:
|
||||
FrameRequestManager() = default;
|
||||
~FrameRequestManager() = default;
|
||||
|
||||
nsresult Schedule(FrameRequestCallback& aCallback, int32_t* aHandle);
|
||||
bool Cancel(int32_t aHandle);
|
||||
|
||||
bool IsEmpty() const { return mCallbacks.IsEmpty(); }
|
||||
|
||||
bool IsCanceled(int32_t aHandle) const {
|
||||
return !mCanceledCallbacks.empty() && mCanceledCallbacks.has(aHandle);
|
||||
}
|
||||
|
||||
void Take(nsTArray<FrameRequest>& aCallbacks) {
|
||||
aCallbacks = std::move(mCallbacks);
|
||||
mCanceledCallbacks.clear();
|
||||
}
|
||||
|
||||
void Unlink();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCB);
|
||||
|
||||
private:
|
||||
nsTArray<FrameRequest> mCallbacks;
|
||||
|
||||
// The set of frame request callbacks that were canceled but which we failed
|
||||
// to find in mFrameRequestCallbacks.
|
||||
HashSet<int32_t> mCanceledCallbacks;
|
||||
|
||||
/**
|
||||
* The current frame request callback handle
|
||||
*/
|
||||
int32_t mCallbackCounter = 0;
|
||||
};
|
||||
|
||||
inline void ImplCycleCollectionUnlink(FrameRequestManager& aField) {
|
||||
aField.Unlink();
|
||||
}
|
||||
|
||||
inline void ImplCycleCollectionTraverse(
|
||||
nsCycleCollectionTraversalCallback& aCallback, FrameRequestManager& aField,
|
||||
const char* aName, uint32_t aFlags) {
|
||||
aField.Traverse(aCallback);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
|
@ -1252,14 +1252,6 @@ void Document::SelectorCache::NotifyExpired(SelectorCacheKey* aSelector) {
|
|||
delete aSelector;
|
||||
}
|
||||
|
||||
Document::FrameRequest::FrameRequest(FrameRequestCallback& aCallback,
|
||||
int32_t aHandle)
|
||||
: mCallback(&aCallback), mHandle(aHandle) {
|
||||
LogFrameRequestCallback::LogDispatch(mCallback);
|
||||
}
|
||||
|
||||
Document::FrameRequest::~FrameRequest() = default;
|
||||
|
||||
Document::PendingFrameStaticClone::~PendingFrameStaticClone() = default;
|
||||
|
||||
// ==================================================================
|
||||
|
@ -1412,7 +1404,6 @@ Document::Document(const char* aContentType)
|
|||
mPreloadPictureDepth(0),
|
||||
mEventsSuppressed(0),
|
||||
mIgnoreDestructiveWritesCounter(0),
|
||||
mFrameRequestCallbackCounter(0),
|
||||
mStaticCloneCount(0),
|
||||
mWindow(nullptr),
|
||||
mBFCacheEntry(nullptr),
|
||||
|
@ -2446,15 +2437,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(Document)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMidasCommandManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAll)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocGroup)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFrameRequestManager)
|
||||
|
||||
// Traverse all our nsCOMArrays.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages)
|
||||
|
||||
for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
|
||||
cb.NoteXPCOMChild(tmp->mFrameRequestCallbacks[i].mCallback);
|
||||
}
|
||||
|
||||
// Traverse animation components
|
||||
if (tmp->mAnimationController) {
|
||||
tmp->mAnimationController->Traverse(&cb);
|
||||
|
@ -2600,7 +2587,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Document)
|
|||
delete tmp->mSubDocuments;
|
||||
tmp->mSubDocuments = nullptr;
|
||||
|
||||
tmp->mFrameRequestCallbacks.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFrameRequestManager)
|
||||
MOZ_RELEASE_ASSERT(!tmp->mFrameRequestCallbacksScheduled,
|
||||
"How did we get here without our presshell going away "
|
||||
"first?");
|
||||
|
@ -6889,7 +6876,7 @@ void Document::UpdateFrameRequestCallbackSchedulingState(
|
|||
// WouldScheduleFrameRequestCallbacks() instead of adding more stuff to this
|
||||
// condition.
|
||||
bool shouldBeScheduled =
|
||||
WouldScheduleFrameRequestCallbacks() && !mFrameRequestCallbacks.IsEmpty();
|
||||
WouldScheduleFrameRequestCallbacks() && !mFrameRequestManager.IsEmpty();
|
||||
if (shouldBeScheduled == mFrameRequestCallbacksScheduled) {
|
||||
// nothing to do
|
||||
return;
|
||||
|
@ -6910,8 +6897,7 @@ void Document::UpdateFrameRequestCallbackSchedulingState(
|
|||
|
||||
void Document::TakeFrameRequestCallbacks(nsTArray<FrameRequest>& aCallbacks) {
|
||||
MOZ_ASSERT(aCallbacks.IsEmpty());
|
||||
aCallbacks = std::move(mFrameRequestCallbacks);
|
||||
mCanceledFrameRequestCallbacks.clear();
|
||||
mFrameRequestManager.Take(aCallbacks);
|
||||
// No need to manually remove ourselves from the refresh driver; it will
|
||||
// handle that part. But we do have to update our state.
|
||||
mFrameRequestCallbacksScheduled = false;
|
||||
|
@ -13210,31 +13196,23 @@ void Document::UnlinkOriginalDocumentIfStatic() {
|
|||
|
||||
nsresult Document::ScheduleFrameRequestCallback(FrameRequestCallback& aCallback,
|
||||
int32_t* aHandle) {
|
||||
if (mFrameRequestCallbackCounter == INT32_MAX) {
|
||||
// Can't increment without overflowing; bail out
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
nsresult rv = mFrameRequestManager.Schedule(aCallback, aHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
int32_t newHandle = ++mFrameRequestCallbackCounter;
|
||||
|
||||
mFrameRequestCallbacks.AppendElement(FrameRequest(aCallback, newHandle));
|
||||
UpdateFrameRequestCallbackSchedulingState();
|
||||
|
||||
*aHandle = newHandle;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void Document::CancelFrameRequestCallback(int32_t aHandle) {
|
||||
// mFrameRequestCallbacks is stored sorted by handle
|
||||
if (mFrameRequestCallbacks.RemoveElementSorted(aHandle)) {
|
||||
if (mFrameRequestManager.Cancel(aHandle)) {
|
||||
UpdateFrameRequestCallbackSchedulingState();
|
||||
} else {
|
||||
Unused << mCanceledFrameRequestCallbacks.put(aHandle);
|
||||
}
|
||||
}
|
||||
|
||||
bool Document::IsCanceledFrameRequestCallback(int32_t aHandle) const {
|
||||
return !mCanceledFrameRequestCallbacks.empty() &&
|
||||
mCanceledFrameRequestCallbacks.has(aHandle);
|
||||
return mFrameRequestManager.IsCanceled(aHandle);
|
||||
}
|
||||
|
||||
nsresult Document::GetStateObject(nsIVariant** aState) {
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "mozilla/UseCounter.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/css/StylePreloadKind.h"
|
||||
#include "mozilla/dom/AnimationFrameProvider.h"
|
||||
#include "mozilla/dom/DispatcherTrait.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -3103,19 +3104,6 @@ class Document : public nsINode,
|
|||
|
||||
SVGSVGElement* GetSVGRootElement() const;
|
||||
|
||||
struct FrameRequest {
|
||||
FrameRequest(FrameRequestCallback& aCallback, int32_t aHandle);
|
||||
~FrameRequest();
|
||||
|
||||
// Comparator operators to allow RemoveElementSorted with an
|
||||
// integer argument on arrays of FrameRequest
|
||||
bool operator==(int32_t aHandle) const { return mHandle == aHandle; }
|
||||
bool operator<(int32_t aHandle) const { return mHandle < aHandle; }
|
||||
|
||||
RefPtr<FrameRequestCallback> mCallback;
|
||||
int32_t mHandle;
|
||||
};
|
||||
|
||||
nsresult ScheduleFrameRequestCallback(FrameRequestCallback& aCallback,
|
||||
int32_t* aHandle);
|
||||
void CancelFrameRequestCallback(int32_t aHandle);
|
||||
|
@ -4985,11 +4973,6 @@ class Document : public nsINode,
|
|||
*/
|
||||
uint32_t mIgnoreDestructiveWritesCounter;
|
||||
|
||||
/**
|
||||
* The current frame request callback handle
|
||||
*/
|
||||
int32_t mFrameRequestCallbackCounter;
|
||||
|
||||
// Count of live static clones of this document.
|
||||
uint32_t mStaticCloneCount;
|
||||
|
||||
|
@ -5011,11 +4994,7 @@ class Document : public nsINode,
|
|||
|
||||
nsCOMPtr<nsIDocumentEncoder> mCachedEncoder;
|
||||
|
||||
nsTArray<FrameRequest> mFrameRequestCallbacks;
|
||||
|
||||
// The set of frame request callbacks that were canceled but which we failed
|
||||
// to find in mFrameRequestCallbacks.
|
||||
HashSet<int32_t> mCanceledFrameRequestCallbacks;
|
||||
FrameRequestManager mFrameRequestManager;
|
||||
|
||||
// This object allows us to evict ourself from the back/forward cache. The
|
||||
// pointer is non-null iff we're currently in the bfcache.
|
||||
|
|
|
@ -148,6 +148,7 @@ EXPORTS.mozilla.dom += [
|
|||
"!UseCounterWorkerList.h",
|
||||
"AbstractRange.h",
|
||||
"AncestorIterator.h",
|
||||
"AnimationFrameProvider.h",
|
||||
"AnonymousContent.h",
|
||||
"Attr.h",
|
||||
"AutoPrintEventDispatcher.h",
|
||||
|
@ -295,6 +296,7 @@ if CONFIG["FUZZING"]:
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
"AbstractRange.cpp",
|
||||
"AnimationFrameProvider.cpp",
|
||||
"AnonymousContent.cpp",
|
||||
"Attr.cpp",
|
||||
"AttrArray.cpp",
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames
|
||||
*/
|
||||
|
||||
callback FrameRequestCallback = void (DOMHighResTimeStamp time);
|
||||
|
||||
interface mixin AnimationFrameProvider {
|
||||
[Throws] long requestAnimationFrame(FrameRequestCallback callback);
|
||||
[Throws] void cancelAnimationFrame(long handle);
|
||||
};
|
|
@ -386,12 +386,8 @@ partial interface Window {
|
|||
[Throws, NeedsCallerType] attribute any outerHeight;
|
||||
};
|
||||
|
||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/RequestAnimationFrame/Overview.html
|
||||
partial interface Window {
|
||||
[Throws] long requestAnimationFrame(FrameRequestCallback callback);
|
||||
[Throws] void cancelAnimationFrame(long handle);
|
||||
};
|
||||
callback FrameRequestCallback = void (DOMHighResTimeStamp time);
|
||||
// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames
|
||||
Window includes AnimationFrameProvider;
|
||||
|
||||
// https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html
|
||||
partial interface Window {
|
||||
|
|
|
@ -403,6 +403,7 @@ WEBIDL_FILES = [
|
|||
"Animatable.webidl",
|
||||
"AnimationEffect.webidl",
|
||||
"AnimationEvent.webidl",
|
||||
"AnimationFrameProvider.webidl",
|
||||
"AnimationTimeline.webidl",
|
||||
"AnonymousContent.webidl",
|
||||
"AppInfo.webidl",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/WindowBinding.h" // For FrameRequestCallback
|
||||
#include "mozilla/dom/AnimationFrameProviderBinding.h"
|
||||
#include "mozilla/dom/WebXRBinding.h"
|
||||
#include "mozilla/dom/XRFrame.h"
|
||||
#include "mozilla/gfx/PVRManagerChild.h"
|
||||
|
|
|
@ -1890,7 +1890,7 @@ struct DocumentFrameCallbacks {
|
|||
explicit DocumentFrameCallbacks(Document* aDocument) : mDocument(aDocument) {}
|
||||
|
||||
RefPtr<Document> mDocument;
|
||||
nsTArray<Document::FrameRequest> mCallbacks;
|
||||
nsTArray<FrameRequest> mCallbacks;
|
||||
};
|
||||
|
||||
static bool HasPendingAnimations(PresShell* aPresShell) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче