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_
11 #include "RecordedEvent.h"
12 #include "RecordingTypes.h"
13 #include "mozilla/FStream.h"
15 #include <unordered_set>
16 #include <unordered_map>
19 #include "nsHashKeys.h"
20 #include "nsTHashtable.h"
27 class DrawEventRecorderPrivate
: public DrawEventRecorder
{
29 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate
, override
)
31 DrawEventRecorderPrivate();
32 virtual ~DrawEventRecorderPrivate() = default;
33 bool Finish() override
{
37 virtual void FlushItem(IntRect
) {}
38 void DetachResources() {
39 // The iteration is a bit awkward here because our iterator will
40 // be invalidated by the removal
41 for (auto font
= mStoredFonts
.begin(); font
!= mStoredFonts
.end();) {
42 auto oldFont
= font
++;
43 (*oldFont
)->RemoveUserData(reinterpret_cast<UserDataKey
*>(this));
45 for (auto surface
= mStoredSurfaces
.begin();
46 surface
!= mStoredSurfaces
.end();) {
47 auto oldSurface
= surface
++;
48 (*oldSurface
)->RemoveUserData(reinterpret_cast<UserDataKey
*>(this));
51 mStoredSurfaces
.clear();
54 void ClearResources() {
55 mStoredObjects
.clear();
56 mStoredFontData
.clear();
61 void WriteHeader(S
& aStream
) {
62 WriteElement(aStream
, kMagicInt
);
63 WriteElement(aStream
, kMajorRevision
);
64 WriteElement(aStream
, kMinorRevision
);
67 virtual void RecordEvent(const RecordedEvent
& aEvent
) = 0;
68 void WritePath(const PathRecording
* aPath
);
70 void AddStoredObject(const ReferencePtr aObject
) {
71 mStoredObjects
.insert(aObject
);
74 void RemoveStoredObject(const ReferencePtr aObject
) {
75 mStoredObjects
.erase(aObject
);
79 * @param aUnscaledFont the UnscaledFont to increment the reference count for
80 * @return the previous reference count
82 int32_t IncrementUnscaledFontRefCount(const ReferencePtr aUnscaledFont
) {
83 int32_t& count
= mUnscaledFontRefs
[aUnscaledFont
];
88 * Decrements the reference count for aUnscaledFont and, if count is now zero,
89 * records its destruction.
90 * @param aUnscaledFont the UnscaledFont to decrement the reference count for
92 void DecrementUnscaledFontRefCount(const ReferencePtr aUnscaledFont
);
94 void AddScaledFont(ScaledFont
* aFont
) {
95 if (mStoredFonts
.insert(aFont
).second
&& WantsExternalFonts()) {
96 mScaledFonts
.push_back(aFont
);
100 void RemoveScaledFont(ScaledFont
* aFont
) { mStoredFonts
.erase(aFont
); }
102 void AddSourceSurface(SourceSurface
* aSurface
) {
103 mStoredSurfaces
.insert(aSurface
);
106 void RemoveSourceSurface(SourceSurface
* aSurface
) {
107 mStoredSurfaces
.erase(aSurface
);
110 bool HasStoredObject(const ReferencePtr aObject
) {
111 return mStoredObjects
.find(aObject
) != mStoredObjects
.end();
114 void AddStoredFontData(const uint64_t aFontDataKey
) {
115 mStoredFontData
.insert(aFontDataKey
);
118 bool HasStoredFontData(const uint64_t aFontDataKey
) {
119 return mStoredFontData
.find(aFontDataKey
) != mStoredFontData
.end();
122 bool WantsExternalFonts() const { return mExternalFonts
; }
124 void TakeExternalSurfaces(std::vector
<RefPtr
<SourceSurface
>>& aSurfaces
) {
125 aSurfaces
= std::move(mExternalSurfaces
);
128 virtual void StoreSourceSurfaceRecording(SourceSurface
* aSurface
,
129 const char* aReason
);
131 virtual void RecordSourceSurfaceDestruction(SourceSurface
* aSurface
);
133 virtual void AddDependentSurface(uint64_t aDependencyId
) {
134 MOZ_CRASH("GFX: AddDependentSurface");
138 void StoreExternalSurfaceRecording(SourceSurface
* aSurface
, uint64_t aKey
);
140 virtual void Flush() = 0;
142 std::unordered_set
<const void*> mStoredObjects
;
144 // It's difficult to track the lifetimes of UnscaledFonts directly, so we
145 // instead track the number of recorded ScaledFonts that hold a reference to
146 // an Unscaled font and use that as a proxy to the real lifetime. An
147 // UnscaledFonts lifetime could be longer than this, but we only use the
148 // ScaledFonts directly and if another uses an UnscaledFont we have destroyed
149 // on the translation side, it will be recreated.
150 std::unordered_map
<const void*, int32_t> mUnscaledFontRefs
;
152 std::unordered_set
<uint64_t> mStoredFontData
;
153 std::unordered_set
<ScaledFont
*> mStoredFonts
;
154 std::vector
<RefPtr
<ScaledFont
>> mScaledFonts
;
155 std::unordered_set
<SourceSurface
*> mStoredSurfaces
;
156 std::vector
<RefPtr
<SourceSurface
>> mExternalSurfaces
;
160 class DrawEventRecorderFile
: public DrawEventRecorderPrivate
{
161 using char_type
= filesystem::Path::value_type
;
164 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile
, override
)
165 explicit DrawEventRecorderFile(const char_type
* aFilename
);
166 virtual ~DrawEventRecorderFile();
168 void RecordEvent(const RecordedEvent
& aEvent
) override
;
171 * Returns whether a recording file is currently open.
176 * Opens new file with the provided name. The recorder does NOT forget which
177 * objects it has recorded. This can be used with Close, so that a recording
178 * can be processed in chunks. The file must not already be open.
180 void OpenNew(const char_type
* aFilename
);
183 * Closes the file so that it can be processed. The recorder does NOT forget
184 * which objects it has recorded. This can be used with OpenNew, so that a
185 * recording can be processed in chunks. The file must be open.
190 void Flush() override
;
192 mozilla::OFStream mOutputStream
;
195 typedef std::function
<void(MemStream
& aStream
,
196 std::vector
<RefPtr
<ScaledFont
>>& aScaledFonts
)>
197 SerializeResourcesFn
;
199 // WARNING: This should not be used in its existing state because
200 // it is likely to OOM because of large continguous allocations.
201 class DrawEventRecorderMemory
: public DrawEventRecorderPrivate
{
203 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderMemory
, override
)
206 * Constructs a DrawEventRecorder that stores the recording in memory.
208 DrawEventRecorderMemory();
209 explicit DrawEventRecorderMemory(const SerializeResourcesFn
& aSerialize
);
211 void RecordEvent(const RecordedEvent
& aEvent
) override
;
213 void AddDependentSurface(uint64_t aDependencyId
) override
;
215 nsTHashtable
<nsUint64HashKey
>&& TakeDependentSurfaces();
218 * @return the current size of the recording (in chars).
220 size_t RecordingSize();
223 * Wipes the internal recording buffer, but the recorder does NOT forget which
224 * objects it has recorded. This can be used so that a recording can be copied
225 * and processed in chunks, releasing memory as it goes.
227 void WipeRecording();
228 bool Finish() override
;
229 void FlushItem(IntRect
) override
;
231 MemStream mOutputStream
;
232 /* The index stream is of the form:
233 * ItemIndex { size_t dataEnd; size_t extraDataEnd; }
234 * It gets concatenated to the end of mOutputStream in Finish()
235 * The last size_t in the stream is offset of the begining of the
241 virtual ~DrawEventRecorderMemory() = default;
244 SerializeResourcesFn mSerializeCallback
;
245 nsTHashtable
<nsUint64HashKey
> mDependentSurfaces
;
247 void Flush() override
;
251 } // namespace mozilla
253 #endif /* MOZILLA_GFX_DRAWEVENTRECORDER_H_ */