Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: Source/platform/graphics/paint/DisplayItemList.cpp

Issue 892293002: First version of new merge algorithm (not enabled yet) (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Traverse indices vector Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "platform/graphics/paint/DisplayItemList.h" 6 #include "platform/graphics/paint/DisplayItemList.h"
7 7
8 #include "platform/NotImplemented.h" 8 #include "platform/NotImplemented.h"
9 #include "platform/RuntimeEnabledFeatures.h" 9 #include "platform/RuntimeEnabledFeatures.h"
10 #ifndef NDEBUG 10 #ifndef NDEBUG
(...skipping 13 matching lines...) Expand all
24 24
25 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) 25 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem)
26 { 26 {
27 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 27 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
28 m_newPaints.append(displayItem); 28 m_newPaints.append(displayItem);
29 } 29 }
30 30
31 void DisplayItemList::invalidate(DisplayItemClient client) 31 void DisplayItemList::invalidate(DisplayItemClient client)
32 { 32 {
33 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 33 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
34 m_cachedClients.remove(client); 34 // Can only be called during layout/paintInvalidation, not during painting.
35 ASSERT(m_newPaints.isEmpty());
36 m_cachedDisplayItemIndicesByClient.remove(client);
35 } 37 }
36 38
37 void DisplayItemList::invalidateAll() 39 void DisplayItemList::invalidateAll()
38 { 40 {
39 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 41 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
40 // Can only be called during layout/paintInvalidation, not during painting. 42 // Can only be called during layout/paintInvalidation, not during painting.
41 ASSERT(m_newPaints.isEmpty()); 43 ASSERT(m_newPaints.isEmpty());
42 m_paintList.clear(); 44 m_paintList.clear();
43 m_cachedClients.clear(); 45 m_cachedDisplayItemIndicesByClient.clear();
44 } 46 }
45 47
46 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const 48 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const
47 { 49 {
48 return RuntimeEnabledFeatures::slimmingPaintDisplayItemCacheEnabled() && m_c achedClients.contains(client); 50 return RuntimeEnabledFeatures::slimmingPaintDisplayItemCacheEnabled() && m_c achedDisplayItemIndicesByClient.contains(client);
49 } 51 }
50 52
51 PaintList::iterator DisplayItemList::findNextMatchingCachedItem(PaintList::itera tor begin, const DisplayItem& displayItem) 53 size_t DisplayItemList::findMatchingCachedItem(const DisplayItem& displayItem)
52 { 54 {
53 PaintList::iterator end = m_paintList.end(); 55 ASSERT(displayItem.isCached() || displayItem.isSubtreeCached());
56 ASSERT(clientCacheIsValid(displayItem.client()));
54 57
55 if (!clientCacheIsValid(displayItem.client())) 58 DisplayItemIndices& indicesStruct = m_cachedDisplayItemIndicesByClient.find( displayItem.client())->value;
56 return end; 59 Vector<size_t>& indices = displayItem.isCached()
60 ? indicesStruct.drawingDisplayItemIndices
61 : indicesStruct.beginSubtreeDisplayItemIndices;
62 DisplayItem::Type matchingType = displayItem.isCached()
63 ? DisplayItem::cachedTypeToDrawingType(displayItem.type())
64 : DisplayItem::subtreeCachedTypeToBeginSubtreeType(displayItem.type());
57 65
58 for (PaintList::iterator it = begin; it != end; ++it) { 66 for (size_t index : indices) {
59 DisplayItem& existing = **it; 67 OwnPtr<DisplayItem>& existingItem = m_paintList[index];
60 if (existing.isDrawing() 68 ASSERT(!existingItem || existingItem->client() == displayItem.client());
61 && existing.client() == displayItem.client() 69 if (existingItem && existingItem->type() == matchingType)
62 && existing.type() == DisplayItem::cachedTypeToDrawingType(displayIt em.type())) 70 return index;
63 return it;
64 } 71 }
65 72
66 ASSERT_NOT_REACHED(); 73 // Previously the client generated a empty display item or an empty subtree
67 return end; 74 // which is not stored in the cache.
75 return kNotFound;
68 } 76 }
69 77
70 static void appendDisplayItem(PaintList& list, HashSet<DisplayItemClient>& clien ts, WTF::PassOwnPtr<DisplayItem> displayItem) 78 void DisplayItemList::appendDisplayItem(PaintList& list, DisplayItemIndicesByCli entMap& displayItemIndicesByClient, WTF::PassOwnPtr<DisplayItem> displayItem)
71 { 79 {
72 clients.add(displayItem->client()); 80 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find (displayItem->client());
81 DisplayItemIndices& indicesStruct = it == displayItemIndicesByClient.end() ?
82 displayItemIndicesByClient.add(displayItem->client(), DisplayItemIndices ()).storedValue->value : it->value;
83
84 if (displayItem->isDrawing())
85 indicesStruct.drawingDisplayItemIndices.append(list.size());
86 else if (displayItem->isBeginSubtree())
87 indicesStruct.beginSubtreeDisplayItemIndices.append(list.size());
88
73 list.append(displayItem); 89 list.append(displayItem);
74 } 90 }
75 91
92 void DisplayItemList::copyCachedSubtree(const DisplayItem& subtreeCachedDisplayI tem, PaintList& list, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
93 {
94 size_t index = findMatchingCachedItem(subtreeCachedDisplayItem);
95 // Previously the client generated an empty subtree for the phase.
96 if (index == kNotFound)
97 return;
98
99 ASSERT(m_paintList[index]->isBeginSubtree());
100 DisplayItem* beginSubtree = m_paintList[index].get();
101 DisplayItem::Type endSubtreeType = DisplayItem::beginSubtreeTypeToEndSubtree Type(beginSubtree->type());
102 do {
103 if (clientCacheIsValid(m_paintList[index]->client()))
104 appendDisplayItem(list, displayItemIndicesByClient, m_paintList[inde x].release());
105 ++index;
106 } while (list.last()->client() != beginSubtree->client() || list.last()->typ e() != endSubtreeType);
107 }
108
76 // Update the existing paintList by removing invalidated entries, updating 109 // Update the existing paintList by removing invalidated entries, updating
77 // repainted ones, and appending new items. 110 // repainted ones, and appending new items.
111 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
112 // - For SubtreeCachedDisplayItem, copy the cached display items between the
113 // corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.);
114 // - Otherwise, copy the new display item.
78 // 115 //
79 // The algorithm is O(|existing paint list| + |newly painted list|): by using 116 // The algorithm is O(|existing paint list| + |newly painted list|).
80 // the ordering implied by the existing paint list, extra treewalks are avoided. 117 // Coefficients are related to the ratio of [Subtree]CachedDisplayItems
118 // and the average number of (Drawing|BeginSubtree)DisplayItems per client.
81 void DisplayItemList::updatePaintList() 119 void DisplayItemList::updatePaintList()
82 { 120 {
83 if (!RuntimeEnabledFeatures::slimmingPaintDisplayItemCacheEnabled()) { 121 if (!RuntimeEnabledFeatures::slimmingPaintDisplayItemCacheEnabled()) {
84 m_paintList.clear(); 122 m_paintList.clear();
85 m_paintList.swap(m_newPaints); 123 m_paintList.swap(m_newPaints);
86 m_cachedClients.clear(); 124 m_cachedDisplayItemIndicesByClient.clear();
87 return; 125 return;
88 } 126 }
89 127
90 PaintList updatedList; 128 PaintList updatedList;
91 HashSet<DisplayItemClient> newCachedClients; 129 DisplayItemIndicesByClientMap newCachedDisplayItemIndicesByClient;
92
93 PaintList::iterator paintListIt = m_paintList.begin();
94 PaintList::iterator paintListEnd = m_paintList.end();
95 130
96 for (OwnPtr<DisplayItem>& newDisplayItem : m_newPaints) { 131 for (OwnPtr<DisplayItem>& newDisplayItem : m_newPaints) {
97 PaintList::iterator cachedItemIt = findNextMatchingCachedItem(paintListI t, *newDisplayItem); 132 if (newDisplayItem->isSubtreeCached()) {
pdr. 2015/02/05 03:35:57 It looks like we may be able to combine this with
Xianzhu 2015/02/05 17:57:03 Done.
98 if (cachedItemIt != paintListEnd) { 133 copyCachedSubtree(*newDisplayItem, updatedList, newCachedDisplayItem IndicesByClient);
99 // Copy all of the existing items over until we hit the matching cac hed item. 134 continue;
100 for (; paintListIt != cachedItemIt; ++paintListIt) { 135 }
101 if (clientCacheIsValid((*paintListIt)->client())) 136
102 appendDisplayItem(updatedList, newCachedClients, paintListIt ->release()); 137 if (newDisplayItem->isCached()) {
103 } 138 size_t index = findMatchingCachedItem(*newDisplayItem);
139 // The client previously produced an empty display item for the type .
140 if (index == kNotFound)
141 continue;
104 142
105 // Use the cached item for the new display item. 143 // Use the cached item for the new display item.
106 appendDisplayItem(updatedList, newCachedClients, cachedItemIt->relea se()); 144 newDisplayItem = m_paintList[index].release();
107 ++paintListIt;
108 } else {
109 // If the new display item is a cached placeholder, we should have f ound
110 // the cached display item.
111 ASSERT(!newDisplayItem->isCached());
112
113 // Copy over the new item.
114 appendDisplayItem(updatedList, newCachedClients, newDisplayItem.rele ase());
115 } 145 }
116 } 146 appendDisplayItem(updatedList, newCachedDisplayItemIndicesByClient, newD isplayItem.release());
117
118 // Copy over any remaining items that are validly cached.
119 for (; paintListIt != paintListEnd; ++paintListIt) {
120 if (clientCacheIsValid((*paintListIt)->client()))
121 appendDisplayItem(updatedList, newCachedClients, paintListIt->releas e());
122 } 147 }
123 148
124 m_newPaints.clear(); 149 m_newPaints.clear();
125 m_paintList.clear(); 150 m_paintList.clear();
126 m_paintList.swap(updatedList); 151 m_paintList.swap(updatedList);
127 m_cachedClients.clear(); 152 m_cachedDisplayItemIndicesByClient.clear();
128 m_cachedClients.swap(newCachedClients); 153 m_cachedDisplayItemIndicesByClient.swap(newCachedDisplayItemIndicesByClient) ;
129 } 154 }
130 155
131 #ifndef NDEBUG 156 #ifndef NDEBUG
132 157
133 WTF::String DisplayItemList::paintListAsDebugString(const PaintList& list) const 158 WTF::String DisplayItemList::paintListAsDebugString(const PaintList& list) const
134 { 159 {
135 StringBuilder stringBuilder; 160 StringBuilder stringBuilder;
136 bool isFirst = true; 161 for (size_t i = 0; i < list.size(); ++i) {
137 for (auto& displayItem : list) { 162 const OwnPtr<DisplayItem>& displayItem = list[i];
138 if (!isFirst) 163 if (i)
139 stringBuilder.append(",\n"); 164 stringBuilder.append(",\n");
140 isFirst = false; 165 if (!displayItem) {
141 stringBuilder.append('{'); 166 stringBuilder.append("null");
167 continue;
168 }
169 stringBuilder.append(String::format("{index: %d, ", (int)i));
142 displayItem->dumpPropertiesAsDebugString(stringBuilder); 170 displayItem->dumpPropertiesAsDebugString(stringBuilder);
143 stringBuilder.append(", cacheIsValid: "); 171 stringBuilder.append(", cacheIsValid: ");
144 stringBuilder.append(clientCacheIsValid(displayItem->client()) ? "true" : "false"); 172 stringBuilder.append(clientCacheIsValid(displayItem->client()) ? "true" : "false");
145 stringBuilder.append('}'); 173 stringBuilder.append('}');
146 } 174 }
147 return stringBuilder.toString(); 175 return stringBuilder.toString();
148 } 176 }
149 177
150 void DisplayItemList::showDebugData() const 178 void DisplayItemList::showDebugData() const
151 { 179 {
152 fprintf(stderr, "paint list: [%s]\n", paintListAsDebugString(m_paintList).ut f8().data()); 180 fprintf(stderr, "paint list: [%s]\n", paintListAsDebugString(m_paintList).ut f8().data());
153 fprintf(stderr, "new paints: [%s]\n", paintListAsDebugString(m_newPaints).ut f8().data()); 181 fprintf(stderr, "new paints: [%s]\n", paintListAsDebugString(m_newPaints).ut f8().data());
154 } 182 }
155 183
156 #endif 184 #endif // ifndef NDEBUG
157 185
158 void DisplayItemList::replay(GraphicsContext* context) 186 void DisplayItemList::replay(GraphicsContext* context)
159 { 187 {
160 updatePaintList(); 188 updatePaintList();
161 for (auto& displayItem : m_paintList) 189 for (auto& displayItem : m_paintList)
162 displayItem->replay(context); 190 displayItem->replay(context);
163 } 191 }
164 192
165 } // namespace blink 193 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698