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" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |