OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "core/paint/ViewDisplayList.h" |
| 7 |
| 8 #include "platform/NotImplemented.h" |
| 9 #include "platform/RuntimeEnabledFeatures.h" |
| 10 |
| 11 #ifndef NDEBUG |
| 12 #include "core/rendering/RenderObject.h" |
| 13 #include "wtf/text/WTFString.h" |
| 14 #endif |
| 15 |
| 16 namespace blink { |
| 17 |
| 18 // DisplayItem types must be kept in sync with PaintPhase. |
| 19 COMPILE_ASSERT((unsigned)DisplayItem::DrawingPaintPhaseBlockBackground == (unsig
ned)PaintPhaseBlockBackground, DisplayItem_Type_should_stay_in_sync); |
| 20 COMPILE_ASSERT((unsigned)DisplayItem::DrawingPaintPhaseClippingMask == (unsigned
)PaintPhaseClippingMask, DisplayItem_Type_should_stay_in_sync); |
| 21 |
| 22 const PaintList& ViewDisplayList::paintList() |
| 23 { |
| 24 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 25 |
| 26 updatePaintList(); |
| 27 return m_paintList; |
| 28 } |
| 29 |
| 30 void ViewDisplayList::add(WTF::PassOwnPtr<DisplayItem> displayItem) |
| 31 { |
| 32 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 33 m_newPaints.append(displayItem); |
| 34 } |
| 35 |
| 36 void ViewDisplayList::invalidate(const RenderObject* renderer) |
| 37 { |
| 38 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 39 m_invalidated.add(renderer); |
| 40 } |
| 41 |
| 42 PaintList::iterator ViewDisplayList::findDisplayItem(PaintList::iterator begin,
const DisplayItem& displayItem) |
| 43 { |
| 44 PaintList::iterator end = m_paintList.end(); |
| 45 if (displayItem.renderer() && !m_paintListRenderers.contains(displayItem.ren
derer())) |
| 46 return end; |
| 47 |
| 48 for (PaintList::iterator it = begin; it != end; ++it) { |
| 49 DisplayItem& existing = **it; |
| 50 if (existing.idsEqual(displayItem)) |
| 51 return it; |
| 52 } |
| 53 |
| 54 // FIXME: Properly handle clips. |
| 55 ASSERT(!displayItem.renderer()); |
| 56 return end; |
| 57 } |
| 58 |
| 59 bool ViewDisplayList::wasInvalidated(const DisplayItem& displayItem) const |
| 60 { |
| 61 // FIXME: Use a bit on RenderObject instead of tracking m_invalidated. |
| 62 return displayItem.renderer() && m_invalidated.contains(displayItem.renderer
()); |
| 63 } |
| 64 |
| 65 static void appendDisplayItem(PaintList& list, HashSet<const RenderObject*>& ren
derers, WTF::PassOwnPtr<DisplayItem> displayItem) |
| 66 { |
| 67 if (const RenderObject* renderer = displayItem->renderer()) |
| 68 renderers.add(renderer); |
| 69 list.append(displayItem); |
| 70 } |
| 71 |
| 72 // Update the existing paintList by removing invalidated entries, updating |
| 73 // repainted ones, and appending new items. |
| 74 // |
| 75 // The algorithm is O(|existing paint list| + |newly painted list|): by using |
| 76 // the ordering implied by the existing paint list, extra treewalks are avoided. |
| 77 void ViewDisplayList::updatePaintList() |
| 78 { |
| 79 PaintList updatedList; |
| 80 HashSet<const RenderObject*> updatedRenderers; |
| 81 |
| 82 if (int maxCapacity = m_newPaints.size() + std::max(0, (int)m_paintList.size
() - (int)m_invalidated.size())) |
| 83 updatedList.reserveCapacity(maxCapacity); |
| 84 |
| 85 PaintList::iterator paintListIt = m_paintList.begin(); |
| 86 PaintList::iterator paintListEnd = m_paintList.end(); |
| 87 |
| 88 for (OwnPtr<DisplayItem>& newDisplayItem : m_newPaints) { |
| 89 if (!wasInvalidated(*newDisplayItem)) { |
| 90 PaintList::iterator repaintIt = findDisplayItem(paintListIt, *newDis
playItem); |
| 91 if (repaintIt != paintListEnd) { |
| 92 // Copy all of the existing items over until we hit the repaint. |
| 93 for (; paintListIt != repaintIt; ++paintListIt) { |
| 94 if (!wasInvalidated(**paintListIt)) |
| 95 appendDisplayItem(updatedList, updatedRenderers, paintLi
stIt->release()); |
| 96 } |
| 97 paintListIt++; |
| 98 } |
| 99 } |
| 100 // Copy over the new item. |
| 101 appendDisplayItem(updatedList, updatedRenderers, newDisplayItem.release(
)); |
| 102 } |
| 103 |
| 104 // Copy over any remaining items that were not invalidated. |
| 105 for (; paintListIt != paintListEnd; ++paintListIt) { |
| 106 if (!wasInvalidated(**paintListIt)) |
| 107 appendDisplayItem(updatedList, updatedRenderers, paintListIt->releas
e()); |
| 108 } |
| 109 |
| 110 m_invalidated.clear(); |
| 111 m_newPaints.clear(); |
| 112 m_paintList.clear(); |
| 113 m_paintList.swap(updatedList); |
| 114 m_paintListRenderers.clear(); |
| 115 m_paintListRenderers.swap(updatedRenderers); |
| 116 } |
| 117 |
| 118 #ifndef NDEBUG |
| 119 WTF::String DisplayItem::typeAsDebugString(DisplayItem::Type type) |
| 120 { |
| 121 switch (type) { |
| 122 case DisplayItem::DrawingPaintPhaseBlockBackground: return "DrawingPaintPhas
eBlockBackground"; |
| 123 case DisplayItem::DrawingPaintPhaseChildBlockBackground: return "DrawingPain
tPhaseChildBlockBackground"; |
| 124 case DisplayItem::DrawingPaintPhaseChildBlockBackgrounds: return "DrawingPai
ntPhaseChildBlockBackgrounds"; |
| 125 case DisplayItem::DrawingPaintPhaseFloat: return "DrawingPaintPhaseFloat"; |
| 126 case DisplayItem::DrawingPaintPhaseForeground: return "DrawingPaintPhaseFore
ground"; |
| 127 case DisplayItem::DrawingPaintPhaseOutline: return "DrawingPaintPhaseOutline
"; |
| 128 case DisplayItem::DrawingPaintPhaseChildOutlines: return "DrawingPaintPhaseC
hildOutlines"; |
| 129 case DisplayItem::DrawingPaintPhaseSelfOutline: return "DrawingPaintPhaseSel
fOutline"; |
| 130 case DisplayItem::DrawingPaintPhaseSelection: return "DrawingPaintPhaseSelec
tion"; |
| 131 case DisplayItem::DrawingPaintPhaseCollapsedTableBorders: return "DrawingPai
ntPhaseCollapsedTableBorders"; |
| 132 case DisplayItem::DrawingPaintPhaseTextClip: return "DrawingPaintPhaseTextCl
ip"; |
| 133 case DisplayItem::DrawingPaintPhaseMask: return "DrawingPaintPhaseMask"; |
| 134 case DisplayItem::DrawingPaintPhaseClippingMask: return "DrawingPaintPhaseCl
ippingMask"; |
| 135 case DisplayItem::ClipLayerOverflowControls: return "ClipLayerOverflowContro
ls"; |
| 136 case DisplayItem::ClipLayerBackground: return "ClipLayerBackground"; |
| 137 case DisplayItem::ClipLayerParent: return "ClipLayerParent"; |
| 138 case DisplayItem::ClipLayerFilter: return "ClipLayerFilter"; |
| 139 case DisplayItem::ClipLayerForeground: return "ClipLayerForeground"; |
| 140 case DisplayItem::ClipLayerFragmentFloat: return "ClipLayerFragmentFloat"; |
| 141 case DisplayItem::ClipLayerFragmentForeground: return "ClipLayerFragmentFore
ground"; |
| 142 case DisplayItem::ClipLayerFragmentChildOutline: return "ClipLayerFragmentCh
ildOutline"; |
| 143 case DisplayItem::ClipLayerFragmentOutline: return "ClipLayerFragmentOutline
"; |
| 144 case DisplayItem::ClipLayerFragmentMask: return "ClipLayerFragmentMask"; |
| 145 case DisplayItem::ClipLayerFragmentClippingMask: return "ClipLayerFragmentCl
ippingMask"; |
| 146 case DisplayItem::ClipLayerFragmentParent: return "ClipLayerFragmentParent"; |
| 147 case DisplayItem::ClipLayerFragmentSelection: return "ClipLayerFragmentSelec
tion"; |
| 148 case DisplayItem::ClipLayerFragmentChildBlockBackgrounds: return "ClipLayerF
ragmentChildBlockBackgrounds"; |
| 149 case DisplayItem::EndClip: return "EndClip"; |
| 150 } |
| 151 ASSERT_NOT_REACHED(); |
| 152 return "Unknown"; |
| 153 } |
| 154 |
| 155 WTF::String DisplayItem::rendererDebugString(const RenderObject* renderer) |
| 156 { |
| 157 if (renderer && renderer->node()) |
| 158 return String::format("nodeName: \"%s\", renderer: \"%p\"", renderer->no
de()->nodeName().utf8().data(), renderer); |
| 159 return String::format("renderer: \"%p\"", renderer); |
| 160 } |
| 161 |
| 162 WTF::String DisplayItem::asDebugString() const |
| 163 { |
| 164 return String::format("{%s, type: \"%s\"}", rendererDebugString(renderer()).
utf8().data(), typeAsDebugString(type()).utf8().data()); |
| 165 } |
| 166 |
| 167 static WTF::String paintListAsDebugString(const PaintList& list) |
| 168 { |
| 169 StringBuilder stringBuilder; |
| 170 bool isFirst = true; |
| 171 for (auto& displayItem : list) { |
| 172 if (!isFirst) |
| 173 stringBuilder.append(", "); |
| 174 isFirst = false; |
| 175 stringBuilder.append(displayItem->asDebugString()); |
| 176 } |
| 177 return stringBuilder.toString(); |
| 178 } |
| 179 |
| 180 void ViewDisplayList::showDebugData() const |
| 181 { |
| 182 fprintf(stderr, "paint list: [%s]\n", paintListAsDebugString(m_paintList).ut
f8().data()); |
| 183 fprintf(stderr, "new paints: [%s]\n", paintListAsDebugString(m_newPaints).ut
f8().data()); |
| 184 } |
| 185 #endif |
| 186 |
| 187 } // namespace blink |
OLD | NEW |