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