Index: Source/platform/graphics/paint/DisplayItems.h |
diff --git a/Source/platform/graphics/paint/DisplayItems.h b/Source/platform/graphics/paint/DisplayItems.h |
index ff125ed3d3d2a9dcbf59e36f76f7e9b05c9726ca..bc4911cbc316647a9a3802e5c4d5245e402716b9 100644 |
--- a/Source/platform/graphics/paint/DisplayItems.h |
+++ b/Source/platform/graphics/paint/DisplayItems.h |
@@ -8,9 +8,13 @@ |
#include "platform/PlatformExport.h" |
#include "platform/graphics/paint/DisplayItem.h" |
#include "platform/graphics/paint/DrawingDisplayItem.h" |
+#include "wtf/Alignment.h" |
#include "wtf/Forward.h" |
#include "wtf/Noncopyable.h" |
#include "wtf/OwnPtr.h" |
+#include "wtf/StdLibExtras.h" |
+#include "wtf/TypeTraits.h" |
+#include "wtf/Utility.h" |
#include "wtf/Vector.h" |
#include <iterator> |
@@ -83,14 +87,14 @@ public: |
// Input iterators over the display items. |
class Iterator : public std::iterator<std::input_iterator_tag, const ItemHandle> { |
public: |
- const ItemHandle& operator*() const { m_handle = ItemHandle(m_iterator->get()); return m_handle; } |
+ const ItemHandle& operator*() const { m_handle = ItemHandle(*m_iterator); return m_handle; } |
const ItemHandle* operator->() const { return &operator*(); } |
Iterator& operator++() { ++m_iterator; return *this; } |
Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } |
bool operator==(const Iterator& other) const { return m_iterator == other.m_iterator; } |
bool operator!=(const Iterator& other) const { return !(*this == other); } |
private: |
- using InternalIterator = Vector<OwnPtr<DisplayItem>>::iterator; |
+ using InternalIterator = Vector<DisplayItem*>::iterator; |
Iterator(const InternalIterator& it) : m_iterator(it) { } |
InternalIterator m_iterator; |
mutable ItemHandle m_handle; |
@@ -100,14 +104,14 @@ public: |
class ConstIterator : public std::iterator<std::input_iterator_tag, const ItemHandle> { |
public: |
ConstIterator(const Iterator& it) : m_iterator(it.m_iterator) { } |
- const ItemHandle& operator*() const { m_handle = ItemHandle(m_iterator->get()); return m_handle; } |
+ const ItemHandle& operator*() const { m_handle = ItemHandle(*m_iterator); return m_handle; } |
const ItemHandle* operator->() const { return &operator*(); } |
ConstIterator& operator++() { ++m_iterator; return *this; } |
ConstIterator operator++(int) { ConstIterator tmp(*this); operator++(); return tmp; } |
bool operator==(const ConstIterator& other) const { return m_iterator == other.m_iterator; } |
bool operator!=(const ConstIterator& other) const { return !(*this == other); } |
private: |
- using InternalIterator = Vector<OwnPtr<DisplayItem>>::const_iterator; |
+ using InternalIterator = Vector<DisplayItem*>::const_iterator; |
ConstIterator(const InternalIterator& it) : m_iterator(it) { } |
InternalIterator m_iterator; |
mutable ItemHandle m_handle; |
@@ -121,7 +125,7 @@ public: |
size_t size() const { return m_items.size(); } |
// Random access may not remain O(1) in the future. |
- ItemHandle operator[](size_t index) const { return ItemHandle(m_items[index].get()); } |
+ ItemHandle operator[](size_t index) const { return ItemHandle(m_items[index]); } |
Iterator iteratorAt(size_t index) { return Iterator(m_items.begin() + index); } |
ConstIterator iteratorAt(size_t index) const { return ConstIterator(m_items.begin() + index); } |
size_t indexForIterator(const Iterator& it) const { return it.m_iterator - m_items.begin(); } |
@@ -134,17 +138,31 @@ public: |
ConstIterator end() const { return ConstIterator(m_items.end()); } |
// Access to the end of the list should also be fast. |
- ItemHandle last() const { return ItemHandle(m_items.last().get()); } |
- |
- // TODO(jbroman): Replace this with something that doesn't first require |
- // heap allocation. |
- void append(PassOwnPtr<DisplayItem>); |
+ ItemHandle last() const { return ItemHandle(m_items.last()); } |
// Appends by moving from another list. The item in the list it's being |
// removed from will become "gone" in this process, but can still be safely |
// destroyed. |
void appendByMoving(const Iterator&); |
+ // TODO(jbroman): Returning the item here is helpful to initialize a handful |
+ // of items, like ClipDisplayItem, but arguably makes this interface leaky. |
+ template <typename DisplayItemClass, typename... Args> |
+ DisplayItemClass& emplaceBack(Args&&... args) |
+ { |
+ static_assert(WTF::IsSubclass<DisplayItemClass, DisplayItem>::value, |
+ "Can only emplace subclasses of DisplayItem."); |
+ static_assert(sizeof(DisplayItemClass) <= maxSize, |
+ "DisplayItem subclass is larger than storage buffer."); |
+ static_assert(maxAlign % WTF_ALIGN_OF(DisplayItemClass) == 0, |
+ "DisplayItem subclass isn't aligned in storage buffer."); |
+ DisplayItemClass* displayItem = |
+ static_cast<DisplayItemClass*>(appendStorageBuffer().asDisplayItem()); |
+ new (displayItem) DisplayItemClass(WTF::forward<Args>(args)...); |
+ m_items.append(displayItem); |
+ return *displayItem; |
+ } |
+ |
void removeLast(); |
void clear(); |
@@ -156,7 +174,33 @@ public: |
void setGone(const Iterator&); |
private: |
- Vector<OwnPtr<DisplayItem>> m_items; |
+ // TODO(jbroman): These need to be kept up to date. |
+ // There are compile-time checks to make sure they aren't invalid, at least. |
+ // Currently Transform3DDisplayItem is the most constraining. |
+ static const size_t maxSize = 64 + sizeof(double) * 16 + sizeof(float) * 4; |
+ static const size_t maxAlign = 16; |
+ |
+ // A DisplayItem must be constructed into asDisplayItem() immediately after |
+ // construction (at a minimum, before destruction). |
+ class StorageBuffer { |
+ WTF_MAKE_NONCOPYABLE(StorageBuffer); |
+ public: |
+ StorageBuffer() { } |
+ ~StorageBuffer() { asDisplayItem()->~DisplayItem(); } |
+ DisplayItem* asDisplayItem() { return reinterpret_cast_ptr<DisplayItem*>(&m_buffer); } |
+ private: |
+ WTF::AlignedBuffer<maxSize, maxAlign> m_buffer; |
+ }; |
+ |
+ using InnerVector = Vector<StorageBuffer>; |
+ using OuterVector = Vector<OwnPtr<InnerVector>, 8>; |
+ |
+ StorageBuffer& appendStorageBuffer(); |
+ |
+ OuterVector m_buffers; |
+ |
+ // Non-owning pointers into m_buffers. |
+ Vector<DisplayItem*> m_items; |
}; |
} // namespace blink |