| 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 "config.h" | 5 #include "config.h" |
| 6 #include "platform/graphics/paint/DisplayItemList.h" | 6 #include "platform/graphics/paint/DisplayItemList.h" |
| 7 | 7 |
| 8 #include "platform/NotImplemented.h" | 8 #include "platform/NotImplemented.h" |
| 9 #include "platform/RuntimeEnabledFeatures.h" | 9 #include "platform/RuntimeEnabledFeatures.h" |
| 10 #include "platform/TraceEvent.h" | 10 #include "platform/TraceEvent.h" |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 } | 33 } |
| 34 | 34 |
| 35 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) | 35 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) |
| 36 { | 36 { |
| 37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 38 ASSERT(!m_constructionDisabled); | 38 ASSERT(!m_constructionDisabled); |
| 39 ASSERT(!skippingCache() || !displayItem->isCached()); | 39 ASSERT(!skippingCache() || !displayItem->isCached()); |
| 40 | 40 |
| 41 if (displayItem->isEnd()) { | 41 if (displayItem->isEnd()) { |
| 42 ASSERT(!m_newDisplayItems.isEmpty()); | 42 ASSERT(!m_newDisplayItems.isEmpty()); |
| 43 if (m_newDisplayItems.last()->isBegin() && !m_newDisplayItems.last()->dr
awsContent()) { | 43 if (m_newDisplayItems.last().isBegin() && !m_newDisplayItems.last().draw
sContent()) { |
| 44 ASSERT(displayItem->isEndAndPairedWith(*m_newDisplayItems.last())); | 44 ASSERT(displayItem->isEndAndPairedWith(m_newDisplayItems.last().type
())); |
| 45 // Remove the beginning display item of this empty pair. | 45 // Remove the beginning display item of this empty pair. |
| 46 m_newDisplayItems.removeLast(); | 46 m_newDisplayItems.removeLast(); |
| 47 #if ENABLE(ASSERT) | 47 #if ENABLE(ASSERT) |
| 48 // Also remove the index pointing to the removed display item. | 48 // Also remove the index pointing to the removed display item. |
| 49 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndices
ByClient.find(displayItem->client()); | 49 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndices
ByClient.find(displayItem->client()); |
| 50 if (it != m_newDisplayItemIndicesByClient.end()) { | 50 if (it != m_newDisplayItemIndicesByClient.end()) { |
| 51 Vector<size_t>& indices = it->value; | 51 Vector<size_t>& indices = it->value; |
| 52 if (!indices.isEmpty() && indices.last() == m_newDisplayItems.si
ze()) | 52 if (!indices.isEmpty() && indices.last() == m_newDisplayItems.si
ze()) |
| 53 indices.removeLast(); | 53 indices.removeLast(); |
| 54 } | 54 } |
| 55 #endif | 55 #endif |
| 56 return; | 56 return; |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | 59 |
| 60 if (!m_scopeStack.isEmpty()) | 60 if (!m_scopeStack.isEmpty()) |
| 61 displayItem->setScope(m_scopeStack.last().id, m_scopeStack.last().client
); | 61 displayItem->setScope(m_scopeStack.last().id, m_scopeStack.last().client
); |
| 62 | 62 |
| 63 #if ENABLE(ASSERT) | 63 #if ENABLE(ASSERT) |
| 64 size_t index = findMatchingItemFromIndex(*displayItem, displayItem->type(),
m_newDisplayItemIndicesByClient, m_newDisplayItems); | 64 size_t index = findMatchingItemFromIndex(displayItem->id(), displayItem->typ
e(), m_newDisplayItemIndicesByClient, m_newDisplayItems); |
| 65 if (index != kNotFound) { | 65 if (index != kNotFound) { |
| 66 #ifndef NDEBUG | 66 #ifndef NDEBUG |
| 67 showDebugData(); | 67 showDebugData(); |
| 68 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", | 68 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", |
| 69 displayItem->asDebugString().utf8().data(), m_newDisplayItems[index]
->asDebugString().utf8().data(), static_cast<int>(index)); | 69 displayItem->asDebugString().utf8().data(), m_newDisplayItems[index]
.asDebugString().utf8().data(), static_cast<int>(index)); |
| 70 #endif | 70 #endif |
| 71 ASSERT_NOT_REACHED(); | 71 ASSERT_NOT_REACHED(); |
| 72 } | 72 } |
| 73 addItemToIndex(*displayItem, m_newDisplayItems.size(), m_newDisplayItemIndic
esByClient); | 73 addItemToIndex(displayItem->client(), displayItem->type(), m_newDisplayItems
.size(), m_newDisplayItemIndicesByClient); |
| 74 #endif // ENABLE(ASSERT) | 74 #endif // ENABLE(ASSERT) |
| 75 | 75 |
| 76 ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the fl
ag. | 76 ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the fl
ag. |
| 77 if (skippingCache()) | 77 if (skippingCache()) |
| 78 displayItem->setSkippedCache(); | 78 displayItem->setSkippedCache(); |
| 79 | 79 |
| 80 m_newDisplayItems.append(displayItem); | 80 m_newDisplayItems.append(displayItem); |
| 81 } | 81 } |
| 82 | 82 |
| 83 void DisplayItemList::beginScope(DisplayItemClient client) | 83 void DisplayItemList::beginScope(DisplayItemClient client) |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 } | 118 } |
| 119 | 119 |
| 120 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const | 120 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
| 121 { | 121 { |
| 122 if (skippingCache()) | 122 if (skippingCache()) |
| 123 return false; | 123 return false; |
| 124 updateValidlyCachedClientsIfNeeded(); | 124 updateValidlyCachedClientsIfNeeded(); |
| 125 return m_validlyCachedClients.contains(client); | 125 return m_validlyCachedClients.contains(client); |
| 126 } | 126 } |
| 127 | 127 |
| 128 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem& displayItem
, DisplayItem::Type matchingType, const DisplayItemIndicesByClientMap& displayIt
emIndicesByClient, const DisplayItems& list) | 128 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, Dis
playItem::Type matchingType, const DisplayItemIndicesByClientMap& displayItemInd
icesByClient, const DisplayItems& list) |
| 129 { | 129 { |
| 130 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(displayItem.client()); | 130 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(id.client); |
| 131 if (it == displayItemIndicesByClient.end()) | 131 if (it == displayItemIndicesByClient.end()) |
| 132 return kNotFound; | 132 return kNotFound; |
| 133 | 133 |
| 134 const Vector<size_t>& indices = it->value; | 134 const Vector<size_t>& indices = it->value; |
| 135 for (size_t index : indices) { | 135 for (size_t index : indices) { |
| 136 const OwnPtr<DisplayItem>& existingItem = list[index]; | 136 DisplayItems::ItemHandle existingItem = list[index]; |
| 137 ASSERT(!existingItem || existingItem->client() == displayItem.client()); | 137 ASSERT(existingItem.isGone() || existingItem.client() == id.client); |
| 138 if (existingItem && existingItem->idsEqual(displayItem, matchingType)) | 138 if (!existingItem.isGone() && existingItem.id().equalToExceptForType(id,
matchingType)) |
| 139 return index; | 139 return index; |
| 140 } | 140 } |
| 141 | 141 |
| 142 return kNotFound; | 142 return kNotFound; |
| 143 } | 143 } |
| 144 | 144 |
| 145 void DisplayItemList::addItemToIndex(const DisplayItem& displayItem, size_t inde
x, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 145 void DisplayItemList::addItemToIndex(DisplayItemClient client, DisplayItem::Type
type, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 146 { | 146 { |
| 147 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem
s. | 147 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem
s. |
| 148 if (!displayItem.isDrawing()) | 148 if (!DisplayItem::isDrawingType(type)) |
| 149 return; | 149 return; |
| 150 | 150 |
| 151 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find
(displayItem.client()); | 151 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find
(client); |
| 152 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? | 152 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
| 153 displayItemIndicesByClient.add(displayItem.client(), Vector<size_t>()).s
toredValue->value : it->value; | 153 displayItemIndicesByClient.add(client, Vector<size_t>()).storedValue->va
lue : it->value; |
| 154 indices.append(index); | 154 indices.append(index); |
| 155 } | 155 } |
| 156 | 156 |
| 157 size_t DisplayItemList::findOutOfOrderCachedItem(size_t& currentDisplayItemsInde
x, const DisplayItem& displayItem, DisplayItem::Type matchingType, DisplayItemIn
dicesByClientMap& displayItemIndicesByClient) | 157 DisplayItems::Iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::I
terator& currentIt, const DisplayItem::Id& id, DisplayItem::Type matchingType, D
isplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 158 { | 158 { |
| 159 ASSERT(displayItem.isCached()); | 159 ASSERT(DisplayItem::isCachedType(id.type)); |
| 160 ASSERT(clientCacheIsValid(displayItem.client())); | 160 ASSERT(clientCacheIsValid(id.client)); |
| 161 | 161 |
| 162 size_t foundIndex = findMatchingItemFromIndex(displayItem, matchingType, dis
playItemIndicesByClient, m_currentDisplayItems); | 162 size_t foundIndex = findMatchingItemFromIndex(id, matchingType, displayItemI
ndicesByClient, m_currentDisplayItems); |
| 163 if (foundIndex != kNotFound) | 163 if (foundIndex != kNotFound) |
| 164 return foundIndex; | 164 return m_currentDisplayItems.iteratorAt(foundIndex); |
| 165 | 165 |
| 166 return findOutOfOrderCachedItemForward(currentDisplayItemsIndex, displayItem
, matchingType, displayItemIndicesByClient); | 166 return findOutOfOrderCachedItemForward(currentIt, id, matchingType, displayI
temIndicesByClient); |
| 167 } | 167 } |
| 168 | 168 |
| 169 // Find forward for the item and index all skipped indexable items. | 169 // Find forward for the item and index all skipped indexable items. |
| 170 size_t DisplayItemList::findOutOfOrderCachedItemForward(size_t& currentDisplayIt
emsIndex, const DisplayItem& displayItem, DisplayItem::Type matchingType, Displa
yItemIndicesByClientMap& displayItemIndicesByClient) | 170 DisplayItems::Iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI
tems::Iterator& currentIt, const DisplayItem::Id& id, DisplayItem::Type matching
Type, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 171 { | 171 { |
| 172 size_t currentDisplayItemsSize = m_currentDisplayItems.size(); | 172 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); |
| 173 for (; currentDisplayItemsIndex < currentDisplayItemsSize; ++currentDisplayI
temsIndex) { | 173 for (; currentIt != currentEnd; ++currentIt) { |
| 174 const DisplayItem* item = m_currentDisplayItems[currentDisplayItemsIndex
].get(); | 174 DisplayItems::ItemHandle item = *currentIt; |
| 175 if (item && item->isDrawing() && m_validlyCachedClients.contains(item->c
lient())) { | 175 if (!item.isGone() |
| 176 if (item->idsEqual(displayItem, matchingType)) | 176 && DisplayItem::isDrawingType(item.type()) |
| 177 return currentDisplayItemsIndex; | 177 && m_validlyCachedClients.contains(item.client())) { |
| 178 if (item.id().equalToExceptForType(id, matchingType)) |
| 179 return currentIt; |
| 178 | 180 |
| 179 addItemToIndex(*item, currentDisplayItemsIndex, displayItemIndicesBy
Client); | 181 size_t currentDisplayItemsIndex = m_currentDisplayItems.indexForIter
ator(currentIt); |
| 182 addItemToIndex(item.client(), item.type(), currentDisplayItemsIndex,
displayItemIndicesByClient); |
| 180 } | 183 } |
| 181 } | 184 } |
| 182 return kNotFound; | 185 return currentEnd; |
| 183 } | 186 } |
| 184 | 187 |
| 185 // Update the existing display items by removing invalidated entries, updating | 188 // Update the existing display items by removing invalidated entries, updating |
| 186 // repainted ones, and appending new items. | 189 // repainted ones, and appending new items. |
| 187 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; | 190 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; |
| 188 // - FIXME: Re-enable SubtreeCachedDisplayItem: | 191 // - FIXME: Re-enable SubtreeCachedDisplayItem: |
| 189 // For SubtreeCachedDisplayItem, copy the cached display items between the | 192 // For SubtreeCachedDisplayItem, copy the cached display items between the |
| 190 // corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.); | 193 // corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.); |
| 191 // - Otherwise, copy the new display item. | 194 // - Otherwise, copy the new display item. |
| 192 // | 195 // |
| 193 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). | 196 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). |
| 194 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI
tems | 197 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI
tems |
| 195 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. | 198 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. |
| 196 void DisplayItemList::commitNewDisplayItems() | 199 void DisplayItemList::commitNewDisplayItems() |
| 197 { | 200 { |
| 198 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); | 201 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); |
| 199 | 202 |
| 200 // These data structures are used during painting only. | 203 // These data structures are used during painting only. |
| 201 m_clientScopeIdMap.clear(); | 204 m_clientScopeIdMap.clear(); |
| 202 ASSERT(m_scopeStack.isEmpty()); | 205 ASSERT(m_scopeStack.isEmpty()); |
| 203 m_scopeStack.clear(); | 206 m_scopeStack.clear(); |
| 204 ASSERT(!skippingCache()); | 207 ASSERT(!skippingCache()); |
| 205 #if ENABLE(ASSERT) | 208 #if ENABLE(ASSERT) |
| 206 m_newDisplayItemIndicesByClient.clear(); | 209 m_newDisplayItemIndicesByClient.clear(); |
| 207 #endif | 210 #endif |
| 208 | 211 |
| 209 if (m_currentDisplayItems.isEmpty()) { | 212 if (m_currentDisplayItems.isEmpty()) { |
| 210 #if ENABLE(ASSERT) | 213 #if ENABLE(ASSERT) |
| 211 for (auto& item : m_newDisplayItems) | 214 for (auto& item : m_newDisplayItems) { |
| 212 ASSERT(!item->isCached() && !item->isSubtreeCached()); | 215 ASSERT(!DisplayItem::isCachedType(item.type()) |
| 216 && !DisplayItem::isSubtreeCachedType(item.type())); |
| 217 } |
| 213 #endif | 218 #endif |
| 214 m_currentDisplayItems.swap(m_newDisplayItems); | 219 m_currentDisplayItems.swap(m_newDisplayItems); |
| 215 m_validlyCachedClientsDirty = true; | 220 m_validlyCachedClientsDirty = true; |
| 216 return; | 221 return; |
| 217 } | 222 } |
| 218 | 223 |
| 219 updateValidlyCachedClientsIfNeeded(); | 224 updateValidlyCachedClientsIfNeeded(); |
| 220 | 225 |
| 221 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that
have not been matched | 226 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that
have not been matched |
| 222 // by CachedDisplayItems during synchronized matching. The indexed items wil
l be matched | 227 // by CachedDisplayItems during synchronized matching. The indexed items wil
l be matched |
| 223 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur
es that when | 228 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur
es that when |
| 224 // out-of-order CachedDisplayItems occur, we only traverse at most once over
m_currentDisplayItems | 229 // out-of-order CachedDisplayItems occur, we only traverse at most once over
m_currentDisplayItems |
| 225 // looking for potential matches. Thus we can ensure that the algorithm runs
in linear time. | 230 // looking for potential matches. Thus we can ensure that the algorithm runs
in linear time. |
| 226 DisplayItemIndicesByClientMap displayItemIndicesByClient; | 231 DisplayItemIndicesByClientMap displayItemIndicesByClient; |
| 227 | 232 |
| 228 #if ENABLE(ASSERT) | 233 #if ENABLE(ASSERT) |
| 229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ | 234 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
{ |
| 230 // Under-invalidation checking requires a full index of m_currentDisplay
Items. | 235 // Under-invalidation checking requires a full index of m_currentDisplay
Items. |
| 231 for (size_t i = 0; i < m_currentDisplayItems.size(); ++i) | 236 size_t i = 0; |
| 232 addItemToIndex(*m_currentDisplayItems[i], i, displayItemIndicesByCli
ent); | 237 for (const auto& item : m_currentDisplayItems) { |
| 238 addItemToIndex(item.client(), item.type(), i, displayItemIndicesByCl
ient); |
| 239 ++i; |
| 240 } |
| 233 } | 241 } |
| 234 #endif // ENABLE(ASSERT) | 242 #endif // ENABLE(ASSERT) |
| 235 | 243 |
| 236 DisplayItems updatedList; | 244 DisplayItems updatedList; |
| 237 size_t currentDisplayItemsIndex = 0; | 245 DisplayItems::Iterator currentIt = m_currentDisplayItems.begin(); |
| 238 for (auto& newDisplayItem : m_newDisplayItems) { | 246 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); |
| 239 DisplayItem::Type matchingType = newDisplayItem->type(); | 247 for (DisplayItems::Iterator newIt = m_newDisplayItems.begin(); newIt != m_ne
wDisplayItems.end(); ++newIt) { |
| 240 if (newDisplayItem->isCached()) | 248 DisplayItems::ItemHandle newDisplayItem = *newIt; |
| 249 DisplayItem::Type matchingType = newDisplayItem.type(); |
| 250 if (DisplayItem::isCachedType(newDisplayItem.type())) |
| 241 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType); | 251 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType); |
| 242 bool isSynchronized = currentDisplayItemsIndex < m_currentDisplayItems.s
ize() | 252 bool isSynchronized = currentIt != currentEnd |
| 243 && m_currentDisplayItems[currentDisplayItemsIndex] | 253 && !currentIt->isGone() |
| 244 && m_currentDisplayItems[currentDisplayItemsIndex]->idsEqual(*newDis
playItem, matchingType); | 254 && currentIt->id().equalToExceptForType(newDisplayItem.id(), matchin
gType); |
| 245 | 255 |
| 246 if (newDisplayItem->isCached()) { | 256 if (DisplayItem::isCachedType(newDisplayItem.type())) { |
| 247 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki
ngEnabled()); | 257 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki
ngEnabled()); |
| 248 ASSERT(clientCacheIsValid(newDisplayItem->client())); | 258 ASSERT(clientCacheIsValid(newDisplayItem.client())); |
| 249 if (isSynchronized) { | 259 if (isSynchronized) { |
| 250 updatedList.append(m_currentDisplayItems[currentDisplayItemsInde
x].release()); | 260 updatedList.appendByMoving(currentIt); |
| 251 } else { | 261 } else { |
| 252 size_t foundIndex = findOutOfOrderCachedItem(currentDisplayItems
Index, *newDisplayItem, matchingType, displayItemIndicesByClient); | 262 DisplayItems::Iterator foundIt = findOutOfOrderCachedItem(curren
tIt, newDisplayItem.id(), matchingType, displayItemIndicesByClient); |
| 253 ASSERT(foundIndex != kNotFound); | 263 ASSERT(foundIt != currentEnd); |
| 254 isSynchronized = (foundIndex == currentDisplayItemsIndex); | 264 isSynchronized = (foundIt == currentIt); |
| 255 updatedList.append(m_currentDisplayItems[foundIndex].release()); | 265 updatedList.appendByMoving(foundIt); |
| 256 } | 266 } |
| 257 } else { | 267 } else { |
| 258 #if ENABLE(ASSERT) | 268 #if ENABLE(ASSERT) |
| 259 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) | 269 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) |
| 260 checkCachedDisplayItemIsUnchanged(*newDisplayItem, displayItemIn
dicesByClient); | 270 checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemInd
icesByClient); |
| 261 else | 271 else |
| 262 ASSERT(!newDisplayItem->isDrawing() || newDisplayItem->skippedCa
che() || !clientCacheIsValid(newDisplayItem->client())); | 272 ASSERT(!DisplayItem::isDrawingType(newDisplayItem.type()) || new
DisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client())); |
| 263 #endif // ENABLE(ASSERT) | 273 #endif // ENABLE(ASSERT) |
| 264 updatedList.append(newDisplayItem.release()); | 274 updatedList.appendByMoving(newIt); |
| 265 } | 275 } |
| 266 | 276 |
| 267 if (isSynchronized) | 277 if (isSynchronized) |
| 268 ++currentDisplayItemsIndex; | 278 ++currentIt; |
| 269 } | 279 } |
| 270 | 280 |
| 271 #if ENABLE(ASSERT) | 281 #if ENABLE(ASSERT) |
| 272 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 282 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| 273 checkNoRemainingCachedDisplayItems(); | 283 checkNoRemainingCachedDisplayItems(); |
| 274 #endif // ENABLE(ASSERT) | 284 #endif // ENABLE(ASSERT) |
| 275 | 285 |
| 276 m_newDisplayItems.clear(); | 286 m_newDisplayItems.clear(); |
| 277 m_validlyCachedClientsDirty = true; | 287 m_validlyCachedClientsDirty = true; |
| 278 m_currentDisplayItems.clear(); | 288 m_currentDisplayItems.clear(); |
| 279 m_currentDisplayItems.swap(updatedList); | 289 m_currentDisplayItems.swap(updatedList); |
| 280 } | 290 } |
| 281 | 291 |
| 282 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const | 292 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const |
| 283 { | 293 { |
| 284 if (!m_validlyCachedClientsDirty) | 294 if (!m_validlyCachedClientsDirty) |
| 285 return; | 295 return; |
| 286 | 296 |
| 287 m_validlyCachedClients.clear(); | 297 m_validlyCachedClients.clear(); |
| 288 m_validlyCachedClientsDirty = false; | 298 m_validlyCachedClientsDirty = false; |
| 289 | 299 |
| 290 DisplayItemClient lastClient = nullptr; | 300 DisplayItemClient lastClient = nullptr; |
| 291 for (const auto& displayItem : m_currentDisplayItems) { | 301 for (const auto& displayItem : m_currentDisplayItems) { |
| 292 if (displayItem->client() == lastClient) | 302 if (displayItem.client() == lastClient) |
| 293 continue; | 303 continue; |
| 294 lastClient = displayItem->client(); | 304 lastClient = displayItem.client(); |
| 295 if (!displayItem->skippedCache()) | 305 if (!displayItem.skippedCache()) |
| 296 m_validlyCachedClients.add(lastClient); | 306 m_validlyCachedClients.add(lastClient); |
| 297 } | 307 } |
| 298 } | 308 } |
| 299 | 309 |
| 310 void DisplayItemList::commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisp
layItemList* list) |
| 311 { |
| 312 commitNewDisplayItems(); |
| 313 for (auto& item : m_currentDisplayItems) |
| 314 item.appendToWebDisplayItemList(list); |
| 315 } |
| 316 |
| 300 #if ENABLE(ASSERT) | 317 #if ENABLE(ASSERT) |
| 301 | 318 |
| 302 static void showUnderInvalidationError(const char* reason, const DisplayItem& di
splayItem) | 319 static void showUnderInvalidationError(const char* reason, const DisplayItems::I
temHandle& displayItem) |
| 303 { | 320 { |
| 304 #ifndef NDEBUG | 321 #ifndef NDEBUG |
| 305 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD
ebugString().utf8().data()); | 322 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD
ebugString().utf8().data()); |
| 306 #else | 323 #else |
| 307 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/
450725.", reason); | 324 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/
450725.", reason); |
| 308 #endif // NDEBUG | 325 #endif // NDEBUG |
| 309 } | 326 } |
| 310 | 327 |
| 311 static bool bitmapIsAllZero(const SkBitmap& bitmap) | 328 static bool bitmapIsAllZero(const SkBitmap& bitmap) |
| 312 { | 329 { |
| 313 bitmap.lockPixels(); | 330 bitmap.lockPixels(); |
| 314 bool result = true; | 331 bool result = true; |
| 315 for (int x = 0; result && x < bitmap.width(); ++x) { | 332 for (int x = 0; result && x < bitmap.width(); ++x) { |
| 316 for (int y = 0; result && y < bitmap.height(); ++y) { | 333 for (int y = 0; result && y < bitmap.height(); ++y) { |
| 317 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT) | 334 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT) |
| 318 result = false; | 335 result = false; |
| 319 } | 336 } |
| 320 } | 337 } |
| 321 bitmap.unlockPixels(); | 338 bitmap.unlockPixels(); |
| 322 return result; | 339 return result; |
| 323 } | 340 } |
| 324 | 341 |
| 325 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ
ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 342 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItems::Item
Handle& displayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 326 { | 343 { |
| 327 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 344 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
| 328 | 345 |
| 329 if (!displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) | 346 if (!DisplayItem::isDrawingType(displayItem.type()) || !clientCacheIsValid(d
isplayItem.client())) |
| 330 return; | 347 return; |
| 331 | 348 |
| 332 const DrawingDisplayItem& drawingDisplayItem = static_cast<const DrawingDisp
layItem&>(displayItem); | 349 DrawingDisplayItem::UnderInvalidationCheckingMode mode = displayItem.underIn
validationCheckingMode(); |
| 333 if (drawingDisplayItem.skippedCache()) | |
| 334 return; | |
| 335 | |
| 336 DrawingDisplayItem::UnderInvalidationCheckingMode mode = drawingDisplayItem.
underInvalidationCheckingMode(); | |
| 337 if (mode == DrawingDisplayItem::DontCheck) | 350 if (mode == DrawingDisplayItem::DontCheck) |
| 338 return; | 351 return; |
| 339 | 352 |
| 340 // If checking under-invalidation, we always generate new display item even
if the client is not invalidated. | 353 // If checking under-invalidation, we always generate new display item even
if the client is not invalidated. |
| 341 // Checks if the new picture is the same as the cached old picture. If the n
ew picture is different but | 354 // Checks if the new picture is the same as the cached old picture. If the n
ew picture is different but |
| 342 // the client is not invalidated, issue error about under-invalidation. | 355 // the client is not invalidated, issue error about under-invalidation. |
| 343 size_t index = findMatchingItemFromIndex(displayItem, displayItem.type(), di
splayItemIndicesByClient, m_currentDisplayItems); | 356 size_t index = findMatchingItemFromIndex(displayItem.id(), displayItem.type(
), displayItemIndicesByClient, m_currentDisplayItems); |
| 344 if (index == kNotFound) { | 357 if (index == kNotFound) { |
| 345 showUnderInvalidationError("ERROR: under-invalidation: no cached display
item", displayItem); | 358 showUnderInvalidationError("ERROR: under-invalidation: no cached display
item", displayItem); |
| 346 ASSERT_NOT_REACHED(); | 359 ASSERT_NOT_REACHED(); |
| 347 return; | 360 return; |
| 348 } | 361 } |
| 349 | 362 |
| 350 RefPtr<const SkPicture> newPicture = drawingDisplayItem.picture(); | 363 DisplayItems::Iterator foundItem = m_currentDisplayItems.iteratorAt(index); |
| 351 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(
*m_currentDisplayItems[index]).picture(); | 364 RefPtr<const SkPicture> newPicture = displayItem.picture(); |
| 365 RefPtr<const SkPicture> oldPicture = foundItem->picture(); |
| 352 // Remove the display item from cache so that we can check if there are any
remaining cached display items after merging. | 366 // Remove the display item from cache so that we can check if there are any
remaining cached display items after merging. |
| 353 m_currentDisplayItems[index] = nullptr; | 367 m_currentDisplayItems.setGone(foundItem); |
| 354 | 368 |
| 355 if (!newPicture && !oldPicture) | 369 if (!newPicture && !oldPicture) |
| 356 return; | 370 return; |
| 357 if (newPicture && oldPicture) { | 371 if (newPicture && oldPicture) { |
| 358 switch (mode) { | 372 switch (mode) { |
| 359 case DrawingDisplayItem::CheckPicture: | 373 case DrawingDisplayItem::CheckPicture: |
| 360 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou
nt()) { | 374 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou
nt()) { |
| 361 SkDynamicMemoryWStream newPictureSerialized; | 375 SkDynamicMemoryWStream newPictureSerialized; |
| 362 newPicture->serialize(&newPictureSerialized); | 376 newPicture->serialize(&newPictureSerialized); |
| 363 SkDynamicMemoryWStream oldPictureSerialized; | 377 SkDynamicMemoryWStream oldPictureSerialized; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data()); | 412 WTFLogAlways("new picture:\n%s\n", newPictureDebugString.utf8().data()); |
| 399 #endif // NDEBUG | 413 #endif // NDEBUG |
| 400 | 414 |
| 401 ASSERT_NOT_REACHED(); | 415 ASSERT_NOT_REACHED(); |
| 402 } | 416 } |
| 403 | 417 |
| 404 void DisplayItemList::checkNoRemainingCachedDisplayItems() | 418 void DisplayItemList::checkNoRemainingCachedDisplayItems() |
| 405 { | 419 { |
| 406 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 420 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
| 407 | 421 |
| 408 for (OwnPtr<DisplayItem>& displayItem : m_currentDisplayItems) { | 422 for (const auto& displayItem : m_currentDisplayItems) { |
| 409 if (!displayItem || !displayItem->isDrawing() || !clientCacheIsValid(dis
playItem->client())) | 423 if (displayItem.isGone() || !DisplayItem::isDrawingType(displayItem.type
()) || !clientCacheIsValid(displayItem.client())) |
| 410 continue; | 424 continue; |
| 411 showUnderInvalidationError("May be under-invalidation: no new display it
em", *displayItem); | 425 showUnderInvalidationError("May be under-invalidation: no new display it
em", displayItem); |
| 412 } | 426 } |
| 413 } | 427 } |
| 414 | 428 |
| 415 #endif // ENABLE(ASSERT) | 429 #endif // ENABLE(ASSERT) |
| 416 | 430 |
| 417 #ifndef NDEBUG | 431 #ifndef NDEBUG |
| 418 | 432 |
| 419 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list)
const | 433 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list)
const |
| 420 { | 434 { |
| 421 StringBuilder stringBuilder; | 435 StringBuilder stringBuilder; |
| 422 for (size_t i = 0; i < list.size(); ++i) { | 436 size_t i = 0; |
| 423 const OwnPtr<DisplayItem>& displayItem = list[i]; | 437 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
| 438 DisplayItems::ItemHandle displayItem = list[i]; |
| 424 if (i) | 439 if (i) |
| 425 stringBuilder.append(",\n"); | 440 stringBuilder.append(",\n"); |
| 426 if (!displayItem) { | 441 if (displayItem.isGone()) { |
| 427 stringBuilder.append("null"); | 442 stringBuilder.append("null"); |
| 428 continue; | 443 continue; |
| 429 } | 444 } |
| 430 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 445 stringBuilder.append(String::format("{index: %d, ", (int)i)); |
| 431 displayItem->dumpPropertiesAsDebugString(stringBuilder); | 446 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
| 432 stringBuilder.append(", cacheIsValid: "); | 447 stringBuilder.append(", cacheIsValid: "); |
| 433 stringBuilder.append(clientCacheIsValid(displayItem->client()) ? "true"
: "false"); | 448 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" :
"false"); |
| 434 stringBuilder.append('}'); | 449 stringBuilder.append('}'); |
| 435 } | 450 } |
| 436 return stringBuilder.toString(); | 451 return stringBuilder.toString(); |
| 437 } | 452 } |
| 438 | 453 |
| 439 void DisplayItemList::showDebugData() const | 454 void DisplayItemList::showDebugData() const |
| 440 { | 455 { |
| 441 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu
rrentDisplayItems).utf8().data()); | 456 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu
rrentDisplayItems).utf8().data()); |
| 442 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis
playItems).utf8().data()); | 457 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis
playItems).utf8().data()); |
| 443 } | 458 } |
| 444 | 459 |
| 445 #endif // ifndef NDEBUG | 460 #endif // ifndef NDEBUG |
| 446 | 461 |
| 447 void DisplayItemList::replay(GraphicsContext& context) const | 462 void DisplayItemList::replay(GraphicsContext& context) const |
| 448 { | 463 { |
| 449 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); | 464 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); |
| 450 ASSERT(m_newDisplayItems.isEmpty()); | 465 ASSERT(m_newDisplayItems.isEmpty()); |
| 451 for (auto& displayItem : m_currentDisplayItems) | 466 for (auto& displayItem : m_currentDisplayItems) |
| 452 displayItem->replay(context); | 467 displayItem.replay(context); |
| 453 } | 468 } |
| 454 | 469 |
| 455 } // namespace blink | 470 } // namespace blink |
| OLD | NEW |