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

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

Issue 2277443003: [SPv2] Rasterization invalidation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix break of debug build with dcheck off 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"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 44
45 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); 45 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type));
46 if (cachedItem == kNotFound) { 46 if (cachedItem == kNotFound) {
47 NOTREACHED(); 47 NOTREACHED();
48 return false; 48 return false;
49 } 49 }
50 50
51 ++m_numCachedNewItems; 51 ++m_numCachedNewItems;
52 ensureNewDisplayItemListInitialCapacity(); 52 ensureNewDisplayItemListInitialCapacity();
53 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati onCheckingEnabled()) 53 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati onCheckingEnabled())
54 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac t.getDisplayItemList()[cachedItem])); 54 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac t.getDisplayItemList()[cachedItem]), FromCachedItem);
55 55
56 m_nextItemToMatch = cachedItem + 1; 56 m_nextItemToMatch = cachedItem + 1;
57 // Items before m_nextItemToMatch have been copied so we don't need to index them. 57 // Items before m_nextItemToMatch have been copied so we don't need to index them.
58 if (m_nextItemToMatch > m_nextItemToIndex) 58 if (m_nextItemToMatch > m_nextItemToIndex)
59 m_nextItemToIndex = m_nextItemToMatch; 59 m_nextItemToIndex = m_nextItemToMatch;
60 60
61 #if DCHECK_IS_ON() 61 #if DCHECK_IS_ON()
62 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { 62 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
63 if (!isCheckingUnderInvalidation()) { 63 if (!isCheckingUnderInvalidation()) {
64 m_underInvalidationCheckingBegin = cachedItem; 64 m_underInvalidationCheckingBegin = cachedItem;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); 126 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent();
127 } 127 }
128 128
129 void PaintController::removeLastDisplayItem() 129 void PaintController::removeLastDisplayItem()
130 { 130 {
131 if (m_newDisplayItemList.isEmpty()) 131 if (m_newDisplayItemList.isEmpty())
132 return; 132 return;
133 133
134 #if DCHECK_IS_ON() 134 #if DCHECK_IS_ON()
135 // Also remove the index pointing to the removed display item. 135 // Also remove the index pointing to the removed display item.
136 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient .find(&m_newDisplayItemList.last().client()); 136 IndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_ne wDisplayItemList.last().client());
137 if (it != m_newDisplayItemIndicesByClient.end()) { 137 if (it != m_newDisplayItemIndicesByClient.end()) {
138 Vector<size_t>& indices = it->value; 138 Vector<size_t>& indices = it->value;
139 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size() - 1)) 139 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size() - 1))
140 indices.removeLast(); 140 indices.removeLast();
141 } 141 }
142 142
143 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) { 143 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) {
144 if (m_skippedProbableUnderInvalidationCount) { 144 if (m_skippedProbableUnderInvalidationCount) {
145 --m_skippedProbableUnderInvalidationCount; 145 --m_skippedProbableUnderInvalidationCount;
146 } else { 146 } else {
147 DCHECK(m_underInvalidationCheckingBegin); 147 DCHECK(m_underInvalidationCheckingBegin);
148 --m_underInvalidationCheckingBegin; 148 --m_underInvalidationCheckingBegin;
149 } 149 }
150 } 150 }
151 #endif 151 #endif
152 m_newDisplayItemList.removeLast(); 152 m_newDisplayItemList.removeLast();
153 153
154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
155 m_newPaintChunks.decrementDisplayItemIndex(); 155 m_newPaintChunks.decrementDisplayItemIndex();
156 } 156 }
157 157
158 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) 158 const DisplayItem* PaintController::lastDisplayItem(unsigned offset)
159 { 159 {
160 if (offset < m_newDisplayItemList.size()) 160 if (offset < m_newDisplayItemList.size())
161 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; 161 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1];
162 return nullptr; 162 return nullptr;
163 } 163 }
164 164
165 void PaintController::processNewItem(DisplayItem& displayItem) 165 void PaintController::processNewItem(DisplayItem& displayItem, NewItemSource new ItemSource)
166 { 166 {
167 DCHECK(!m_constructionDisabled); 167 DCHECK(!m_constructionDisabled);
168 168
169 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 169 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
170 if (!isSkippingCache()) { 170 if (!isSkippingCache()) {
171 if (displayItem.isCacheable()) { 171 if (displayItem.isCacheable()) {
172 // Mark the client shouldKeepAlive under this PaintController. 172 // Mark the client shouldKeepAlive under this PaintController.
173 // The status will end after the new display items are committed. 173 // The status will end after the new display items are committed.
174 displayItem.client().beginShouldKeepAlive(this); 174 displayItem.client().beginShouldKeepAlive(this);
175 175
176 if (!m_currentSubsequenceClients.isEmpty()) { 176 if (!m_currentSubsequenceClients.isEmpty()) {
177 // Mark the client shouldKeepAlive under the current subsequence . 177 // Mark the client shouldKeepAlive under the current subsequence .
178 // The status will end when the subsequence owner is invalidated or deleted. 178 // The status will end when the subsequence owner is invalidated or deleted.
179 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last()); 179 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last());
180 } 180 }
181 } 181 }
182 182
183 if (displayItem.getType() == DisplayItem::Subsequence) { 183 if (displayItem.getType() == DisplayItem::Subsequence) {
184 m_currentSubsequenceClients.append(&displayItem.client()); 184 m_currentSubsequenceClients.append(&displayItem.client());
185 } else if (displayItem.getType() == DisplayItem::EndSubsequence) { 185 } else if (displayItem.getType() == DisplayItem::EndSubsequence) {
186 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); 186 CHECK(m_currentSubsequenceClients.last() == &displayItem.client());
187 m_currentSubsequenceClients.removeLast(); 187 m_currentSubsequenceClients.removeLast();
188 } 188 }
189 } 189 }
190 #endif 190 #endif
191 191
192 if (isSkippingCache()) 192 if (isSkippingCache()) {
193 DCHECK(newItemSource == NewPainting);
193 displayItem.setSkippedCache(); 194 displayItem.setSkippedCache();
195 }
196
197 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
198 if (newItemSource != FromCachedSubsequence)
199 m_currentChunkIsFromCachedSubsequence = false;
200
201 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex();
202 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) {
203 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex());
204 if (lastChunkIndex != kNotFound)
205 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex));
206 m_currentChunkIsFromCachedSubsequence = true;
207 }
208 }
194 209
195 #if DCHECK_IS_ON() 210 #if DCHECK_IS_ON()
196 // Verify noop begin/end pairs have been removed. 211 // Verify noop begin/end pairs have been removed.
197 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { 212 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) {
198 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; 213 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2];
199 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::Subsequence && !beginDisplayItem.drawsContent()) 214 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::Subsequence && !beginDisplayItem.drawsContent())
200 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); 215 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType()));
201 } 216 }
202 217
203 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); 218 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList);
204 if (index != kNotFound) { 219 if (index != kNotFound) {
205 #ifndef NDEBUG 220 #ifndef NDEBUG
206 showDebugData(); 221 showDebugData();
207 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", 222 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n",
208 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); 223 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index));
209 #endif 224 #endif
210 NOTREACHED(); 225 NOTREACHED();
211 } 226 }
212 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); 227 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient);
213 228
214 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) 229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
215 checkUnderInvalidation(); 230 checkUnderInvalidation();
216 #endif // DCHECK_IS_ON() 231 #endif // DCHECK_IS_ON()
217
218 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
219 m_newPaintChunks.incrementDisplayItemIndex(displayItem);
220 } 232 }
221 233
222 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties) 234 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties)
223 { 235 {
224 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); 236 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties);
225 } 237 }
226 238
227 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const 239 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const
228 { 240 {
229 return m_newPaintChunks.currentPaintChunkProperties(); 241 return m_newPaintChunks.currentPaintChunkProperties();
(...skipping 10 matching lines...) Expand all
240 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const 252 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const
241 { 253 {
242 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 254 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
243 CHECK(client.isAlive()); 255 CHECK(client.isAlive());
244 #endif 256 #endif
245 if (isSkippingCache()) 257 if (isSkippingCache())
246 return false; 258 return false;
247 return client.displayItemsAreCached(m_currentCacheGeneration); 259 return client.displayItemsAreCached(m_currentCacheGeneration);
248 } 260 }
249 261
250 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItemL ist& list) 262 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list)
251 { 263 {
252 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(&id.client); 264 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client);
253 if (it == displayItemIndicesByClient.end()) 265 if (it == displayItemIndicesByClient.end())
254 return kNotFound; 266 return kNotFound;
255 267
256 const Vector<size_t>& indices = it->value; 268 const Vector<size_t>& indices = it->value;
257 for (size_t index : indices) { 269 for (size_t index : indices) {
258 const DisplayItem& existingItem = list[index]; 270 const DisplayItem& existingItem = list[index];
259 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); 271 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent);
260 if (id == existingItem.getId()) 272 if (id == existingItem.getId())
261 return index; 273 return index;
262 } 274 }
263 275
264 return kNotFound; 276 return kNotFound;
265 } 277 }
266 278
267 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 279 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient)
268 { 280 {
269 if (!displayItem.isCacheable()) 281 if (!displayItem.isCacheable())
270 return; 282 return;
271 283
272 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find (&displayItem.client()); 284 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client());
273 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? 285 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ?
274 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; 286 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value;
275 indices.append(index); 287 indices.append(index);
276 } 288 }
277 289
278 size_t PaintController::findCachedItem(const DisplayItem::Id& id) 290 size_t PaintController::findCachedItem(const DisplayItem::Id& id)
279 { 291 {
280 DCHECK(clientCacheIsValid(id.client)); 292 DCHECK(clientCacheIsValid(id.client));
281 293
282 // Try to find the item sequentially first. This is fast if the current list and the new list are in 294 // Try to find the item sequentially first. This is fast if the current list and the new list are in
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS 382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
371 CHECK(cachedItem->client().isAlive()); 383 CHECK(cachedItem->client().isAlive());
372 #endif 384 #endif
373 ++m_numCachedNewItems; 385 ++m_numCachedNewItems;
374 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; 386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId;
375 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { 387 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) {
376 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { 388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) {
377 ++cachedChunk; 389 ++cachedChunk;
378 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); 390 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties);
379 } 391 }
380 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); 392 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence);
381 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) 393 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
382 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); 394 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk));
383 } 395 }
384 396
385 ++cachedItemIndex; 397 ++cachedItemIndex;
386 if (metEndSubsequence) 398 if (metEndSubsequence)
387 break; 399 break;
388 400
389 // We should always be able to find the EndSubsequence display item. 401 // We should always be able to find the EndSubsequence display item.
390 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e()); 402 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e());
(...skipping 12 matching lines...) Expand all
403 { 415 {
404 LayoutRect visualRect = displayItem.client().visualRect(); 416 LayoutRect visualRect = displayItem.client().visualRect();
405 visualRect.move(-offsetFromLayoutObject); 417 visualRect.move(-offsetFromLayoutObject);
406 return enclosingIntRect(visualRect); 418 return enclosingIntRect(visualRect);
407 } 419 }
408 420
409 void PaintController::resetCurrentListIndices() 421 void PaintController::resetCurrentListIndices()
410 { 422 {
411 m_nextItemToMatch = 0; 423 m_nextItemToMatch = 0;
412 m_nextItemToIndex = 0; 424 m_nextItemToIndex = 0;
425 m_nextChunkToMatch = 0;
413 #if DCHECK_IS_ON() 426 #if DCHECK_IS_ON()
414 m_underInvalidationCheckingBegin = 0; 427 m_underInvalidationCheckingBegin = 0;
415 m_underInvalidationCheckingEnd = 0; 428 m_underInvalidationCheckingEnd = 0;
416 m_skippedProbableUnderInvalidationCount = 0; 429 m_skippedProbableUnderInvalidationCount = 0;
417 #endif 430 #endif
418 } 431 }
419 432
420 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb ject) 433 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb ject)
421 { 434 {
422 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", 435 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems",
423 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(), 436 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(),
424 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems); 437 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems);
425 m_numCachedNewItems = 0; 438 m_numCachedNewItems = 0;
426 439
427 // These data structures are used during painting only. 440 // These data structures are used during painting only.
428 DCHECK(!isSkippingCache()); 441 DCHECK(!isSkippingCache());
429 #if DCHECK_IS_ON() 442 #if DCHECK_IS_ON()
430 m_newDisplayItemIndicesByClient.clear(); 443 m_newDisplayItemIndicesByClient.clear();
431 #endif 444 #endif
432 445
446 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !m_newDisplayItemLis t.isEmpty())
447 generateChunkRasterInvalidationRects(m_newPaintChunks.lastChunk());
448
433 SkPictureGpuAnalyzer gpuAnalyzer; 449 SkPictureGpuAnalyzer gpuAnalyzer;
434 450
435 m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationR eason::next(); 451 m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationR eason::next();
436 Vector<const DisplayItemClient*> skippedCacheClients; 452 Vector<const DisplayItemClient*> skippedCacheClients;
437 for (const auto& item : m_newDisplayItemList) { 453 for (const auto& item : m_newDisplayItemList) {
438 // No reason to continue the analysis once we have a veto. 454 // No reason to continue the analysis once we have a veto.
439 if (gpuAnalyzer.suitableForGpuRasterization()) 455 if (gpuAnalyzer.suitableForGpuRasterization())
440 item.analyzeForGpuRasterization(gpuAnalyzer); 456 item.analyzeForGpuRasterization(gpuAnalyzer);
441 457
442 // TODO(wkorman): Only compute and append visual rect for drawings. 458 // TODO(wkorman): Only compute and append visual rect for drawings.
(...skipping 10 matching lines...) Expand all
453 } 469 }
454 470
455 for (auto* client : skippedCacheClients) 471 for (auto* client : skippedCacheClients)
456 client->setDisplayItemsUncached(); 472 client->setDisplayItemsUncached();
457 473
458 // The new list will not be appended to again so we can release unused memor y. 474 // The new list will not be appended to again so we can release unused memor y.
459 m_newDisplayItemList.shrinkToFit(); 475 m_newDisplayItemList.shrinkToFit();
460 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); 476 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
461 resetCurrentListIndices(); 477 resetCurrentListIndices();
462 m_outOfOrderItemIndices.clear(); 478 m_outOfOrderItemIndices.clear();
479 m_outOfOrderChunkIndices.clear();
463 480
464 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 481 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
465 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) { 482 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) {
466 if (chunk.id && chunk.id->client.isJustCreated()) 483 if (chunk.id && chunk.id->client.isJustCreated())
467 chunk.id->client.clearIsJustCreated(); 484 chunk.id->client.clearIsJustCreated();
468 } 485 }
469 } 486 }
470 487
471 // We'll allocate the initial buffer when we start the next paint. 488 // We'll allocate the initial buffer when we start the next paint.
472 m_newDisplayItemList = DisplayItemList(0); 489 m_newDisplayItemList = DisplayItemList(0);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 527
511 void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis playItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayou tObject) 528 void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis playItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayou tObject)
512 { 529 {
513 DCHECK(m_newDisplayItemList.isEmpty()); 530 DCHECK(m_newDisplayItemList.isEmpty());
514 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug Drawing, picture); 531 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug Drawing, picture);
515 displayItem.setSkippedCache(); 532 displayItem.setSkippedCache();
516 // TODO(wkorman): Only compute and append visual rect for drawings. 533 // TODO(wkorman): Only compute and append visual rect for drawings.
517 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); 534 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject));
518 } 535 }
519 536
537 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk)
538 {
539 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
540 if (m_currentChunkIsFromCachedSubsequence)
541 return;
542
543 if (!newChunk.id) {
544 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect()));
545 return;
546 }
547
548 // Try to match old chunk sequentially first.
549 const auto& oldChunks = m_currentPaintArtifact.paintChunks();
550 while (m_nextChunkToMatch < oldChunks.size()) {
551 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch];
552 if (newChunk.matches(oldChunk)) {
553 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldC hunk);
554 ++m_nextChunkToMatch;
555 return;
556 }
557
558 // Add skipped old chunks into the index.
559 if (oldChunk.id) {
560 auto it = m_outOfOrderChunkIndices.find(&oldChunk.id->client);
561 Vector<size_t>& indices = it == m_outOfOrderChunkIndices.end() ?
562 m_outOfOrderChunkIndices.add(&oldChunk.id->client, Vector<size_t >()).storedValue->value : it->value;
563 indices.append(m_nextChunkToMatch);
564 }
565 ++m_nextChunkToMatch;
566 }
567
568 // Sequential matching reaches the end. Find from the out-of-order index.
569 auto it = m_outOfOrderChunkIndices.find(&newChunk.id->client);
570 if (it != m_outOfOrderChunkIndices.end()) {
571 for (size_t i : it->value) {
572 if (newChunk.matches(oldChunks[i])) {
573 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldChunks[i]);
574 return;
575 }
576 }
577 }
578
579 // We reach here because the chunk is new.
580 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t()));
581 }
582
583 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk)
584 {
585 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
586
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.
590 // TODO(wangxianzhu): Optimize paint offset change.
591
592 // Maps from each client to the index of the first drawing-content display i tem of the client.
593 HashMap<const DisplayItemClient*, size_t> oldChunkClients;
594 for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) {
595 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [i];
596 // oldItem.hasValidClient() indicates that the item has not been copied as a cached item into
597 // m_newDislayItemList, so the item either disappeared or changed, and n eeds raster invalidation.
598 if (oldItem.hasValidClient() && oldItem.drawsContent() && oldChunkClient s.add(&oldItem.client(), i).isNewEntry)
599 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(i));
600 }
601
602 HashSet<const DisplayItemClient*> newChunkClients;
603 for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) {
604 const DisplayItem& newItem = m_newDisplayItemList[i];
605 if (newItem.drawsContent()) {
606 if (!clientCacheIsValid(newItem.client())) {
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 }
615 }
616
520 #if DCHECK_IS_ON() 617 #if DCHECK_IS_ON()
521 618
522 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const 619 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const
523 { 620 {
524 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; 621 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason;
525 #ifndef NDEBUG 622 #ifndef NDEBUG
526 LOG(ERROR) << "New display item: " << newItem.asDebugString(); 623 LOG(ERROR) << "New display item: " << newItem.asDebugString();
527 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None"); 624 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None");
528 #else 625 #else
529 LOG(ERROR) << "Run debug build to get more details."; 626 LOG(ERROR) << "Run debug build to get more details.";
(...skipping 12 matching lines...) Expand all
542 639
543 void PaintController::checkUnderInvalidation() 640 void PaintController::checkUnderInvalidation()
544 { 641 {
545 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 642 DCHECK(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
546 643
547 if (!isCheckingUnderInvalidation()) 644 if (!isCheckingUnderInvalidation())
548 return; 645 return;
549 646
550 const DisplayItem& newItem = m_newDisplayItemList.last(); 647 const DisplayItem& newItem = m_newDisplayItemList.last();
551 size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUn derInvalidationCount; 648 size_t oldItemIndex = m_underInvalidationCheckingBegin + m_skippedProbableUn derInvalidationCount;
552 const DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDispla yItemList().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : nullptr; 649 DisplayItem* oldItem = oldItemIndex < m_currentPaintArtifact.getDisplayItemL ist().size() ? &m_currentPaintArtifact.getDisplayItemList()[oldItemIndex] : null ptr;
553 650
554 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem); 651 bool oldAndNewEqual = oldItem && newItem.equals(*oldItem);
555 if (!oldAndNewEqual) { 652 if (!oldAndNewEqual) {
556 if (newItem.isBegin()) { 653 if (newItem.isBegin()) {
557 // Temporarily skip mismatching begin display item which may be remo ved when we remove a no-op pair. 654 // Temporarily skip mismatching begin display item which may be remo ved when we remove a no-op pair.
558 ++m_skippedProbableUnderInvalidationCount; 655 ++m_skippedProbableUnderInvalidationCount;
559 return; 656 return;
560 } 657 }
561 if (newItem.isDrawing() && m_skippedProbableUnderInvalidationCount == 1) { 658 if (newItem.isDrawing() && m_skippedProbableUnderInvalidationCount == 1) {
562 DCHECK_GE(m_newDisplayItemList.size(), 2u); 659 DCHECK_GE(m_newDisplayItemList.size(), 2u);
563 if (m_newDisplayItemList[m_newDisplayItemList.size() - 2].getType() == DisplayItem::BeginCompositing) { 660 if (m_newDisplayItemList[m_newDisplayItemList.size() - 2].getType() == DisplayItem::BeginCompositing) {
564 // This might be a drawing item between a pair of begin/end comp ositing display items that will be folded 661 // This might be a drawing item between a pair of begin/end comp ositing display items that will be folded
565 // into a single drawing display item. 662 // into a single drawing display item.
566 ++m_skippedProbableUnderInvalidationCount; 663 ++m_skippedProbableUnderInvalidationCount;
567 return; 664 return;
568 } 665 }
569 } 666 }
570 } 667 }
571 668
572 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) { 669 if (m_skippedProbableUnderInvalidationCount || !oldAndNewEqual) {
573 // If we ever skipped reporting any under-invalidations, report the earl iest one. 670 // If we ever skipped reporting any under-invalidations, report the earl iest one.
574 showUnderInvalidationError("under-invalidation: display item changed", 671 showUnderInvalidationError("under-invalidation: display item changed",
575 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable UnderInvalidationCount - 1], 672 m_newDisplayItemList[m_newDisplayItemList.size() - m_skippedProbable UnderInvalidationCount - 1],
576 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec kingBegin]); 673 &m_currentPaintArtifact.getDisplayItemList()[m_underInvalidationChec kingBegin]);
577 NOTREACHED(); 674 NOTREACHED();
578 } 675 }
579 676
677 // Align with the non-under-invalidation-checking path: move the cached item into m_newDisplayItemList.
678 m_newDisplayItemList.removeLast();
chrishtr 2016/08/26 20:01:49 This part is new too, right? Why?
Xianzhu 2016/08/26 20:23:23 This is required by the new generateChunkRasterInv
chrishtr 2016/08/26 20:32:22 I still don't get it. What exactly do these two li
Xianzhu 2016/08/26 20:53:49 In normal mode, if a display item can use cache, w
679 m_newDisplayItemList.appendByMoving(*oldItem);
680
580 ++m_underInvalidationCheckingBegin; 681 ++m_underInvalidationCheckingBegin;
581 } 682 }
582 683
583 #endif // DCHECK_IS_ON() 684 #endif // DCHECK_IS_ON()
584 685
585 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const 686 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const
586 { 687 {
587 StringBuilder stringBuilder; 688 StringBuilder stringBuilder;
588 size_t i = 0; 689 size_t i = 0;
589 for (auto it = list.begin(); it != list.end(); ++it, ++i) { 690 for (auto it = list.begin(); it != list.end(); ++it, ++i) {
590 const DisplayItem& displayItem = *it; 691 const DisplayItem& displayItem = *it;
591 if (i) 692 if (i)
592 stringBuilder.append(",\n"); 693 stringBuilder.append(",\n");
593 stringBuilder.append(String::format("{index: %d, ", (int)i)); 694 stringBuilder.append(String::format("{index: %d, ", (int)i));
594 #ifndef NDEBUG 695 #ifndef NDEBUG
595 displayItem.dumpPropertiesAsDebugString(stringBuilder); 696 displayItem.dumpPropertiesAsDebugString(stringBuilder);
596 #else 697 #else
597 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); 698 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data()));
598 #endif 699 #endif
599 if (displayItem.hasValidClient()) { 700 if (displayItem.hasValidClient()) {
600 stringBuilder.append(", cacheIsValid: "); 701 if (displayItem.client().isAlive()) {
601 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "tru e" : "false"); 702 stringBuilder.append(", cacheIsValid: ");
703 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
704 } else {
705 stringBuilder.append(", clientIsAlive: false");
706 }
602 } 707 }
603 if (list.hasVisualRect(i)) { 708 if (list.hasVisualRect(i)) {
604 IntRect visualRect = list.visualRect(i); 709 IntRect visualRect = list.visualRect(i);
605 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", 710 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]",
606 visualRect.x(), visualRect.y(), 711 visualRect.x(), visualRect.y(),
607 visualRect.width(), visualRect.height())); 712 visualRect.width(), visualRect.height()));
608 } 713 }
609 stringBuilder.append('}'); 714 stringBuilder.append('}');
610 } 715 }
611 return stringBuilder.toString(); 716 return stringBuilder.toString();
612 } 717 }
613 718
614 void PaintController::showDebugData() const 719 void PaintController::showDebugData() const
615 { 720 {
616 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); 721 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data());
617 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); 722 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data());
618 } 723 }
619 724
620 } // namespace blink 725 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698