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 #include "DrawEventRecorder.h"
9 #include "mozilla/UniquePtrExtensions.h"
10 #include "PathRecording.h"
11 #include "RecordingTypes.h"
12 #include "RecordedEventImpl.h"
17 DrawEventRecorderPrivate::DrawEventRecorderPrivate() : mExternalFonts(false) {}
19 DrawEventRecorderPrivate::~DrawEventRecorderPrivate() = default;
21 void DrawEventRecorderPrivate::SetDrawTarget(ReferencePtr aDT
) {
22 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
24 RecordEvent(RecordedSetCurrentDrawTarget(aDT
));
28 void DrawEventRecorderPrivate::StoreExternalSurfaceRecording(
29 SourceSurface
* aSurface
, uint64_t aKey
) {
30 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
32 RecordEvent(RecordedExternalSurfaceCreation(aSurface
, aKey
));
33 mExternalSurfaces
.push_back({aSurface
});
36 void DrawEventRecorderPrivate::StoreExternalImageRecording(
37 const RefPtr
<layers::Image
>& aImageOfSurfaceDescriptor
) {
38 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
40 mExternalImages
.push_back({aImageOfSurfaceDescriptor
});
43 void DrawEventRecorderPrivate::StoreSourceSurfaceRecording(
44 SourceSurface
* aSurface
, const char* aReason
) {
45 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
47 RefPtr
<DataSourceSurface
> dataSurf
= aSurface
->GetDataSurface();
48 IntSize surfaceSize
= aSurface
->GetSize();
49 Maybe
<DataSourceSurface::ScopedMap
> map
;
51 map
.emplace(dataSurf
, DataSourceSurface::READ
);
53 if (!dataSurf
|| !map
->IsMapped() ||
54 !Factory::AllowedSurfaceSize(surfaceSize
)) {
55 gfxWarning() << "Recording failed to record SourceSurface for " << aReason
;
57 // If surface size is not allowed, replace with reasonable size.
58 if (!Factory::AllowedSurfaceSize(surfaceSize
)) {
59 surfaceSize
.width
= std::min(surfaceSize
.width
, kReasonableSurfaceSize
);
60 surfaceSize
.height
= std::min(surfaceSize
.height
, kReasonableSurfaceSize
);
63 // Insert a dummy source surface.
64 int32_t stride
= surfaceSize
.width
* BytesPerPixel(aSurface
->GetFormat());
65 UniquePtr
<uint8_t[]> sourceData
=
66 MakeUniqueFallible
<uint8_t[]>(stride
* surfaceSize
.height
);
68 // If the surface is too big just create a 1 x 1 dummy.
69 surfaceSize
.width
= 1;
70 surfaceSize
.height
= 1;
71 stride
= surfaceSize
.width
* BytesPerPixel(aSurface
->GetFormat());
72 sourceData
= MakeUnique
<uint8_t[]>(stride
* surfaceSize
.height
);
75 RecordEvent(RecordedSourceSurfaceCreation(aSurface
, sourceData
.get(),
77 aSurface
->GetFormat()));
81 RecordEvent(RecordedSourceSurfaceCreation(
82 aSurface
, map
->GetData(), map
->GetStride(), dataSurf
->GetSize(),
83 dataSurf
->GetFormat()));
86 void DrawEventRecorderPrivate::RecordSourceSurfaceDestruction(void* aSurface
) {
87 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
89 RemoveSourceSurface(static_cast<SourceSurface
*>(aSurface
));
90 RemoveStoredObject(aSurface
);
91 RecordEvent(RecordedSourceSurfaceDestruction(ReferencePtr(aSurface
)));
94 void DrawEventRecorderPrivate::DecrementUnscaledFontRefCount(
95 const ReferencePtr aUnscaledFont
) {
96 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderPrivate
);
98 auto element
= mUnscaledFontRefs
.Lookup(aUnscaledFont
);
99 MOZ_DIAGNOSTIC_ASSERT(element
,
100 "DecrementUnscaledFontRefCount calls should balance "
101 "with IncrementUnscaledFontRefCount calls");
102 if (--element
.Data() <= 0) {
103 RecordEvent(RecordedUnscaledFontDestruction(aUnscaledFont
));
108 void DrawEventRecorderMemory::RecordEvent(const RecordedEvent
& aEvent
) {
109 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
110 aEvent
.RecordToStream(mOutputStream
);
113 void DrawEventRecorderMemory::AddDependentSurface(uint64_t aDependencyId
) {
114 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
115 mDependentSurfaces
.Insert(aDependencyId
);
118 nsTHashSet
<uint64_t>&& DrawEventRecorderMemory::TakeDependentSurfaces() {
119 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
120 return std::move(mDependentSurfaces
);
123 DrawEventRecorderMemory::DrawEventRecorderMemory() {
124 WriteHeader(mOutputStream
);
127 DrawEventRecorderMemory::DrawEventRecorderMemory(
128 const SerializeResourcesFn
& aFn
)
129 : mSerializeCallback(aFn
) {
130 mExternalFonts
= !!mSerializeCallback
;
131 WriteHeader(mOutputStream
);
134 void DrawEventRecorderMemory::Flush() {
135 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
138 void DrawEventRecorderMemory::FlushItem(IntRect aRect
) {
139 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
141 MOZ_RELEASE_ASSERT(!aRect
.IsEmpty());
142 // Detaching our existing resources will add some
143 // destruction events to our stream so we need to do that
147 // See moz2d_renderer.rs for a description of the stream format
148 WriteElement(mIndex
, mOutputStream
.mLength
);
150 // write out the fonts into the extra data section
151 mSerializeCallback(mOutputStream
, mScaledFonts
);
152 WriteElement(mIndex
, mOutputStream
.mLength
);
154 WriteElement(mIndex
, aRect
.x
);
155 WriteElement(mIndex
, aRect
.y
);
156 WriteElement(mIndex
, aRect
.XMost());
157 WriteElement(mIndex
, aRect
.YMost());
160 // write out a new header for the next recording in the stream
161 WriteHeader(mOutputStream
);
164 bool DrawEventRecorderMemory::Finish() {
165 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
167 // this length might be 0, and things should still work.
168 // for example if there are no items in a particular area
169 size_t indexOffset
= mOutputStream
.mLength
;
170 // write out the index
171 mOutputStream
.write(mIndex
.mData
, mIndex
.mLength
);
172 bool hasItems
= mIndex
.mLength
!= 0;
174 // write out the offset of the Index to the end of the output stream
175 WriteElement(mOutputStream
, indexOffset
);
180 size_t DrawEventRecorderMemory::RecordingSize() {
181 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
182 return mOutputStream
.mLength
;
185 void DrawEventRecorderMemory::WipeRecording() {
186 NS_ASSERT_OWNINGTHREAD(DrawEventRecorderMemory
);
188 mOutputStream
.reset();
191 WriteHeader(mOutputStream
);
195 } // namespace mozilla