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

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

Issue 2307623002: [SPv2] Defer decision of raster invalidation after paint for changes z-index, transform, etc. (Closed)
Patch Set: Remove duplicated spv2 expectation entries Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
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 #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 21 matching lines...) Expand all
42 43
43 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); 44 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type));
44 if (cachedItem == kNotFound) { 45 if (cachedItem == kNotFound) {
45 NOTREACHED(); 46 NOTREACHED();
46 return false; 47 return false;
47 } 48 }
48 49
49 ++m_numCachedNewItems; 50 ++m_numCachedNewItems;
50 ensureNewDisplayItemListInitialCapacity(); 51 ensureNewDisplayItemListInitialCapacity();
51 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) 52 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
52 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac t.getDisplayItemList()[cachedItem]), FromCachedItem); 53 processNewItem(moveItemFromCurrentListToNewList(cachedItem));
53 54
54 m_nextItemToMatch = cachedItem + 1; 55 m_nextItemToMatch = cachedItem + 1;
55 // Items before m_nextItemToMatch have been copied so we don't need to index them. 56 // Items before m_nextItemToMatch have been copied so we don't need to index them.
56 if (m_nextItemToMatch > m_nextItemToIndex) 57 if (m_nextItemToMatch > m_nextItemToIndex)
57 m_nextItemToIndex = m_nextItemToMatch; 58 m_nextItemToIndex = m_nextItemToMatch;
58 59
59 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { 60 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
60 if (!isCheckingUnderInvalidation()) { 61 if (!isCheckingUnderInvalidation()) {
61 m_underInvalidationCheckingBegin = cachedItem; 62 m_underInvalidationCheckingBegin = cachedItem;
62 m_underInvalidationCheckingEnd = cachedItem + 1; 63 m_underInvalidationCheckingEnd = cachedItem + 1;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 m_newPaintChunks.decrementDisplayItemIndex(); 148 m_newPaintChunks.decrementDisplayItemIndex();
148 } 149 }
149 150
150 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) 151 const DisplayItem* PaintController::lastDisplayItem(unsigned offset)
151 { 152 {
152 if (offset < m_newDisplayItemList.size()) 153 if (offset < m_newDisplayItemList.size())
153 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; 154 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1];
154 return nullptr; 155 return nullptr;
155 } 156 }
156 157
157 void PaintController::processNewItem(DisplayItem& displayItem, NewItemSource new ItemSource) 158 void PaintController::processNewItem(DisplayItem& displayItem)
158 { 159 {
159 DCHECK(!m_constructionDisabled); 160 DCHECK(!m_constructionDisabled);
160 161
161 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 162 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
162 if (!isSkippingCache()) { 163 if (!isSkippingCache()) {
163 if (displayItem.isCacheable()) { 164 if (displayItem.isCacheable()) {
164 // Mark the client shouldKeepAlive under this PaintController. 165 // Mark the client shouldKeepAlive under this PaintController.
165 // The status will end after the new display items are committed. 166 // The status will end after the new display items are committed.
166 displayItem.client().beginShouldKeepAlive(this); 167 displayItem.client().beginShouldKeepAlive(this);
167 168
168 if (!m_currentSubsequenceClients.isEmpty()) { 169 if (!m_currentSubsequenceClients.isEmpty()) {
169 // Mark the client shouldKeepAlive under the current subsequence . 170 // Mark the client shouldKeepAlive under the current subsequence .
170 // The status will end when the subsequence owner is invalidated or deleted. 171 // The status will end when the subsequence owner is invalidated or deleted.
171 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last()); 172 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last());
172 } 173 }
173 } 174 }
174 175
175 if (displayItem.getType() == DisplayItem::kSubsequence) { 176 if (displayItem.getType() == DisplayItem::kSubsequence) {
176 m_currentSubsequenceClients.append(&displayItem.client()); 177 m_currentSubsequenceClients.append(&displayItem.client());
177 } else if (displayItem.getType() == DisplayItem::kEndSubsequence) { 178 } else if (displayItem.getType() == DisplayItem::kEndSubsequence) {
178 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); 179 CHECK(m_currentSubsequenceClients.last() == &displayItem.client());
179 m_currentSubsequenceClients.removeLast(); 180 m_currentSubsequenceClients.removeLast();
180 } 181 }
181 } 182 }
182 #endif 183 #endif
183 184
184 if (isSkippingCache()) { 185 if (isSkippingCache())
185 DCHECK(newItemSource == NewPainting);
186 displayItem.setSkippedCache(); 186 displayItem.setSkippedCache();
187 }
188 187
189 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 188 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
190 if (newItemSource != FromCachedSubsequence)
191 m_currentChunkIsFromCachedSubsequence = false;
192
193 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); 189 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex();
194 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { 190 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) {
195 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); 191 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex());
196 if (lastChunkIndex != kNotFound) 192 if (lastChunkIndex != kNotFound)
197 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex)); 193 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex));
198 m_currentChunkIsFromCachedSubsequence = true;
199 } 194 }
200 } 195 }
201 196
202 #if DCHECK_IS_ON() 197 #if DCHECK_IS_ON()
203 // Verify noop begin/end pairs have been removed. 198 // Verify noop begin/end pairs have been removed.
204 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { 199 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) {
205 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; 200 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2];
206 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent()) 201 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent())
207 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); 202 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType()));
208 } 203 }
209 204
210 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); 205 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList);
211 if (index != kNotFound) { 206 if (index != kNotFound) {
212 #ifndef NDEBUG 207 #ifndef NDEBUG
213 showDebugData(); 208 showDebugData();
214 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", 209 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% zu)\n",
215 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); 210 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), index);
216 #endif 211 #endif
217 NOTREACHED(); 212 NOTREACHED();
218 } 213 }
219 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); 214 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient);
220 #endif // DCHECK_IS_ON() 215 #endif // DCHECK_IS_ON()
221 216
222 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) 217 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled())
223 checkUnderInvalidation(); 218 checkUnderInvalidation();
224 } 219 }
225 220
221 DisplayItem& PaintController::moveItemFromCurrentListToNewList(size_t index)
222 {
223 m_itemsMovedIntoNewList.resize(m_currentPaintArtifact.getDisplayItemList().s ize());
224 m_itemsMovedIntoNewList[index] = m_newDisplayItemList.size();
225 return m_newDisplayItemList.appendByMoving(m_currentPaintArtifact.getDisplay ItemList()[index]);
226 }
227
226 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties) 228 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties)
227 { 229 {
228 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); 230 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties);
229 } 231 }
230 232
231 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const 233 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const
232 { 234 {
233 return m_newPaintChunks.currentPaintChunkProperties(); 235 return m_newPaintChunks.currentPaintChunkProperties();
234 } 236 }
235 237
(...skipping 17 matching lines...) Expand all
253 255
254 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) 256 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list)
255 { 257 {
256 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); 258 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client);
257 if (it == displayItemIndicesByClient.end()) 259 if (it == displayItemIndicesByClient.end())
258 return kNotFound; 260 return kNotFound;
259 261
260 const Vector<size_t>& indices = it->value; 262 const Vector<size_t>& indices = it->value;
261 for (size_t index : indices) { 263 for (size_t index : indices) {
262 const DisplayItem& existingItem = list[index]; 264 const DisplayItem& existingItem = list[index];
263 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); 265 if (!existingItem.hasValidClient())
266 continue;
267 DCHECK(existingItem.client() == id.client);
264 if (id == existingItem.getId()) 268 if (id == existingItem.getId())
265 return index; 269 return index;
266 } 270 }
267 271
268 return kNotFound; 272 return kNotFound;
269 } 273 }
270 274
271 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) 275 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient)
272 { 276 {
273 if (!displayItem.isCacheable()) 277 if (!displayItem.isCacheable())
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 // 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.
346 return kNotFound; 350 return kNotFound;
347 } 351 }
348 352
349 // 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,
350 // |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.
351 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence, 355 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence,
352 // 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 .
353 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) 357 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex)
354 { 358 {
359 AutoReset<size_t> subsequenceBeginIndex(&m_currentCachedSubsequenceBeginInde xInNewList, m_newDisplayItemList.size());
355 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex]; 360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex];
356 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); 361 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence);
357 362
358 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { 363 if (RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
359 DCHECK(!isCheckingUnderInvalidation()); 364 DCHECK(!isCheckingUnderInvalidation());
360 m_underInvalidationCheckingBegin = cachedItemIndex; 365 m_underInvalidationCheckingBegin = cachedItemIndex;
361 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")"; 366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")";
362 } 367 }
363 368
364 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence); 369 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence);
365 Vector<PaintChunk>::const_iterator cachedChunk; 370 Vector<PaintChunk>::const_iterator cachedChunk;
366 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 371 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
367 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex); 372 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex);
373 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end());
368 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); 374 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties);
369 } else { 375 } else {
370 // This is to avoid compilation error about uninitialized variable on Wi ndows. 376 // This is to avoid compilation error about uninitialized variable on Wi ndows.
371 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); 377 cachedChunk = m_currentPaintArtifact.paintChunks().begin();
372 } 378 }
373 379
374 while (true) { 380 while (true) {
375 DCHECK(cachedItem->hasValidClient()); 381 DCHECK(cachedItem->hasValidClient());
376 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
377 CHECK(cachedItem->client().isAlive()); 383 CHECK(cachedItem->client().isAlive());
378 #endif 384 #endif
379 ++m_numCachedNewItems; 385 ++m_numCachedNewItems;
380 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; 386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId;
381 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) { 387 if (!RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled()) {
382 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { 388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) {
383 ++cachedChunk; 389 ++cachedChunk;
390 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end() );
384 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); 391 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties);
385 } 392 }
386 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); 393 processNewItem(moveItemFromCurrentListToNewList(cachedItemIndex));
387 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 394 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
388 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); 395 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk));
389 } 396 }
390 397
391 ++cachedItemIndex; 398 ++cachedItemIndex;
392 if (metEndSubsequence) 399 if (metEndSubsequence)
393 break; 400 break;
394 401
395 // We should always be able to find the EndSubsequence display item. 402 // We should always be able to find the EndSubsequence display item.
396 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e()); 403 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e());
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 467
461 for (auto* client : skippedCacheClients) 468 for (auto* client : skippedCacheClients)
462 client->setDisplayItemsUncached(); 469 client->setDisplayItemsUncached();
463 470
464 // The new list will not be appended to again so we can release unused memor y. 471 // The new list will not be appended to again so we can release unused memor y.
465 m_newDisplayItemList.shrinkToFit(); 472 m_newDisplayItemList.shrinkToFit();
466 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); 473 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
467 resetCurrentListIndices(); 474 resetCurrentListIndices();
468 m_outOfOrderItemIndices.clear(); 475 m_outOfOrderItemIndices.clear();
469 m_outOfOrderChunkIndices.clear(); 476 m_outOfOrderChunkIndices.clear();
477 m_itemsMovedIntoNewList.clear();
470 478
471 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 479 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
472 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) { 480 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) {
473 if (chunk.id && chunk.id->client.isJustCreated()) 481 if (chunk.id && chunk.id->client.isJustCreated())
474 chunk.id->client.clearIsJustCreated(); 482 chunk.id->client.clearIsJustCreated();
475 } 483 }
476 } 484 }
477 485
478 // We'll allocate the initial buffer when we start the next paint. 486 // We'll allocate the initial buffer when we start the next paint.
479 m_newDisplayItemList = DisplayItemList(0); 487 m_newDisplayItemList = DisplayItemList(0);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 DCHECK(m_newDisplayItemList.isEmpty()); 528 DCHECK(m_newDisplayItemList.isEmpty());
521 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, std::move(picture)); 529 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, std::move(picture));
522 displayItem.setSkippedCache(); 530 displayItem.setSkippedCache();
523 // TODO(wkorman): Only compute and append visual rect for drawings. 531 // TODO(wkorman): Only compute and append visual rect for drawings.
524 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); 532 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject));
525 } 533 }
526 534
527 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) 535 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk)
528 { 536 {
529 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); 537 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
530 if (m_currentChunkIsFromCachedSubsequence) 538 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList)
531 return; 539 return;
532 540
533 if (!newChunk.id) { 541 if (!newChunk.id) {
534 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); 542 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect()));
535 return; 543 return;
536 } 544 }
537 545
538 // Try to match old chunk sequentially first. 546 // Try to match old chunk sequentially first.
539 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); 547 const auto& oldChunks = m_currentPaintArtifact.paintChunks();
540 while (m_nextChunkToMatch < oldChunks.size()) { 548 while (m_nextChunkToMatch < oldChunks.size()) {
(...skipping 26 matching lines...) Expand all
567 } 575 }
568 576
569 // We reach here because the chunk is new. 577 // We reach here because the chunk is new.
570 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); 578 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t()));
571 } 579 }
572 580
573 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk) 581 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk)
574 { 582 {
575 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); 583 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
576 584
577 // TODO(wangxianzhu): Support raster invalidation for reordered display item s without invalidating
578 // display item clients. Currently we invalidate display item clients ensuri ng raster invalidation.
579 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. 585 // TODO(wangxianzhu): Handle PaintInvalidationIncremental.
580 // TODO(wangxianzhu): Optimize paint offset change. 586 // TODO(wangxianzhu): Optimize paint offset change.
581 587
582 // Maps from each client to the index of the first drawing-content display i tem of the client. 588 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk;
583 HashMap<const DisplayItemClient*, size_t> oldChunkClients; 589 size_t highestMovedToIndex = 0;
584 for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) { 590 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; ++ oldIndex) {
585 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [i]; 591 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [oldIndex];
586 // oldItem.hasValidClient() indicates that the item has not been copied as a cached item into 592 const DisplayItemClient* clientToInvalidate = nullptr;
587 // m_newDislayItemList, so the item either disappeared or changed, and n eeds raster invalidation. 593 if (!oldItem.hasValidClient()) {
588 if (oldItem.hasValidClient() && oldItem.drawsContent() && oldChunkClient s.add(&oldItem.client(), i).isNewEntry) 594 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex];
589 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(i)); 595 if (m_newDisplayItemList[movedToIndex].drawsContent()) {
596 if (movedToIndex < newChunk.beginIndex || movedToIndex >= newChu nk.endIndex) {
597 // The item has been moved into another chunk, so need to in validate it in the old chunk.
598 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent();
599 // And invalidate in the new chunk into which the item was m oved.
600 PaintChunk& movedToChunk = m_newPaintChunks.findChunkByDispl ayItemIndex(movedToIndex);
601 movedToChunk.rasterInvalidationRects.append(clientToInvalida te->visualRect());
602 } else if (movedToIndex < highestMovedToIndex) {
603 // The item has been moved behind other cached items, so nee d to invalidate the area
604 // that is probably exposed by the item moved earlier.
605 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent();
606 } else {
607 highestMovedToIndex = movedToIndex;
608 }
609 }
610 } else if (oldItem.drawsContent()) {
611 clientToInvalidate = &oldItem.client();
612 }
613 if (clientToInvalidate && invalidatedClientsInOldChunk.add(clientToInval idate).isNewEntry) {
614 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(oldIndex));
615 }
590 } 616 }
591 617
592 HashSet<const DisplayItemClient*> newChunkClients; 618 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk;
593 for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) { 619 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; ++ newIndex) {
594 const DisplayItem& newItem = m_newDisplayItemList[i]; 620 const DisplayItem& newItem = m_newDisplayItemList[newIndex];
595 if (newItem.drawsContent()) { 621 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && i nvalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry)
596 if (!clientCacheIsValid(newItem.client())) { 622 newChunk.rasterInvalidationRects.append(newItem.client().visualRect( ));
597 if (newChunkClients.add(&newItem.client()).isNewEntry)
598 newChunk.rasterInvalidationRects.append(newItem.client().vis ualRect());
599 } else {
600 // The cached item was moved from the old chunk which should not contain any item of the client now.
601 DCHECK(!oldChunkClients.contains(&newItem.client()));
602 }
603 }
604 } 623 }
605 } 624 }
606 625
607 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const 626 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const
608 { 627 {
609 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; 628 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason;
610 #ifndef NDEBUG 629 #ifndef NDEBUG
611 LOG(ERROR) << "New display item: " << newItem.asDebugString(); 630 LOG(ERROR) << "New display item: " << newItem.asDebugString();
612 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None"); 631 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None");
613 #else 632 #else
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 showUnderInvalidationError("under-invalidation: display item changed", 678 showUnderInvalidationError("under-invalidation: display item changed",
660 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable UnderInvalidationCount - 1], 679 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable UnderInvalidationCount - 1],
661 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec kingBegin]); 680 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec kingBegin]);
662 CHECK(false); 681 CHECK(false);
663 } 682 }
664 683
665 // Discard the forced repainted display item and move the cached item into m _newDisplayItemList. 684 // Discard the forced repainted display item and move the cached item into m _newDisplayItemList.
666 // This is to align with the non-under-invalidation-checking path to empty t he original cached slot, 685 // This is to align with the non-under-invalidation-checking path to empty t he original cached slot,
667 // leaving only disappeared or invalidated display items in the old list aft er painting. 686 // leaving only disappeared or invalidated display items in the old list aft er painting.
668 m_newDisplayItemList.removeLast(); 687 m_newDisplayItemList.removeLast();
669 m_newDisplayItemList.appendByMoving(*oldItem); 688 moveItemFromCurrentListToNewList(oldItemIndex);
670 689
671 ++m_underInvalidationCheckingBegin; 690 ++m_underInvalidationCheckingBegin;
672 } 691 }
673 692
674 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const 693 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const
675 { 694 {
676 StringBuilder stringBuilder; 695 StringBuilder stringBuilder;
677 size_t i = 0; 696 size_t i = 0;
678 for (auto it = list.begin(); it != list.end(); ++it, ++i) { 697 for (auto it = list.begin(); it != list.end(); ++it, ++i) {
679 const DisplayItem& displayItem = *it; 698 const DisplayItem& displayItem = *it;
680 if (i) 699 if (i)
681 stringBuilder.append(",\n"); 700 stringBuilder.append(",\n");
682 stringBuilder.append(String::format("{index: %d, ", (int)i)); 701 stringBuilder.append(String::format("{index: %zu, ", i));
683 #ifndef NDEBUG 702 #ifndef NDEBUG
684 displayItem.dumpPropertiesAsDebugString(stringBuilder); 703 displayItem.dumpPropertiesAsDebugString(stringBuilder);
685 #else 704 #else
686 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); 705 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data()));
687 #endif 706 #endif
688 if (displayItem.hasValidClient()) { 707 if (displayItem.hasValidClient()) {
689 do { 708 do {
690 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 709 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
691 if (!displayItem.client().isAlive()) { 710 if (!displayItem.client().isAlive()) {
692 stringBuilder.append(", clientIsAlive: false"); 711 stringBuilder.append(", clientIsAlive: false");
(...skipping 15 matching lines...) Expand all
708 return stringBuilder.toString(); 727 return stringBuilder.toString();
709 } 728 }
710 729
711 void PaintController::showDebugData() const 730 void PaintController::showDebugData() const
712 { 731 {
713 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); 732 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data());
714 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); 733 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data());
715 } 734 }
716 735
717 } // namespace blink 736 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698