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

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

Issue 2729243002: Improve performance of GeometryMapper cache. (Closed)
Patch Set: none Created 3 years, 9 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/GeometryMapper.h" 5 #include "platform/graphics/paint/GeometryMapper.h"
6 6
7 #include "platform/RuntimeEnabledFeatures.h" 7 #include "platform/RuntimeEnabledFeatures.h"
8 #include "platform/geometry/LayoutRect.h" 8 #include "platform/geometry/LayoutRect.h"
9 9
10 namespace blink { 10 namespace blink {
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 return rect; 207 return rect;
208 208
209 const auto& transformMatrix = 209 const auto& transformMatrix =
210 localToAncestorMatrix(localTransformNode, ancestorTransformNode); 210 localToAncestorMatrix(localTransformNode, ancestorTransformNode);
211 DCHECK(transformMatrix.isInvertible()); 211 DCHECK(transformMatrix.isInvertible());
212 212
213 // TODO(chrishtr): Cache the inverse? 213 // TODO(chrishtr): Cache the inverse?
214 return transformMatrix.inverse().mapRect(rect); 214 return transformMatrix.inverse().mapRect(rect);
215 } 215 }
216 216
217 GeometryMapper::TransformCache& GeometryMapper::getTransformCache(
218 const TransformPaintPropertyNode* ancestor) {
219 auto addResult = m_transformCache.insert(ancestor, nullptr);
220 if (addResult.isNewEntry)
221 addResult.storedValue->value = WTF::wrapUnique(new TransformCache);
222 return *addResult.storedValue->value;
223 }
224
225 GeometryMapper::ClipCache& GeometryMapper::getClipCache(
226 const ClipPaintPropertyNode* ancestorClip,
227 const TransformPaintPropertyNode* ancestorTransform) {
228 auto addResultTransform = m_clipCache.insert(ancestorClip, nullptr);
229 if (addResultTransform.isNewEntry) {
230 addResultTransform.storedValue->value =
231 WTF::wrapUnique(new TransformToClip);
232 }
233
234 auto addResultClip =
235 addResultTransform.storedValue->value->insert(ancestorTransform, nullptr);
236 if (addResultClip.isNewEntry)
237 addResultClip.storedValue->value = WTF::wrapUnique(new ClipCache);
238
239 return *addResultClip.storedValue->value;
240 }
241
242 FloatClipRect GeometryMapper::localToAncestorClipRect( 217 FloatClipRect GeometryMapper::localToAncestorClipRect(
243 const PropertyTreeState& localState, 218 const PropertyTreeState& localState,
244 const PropertyTreeState& ancestorState) { 219 const PropertyTreeState& ancestorState) {
245 bool success = false; 220 bool success = false;
246 FloatClipRect result = 221 FloatClipRect result =
247 localToAncestorClipRectInternal(localState.clip(), ancestorState.clip(), 222 localToAncestorClipRectInternal(localState.clip(), ancestorState.clip(),
248 ancestorState.transform(), success); 223 ancestorState.transform(), success);
249 224
250 DCHECK(success); 225 DCHECK(success);
251 226
(...skipping 15 matching lines...) Expand all
267 const PropertyTreeState& sourceState, 242 const PropertyTreeState& sourceState,
268 const PropertyTreeState& destinationState, 243 const PropertyTreeState& destinationState,
269 bool& success) { 244 bool& success) {
270 FloatClipRect result = localToAncestorClipRectInternal( 245 FloatClipRect result = localToAncestorClipRectInternal(
271 sourceState.clip(), destinationState.clip(), destinationState.transform(), 246 sourceState.clip(), destinationState.clip(), destinationState.transform(),
272 success); 247 success);
273 // Success if destinationState is an ancestor state. 248 // Success if destinationState is an ancestor state.
274 if (success) 249 if (success)
275 return result; 250 return result;
276 251
277 // Otherwise first map to the lowest common ancestor, then map to destination. 252 // Otherwise first map to the lowest common ancestor, then map to
253 // destination.
278 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor( 254 const TransformPaintPropertyNode* lcaTransform = lowestCommonAncestor(
279 sourceState.transform(), destinationState.transform()); 255 sourceState.transform(), destinationState.transform());
280 DCHECK(lcaTransform); 256 DCHECK(lcaTransform);
281 257
282 // Assume that the clip of destinationState is an ancestor of the clip of 258 // Assume that the clip of destinationState is an ancestor of the clip of
283 // sourceState and is under the space of lcaTransform. Otherwise 259 // sourceState and is under the space of lcaTransform. Otherwise
284 // localToAncestorClipRectInternal() will fail. 260 // localToAncestorClipRectInternal() will fail.
285 PropertyTreeState lcaState = destinationState; 261 PropertyTreeState lcaState = destinationState;
286 lcaState.setTransform(lcaTransform); 262 lcaState.setTransform(lcaTransform);
287 263
288 result = localToAncestorClipRectInternal(sourceState.clip(), lcaState.clip(), 264 result = localToAncestorClipRectInternal(sourceState.clip(), lcaState.clip(),
289 lcaState.transform(), success); 265 lcaState.transform(), success);
290 if (!success) { 266 if (!success) {
291 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { 267 if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
292 // On SPv1 we may fail when the paint invalidation container creates an 268 // On SPv1 we may fail when the paint invalidation container creates an
293 // overflow clip (in ancestorState) which is not in localState of an 269 // overflow clip (in ancestorState) which is not in localState of an
294 // out-of-flow positioned descendant. See crbug.com/513108 and layout test 270 // out-of-flow positioned descendant. See crbug.com/513108 and layout
295 // compositing/overflow/handle-non-ancestor-clip-parent.html (run with 271 // test compositing/overflow/handle-non-ancestor-clip-parent.html (run
296 // --enable-prefer-compositing-to-lcd-text) for details. 272 // with --enable-prefer-compositing-to-lcd-text) for details.
297 // Ignore it for SPv1 for now. 273 // Ignore it for SPv1 for now.
298 success = true; 274 success = true;
299 } 275 }
300 return result; 276 return result;
301 } 277 }
302 if (!result.isInfinite()) { 278 if (!result.isInfinite()) {
303 FloatRect final = ancestorToLocalRect(result.rect(), lcaTransform, 279 FloatRect final = ancestorToLocalRect(result.rect(), lcaTransform,
304 destinationState.transform()); 280 destinationState.transform());
305 result.setRect(final); 281 result.setRect(final);
306 } 282 }
307 return result; 283 return result;
308 } 284 }
309 285
310 FloatClipRect GeometryMapper::localToAncestorClipRectInternal( 286 const FloatClipRect& GeometryMapper::localToAncestorClipRectInternal(
311 const ClipPaintPropertyNode* descendant, 287 const ClipPaintPropertyNode* descendant,
312 const ClipPaintPropertyNode* ancestorClip, 288 const ClipPaintPropertyNode* ancestorClip,
313 const TransformPaintPropertyNode* ancestorTransform, 289 const TransformPaintPropertyNode* ancestorTransform,
314 bool& success) { 290 bool& success) {
315 FloatClipRect clip; 291 FloatClipRect clip;
316 if (descendant == ancestorClip) { 292 if (descendant == ancestorClip) {
317 success = true; 293 success = true;
318 // Return an infinite clip. 294 return m_infiniteClip;
319 return clip;
320 } 295 }
321 296
322 ClipCache& clipCache = getClipCache(ancestorClip, ancestorTransform);
323 const ClipPaintPropertyNode* clipNode = descendant; 297 const ClipPaintPropertyNode* clipNode = descendant;
324 Vector<const ClipPaintPropertyNode*> intermediateNodes; 298 Vector<const ClipPaintPropertyNode*> intermediateNodes;
325 299
300 GeometryMapperClipCache::ClipAndTransform clipAndTransform(ancestorClip,
301 ancestorTransform);
326 // Iterate over the path from localState.clip to ancestorState.clip. Stop if 302 // Iterate over the path from localState.clip to ancestorState.clip. Stop if
327 // we've found a memoized (precomputed) clip for any particular node. 303 // we've found a memoized (precomputed) clip for any particular node.
328 while (clipNode && clipNode != ancestorClip) { 304 while (clipNode && clipNode != ancestorClip) {
329 auto it = clipCache.find(clipNode); 305 if (const FloatClipRect* cachedClip =
330 if (it != clipCache.end()) { 306 clipNode->getClipCache().getCachedClip(clipAndTransform)) {
331 clip = it->value; 307 clip = *cachedClip;
332 break; 308 break;
333 } 309 }
310
334 intermediateNodes.push_back(clipNode); 311 intermediateNodes.push_back(clipNode);
335 clipNode = clipNode->parent(); 312 clipNode = clipNode->parent();
336 } 313 }
337 if (!clipNode) { 314 if (!clipNode) {
338 success = false; 315 success = false;
339 return clip; 316 return m_infiniteClip;
340 } 317 }
341 318
342 // Iterate down from the top intermediate node found in the previous loop, 319 // Iterate down from the top intermediate node found in the previous loop,
343 // computing and memoizing clip rects as we go. 320 // computing and memoizing clip rects as we go.
344 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); 321 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend();
345 ++it) { 322 ++it) {
346 success = false; 323 success = false;
347 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal( 324 const TransformationMatrix& transformMatrix = localToAncestorMatrixInternal(
348 (*it)->localTransformSpace(), ancestorTransform, success); 325 (*it)->localTransformSpace(), ancestorTransform, success);
349 if (!success) 326 if (!success)
350 return clip; 327 return m_infiniteClip;
351 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect()); 328 FloatRect mappedRect = transformMatrix.mapRect((*it)->clipRect().rect());
352 clip.intersect(mappedRect); 329 clip.intersect(mappedRect);
353 if ((*it)->clipRect().isRounded()) 330 if ((*it)->clipRect().isRounded())
354 clip.setHasRadius(); 331 clip.setHasRadius();
355 clipCache.set(*it, clip); 332 (*it)->getClipCache().setCachedClip(clipAndTransform, clip);
356 } 333 }
357 334
358 success = true; 335 success = true;
359 return clipCache.find(descendant)->value; 336
337 const FloatClipRect* cachedClip =
338 descendant->getClipCache().getCachedClip(clipAndTransform);
339 DCHECK(cachedClip);
340 return *cachedClip;
360 } 341 }
361 342
362 const TransformationMatrix& GeometryMapper::localToAncestorMatrix( 343 const TransformationMatrix& GeometryMapper::localToAncestorMatrix(
363 const TransformPaintPropertyNode* localTransformNode, 344 const TransformPaintPropertyNode* localTransformNode,
364 const TransformPaintPropertyNode* ancestorTransformNode) { 345 const TransformPaintPropertyNode* ancestorTransformNode) {
365 bool success = false; 346 bool success = false;
366 const auto& result = localToAncestorMatrixInternal( 347 const auto& result = localToAncestorMatrixInternal(
367 localTransformNode, ancestorTransformNode, success); 348 localTransformNode, ancestorTransformNode, success);
368 DCHECK(success); 349 DCHECK(success);
369 return result; 350 return result;
370 } 351 }
371 352
372 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal( 353 const TransformationMatrix& GeometryMapper::localToAncestorMatrixInternal(
373 const TransformPaintPropertyNode* localTransformNode, 354 const TransformPaintPropertyNode* localTransformNode,
374 const TransformPaintPropertyNode* ancestorTransformNode, 355 const TransformPaintPropertyNode* ancestorTransformNode,
375 bool& success) { 356 bool& success) {
376 if (localTransformNode == ancestorTransformNode) { 357 if (localTransformNode == ancestorTransformNode) {
377 success = true; 358 success = true;
378 return m_identity; 359 return m_identity;
379 } 360 }
380 361
381 TransformCache& transformCache = getTransformCache(ancestorTransformNode);
382
383 const TransformPaintPropertyNode* transformNode = localTransformNode; 362 const TransformPaintPropertyNode* transformNode = localTransformNode;
384 Vector<const TransformPaintPropertyNode*> intermediateNodes; 363 Vector<const TransformPaintPropertyNode*> intermediateNodes;
385 TransformationMatrix transformMatrix; 364 TransformationMatrix transformMatrix;
386 365
387 // Iterate over the path from localTransformNode to ancestorState.transform. 366 // Iterate over the path from localTransformNode to ancestorState.transform.
388 // Stop if we've found a memoized (precomputed) transform for any particular 367 // Stop if we've found a memoized (precomputed) transform for any particular
389 // node. 368 // node.
390 while (transformNode && transformNode != ancestorTransformNode) { 369 while (transformNode && transformNode != ancestorTransformNode) {
391 auto it = transformCache.find(transformNode); 370 if (const TransformationMatrix* cachedMatrix =
392 if (it != transformCache.end()) { 371 transformNode->getTransformCache().getCachedTransform(
393 transformMatrix = it->value; 372 ancestorTransformNode)) {
373 transformMatrix = *cachedMatrix;
394 break; 374 break;
395 } 375 }
376
396 intermediateNodes.push_back(transformNode); 377 intermediateNodes.push_back(transformNode);
397 transformNode = transformNode->parent(); 378 transformNode = transformNode->parent();
398 } 379 }
399 if (!transformNode) { 380 if (!transformNode) {
400 success = false; 381 success = false;
401 return m_identity; 382 return m_identity;
402 } 383 }
403 384
404 // Iterate down from the top intermediate node found in the previous loop, 385 // Iterate down from the top intermediate node found in the previous loop,
405 // computing and memoizing transforms as we go. 386 // computing and memoizing transforms as we go.
406 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend(); 387 for (auto it = intermediateNodes.rbegin(); it != intermediateNodes.rend();
407 it++) { 388 it++) {
408 TransformationMatrix localTransformMatrix = (*it)->matrix(); 389 TransformationMatrix localTransformMatrix = (*it)->matrix();
409 localTransformMatrix.applyTransformOrigin((*it)->origin()); 390 localTransformMatrix.applyTransformOrigin((*it)->origin());
410 transformMatrix = transformMatrix * localTransformMatrix; 391 transformMatrix = transformMatrix * localTransformMatrix;
411 transformCache.set(*it, transformMatrix); 392 (*it)->getTransformCache().setCachedTransform(ancestorTransformNode,
393 transformMatrix);
412 } 394 }
413 success = true; 395 success = true;
414 return transformCache.find(localTransformNode)->value; 396 const TransformationMatrix* cachedMatrix =
397 localTransformNode->getTransformCache().getCachedTransform(
398 ancestorTransformNode);
399 DCHECK(cachedMatrix);
400 return *cachedMatrix;
415 } 401 }
416 402
417 void GeometryMapper::clearCache() { 403 void GeometryMapper::clearCache() {
418 m_transformCache.clear(); 404 GeometryMapperTransformCache::clearCache();
419 m_clipCache.clear(); 405 GeometryMapperClipCache::clearCache();
420 } 406 }
421 407
422 namespace { 408 namespace {
423 409
424 template <typename NodeType> 410 template <typename NodeType>
425 unsigned nodeDepth(const NodeType* node) { 411 unsigned nodeDepth(const NodeType* node) {
426 unsigned depth = 0; 412 unsigned depth = 0;
427 while (node) { 413 while (node) {
428 depth++; 414 depth++;
429 node = node->parent(); 415 node = node->parent();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 const TransformPaintPropertyNode*, 456 const TransformPaintPropertyNode*,
471 const TransformPaintPropertyNode*); 457 const TransformPaintPropertyNode*);
472 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor( 458 template const ClipPaintPropertyNode* GeometryMapper::lowestCommonAncestor(
473 const ClipPaintPropertyNode*, 459 const ClipPaintPropertyNode*,
474 const ClipPaintPropertyNode*); 460 const ClipPaintPropertyNode*);
475 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor( 461 template const ScrollPaintPropertyNode* GeometryMapper::lowestCommonAncestor(
476 const ScrollPaintPropertyNode*, 462 const ScrollPaintPropertyNode*,
477 const ScrollPaintPropertyNode*); 463 const ScrollPaintPropertyNode*);
478 464
479 } // namespace blink 465 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698