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/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 #include "third_party/skia/include/core/SkPictureAnalyzer.h" | 10 #include "third_party/skia/include/core/SkPictureAnalyzer.h" |
11 #include "wtf/AutoReset.h" | |
11 #include "wtf/text/StringBuilder.h" | 12 #include "wtf/text/StringBuilder.h" |
12 | 13 |
13 #ifndef NDEBUG | 14 #ifndef NDEBUG |
14 #include "platform/graphics/LoggingCanvas.h" | 15 #include "platform/graphics/LoggingCanvas.h" |
15 #include <stdio.h> | 16 #include <stdio.h> |
16 #endif | 17 #endif |
17 | 18 |
18 namespace blink { | 19 namespace blink { |
19 | 20 |
20 const PaintArtifact& PaintController::paintArtifact() const | 21 const PaintArtifact& PaintController::paintArtifact() const |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
188 } | 189 } |
189 } | 190 } |
190 #endif | 191 #endif |
191 | 192 |
192 if (isSkippingCache()) { | 193 if (isSkippingCache()) { |
193 DCHECK(newItemSource == NewPainting); | 194 DCHECK(newItemSource == NewPainting); |
194 displayItem.setSkippedCache(); | 195 displayItem.setSkippedCache(); |
195 } | 196 } |
196 | 197 |
197 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 198 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
198 if (newItemSource != FromCachedSubsequence) | |
199 m_currentChunkIsFromCachedSubsequence = false; | |
200 | |
201 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); | 199 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); |
202 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { | 200 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { |
203 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); | 201 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); |
204 if (lastChunkIndex != kNotFound) | 202 if (lastChunkIndex != kNotFound) |
205 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex)); | 203 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex)); |
206 m_currentChunkIsFromCachedSubsequence = true; | |
207 } | 204 } |
208 } | 205 } |
209 | 206 |
210 #if DCHECK_IS_ON() | 207 #if DCHECK_IS_ON() |
211 // Verify noop begin/end pairs have been removed. | 208 // Verify noop begin/end pairs have been removed. |
212 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { | 209 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { |
213 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; | 210 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; |
214 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent()) | 211 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent()) |
215 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); | 212 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); |
216 } | 213 } |
217 | 214 |
218 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); | 215 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); |
219 if (index != kNotFound) { | 216 if (index != kNotFound) { |
220 #ifndef NDEBUG | 217 #ifndef NDEBUG |
221 showDebugData(); | 218 showDebugData(); |
222 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", | 219 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% zu)\n", |
223 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); | 220 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), index); |
224 #endif | 221 #endif |
225 NOTREACHED(); | 222 NOTREACHED(); |
226 } | 223 } |
227 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); | 224 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); |
228 | 225 |
229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 226 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
230 checkUnderInvalidation(); | 227 checkUnderInvalidation(); |
231 #endif // DCHECK_IS_ON() | 228 #endif // DCHECK_IS_ON() |
232 } | 229 } |
233 | 230 |
(...skipping 27 matching lines...) Expand all Loading... | |
261 | 258 |
262 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) | 259 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) |
263 { | 260 { |
264 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); | 261 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); |
265 if (it == displayItemIndicesByClient.end()) | 262 if (it == displayItemIndicesByClient.end()) |
266 return kNotFound; | 263 return kNotFound; |
267 | 264 |
268 const Vector<size_t>& indices = it->value; | 265 const Vector<size_t>& indices = it->value; |
269 for (size_t index : indices) { | 266 for (size_t index : indices) { |
270 const DisplayItem& existingItem = list[index]; | 267 const DisplayItem& existingItem = list[index]; |
271 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); | 268 if (existingItem.hasBeenMoved()) |
269 continue; | |
270 DCHECK(existingItem.client() == id.client); | |
272 if (id == existingItem.getId()) | 271 if (id == existingItem.getId()) |
273 return index; | 272 return index; |
274 } | 273 } |
275 | 274 |
276 return kNotFound; | 275 return kNotFound; |
277 } | 276 } |
278 | 277 |
279 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) | 278 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) |
280 { | 279 { |
281 if (!displayItem.isCacheable()) | 280 if (!displayItem.isCacheable()) |
282 return; | 281 return; |
283 | 282 |
284 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client()); | 283 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client()); |
285 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? | 284 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
286 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; | 285 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; |
287 indices.append(index); | 286 indices.append(index); |
288 } | 287 } |
289 | 288 |
290 size_t PaintController::findCachedItem(const DisplayItem::Id& id) | 289 size_t PaintController::findCachedItem(const DisplayItem::Id& id) |
291 { | 290 { |
292 DCHECK(clientCacheIsValid(id.client)); | 291 DCHECK(clientCacheIsValid(id.client)); |
293 | 292 |
294 // Try to find the item sequentially first. This is fast if the current list and the new list are in | 293 // Try to find the item sequentially first. This is fast if the current list and the new list are in |
295 // the same order around the new item. If found, we don't need to update and lookup the index. | 294 // the same order around the new item. If found, we don't need to update and lookup the index. |
296 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { | 295 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { |
297 // We encounter an item that has already been copied which indicates we can't do sequential matching. | 296 // We encounter an item that has already been copied which indicates we can't do sequential matching. |
298 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; | 297 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; |
299 if (!item.hasValidClient()) | 298 if (item.hasBeenMoved()) |
300 break; | 299 break; |
301 if (id == item.getId()) { | 300 if (id == item.getId()) { |
302 #if DCHECK_IS_ON() | 301 #if DCHECK_IS_ON() |
303 ++m_numSequentialMatches; | 302 ++m_numSequentialMatches; |
304 #endif | 303 #endif |
305 return i; | 304 return i; |
306 } | 305 } |
307 // We encounter a different cacheable item which also indicates we can't do sequential matching. | 306 // We encounter a different cacheable item which also indicates we can't do sequential matching. |
308 if (item.isCacheable()) | 307 if (item.isCacheable()) |
309 break; | 308 break; |
310 } | 309 } |
311 | 310 |
312 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m _currentPaintArtifact.getDisplayItemList()); | 311 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m _currentPaintArtifact.getDisplayItemList()); |
313 if (foundIndex != kNotFound) { | 312 if (foundIndex != kNotFound) { |
314 #if DCHECK_IS_ON() | 313 #if DCHECK_IS_ON() |
315 ++m_numOutOfOrderMatches; | 314 ++m_numOutOfOrderMatches; |
316 #endif | 315 #endif |
317 return foundIndex; | 316 return foundIndex; |
318 } | 317 } |
319 | 318 |
320 return findOutOfOrderCachedItemForward(id); | 319 return findOutOfOrderCachedItemForward(id); |
321 } | 320 } |
322 | 321 |
323 // Find forward for the item and index all skipped indexable items. | 322 // Find forward for the item and index all skipped indexable items. |
324 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i d) | 323 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i d) |
325 { | 324 { |
326 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { | 325 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { |
327 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; | 326 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; |
328 DCHECK(item.hasValidClient()); | 327 DCHECK(!item.hasBeenMoved()); |
329 if (id == item.getId()) { | 328 if (id == item.getId()) { |
330 #if DCHECK_IS_ON() | 329 #if DCHECK_IS_ON() |
331 ++m_numSequentialMatches; | 330 ++m_numSequentialMatches; |
332 #endif | 331 #endif |
333 return i; | 332 return i; |
334 } | 333 } |
335 if (item.isCacheable()) { | 334 if (item.isCacheable()) { |
336 #if DCHECK_IS_ON() | 335 #if DCHECK_IS_ON() |
337 ++m_numIndexedItems; | 336 ++m_numIndexedItems; |
338 #endif | 337 #endif |
(...skipping 11 matching lines...) Expand all Loading... | |
350 // In this case, the caller should fall back to repaint the display item. | 349 // In this case, the caller should fall back to repaint the display item. |
351 return kNotFound; | 350 return kNotFound; |
352 } | 351 } |
353 | 352 |
354 // Copies a cached subsequence from current list to the new list. On return, | 353 // Copies a cached subsequence from current list to the new list. On return, |
355 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub sequence. | 354 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub sequence. |
356 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence, | 355 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence, |
357 // but mark the begin and end of the subsequence for under-invalidation checking . | 356 // but mark the begin and end of the subsequence for under-invalidation checking . |
358 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) | 357 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) |
359 { | 358 { |
359 AutoReset<size_t> subsequenceBeginIndex(&m_currentCachedSubsequenceBeginInde xInNewList, m_newDisplayItemList.size()); | |
chrishtr
2016/09/06 22:14:12
What does changing to m_currentCachedSubsequenceBe
Xianzhu
2016/09/06 22:42:38
This replaces the original m_currentChunkIsFromCac
| |
360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex]; | 360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex]; |
361 #if DCHECK_IS_ON() | 361 #if DCHECK_IS_ON() |
362 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); | 362 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); |
363 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { | 363 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { |
364 DCHECK(!isCheckingUnderInvalidation()); | 364 DCHECK(!isCheckingUnderInvalidation()); |
365 m_underInvalidationCheckingBegin = cachedItemIndex; | 365 m_underInvalidationCheckingBegin = cachedItemIndex; |
366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")"; | 366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")"; |
367 } | 367 } |
368 #endif | 368 #endif |
369 | 369 |
370 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence); | 370 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence); |
371 Vector<PaintChunk>::const_iterator cachedChunk; | 371 Vector<PaintChunk>::const_iterator cachedChunk; |
372 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 372 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
373 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex); | 373 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex); |
374 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); | |
374 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); | 375 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); |
375 } else { | 376 } else { |
376 // This is to avoid compilation error about uninitialized variable on Wi ndows. | 377 // This is to avoid compilation error about uninitialized variable on Wi ndows. |
377 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); | 378 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); |
378 } | 379 } |
379 | 380 |
380 while (true) { | 381 while (true) { |
381 DCHECK(cachedItem->hasValidClient()); | 382 DCHECK(!cachedItem->hasBeenMoved()); |
382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 383 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
383 CHECK(cachedItem->client().isAlive()); | 384 CHECK(cachedItem->client().isAlive()); |
384 #endif | 385 #endif |
385 ++m_numCachedNewItems; | 386 ++m_numCachedNewItems; |
386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; | 387 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
387 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { | 388 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { |
388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { | 389 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { |
389 ++cachedChunk; | 390 ++cachedChunk; |
391 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end() ); | |
390 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); | 392 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); |
391 } | 393 } |
392 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); | 394 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); |
393 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 395 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
394 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); | 396 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
395 } | 397 } |
396 | 398 |
397 ++cachedItemIndex; | 399 ++cachedItemIndex; |
398 if (metEndSubsequence) | 400 if (metEndSubsequence) |
399 break; | 401 break; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
530 DCHECK(m_newDisplayItemList.isEmpty()); | 532 DCHECK(m_newDisplayItemList.isEmpty()); |
531 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, picture); | 533 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, picture); |
532 displayItem.setSkippedCache(); | 534 displayItem.setSkippedCache(); |
533 // TODO(wkorman): Only compute and append visual rect for drawings. | 535 // TODO(wkorman): Only compute and append visual rect for drawings. |
534 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); | 536 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); |
535 } | 537 } |
536 | 538 |
537 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) | 539 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) |
538 { | 540 { |
539 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 541 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
540 if (m_currentChunkIsFromCachedSubsequence) | 542 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) |
541 return; | 543 return; |
542 | 544 |
543 if (!newChunk.id) { | 545 if (!newChunk.id) { |
544 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); | 546 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); |
545 return; | 547 return; |
546 } | 548 } |
547 | 549 |
548 // Try to match old chunk sequentially first. | 550 // Try to match old chunk sequentially first. |
549 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); | 551 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); |
550 while (m_nextChunkToMatch < oldChunks.size()) { | 552 while (m_nextChunkToMatch < oldChunks.size()) { |
(...skipping 26 matching lines...) Expand all Loading... | |
577 } | 579 } |
578 | 580 |
579 // We reach here because the chunk is new. | 581 // We reach here because the chunk is new. |
580 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); | 582 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); |
581 } | 583 } |
582 | 584 |
583 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk) | 585 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk) |
584 { | 586 { |
585 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 587 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
586 | 588 |
587 // TODO(wangxianzhu): Support raster invalidation for reordered display item s without invalidating | |
588 // display item clients. Currently we invalidate display item clients ensuri ng raster invalidation. | |
589 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 589 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
590 // TODO(wangxianzhu): Optimize paint offset change. | 590 // TODO(wangxianzhu): Optimize paint offset change. |
591 | 591 |
592 // Maps from each client to the index of the first drawing-content display i tem of the client. | 592 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; |
593 HashMap<const DisplayItemClient*, size_t> oldChunkClients; | 593 size_t highestMovedToIndex = 0; |
594 for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) { | 594 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; ++ oldIndex) { |
595 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [i]; | 595 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [oldIndex]; |
596 // oldItem.hasValidClient() indicates that the item has not been copied as a cached item into | 596 const DisplayItemClient* clientToInvalidate = nullptr; |
597 // m_newDislayItemList, so the item either disappeared or changed, and n eeds raster invalidation. | 597 if (oldItem.hasBeenMoved()) { |
598 if (oldItem.hasValidClient() && oldItem.drawsContent() && oldChunkClient s.add(&oldItem.client(), i).isNewEntry) | 598 size_t movedToIndex = oldItem.movedToIndex(); |
599 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(i)); | 599 if (m_newDisplayItemList[movedToIndex].drawsContent()) { |
600 if (movedToIndex < newChunk.beginIndex || movedToIndex >= newChu nk.endIndex) { | |
601 // The item has been moved into another chunk, so need to in validate it in the old chunk. | |
602 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent(); | |
603 // And invalidate in the new chunk into which the item was m oved. | |
604 PaintChunk& movedToChunk = m_newPaintChunks.findChunkByDispl ayItemIndex(movedToIndex); | |
605 movedToChunk.rasterInvalidationRects.append(clientToInvalida te->visualRect()); | |
606 } else if (movedToIndex < highestMovedToIndex) { | |
607 // The item has been moved behind other cached items, so nee d to invalidate the area | |
608 // that is probably exposed by the item. | |
chrishtr
2016/09/06 22:14:12
"exposed by the item moving earlier"
Xianzhu
2016/09/06 22:42:38
Done.
| |
609 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent(); | |
610 } else { | |
611 highestMovedToIndex = movedToIndex; | |
612 } | |
613 } | |
614 } else if (oldItem.drawsContent()) { | |
615 clientToInvalidate = &oldItem.client(); | |
616 } | |
617 if (clientToInvalidate && invalidatedClientsInOldChunk.add(clientToInval idate).isNewEntry) { | |
618 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(oldIndex)); | |
619 } | |
600 } | 620 } |
601 | 621 |
602 HashSet<const DisplayItemClient*> newChunkClients; | 622 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; |
603 for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) { | 623 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; ++ newIndex) { |
604 const DisplayItem& newItem = m_newDisplayItemList[i]; | 624 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; |
605 if (newItem.drawsContent()) { | 625 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && i nvalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) |
606 if (!clientCacheIsValid(newItem.client())) { | 626 newChunk.rasterInvalidationRects.append(newItem.client().visualRect( )); |
607 if (newChunkClients.add(&newItem.client()).isNewEntry) | |
608 newChunk.rasterInvalidationRects.append(newItem.client().vis ualRect()); | |
609 } else { | |
610 // The cached item was moved from the old chunk which should not contain any item of the client now. | |
611 DCHECK(!oldChunkClients.contains(&newItem.client())); | |
612 } | |
613 } | |
614 } | 627 } |
615 } | 628 } |
616 | 629 |
617 #if DCHECK_IS_ON() | 630 #if DCHECK_IS_ON() |
618 | 631 |
619 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const | 632 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const |
620 { | 633 { |
621 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 634 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
622 #ifndef NDEBUG | 635 #ifndef NDEBUG |
623 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 636 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 #endif // DCHECK_IS_ON() | 699 #endif // DCHECK_IS_ON() |
687 | 700 |
688 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const | 701 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const |
689 { | 702 { |
690 StringBuilder stringBuilder; | 703 StringBuilder stringBuilder; |
691 size_t i = 0; | 704 size_t i = 0; |
692 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 705 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
693 const DisplayItem& displayItem = *it; | 706 const DisplayItem& displayItem = *it; |
694 if (i) | 707 if (i) |
695 stringBuilder.append(",\n"); | 708 stringBuilder.append(",\n"); |
696 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 709 stringBuilder.append(String::format("{index: %zu, ", i)); |
697 #ifndef NDEBUG | 710 #ifndef NDEBUG |
698 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 711 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
699 #else | 712 #else |
700 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); | 713 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); |
701 #endif | 714 #endif |
702 if (displayItem.hasValidClient()) { | 715 if (!displayItem.hasBeenMoved()) { |
703 do { | 716 do { |
704 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 717 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
705 if (!displayItem.client().isAlive()) { | 718 if (!displayItem.client().isAlive()) { |
706 stringBuilder.append(", clientIsAlive: false"); | 719 stringBuilder.append(", clientIsAlive: false"); |
707 break; | 720 break; |
708 } | 721 } |
709 #endif | 722 #endif |
710 stringBuilder.append(", cacheIsValid: "); | 723 stringBuilder.append(", cacheIsValid: "); |
711 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); | 724 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); |
712 } while (false); | 725 } while (false); |
713 } | 726 } |
714 if (list.hasVisualRect(i)) { | 727 if (list.hasVisualRect(i)) { |
715 IntRect visualRect = list.visualRect(i); | 728 IntRect visualRect = list.visualRect(i); |
716 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", | 729 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", |
717 visualRect.x(), visualRect.y(), | 730 visualRect.x(), visualRect.y(), |
718 visualRect.width(), visualRect.height())); | 731 visualRect.width(), visualRect.height())); |
719 } | 732 } |
720 stringBuilder.append('}'); | 733 stringBuilder.append('}'); |
721 } | 734 } |
722 return stringBuilder.toString(); | 735 return stringBuilder.toString(); |
723 } | 736 } |
724 | 737 |
725 void PaintController::showDebugData() const | 738 void PaintController::showDebugData() const |
726 { | 739 { |
727 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); | 740 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
728 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); | 741 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); |
729 } | 742 } |
730 | 743 |
731 } // namespace blink | 744 } // namespace blink |
OLD | NEW |