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

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

Issue 1401363003: Rename DisplayItemList to PaintController (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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
(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 "platform/graphics/paint/DisplayItemList.h"
7
8 #include "platform/NotImplemented.h"
9 #include "platform/TraceEvent.h"
10 #include "platform/graphics/GraphicsLayer.h"
11 #include "platform/graphics/paint/DrawingDisplayItem.h"
12
13 #ifndef NDEBUG
14 #include "platform/graphics/LoggingCanvas.h"
15 #include "wtf/text/StringBuilder.h"
16 #include <stdio.h>
17 #endif
18
19 namespace blink {
20
21 const PaintArtifact& DisplayItemList::paintArtifact() const
22 {
23 ASSERT(m_newDisplayItems.isEmpty());
24 ASSERT(m_newPaintChunks.isInInitialState());
25 return m_currentPaintArtifact;
26 }
27
28 bool DisplayItemList::lastDisplayItemIsNoopBegin() const
29 {
30 if (m_newDisplayItems.isEmpty())
31 return false;
32
33 const auto& lastDisplayItem = m_newDisplayItems.last();
34 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent();
35 }
36
37 void DisplayItemList::removeLastDisplayItem()
38 {
39 if (m_newDisplayItems.isEmpty())
40 return;
41
42 #if ENABLE(ASSERT)
43 // Also remove the index pointing to the removed display item.
44 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient .find(m_newDisplayItems.last().client());
45 if (it != m_newDisplayItemIndicesByClient.end()) {
46 Vector<size_t>& indices = it->value;
47 if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() - 1))
48 indices.removeLast();
49 }
50 #endif
51 m_newDisplayItems.removeLast();
52
53 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
54 m_newPaintChunks.decrementDisplayItemIndex();
55 }
56
57 void DisplayItemList::processNewItem(DisplayItem& displayItem)
58 {
59 ASSERT(!m_constructionDisabled);
60 ASSERT(!skippingCache() || !displayItem.isCached());
61
62 if (displayItem.isCached())
63 ++m_numCachedItems;
64
65 #if ENABLE(ASSERT)
66 // Verify noop begin/end pairs have been removed.
67 if (m_newDisplayItems.size() >= 2 && displayItem.isEnd()) {
68 const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size( ) - 2];
69 if (beginDisplayItem.isBegin() && !beginDisplayItem.isSubsequence() && ! beginDisplayItem.drawsContent())
70 ASSERT(!displayItem.isEndAndPairedWith(beginDisplayItem.type()));
71 }
72 #endif
73
74 if (!m_scopeStack.isEmpty())
75 displayItem.setScope(m_scopeStack.last());
76
77 #if ENABLE(ASSERT)
78 size_t index = findMatchingItemFromIndex(displayItem.nonCachedId(), m_newDis playItemIndicesByClient, m_newDisplayItems);
79 if (index != kNotFound) {
80 #ifndef NDEBUG
81 showDebugData();
82 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n",
83 displayItem.asDebugString().utf8().data(), m_newDisplayItems[index]. asDebugString().utf8().data(), static_cast<int>(index));
84 #endif
85 ASSERT_NOT_REACHED();
86 }
87 addItemToIndexIfNeeded(displayItem, m_newDisplayItems.size() - 1, m_newDispl ayItemIndicesByClient);
88 #endif // ENABLE(ASSERT)
89
90 if (skippingCache())
91 displayItem.setSkippedCache();
92
93 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
94 m_newPaintChunks.incrementDisplayItemIndex();
95 }
96
97 void DisplayItemList::updateCurrentPaintChunkProperties(const PaintChunkProperti es& newProperties)
98 {
99 m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties);
100 }
101
102 void DisplayItemList::beginScope()
103 {
104 ASSERT_WITH_SECURITY_IMPLICATION(m_nextScope < UINT_MAX);
105 m_scopeStack.append(m_nextScope++);
106 beginSkippingCache();
107 }
108
109 void DisplayItemList::endScope()
110 {
111 m_scopeStack.removeLast();
112 endSkippingCache();
113 }
114
115 void DisplayItemList::invalidate(const DisplayItemClientWrapper& client, PaintIn validationReason paintInvalidationReason, const IntRect& previousPaintInvalidati onRect, const IntRect& newPaintInvalidationRect)
116 {
117 invalidateClient(client);
118
119 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
120 Invalidation invalidation = { previousPaintInvalidationRect, paintInvali dationReason };
121 if (!previousPaintInvalidationRect.isEmpty())
122 m_invalidations.append(invalidation);
123 if (newPaintInvalidationRect != previousPaintInvalidationRect && !newPai ntInvalidationRect.isEmpty()) {
124 invalidation.rect = newPaintInvalidationRect;
125 m_invalidations.append(invalidation);
126 }
127 }
128 }
129
130 void DisplayItemList::invalidateClient(const DisplayItemClientWrapper& client)
131 {
132 invalidateUntracked(client.displayItemClient());
133 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects)
134 m_trackedPaintInvalidationObjects->append(client.debugName());
135 }
136
137 void DisplayItemList::invalidateUntracked(DisplayItemClient client)
138 {
139 // This can be called during painting, but we can't invalidate already paint ed clients.
140 ASSERT(!m_newDisplayItemIndicesByClient.contains(client));
141 updateValidlyCachedClientsIfNeeded();
142 m_validlyCachedClients.remove(client);
143 }
144
145 void DisplayItemList::invalidateAll()
146 {
147 // Can only be called during layout/paintInvalidation, not during painting.
148 ASSERT(m_newDisplayItems.isEmpty());
149 m_currentPaintArtifact.reset();
150 m_validlyCachedClients.clear();
151 m_validlyCachedClientsDirty = false;
152
153 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && m_trackedPaintInvali dationObjects)
154 m_trackedPaintInvalidationObjects->append("##ALL##");
155 }
156
157 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const
158 {
159 if (skippingCache())
160 return false;
161 updateValidlyCachedClientsIfNeeded();
162 return m_validlyCachedClients.contains(client);
163 }
164
165 void DisplayItemList::invalidatePaintOffset(const DisplayItemClientWrapper& clie nt)
166 {
167 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
168 invalidateClient(client);
169
170 #if ENABLE(ASSERT)
171 ASSERT(!paintOffsetWasInvalidated(client.displayItemClient()));
172 m_clientsWithPaintOffsetInvalidations.add(client.displayItemClient());
173 #endif
174 }
175
176 #if ENABLE(ASSERT)
177 bool DisplayItemList::paintOffsetWasInvalidated(DisplayItemClient client) const
178 {
179 ASSERT(RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled());
180 return m_clientsWithPaintOffsetInvalidations.contains(client);
181 }
182 #endif
183
184 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems & list)
185 {
186 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(id.client);
187 if (it == displayItemIndicesByClient.end())
188 return kNotFound;
189
190 const Vector<size_t>& indices = it->value;
191 for (size_t index : indices) {
192 const DisplayItem& existingItem = list[index];
193 ASSERT(!existingItem.isValid() || existingItem.client() == id.client);
194 if (existingItem.isValid() && id.matches(existingItem))
195 return index;
196 }
197
198 return kNotFound;
199 }
200
201 void DisplayItemList::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
202 {
203 if (!displayItem.isCacheable())
204 return;
205
206 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find (displayItem.client());
207 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ?
208 displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).s toredValue->value : it->value;
209 indices.append(index);
210 }
211
212 struct DisplayItemList::OutOfOrderIndexContext {
213 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin ) { }
214
215 DisplayItems::iterator nextItemToIndex;
216 DisplayItemIndicesByClientMap displayItemIndicesByClient;
217 };
218
219 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(const DisplayIt em::Id& id, OutOfOrderIndexContext& context)
220 {
221 ASSERT(clientCacheIsValid(id.client));
222
223 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices ByClient, m_currentPaintArtifact.displayItems());
224 if (foundIndex != kNotFound)
225 return m_currentPaintArtifact.displayItems().begin() + foundIndex;
226
227 return findOutOfOrderCachedItemForward(id, context);
228 }
229
230 // Find forward for the item and index all skipped indexable items.
231 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di splayItem::Id& id, OutOfOrderIndexContext& context)
232 {
233 DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().en d();
234 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
235 const DisplayItem& item = *context.nextItemToIndex;
236 ASSERT(item.isValid());
237 if (item.isCacheable() && clientCacheIsValid(item.client())) {
238 if (id.matches(item))
239 return context.nextItemToIndex++;
240
241 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain tArtifact.displayItems().begin(), context.displayItemIndicesByClient);
242 }
243 }
244 return currentEnd;
245 }
246
247 void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, D isplayItems& updatedList)
248 {
249 ASSERT(currentIt->isSubsequence());
250 ASSERT(!currentIt->scope());
251 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::subsequen ceTypeToEndSubsequenceType(currentIt->type()), 0);
252 do {
253 // We should always find the EndSubsequence display item.
254 ASSERT(currentIt != m_currentPaintArtifact.displayItems().end());
255 ASSERT(currentIt->isValid());
256 updatedList.appendByMoving(*currentIt);
257 ++currentIt;
258 } while (!endSubsequenceId.matches(updatedList.last()));
259 }
260
261 // Update the existing display items by removing invalidated entries, updating
262 // repainted ones, and appending new items.
263 // - For cached drawing display item, copy the corresponding cached DrawingDispl ayItem;
264 // - For cached subsequence display item, copy the cached display items between the
265 // corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
266 // - Otherwise, copy the new display item.
267 //
268 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|).
269 // Coefficients are related to the ratio of out-of-order CachedDisplayItems
270 // and the average number of (Drawing|Subsequence)DisplayItems per client.
271 //
272 void DisplayItemList::commitNewDisplayItems(GraphicsLayer* graphicsLayer)
273 {
274 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems",
275 "current_display_list_size", (int)m_currentPaintArtifact.displayItems(). size(),
276 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI tems);
277
278 if (RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled()) {
279 for (const auto& invalidation : m_invalidations)
280 graphicsLayer->setNeedsDisplayInRect(invalidation.rect, invalidation .invalidationReason);
281 m_invalidations.clear();
282 m_clientsCheckedPaintInvalidation.clear();
283 }
284
285 // These data structures are used during painting only.
286 ASSERT(m_scopeStack.isEmpty());
287 m_scopeStack.clear();
288 m_nextScope = 1;
289 ASSERT(!skippingCache());
290 #if ENABLE(ASSERT)
291 m_newDisplayItemIndicesByClient.clear();
292 m_clientsWithPaintOffsetInvalidations.clear();
293 #endif
294
295 if (m_currentPaintArtifact.isEmpty()) {
296 #if ENABLE(ASSERT)
297 for (const auto& item : m_newDisplayItems)
298 ASSERT(!item.isCached());
299 #endif
300 m_currentPaintArtifact.displayItems().swap(m_newDisplayItems);
301 m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChun ks();
302 m_validlyCachedClientsDirty = true;
303 m_numCachedItems = 0;
304 return;
305 }
306
307 updateValidlyCachedClientsIfNeeded();
308
309 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched
310 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched
311 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur es that when
312 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems
313 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time.
314 OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.display Items().begin());
315
316 // TODO(jbroman): Consider revisiting this heuristic.
317 DisplayItems updatedList(std::max(m_currentPaintArtifact.displayItems().used CapacityInBytes(), m_newDisplayItems.usedCapacityInBytes()));
318 Vector<PaintChunk> updatedPaintChunks;
319 DisplayItems::iterator currentIt = m_currentPaintArtifact.displayItems().beg in();
320 DisplayItems::iterator currentEnd = m_currentPaintArtifact.displayItems().en d();
321 for (DisplayItems::iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) {
322 const DisplayItem& newDisplayItem = *newIt;
323 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId();
324 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt emId.type;
325
326 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche s(*currentIt);
327
328 if (newDisplayItemHasCachedType) {
329 ASSERT(newDisplayItem.isCached());
330 ASSERT(clientCacheIsValid(newDisplayItem.client()) || (RuntimeEnable dFeatures::slimmingPaintOffsetCachingEnabled() && !paintOffsetWasInvalidated(new DisplayItem.client())));
331 if (!isSynchronized) {
332 currentIt = findOutOfOrderCachedItem(newDisplayItemId, outOfOrde rIndexContext);
333
334 if (currentIt == currentEnd) {
335 #ifndef NDEBUG
336 showDebugData();
337 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD isplayItem.asDebugString().utf8().data());
338 #endif
339 ASSERT_NOT_REACHED();
340 // We did not find the cached display item. This should be i mpossible, but may occur if there is a bug
341 // in the system, such as under-invalidation, incorrect cach e checking or duplicate display ids.
342 // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list.
343 continue;
344 }
345 }
346 #if ENABLE(ASSERT)
347 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) {
348 DisplayItems::iterator temp = currentIt;
349 checkUnderInvalidation(newIt, temp);
350 }
351 #endif
352 if (newDisplayItem.isCachedDrawing()) {
353 updatedList.appendByMoving(*currentIt);
354 ++currentIt;
355 } else {
356 ASSERT(newDisplayItem.isCachedSubsequence());
357 copyCachedSubsequence(currentIt, updatedList);
358 ASSERT(updatedList.last().isEndSubsequence());
359 }
360 } else {
361 ASSERT(!newDisplayItem.isDrawing()
362 || newDisplayItem.skippedCache()
363 || !clientCacheIsValid(newDisplayItem.client())
364 || (RuntimeEnabledFeatures::slimmingPaintOffsetCachingEnabled() && paintOffsetWasInvalidated(newDisplayItem.client())));
365
366 updatedList.appendByMoving(*newIt);
367
368 if (isSynchronized)
369 ++currentIt;
370 }
371 // Items before currentIt should have been copied so we don't need to in dex them.
372 if (currentIt - outOfOrderIndexContext.nextItemToIndex > 0)
373 outOfOrderIndexContext.nextItemToIndex = currentIt;
374 }
375
376 #if ENABLE(ASSERT)
377 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
378 checkNoRemainingCachedDisplayItems();
379 #endif // ENABLE(ASSERT)
380
381
382 // TODO(jbroman): When subsequence caching applies to SPv2, we'll need to
383 // merge the paint chunks as well.
384 m_currentPaintArtifact.displayItems().swap(updatedList);
385 m_currentPaintArtifact.paintChunks() = m_newPaintChunks.releasePaintChunks() ;
386
387 m_newDisplayItems.clear();
388 m_validlyCachedClientsDirty = true;
389 m_numCachedItems = 0;
390 }
391
392 size_t DisplayItemList::approximateUnsharedMemoryUsage() const
393 {
394 size_t memoryUsage = sizeof(*this);
395
396 // Memory outside this class due to m_currentPaintArtifact.
397 memoryUsage += m_currentPaintArtifact.approximateUnsharedMemoryUsage() - siz eof(m_currentPaintArtifact);
398
399 // TODO(jbroman): If display items begin to have significant external memory
400 // usage that's not shared with the embedder, we should account for it here.
401 //
402 // External objects, shared with the embedder, such as SkPicture, should be
403 // excluded to avoid double counting. It is the embedder's responsibility to
404 // count such objects.
405 //
406 // At time of writing, the only known case of unshared external memory was
407 // the rounded clips vector in ClipDisplayItem, which is not expected to
408 // contribute significantly to memory usage.
409
410 // Memory outside this class due to m_newDisplayItems.
411 ASSERT(m_newDisplayItems.isEmpty());
412 memoryUsage += m_newDisplayItems.memoryUsageInBytes();
413
414 return memoryUsage;
415 }
416
417 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const
418 {
419 if (!m_validlyCachedClientsDirty)
420 return;
421
422 m_validlyCachedClients.clear();
423 m_validlyCachedClientsDirty = false;
424
425 DisplayItemClient lastAddedClient = nullptr;
426 for (const DisplayItem& displayItem : m_currentPaintArtifact.displayItems()) {
427 if (displayItem.client() == lastAddedClient)
428 continue;
429 if (displayItem.isCacheable()) {
430 lastAddedClient = displayItem.client();
431 m_validlyCachedClients.add(lastAddedClient);
432 }
433 }
434 }
435
436 #if ENABLE(ASSERT)
437
438 void DisplayItemList::checkUnderInvalidation(DisplayItems::iterator& newIt, Disp layItems::iterator& currentIt)
439 {
440 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
441 ASSERT(newIt->isCached());
442
443 // When under-invalidation-checking is enabled, the forced painting is follo wing the cached display item.
444 DisplayItem::Type nextItemType = DisplayItem::nonCachedType(newIt->type());
445 ++newIt;
446 ASSERT(newIt->type() == nextItemType);
447
448 if (newIt->isDrawing()) {
449 checkCachedDisplayItemIsUnchanged("", *newIt, *currentIt);
450 return;
451 }
452
453 ASSERT(newIt->isSubsequence());
454
455 #ifndef NDEBUG
456 CString messagePrefix = String::format("(In CachedSubsequence of %s)", newIt ->clientDebugString().utf8().data()).utf8();
457 #else
458 CString messagePrefix = "(In CachedSubsequence)";
459 #endif
460
461 DisplayItem::Id endSubsequenceId(newIt->client(), DisplayItem::subsequenceTy peToEndSubsequenceType(newIt->type()), 0);
462 while (true) {
463 ASSERT(newIt != m_newDisplayItems.end());
464 if (newIt->isCached())
465 checkUnderInvalidation(newIt, currentIt);
466 else
467 checkCachedDisplayItemIsUnchanged(messagePrefix.data(), *newIt, *cur rentIt);
468
469 if (endSubsequenceId.matches(*newIt))
470 break;
471
472 ++newIt;
473 ++currentIt;
474 }
475 }
476
477 static void showUnderInvalidationError(const char* messagePrefix, const char* re ason, const DisplayItem* newItem, const DisplayItem* oldItem)
478 {
479 #ifndef NDEBUG
480 WTFLogAlways("%s %s:\nNew display item: %s\nOld display item: %s\nSee http:/ /crbug.com/450725.", messagePrefix, reason,
481 newItem ? newItem->asDebugString().utf8().data() : "None",
482 oldItem ? oldItem->asDebugString().utf8().data() : "None");
483 #else
484 WTFLogAlways("%s %s. Run debug build to get more details\nSee http://crbug.c om/450725.", messagePrefix, reason);
485 #endif // NDEBUG
486 }
487
488 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const char* messagePrefi x, const DisplayItem& newItem, const DisplayItem& oldItem)
489 {
490 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
491 ASSERT(!newItem.isCached());
492 ASSERT(!oldItem.isCached());
493
494 if (newItem.skippedCache()) {
495 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: sk ipped-cache in cached subsequence", &newItem, &oldItem);
496 ASSERT_NOT_REACHED();
497 }
498
499 if (newItem.isCacheable() && !m_validlyCachedClients.contains(newItem.client ())) {
500 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: in validated in cached subsequence", &newItem, &oldItem);
501 ASSERT_NOT_REACHED();
502 }
503
504 if (newItem.equals(oldItem))
505 return;
506
507 showUnderInvalidationError(messagePrefix, "ERROR: under-invalidation: displa y item changed", &newItem, &oldItem);
508
509 #ifndef NDEBUG
510 if (newItem.isDrawing()) {
511 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayIte m&>(newItem).picture();
512 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayIte m&>(oldItem).picture();
513 String oldPictureDebugString = oldPicture ? pictureAsDebugString(oldPict ure.get()) : "None";
514 String newPictureDebugString = newPicture ? pictureAsDebugString(newPict ure.get()) : "None";
515 WTFLogAlways("old picture:\n%s\n", oldPictureDebugString.utf8().data());
516 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data());
517 }
518 #endif // NDEBUG
519
520 ASSERT_NOT_REACHED();
521 }
522
523 void DisplayItemList::checkNoRemainingCachedDisplayItems()
524 {
525 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
526
527 for (const auto& displayItem : m_currentPaintArtifact.displayItems()) {
528 if (!displayItem.isValid() || !displayItem.isCacheable() || !clientCache IsValid(displayItem.client()))
529 continue;
530 showUnderInvalidationError("", "May be under-invalidation: no new displa y item", nullptr, &displayItem);
531 }
532 }
533
534 #endif // ENABLE(ASSERT)
535
536 #ifndef NDEBUG
537
538 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const
539 {
540 StringBuilder stringBuilder;
541 size_t i = 0;
542 for (auto it = list.begin(); it != list.end(); ++it, ++i) {
543 const DisplayItem& displayItem = *it;
544 if (i)
545 stringBuilder.append(",\n");
546 stringBuilder.append(String::format("{index: %d, ", (int)i));
547 displayItem.dumpPropertiesAsDebugString(stringBuilder);
548 if (displayItem.isValid()) {
549 stringBuilder.append(", cacheIsValid: ");
550 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru e" : "false");
551 }
552 stringBuilder.append('}');
553 }
554 return stringBuilder.toString();
555 }
556
557 void DisplayItemList::showDebugData() const
558 {
559 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu rrentPaintArtifact.displayItems()).utf8().data());
560 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis playItems).utf8().data());
561 }
562
563 #endif // ifndef NDEBUG
564
565 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698