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

Side by Side Diff: Source/platform/graphics/paint/DisplayItemList.cpp

Issue 1315993004: Implement a paint offset cache for slimming paint v2 (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Fix bugs caught by unittest failures Created 5 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 "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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/platform/graphics/paint/DisplayItemList.h ('k') | Source/platform/graphics/paint/DrawingRecorder.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698