Backed out changeset 2960ea3e50ca (bug 1881157) for causing crashtest assertion failu...
[gecko.git] / layout / printing / DrawEventRecorder.h
blob26adf8862ab2bf4c0534b003ba5b86afbced5057
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_layout_printing_DrawEventRecorder_h
8 #define mozilla_layout_printing_DrawEventRecorder_h
10 #include <memory>
12 #include "mozilla/gfx/DrawEventRecorder.h"
13 #include "mozilla/gfx/RecordingTypes.h"
14 #include "prio.h"
15 #include "nsTArray.h"
17 namespace mozilla {
18 namespace layout {
20 class PRFileDescStream final : public mozilla::gfx::EventStream {
21 // Most writes, as seen in the print IPC use case, are very small (<32 bytes),
22 // with a small number of very large (>40KB) writes. Writes larger than this
23 // value are not buffered.
24 static const size_t kBufferSize = 1024;
26 public:
27 PRFileDescStream()
28 : mFd(nullptr), mBuffer(nullptr), mBufferPos(0), mGood(true) {}
29 PRFileDescStream(const PRFileDescStream& other) = delete;
30 ~PRFileDescStream() { Close(); }
32 void OpenFD(PRFileDesc* aFd) {
33 MOZ_DIAGNOSTIC_ASSERT(!IsOpen());
34 mFd = aFd;
35 mGood = !!mFd;
36 mBuffer.reset(new uint8_t[kBufferSize]);
37 mBufferPos = 0;
40 void Close() {
41 // We need to be API compatible with std::ostream, and so we silently handle
42 // closes on a closed FD.
43 if (IsOpen()) {
44 Flush();
45 PR_Close(mFd);
46 mFd = nullptr;
47 mBuffer.reset();
48 mBufferPos = 0;
52 bool IsOpen() { return mFd != nullptr; }
54 void Flush() {
55 // See comment in Close().
56 if (IsOpen() && mBufferPos > 0) {
57 PRInt32 length =
58 PR_Write(mFd, static_cast<const void*>(mBuffer.get()), mBufferPos);
59 mGood = length >= 0 && static_cast<size_t>(length) == mBufferPos;
60 mBufferPos = 0;
64 void Seek(PRInt64 aOffset, PRSeekWhence aWhence) {
65 Flush();
66 PRInt64 pos = PR_Seek64(mFd, aOffset, aWhence);
67 mGood = pos != -1;
70 void write(const char* aData, size_t aSize) override {
71 if (!good()) {
72 return;
75 // See comment in Close().
76 if (IsOpen()) {
77 // If we're writing more data than could ever fit in our buffer, flush the
78 // buffer and write directly.
79 if (aSize > kBufferSize) {
80 Flush();
81 PRInt32 length = PR_Write(mFd, static_cast<const void*>(aData), aSize);
82 mGood = length >= 0 && static_cast<size_t>(length) == aSize;
83 // If our write could fit in our buffer, but doesn't because the buffer
84 // is partially full, write to the buffer, flush the buffer, and then
85 // write the rest of the data to the buffer.
86 } else if (aSize > AvailableBufferSpace()) {
87 size_t length = AvailableBufferSpace();
88 WriteToBuffer(aData, length);
89 Flush();
91 WriteToBuffer(aData + length, aSize - length);
92 // Write fits in the buffer.
93 } else {
94 WriteToBuffer(aData, aSize);
99 void read(char* aOut, size_t aSize) override {
100 if (!good()) {
101 return;
104 Flush();
105 PRInt32 res = PR_Read(mFd, static_cast<void*>(aOut), aSize);
106 mGood = res >= 0 && (static_cast<size_t>(res) == aSize);
109 bool good() final { return mGood; }
111 void SetIsBad() final { mGood = false; }
113 private:
114 size_t AvailableBufferSpace() { return kBufferSize - mBufferPos; }
116 void WriteToBuffer(const char* aData, size_t aSize) {
117 MOZ_ASSERT(aSize <= AvailableBufferSpace());
118 memcpy(mBuffer.get() + mBufferPos, aData, aSize);
119 mBufferPos += aSize;
122 PRFileDesc* mFd;
123 std::unique_ptr<uint8_t[]> mBuffer;
124 size_t mBufferPos;
125 bool mGood;
128 class DrawEventRecorderPRFileDesc final : public gfx::DrawEventRecorderPrivate {
129 public:
130 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPRFileDesc, override)
131 explicit DrawEventRecorderPRFileDesc() = default;
132 ~DrawEventRecorderPRFileDesc();
134 gfx::RecorderType GetRecorderType() const final {
135 return gfx::RecorderType::PRFILEDESC;
138 void RecordEvent(const gfx::RecordedEvent& aEvent) override;
141 * Returns whether a recording file is currently open.
143 bool IsOpen();
146 * Opens the recorder with the provided PRFileDesc *.
148 void OpenFD(PRFileDesc* aFd);
151 * Closes the file so that it can be processed. The recorder does NOT forget
152 * which objects it has recorded. This can be used with OpenNew, so that a
153 * recording can be processed in chunks. The file must be open.
155 void Close();
157 void AddDependentSurface(uint64_t aDependencyId) override;
158 nsTArray<uint64_t>&& TakeDependentSurfaces();
160 private:
161 void Flush() override;
163 PRFileDescStream mOutputStream;
164 nsTArray<uint64_t> mDependentSurfaces;
167 } // namespace layout
169 } // namespace mozilla
171 #endif /* mozilla_layout_printing_DrawEventRecorder_h */