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

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

Powered by Google App Engine
This is Rietveld 408576698