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 |