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

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

Issue 1313223002: Simplify subtree (now subsequence) caching (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 3 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 #include "platform/TraceEvent.h" 10 #include "platform/TraceEvent.h"
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 ASSERT(!m_constructionDisabled); 66 ASSERT(!m_constructionDisabled);
67 ASSERT(!skippingCache() || !displayItem->isCached()); 67 ASSERT(!skippingCache() || !displayItem->isCached());
68 68
69 if (displayItem->isCached()) 69 if (displayItem->isCached())
70 ++m_numCachedItems; 70 ++m_numCachedItems;
71 71
72 #if ENABLE(ASSERT) 72 #if ENABLE(ASSERT)
73 // Verify noop begin/end pairs have been removed. 73 // Verify noop begin/end pairs have been removed.
74 if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) { 74 if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) {
75 const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size( ) - 2]; 75 const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size( ) - 2];
76 if (beginDisplayItem.isBegin() && !beginDisplayItem.drawsContent()) 76 if (beginDisplayItem.isBegin() && beginDisplayItem.type() != DisplayItem ::BeginSubsequence && !beginDisplayItem.drawsContent())
77 ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type())); 77 ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type()));
78 } 78 }
79 #endif 79 #endif
80 80
81 if (!m_scopeStack.isEmpty()) 81 if (!m_scopeStack.isEmpty())
82 displayItem->setScope(m_scopeStack.last()); 82 displayItem->setScope(m_scopeStack.last());
83 83
84 #if ENABLE(ASSERT) 84 #if ENABLE(ASSERT)
85 size_t index = findMatchingItemFromIndex(displayItem->nonCachedId(), m_newDi splayItemIndicesByClient, m_newDisplayItems); 85 size_t index = findMatchingItemFromIndex(displayItem->nonCachedId(), m_newDi splayItemIndicesByClient, m_newDisplayItems);
86 if (index != kNotFound) { 86 if (index != kNotFound) {
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin ) { } 171 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin ) { }
172 172
173 DisplayItems::iterator nextItemToIndex; 173 DisplayItems::iterator nextItemToIndex;
174 DisplayItemIndicesByClientMap displayItemIndicesByClient; 174 DisplayItemIndicesByClientMap displayItemIndicesByClient;
175 }; 175 };
176 176
177 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i terator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context) 177 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i terator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context)
178 { 178 {
179 ASSERT(clientCacheIsValid(id.client)); 179 ASSERT(clientCacheIsValid(id.client));
180 180
181 // Skip indexing of copied items.
182 if (currentIt - context.nextItemToIndex > 0)
183 context.nextItemToIndex = currentIt;
184
185 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices ByClient, m_currentDisplayItems); 181 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices ByClient, m_currentDisplayItems);
186 if (foundIndex != kNotFound) 182 if (foundIndex != kNotFound)
187 return m_currentDisplayItems.begin() + foundIndex; 183 return m_currentDisplayItems.begin() + foundIndex;
188 184
189 return findOutOfOrderCachedItemForward(id, context); 185 return findOutOfOrderCachedItemForward(currentIt, id, context);
190 } 186 }
191 187
192 // Find forward for the item and index all skipped indexable items. 188 // Find forward for the item and index all skipped indexable items.
193 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di splayItem::Id& id, OutOfOrderIndexContext& context) 189 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI tems::iterator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& con text)
194 { 190 {
191 // Items before currentIt should have been copied. Skip indexing of them.
192 if (currentIt - context.nextItemToIndex > 0)
193 context.nextItemToIndex = currentIt;
194
195 DisplayItems::iterator currentEnd = m_currentDisplayItems.end(); 195 DisplayItems::iterator currentEnd = m_currentDisplayItems.end();
196 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { 196 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
197 const DisplayItem& item = *context.nextItemToIndex; 197 const DisplayItem& item = *context.nextItemToIndex;
198 ASSERT(item.isValid()); 198 ASSERT(item.isValid());
199 if (item.isCacheable() && clientCacheIsValid(item.client())) { 199 if (item.isCacheable() && clientCacheIsValid(item.client())) {
200 if (id.matches(item)) 200 if (id.matches(item))
201 return context.nextItemToIndex++; 201 return context.nextItemToIndex++;
202 202
203 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisp layItems.begin(), context.displayItemIndicesByClient); 203 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisp layItems.begin(), context.displayItemIndicesByClient);
204 } 204 }
205 } 205 }
206 return currentEnd; 206 return currentEnd;
207 } 207 }
208 208
209 void DisplayItemList::copyCachedSubtree(DisplayItems::iterator& currentIt, Displ ayItems& updatedList) 209 void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, D isplayItems& updatedList)
210 { 210 {
211 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); 211 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
212 ASSERT(currentIt->isBeginSubtree()); 212 ASSERT(currentIt->type() == DisplayItem::BeginSubsequence);
213 ASSERT(!currentIt->scope()); 213 ASSERT(!currentIt->scope());
214 DisplayItem::Id endSubtreeId(currentIt->client(), DisplayItem::beginSubtreeT ypeToEndSubtreeType(currentIt->type()), 0); 214 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq uence, 0);
215 do { 215 do {
216 // We should always find the EndSubtree display item. 216 // We should always find the EndSubsequence display item.
217 ASSERT(currentIt != m_currentDisplayItems.end()); 217 ASSERT(currentIt != m_currentDisplayItems.end());
218 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); 218 updatedList.appendByMoving(*currentIt, currentIt->derivedSize());
219 ++currentIt; 219 ++currentIt;
220 } while (!endSubtreeId.matches(updatedList.last())); 220 } while (!endSubsequenceId.matches(updatedList.last()));
221 } 221 }
222 222
223 // Update the existing display items by removing invalidated entries, updating 223 // Update the existing display items by removing invalidated entries, updating
224 // repainted ones, and appending new items. 224 // repainted ones, and appending new items.
225 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; 225 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
226 // - For SubtreeCachedDisplayItem, copy the cached display items between the 226 // - For SubsequenceCachedDisplayItem, copy the cached display items between the
227 // corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.); 227 // corresponding BeginSubsequenceDisplayItem and EndSubsequenceDisplayItem (in cl.);
228 // - Otherwise, copy the new display item. 228 // - Otherwise, copy the new display item.
229 // 229 //
230 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). 230 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|).
231 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI tems 231 // Coefficients are related to the ratio of out-of-order [Subsequence]CachedDisp layItems
232 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. 232 // and the average number of (Drawing|BeginSubsequence)DisplayItems per client.
233 // 233 //
234 // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2. 234 // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2.
235 void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) 235 void DisplayItemList::commitNewDisplayItems(DisplayListDiff*)
236 { 236 {
237 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems", "c urrent_display_list_size", (int)m_currentDisplayItems.size(), 237 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems", "c urrent_display_list_size", (int)m_currentDisplayItems.size(),
238 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI tems); 238 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI tems);
239 239
240 // These data structures are used during painting only. 240 // These data structures are used during painting only.
241 ASSERT(m_scopeStack.isEmpty()); 241 ASSERT(m_scopeStack.isEmpty());
242 m_scopeStack.clear(); 242 m_scopeStack.clear();
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); 288 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId();
289 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt emId.type; 289 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt emId.type;
290 290
291 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche s(*currentIt); 291 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche s(*currentIt);
292 292
293 if (newDisplayItemHasCachedType) { 293 if (newDisplayItemHasCachedType) {
294 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled()); 294 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled());
295 ASSERT(newDisplayItem.isCached()); 295 ASSERT(newDisplayItem.isCached());
296 ASSERT(clientCacheIsValid(newDisplayItem.client())); 296 ASSERT(clientCacheIsValid(newDisplayItem.client()));
297 if (!isSynchronized) { 297 if (!isSynchronized) {
298 DisplayItems::iterator foundIt = findOutOfOrderCachedItem(curren tIt, newDisplayItemId, outOfOrderIndexContext); 298 currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId , outOfOrderIndexContext);
299 299
300 if (foundIt == currentEnd) { 300 if (currentIt == currentEnd) {
301 #ifndef NDEBUG 301 #ifndef NDEBUG
302 showDebugData(); 302 showDebugData();
303 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD isplayItem.asDebugString().utf8().data()); 303 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD isplayItem.asDebugString().utf8().data());
304 #endif 304 #endif
305 ASSERT_NOT_REACHED(); 305 ASSERT_NOT_REACHED();
306 306 // We did not find the cached display item. This should be i mpossible, but may occur if there is a bug
307 // If foundIt == currentEnd, it means that we did not find t he cached display item. This should be impossible, but may occur 307 // in the system, such as under-invalidation, incorrect cach e checking or duplicate display ids.
308 // if there is a bug in the system, such as under-invalidati on, incorrect cache checking or duplicate display ids. In this case, 308 // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list.
309 // attempt to recover rather than crashing or bailing on dis play of the rest of the display list.
310 continue; 309 continue;
311 } 310 }
312
313 ASSERT(foundIt != currentIt); // because we are in 'if (!isSynch ronized)'
314 currentIt = foundIt;
315 } 311 }
316 312
317 if (newDisplayItem.isCachedDrawing()) { 313 if (newDisplayItem.isCachedDrawing()) {
318 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()) ; 314 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()) ;
319 ++currentIt; 315 ++currentIt;
320 } else { 316 } else {
321 ASSERT(newDisplayItem.isCachedSubtree()); 317 ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence);
322 copyCachedSubtree(currentIt, updatedList); 318 copyCachedSubsequence(currentIt, updatedList);
323 ASSERT(updatedList.last().isEndSubtree()); 319 ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence) ;
324 } 320 }
325 } else { 321 } else {
326 #if ENABLE(ASSERT) 322 #if ENABLE(ASSERT)
327 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) 323 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled())
328 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde xContext.displayItemIndicesByClient); 324 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde xContext.displayItemIndicesByClient);
329 else 325 else
330 ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCach e() || !clientCacheIsValid(newDisplayItem.client())); 326 ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCach e() || !clientCacheIsValid(newDisplayItem.client()));
331 #endif // ENABLE(ASSERT) 327 #endif // ENABLE(ASSERT)
332 updatedList.appendByMoving(*newIt, newIt->derivedSize()); 328 updatedList.appendByMoving(*newIt, newIt->derivedSize());
333 329
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 541
546 void DisplayItemList::replay(GraphicsContext& context) 542 void DisplayItemList::replay(GraphicsContext& context)
547 { 543 {
548 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); 544 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay");
549 ASSERT(m_newDisplayItems.isEmpty()); 545 ASSERT(m_newDisplayItems.isEmpty());
550 for (DisplayItem& displayItem : m_currentDisplayItems) 546 for (DisplayItem& displayItem : m_currentDisplayItems)
551 displayItem.replay(context); 547 displayItem.replay(context);
552 } 548 }
553 549
554 } // namespace blink 550 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/graphics/paint/DisplayItemList.h ('k') | Source/platform/graphics/paint/DisplayItemListTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698