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_2d_CaptureCommandList_h
8 #define mozilla_gfx_2d_CaptureCommandList_h
14 #include "DrawCommand.h"
16 #include "mozilla/PodOperations.h"
18 // Command object is stored into record with header containing size and
19 // redundant size of whole record. Some platforms may require Command
20 // object to be stored on 8 bytes aligned address. Therefore we need to
21 // adjust size of header for these platforms.
23 typedef uint32_t kAdvance_t
;
25 typedef uint16_t kAdvance_t
;
31 class CaptureCommandList
{
33 CaptureCommandList() : mLastCommand(nullptr) {}
34 CaptureCommandList(CaptureCommandList
&& aOther
)
35 : mStorage(std::move(aOther
.mStorage
)),
36 mLastCommand(aOther
.mLastCommand
) {
37 aOther
.mLastCommand
= nullptr;
39 ~CaptureCommandList();
41 CaptureCommandList
& operator=(CaptureCommandList
&& aOther
) {
42 mStorage
= std::move(aOther
.mStorage
);
43 mLastCommand
= aOther
.mLastCommand
;
44 aOther
.mLastCommand
= nullptr;
50 static_assert(sizeof(T
) + 2 * sizeof(kAdvance_t
) <=
51 std::numeric_limits
<kAdvance_t
>::max(),
52 "encoding is too small to contain advance");
53 const kAdvance_t kAdvance
= sizeof(T
) + 2 * sizeof(kAdvance_t
);
55 size_t size
= mStorage
.size();
56 mStorage
.resize(size
+ kAdvance
);
58 uint8_t* current
= &mStorage
.front() + size
;
59 *(kAdvance_t
*)(current
) = kAdvance
;
60 current
+= sizeof(kAdvance_t
);
61 *(kAdvance_t
*)(current
) = ~kAdvance
;
62 current
+= sizeof(kAdvance_t
);
64 T
* command
= reinterpret_cast<T
*>(current
);
65 mLastCommand
= command
;
72 if (mLastCommand
!= nullptr && mLastCommand
->GetType() == T::Type
) {
73 return reinterpret_cast<T
*>(mLastCommand
);
79 bool IsEmpty() const { return mStorage
.empty(); }
82 bool BufferWillAlloc() const {
83 const kAdvance_t kAdvance
= sizeof(T
) + 2 * sizeof(kAdvance_t
);
84 return mStorage
.size() + kAdvance
> mStorage
.capacity();
87 size_t BufferCapacity() const { return mStorage
.capacity(); }
93 explicit iterator(CaptureCommandList
& aParent
)
94 : mParent(aParent
), mCurrent(nullptr), mEnd(nullptr) {
95 if (!mParent
.mStorage
.empty()) {
96 mCurrent
= &mParent
.mStorage
.front();
97 mEnd
= mCurrent
+ mParent
.mStorage
.size();
101 bool Done() const { return mCurrent
>= mEnd
; }
104 kAdvance_t advance
= *reinterpret_cast<kAdvance_t
*>(mCurrent
);
105 kAdvance_t redundant
=
106 ~*reinterpret_cast<kAdvance_t
*>(mCurrent
+ sizeof(kAdvance_t
));
107 MOZ_RELEASE_ASSERT(advance
== redundant
);
110 DrawingCommand
* Get() {
112 return reinterpret_cast<DrawingCommand
*>(mCurrent
+
113 2 * sizeof(kAdvance_t
));
117 CaptureCommandList
& mParent
;
122 void Log(TreeLog
<>& aStream
) {
123 for (iterator
iter(*this); !iter
.Done(); iter
.Next()) {
124 DrawingCommand
* cmd
= iter
.Get();
131 CaptureCommandList(const CaptureCommandList
& aOther
) = delete;
132 void operator=(const CaptureCommandList
& aOther
) = delete;
135 std::vector
<uint8_t> mStorage
;
136 DrawingCommand
* mLastCommand
;
140 } // namespace mozilla
142 #endif // mozilla_gfx_2d_CaptureCommandList_h