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

Side by Side Diff: third_party/WebKit/Source/core/paint/PaintPropertyTreeBuilder.cpp

Issue 2831683003: Refactor to centralize code which decides whether ObjectPaintProperties are needed. (Closed)
Patch Set: none Created 3 years, 8 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 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 <memory> 7 #include <memory>
8 #include "core/dom/DOMNodeIds.h" 8 #include "core/dom/DOMNodeIds.h"
9 #include "core/frame/FrameView.h" 9 #include "core/frame/FrameView.h"
10 #include "core/frame/LocalFrame.h" 10 #include "core/frame/LocalFrame.h"
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 context.container_for_absolute_position = nullptr; 217 context.container_for_absolute_position = nullptr;
218 context.fixed_position = context.current; 218 context.fixed_position = context.current;
219 context.fixed_position.transform = fixed_transform_node; 219 context.fixed_position.transform = fixed_transform_node;
220 context.fixed_position.scroll = fixed_scroll_node; 220 context.fixed_position.scroll = fixed_scroll_node;
221 221
222 std::unique_ptr<PropertyTreeState> contents_state(new PropertyTreeState( 222 std::unique_ptr<PropertyTreeState> contents_state(new PropertyTreeState(
223 context.current.transform, context.current.clip, context.current_effect)); 223 context.current.transform, context.current.clip, context.current_effect));
224 frame_view.SetTotalPropertyTreeStateForContents(std::move(contents_state)); 224 frame_view.SetTotalPropertyTreeStateForContents(std::move(contents_state));
225 } 225 }
226 226
227 static bool NeedsPaintPropertiesForPaintOffsetTranslation(
pdr. 2017/04/20 22:56:28 Bikeshed: how about NeedsPaintOffsetTranslation to
chrishtr 2017/04/21 01:20:02 Done. Now there is a nice symmetry: Needs*() and U
228 const LayoutObject& object) {
229 if (!object.IsBoxModelObject())
230 return false;
231 const LayoutBoxModelObject& box_model = ToLayoutBoxModelObject(object);
232 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
233 box_model.IsLayoutView()) {
234 // Root layer scrolling always creates a translation node for LayoutView to
235 // ensure fixed and absolute contexts use the correct transform space.
236 return true;
237 } else if (box_model.HasLayer() &&
238 box_model.Layer()->PaintsWithTransform(
239 kGlobalPaintFlattenCompositingLayers)) {
240 return true;
241 }
242 return false;
243 }
244
227 void PaintPropertyTreeBuilder::UpdatePaintOffsetTranslation( 245 void PaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
228 const LayoutBoxModelObject& object, 246 const LayoutBoxModelObject& object,
229 PaintPropertyTreeBuilderContext& context) { 247 PaintPropertyTreeBuilderContext& context) {
230 bool uses_paint_offset_translation = false; 248 bool uses_paint_offset_translation =
231 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 249 NeedsPaintPropertiesForPaintOffsetTranslation(object);
232 object.IsLayoutView()) { 250 if (!object.IsLayoutView() && context.current.paint_offset == LayoutPoint())
pdr. 2017/04/20 22:56:28 Can you add a comment here? Something like: // As
chrishtr 2017/04/21 01:20:02 Done. Also cleaned up the code some more.
233 // Root layer scrolling always creates a translation node for LayoutView to 251 uses_paint_offset_translation = false;
234 // ensure fixed and absolute contexts use the correct transform space. 252
235 uses_paint_offset_translation = true; 253 auto* properties = object.GetMutableForPainting().PaintProperties();
pdr. 2017/04/20 22:56:28 In the future maybe we can refactor the Update* fu
chrishtr 2017/04/21 01:20:02 Agreed.
236 } else if (object.HasLayer() &&
237 context.current.paint_offset != LayoutPoint() &&
238 object.Layer()->PaintsWithTransform(
239 kGlobalPaintFlattenCompositingLayers)) {
240 uses_paint_offset_translation = true;
241 }
242 254
243 if (!uses_paint_offset_translation) { 255 if (!uses_paint_offset_translation) {
244 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 256 if (properties)
245 context.force_subtree_update |= properties->ClearPaintOffsetTranslation(); 257 context.force_subtree_update |= properties->ClearPaintOffsetTranslation();
246 return; 258 return;
247 } 259 }
260 DCHECK(properties);
248 261
249 // We should use the same subpixel paint offset values for snapping 262 // We should use the same subpixel paint offset values for snapping
250 // regardless of whether a transform is present. If there is a transform 263 // regardless of whether a transform is present. If there is a transform
251 // we round the paint offset but keep around the residual fractional 264 // we round the paint offset but keep around the residual fractional
252 // component for the transformed content to paint with. In spv1 this was 265 // component for the transformed content to paint with. In spv1 this was
253 // called "subpixel accumulation". For more information, see 266 // called "subpixel accumulation". For more information, see
254 // PaintLayer::subpixelAccumulation() and 267 // PaintLayer::subpixelAccumulation() and
255 // PaintLayerPainter::paintFragmentByApplyingTransform. 268 // PaintLayerPainter::paintFragmentByApplyingTransform.
256 IntPoint rounded_paint_offset = RoundedIntPoint(context.current.paint_offset); 269 IntPoint rounded_paint_offset = RoundedIntPoint(context.current.paint_offset);
257 LayoutPoint fractional_paint_offset = 270 LayoutPoint fractional_paint_offset =
258 LayoutPoint(context.current.paint_offset - rounded_paint_offset); 271 LayoutPoint(context.current.paint_offset - rounded_paint_offset);
259 272
260 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 273 context.force_subtree_update |= properties->UpdatePaintOffsetTranslation(
261 context.force_subtree_update |= properties.UpdatePaintOffsetTranslation(
262 context.current.transform, 274 context.current.transform,
263 TransformationMatrix().Translate(rounded_paint_offset.X(), 275 TransformationMatrix().Translate(rounded_paint_offset.X(),
264 rounded_paint_offset.Y()), 276 rounded_paint_offset.Y()),
265 FloatPoint3D(), context.current.should_flatten_inherited_transform, 277 FloatPoint3D(), context.current.should_flatten_inherited_transform,
266 context.current.rendering_context_id); 278 context.current.rendering_context_id);
267 279
268 context.current.transform = properties.PaintOffsetTranslation(); 280 context.current.transform = properties->PaintOffsetTranslation();
269 context.current.paint_offset = fractional_paint_offset; 281 context.current.paint_offset = fractional_paint_offset;
270 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() && 282 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled() &&
271 object.IsLayoutView()) { 283 object.IsLayoutView()) {
272 context.absolute_position.transform = properties.PaintOffsetTranslation(); 284 context.absolute_position.transform = properties->PaintOffsetTranslation();
273 context.fixed_position.transform = properties.PaintOffsetTranslation(); 285 context.fixed_position.transform = properties->PaintOffsetTranslation();
274 context.absolute_position.paint_offset = LayoutPoint(); 286 context.absolute_position.paint_offset = LayoutPoint();
275 context.fixed_position.paint_offset = LayoutPoint(); 287 context.fixed_position.paint_offset = LayoutPoint();
276 } 288 }
277 } 289 }
278 290
291 static bool NeedsPaintPropertiesForNonRootSVG(const LayoutObject& object) {
292 // TODO(pdr): Check for the presence of a transform instead of the value.
293 // Checking for an identity matrix will cause the property tree structure
294 // to change during animations if the animation passes through the
295 // identity matrix.
296 return object.IsSVGChild() &&
297 !object.LocalToSVGParentTransform().IsIdentity();
298 }
299
279 // SVG does not use the general transform update of |updateTransform|, instead 300 // SVG does not use the general transform update of |updateTransform|, instead
280 // creating a transform node for SVG-specific transforms without 3D. 301 // creating a transform node for SVG-specific transforms without 3D.
281 void PaintPropertyTreeBuilder::UpdateTransformForNonRootSVG( 302 void PaintPropertyTreeBuilder::UpdateTransformForNonRootSVG(
282 const LayoutObject& object, 303 const LayoutObject& object,
283 PaintPropertyTreeBuilderContext& context) { 304 PaintPropertyTreeBuilderContext& context) {
284 DCHECK(object.IsSVGChild()); 305 DCHECK(object.IsSVGChild());
285 // SVG does not use paint offset internally, except for SVGForeignObject which 306 // SVG does not use paint offset internally, except for SVGForeignObject which
286 // has different SVG and HTML coordinate spaces. 307 // has different SVG and HTML coordinate spaces.
287 DCHECK(object.IsSVGForeignObject() || 308 DCHECK(object.IsSVGForeignObject() ||
288 context.current.paint_offset == LayoutPoint()); 309 context.current.paint_offset == LayoutPoint());
289 310
290 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 311 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
291 AffineTransform transform = object.LocalToSVGParentTransform(); 312 AffineTransform transform = object.LocalToSVGParentTransform();
292 // TODO(pdr): Check for the presence of a transform instead of the value. 313 if (NeedsPaintPropertiesForNonRootSVG(object)) {
293 // Checking for an identity matrix will cause the property tree structure
294 // to change during animations if the animation passes through the
295 // identity matrix.
296 if (!transform.IsIdentity()) {
297 // The origin is included in the local transform, so leave origin empty. 314 // The origin is included in the local transform, so leave origin empty.
298 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 315 auto& properties = *object.GetMutableForPainting().PaintProperties();
299 context.force_subtree_update |= properties.UpdateTransform( 316 context.force_subtree_update |= properties.UpdateTransform(
300 context.current.transform, TransformationMatrix(transform), 317 context.current.transform, TransformationMatrix(transform),
301 FloatPoint3D()); 318 FloatPoint3D());
302 } else { 319 } else {
303 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 320 if (auto* properties = object.GetMutableForPainting().PaintProperties())
304 context.force_subtree_update |= properties->ClearTransform(); 321 context.force_subtree_update |= properties->ClearTransform();
305 } 322 }
306 } 323 }
307 324
308 if (object.PaintProperties() && object.PaintProperties()->Transform()) { 325 if (object.PaintProperties() && object.PaintProperties()->Transform()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 // Transform origin has no effect without a transform or motion path. 357 // Transform origin has no effect without a transform or motion path.
341 if (!style.HasTransform()) 358 if (!style.HasTransform())
342 return FloatPoint3D(); 359 return FloatPoint3D();
343 FloatSize border_box_size(box.Size()); 360 FloatSize border_box_size(box.Size());
344 return FloatPoint3D( 361 return FloatPoint3D(
345 FloatValueForLength(style.TransformOriginX(), border_box_size.Width()), 362 FloatValueForLength(style.TransformOriginX(), border_box_size.Width()),
346 FloatValueForLength(style.TransformOriginY(), border_box_size.Height()), 363 FloatValueForLength(style.TransformOriginY(), border_box_size.Height()),
347 style.TransformOriginZ()); 364 style.TransformOriginZ());
348 } 365 }
349 366
367 static bool NeedsPaintPropertiesForTransform(const LayoutObject& object) {
368 if (!object.IsBox())
369 return false;
370 return object.StyleRef().HasTransform() || object.StyleRef().Preserves3D() ||
371 CompositingReasonsForTransform(ToLayoutBox(object)) !=
372 kCompositingReasonNone;
373 }
374
350 void PaintPropertyTreeBuilder::UpdateTransform( 375 void PaintPropertyTreeBuilder::UpdateTransform(
351 const LayoutObject& object, 376 const LayoutObject& object,
352 PaintPropertyTreeBuilderContext& context) { 377 PaintPropertyTreeBuilderContext& context) {
353 if (object.IsSVGChild()) { 378 if (object.IsSVGChild()) {
354 UpdateTransformForNonRootSVG(object, context); 379 UpdateTransformForNonRootSVG(object, context);
355 return; 380 return;
356 } 381 }
357 382
358 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 383 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
359 const ComputedStyle& style = object.StyleRef(); 384 const ComputedStyle& style = object.StyleRef();
360 385
361 // A transform node is allocated for transforms, preserves-3d and any 386 // A transform node is allocated for transforms, preserves-3d and any
362 // direct compositing reason. The latter is required because this is the 387 // direct compositing reason. The latter is required because this is the
363 // only way to represent compositing both an element and its stacking 388 // only way to represent compositing both an element and its stacking
364 // descendants. 389 // descendants.
365 bool has_transform = false; 390 if (NeedsPaintPropertiesForTransform(object)) {
366 if (object.IsBox()) {
367 auto& box = ToLayoutBox(object); 391 auto& box = ToLayoutBox(object);
368 392
369 CompositingReasons compositing_reasons = 393 CompositingReasons compositing_reasons =
370 CompositingReasonsForTransform(box); 394 CompositingReasonsForTransform(box);
371 395
372 if (style.HasTransform() || style.Preserves3D() || 396 TransformationMatrix matrix;
373 compositing_reasons != kCompositingReasonNone) { 397 style.ApplyTransform(
374 TransformationMatrix matrix; 398 matrix, box.Size(), ComputedStyle::kExcludeTransformOrigin,
375 style.ApplyTransform( 399 ComputedStyle::kIncludeMotionPath,
376 matrix, box.Size(), ComputedStyle::kExcludeTransformOrigin, 400 ComputedStyle::kIncludeIndependentTransformProperties);
377 ComputedStyle::kIncludeMotionPath,
378 ComputedStyle::kIncludeIndependentTransformProperties);
379 401
380 // TODO(trchen): transform-style should only be respected if a 402 // TODO(trchen): transform-style should only be respected if a
381 // PaintLayer is created. If a node with transform-style: preserve-3d 403 // PaintLayer is created. If a node with transform-style: preserve-3d
382 // does not exist in an existing rendering context, it establishes a new 404 // does not exist in an existing rendering context, it establishes a new
383 // one. 405 // one.
384 unsigned rendering_context_id = context.current.rendering_context_id; 406 unsigned rendering_context_id = context.current.rendering_context_id;
385 if (style.Preserves3D() && !rendering_context_id) 407 if (style.Preserves3D() && !rendering_context_id)
386 rendering_context_id = PtrHash<const LayoutObject>::GetHash(&object); 408 rendering_context_id = PtrHash<const LayoutObject>::GetHash(&object);
387 409
388 CompositorElementId compositor_element_id = 410 CompositorElementId compositor_element_id =
389 style.HasCurrentTransformAnimation() 411 style.HasCurrentTransformAnimation()
390 ? CreateDomNodeBasedCompositorElementId(object) 412 ? CreateDomNodeBasedCompositorElementId(object)
391 : CompositorElementId(); 413 : CompositorElementId();
392 414
393 auto& properties = 415 auto& properties = *object.GetMutableForPainting().PaintProperties();
394 object.GetMutableForPainting().EnsurePaintProperties(); 416 context.force_subtree_update |= properties.UpdateTransform(
395 context.force_subtree_update |= properties.UpdateTransform( 417 context.current.transform, matrix, TransformOrigin(box),
396 context.current.transform, matrix, TransformOrigin(box), 418 context.current.should_flatten_inherited_transform,
397 context.current.should_flatten_inherited_transform, 419 rendering_context_id, compositing_reasons, compositor_element_id);
398 rendering_context_id, compositing_reasons, compositor_element_id); 420 } else {
399 has_transform = true;
400 }
401 }
402 if (!has_transform) {
403 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 421 if (auto* properties = object.GetMutableForPainting().PaintProperties())
404 context.force_subtree_update |= properties->ClearTransform(); 422 context.force_subtree_update |= properties->ClearTransform();
405 } 423 }
406 } 424 }
407 425
408 const auto* properties = object.PaintProperties(); 426 const auto* properties = object.PaintProperties();
409 if (properties && properties->Transform()) { 427 if (properties && properties->Transform()) {
410 context.current.transform = properties->Transform(); 428 context.current.transform = properties->Transform();
411 if (object.StyleRef().Preserves3D()) { 429 if (object.StyleRef().Preserves3D()) {
412 context.current.rendering_context_id = 430 context.current.rendering_context_id =
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 // Either way here we are only interested in the bounding box of them. 472 // Either way here we are only interested in the bounding box of them.
455 DCHECK(object.IsLayoutInline()); 473 DCHECK(object.IsLayoutInline());
456 maximum_mask_region = ToLayoutInline(object).LinesBoundingBox(); 474 maximum_mask_region = ToLayoutInline(object).LinesBoundingBox();
457 } 475 }
458 maximum_mask_region.MoveBy(paint_offset); 476 maximum_mask_region.MoveBy(paint_offset);
459 mask_clip = EnclosingIntRect(maximum_mask_region); 477 mask_clip = EnclosingIntRect(maximum_mask_region);
460 mask_color_filter = kColorFilterNone; 478 mask_color_filter = kColorFilterNone;
461 return true; 479 return true;
462 } 480 }
463 481
482 static bool NeedsPaintPropertiesForEffect(const LayoutObject& object) {
pdr. 2017/04/20 22:56:28 Do we need to include the "!is_css_isolated_group
chrishtr 2017/04/21 01:20:02 Ah good catch. Added, and simplified UpdateEffect.
483 if (object.IsSVG()) {
484 // This handles SVGRoot objects which have PaintLayers.
485 if (object.IsSVGRoot() && object.HasNonIsolatedBlendingDescendants())
486 return true;
487 if (SVGLayoutSupport::IsIsolationRequired(&object))
488 return true;
489 } else if (object.IsBoxModelObject()) {
490 if (PaintLayer* layer = ToLayoutBoxModelObject(object).Layer()) {
491 if (layer->HasNonIsolatedDescendantWithBlendMode())
492 return true;
493 }
494 }
495
496 const ComputedStyle& style = object.StyleRef();
497
498 SkBlendMode blend_mode = object.IsBlendingAllowed()
499 ? WebCoreCompositeToSkiaComposite(
500 kCompositeSourceOver, style.BlendMode())
501 : SkBlendMode::kSrcOver;
502 if (blend_mode != SkBlendMode::kSrcOver)
503 return true;
504
505 float opacity = style.Opacity();
506 if (opacity != 1.0f)
507 return true;
508
509 if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(style))
510 return true;
511
512 if (object.IsSVGChild() &&
513 SVGResourcesCache::CachedResourcesForLayoutObject(&object))
514 return true;
515
516 if (object.StyleRef().HasMask())
517 return true;
518
519 return false;
520 }
521
464 void PaintPropertyTreeBuilder::UpdateEffect( 522 void PaintPropertyTreeBuilder::UpdateEffect(
465 const LayoutObject& object, 523 const LayoutObject& object,
466 PaintPropertyTreeBuilderContext& context) { 524 PaintPropertyTreeBuilderContext& context) {
467 const ComputedStyle& style = object.StyleRef(); 525 const ComputedStyle& style = object.StyleRef();
468 526
469 const bool is_css_isolated_group = 527 const bool is_css_isolated_group =
470 object.IsBoxModelObject() && style.IsStackingContext(); 528 object.IsBoxModelObject() && style.IsStackingContext();
471 if (!is_css_isolated_group && !object.IsSVGChild()) { 529 if (!is_css_isolated_group && !object.IsSVGChild()) {
472 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 530 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
473 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { 531 if (auto* properties = object.GetMutableForPainting().PaintProperties()) {
474 context.force_subtree_update |= properties->ClearEffect(); 532 context.force_subtree_update |= properties->ClearEffect();
475 context.force_subtree_update |= properties->ClearMask(); 533 context.force_subtree_update |= properties->ClearMask();
476 context.force_subtree_update |= properties->ClearMaskClip(); 534 context.force_subtree_update |= properties->ClearMaskClip();
477 } 535 }
478 } 536 }
479 return; 537 return;
480 } 538 }
481 539
482 // TODO(trchen): Can't omit effect node if we have 3D children. 540 // TODO(trchen): Can't omit effect node if we have 3D children.
483 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 541 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
484 const ClipPaintPropertyNode* output_clip = 542 const ClipPaintPropertyNode* output_clip =
485 context.input_clip_of_current_effect; 543 context.input_clip_of_current_effect;
486 544
487 bool effect_node_needed = false; 545 if (NeedsPaintPropertiesForEffect(object)) {
546 auto& properties = *object.GetMutableForPainting().PaintProperties();
488 547
489 // Can't omit effect node if we have paint children with exotic blending. 548 // We may begin to composite our subtree prior to an animation starts,
490 if (object.IsSVG()) { 549 // but a compositor element ID is only needed when an animation is
491 // This handles SVGRoot objects which have PaintLayers. 550 // current.
492 if (object.IsSVGRoot() && object.HasNonIsolatedBlendingDescendants()) 551 CompositingReasons compositing_reasons = kCompositingReasonNone;
493 effect_node_needed = true; 552 if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(
494 else if (SVGLayoutSupport::IsIsolationRequired(&object)) 553 style)) {
495 effect_node_needed = true; 554 compositing_reasons = kCompositingReasonActiveAnimation;
496 } else if (PaintLayer* layer = ToLayoutBoxModelObject(object).Layer()) { 555 }
497 if (layer->HasNonIsolatedDescendantWithBlendMode())
498 effect_node_needed = true;
499 }
500 556
501 SkBlendMode blend_mode = object.IsBlendingAllowed() 557 IntRect mask_clip;
502 ? WebCoreCompositeToSkiaComposite( 558 ColorFilter mask_color_filter;
503 kCompositeSourceOver, style.BlendMode()) 559 bool has_mask = ComputeMaskParameters(
504 : SkBlendMode::kSrcOver; 560 mask_clip, mask_color_filter, object, context.current.paint_offset);
505 if (blend_mode != SkBlendMode::kSrcOver) 561 if (has_mask) {
506 effect_node_needed = true; 562 context.force_subtree_update |= properties.UpdateMaskClip(
563 context.current.clip, context.current.transform,
564 FloatRoundedRect(mask_clip));
565 output_clip = properties.MaskClip();
507 566
508 float opacity = style.Opacity(); 567 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle
509 if (opacity != 1.0f) 568 // grouping (i.e. descendant-dependent compositing reason) properly yet.
510 effect_node_needed = true; 569 // This forces masked subtree always create a layer for now.
570 compositing_reasons |= kCompositingReasonIsolateCompositedDescendants;
571 } else {
572 if (auto* properties = object.GetMutableForPainting().PaintProperties())
573 context.force_subtree_update |= properties->ClearMaskClip();
574 }
511 575
512 // We may begin to composite our subtree prior to an animation starts, 576 SkBlendMode blend_mode =
513 // but a compositor element ID is only needed when an animation is current. 577 object.IsBlendingAllowed()
514 CompositorElementId compositor_element_id = 578 ? WebCoreCompositeToSkiaComposite(kCompositeSourceOver,
515 style.HasCurrentOpacityAnimation() 579 style.BlendMode())
516 ? CreateDomNodeBasedCompositorElementId(object) 580 : SkBlendMode::kSrcOver;
517 : CompositorElementId();
518 CompositingReasons compositing_reasons = kCompositingReasonNone;
519 if (CompositingReasonFinder::RequiresCompositingForOpacityAnimation(
520 style)) {
521 compositing_reasons = kCompositingReasonActiveAnimation;
522 effect_node_needed = true;
523 }
524 DCHECK(!style.HasCurrentOpacityAnimation() ||
525 compositing_reasons != kCompositingReasonNone);
526 581
527 IntRect mask_clip; 582 CompositorElementId compositor_element_id =
528 ColorFilter mask_color_filter; 583 style.HasCurrentOpacityAnimation()
529 bool has_mask = ComputeMaskParameters(mask_clip, mask_color_filter, object, 584 ? CreateDomNodeBasedCompositorElementId(object)
530 context.current.paint_offset); 585 : CompositorElementId();
531 if (has_mask) {
532 effect_node_needed = true;
533 586
534 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 587 DCHECK(!style.HasCurrentOpacityAnimation() ||
535 context.force_subtree_update |= properties.UpdateMaskClip( 588 compositing_reasons != kCompositingReasonNone);
536 context.current.clip, context.current.transform,
537 FloatRoundedRect(mask_clip));
538 output_clip = properties.MaskClip();
539 589
540 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle
541 // grouping (i.e. descendant-dependent compositing reason) properly yet.
542 // This forces masked subtree always create a layer for now.
543 compositing_reasons |= kCompositingReasonIsolateCompositedDescendants;
544 } else {
545 if (auto* properties = object.GetMutableForPainting().PaintProperties())
546 context.force_subtree_update |= properties->ClearMaskClip();
547 }
548
549 if (effect_node_needed) {
550 auto& properties = object.GetMutableForPainting().EnsurePaintProperties();
551 context.force_subtree_update |= properties.UpdateEffect( 590 context.force_subtree_update |= properties.UpdateEffect(
552 context.current_effect, context.current.transform, output_clip, 591 context.current_effect, context.current.transform, output_clip,
553 kColorFilterNone, CompositorFilterOperations(), opacity, blend_mode, 592 kColorFilterNone, CompositorFilterOperations(), style.Opacity(),
554 compositing_reasons, compositor_element_id); 593 blend_mode, compositing_reasons, compositor_element_id);
555 if (has_mask) { 594 if (has_mask) {
556 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle 595 // TODO(crbug.com/683425): PaintArtifactCompositor does not handle
557 // grouping (i.e. descendant-dependent compositing reason) properly yet. 596 // grouping (i.e. descendant-dependent compositing reason) properly yet.
558 // Adding CompositingReasonSquashingDisallowed forces mask not getting 597 // Adding CompositingReasonSquashingDisallowed forces mask not getting
559 // squashed into a child effect. Have no compositing reason otherwise. 598 // squashed into a child effect. Have no compositing reason otherwise.
560 context.force_subtree_update |= properties.UpdateMask( 599 context.force_subtree_update |= properties.UpdateMask(
561 properties.Effect(), context.current.transform, output_clip, 600 properties.Effect(), context.current.transform, output_clip,
562 mask_color_filter, CompositorFilterOperations(), 1.f, 601 mask_color_filter, CompositorFilterOperations(), 1.f,
563 SkBlendMode::kDstIn, kCompositingReasonSquashingDisallowed, 602 SkBlendMode::kDstIn, kCompositingReasonSquashingDisallowed,
564 CompositorElementId()); 603 CompositorElementId());
(...skipping 12 matching lines...) Expand all
577 if (properties && properties->Effect()) { 616 if (properties && properties->Effect()) {
578 context.current_effect = properties->Effect(); 617 context.current_effect = properties->Effect();
579 if (properties->MaskClip()) { 618 if (properties->MaskClip()) {
580 context.input_clip_of_current_effect = context.current.clip = 619 context.input_clip_of_current_effect = context.current.clip =
581 context.absolute_position.clip = context.fixed_position.clip = 620 context.absolute_position.clip = context.fixed_position.clip =
582 properties->MaskClip(); 621 properties->MaskClip();
583 } 622 }
584 } 623 }
585 } 624 }
586 625
626 static bool NeedsPaintPropertiesForFilter(const LayoutObject& object) {
627 // TODO(trchen): SVG caches filters in SVGResources. Implement it.
628 return object.IsBoxModelObject() && object.StyleRef().HasFilter() &&
629 ToLayoutBoxModelObject(object).Layer();
630 }
631
587 void PaintPropertyTreeBuilder::UpdateFilter( 632 void PaintPropertyTreeBuilder::UpdateFilter(
588 const LayoutObject& object, 633 const LayoutObject& object,
589 PaintPropertyTreeBuilderContext& context) { 634 PaintPropertyTreeBuilderContext& context) {
590 const ComputedStyle& style = object.StyleRef(); 635 const ComputedStyle& style = object.StyleRef();
591 636
592 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 637 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
593 CompositorFilterOperations filter; 638 if (NeedsPaintPropertiesForFilter(object)) {
594 if (object.IsSVGChild()) { 639 CompositorFilterOperations filter =
595 // TODO(trchen): SVG caches filters in SVGResources. Implement it. 640 ToLayoutBoxModelObject(object)
596 } else if (PaintLayer* layer = ToLayoutBoxModelObject(object).Layer()) { 641 .Layer()
597 // TODO(trchen): Eliminate PaintLayer dependency. 642 ->CreateCompositorFilterOperationsForFilter(style);
598 filter = layer->CreateCompositorFilterOperationsForFilter(style);
599 }
600 643
601 // The CSS filter spec didn't specify how filters interact with overflow 644 // The CSS filter spec didn't specify how filters interact with overflow
602 // clips. The implementation here mimics the old Blink/WebKit behavior for 645 // clips. The implementation here mimics the old Blink/WebKit behavior for
603 // backward compatibility. 646 // backward compatibility.
604 // Basically the output of the filter will be affected by clips that applies 647 // Basically the output of the filter will be affected by clips that
605 // to the current element. The descendants that paints into the input of the 648 // applies to the current element. The descendants that paints into the
606 // filter ignores any clips collected so far. For example: 649 // input of the filter ignores any clips collected so far. For example:
607 // <div style="overflow:scroll"> 650 // <div style="overflow:scroll">
608 // <div style="filter:blur(1px);"> 651 // <div style="filter:blur(1px);">
609 // <div>A</div> 652 // <div>A</div>
610 // <div style="position:absolute;">B</div> 653 // <div style="position:absolute;">B</div>
611 // </div> 654 // </div>
612 // </div> 655 // </div>
613 // In this example "A" should be clipped if the filter was not present. 656 // In this example "A" should be clipped if the filter was not present.
614 // With the filter, "A" will be rastered without clipping, but instead 657 // With the filter, "A" will be rastered without clipping, but instead
615 // the blurred result will be clipped. 658 // the blurred result will be clipped.
616 // On the other hand, "B" should not be clipped because the overflow clip is 659 // On the other hand, "B" should not be clipped because the overflow clip
617 // not in its containing block chain, but as the filter output will be 660 // is not in its containing block chain, but as the filter output will be
618 // clipped, so a blurred "B" may still be invisible. 661 // clipped, so a blurred "B" may still be invisible.
619 const ClipPaintPropertyNode* output_clip = context.current.clip; 662 const ClipPaintPropertyNode* output_clip = context.current.clip;
620 663
621 // TODO(trchen): A filter may contain spatial operations such that an 664 // TODO(trchen): A filter may contain spatial operations such that an
622 // output pixel may depend on an input pixel outside of the output clip. 665 // output pixel may depend on an input pixel outside of the output clip.
623 // We should generate a special clip node to represent this expansion. 666 // We should generate a special clip node to represent this expansion.
624 667
625 // We may begin to composite our subtree prior to an animation starts, 668 // We may begin to composite our subtree prior to an animation starts,
626 // but a compositor element ID is only needed when an animation is current. 669 // but a compositor element ID is only needed when an animation is
627 CompositorElementId compositor_element_id = 670 // current.
628 style.HasCurrentFilterAnimation() 671 CompositorElementId compositor_element_id =
629 ? CreateDomNodeBasedCompositorElementId(object) 672 style.HasCurrentFilterAnimation()
630 : CompositorElementId(); 673 ? CreateDomNodeBasedCompositorElementId(object)
631 CompositingReasons compositing_reasons = 674 : CompositorElementId();
632 CompositingReasonFinder::RequiresCompositingForFilterAnimation(style) 675 CompositingReasons compositing_reasons =
633 ? kCompositingReasonActiveAnimation 676 CompositingReasonFinder::RequiresCompositingForFilterAnimation(style)
634 : kCompositingReasonNone; 677 ? kCompositingReasonActiveAnimation
635 DCHECK(!style.HasCurrentFilterAnimation() || 678 : kCompositingReasonNone;
636 compositing_reasons != kCompositingReasonNone); 679 DCHECK(!style.HasCurrentFilterAnimation() ||
680 compositing_reasons != kCompositingReasonNone);
637 681
638 if (compositing_reasons == kCompositingReasonNone && filter.IsEmpty()) { 682 auto& properties = *object.GetMutableForPainting().PaintProperties();
639 if (auto* properties = object.GetMutableForPainting().PaintProperties())
640 context.force_subtree_update |= properties->ClearFilter();
641 } else {
642 auto& properties = object.GetMutableForPainting().EnsurePaintProperties();
643 context.force_subtree_update |= properties.UpdateFilter( 683 context.force_subtree_update |= properties.UpdateFilter(
644 context.current_effect, context.current.transform, output_clip, 684 context.current_effect, context.current.transform, output_clip,
645 kColorFilterNone, std::move(filter), 1.f, SkBlendMode::kSrcOver, 685 kColorFilterNone, std::move(filter), 1.f, SkBlendMode::kSrcOver,
646 compositing_reasons, compositor_element_id); 686 compositing_reasons, compositor_element_id);
687 } else {
688 if (auto* properties = object.GetMutableForPainting().PaintProperties())
689 context.force_subtree_update |= properties->ClearFilter();
647 } 690 }
648 } 691 }
649 692
650 const auto* properties = object.PaintProperties(); 693 const auto* properties = object.PaintProperties();
651 if (properties && properties->Filter()) { 694 if (properties && properties->Filter()) {
652 context.current_effect = properties->Filter(); 695 context.current_effect = properties->Filter();
653 // TODO(trchen): Change input clip to expansion hint once implemented. 696 // TODO(trchen): Change input clip to expansion hint once implemented.
654 const ClipPaintPropertyNode* input_clip = 697 const ClipPaintPropertyNode* input_clip =
655 properties->Filter()->OutputClip(); 698 properties->Filter()->OutputClip();
656 context.input_clip_of_current_effect = context.current.clip = 699 context.input_clip_of_current_effect = context.current.clip =
657 context.absolute_position.clip = context.fixed_position.clip = 700 context.absolute_position.clip = context.fixed_position.clip =
658 input_clip; 701 input_clip;
659 } 702 }
660 } 703 }
661 704
705 static bool NeedsPaintPropertiesForCssClip(const LayoutObject& object) {
706 return object.HasClip();
707 }
708
662 void PaintPropertyTreeBuilder::UpdateCssClip( 709 void PaintPropertyTreeBuilder::UpdateCssClip(
663 const LayoutObject& object, 710 const LayoutObject& object,
664 PaintPropertyTreeBuilderContext& context) { 711 PaintPropertyTreeBuilderContext& context) {
665 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 712 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
666 if (object.HasClip()) { 713 if (NeedsPaintPropertiesForCssClip(object)) {
667 // Create clip node for descendants that are not fixed position. 714 // Create clip node for descendants that are not fixed position.
668 // We don't have to setup context.absolutePosition.clip here because this 715 // We don't have to setup context.absolutePosition.clip here because this
669 // object must be a container for absolute position descendants, and will 716 // object must be a container for absolute position descendants, and will
670 // copy from in-flow context later at updateOutOfFlowContext() step. 717 // copy from in-flow context later at updateOutOfFlowContext() step.
671 DCHECK(object.CanContainAbsolutePositionObjects()); 718 DCHECK(object.CanContainAbsolutePositionObjects());
672 LayoutRect clip_rect = 719 LayoutRect clip_rect =
673 ToLayoutBox(object).ClipRect(context.current.paint_offset); 720 ToLayoutBox(object).ClipRect(context.current.paint_offset);
674 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 721 auto& properties = *object.GetMutableForPainting().PaintProperties();
675 context.force_subtree_update |= properties.UpdateCssClip( 722 context.force_subtree_update |= properties.UpdateCssClip(
676 context.current.clip, context.current.transform, 723 context.current.clip, context.current.transform,
677 FloatRoundedRect(FloatRect(clip_rect))); 724 FloatRoundedRect(FloatRect(clip_rect)));
678 } else { 725 } else {
679 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 726 if (auto* properties = object.GetMutableForPainting().PaintProperties())
680 context.force_subtree_update |= properties->ClearCssClip(); 727 context.force_subtree_update |= properties->ClearCssClip();
681 } 728 }
682 } 729 }
683 730
684 const auto* properties = object.PaintProperties(); 731 const auto* properties = object.PaintProperties();
(...skipping 12 matching lines...) Expand all
697 object.GetMutableForPainting().ClearLocalBorderBoxProperties(); 744 object.GetMutableForPainting().ClearLocalBorderBoxProperties();
698 } else { 745 } else {
699 PropertyTreeState local_border_box = 746 PropertyTreeState local_border_box =
700 PropertyTreeState(context.current.transform, context.current.clip, 747 PropertyTreeState(context.current.transform, context.current.clip,
701 context.current_effect); 748 context.current_effect);
702 object.GetMutableForPainting().SetLocalBorderBoxProperties( 749 object.GetMutableForPainting().SetLocalBorderBoxProperties(
703 local_border_box); 750 local_border_box);
704 } 751 }
705 } 752 }
706 753
754 static bool NeedsPaintPropertiesForScrollbarPaintOffset(
755 const LayoutObject& object) {
756 if (object.IsBoxModelObject()) {
757 if (auto* area = ToLayoutBoxModelObject(object).GetScrollableArea()) {
758 if (area->HorizontalScrollbar() || area->VerticalScrollbar())
759 return true;
760 }
761 }
762 return false;
763 }
764
707 // TODO(trchen): Remove this once we bake the paint offset into frameRect. 765 // TODO(trchen): Remove this once we bake the paint offset into frameRect.
708 void PaintPropertyTreeBuilder::UpdateScrollbarPaintOffset( 766 void PaintPropertyTreeBuilder::UpdateScrollbarPaintOffset(
709 const LayoutObject& object, 767 const LayoutObject& object,
710 PaintPropertyTreeBuilderContext& context) { 768 PaintPropertyTreeBuilderContext& context) {
711 if (!object.NeedsPaintPropertyUpdate() && !context.force_subtree_update) 769 if (!object.NeedsPaintPropertyUpdate() && !context.force_subtree_update)
712 return; 770 return;
713 771
714 bool needs_scrollbar_paint_offset = false; 772 if (NeedsPaintPropertiesForScrollbarPaintOffset(object)) {
715 IntPoint rounded_paint_offset = RoundedIntPoint(context.current.paint_offset); 773 IntPoint rounded_paint_offset =
716 if (rounded_paint_offset != IntPoint() && object.IsBoxModelObject()) { 774 RoundedIntPoint(context.current.paint_offset);
717 if (auto* area = ToLayoutBoxModelObject(object).GetScrollableArea()) { 775 auto paint_offset = TransformationMatrix().Translate(
718 if (area->HorizontalScrollbar() || area->VerticalScrollbar()) { 776 rounded_paint_offset.X(), rounded_paint_offset.Y());
719 auto paint_offset = TransformationMatrix().Translate( 777 auto& properties = *object.GetMutableForPainting().PaintProperties();
720 rounded_paint_offset.X(), rounded_paint_offset.Y()); 778 context.force_subtree_update |= properties.UpdateScrollbarPaintOffset(
721 auto& properties = 779 context.current.transform, paint_offset, FloatPoint3D());
722 object.GetMutableForPainting().EnsurePaintProperties(); 780 } else {
723 context.force_subtree_update |= properties.UpdateScrollbarPaintOffset( 781 if (auto* properties = object.GetMutableForPainting().PaintProperties())
724 context.current.transform, paint_offset, FloatPoint3D()); 782 context.force_subtree_update |= properties->ClearScrollbarPaintOffset();
725 needs_scrollbar_paint_offset = true;
726 }
727 }
728 } 783 }
784 }
729 785
730 auto* properties = object.GetMutableForPainting().PaintProperties(); 786 static bool NeedsPaintPropertiesForOverflowScroll(const LayoutObject& object) {
731 if (!needs_scrollbar_paint_offset && properties) 787 return object.IsBox() && ToLayoutBox(object).ShouldClipOverflow();
732 context.force_subtree_update |= properties->ClearScrollbarPaintOffset();
733 } 788 }
734 789
735 void PaintPropertyTreeBuilder::UpdateOverflowClip( 790 void PaintPropertyTreeBuilder::UpdateOverflowClip(
736 const LayoutObject& object, 791 const LayoutObject& object,
737 PaintPropertyTreeBuilderContext& context) { 792 PaintPropertyTreeBuilderContext& context) {
738 if (!object.IsBox())
739 return;
740
741 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 793 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
742 const LayoutBox& box = ToLayoutBox(object); 794 if (NeedsPaintPropertiesForOverflowScroll(object)) {
743 // The <input> elements can't have contents thus CSS overflow property 795 const LayoutBox& box = ToLayoutBox(object);
pdr. 2017/04/20 22:56:28 This comment was dropped. Is it wrong?
chrishtr 2017/04/21 01:20:02 It was obsolete, because control clips have subseq
744 // doesn't apply. However for layout purposes we do generate child layout 796 LayoutRect clip_rect;
745 // objects for them, e.g. button label. We should clip the overflow from
746 // those children. This is called control clip and we technically treat them
747 // like overflow clip.
748 LayoutRect clip_rect;
749 if (box.ShouldClipOverflow()) {
750 clip_rect = 797 clip_rect =
751 LayoutRect(box.OverflowClipRect(context.current.paint_offset)); 798 LayoutRect(box.OverflowClipRect(context.current.paint_offset));
799
800 auto& properties = *object.GetMutableForPainting().PaintProperties();
801 const auto* current_clip = context.current.clip;
802 if (box.StyleRef().HasBorderRadius()) {
803 auto inner_border = box.StyleRef().GetRoundedInnerBorderFor(
804 LayoutRect(context.current.paint_offset, box.Size()));
805 context.force_subtree_update |= properties.UpdateInnerBorderRadiusClip(
806 context.current.clip, context.current.transform, inner_border);
807 current_clip = properties.InnerBorderRadiusClip();
808 } else {
809 context.force_subtree_update |= properties.ClearInnerBorderRadiusClip();
810 }
811
812 context.force_subtree_update |=
813 properties.UpdateOverflowClip(current_clip, context.current.transform,
814 FloatRoundedRect(FloatRect(clip_rect)));
752 } else { 815 } else {
753 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { 816 if (auto* properties = object.GetMutableForPainting().PaintProperties()) {
754 context.force_subtree_update |= 817 context.force_subtree_update |=
755 properties->ClearInnerBorderRadiusClip(); 818 properties->ClearInnerBorderRadiusClip();
756 context.force_subtree_update |= properties->ClearOverflowClip(); 819 context.force_subtree_update |= properties->ClearOverflowClip();
757 } 820 }
758 return; 821 return;
759 } 822 }
760
761 auto& properties = object.GetMutableForPainting().EnsurePaintProperties();
762 const auto* current_clip = context.current.clip;
763 if (box.StyleRef().HasBorderRadius()) {
764 auto inner_border = box.StyleRef().GetRoundedInnerBorderFor(
765 LayoutRect(context.current.paint_offset, box.Size()));
766 context.force_subtree_update |= properties.UpdateInnerBorderRadiusClip(
767 context.current.clip, context.current.transform, inner_border);
768 current_clip = properties.InnerBorderRadiusClip();
769 } else {
770 context.force_subtree_update |= properties.ClearInnerBorderRadiusClip();
771 }
772
773 context.force_subtree_update |=
774 properties.UpdateOverflowClip(current_clip, context.current.transform,
775 FloatRoundedRect(FloatRect(clip_rect)));
776 } 823 }
777 824
778 const auto* properties = object.PaintProperties(); 825 const auto* properties = object.PaintProperties();
779 if (properties && properties->OverflowClip()) 826 if (properties && properties->OverflowClip())
780 context.current.clip = properties->OverflowClip(); 827 context.current.clip = properties->OverflowClip();
781 } 828 }
782 829
783 static FloatPoint PerspectiveOrigin(const LayoutBox& box) { 830 static FloatPoint PerspectiveOrigin(const LayoutBox& box) {
784 const ComputedStyle& style = box.StyleRef(); 831 const ComputedStyle& style = box.StyleRef();
785 // Perspective origin has no effect without perspective. 832 // Perspective origin has no effect without perspective.
786 DCHECK(style.HasPerspective()); 833 DCHECK(style.HasPerspective());
787 FloatSize border_box_size(box.Size()); 834 FloatSize border_box_size(box.Size());
788 return FloatPoint( 835 return FloatPoint(
789 FloatValueForLength(style.PerspectiveOriginX(), border_box_size.Width()), 836 FloatValueForLength(style.PerspectiveOriginX(), border_box_size.Width()),
790 FloatValueForLength(style.PerspectiveOriginY(), 837 FloatValueForLength(style.PerspectiveOriginY(),
791 border_box_size.Height())); 838 border_box_size.Height()));
792 } 839 }
793 840
841 static bool NeedsPaintPropertiesForPerspective(const LayoutObject& object) {
842 return object.IsBox() && object.StyleRef().HasPerspective();
843 }
844
794 void PaintPropertyTreeBuilder::UpdatePerspective( 845 void PaintPropertyTreeBuilder::UpdatePerspective(
795 const LayoutObject& object, 846 const LayoutObject& object,
796 PaintPropertyTreeBuilderContext& context) { 847 PaintPropertyTreeBuilderContext& context) {
797 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 848 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
798 const ComputedStyle& style = object.StyleRef(); 849 if (NeedsPaintPropertiesForPerspective(object)) {
799 if (object.IsBox() && style.HasPerspective()) { 850 const ComputedStyle& style = object.StyleRef();
800 // The perspective node must not flatten (else nothing will get 851 // The perspective node must not flatten (else nothing will get
801 // perspective), but it should still extend the rendering context as 852 // perspective), but it should still extend the rendering context as
802 // most transform nodes do. 853 // most transform nodes do.
803 TransformationMatrix matrix = 854 TransformationMatrix matrix =
804 TransformationMatrix().ApplyPerspective(style.Perspective()); 855 TransformationMatrix().ApplyPerspective(style.Perspective());
805 FloatPoint3D origin = PerspectiveOrigin(ToLayoutBox(object)) + 856 FloatPoint3D origin = PerspectiveOrigin(ToLayoutBox(object)) +
806 ToLayoutSize(context.current.paint_offset); 857 ToLayoutSize(context.current.paint_offset);
807 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 858 auto& properties = *object.GetMutableForPainting().PaintProperties();
808 context.force_subtree_update |= properties.UpdatePerspective( 859 context.force_subtree_update |= properties.UpdatePerspective(
809 context.current.transform, matrix, origin, 860 context.current.transform, matrix, origin,
810 context.current.should_flatten_inherited_transform, 861 context.current.should_flatten_inherited_transform,
811 context.current.rendering_context_id); 862 context.current.rendering_context_id);
812 } else { 863 } else {
813 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 864 if (auto* properties = object.GetMutableForPainting().PaintProperties())
814 context.force_subtree_update |= properties->ClearPerspective(); 865 context.force_subtree_update |= properties->ClearPerspective();
815 } 866 }
816 } 867 }
817 868
818 const auto* properties = object.PaintProperties(); 869 const auto* properties = object.PaintProperties();
819 if (properties && properties->Perspective()) { 870 if (properties && properties->Perspective()) {
820 context.current.transform = properties->Perspective(); 871 context.current.transform = properties->Perspective();
821 context.current.should_flatten_inherited_transform = false; 872 context.current.should_flatten_inherited_transform = false;
822 } 873 }
823 } 874 }
824 875
876 static bool NeedsPaintPropertiesForSVGLocalToBorderBoxTransform(
877 const LayoutObject& object) {
878 return object.IsSVGRoot();
879 }
880
825 void PaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform( 881 void PaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform(
826 const LayoutObject& object, 882 const LayoutObject& object,
827 PaintPropertyTreeBuilderContext& context) { 883 PaintPropertyTreeBuilderContext& context) {
828 if (!object.IsSVGRoot()) 884 if (!object.IsSVGRoot())
829 return; 885 return;
830 886
831 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 887 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
832 AffineTransform transform_to_border_box = 888 AffineTransform transform_to_border_box =
833 SVGRootPainter(ToLayoutSVGRoot(object)) 889 SVGRootPainter(ToLayoutSVGRoot(object))
834 .TransformToPixelSnappedBorderBox(context.current.paint_offset); 890 .TransformToPixelSnappedBorderBox(context.current.paint_offset);
835 if (!transform_to_border_box.IsIdentity()) { 891 if (NeedsPaintPropertiesForSVGLocalToBorderBoxTransform(object)) {
836 auto& properties = object.GetMutableForPainting().EnsurePaintProperties(); 892 auto& properties = *object.GetMutableForPainting().PaintProperties();
837 context.force_subtree_update |= 893 context.force_subtree_update |=
838 properties.UpdateSvgLocalToBorderBoxTransform( 894 properties.UpdateSvgLocalToBorderBoxTransform(
839 context.current.transform, transform_to_border_box, 895 context.current.transform, transform_to_border_box,
840 FloatPoint3D()); 896 FloatPoint3D());
841 } else { 897 } else {
842 if (auto* properties = object.GetMutableForPainting().PaintProperties()) { 898 if (auto* properties = object.GetMutableForPainting().PaintProperties()) {
843 context.force_subtree_update |= 899 context.force_subtree_update |=
844 properties->ClearSvgLocalToBorderBoxTransform(); 900 properties->ClearSvgLocalToBorderBoxTransform();
845 } 901 }
846 } 902 }
(...skipping 16 matching lines...) Expand all
863 // The current main thread scrolling reasons implementation only changes 919 // The current main thread scrolling reasons implementation only changes
864 // reasons at frame boundaries, so we can early-out when not at a LayoutView. 920 // reasons at frame boundaries, so we can early-out when not at a LayoutView.
865 // TODO(pdr): Need to find a solution to the style-related main thread 921 // TODO(pdr): Need to find a solution to the style-related main thread
866 // scrolling reasons such as opacity and transform which violate this. 922 // scrolling reasons such as opacity and transform which violate this.
867 if (!object.IsLayoutView()) 923 if (!object.IsLayoutView())
868 return ancestor_reasons; 924 return ancestor_reasons;
869 return GetMainThreadScrollingReasons(*object.GetFrameView(), 925 return GetMainThreadScrollingReasons(*object.GetFrameView(),
870 ancestor_reasons); 926 ancestor_reasons);
871 } 927 }
872 928
929 static bool NeedsPaintPropertiesForScroll(const LayoutObject& object) {
930 if (object.HasOverflowClip()) {
931 const LayoutBox& box = ToLayoutBox(object);
932 auto* scrollable_area = box.GetScrollableArea();
933 IntSize scroll_offset = box.ScrolledContentOffset();
934 if (!scroll_offset.IsZero() || scrollable_area->ScrollsOverflow())
935 return true;
936 }
937 return false;
938 }
939
873 void PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation( 940 void PaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation(
874 const LayoutObject& object, 941 const LayoutObject& object,
875 PaintPropertyTreeBuilderContext& context) { 942 PaintPropertyTreeBuilderContext& context) {
876 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 943 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
877 bool needs_scroll_properties = false; 944 if (NeedsPaintPropertiesForScroll(object)) {
878 if (object.HasOverflowClip()) { 945 const LayoutBox& box = ToLayoutBox(object);
946 auto* scrollable_area = box.GetScrollableArea();
947 IntSize scroll_offset = box.ScrolledContentOffset();
948 auto& properties = *object.GetMutableForPainting().PaintProperties();
949
950 IntSize scroll_clip = scrollable_area->VisibleContentRect().Size();
951 IntSize scroll_bounds = scrollable_area->ContentsSize();
952 bool user_scrollable_horizontal =
953 scrollable_area->UserInputScrollable(kHorizontalScrollbar);
954 bool user_scrollable_vertical =
955 scrollable_area->UserInputScrollable(kVerticalScrollbar);
956
879 auto ancestor_reasons = 957 auto ancestor_reasons =
880 context.current.scroll->GetMainThreadScrollingReasons(); 958 context.current.scroll->GetMainThreadScrollingReasons();
881 auto reasons = GetMainThreadScrollingReasons(object, ancestor_reasons); 959 auto reasons = GetMainThreadScrollingReasons(object, ancestor_reasons);
882 bool scroll_node_needed_for_main_thread_reasons =
883 ancestor_reasons != reasons;
884 960
885 const LayoutBox& box = ToLayoutBox(object); 961 // Main thread scrolling reasons depend on their ancestor's reasons
886 auto* scrollable_area = box.GetScrollableArea(); 962 // so ensure the entire subtree is updated when reasons change.
887 IntSize scroll_offset = box.ScrolledContentOffset(); 963 if (auto* existing_scroll_translation = properties.ScrollTranslation()) {
888 if (scroll_node_needed_for_main_thread_reasons || 964 auto* existing_scroll_node = existing_scroll_translation->ScrollNode();
889 !scroll_offset.IsZero() || scrollable_area->ScrollsOverflow()) { 965 if (existing_scroll_node->GetMainThreadScrollingReasons() != reasons)
890 needs_scroll_properties = true; 966 context.force_subtree_update = true;
891 auto& properties = 967 }
892 object.GetMutableForPainting().EnsurePaintProperties();
893 968
894 IntSize scroll_clip = scrollable_area->VisibleContentRect().Size(); 969 CompositorElementId compositor_element_id =
895 IntSize scroll_bounds = scrollable_area->ContentsSize(); 970 CreateDomNodeBasedCompositorElementId(object);
896 bool user_scrollable_horizontal = 971 TransformationMatrix matrix = TransformationMatrix().Translate(
897 scrollable_area->UserInputScrollable(kHorizontalScrollbar); 972 -scroll_offset.Width(), -scroll_offset.Height());
898 bool user_scrollable_vertical = 973 context.force_subtree_update |= properties.UpdateScrollTranslation(
899 scrollable_area->UserInputScrollable(kVerticalScrollbar); 974 context.current.transform, matrix, FloatPoint3D(),
900 975 context.current.should_flatten_inherited_transform,
901 // Main thread scrolling reasons depend on their ancestor's reasons 976 context.current.rendering_context_id, kCompositingReasonNone,
902 // so ensure the entire subtree is updated when reasons change. 977 compositor_element_id, context.current.scroll, scroll_clip,
903 if (auto* existing_scroll_translation = 978 scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical,
904 properties.ScrollTranslation()) { 979 reasons, scrollable_area);
905 auto* existing_scroll_node = 980 } else {
906 existing_scroll_translation->ScrollNode();
907 if (existing_scroll_node->GetMainThreadScrollingReasons() != reasons)
908 context.force_subtree_update = true;
909 }
910
911 CompositorElementId compositor_element_id =
912 CreateDomNodeBasedCompositorElementId(object);
913 TransformationMatrix matrix = TransformationMatrix().Translate(
914 -scroll_offset.Width(), -scroll_offset.Height());
915 context.force_subtree_update |= properties.UpdateScrollTranslation(
916 context.current.transform, matrix, FloatPoint3D(),
917 context.current.should_flatten_inherited_transform,
918 context.current.rendering_context_id, kCompositingReasonNone,
919 compositor_element_id, context.current.scroll, scroll_clip,
920 scroll_bounds, user_scrollable_horizontal, user_scrollable_vertical,
921 reasons, scrollable_area);
922 }
923 }
924
925 if (!needs_scroll_properties) {
926 // Ensure pre-existing properties are cleared. 981 // Ensure pre-existing properties are cleared.
927 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 982 if (auto* properties = object.GetMutableForPainting().PaintProperties())
928 context.force_subtree_update |= properties->ClearScrollTranslation(); 983 context.force_subtree_update |= properties->ClearScrollTranslation();
929 } 984 }
930 } 985 }
931 986
932 if (object.PaintProperties() && 987 if (object.PaintProperties() &&
933 object.PaintProperties()->ScrollTranslation()) { 988 object.PaintProperties()->ScrollTranslation()) {
934 context.current.transform = object.PaintProperties()->ScrollTranslation(); 989 context.current.transform = object.PaintProperties()->ScrollTranslation();
935 context.current.scroll = context.current.transform->ScrollNode(); 990 context.current.scroll = context.current.transform->ScrollNode();
936 context.current.should_flatten_inherited_transform = false; 991 context.current.should_flatten_inherited_transform = false;
937 } 992 }
938 } 993 }
939 994
995 static bool NeedsPaintPropertiesForCssClipFixedPosition(
996 const LayoutObject& object) {
997 return !object.IsLayoutView() && !object.CanContainFixedPositionObjects() &&
998 NeedsPaintPropertiesForCssClip(object);
999 }
1000
940 void PaintPropertyTreeBuilder::UpdateOutOfFlowContext( 1001 void PaintPropertyTreeBuilder::UpdateOutOfFlowContext(
941 const LayoutObject& object, 1002 const LayoutObject& object,
942 PaintPropertyTreeBuilderContext& context) { 1003 PaintPropertyTreeBuilderContext& context) {
943 if (object.IsLayoutBlock()) 1004 if (object.IsLayoutBlock())
944 context.paint_offset_for_float = context.current.paint_offset; 1005 context.paint_offset_for_float = context.current.paint_offset;
945 1006
946 if (object.CanContainAbsolutePositionObjects()) { 1007 if (object.CanContainAbsolutePositionObjects()) {
947 context.absolute_position = context.current; 1008 context.absolute_position = context.current;
948 context.container_for_absolute_position = &object; 1009 context.container_for_absolute_position = &object;
949 } 1010 }
950 1011
951 if (object.IsLayoutView()) { 1012 if (object.IsLayoutView()) {
952 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { 1013 if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) {
953 const auto* initial_fixed_transform = context.fixed_position.transform; 1014 const auto* initial_fixed_transform = context.fixed_position.transform;
954 const auto* initial_fixed_scroll = context.fixed_position.scroll; 1015 const auto* initial_fixed_scroll = context.fixed_position.scroll;
955 1016
956 context.fixed_position = context.current; 1017 context.fixed_position = context.current;
957 1018
958 // Fixed position transform and scroll nodes should not be affected. 1019 // Fixed position transform and scroll nodes should not be affected.
959 context.fixed_position.transform = initial_fixed_transform; 1020 context.fixed_position.transform = initial_fixed_transform;
960 context.fixed_position.scroll = initial_fixed_scroll; 1021 context.fixed_position.scroll = initial_fixed_scroll;
961 } 1022 }
962 } else if (object.CanContainFixedPositionObjects()) { 1023 } else if (object.CanContainFixedPositionObjects()) {
963 context.fixed_position = context.current; 1024 context.fixed_position = context.current;
964 } else if (object.GetMutableForPainting().PaintProperties() && 1025 } else if (object.GetMutableForPainting().PaintProperties() &&
965 object.PaintProperties()->CssClip()) { 1026 object.PaintProperties()->CssClip()) {
1027 CHECK(NeedsPaintPropertiesForCssClipFixedPosition(object));
966 // CSS clip applies to all descendants, even if this object is not a 1028 // CSS clip applies to all descendants, even if this object is not a
967 // containing block ancestor of the descendant. It is okay for 1029 // containing block ancestor of the descendant. It is okay for
968 // absolute-position descendants because having CSS clip implies being 1030 // absolute-position descendants because having CSS clip implies being
969 // absolute position container. However for fixed-position descendants we 1031 // absolute position container. However for fixed-position descendants we
970 // need to insert the clip here if we are not a containing block ancestor of 1032 // need to insert the clip here if we are not a containing block ancestor of
971 // them. 1033 // them.
972 auto* css_clip = 1034 auto& properties = *object.GetMutableForPainting().PaintProperties();
973 object.GetMutableForPainting().PaintProperties()->CssClip(); 1035 auto* css_clip = properties.CssClip();
974 1036
975 // Before we actually create anything, check whether in-flow context and 1037 // Before we actually create anything, check whether in-flow context and
976 // fixed-position context has exactly the same clip. Reuse if possible. 1038 // fixed-position context has exactly the same clip. Reuse if possible.
977 if (context.fixed_position.clip == css_clip->Parent()) { 1039 if (context.fixed_position.clip == css_clip->Parent()) {
978 context.fixed_position.clip = css_clip; 1040 context.fixed_position.clip = css_clip;
979 } else { 1041 } else {
980 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 1042 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
981 auto& properties =
982 object.GetMutableForPainting().EnsurePaintProperties();
983 context.force_subtree_update |= properties.UpdateCssClipFixedPosition( 1043 context.force_subtree_update |= properties.UpdateCssClipFixedPosition(
984 context.fixed_position.clip, 1044 context.fixed_position.clip,
985 const_cast<TransformPaintPropertyNode*>( 1045 const_cast<TransformPaintPropertyNode*>(
986 css_clip->LocalTransformSpace()), 1046 css_clip->LocalTransformSpace()),
987 css_clip->ClipRect()); 1047 css_clip->ClipRect());
988 } 1048 }
989 const auto* properties = object.PaintProperties(); 1049 if (properties.CssClipFixedPosition())
990 if (properties && properties->CssClipFixedPosition()) 1050 context.fixed_position.clip = properties.CssClipFixedPosition();
991 context.fixed_position.clip = properties->CssClipFixedPosition();
992 return; 1051 return;
993 } 1052 }
994 } 1053 }
995 1054
996 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) { 1055 if (object.NeedsPaintPropertyUpdate() || context.force_subtree_update) {
997 if (auto* properties = object.GetMutableForPainting().PaintProperties()) 1056 if (auto* properties = object.GetMutableForPainting().PaintProperties())
998 context.force_subtree_update |= properties->ClearCssClipFixedPosition(); 1057 context.force_subtree_update |= properties->ClearCssClipFixedPosition();
999 } 1058 }
1000 } 1059 }
1001 1060
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 box.HasClip() || 1163 box.HasClip() ||
1105 // Relative lengths (e.g., percentage values) in transform, perspective, 1164 // Relative lengths (e.g., percentage values) in transform, perspective,
1106 // transform-origin, and perspective-origin can depend on the size of the 1165 // transform-origin, and perspective-origin can depend on the size of the
1107 // frame rect, so force a property update if it changes. TODO(pdr): We 1166 // frame rect, so force a property update if it changes. TODO(pdr): We
1108 // only need to update properties if there are relative lengths. 1167 // only need to update properties if there are relative lengths.
1109 box.StyleRef().HasTransform() || box.StyleRef().HasPerspective() || 1168 box.StyleRef().HasTransform() || box.StyleRef().HasPerspective() ||
1110 box_generates_property_nodes_for_mask_and_clip_path) 1169 box_generates_property_nodes_for_mask_and_clip_path)
1111 box.GetMutableForPainting().SetNeedsPaintPropertyUpdate(); 1170 box.GetMutableForPainting().SetNeedsPaintPropertyUpdate();
1112 } 1171 }
1113 1172
1173 void PaintPropertyTreeBuilder::UpdatePaintProperties(
1174 const LayoutObject& object) {
1175 if (NeedsPaintPropertiesForPaintOffsetTranslation(object) ||
1176 NeedsPaintPropertiesForTransform(object) ||
1177 NeedsPaintPropertiesForEffect(object) ||
1178 NeedsPaintPropertiesForNonRootSVG(object) ||
1179 NeedsPaintPropertiesForFilter(object) ||
1180 NeedsPaintPropertiesForFilter(object) ||
1181 NeedsPaintPropertiesForCssClip(object) ||
1182 NeedsPaintPropertiesForScrollbarPaintOffset(object) ||
1183 NeedsPaintPropertiesForOverflowScroll(object) ||
1184 NeedsPaintPropertiesForPerspective(object) ||
1185 NeedsPaintPropertiesForSVGLocalToBorderBoxTransform(object) ||
1186 NeedsPaintPropertiesForScroll(object) ||
1187 NeedsPaintPropertiesForCssClipFixedPosition(object))
1188 object.GetMutableForPainting().EnsurePaintProperties();
1189 else
1190 object.GetMutableForPainting().ClearPaintProperties();
1191 }
1192
1114 void PaintPropertyTreeBuilder::UpdatePropertiesForSelf( 1193 void PaintPropertyTreeBuilder::UpdatePropertiesForSelf(
1115 const LayoutObject& object, 1194 const LayoutObject& object,
1116 PaintPropertyTreeBuilderContext& context) { 1195 PaintPropertyTreeBuilderContext& context) {
1117 if (object.IsSVGHiddenContainer()) { 1196 if (object.IsSVGHiddenContainer()) {
1118 // SVG resources are painted within one or more other locations in the 1197 // SVG resources are painted within one or more other locations in the
1119 // SVG during paint, and hence have their own independent paint property 1198 // SVG during paint, and hence have their own independent paint property
1120 // trees, paint offset, etc. 1199 // trees, paint offset, etc.
1121 context = PaintPropertyTreeBuilderContext(); 1200 context = PaintPropertyTreeBuilderContext();
1122 } 1201 }
1123 1202
1203 UpdatePaintProperties(object);
1204
1124 // This is not in FindObjectPropertiesNeedingUpdateScope because paint offset 1205 // This is not in FindObjectPropertiesNeedingUpdateScope because paint offset
1125 // can change without needsPaintPropertyUpdate. 1206 // can change without needsPaintPropertyUpdate.
1126 UpdateForObjectLocationAndSize(object, context); 1207 UpdateForObjectLocationAndSize(object, context);
1127 1208
1128 #if DCHECK_IS_ON() 1209 #if DCHECK_IS_ON()
1129 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(object, 1210 FindObjectPropertiesNeedingUpdateScope check_needs_update_scope(object,
1130 context); 1211 context);
1131 #endif 1212 #endif
1132 1213
1133 if (object.IsBoxModelObject() || object.IsSVG()) { 1214 if (object.IsBoxModelObject() || object.IsSVG()) {
(...skipping 23 matching lines...) Expand all
1157 UpdateOverflowClip(object, context); 1238 UpdateOverflowClip(object, context);
1158 UpdatePerspective(object, context); 1239 UpdatePerspective(object, context);
1159 UpdateSvgLocalToBorderBoxTransform(object, context); 1240 UpdateSvgLocalToBorderBoxTransform(object, context);
1160 UpdateScrollAndScrollTranslation(object, context); 1241 UpdateScrollAndScrollTranslation(object, context);
1161 UpdateOutOfFlowContext(object, context); 1242 UpdateOutOfFlowContext(object, context);
1162 1243
1163 context.force_subtree_update |= object.SubtreeNeedsPaintPropertyUpdate(); 1244 context.force_subtree_update |= object.SubtreeNeedsPaintPropertyUpdate();
1164 } 1245 }
1165 1246
1166 } // namespace blink 1247 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698