Chromium Code Reviews| 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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 m_scopeStack.append(m_nextScope++); | 105 m_scopeStack.append(m_nextScope++); |
| 106 beginSkippingCache(); | 106 beginSkippingCache(); |
| 107 } | 107 } |
| 108 | 108 |
| 109 void DisplayItemList::endScope() | 109 void DisplayItemList::endScope() |
| 110 { | 110 { |
| 111 m_scopeStack.removeLast(); | 111 m_scopeStack.removeLast(); |
| 112 endSkippingCache(); | 112 endSkippingCache(); |
| 113 } | 113 } |
| 114 | 114 |
| 115 void DisplayItemList::invalidate(DisplayItemClient client) | 115 void DisplayItemList::invalidate(DisplayItemClient client) |
|
chrishtr
2015/08/28 17:10:47
Don't you also want to invalidate the paint offset
| |
| 116 { | 116 { |
| 117 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 117 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 118 // Can only be called during layout/paintInvalidation, not during painting. | 118 // Can only be called during layout/paintInvalidation, not during painting. |
| 119 ASSERT(m_newDisplayItems.isEmpty()); | 119 ASSERT(m_newDisplayItems.isEmpty()); |
| 120 updateValidlyCachedClientsIfNeeded(); | 120 updateValidlyCachedClientsIfNeeded(); |
| 121 m_validlyCachedClients.remove(client); | 121 m_validlyCachedClients.remove(client); |
| 122 } | 122 } |
| 123 | 123 |
| 124 void DisplayItemList::invalidateAll() | 124 void DisplayItemList::invalidateAll() |
| 125 { | 125 { |
| 126 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 126 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 127 // Can only be called during layout/paintInvalidation, not during painting. | 127 // Can only be called during layout/paintInvalidation, not during painting. |
| 128 ASSERT(m_newDisplayItems.isEmpty()); | 128 ASSERT(m_newDisplayItems.isEmpty()); |
| 129 m_currentDisplayItems.clear(); | 129 m_currentDisplayItems.clear(); |
| 130 m_validlyCachedClients.clear(); | 130 m_validlyCachedClients.clear(); |
| 131 m_validlyCachedClientsDirty = false; | 131 m_validlyCachedClientsDirty = false; |
| 132 } | 132 } |
| 133 | 133 |
| 134 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const | 134 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
| 135 { | 135 { |
| 136 if (skippingCache()) | 136 if (skippingCache()) |
| 137 return false; | 137 return false; |
| 138 updateValidlyCachedClientsIfNeeded(); | 138 updateValidlyCachedClientsIfNeeded(); |
| 139 return m_validlyCachedClients.contains(client); | 139 return m_validlyCachedClients.contains(client); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void DisplayItemList::invalidatePaintOffset(DisplayItemClient client) | |
| 143 { | |
| 144 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 145 | |
| 146 updateValidlyCachedClientsIfNeeded(); | |
| 147 m_validlyCachedClients.remove(client); | |
| 148 | |
| 149 #if ENABLE(ASSERT) | |
| 150 m_clientsWithPaintOffsetInvalidations.add(client); | |
| 151 | |
| 152 // Ensure no phases slipped in using the old paint offset which would indica te | |
| 153 // different phases used different paint offsets, which should not happen. | |
| 154 for (const auto& item : m_newDisplayItems) | |
| 155 ASSERT(!item.isCached() || item.client() != client); | |
| 156 #endif | |
| 157 } | |
| 158 | |
| 159 #if ENABLE(ASSERT) | |
| 160 bool DisplayItemList::paintOffsetWasInvalidated(DisplayItemClient client) const | |
| 161 { | |
| 162 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 163 return m_clientsWithPaintOffsetInvalidations.contains(client); | |
| 164 } | |
| 165 #endif | |
| 166 | |
| 167 void DisplayItemList::recordPaintOffset(DisplayItemClient client, const LayoutPo int& paintOffset) | |
| 168 { | |
| 169 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 170 m_previousPaintOffsets.set(client, paintOffset); | |
| 171 } | |
| 172 | |
| 173 bool DisplayItemList::paintOffsetWasRecorded(DisplayItemClient client, const Lay outPoint& paintOffset) const | |
|
chrishtr
2015/08/28 17:10:47
This name doesn't seem quite right. Shouldn't it b
| |
| 174 { | |
| 175 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 176 PreviousPaintOffsets::const_iterator it = m_previousPaintOffsets.find(client ); | |
| 177 if (it == m_previousPaintOffsets.end()) | |
| 178 return false; | |
| 179 return paintOffset == it->value; | |
| 180 } | |
| 181 | |
| 182 void DisplayItemList::removeUnneededPaintOffsetEntries() | |
| 183 { | |
| 184 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 185 | |
| 186 // This function is only needed temporarily while paint offsets are stored | |
| 187 // in a map on the list itself. Because we don't always get notified when | |
| 188 // a display item client is removed, we need to infer it to prevent the | |
| 189 // paint offset map from growing indefinitely. This is achieved by just | |
| 190 // removing any paint offset clients that are no longer in the full list. | |
| 191 | |
| 192 HashSet<DisplayItemClient> paintOffsetClientsToRemove; | |
| 193 for (auto& client : m_previousPaintOffsets.keys()) | |
| 194 paintOffsetClientsToRemove.add(client); | |
| 195 for (auto& item : m_currentDisplayItems) | |
| 196 paintOffsetClientsToRemove.remove(item.client()); | |
| 197 | |
| 198 for (auto& client : paintOffsetClientsToRemove) | |
| 199 m_previousPaintOffsets.remove(client); | |
| 200 } | |
| 201 | |
| 142 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems & list) | 202 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, con st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItems & list) |
| 143 { | 203 { |
| 144 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(id.client); | 204 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(id.client); |
| 145 if (it == displayItemIndicesByClient.end()) | 205 if (it == displayItemIndicesByClient.end()) |
| 146 return kNotFound; | 206 return kNotFound; |
| 147 | 207 |
| 148 const Vector<size_t>& indices = it->value; | 208 const Vector<size_t>& indices = it->value; |
| 149 for (size_t index : indices) { | 209 for (size_t index : indices) { |
| 150 const DisplayItem& existingItem = list[index]; | 210 const DisplayItem& existingItem = list[index]; |
| 151 ASSERT(!existingItem.isValid() || existingItem.client() == id.client); | 211 ASSERT(!existingItem.isValid() || existingItem.client() == id.client); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 #endif | 307 #endif |
| 248 | 308 |
| 249 if (m_currentDisplayItems.isEmpty()) { | 309 if (m_currentDisplayItems.isEmpty()) { |
| 250 #if ENABLE(ASSERT) | 310 #if ENABLE(ASSERT) |
| 251 for (const auto& item : m_newDisplayItems) | 311 for (const auto& item : m_newDisplayItems) |
| 252 ASSERT(!item.isCached()); | 312 ASSERT(!item.isCached()); |
| 253 #endif | 313 #endif |
| 254 m_currentDisplayItems.swap(m_newDisplayItems); | 314 m_currentDisplayItems.swap(m_newDisplayItems); |
| 255 m_validlyCachedClientsDirty = true; | 315 m_validlyCachedClientsDirty = true; |
| 256 m_numCachedItems = 0; | 316 m_numCachedItems = 0; |
| 317 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | |
| 318 removeUnneededPaintOffsetEntries(); | |
| 257 return; | 319 return; |
| 258 } | 320 } |
| 259 | 321 |
| 260 updateValidlyCachedClientsIfNeeded(); | 322 updateValidlyCachedClientsIfNeeded(); |
| 261 | 323 |
| 262 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched | 324 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched |
| 263 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched | 325 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched |
| 264 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur es that when | 326 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur es that when |
| 265 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems | 327 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems |
| 266 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time. | 328 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 286 for (DisplayItems::iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) { | 348 for (DisplayItems::iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) { |
| 287 const DisplayItem& newDisplayItem = *newIt; | 349 const DisplayItem& newDisplayItem = *newIt; |
| 288 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); | 350 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); |
| 289 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt emId.type; | 351 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt emId.type; |
| 290 | 352 |
| 291 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche s(*currentIt); | 353 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche s(*currentIt); |
| 292 | 354 |
| 293 if (newDisplayItemHasCachedType) { | 355 if (newDisplayItemHasCachedType) { |
| 294 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled()); | 356 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled()); |
| 295 ASSERT(newDisplayItem.isCached()); | 357 ASSERT(newDisplayItem.isCached()); |
| 296 ASSERT(clientCacheIsValid(newDisplayItem.client())); | 358 ASSERT(clientCacheIsValid(newDisplayItem.client()) || (RuntimeEnable dFeatures::slimmingPaintV2Enabled() && !paintOffsetWasInvalidated(newDisplayItem .client()))); |
| 297 if (!isSynchronized) { | 359 if (!isSynchronized) { |
| 298 currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId , outOfOrderIndexContext); | 360 currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId , outOfOrderIndexContext); |
| 299 | 361 |
| 300 if (currentIt == currentEnd) { | 362 if (currentIt == currentEnd) { |
| 301 #ifndef NDEBUG | 363 #ifndef NDEBUG |
| 302 showDebugData(); | 364 showDebugData(); |
| 303 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD isplayItem.asDebugString().utf8().data()); | 365 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD isplayItem.asDebugString().utf8().data()); |
| 304 #endif | 366 #endif |
| 305 ASSERT_NOT_REACHED(); | 367 ASSERT_NOT_REACHED(); |
| 306 // We did not find the cached display item. This should be i mpossible, but may occur if there is a bug | 368 // We did not find the cached display item. This should be i mpossible, but may occur if there is a bug |
| 307 // in the system, such as under-invalidation, incorrect cach e checking or duplicate display ids. | 369 // in the system, such as under-invalidation, incorrect cach e checking or duplicate display ids. |
| 308 // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list. | 370 // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list. |
| 309 continue; | 371 continue; |
| 310 } | 372 } |
| 311 } | 373 } |
| 312 | 374 |
| 313 if (newDisplayItem.isCachedDrawing()) { | 375 if (newDisplayItem.isCachedDrawing()) { |
| 314 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()) ; | 376 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()) ; |
| 315 ++currentIt; | 377 ++currentIt; |
| 316 } else { | 378 } else { |
| 317 ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence); | 379 ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence); |
| 318 copyCachedSubsequence(currentIt, updatedList); | 380 copyCachedSubsequence(currentIt, updatedList); |
| 319 ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence) ; | 381 ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence) ; |
| 320 } | 382 } |
| 321 } else { | 383 } else { |
| 322 #if ENABLE(ASSERT) | 384 #if ENABLE(ASSERT) |
| 323 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) | 385 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) { |
| 324 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde xContext.displayItemIndicesByClient); | 386 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde xContext.displayItemIndicesByClient); |
| 325 else | 387 } else { |
| 326 ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCach e() || !clientCacheIsValid(newDisplayItem.client())); | 388 ASSERT(!newDisplayItem.isDrawing() |
| 327 #endif // ENABLE(ASSERT) | 389 || newDisplayItem.skippedCache() |
| 390 || !clientCacheIsValid(newDisplayItem.client()) | |
| 391 || (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && pain tOffsetWasInvalidated(newDisplayItem.client()))); | |
| 392 } | |
| 393 #endif | |
| 328 updatedList.appendByMoving(*newIt, newIt->derivedSize()); | 394 updatedList.appendByMoving(*newIt, newIt->derivedSize()); |
| 329 | 395 |
| 330 if (isSynchronized) | 396 if (isSynchronized) |
| 331 ++currentIt; | 397 ++currentIt; |
| 332 } | 398 } |
| 333 } | 399 } |
| 334 | 400 |
| 335 #if ENABLE(ASSERT) | 401 #if ENABLE(ASSERT) |
| 336 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 402 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| 337 checkNoRemainingCachedDisplayItems(); | 403 checkNoRemainingCachedDisplayItems(); |
| 338 #endif // ENABLE(ASSERT) | 404 #endif // ENABLE(ASSERT) |
| 339 | 405 |
| 340 m_newDisplayItems.clear(); | 406 m_newDisplayItems.clear(); |
| 341 m_validlyCachedClientsDirty = true; | 407 m_validlyCachedClientsDirty = true; |
| 342 m_currentDisplayItems.swap(updatedList); | 408 m_currentDisplayItems.swap(updatedList); |
| 343 m_numCachedItems = 0; | 409 m_numCachedItems = 0; |
| 410 | |
| 411 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | |
| 412 removeUnneededPaintOffsetEntries(); | |
| 413 | |
| 414 #if ENABLE(ASSERT) | |
| 415 m_clientsWithPaintOffsetInvalidations.clear(); | |
| 416 #endif | |
| 344 } | 417 } |
| 345 | 418 |
| 346 size_t DisplayItemList::approximateUnsharedMemoryUsage() const | 419 size_t DisplayItemList::approximateUnsharedMemoryUsage() const |
| 347 { | 420 { |
| 348 size_t memoryUsage = sizeof(*this); | 421 size_t memoryUsage = sizeof(*this); |
| 349 | 422 |
| 350 // Memory outside this class due to m_currentDisplayItems. | 423 // Memory outside this class due to m_currentDisplayItems. |
| 351 memoryUsage += m_currentDisplayItems.memoryUsageInBytes(); | 424 memoryUsage += m_currentDisplayItems.memoryUsageInBytes(); |
| 352 | 425 |
| 353 // TODO(jbroman): If display items begin to have significant external memory | 426 // TODO(jbroman): If display items begin to have significant external memory |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 | 614 |
| 542 void DisplayItemList::replay(GraphicsContext& context) | 615 void DisplayItemList::replay(GraphicsContext& context) |
| 543 { | 616 { |
| 544 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); | 617 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); |
| 545 ASSERT(m_newDisplayItems.isEmpty()); | 618 ASSERT(m_newDisplayItems.isEmpty()); |
| 546 for (DisplayItem& displayItem : m_currentDisplayItems) | 619 for (DisplayItem& displayItem : m_currentDisplayItems) |
| 547 displayItem.replay(context); | 620 displayItem.replay(context); |
| 548 } | 621 } |
| 549 | 622 |
| 550 } // namespace blink | 623 } // namespace blink |
| OLD | NEW |