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

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

Powered by Google App Engine
This is Rietveld 408576698