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

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

Issue 899753003: Walk render tree instead of render layers for paint. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: address review comments 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
« no previous file with comments | « sky/engine/core/rendering/RenderLayer.h ('k') | sky/engine/core/rendering/RenderLineBoxList.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 * 3 *
4 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 4 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5 * 5 *
6 * Other contributors: 6 * Other contributors:
7 * Robert O'Callahan <roc+@cs.cmu.edu> 7 * Robert O'Callahan <roc+@cs.cmu.edu>
8 * David Baron <dbaron@fas.harvard.edu> 8 * David Baron <dbaron@fas.harvard.edu>
9 * Christian Biesinger <cbiesinger@web.de> 9 * Christian Biesinger <cbiesinger@web.de>
10 * Randall Jesup <rjesup@wgate.com> 10 * Randall Jesup <rjesup@wgate.com>
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 } 734 }
735 735
736 void RenderLayer::updateStackingNode() 736 void RenderLayer::updateStackingNode()
737 { 737 {
738 if (requiresStackingNode()) 738 if (requiresStackingNode())
739 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this)); 739 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this));
740 else 740 else
741 m_stackingNode = nullptr; 741 m_stackingNode = nullptr;
742 } 742 }
743 743
744 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect)
745 {
746 TRACE_EVENT0("blink", "RenderLayer::paint");
747 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), LayoutSiz e());
748 paintLayer(context, paintingInfo, PaintContent);
749 }
750
751 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye r) 744 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye r)
752 { 745 {
753 if (startLayer == endLayer) 746 if (startLayer == endLayer)
754 return true; 747 return true;
755 748
756 RenderView* view = startLayer->renderer()->view(); 749 RenderView* view = startLayer->renderer()->view();
757 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo ck()) { 750 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlo ck()) {
758 if (currentBlock->layer() == endLayer) 751 if (currentBlock->layer() == endLayer)
759 return true; 752 return true;
760 } 753 }
(...skipping 27 matching lines...) Expand all
788 } 781 }
789 } 782 }
790 783
791 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintD irtyRect, const ClipRect& clipRect) 784 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintD irtyRect, const ClipRect& clipRect)
792 { 785 {
793 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius()) 786 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
794 return; 787 return;
795 context->restore(); 788 context->restore();
796 } 789 }
797 790
798 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
799 {
800 // Non self-painting leaf layers don't need to be painted as their renderer( ) should properly paint itself.
801 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
802 return;
803
804 // If this layer is totally invisible then there is nothing to paint.
805 if (!renderer()->opacity())
806 return;
807
808 if (paintsWithTransform()) {
809 TransformationMatrix layerTransform = renderableTransform();
810 // If the transform can't be inverted, then don't paint anything.
811 if (!layerTransform.isInvertible())
812 return;
813
814 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
815 // layer from the parent now, assuming there is a parent
816 if (isTransparent()) {
817 if (parent())
818 parent()->beginTransparencyLayers(context, paintingInfo.rootLaye r, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
819 else
820 beginTransparencyLayers(context, paintingInfo.rootLayer, paintin gInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
821 }
822
823 // Make sure the parent's clip rects have been calculated.
824 ClipRect clipRect = paintingInfo.paintDirtyRect;
825 if (parent()) {
826 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, PaintingCl ipRects);
827 clipRect = clipper().backgroundClipRect(clipRectsContext);
828 clipRect.intersect(paintingInfo.paintDirtyRect);
829
830 // Push the parent coordinate space's clip.
831 parent()->clipToRect(paintingInfo, context, clipRect);
832 }
833
834 paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
835
836 // Restore the clip.
837 if (parent())
838 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect );
839
840 return;
841 }
842
843 paintLayerContents(context, paintingInfo, paintFlags);
844 }
845
846 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti ngInfo& paintingInfo, PaintLayerFlags paintFlags)
847 {
848 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
849
850 float deviceScaleFactor = blink::deviceScaleFactor(renderer()->frame());
851 context->setDeviceScaleFactor(deviceScaleFactor);
852
853 GraphicsContext* transparencyLayerContext = context;
854
855 m_stackingNode->updateLayerListsIfNeeded();
856
857 LayoutPoint offsetFromRoot;
858 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
859
860 LayoutRect rootRelativeBounds;
861 bool rootRelativeBoundsComputed = false;
862
863 // Apply clip-path to context.
864 GraphicsContextStateSaver clipStateSaver(*context, false);
865 RenderStyle* style = renderer()->style();
866
867 // Clip-path, like border radius, must not be applied to the contents of a c omposited-scrolling container.
868 // It must, however, still be applied to the mask layer, so that the composi tor can properly mask the
869 // scrolling contents and scrollbars.
870 if (renderer()->hasClipPath() && style) {
871 ASSERT(style->clipPath());
872 if (style->clipPath()->type() == ClipPathOperation::SHAPE) {
873 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->c lipPath());
874 if (clipPath->isValid()) {
875 clipStateSaver.save();
876
877 if (!rootRelativeBoundsComputed) {
878 rootRelativeBounds = physicalBoundingBoxIncludingReflectionA ndStackingChildren(paintingInfo.rootLayer, offsetFromRoot);
879 rootRelativeBoundsComputed = true;
880 }
881
882 context->clipPath(clipPath->path(rootRelativeBounds), clipPath-> windRule());
883 }
884 }
885 }
886
887 LayerPaintingInfo localPaintingInfo(paintingInfo);
888 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilte rs());
889
890 LayoutRect layerBounds;
891 // FIXME(sky): Remove foregroundRect. It's unused.
892 ClipRect backgroundRect, foregroundRect;
893 ClipRectsContext clipRectsContext(localPaintingInfo.rootLayer, PaintingClipR ects, localPaintingInfo.subPixelAccumulation);
894 clipper().calculateRects(clipRectsContext, localPaintingInfo.paintDirtyRect,
895 layerBounds, backgroundRect, foregroundRect,
896 &offsetFromRoot);
897
898 bool shouldPaintContent = isSelfPaintingLayer() && intersectsDamageRect(laye rBounds, backgroundRect.rect(), localPaintingInfo.rootLayer, &offsetFromRoot);
899
900 bool haveTransparency = isTransparent();
901
902 if (filterPainter.haveFilterEffect()) {
903 ASSERT(this->filterInfo());
904
905 if (!rootRelativeBoundsComputed)
906 rootRelativeBounds = physicalBoundingBoxIncludingReflectionAndStacki ngChildren(paintingInfo.rootLayer, offsetFromRoot);
907
908 if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, painting Info.paintDirtyRect)) {
909 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
910 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
911 // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that
912 // beginTransparencyLayers will only create a single lazy transparen cy layer, even though it is called twice in this method.
913 // With deferred filters, we don't need a separate context, but we d o need to do transparency and clipping before starting
914 // filter processing.
915 // FIXME: when the legacy path is removed, remove the transparencyLa yerContext as well.
916 if (haveTransparency) {
917 // 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.
918 beginTransparencyLayers(context, localPaintingInfo.rootLayer, pa intingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation);
919 }
920 // We'll handle clipping to the dirty rect before filter rasterizati on.
921 // Filter processing will automatically expand the clip rect and the offscreen to accommodate any filter outsets.
922 // FIXME: It is incorrect to just clip to the damageRect here once m ultiple fragments are involved.
923 clipToRect(localPaintingInfo, context, backgroundRect);
924 // Subsequent code should not clip to the dirty rect, since we've al ready
925 // done it above, and doing it later will defeat the outsets.
926 localPaintingInfo.clipToDirtyRect = false;
927
928 context = filterPainter.beginFilterEffect(context);
929 }
930 }
931
932 LayoutPoint layerLocation = toPoint(layerBounds.location() - renderBoxLocati on() + localPaintingInfo.subPixelAccumulation);
933
934 if (shouldPaintContent) {
935 paintForeground(context, transparencyLayerContext, paintingInfo.paintDir tyRect, haveTransparency,
936 localPaintingInfo, layerLocation, backgroundRect);
937 }
938
939 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, painting Info, paintFlags);
940
941 if (filterPainter.hasStartedFilterEffect()) {
942 context = filterPainter.applyFilterEffect();
943 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
944 }
945
946 // Make sure that we now use the original transparency context.
947 ASSERT(transparencyLayerContext == context);
948
949 // End our transparency layer
950 if (haveTransparency && m_usedTransparency) {
951 context->endLayer();
952 context->restore();
953 m_usedTransparency = false;
954 }
955 }
956
957 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset)
958 {
959 // This involves subtracting out the position of the layer in our current co ordinate space, but preserving
960 // the accumulated error for sub-pixel layout.
961 LayoutPoint delta;
962 convertToLayerCoords(paintingInfo.rootLayer, delta);
963 delta.moveBy(translationOffset);
964 TransformationMatrix transform(renderableTransform());
965 IntPoint roundedDelta = roundedIntPoint(delta);
966 transform.translateRight(roundedDelta.x(), roundedDelta.y());
967 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
968
969 // Apply the transform.
970 GraphicsContextStateSaver stateSaver(*context, false);
971 if (!transform.isIdentity()) {
972 stateSaver.save();
973 context->concatCTM(transform.toAffineTransform());
974 }
975
976 // Now do a paint with the root layer shifted to be us.
977 LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.i nverse().mapRect(paintingInfo.paintDirtyRect)),
978 adjustedSubPixelAccumulation);
979 paintLayerContents(context, transformedPaintingInfo, paintFlags);
980 }
981
982 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* conte xt, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
983 {
984 if (!hasSelfPaintingLayerDescendant())
985 return;
986
987 #if ENABLE(ASSERT)
988 LayerListMutationDetector mutationChecker(m_stackingNode.get());
989 #endif
990
991 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit);
992 while (RenderLayerStackingNode* child = iterator.next()) {
993 child->layer()->paintLayer(context, paintingInfo, paintFlags);
994 }
995 }
996
997 void RenderLayer::paintForeground(GraphicsContext* context, GraphicsContext* tra nsparencyLayerContext,
998 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const L ayerPaintingInfo& localPaintingInfo,
999 LayoutPoint& layerLocation, ClipRect& layerForegroundRect)
1000 {
1001 bool foregroundRectIsEmpty = layerForegroundRect.isEmpty();
1002
1003 // Begin transparency if we have something to paint.
1004 if (haveTransparency && !foregroundRectIsEmpty)
1005 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.root Layer, transparencyPaintDirtyRect, localPaintingInfo.subPixelAccumulation);
1006
1007 // Optimize clipping for the single fragment case.
1008 bool shouldClip = localPaintingInfo.clipToDirtyRect && !foregroundRectIsEmpt y;
1009 if (shouldClip)
1010 clipToRect(localPaintingInfo, context, layerForegroundRect);
1011
1012 // TODO(ojan): We probably should early return at the beginning of this func tion
1013 // if the rect is empty.
1014 if (!foregroundRectIsEmpty) {
1015 PaintInfo paintInfo(context, pixelSnappedIntRect(layerForegroundRect.rec t()), localPaintingInfo.rootLayer->renderer());
1016 renderer()->paint(paintInfo, layerLocation);
1017 }
1018
1019 if (shouldClip)
1020 restoreClip(context, localPaintingInfo.paintDirtyRect, layerForegroundRe ct);
1021 }
1022
1023 static inline LayoutRect frameVisibleRect(RenderObject* renderer) 791 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
1024 { 792 {
1025 FrameView* frameView = renderer->document().view(); 793 FrameView* frameView = renderer->document().view();
1026 if (!frameView) 794 if (!frameView)
1027 return LayoutRect(); 795 return LayoutRect();
1028 796
1029 return frameView->visibleContentRect(); 797 return frameView->visibleContentRect();
1030 } 798 }
1031 799
1032 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result) 800 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
(...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after
1668 } 1436 }
1669 } 1437 }
1670 1438
1671 void showLayerTree(const blink::RenderObject* renderer) 1439 void showLayerTree(const blink::RenderObject* renderer)
1672 { 1440 {
1673 if (!renderer) 1441 if (!renderer)
1674 return; 1442 return;
1675 showLayerTree(renderer->enclosingLayer()); 1443 showLayerTree(renderer->enclosingLayer());
1676 } 1444 }
1677 #endif 1445 #endif
OLDNEW
« no previous file with comments | « sky/engine/core/rendering/RenderLayer.h ('k') | sky/engine/core/rendering/RenderLineBoxList.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698