OLD | NEW |
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/NotImplemented.h" | 7 #include "platform/NotImplemented.h" |
8 #include "platform/TraceEvent.h" | 8 #include "platform/TraceEvent.h" |
9 #include "platform/graphics/GraphicsLayer.h" | 9 #include "platform/graphics/GraphicsLayer.h" |
10 #include "platform/graphics/paint/DrawingDisplayItem.h" | 10 #include "platform/graphics/paint/DrawingDisplayItem.h" |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 OutOfOrderIndexContext(DisplayItemList::iterator begin) : nextItemToIndex(be
gin) { } | 216 OutOfOrderIndexContext(DisplayItemList::iterator begin) : nextItemToIndex(be
gin) { } |
217 | 217 |
218 DisplayItemList::iterator nextItemToIndex; | 218 DisplayItemList::iterator nextItemToIndex; |
219 DisplayItemIndicesByClientMap displayItemIndicesByClient; | 219 DisplayItemIndicesByClientMap displayItemIndicesByClient; |
220 }; | 220 }; |
221 | 221 |
222 DisplayItemList::iterator PaintController::findOutOfOrderCachedItem(const Displa
yItem::Id& id, OutOfOrderIndexContext& context) | 222 DisplayItemList::iterator PaintController::findOutOfOrderCachedItem(const Displa
yItem::Id& id, OutOfOrderIndexContext& context) |
223 { | 223 { |
224 ASSERT(clientCacheIsValid(id.client)); | 224 ASSERT(clientCacheIsValid(id.client)); |
225 | 225 |
226 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentPaintArtifact.displayItemList()); | 226 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentPaintArtifact.getDisplayItemList()); |
227 if (foundIndex != kNotFound) | 227 if (foundIndex != kNotFound) |
228 return m_currentPaintArtifact.displayItemList().begin() + foundIndex; | 228 return m_currentPaintArtifact.getDisplayItemList().begin() + foundIndex; |
229 | 229 |
230 return findOutOfOrderCachedItemForward(id, context); | 230 return findOutOfOrderCachedItemForward(id, context); |
231 } | 231 } |
232 | 232 |
233 // Find forward for the item and index all skipped indexable items. | 233 // Find forward for the item and index all skipped indexable items. |
234 DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const
DisplayItem::Id& id, OutOfOrderIndexContext& context) | 234 DisplayItemList::iterator PaintController::findOutOfOrderCachedItemForward(const
DisplayItem::Id& id, OutOfOrderIndexContext& context) |
235 { | 235 { |
236 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.displayItemLis
t().end(); | 236 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItem
List().end(); |
237 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { | 237 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { |
238 const DisplayItem& item = *context.nextItemToIndex; | 238 const DisplayItem& item = *context.nextItemToIndex; |
239 ASSERT(item.hasValidClient()); | 239 ASSERT(item.hasValidClient()); |
240 if (item.isCacheable() && clientCacheIsValid(item.client())) { | 240 if (item.isCacheable() && clientCacheIsValid(item.client())) { |
241 if (id.matches(item)) | 241 if (id.matches(item)) |
242 return context.nextItemToIndex++; | 242 return context.nextItemToIndex++; |
243 | 243 |
244 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain
tArtifact.displayItemList().begin(), context.displayItemIndicesByClient); | 244 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentPain
tArtifact.getDisplayItemList().begin(), context.displayItemIndicesByClient); |
245 } | 245 } |
246 } | 246 } |
247 return currentEnd; | 247 return currentEnd; |
248 } | 248 } |
249 | 249 |
250 void PaintController::copyCachedSubsequence(const DisplayItemList& currentList,
DisplayItemList::iterator& currentIt, DisplayItemList& updatedList) | 250 void PaintController::copyCachedSubsequence(const DisplayItemList& currentList,
DisplayItemList::iterator& currentIt, DisplayItemList& updatedList) |
251 { | 251 { |
252 ASSERT(currentIt->getType() == DisplayItem::Subsequence); | 252 ASSERT(currentIt->getType() == DisplayItem::Subsequence); |
253 ASSERT(!currentIt->scope()); | 253 ASSERT(!currentIt->scope()); |
254 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq
uence, 0); | 254 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq
uence, 0); |
255 do { | 255 do { |
256 // We should always find the EndSubsequence display item. | 256 // We should always find the EndSubsequence display item. |
257 ASSERT(currentIt != m_currentPaintArtifact.displayItemList().end()); | 257 ASSERT(currentIt != m_currentPaintArtifact.getDisplayItemList().end()); |
258 ASSERT(currentIt->hasValidClient()); | 258 ASSERT(currentIt->hasValidClient()); |
259 updatedList.appendByMoving(*currentIt, currentList.visualRect(currentIt
- m_currentPaintArtifact.displayItemList().begin())); | 259 updatedList.appendByMoving(*currentIt, currentList.visualRect(currentIt
- m_currentPaintArtifact.getDisplayItemList().begin())); |
260 ++currentIt; | 260 ++currentIt; |
261 } while (!endSubsequenceId.matches(updatedList.last())); | 261 } while (!endSubsequenceId.matches(updatedList.last())); |
262 } | 262 } |
263 | 263 |
264 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) | 264 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
ject) |
265 { | 265 { |
266 #if ENABLE(ASSERT) | 266 #if ENABLE(ASSERT) |
267 m_newDisplayItemList.assertDisplayItemClientsAreAlive(); | 267 m_newDisplayItemList.assertDisplayItemClientsAreAlive(); |
268 #endif | 268 #endif |
269 commitNewDisplayItemsInternal(offsetFromLayoutObject); | 269 commitNewDisplayItemsInternal(offsetFromLayoutObject); |
270 #if ENABLE(ASSERT) | 270 #if ENABLE(ASSERT) |
271 m_currentPaintArtifact.displayItemList().assertDisplayItemClientsAreAlive(); | 271 m_currentPaintArtifact.getDisplayItemList().assertDisplayItemClientsAreAlive
(); |
272 #endif | 272 #endif |
273 } | 273 } |
274 | 274 |
275 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) | 275 static IntRect visualRectForDisplayItem(const DisplayItem& displayItem, const La
youtSize& offsetFromLayoutObject) |
276 { | 276 { |
277 LayoutRect visualRect = displayItem.client().visualRect(); | 277 LayoutRect visualRect = displayItem.client().visualRect(); |
278 visualRect.move(-offsetFromLayoutObject); | 278 visualRect.move(-offsetFromLayoutObject); |
279 return enclosingIntRect(visualRect); | 279 return enclosingIntRect(visualRect); |
280 } | 280 } |
281 | 281 |
282 // Update the existing display items by removing invalidated entries, updating | 282 // Update the existing display items by removing invalidated entries, updating |
283 // repainted ones, and appending new items. | 283 // repainted ones, and appending new items. |
284 // - For cached drawing display item, copy the corresponding cached DrawingDispl
ayItem; | 284 // - For cached drawing display item, copy the corresponding cached DrawingDispl
ayItem; |
285 // - For cached subsequence display item, copy the cached display items between
the | 285 // - For cached subsequence display item, copy the cached display items between
the |
286 // corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.); | 286 // corresponding SubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.); |
287 // - Otherwise, copy the new display item. | 287 // - Otherwise, copy the new display item. |
288 // | 288 // |
289 // The algorithm is O(|m_currentDisplayItemList| + |m_newDisplayItemList|). | 289 // The algorithm is O(|m_currentDisplayItemList| + |m_newDisplayItemList|). |
290 // Coefficients are related to the ratio of out-of-order CachedDisplayItems | 290 // Coefficients are related to the ratio of out-of-order CachedDisplayItems |
291 // and the average number of (Drawing|Subsequence)DisplayItems per client. | 291 // and the average number of (Drawing|Subsequence)DisplayItems per client. |
292 // | 292 // |
293 void PaintController::commitNewDisplayItemsInternal(const LayoutSize& offsetFrom
LayoutObject) | 293 void PaintController::commitNewDisplayItemsInternal(const LayoutSize& offsetFrom
LayoutObject) |
294 { | 294 { |
295 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", | 295 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", |
296 "current_display_list_size", (int)m_currentPaintArtifact.displayItemList
().size(), | 296 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL
ist().size(), |
297 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); | 297 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach
edNewItems); |
298 m_numCachedNewItems = 0; | 298 m_numCachedNewItems = 0; |
299 | 299 |
300 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 300 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
301 m_clientsCheckedPaintInvalidation.clear(); | 301 m_clientsCheckedPaintInvalidation.clear(); |
302 | 302 |
303 // These data structures are used during painting only. | 303 // These data structures are used during painting only. |
304 ASSERT(m_scopeStack.isEmpty()); | 304 ASSERT(m_scopeStack.isEmpty()); |
305 m_scopeStack.clear(); | 305 m_scopeStack.clear(); |
306 m_nextScope = 1; | 306 m_nextScope = 1; |
(...skipping 18 matching lines...) Expand all Loading... |
325 return; | 325 return; |
326 } | 326 } |
327 | 327 |
328 updateValidlyCachedClientsIfNeeded(); | 328 updateValidlyCachedClientsIfNeeded(); |
329 | 329 |
330 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that
have not been matched | 330 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that
have not been matched |
331 // by CachedDisplayItems during synchronized matching. The indexed items wil
l be matched | 331 // by CachedDisplayItems during synchronized matching. The indexed items wil
l be matched |
332 // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This en
sures that when | 332 // by later out-of-order CachedDisplayItems in m_newDisplayItemList. This en
sures that when |
333 // out-of-order CachedDisplayItems occur, we only traverse at most once over
m_currentDisplayItems | 333 // out-of-order CachedDisplayItems occur, we only traverse at most once over
m_currentDisplayItems |
334 // looking for potential matches. Thus we can ensure that the algorithm runs
in linear time. | 334 // looking for potential matches. Thus we can ensure that the algorithm runs
in linear time. |
335 OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.display
ItemList().begin()); | 335 OutOfOrderIndexContext outOfOrderIndexContext(m_currentPaintArtifact.getDisp
layItemList().begin()); |
336 | 336 |
337 // TODO(jbroman): Consider revisiting this heuristic. | 337 // TODO(jbroman): Consider revisiting this heuristic. |
338 DisplayItemList updatedList(std::max(m_currentPaintArtifact.displayItemList(
).usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes())); | 338 DisplayItemList updatedList(std::max(m_currentPaintArtifact.getDisplayItemLi
st().usedCapacityInBytes(), m_newDisplayItemList.usedCapacityInBytes())); |
339 Vector<PaintChunk> updatedPaintChunks; | 339 Vector<PaintChunk> updatedPaintChunks; |
340 DisplayItemList::iterator currentIt = m_currentPaintArtifact.displayItemList
().begin(); | 340 DisplayItemList::iterator currentIt = m_currentPaintArtifact.getDisplayItemL
ist().begin(); |
341 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.displayItemLis
t().end(); | 341 DisplayItemList::iterator currentEnd = m_currentPaintArtifact.getDisplayItem
List().end(); |
342 for (DisplayItemList::iterator newIt = m_newDisplayItemList.begin(); newIt !
= m_newDisplayItemList.end(); ++newIt) { | 342 for (DisplayItemList::iterator newIt = m_newDisplayItemList.begin(); newIt !
= m_newDisplayItemList.end(); ++newIt) { |
343 const DisplayItem& newDisplayItem = *newIt; | 343 const DisplayItem& newDisplayItem = *newIt; |
344 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); | 344 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); |
345 bool newDisplayItemHasCachedType = newDisplayItem.getType() != newDispla
yItemId.type; | 345 bool newDisplayItemHasCachedType = newDisplayItem.getType() != newDispla
yItemId.type; |
346 | 346 |
347 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche
s(*currentIt); | 347 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche
s(*currentIt); |
348 | 348 |
349 if (newDisplayItemHasCachedType) { | 349 if (newDisplayItemHasCachedType) { |
350 ASSERT(newDisplayItem.isCached()); | 350 ASSERT(newDisplayItem.isCached()); |
351 ASSERT(clientCacheIsValid(newDisplayItem.client()) || (RuntimeEnable
dFeatures::slimmingPaintInvalidationEnabled() && !paintOffsetWasInvalidated(newD
isplayItem.client()))); | 351 ASSERT(clientCacheIsValid(newDisplayItem.client()) || (RuntimeEnable
dFeatures::slimmingPaintInvalidationEnabled() && !paintOffsetWasInvalidated(newD
isplayItem.client()))); |
(...skipping 12 matching lines...) Expand all Loading... |
364 continue; | 364 continue; |
365 } | 365 } |
366 } | 366 } |
367 #if ENABLE(ASSERT) | 367 #if ENABLE(ASSERT) |
368 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) { | 368 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) { |
369 DisplayItemList::iterator temp = currentIt; | 369 DisplayItemList::iterator temp = currentIt; |
370 checkUnderInvalidation(newIt, temp); | 370 checkUnderInvalidation(newIt, temp); |
371 } | 371 } |
372 #endif | 372 #endif |
373 if (newDisplayItem.isCachedDrawing()) { | 373 if (newDisplayItem.isCachedDrawing()) { |
374 updatedList.appendByMoving(*currentIt, m_currentPaintArtifact.di
splayItemList().visualRect(currentIt - m_currentPaintArtifact.displayItemList().
begin())); | 374 updatedList.appendByMoving(*currentIt, m_currentPaintArtifact.ge
tDisplayItemList().visualRect(currentIt - m_currentPaintArtifact.getDisplayItemL
ist().begin())); |
375 ++currentIt; | 375 ++currentIt; |
376 } else { | 376 } else { |
377 ASSERT(newDisplayItem.getType() == DisplayItem::CachedSubsequenc
e); | 377 ASSERT(newDisplayItem.getType() == DisplayItem::CachedSubsequenc
e); |
378 copyCachedSubsequence(m_currentPaintArtifact.displayItemList(),
currentIt, updatedList); | 378 copyCachedSubsequence(m_currentPaintArtifact.getDisplayItemList(
), currentIt, updatedList); |
379 ASSERT(updatedList.last().getType() == DisplayItem::EndSubsequen
ce); | 379 ASSERT(updatedList.last().getType() == DisplayItem::EndSubsequen
ce); |
380 } | 380 } |
381 } else { | 381 } else { |
382 ASSERT(!newDisplayItem.isDrawing() | 382 ASSERT(!newDisplayItem.isDrawing() |
383 || newDisplayItem.skippedCache() | 383 || newDisplayItem.skippedCache() |
384 || !clientCacheIsValid(newDisplayItem.client()) | 384 || !clientCacheIsValid(newDisplayItem.client()) |
385 || (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() &
& paintOffsetWasInvalidated(newDisplayItem.client()))); | 385 || (RuntimeEnabledFeatures::slimmingPaintInvalidationEnabled() &
& paintOffsetWasInvalidated(newDisplayItem.client()))); |
386 | 386 |
387 updatedList.appendByMoving(*newIt, visualRectForDisplayItem(*newIt,
offsetFromLayoutObject)); | 387 updatedList.appendByMoving(*newIt, visualRectForDisplayItem(*newIt,
offsetFromLayoutObject)); |
388 | 388 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 | 434 |
435 void PaintController::updateValidlyCachedClientsIfNeeded() const | 435 void PaintController::updateValidlyCachedClientsIfNeeded() const |
436 { | 436 { |
437 if (!m_validlyCachedClientsDirty) | 437 if (!m_validlyCachedClientsDirty) |
438 return; | 438 return; |
439 | 439 |
440 m_validlyCachedClients.clear(); | 440 m_validlyCachedClients.clear(); |
441 m_validlyCachedClientsDirty = false; | 441 m_validlyCachedClientsDirty = false; |
442 | 442 |
443 const DisplayItemClient* lastAddedClient = nullptr; | 443 const DisplayItemClient* lastAddedClient = nullptr; |
444 for (const DisplayItem& displayItem : m_currentPaintArtifact.displayItemList
()) { | 444 for (const DisplayItem& displayItem : m_currentPaintArtifact.getDisplayItemL
ist()) { |
445 if (&displayItem.client() == lastAddedClient) | 445 if (&displayItem.client() == lastAddedClient) |
446 continue; | 446 continue; |
447 if (displayItem.isCacheable()) { | 447 if (displayItem.isCacheable()) { |
448 lastAddedClient = &displayItem.client(); | 448 lastAddedClient = &displayItem.client(); |
449 m_validlyCachedClients.add(lastAddedClient); | 449 m_validlyCachedClients.add(lastAddedClient); |
450 } | 450 } |
451 } | 451 } |
452 } | 452 } |
453 | 453 |
454 #if ENABLE(ASSERT) | 454 #if ENABLE(ASSERT) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 } | 535 } |
536 #endif // NDEBUG | 536 #endif // NDEBUG |
537 | 537 |
538 ASSERT_NOT_REACHED(); | 538 ASSERT_NOT_REACHED(); |
539 } | 539 } |
540 | 540 |
541 void PaintController::checkNoRemainingCachedDisplayItems() | 541 void PaintController::checkNoRemainingCachedDisplayItems() |
542 { | 542 { |
543 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 543 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
544 | 544 |
545 for (const auto& displayItem : m_currentPaintArtifact.displayItemList()) { | 545 for (const auto& displayItem : m_currentPaintArtifact.getDisplayItemList())
{ |
546 if (!displayItem.hasValidClient() || !displayItem.isCacheable() || !clie
ntCacheIsValid(displayItem.client())) | 546 if (!displayItem.hasValidClient() || !displayItem.isCacheable() || !clie
ntCacheIsValid(displayItem.client())) |
547 continue; | 547 continue; |
548 showUnderInvalidationError("", "May be under-invalidation: no new displa
y item", nullptr, &displayItem); | 548 showUnderInvalidationError("", "May be under-invalidation: no new displa
y item", nullptr, &displayItem); |
549 } | 549 } |
550 } | 550 } |
551 | 551 |
552 #endif // ENABLE(ASSERT) | 552 #endif // ENABLE(ASSERT) |
553 | 553 |
554 #ifndef NDEBUG | 554 #ifndef NDEBUG |
555 | 555 |
556 WTF::String PaintController::displayItemListAsDebugString(const DisplayItemList&
list) const | 556 WTF::String PaintController::displayItemListAsDebugString(const DisplayItemList&
list) const |
557 { | 557 { |
558 StringBuilder stringBuilder; | 558 StringBuilder stringBuilder; |
559 size_t i = 0; | 559 size_t i = 0; |
560 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 560 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
561 const DisplayItem& displayItem = *it; | 561 const DisplayItem& displayItem = *it; |
562 if (i) | 562 if (i) |
563 stringBuilder.append(",\n"); | 563 stringBuilder.append(",\n"); |
564 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 564 stringBuilder.append(String::format("{index: %d, ", (int)i)); |
565 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 565 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
566 stringBuilder.append(", cacheIsValid: "); | 566 stringBuilder.append(", cacheIsValid: "); |
567 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" :
"false"); | 567 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" :
"false"); |
568 stringBuilder.append('}'); | 568 stringBuilder.append('}'); |
569 } | 569 } |
570 return stringBuilder.toString(); | 570 return stringBuilder.toString(); |
571 } | 571 } |
572 | 572 |
573 void PaintController::showDebugData() const | 573 void PaintController::showDebugData() const |
574 { | 574 { |
575 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.displayItemList()).utf8().data()); | 575 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
576 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()); |
577 } | 577 } |
578 | 578 |
579 #endif // ifndef NDEBUG | 579 #endif // ifndef NDEBUG |
580 | 580 |
581 } // namespace blink | 581 } // namespace blink |
OLD | NEW |