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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp

Issue 1508223005: Client side display item cache flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ScrollbarTheme
Patch Set: Try performance 2 Created 4 years, 8 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
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 "platform/graphics/paint/PaintController.h" 5 #include "platform/graphics/paint/PaintController.h"
6 6
7 #include "platform/TraceEvent.h" 7 #include "platform/TraceEvent.h"
8 #include "platform/graphics/GraphicsLayer.h" 8 #include "platform/graphics/GraphicsLayer.h"
9 #include "platform/graphics/paint/DrawingDisplayItem.h" 9 #include "platform/graphics/paint/DrawingDisplayItem.h"
10 10
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 #endif 131 #endif
132 132
133 invalidateUntracked(client); 133 invalidateUntracked(client);
134 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects) 134 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects)
135 m_trackedPaintInvalidationObjects->append(client.debugName()); 135 m_trackedPaintInvalidationObjects->append(client.debugName());
136 } 136 }
137 137
138 void PaintController::invalidateUntracked(const DisplayItemClient& client) 138 void PaintController::invalidateUntracked(const DisplayItemClient& client)
139 { 139 {
140 // This can be called during painting, but we can't invalidate already paint ed clients. 140 // This can be called during painting, but we can't invalidate already paint ed clients.
141 client.setDisplayItemsCached(DisplayItemClient::kInvalidCacheGeneration);
141 ASSERT(!m_newDisplayItemIndicesByClient.contains(&client)); 142 ASSERT(!m_newDisplayItemIndicesByClient.contains(&client));
142 updateValidlyCachedClientsIfNeeded();
143 m_validlyCachedClients.remove(&client);
144 } 143 }
145 144
146 void PaintController::invalidateAll() 145 void PaintController::invalidateAll()
147 { 146 {
148 // Can only be called during layout/paintInvalidation, not during painting. 147 // Can only be called during layout/paintInvalidation, not during painting.
149 ASSERT(m_newDisplayItemList.isEmpty()); 148 ASSERT(m_newDisplayItemList.isEmpty());
150 m_currentPaintArtifact.reset(); 149 m_currentPaintArtifact.reset();
151 m_validlyCachedClients.clear(); 150 m_currentCacheGeneration = DisplayItemClient::kInvalidCacheGeneration;
152 m_validlyCachedClientsDirty = false;
153 151
154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects) 152 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects)
155 m_trackedPaintInvalidationObjects->append("##ALL##"); 153 m_trackedPaintInvalidationObjects->append("##ALL##");
156 } 154 }
157 155
158 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const 156 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const
159 { 157 {
160 if (skippingCache()) 158 ASSERT(DisplayItemClient::isAlive(client));
159 return DisplayItemClient::s_cacheStatus;
160 #if 0
161 if (!canUseClientCacheStatus() || skippingCache())
161 return false; 162 return false;
162 updateValidlyCachedClientsIfNeeded(); 163 return client.displayItemsAreCached(m_currentCacheGeneration);
163 return m_validlyCachedClients.contains(&client); 164 #endif
164 } 165 }
165 166
166 void PaintController::invalidatePaintOffset(const DisplayItemClient& client) 167 void PaintController::invalidatePaintOffset(const DisplayItemClient& client)
167 { 168 {
168 ASSERT(RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled()); 169 ASSERT(RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled());
169 invalidate(client); 170 invalidate(client);
170 171
171 #if ENABLE(ASSERT) 172 #if ENABLE(ASSERT)
172 ASSERT(!paintOffsetWasInvalidated(client)); 173 ASSERT(!paintOffsetWasInvalidated(client));
173 m_clientsWithPaintOffsetInvalidations.add(&client); 174 m_clientsWithPaintOffsetInvalidations.add(&client);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 return findOutOfOrderCachedItemForward(id, context); 230 return findOutOfOrderCachedItemForward(id, context);
230 } 231 }
231 232
232 // Find forward for the item and index all skipped indexable items. 233 // Find forward for the item and index all skipped indexable items.
233 DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context) 234 DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context)
234 { 235 {
235 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItem List().end(); 236 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItem List().end();
236 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { 237 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
237 const DisplayItem& item = *context.nextItemToIndex; 238 const DisplayItem& item = *context.nextItemToIndex;
238 ASSERT(item.hasValidClient()); 239 ASSERT(item.hasValidClient());
239 if (item.isCacheable() && clientCacheIsValid(item.client())) { 240 if (id.matches(item))
240 if (id.matches(item)) 241 return context.nextItemToIndex++;
241 return context.nextItemToIndex++; 242 if (item.isCacheable())
242
243 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain tArtifact.getDisplayItemList().begin(), context.displayItemIndicesByClient); 243 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain tArtifact.getDisplayItemList().begin(), context.displayItemIndicesByClient);
244 }
245 } 244 }
246 return currentEnd; 245 return currentEnd;
247 } 246 }
248 247
249 void PaintController::copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList) 248 void PaintController::copyCachedSubsequence(const DisplayItemList& currentList, DisplayItemList::iterator& currentIt, DisplayItemList& updatedList)
250 { 249 {
251 ASSERT(currentIt->getType() == DisplayItem::Subsequence); 250 ASSERT(currentIt->getType() == DisplayItem::Subsequence);
252 ASSERT(!currentIt->scope()); 251 ASSERT(!currentIt->scope());
253 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq uence, 0); 252 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq uence, 0);
254 do { 253 do {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 // Coefficients are related to the ratio of out-of-order CachedDisplayItems 288 // Coefficients are related to the ratio of out-of-order CachedDisplayItems
290 // and the average number of (Drawing|Subsequence)DisplayItems per client. 289 // and the average number of (Drawing|Subsequence)DisplayItems per client.
291 // 290 //
292 void PaintController::commitNewDisplayItemsInternal(const LayoutSize& offsetFrom LayoutObject) 291 void PaintController::commitNewDisplayItemsInternal(const LayoutSize& offsetFrom LayoutObject)
293 { 292 {
294 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", 293 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems",
295 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(), 294 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(),
296 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems); 295 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems);
297 m_numCachedNewItems = 0; 296 m_numCachedNewItems = 0;
298 297
299 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
300 m_clientsCheckedPaintInvalidation.clear();
301
302 // These data structures are used during painting only. 298 // These data structures are used during painting only.
303 ASSERT(m_scopeStack.isEmpty()); 299 ASSERT(m_scopeStack.isEmpty());
304 m_scopeStack.clear(); 300 m_scopeStack.clear();
305 m_nextScope = 1; 301 m_nextScope = 1;
306 ASSERT(!skippingCache()); 302 ASSERT(!skippingCache());
307 #if ENABLE(ASSERT) 303 #if ENABLE(ASSERT)
308 m_newDisplayItemIndicesByClient.clear(); 304 m_newDisplayItemIndicesByClient.clear();
309 m_clientsWithPaintOffsetInvalidations.clear(); 305 m_clientsWithPaintOffsetInvalidations.clear();
310 m_invalidations.clear(); 306 m_invalidations.clear();
311 #endif 307 #endif
312 308
313 if (m_currentPaintArtifact.isEmpty()) { 309 if (m_currentPaintArtifact.isEmpty()) {
314 #if ENABLE(ASSERT) 310 #if ENABLE(ASSERT)
315 for (const auto& item : m_newDisplayItemList) 311 for (const auto& item : m_newDisplayItemList)
316 ASSERT(!item.isCached()); 312 ASSERT(!item.isCached());
317 #endif 313 #endif
318 for (const auto& item : m_newDisplayItemList) 314 for (const auto& item : m_newDisplayItemList)
319 m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject)); 315 m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject));
320 316
321 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks()); 317 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks());
322 m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBy tes); 318 m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBy tes);
323 m_validlyCachedClientsDirty = true; 319 updateCacheGeneration();
324 return; 320 return;
325 } 321 }
326 322
327 updateValidlyCachedClientsIfNeeded();
328
329 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched 323 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched
330 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched 324 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched
331 // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This en sures that when 325 // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This en sures that when
332 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems 326 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems
333 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time. 327 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time.
334 OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.getDisp layItemList().begin()); 328 OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.getDisp layItemList().begin());
335 329
336 // TODO(jbroman): Consider revisiting this heuristic. 330 // TODO(jbroman): Consider revisiting this heuristic.
337 DisplayItemList updatedList(std::max(m_currentPaintArtifact.getDisplayItemLi st().usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes())); 331 DisplayItemList updatedList(std::max(m_currentPaintArtifact.getDisplayItemLi st().usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes()));
338 Vector<PaintChunk> updatedPaintChunks; 332 Vector<PaintChunk> updatedPaintChunks;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 #if ENABLE(ASSERT) 390 #if ENABLE(ASSERT)
397 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) 391 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
398 checkNoRemainingCachedDisplayItems(); 392 checkNoRemainingCachedDisplayItems();
399 #endif // ENABLE(ASSERT) 393 #endif // ENABLE(ASSERT)
400 394
401 // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to 395 // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to
402 // merge the paint chunks as well. 396 // merge the paint chunks as well.
403 m_currentPaintArtifact = PaintArtifact(std::move(updatedList), m_newPaintChu nks.releasePaintChunks()); 397 m_currentPaintArtifact = PaintArtifact(std::move(updatedList), m_newPaintChu nks.releasePaintChunks());
404 398
405 m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes) ; 399 m_newDisplayItemList = DisplayItemList(kInitialDisplayItemListCapacityBytes) ;
406 m_validlyCachedClientsDirty = true; 400 updateCacheGeneration();
407 } 401 }
408 402
409 size_t PaintController::approximateUnsharedMemoryUsage() const 403 size_t PaintController::approximateUnsharedMemoryUsage() const
410 { 404 {
411 size_t memoryUsage = sizeof(*this); 405 size_t memoryUsage = sizeof(*this);
412 406
413 // Memory outside this class due to m_currentPaintArtifact. 407 // Memory outside this class due to m_currentPaintArtifact.
414 memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - siz eof(m_currentPaintArtifact); 408 memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - siz eof(m_currentPaintArtifact);
415 409
416 // TODO(jbroman): If display items begin to have significant external memory 410 // TODO(jbroman): If display items begin to have significant external memory
417 // usage that's not shared with the embedder, we should account for it here. 411 // usage that's not shared with the embedder, we should account for it here.
418 // 412 //
419 // External objects, shared with the embedder, such as SkPicture, should be 413 // External objects, shared with the embedder, such as SkPicture, should be
420 // excluded to avoid double counting. It is the embedder's responsibility to 414 // excluded to avoid double counting. It is the embedder's responsibility to
421 // count such objects. 415 // count such objects.
422 // 416 //
423 // At time of writing, the only known case of unshared external memory was 417 // At time of writing, the only known case of unshared external memory was
424 // the rounded clips vector in ClipDisplayItem, which is not expected to 418 // the rounded clips vector in ClipDisplayItem, which is not expected to
425 // contribute significantly to memory usage. 419 // contribute significantly to memory usage.
426 420
427 // Memory outside this class due to m_newDisplayItemList. 421 // Memory outside this class due to m_newDisplayItemList.
428 ASSERT(m_newDisplayItemList.isEmpty()); 422 ASSERT(m_newDisplayItemList.isEmpty());
429 memoryUsage += m_newDisplayItemList.memoryUsageInBytes(); 423 memoryUsage += m_newDisplayItemList.memoryUsageInBytes();
430 424
431 return memoryUsage; 425 return memoryUsage;
432 } 426 }
433 427
434 void PaintController::updateValidlyCachedClientsIfNeeded() const 428 unsigned PaintController::nextCacheGeneration()
435 { 429 {
436 if (!m_validlyCachedClientsDirty) 430 static unsigned cacheGeneration = DisplayItemClient::kInvalidCacheGeneration ;
431 ++cacheGeneration;
432 if (cacheGeneration == DisplayItemClient::kInvalidCacheGeneration) {
433 // TODO(wangxianzhu): We'll reuse an old cache generation. Should invali date all
434 // clients that are still using the old generation.
435 ++cacheGeneration;
436 }
437 return cacheGeneration;
438 }
439
440 void PaintController::updateCacheGeneration()
441 {
442 if (!canUseClientCacheStatus())
437 return; 443 return;
438 444
439 m_validlyCachedClients.clear(); 445 m_currentCacheGeneration = nextCacheGeneration();
440 m_validlyCachedClientsDirty = false;
441
442 const DisplayItemClient* lastAddedClient = nullptr;
443 for (const DisplayItem& displayItem : m_currentPaintArtifact.getDisplayItemL ist()) { 446 for (const DisplayItem& displayItem : m_currentPaintArtifact.getDisplayItemL ist()) {
444 if (&displayItem.client() == lastAddedClient) 447 if (displayItem.isCacheable())
445 continue; 448 displayItem.client().setDisplayItemsCached(m_currentCacheGeneration) ;
446 if (displayItem.isCacheable()) {
447 lastAddedClient = &displayItem.client();
448 m_validlyCachedClients.add(lastAddedClient);
449 }
450 } 449 }
451 } 450 }
452 451
453 #if ENABLE(ASSERT) 452 #if ENABLE(ASSERT)
454 453
455 void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, D isplayItemList::iterator& currentIt) 454 void PaintController::checkUnderInvalidation(DisplayItemList::iterator& newIt, D isplayItemList::iterator& currentIt)
456 { 455 {
457 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 456 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
458 ASSERT(newIt->isCached()); 457 ASSERT(newIt->isCached());
459 458
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 { 505 {
507 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 506 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
508 ASSERT(!newItem.isCached()); 507 ASSERT(!newItem.isCached());
509 ASSERT(!oldItem.isCached()); 508 ASSERT(!oldItem.isCached());
510 509
511 if (newItem.skippedCache()) { 510 if (newItem.skippedCache()) {
512 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk ipped-cache in cached subsequence", &newItem, &oldItem); 511 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk ipped-cache in cached subsequence", &newItem, &oldItem);
513 ASSERT_NOT_REACHED(); 512 ASSERT_NOT_REACHED();
514 } 513 }
515 514
516 if (newItem.isCacheable() && !m_validlyCachedClients.contains(&newItem.clien t())) { 515 if (newItem.isCacheable() && !clientCacheIsValid(newItem.client())) {
517 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: in validated in cached subsequence", &newItem, &oldItem); 516 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: in validated in cached subsequence", &newItem, &oldItem);
518 ASSERT_NOT_REACHED(); 517 ASSERT_NOT_REACHED();
519 } 518 }
520 519
521 if (newItem.equals(oldItem)) 520 if (newItem.equals(oldItem))
522 return; 521 return;
523 522
524 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: displa y item changed", &newItem, &oldItem); 523 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: displa y item changed", &newItem, &oldItem);
525 524
526 #ifndef NDEBUG 525 #ifndef NDEBUG
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 572
574 void PaintController::showDebugData() const 573 void PaintController::showDebugData() const
575 { 574 {
576 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); 575 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data());
577 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); 576 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data());
578 } 577 }
579 578
580 #endif // ifndef NDEBUG 579 #endif // ifndef NDEBUG
581 580
582 } // namespace blink 581 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698