Bug 1866777 - Disable test_race_cache_with_network.js on windows opt for frequent...
[gecko.git] / gfx / 2d / DrawEventRecorder.h
blob4cd572ce3104946b3d7e60eb940813ddf20bea7d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_DRAWEVENTRECORDER_H_
8 #define MOZILLA_GFX_DRAWEVENTRECORDER_H_
10 #include "2D.h"
11 #include "RecordedEvent.h"
12 #include "RecordingTypes.h"
14 #include <functional>
15 #include <vector>
17 #include "mozilla/DataMutex.h"
18 #include "mozilla/ThreadSafeWeakPtr.h"
19 #include "nsTHashMap.h"
20 #include "nsTHashSet.h"
21 #include "nsISupportsImpl.h"
23 namespace mozilla {
24 namespace gfx {
26 class PathRecording;
28 class DrawEventRecorderPrivate : public DrawEventRecorder {
29 public:
30 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate, override)
32 DrawEventRecorderPrivate();
33 virtual ~DrawEventRecorderPrivate();
34 bool Finish() override {
35 ClearResources();
36 return true;
38 virtual void FlushItem(IntRect) {}
39 void DetachResources() {
40 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
42 nsTHashSet<ScaledFont*> fonts = std::move(mStoredFonts);
43 for (const auto& font : fonts) {
44 font->RemoveUserData(reinterpret_cast<UserDataKey*>(this));
47 // SourceSurfaces can be deleted off the main thread, so we use
48 // ThreadSafeWeakPtrs to allow for this. RemoveUserData is thread safe.
49 nsTHashMap<void*, ThreadSafeWeakPtr<SourceSurface>> surfaces =
50 std::move(mStoredSurfaces);
51 for (const auto& entry : surfaces) {
52 RefPtr<SourceSurface> strongRef(entry.GetData());
53 if (strongRef) {
54 strongRef->RemoveUserData(reinterpret_cast<UserDataKey*>(this));
58 // Now that we've detached we can't get any more pending deletions, so
59 // processing now should mean we include all clean up operations.
60 ProcessPendingDeletions();
63 void ClearResources() {
64 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
65 mStoredObjects.Clear();
66 mStoredFontData.Clear();
67 mScaledFonts.clear();
70 template <class S>
71 void WriteHeader(S& aStream) {
72 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
73 WriteElement(aStream, kMagicInt);
74 WriteElement(aStream, kMajorRevision);
75 WriteElement(aStream, kMinorRevision);
78 virtual void RecordEvent(const RecordedEvent& aEvent) = 0;
80 void AddStoredObject(const ReferencePtr aObject) {
81 ProcessPendingDeletions();
82 mStoredObjects.Insert(aObject);
85 /**
86 * This is a combination of HasStoredObject and AddStoredObject, so that we
87 * only have to call ProcessPendingDeletions once, which involves locking.
88 * @param aObject the object to store if not already stored
89 * @return true if the object was not already stored, false if it was
91 bool TryAddStoredObject(const ReferencePtr aObject) {
92 ProcessPendingDeletions();
93 return mStoredObjects.EnsureInserted(aObject);
96 void AddPendingDeletion(std::function<void()>&& aPendingDeletion) {
97 auto lockedPendingDeletions = mPendingDeletions.Lock();
98 lockedPendingDeletions->emplace_back(std::move(aPendingDeletion));
101 void RemoveStoredObject(const ReferencePtr aObject) {
102 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
103 mStoredObjects.Remove(aObject);
107 * @param aUnscaledFont the UnscaledFont to increment the reference count for
108 * @return the previous reference count
110 int32_t IncrementUnscaledFontRefCount(const ReferencePtr aUnscaledFont) {
111 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
112 int32_t& count = mUnscaledFontRefs.LookupOrInsert(aUnscaledFont, 0);
113 return count++;
117 * Decrements the reference count for aUnscaledFont and, if count is now zero,
118 * records its destruction.
119 * @param aUnscaledFont the UnscaledFont to decrement the reference count for
121 void DecrementUnscaledFontRefCount(const ReferencePtr aUnscaledFont);
123 void AddScaledFont(ScaledFont* aFont) {
124 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
125 if (mStoredFonts.EnsureInserted(aFont) && WantsExternalFonts()) {
126 mScaledFonts.push_back(aFont);
130 void RemoveScaledFont(ScaledFont* aFont) { mStoredFonts.Remove(aFont); }
132 void AddSourceSurface(SourceSurface* aSurface) {
133 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
134 mStoredSurfaces.InsertOrUpdate(aSurface, aSurface);
137 void RemoveSourceSurface(SourceSurface* aSurface) {
138 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
139 mStoredSurfaces.Remove(aSurface);
142 #if defined(DEBUG)
143 // Only used within debug assertions.
144 bool HasStoredObject(const ReferencePtr aObject) {
145 ProcessPendingDeletions();
146 return mStoredObjects.Contains(aObject);
148 #endif
150 void AddStoredFontData(const uint64_t aFontDataKey) {
151 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
152 mStoredFontData.Insert(aFontDataKey);
155 bool HasStoredFontData(const uint64_t aFontDataKey) {
156 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
157 return mStoredFontData.Contains(aFontDataKey);
160 bool WantsExternalFonts() const { return mExternalFonts; }
162 void TakeExternalSurfaces(std::vector<RefPtr<SourceSurface>>& aSurfaces) {
163 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
164 aSurfaces = std::move(mExternalSurfaces);
167 virtual void StoreSourceSurfaceRecording(SourceSurface* aSurface,
168 const char* aReason);
171 * Used when a source surface is destroyed, aSurface is a void* instead of a
172 * SourceSurface* because this is called during the SourceSurface destructor,
173 * so it is partially destructed and should not be accessed.
174 * @param aSurface the surface whose destruction is being recorded
176 void RecordSourceSurfaceDestruction(void* aSurface);
178 virtual void AddDependentSurface(uint64_t aDependencyId) {
179 MOZ_CRASH("GFX: AddDependentSurface");
182 protected:
183 NS_DECL_OWNINGTHREAD
185 void StoreExternalSurfaceRecording(SourceSurface* aSurface, uint64_t aKey);
187 void ProcessPendingDeletions() {
188 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate);
190 PendingDeletionsVector pendingDeletions;
192 auto lockedPendingDeletions = mPendingDeletions.Lock();
193 pendingDeletions.swap(*lockedPendingDeletions);
195 for (const auto& pendingDeletion : pendingDeletions) {
196 pendingDeletion();
200 virtual void Flush() = 0;
202 nsTHashSet<const void*> mStoredObjects;
204 using PendingDeletionsVector = std::vector<std::function<void()>>;
205 DataMutex<PendingDeletionsVector> mPendingDeletions{
206 "DrawEventRecorderPrivate::mPendingDeletions"};
208 // It's difficult to track the lifetimes of UnscaledFonts directly, so we
209 // instead track the number of recorded ScaledFonts that hold a reference to
210 // an Unscaled font and use that as a proxy to the real lifetime. An
211 // UnscaledFonts lifetime could be longer than this, but we only use the
212 // ScaledFonts directly and if another uses an UnscaledFont we have destroyed
213 // on the translation side, it will be recreated.
214 nsTHashMap<const void*, int32_t> mUnscaledFontRefs;
216 nsTHashSet<uint64_t> mStoredFontData;
217 nsTHashSet<ScaledFont*> mStoredFonts;
218 std::vector<RefPtr<ScaledFont>> mScaledFonts;
220 // SourceSurfaces can get deleted off the main thread, so we hold a map of the
221 // raw pointer to a ThreadSafeWeakPtr to protect against this.
222 nsTHashMap<void*, ThreadSafeWeakPtr<SourceSurface>> mStoredSurfaces;
223 std::vector<RefPtr<SourceSurface>> mExternalSurfaces;
224 bool mExternalFonts;
227 typedef std::function<void(MemStream& aStream,
228 std::vector<RefPtr<ScaledFont>>& aScaledFonts)>
229 SerializeResourcesFn;
231 // WARNING: This should not be used in its existing state because
232 // it is likely to OOM because of large continguous allocations.
233 class DrawEventRecorderMemory : public DrawEventRecorderPrivate {
234 public:
235 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderMemory, override)
238 * Constructs a DrawEventRecorder that stores the recording in memory.
240 DrawEventRecorderMemory();
241 explicit DrawEventRecorderMemory(const SerializeResourcesFn& aSerialize);
243 void RecordEvent(const RecordedEvent& aEvent) override;
245 void AddDependentSurface(uint64_t aDependencyId) override;
247 nsTHashSet<uint64_t>&& TakeDependentSurfaces();
250 * @return the current size of the recording (in chars).
252 size_t RecordingSize();
255 * Wipes the internal recording buffer, but the recorder does NOT forget which
256 * objects it has recorded. This can be used so that a recording can be copied
257 * and processed in chunks, releasing memory as it goes.
259 void WipeRecording();
260 bool Finish() override;
261 void FlushItem(IntRect) override;
263 MemStream mOutputStream;
264 /* The index stream is of the form:
265 * ItemIndex { size_t dataEnd; size_t extraDataEnd; }
266 * It gets concatenated to the end of mOutputStream in Finish()
267 * The last size_t in the stream is offset of the begining of the
268 * index.
270 MemStream mIndex;
272 protected:
273 virtual ~DrawEventRecorderMemory() = default;
275 private:
276 SerializeResourcesFn mSerializeCallback;
277 nsTHashSet<uint64_t> mDependentSurfaces;
279 void Flush() override;
282 } // namespace gfx
283 } // namespace mozilla
285 #endif /* MOZILLA_GFX_DRAWEVENTRECORDER_H_ */