Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "core/paint/PaintPropertyTreeBuilder.h" | 5 #include "core/paint/PaintPropertyTreeBuilder.h" |
| 6 | 6 |
| 7 #include "core/dom/DOMNodeIds.h" | 7 #include "core/dom/DOMNodeIds.h" |
| 8 #include "core/frame/FrameView.h" | 8 #include "core/frame/FrameView.h" |
| 9 #include "core/frame/LocalFrame.h" | 9 #include "core/frame/LocalFrame.h" |
| 10 #include "core/frame/Settings.h" | 10 #include "core/frame/Settings.h" |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 423 context.current.renderingContextId = | 423 context.current.renderingContextId = |
| 424 properties->transform()->renderingContextId(); | 424 properties->transform()->renderingContextId(); |
| 425 context.current.shouldFlattenInheritedTransform = false; | 425 context.current.shouldFlattenInheritedTransform = false; |
| 426 } else { | 426 } else { |
| 427 context.current.renderingContextId = 0; | 427 context.current.renderingContextId = 0; |
| 428 context.current.shouldFlattenInheritedTransform = true; | 428 context.current.shouldFlattenInheritedTransform = true; |
| 429 } | 429 } |
| 430 } | 430 } |
| 431 } | 431 } |
| 432 | 432 |
| 433 void PaintPropertyTreeBuilder::updateMask( | |
| 434 const LayoutObject& object, | |
| 435 PaintPropertyTreeBuilderContext& context) { | |
| 436 DCHECK(object.isBoxModelObject() || object.isSVGChild()); | |
| 437 const ComputedStyle& style = object.styleRef(); | |
| 438 | |
| 439 bool hasMask = false; | |
| 440 IntRect maskClip; | |
| 441 if (object.isSVGChild()) { | |
| 442 // TODO(trchen): Figure out what to do with SVG. SVG may use object | |
| 443 // bounding box for mask sizing, but computing it requires property | |
| 444 // tree to be built. | |
| 445 } else if (style.hasMask()) { | |
| 446 // For HTML/CSS objects, the extent of the mask is known as "mask | |
| 447 // painting area", which is determined by CSS mask-clip property. | |
| 448 // We don't implement mask-clip:margin-box or no-clip currently, | |
| 449 // so the maximum we can get is border-box. | |
| 450 LayoutRect maximumMaskRegion; | |
| 451 if (object.isBox()) { | |
| 452 maximumMaskRegion = toLayoutBox(object).borderBoxRect(); | |
| 453 } else { | |
| 454 // For inline elements, depends on the value of box-decoration-break | |
| 455 // there could be one box in multiple fragments or multiple boxes. | |
| 456 // Either way here we are only interested in the bounding box of them. | |
| 457 DCHECK(object.isLayoutInline()); | |
| 458 maximumMaskRegion = toLayoutInline(object).linesBoundingBox(); | |
| 459 } | |
| 460 maximumMaskRegion.moveBy(context.current.paintOffset); | |
| 461 maskClip = enclosingIntRect(maximumMaskRegion); | |
| 462 hasMask = true; | |
| 463 } | |
| 464 | |
| 465 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | |
| 466 if (hasMask) { | |
| 467 SkBlendMode blendMode = object.isBlendingAllowed() | |
| 468 ? WebCoreCompositeToSkiaComposite( | |
| 469 CompositeSourceOver, style.blendMode()) | |
| 470 : SkBlendMode::kSrcOver; | |
| 471 float opacity = style.opacity(); | |
| 472 | |
| 473 auto& properties = object.getMutableForPainting().ensurePaintProperties(); | |
| 474 context.forceSubtreeUpdate |= properties.updateMaskClip( | |
| 475 context.current.clip, context.current.transform, | |
| 476 FloatRoundedRect(maskClip)); | |
| 477 context.forceSubtreeUpdate |= properties.updateMaskIsolation( | |
| 478 context.currentEffect, context.current.transform, | |
| 479 properties.maskClip(), CompositorFilterOperations(), opacity, | |
| 480 blendMode, CompositingReasonNone, CompositorElementId()); | |
| 481 context.forceSubtreeUpdate |= properties.updateMaskContent( | |
| 482 properties.maskIsolation(), context.current.transform, | |
| 483 properties.maskClip(), CompositorFilterOperations(), 1.f, | |
| 484 SkBlendMode::kDstIn, CompositingReasonNone, CompositorElementId()); | |
| 485 } else if (auto* properties = | |
| 486 object.getMutableForPainting().paintProperties()) { | |
| 487 context.forceSubtreeUpdate |= properties->clearMaskClip(); | |
| 488 context.forceSubtreeUpdate |= properties->clearMaskIsolation(); | |
| 489 context.forceSubtreeUpdate |= properties->clearMaskContent(); | |
| 490 } | |
| 491 } | |
| 492 | |
| 493 if (hasMask) { | |
| 494 auto& properties = *object.getMutableForPainting().paintProperties(); | |
| 495 context.inputClipOfCurrentEffect = context.current.clip = | |
| 496 context.absolutePosition.clip = context.fixedPosition.clip = | |
| 497 properties.maskClip(); | |
| 498 context.currentEffect = properties.maskIsolation(); | |
| 499 } | |
| 500 } | |
| 501 | |
| 433 void PaintPropertyTreeBuilder::updateEffect( | 502 void PaintPropertyTreeBuilder::updateEffect( |
| 434 const LayoutObject& object, | 503 const LayoutObject& object, |
| 435 PaintPropertyTreeBuilderContext& context) { | 504 PaintPropertyTreeBuilderContext& context) { |
| 436 const ComputedStyle& style = object.styleRef(); | 505 const ComputedStyle& style = object.styleRef(); |
| 437 | 506 |
| 438 const bool isCSSIsolatedGroup = | 507 const bool isCSSIsolatedGroup = |
| 439 object.isBoxModelObject() && style.isStackingContext(); | 508 object.isBoxModelObject() && style.isStackingContext(); |
| 440 if (!isCSSIsolatedGroup && !object.isSVGChild()) { | 509 if (!isCSSIsolatedGroup && !object.isSVGChild()) { |
| 441 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 510 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| 442 if (auto* properties = object.getMutableForPainting().paintProperties()) | 511 if (auto* properties = object.getMutableForPainting().paintProperties()) |
| 443 context.forceSubtreeUpdate |= properties->clearEffect(); | 512 context.forceSubtreeUpdate |= properties->clearEffect(); |
| 444 } | 513 } |
| 445 return; | 514 return; |
| 446 } | 515 } |
| 447 | 516 |
| 448 // TODO(trchen): Can't omit effect node if we have 3D children. | 517 // TODO(trchen): Can't omit effect node if we have 3D children. |
| 449 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 518 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| 519 bool blendModeAndOpacityAlreadyApplied = false; | |
|
trchen
2017/01/21 01:27:08
I feel this blend mode & opacity juggling will mak
chrishtr
2017/01/24 01:16:28
How about just making different nodes for all of t
trchen
2017/02/11 02:35:45
As discussed offline. Kick filter out is the most
| |
| 520 if (auto* properties = object.getMutableForPainting().paintProperties()) | |
| 521 blendModeAndOpacityAlreadyApplied = !!properties->maskIsolation(); | |
| 522 | |
| 450 bool effectNodeNeeded = false; | 523 bool effectNodeNeeded = false; |
| 451 | 524 |
| 452 // Can't omit effect node if we have paint children with exotic blending. | 525 // Can't omit effect node if we have paint children with exotic blending. |
| 453 if (object.isSVG()) { | 526 if (blendModeAndOpacityAlreadyApplied) { |
| 527 // No-op. The current effect node already isolated for us. | |
| 528 } else if (object.isSVG()) { | |
| 454 // Yes, including LayoutSVGRoot, because SVG layout objects don't create | 529 // Yes, including LayoutSVGRoot, because SVG layout objects don't create |
| 455 // PaintLayer so PaintLayer::hasNonIsolatedDescendantWithBlendMode() | 530 // PaintLayer so PaintLayer::hasNonIsolatedDescendantWithBlendMode() |
| 456 // doesn't catch SVG descendants. | 531 // doesn't catch SVG descendants. |
| 457 if (SVGLayoutSupport::isIsolationRequired(&object)) | 532 if (SVGLayoutSupport::isIsolationRequired(&object)) |
| 458 effectNodeNeeded = true; | 533 effectNodeNeeded = true; |
| 459 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) { | 534 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) { |
| 460 if (layer->hasNonIsolatedDescendantWithBlendMode()) | 535 if (layer->hasNonIsolatedDescendantWithBlendMode()) |
| 461 effectNodeNeeded = true; | 536 effectNodeNeeded = true; |
| 462 } | 537 } |
| 463 | 538 |
| 464 SkBlendMode blendMode = object.isBlendingAllowed() | 539 SkBlendMode blendMode = |
| 465 ? WebCoreCompositeToSkiaComposite( | 540 (!blendModeAndOpacityAlreadyApplied && object.isBlendingAllowed()) |
| 466 CompositeSourceOver, style.blendMode()) | 541 ? WebCoreCompositeToSkiaComposite(CompositeSourceOver, |
| 467 : SkBlendMode::kSrcOver; | 542 style.blendMode()) |
| 543 : SkBlendMode::kSrcOver; | |
| 468 if (blendMode != SkBlendMode::kSrcOver) | 544 if (blendMode != SkBlendMode::kSrcOver) |
| 469 effectNodeNeeded = true; | 545 effectNodeNeeded = true; |
| 470 | 546 |
| 471 float opacity = style.opacity(); | 547 float opacity = blendModeAndOpacityAlreadyApplied ? 1.0f : style.opacity(); |
| 472 if (opacity != 1.0f) | 548 if (opacity != 1.0f) |
| 473 effectNodeNeeded = true; | 549 effectNodeNeeded = true; |
| 474 | 550 |
| 475 CompositorFilterOperations filter; | 551 CompositorFilterOperations filter; |
| 476 if (object.isSVGChild()) { | 552 if (object.isSVGChild()) { |
| 477 // TODO(trchen): SVG caches filters in SVGResources. Implement it. | 553 // TODO(trchen): SVG caches filters in SVGResources. Implement it. |
| 478 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) { | 554 } else if (PaintLayer* layer = toLayoutBoxModelObject(object).layer()) { |
| 479 // TODO(trchen): Eliminate PaintLayer dependency. | 555 // TODO(trchen): Eliminate PaintLayer dependency. |
| 480 filter = layer->createCompositorFilterOperationsForFilter(style); | 556 filter = layer->createCompositorFilterOperationsForFilter(style); |
| 481 } | 557 } |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 955 void PaintPropertyTreeBuilder::updatePropertiesForSelf( | 1031 void PaintPropertyTreeBuilder::updatePropertiesForSelf( |
| 956 const LayoutObject& object, | 1032 const LayoutObject& object, |
| 957 PaintPropertyTreeBuilderContext& context) { | 1033 PaintPropertyTreeBuilderContext& context) { |
| 958 #if DCHECK_IS_ON() | 1034 #if DCHECK_IS_ON() |
| 959 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); | 1035 FindObjectPropertiesNeedingUpdateScope checkNeedsUpdateScope(object, context); |
| 960 #endif | 1036 #endif |
| 961 | 1037 |
| 962 if (object.isBoxModelObject() || object.isSVG()) { | 1038 if (object.isBoxModelObject() || object.isSVG()) { |
| 963 updatePaintOffsetTranslation(object, context); | 1039 updatePaintOffsetTranslation(object, context); |
| 964 updateTransform(object, context); | 1040 updateTransform(object, context); |
| 1041 updateMask(object, context); | |
| 965 updateEffect(object, context); | 1042 updateEffect(object, context); |
| 966 updateCssClip(object, context); | 1043 updateCssClip(object, context); |
| 967 updateLocalBorderBoxContext(object, context); | 1044 updateLocalBorderBoxContext(object, context); |
| 968 updateScrollbarPaintOffset(object, context); | 1045 updateScrollbarPaintOffset(object, context); |
| 969 } | 1046 } |
| 970 | 1047 |
| 971 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { | 1048 if (object.needsPaintPropertyUpdate() || context.forceSubtreeUpdate) { |
| 972 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && | 1049 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && |
| 973 object.paintOffset() != context.current.paintOffset) { | 1050 object.paintOffset() != context.current.paintOffset) { |
| 974 object.getMutableForPainting().setShouldDoFullPaintInvalidation( | 1051 object.getMutableForPainting().setShouldDoFullPaintInvalidation( |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 991 updateOverflowClip(object, context); | 1068 updateOverflowClip(object, context); |
| 992 updatePerspective(object, context); | 1069 updatePerspective(object, context); |
| 993 updateSvgLocalToBorderBoxTransform(object, context); | 1070 updateSvgLocalToBorderBoxTransform(object, context); |
| 994 updateScrollAndScrollTranslation(object, context); | 1071 updateScrollAndScrollTranslation(object, context); |
| 995 updateOutOfFlowContext(object, context); | 1072 updateOutOfFlowContext(object, context); |
| 996 | 1073 |
| 997 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); | 1074 context.forceSubtreeUpdate |= object.subtreeNeedsPaintPropertyUpdate(); |
| 998 } | 1075 } |
| 999 | 1076 |
| 1000 } // namespace blink | 1077 } // namespace blink |
| OLD | NEW |