| 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
|
|
|