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

Side by Side Diff: sky/engine/core/rendering/RenderBox.cpp

Issue 899753003: Walk render tree instead of render layers for paint. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 10 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 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv ed. 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserv ed.
7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 7 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
8 * 8 *
9 * This library is free software; you can redistribute it and/or 9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public 10 * modify it under the terms of the GNU Library General Public
(...skipping 19 matching lines...) Expand all
30 #include <algorithm> 30 #include <algorithm>
31 #include "sky/engine/core/dom/Document.h" 31 #include "sky/engine/core/dom/Document.h"
32 #include "sky/engine/core/editing/htmlediting.h" 32 #include "sky/engine/core/editing/htmlediting.h"
33 #include "sky/engine/core/frame/FrameHost.h" 33 #include "sky/engine/core/frame/FrameHost.h"
34 #include "sky/engine/core/frame/FrameView.h" 34 #include "sky/engine/core/frame/FrameView.h"
35 #include "sky/engine/core/frame/LocalFrame.h" 35 #include "sky/engine/core/frame/LocalFrame.h"
36 #include "sky/engine/core/frame/Settings.h" 36 #include "sky/engine/core/frame/Settings.h"
37 #include "sky/engine/core/html/HTMLElement.h" 37 #include "sky/engine/core/html/HTMLElement.h"
38 #include "sky/engine/core/page/EventHandler.h" 38 #include "sky/engine/core/page/EventHandler.h"
39 #include "sky/engine/core/page/Page.h" 39 #include "sky/engine/core/page/Page.h"
40 #include "sky/engine/core/rendering/FilterEffectRenderer.h"
40 #include "sky/engine/core/rendering/HitTestResult.h" 41 #include "sky/engine/core/rendering/HitTestResult.h"
41 #include "sky/engine/core/rendering/PaintInfo.h" 42 #include "sky/engine/core/rendering/PaintInfo.h"
42 #include "sky/engine/core/rendering/RenderFlexibleBox.h" 43 #include "sky/engine/core/rendering/RenderFlexibleBox.h"
43 #include "sky/engine/core/rendering/RenderGeometryMap.h" 44 #include "sky/engine/core/rendering/RenderGeometryMap.h"
44 #include "sky/engine/core/rendering/RenderInline.h" 45 #include "sky/engine/core/rendering/RenderInline.h"
45 #include "sky/engine/core/rendering/RenderLayer.h" 46 #include "sky/engine/core/rendering/RenderLayer.h"
46 #include "sky/engine/core/rendering/RenderView.h" 47 #include "sky/engine/core/rendering/RenderView.h"
47 #include "sky/engine/platform/LengthFunctions.h" 48 #include "sky/engine/platform/LengthFunctions.h"
48 #include "sky/engine/platform/geometry/FloatQuad.h" 49 #include "sky/engine/platform/geometry/FloatQuad.h"
49 #include "sky/engine/platform/geometry/TransformState.h" 50 #include "sky/engine/platform/geometry/TransformState.h"
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 updateHitTestResult(result, locationInContainer.point() - toLayoutSize(a djustedLocation)); 382 updateHitTestResult(result, locationInContainer.point() - toLayoutSize(a djustedLocation));
382 if (!result.addNodeToRectBasedTestResult(node(), request, locationInCont ainer, boundsRect)) 383 if (!result.addNodeToRectBasedTestResult(node(), request, locationInCont ainer, boundsRect))
383 return true; 384 return true;
384 } 385 }
385 386
386 return false; 387 return false;
387 } 388 }
388 389
389 // --------------------- painting stuff ------------------------------- 390 // --------------------- painting stuff -------------------------------
390 391
391 void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset) 392 static inline bool compareZIndex(RenderBox* first, RenderBox* second)
393 {
394 return first->style()->zIndex() < second->style()->zIndex();
395 }
396
397 void RenderBox::paintLayer(GraphicsContext* context, RenderLayer* rootLayer, con st IntRect& rect)
398 {
399 // If this layer is totally invisible then there is nothing to paint.
400 if (!opacity())
esprehn 2015/02/05 23:47:00 We could actually do this optimization in the hasS
ojan 2015/02/06 00:28:46 Good idea. Added TODO.
401 return;
402
403 LayerPaintingInfo paintingInfo(rootLayer, rect, LayoutSize());
404
405 if (!layer()->paintsWithTransform()) {
406 paintLayerContents(context, paintingInfo, rect);
407 return;
408 }
409
410 TransformationMatrix layerTransform = layer()->renderableTransform();
411 // If the transform can't be inverted, then don't paint anything.
412 if (!layerTransform.isInvertible())
413 return;
414
415 // If we have a transparency layer enclosing us and we are the root of a tra nsform, then we need to establish the transparency
416 // layer from the parent now, assuming there is a parent
417 if (layer()->isTransparent()) {
418 if (layer()->parent())
419 layer()->parent()->beginTransparencyLayers(context, paintingInfo.roo tLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
420 else
421 layer()->beginTransparencyLayers(context, paintingInfo.rootLayer, pa intingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
422 }
423
424 // Make sure the parent's clip rects have been calculated.
425 ClipRect clipRect;
426 if (layer()->parent()) {
esprehn 2015/02/05 23:47:00 The root never has a transform, so in a future pat
ojan 2015/02/06 00:28:46 TODOs added.
427 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, PaintingClipRe cts);
428 clipRect = layer()->clipper().backgroundClipRect(clipRectsContext);
429 clipRect.intersect(paintingInfo.paintDirtyRect);
430
431 // Push the parent coordinate space's clip.
432 layer()->parent()->clipToRect(paintingInfo, context, clipRect);
433 }
434
435 // This involves subtracting out the position of the layer in our current co ordinate space, but preserving
436 // the accumulated error for sub-pixel layout.
437 LayoutPoint delta;
438 layer()->convertToLayerCoords(paintingInfo.rootLayer, delta);
439 TransformationMatrix transform(layer()->renderableTransform());
440 IntPoint roundedDelta = roundedIntPoint(delta);
441 transform.translateRight(roundedDelta.x(), roundedDelta.y());
442 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
443
444 // Apply the transform.
445 GraphicsContextStateSaver stateSaver(*context, false);
446 if (!transform.isIdentity()) {
447 stateSaver.save();
448 context->concatCTM(transform.toAffineTransform());
449 }
450
451 // Now do a paint with the root layer shifted to be us.
452 LayerPaintingInfo transformedPaintingInfo(layer(), enclosingIntRect(transfor m.inverse().mapRect(paintingInfo.paintDirtyRect)),
453 adjustedSubPixelAccumulation);
454 paintLayerContents(context, transformedPaintingInfo, rect);
455
456 // Restore the clip.
457 if (layer()->parent())
458 layer()->parent()->restoreClip(context, paintingInfo.paintDirtyRect, cli pRect);
459 }
460
461 void RenderBox::paintLayerContents(GraphicsContext* context, const LayerPainting Info& paintingInfo, const IntRect& rect)
462 {
463 float deviceScaleFactor = blink::deviceScaleFactor(frame());
464 context->setDeviceScaleFactor(deviceScaleFactor);
465
466 GraphicsContext* transparencyLayerContext = context;
467
468 LayoutPoint offsetFromRoot;
469 layer()->convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
470
471 LayoutRect rootRelativeBounds;
472 bool rootRelativeBoundsComputed = false;
473
474 // Apply clip-path to context.
475 GraphicsContextStateSaver clipStateSaver(*context, false);
476
477 // Clip-path, like border radius, must not be applied to the contents of a c omposited-scrolling container.
478 // It must, however, still be applied to the mask layer, so that the composi tor can properly mask the
479 // scrolling contents and scrollbars.
480 if (hasClipPath() && style()) {
esprehn 2015/02/05 23:47:00 The style() null check doesn't make sense, you alw
ojan 2015/02/06 00:28:46 Yup. I had that thought too, but wanted to minimiz
481 ASSERT(style()->clipPath());
482 if (style()->clipPath()->type() == ClipPathOperation::SHAPE) {
483 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style()- >clipPath());
484 if (clipPath->isValid()) {
485 clipStateSaver.save();
486
487 if (!rootRelativeBoundsComputed) {
488 rootRelativeBounds = layer()->physicalBoundingBoxIncludingRe flectionAndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
489 rootRelativeBoundsComputed = true;
490 }
491
492 context->clipPath(clipPath->path(rootRelativeBounds), clipPath-> windRule());
493 }
494 }
495 }
496
497 LayerPaintingInfo localPaintingInfo(paintingInfo);
498 FilterEffectRendererHelper filterPainter(layer()->filterRenderer() && layer( )->paintsWithFilters());
499
500 LayoutRect layerBounds;
501 // FIXME(sky): Remove foregroundRect. It's unused.
502 ClipRect contentRect, foregroundRect;
503 ClipRectsContext clipRectsContext(localPaintingInfo.rootLayer, PaintingClipR ects, localPaintingInfo.subPixelAccumulation);
504 layer()->clipper().calculateRects(clipRectsContext, localPaintingInfo.paintD irtyRect,
505 layerBounds, contentRect, foregroundRect,
506 &offsetFromRoot);
507
508 bool shouldPaintContent = layer()->intersectsDamageRect(layerBounds, content Rect.rect(), localPaintingInfo.rootLayer, &offsetFromRoot);
509
510 bool haveTransparency = layer()->isTransparent();
511
512 if (filterPainter.haveFilterEffect()) {
513 ASSERT(layer()->filterInfo());
514
515 if (!rootRelativeBoundsComputed)
516 rootRelativeBounds = layer()->physicalBoundingBoxIncludingReflection AndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
517
518 if (filterPainter.prepareFilterEffect(layer(), rootRelativeBounds, paint ingInfo.paintDirtyRect)) {
519 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
520 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
521 // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that
522 // beginTransparencyLayers will only create a single lazy transparen cy layer, even though it is called twice in this method.
523 // With deferred filters, we don't need a separate context, but we d o need to do transparency and clipping before starting
524 // filter processing.
525 // FIXME: when the legacy path is removed, remove the transparencyLa yerContext as well.
526 if (haveTransparency) {
527 // If we have a filter and transparency, we have to eagerly star t a transparency layer here, rather than risk a child layer lazily starts one af ter filter processing.
528 layer()->beginTransparencyLayers(context, localPaintingInfo.root Layer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
529 }
530 // We'll handle clipping to the dirty rect before filter rasterizati on.
531 // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
532 // FIXME: It is incorrect to just clip to the damageRect here once m ultiple fragments are involved.
533 layer()->clipToRect(localPaintingInfo, context, contentRect);
534 // Subsequent code should not clip to the dirty rect, since we've al ready
535 // done it above, and doing it later will defeat the outsets.
536 localPaintingInfo.clipToDirtyRect = false;
537
538 context = filterPainter.beginFilterEffect(context);
539 }
540 }
541
542 LayoutPoint layerLocation = toPoint(layerBounds.location() - location() + lo calPaintingInfo.subPixelAccumulation);
543
544 if (shouldPaintContent) {
545 bool contentRectIsEmpty = contentRect.isEmpty();
546
547 // Begin transparency if we have something to paint.
548 if (haveTransparency && !contentRectIsEmpty)
549 layer()->beginTransparencyLayers(transparencyLayerContext, localPain tingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.subPixelAccum ulation);
550
551 // Optimize clipping for the single fragment case.
552 bool shouldClip = localPaintingInfo.clipToDirtyRect && !contentRectIsEmp ty;
553 if (shouldClip)
554 layer()->clipToRect(localPaintingInfo, context, contentRect);
555
556 // TODO(ojan): We probably should have already set shouldPaintContent to false if the rect is empty.
557 if (!contentRectIsEmpty) {
558 Vector<RenderBox*> layers;
559
560 PaintInfo paintInfo(context, pixelSnappedIntRect(contentRect.rect()) , localPaintingInfo.rootLayer->renderer());
561 paint(paintInfo, layerLocation, layers);
562
563 std::stable_sort(layers.begin(), layers.end(), compareZIndex);
564 for (auto& box : layers) {
565 box->paintLayer(context, paintingInfo.rootLayer, rect);
566 }
567 }
568
569 if (shouldClip)
570 layer()->restoreClip(context, localPaintingInfo.paintDirtyRect, cont entRect);
571 }
572
573 if (filterPainter.hasStartedFilterEffect()) {
574 context = filterPainter.applyFilterEffect();
575 layer()->restoreClip(transparencyLayerContext, localPaintingInfo.paintDi rtyRect, contentRect);
576 }
577
578 // Make sure that we now use the original transparency context.
579 ASSERT(transparencyLayerContext == context);
580
581 // End our transparency layer
582 if (haveTransparency && layer()->usedTransparency()) {
583 context->endLayer();
584 context->restore();
585 layer()->clearUsedTransparency();
586 }
587 }
588
589 void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, Vect or<RenderBox*>& layers)
392 { 590 {
393 LayoutPoint adjustedPaintOffset = paintOffset + location(); 591 LayoutPoint adjustedPaintOffset = paintOffset + location();
394 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli ng()) 592 for (RenderObject* child = slowFirstChild(); child; child = child->nextSibli ng())
395 child->paint(paintInfo, adjustedPaintOffset); 593 child->paint(paintInfo, adjustedPaintOffset, layers);
396 } 594 }
397 595
398 void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo) 596 void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
399 { 597 {
400 const FillLayer& bgLayer = style()->backgroundLayers(); 598 const FillLayer& bgLayer = style()->backgroundLayers();
401 Color bgColor = resolveColor(CSSPropertyBackgroundColor); 599 Color bgColor = resolveColor(CSSPropertyBackgroundColor);
402 600
403 paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), B ackgroundBleedNone, this); 601 paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), B ackgroundBleedNone, this);
404 } 602 }
405 603
(...skipping 2282 matching lines...) Expand 10 before | Expand all | Expand 10 after
2688 2886
2689 RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style) 2887 RenderBox::BoxDecorationData::BoxDecorationData(const RenderStyle& style)
2690 { 2888 {
2691 backgroundColor = style.colorIncludingFallback(CSSPropertyBackgroundColor); 2889 backgroundColor = style.colorIncludingFallback(CSSPropertyBackgroundColor);
2692 hasBackground = backgroundColor.alpha() || style.hasBackgroundImage(); 2890 hasBackground = backgroundColor.alpha() || style.hasBackgroundImage();
2693 ASSERT(hasBackground == style.hasBackground()); 2891 ASSERT(hasBackground == style.hasBackground());
2694 hasBorder = style.hasBorder(); 2892 hasBorder = style.hasBorder();
2695 } 2893 }
2696 2894
2697 } // namespace blink 2895 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698