X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=src%2Fthird_party%2FWebKit%2FSource%2Fcore%2Frendering%2FRenderLayer.cpp;h=594ded352958d09798aed05c5594dc16e736b907;hb=ff3e2503a20db9193d323c1d19c38c68004dec4a;hp=bf2f39420dadded07e16b9b51166dcd65e77b2a9;hpb=7338fba38ba696536d1cc9d389afd716a6ab2fe6;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/third_party/WebKit/Source/core/rendering/RenderLayer.cpp b/src/third_party/WebKit/Source/core/rendering/RenderLayer.cpp index bf2f394..594ded3 100644 --- a/src/third_party/WebKit/Source/core/rendering/RenderLayer.cpp +++ b/src/third_party/WebKit/Source/core/rendering/RenderLayer.cpp @@ -52,12 +52,12 @@ #include "core/css/PseudoStyleRequest.h" #include "core/dom/Document.h" #include "core/dom/shadow/ShadowRoot.h" -#include "core/html/HTMLFrameElement.h" +#include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h" #include "core/frame/Frame.h" #include "core/frame/FrameView.h" -#include "core/page/Page.h" #include "core/frame/Settings.h" -#include "core/frame/animation/AnimationController.h" +#include "core/html/HTMLFrameElement.h" +#include "core/page/Page.h" #include "core/page/scrolling/ScrollingCoordinator.h" #include "core/rendering/ColumnInfo.h" #include "core/rendering/CompositedLayerMapping.h" @@ -95,10 +95,17 @@ using namespace std; namespace WebCore { +namespace { + +static CompositingQueryMode gCompositingQueryMode = + CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases; + +} // namespace + using namespace HTMLNames; RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type) - : m_isOverflowOnlyLayer(type == OverflowClipLayer) + : m_layerType(type) , m_hasSelfPaintingLayerDescendant(false) , m_hasSelfPaintingLayerDescendantDirty(false) , m_hasOutOfFlowPositionedDescendant(false) @@ -127,6 +134,7 @@ RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type) , m_staticInlinePosition(0) , m_staticBlockPosition(0) , m_enclosingPaginationLayer(0) + , m_3dRenderingContextRoot(0) , m_groupedMapping(0) , m_repainter(renderer) , m_clipper(renderer) @@ -156,6 +164,11 @@ RenderLayer::~RenderLayer() removeFilterInfoIfNeeded(); + if (groupedMapping()) { + groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this); + setGroupedMapping(0); + } + // Child layers will be deleted by their corresponding render objects, so // we don't need to delete them ourselves. @@ -164,8 +177,10 @@ RenderLayer::~RenderLayer() String RenderLayer::debugName() const { - if (isReflection()) + if (isReflection()) { + ASSERT(m_reflectionInfo); return m_reflectionInfo->debugName(); + } return renderer()->debugName(); } @@ -178,9 +193,11 @@ RenderLayerCompositor* RenderLayer::compositor() const void RenderLayer::contentChanged(ContentChangeType changeType) { + DisableCompositingQueryAsserts disabler; + // This can get called when video becomes accelerated, so the layers may change. - if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this)) - compositor()->setCompositingLayersNeedRebuild(); + if (changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) + compositor()->updateLayerCompositingState(this); if (m_compositedLayerMapping) m_compositedLayerMapping->contentChanged(changeType); @@ -196,6 +213,8 @@ bool RenderLayer::paintsWithFilters() const if (!renderer()->hasFilter()) return false; + // https://code.google.com/p/chromium/issues/detail?id=343759 + DisableCompositingQueryAsserts disabler; if (compositingState() != PaintsIntoOwnBacking) return true; @@ -238,6 +257,11 @@ LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags) { TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout"); + + // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues + // https://code.google.com/p/chromium/issues/detail?id=343756 + DisableCompositingQueryAsserts disabler; + RenderGeometryMap geometryMap(UseTransforms); if (this != rootLayer) geometryMap.pushMappingsToAncestor(parent(), 0); @@ -474,6 +498,9 @@ void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap if (flags & HasSeenViewportConstrainedAncestor || (flags & IsOverflowScroll && flags & HasSeenAncestorWithOverflowClip && !m_canSkipRepaintRectsUpdateOnScroll)) { + // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues + // https://code.google.com/p/chromium/issues/detail?id=343756 + DisableCompositingQueryAsserts disabler; // FIXME: We could track the repaint container as we walk down the tree. repainter().computeRepaintRects(renderer()->containerForRepaint(), geometryMap); } else { @@ -524,20 +551,27 @@ void RenderLayer::updateTransform() dirty3DTransformedDescendantStatus(); } +// Note: this function assumes that all ancestors have an updated 3d rendering context root. +void RenderLayer::update3dRenderingContext() +{ + m_3dRenderingContextRoot = 0; + + if (!shouldFlattenTransform()) + m_3dRenderingContextRoot = this; + + if (RenderObject* containingBlock = renderer()->containingBlock()) { + if (RenderLayer* ancestorLayer = containingBlock->enclosingLayer()) { + if (!ancestorLayer->shouldFlattenTransform()) + m_3dRenderingContextRoot = ancestorLayer->renderingContextRoot(); + } + } +} + TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const { if (!m_transform) return TransformationMatrix(); - // FIXME: handle this under web-animations - if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled() && renderer()->style()->isRunningAcceleratedAnimation()) { - TransformationMatrix currTransform; - RefPtr style = renderer()->animation().getAnimatedStyleForRenderer(renderer()); - style->applyTransform(currTransform, renderBox()->pixelSnappedBorderBoxRect().size(), applyOrigin); - makeMatrixRenderable(currTransform, canRender3DTransforms()); - return currTransform; - } - // m_transform includes transform-origin, so we need to recompute the transform here. if (applyOrigin == RenderStyle::ExcludeTransformOrigin) { RenderBox* box = renderBox(); @@ -600,8 +634,7 @@ static bool checkContainingBlockChainForPagination(RenderLayerModelObject* rende bool RenderLayer::useRegionBasedColumns() const { - const Settings* settings = renderer()->document().settings(); - return settings && settings->regionBasedColumnsEnabled(); + return renderer()->document().regionBasedColumnsEnabled(); } void RenderLayer::updatePagination() @@ -1050,6 +1083,8 @@ const RenderLayer* RenderLayer::compositingContainer() const // any other use cases should probably have an API between the non-compositing and compositing sides of code. RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf) const { + ASSERT(isAllowedToQueryCompositingState()); + if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) return const_cast(this); @@ -1063,6 +1098,8 @@ RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const { + ASSERT(isAllowedToQueryCompositingState()); + if ((includeSelf == IncludeSelf) && (compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking)) return const_cast(this); @@ -1076,6 +1113,8 @@ RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot i RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const { + ASSERT(isAllowedToQueryCompositingState()); + if (!renderer()->acceleratedCompositingForOverflowScrollEnabled()) return 0; @@ -1476,7 +1515,7 @@ static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLay // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread // may need to be revisited in a future patch. // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute, - // since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be + // since localToAbsolute maps the coordinates from flow thread to regions coordinates and regions can be // positioned in a completely different place in the viewport (RenderView). if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) { // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling @@ -1656,6 +1695,7 @@ void RenderLayer::didUpdateNeedsCompositedScrolling() void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle) { + ASSERT(!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)); if (renderer()->hasReflection()) { if (!m_reflectionInfo) m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(toRenderBox(renderer()))); @@ -1693,11 +1733,11 @@ bool RenderLayer::hasOverflowControls() const return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE); } -void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags) +void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, PaintLayerFlags paintFlags) { OverlapTestRequestMap overlapTestRequests; - LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, region, &overlapTestRequests); + LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, &overlapTestRequests); paintLayer(context, paintingInfo, paintFlags); OverlapTestRequestMap::iterator end = overlapTestRequests.end(); @@ -1802,6 +1842,9 @@ static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlag void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags) { + // https://code.google.com/p/chromium/issues/detail?id=343772 + DisableCompositingQueryAsserts disabler; + if (compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) { // The updatingControlTints() painting pass goes through compositing layers, // but we need to ensure that we don't cache clip rects computed with the wrong root in this case. @@ -1857,7 +1900,7 @@ void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& // Make sure the parent's clip rects have been calculated. ClipRect clipRect = paintingInfo.paintDirtyRect; if (parent()) { - ClipRectsContext clipRectsContext(paintingInfo.rootLayer, paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, + ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip); clipRect = clipper().backgroundClipRect(clipRectsContext); clipRect.intersect(paintingInfo.paintDirtyRect); @@ -2050,7 +2093,7 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) { // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each // fragment should paint. - collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.region, localPaintingInfo.paintDirtyRect, + collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.paintDirtyRect, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation); updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot); @@ -2123,12 +2166,15 @@ void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta); // Apply the transform. - GraphicsContextStateSaver stateSaver(*context); - context->concatCTM(transform.toAffineTransform()); + GraphicsContextStateSaver stateSaver(*context, false); + if (!transform.isIdentity()) { + stateSaver.save(); + context->concatCTM(transform.toAffineTransform()); + } // Now do a paint with the root layer shifted to be us. LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior, - adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.region, paintingInfo.overlapTestRequests); + adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.overlapTestRequests); paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags); } @@ -2156,14 +2202,14 @@ void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* conte } } -void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect& dirtyRect, +void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect, ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot, const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox) { if (!enclosingPaginationLayer() || hasTransform()) { // For unpaginated layers, there is only one fragment. LayerFragment fragment; - ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation); + ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation); clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot); fragments.append(fragment); return; @@ -2175,7 +2221,7 @@ void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate // layers between us and the pagination context. It's important to minimize the number of fragments we need to create and this helps with that. - ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); + ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); LayoutRect layerBoundsInFlowThread; ClipRect backgroundRectInFlowThread; ClipRect foregroundRectInFlowThread; @@ -2204,7 +2250,7 @@ void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents. ClipRect ancestorClipRect = dirtyRect; if (enclosingPaginationLayer()->parent()) { - ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); + ClipRectsContext clipRectsContext(rootLayer, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip); ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipRect(clipRectsContext); ancestorClipRect.intersect(dirtyRect); } @@ -2247,7 +2293,7 @@ void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, c LayerFragments enclosingPaginationFragments; LayoutPoint offsetOfPaginationLayerFromRoot; LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.paintBehavior); - enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.region, paintingInfo.paintDirtyRect, + enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetOfPaginationLayerFromRoot, paintingInfo.subPixelAccumulation, &transformedExtent); @@ -2262,7 +2308,7 @@ void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, c if (parent() != enclosingPaginationLayer()) { enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot); - ClipRectsContext clipRectsContext(enclosingPaginationLayer(), paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, + ClipRectsContext clipRectsContext(enclosingPaginationLayer(), (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip); LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect(); parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot); @@ -2305,7 +2351,7 @@ void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragmen // Paint the background. // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info. - PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer()); + PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); if (localPaintingInfo.clipToDirtyRect) @@ -2363,7 +2409,7 @@ void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const L if (shouldClip) clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect); - PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer()); + PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); if (phase == PaintPhaseForeground) paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests; renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); @@ -2382,7 +2428,7 @@ void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, continue; // Paint our own outline - PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer()); + PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.outlineRect, DoNotIncludeSelfForBorderRadius); renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect); @@ -2402,7 +2448,7 @@ void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, Gr // Paint the mask. // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info. - PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer()); + PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); if (localPaintingInfo.clipToDirtyRect) @@ -2422,7 +2468,7 @@ void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layer clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self. // Paint the the clipped mask. - PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer()); + PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, 0, 0, localPaintingInfo.rootLayer->renderer()); renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))); if (localPaintingInfo.clipToDirtyRect) @@ -2727,7 +2773,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont // Make sure the parent's clip rects have been calculated. if (parent()) { - ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize); + ClipRectsContext clipRectsContext(rootLayer, RootRelativeClipRects, IncludeOverlayScrollbarSize); ClipRect clipRect = clipper().backgroundClipRect(clipRectsContext); // Go ahead and test the enclosing clip now. if (!clipRect.intersects(hitTestLocation)) @@ -2813,7 +2859,7 @@ RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont // Collect the fragments. This will compute the clip rectangles for each layer fragment. LayerFragments layerFragments; - collectFragments(layerFragments, rootLayer, hitTestLocation.region(), hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize); + collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize); if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) { renderer()->updateHitTestResult(result, hitTestLocation.point()); @@ -2896,7 +2942,7 @@ RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLa LayerFragments enclosingPaginationFragments; LayoutPoint offsetOfPaginationLayerFromRoot; LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox); - enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestLocation.region(), hitTestRect, + enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent); for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) { @@ -2910,7 +2956,7 @@ RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLa if (parent() != enclosingPaginationLayer()) { enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot); - ClipRectsContext clipRectsContext(enclosingPaginationLayer(), hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize); + ClipRectsContext clipRectsContext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbarSize); LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect(); parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot); clipRect.intersect(parentClipRect); @@ -3168,10 +3214,10 @@ void RenderLayer::repaintBlockSelectionGaps() RenderBox* box = renderBox(); rect.move(-box->scrolledContentOffset()); if (!scrollableArea()->usesCompositedScrolling()) - rect.intersect(box->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for. + rect.intersect(box->overflowClipRect(LayoutPoint())); } if (renderer()->hasClip()) - rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for. + rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint())); if (!rect.isEmpty()) renderer()->repaintRectangle(rect); } @@ -3332,6 +3378,7 @@ LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, c } LayoutRect unionBounds = boundingBoxRect; + bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (transform() && flags & PretendLayerHasOwnBacking); if (flags & UseLocalClipRectIfPossible) { @@ -3409,6 +3456,8 @@ LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, c CompositingState RenderLayer::compositingState() const { + ASSERT(isAllowedToQueryCompositingState()); + // This is computed procedurally so there is no redundant state variable that // can get out of sync from the real actual compositing state. @@ -3428,6 +3477,13 @@ CompositingState RenderLayer::compositingState() const return PaintsIntoOwnBacking; } +bool RenderLayer::isAllowedToQueryCompositingState() const +{ + if (gCompositingQueryMode == CompositingQueriesAreAllowed) + return true; + return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate; +} + CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping() { if (!m_compositedLayerMapping) { @@ -3473,6 +3529,13 @@ bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking); } +bool RenderLayer::paintsWithBlendMode() const +{ + // https://code.google.com/p/chromium/issues/detail?id=343759 + DisableCompositingQueryAsserts disabler; + return m_blendInfo.hasBlendMode() && compositingState() != PaintsIntoOwnBacking; +} + bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const { if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant()) @@ -3550,7 +3613,7 @@ void RenderLayer::setParent(RenderLayer* parent) bool RenderLayer::shouldBeSelfPaintingLayer() const { - return !m_isOverflowOnlyLayer + return m_layerType == NormalLayer || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars()) || needsCompositedScrolling(); } @@ -3623,16 +3686,9 @@ bool RenderLayer::isVisuallyNonEmpty() const return false; } -void RenderLayer::updateVisibilityAfterStyleChange(const RenderStyle* oldStyle) -{ - if (!oldStyle || (oldStyle->visibility() != renderer()->style()->visibility())) - compositor()->setNeedsUpdateCompositingRequirementsState(); -} - void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle) { - if (oldStyle && (renderer()->style()->position() == oldStyle->position())) - return; + ASSERT(!oldStyle || renderer()->style()->position() != oldStyle->position()); bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition); bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned(); @@ -3683,7 +3739,11 @@ inline bool RenderLayer::needsCompositingLayersRebuiltForClip(const RenderStyle* inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const { ASSERT(newStyle); - return !hasCompositedLayerMapping() && oldStyle && (oldStyle->overflowX() != newStyle->overflowX()) && m_stackingNode->ancestorStackingContainerNode()->layer()->hasCompositingDescendant(); + return !hasCompositedLayerMapping() + && oldStyle + && (oldStyle->overflowX() != newStyle->overflowX()) + && m_stackingNode->ancestorStackingContainerNode() + && m_stackingNode->ancestorStackingContainerNode()->layer()->hasCompositingDescendant(); } inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const @@ -3691,9 +3751,7 @@ inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderSty if (!hasOrHadFilters(oldStyle, newStyle)) return false; - if (RuntimeEnabledFeatures::webAnimationsCSSEnabled() - ? hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter) - : renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)) { + if (hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)) { // When the compositor is performing the filter animation, we shouldn't touch the compositing layers. // All of the layers above us should have been promoted to compositing layers already. @@ -3739,58 +3797,69 @@ void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* updateOrRemoveFilterClients(); // During an accelerated animation, both WebKit and the compositor animate properties. // However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation. - if (hasCompositedLayerMapping() && (RuntimeEnabledFeatures::webAnimationsCSSEnabled() - ? !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter) - : !renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter))) + if (hasCompositedLayerMapping() && !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)) compositedLayerMapping()->updateFilters(renderer()->style()); updateOrRemoveFilterEffectRenderer(); } -void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle) +void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle) { m_stackingNode->updateIsNormalFlowOnly(); if (m_scrollableArea) m_scrollableArea->updateAfterStyleChange(oldStyle); m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle); - updateVisibilityAfterStyleChange(oldStyle); + + if (!oldStyle || oldStyle->visibility() != renderer()->style()->visibility()) { + ASSERT(!oldStyle || diff >= StyleDifferenceRepaint); + compositor()->setNeedsUpdateCompositingRequirementsState(); + } + // Overlay scrollbars can make this layer self-painting so we need // to recompute the bit once scrollbars have been updated. updateSelfPaintingLayer(); - updateOutOfFlowPositioned(oldStyle); - updateReflectionInfo(oldStyle); + if (!oldStyle || renderer()->style()->position() != oldStyle->position()) { + ASSERT(!oldStyle || diff >= StyleDifferenceLayout); + updateOutOfFlowPositioned(oldStyle); + } + + if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) { + ASSERT(!oldStyle || diff >= StyleDifferenceLayout); + updateReflectionInfo(oldStyle); + } if (RuntimeEnabledFeatures::cssCompositingEnabled()) m_blendInfo.updateBlendMode(); updateDescendantDependentFlags(); - updateTransform(); + + if (!oldStyle || !renderer()->style()->transformDataEquivalent(oldStyle)) + updateTransform(); bool didPaintWithFilters = false; - if (paintsWithFilters()) - didPaintWithFilters = true; - updateFilters(oldStyle, renderer()->style()); + { + // https://code.google.com/p/chromium/issues/detail?id=343759 + DisableCompositingQueryAsserts disabler; + if (paintsWithFilters()) + didPaintWithFilters = true; + updateFilters(oldStyle, renderer()->style()); + } + + // FIXME: Remove incremental compositing updates after fixing the chicken/egg issues + // https://code.google.com/p/chromium/issues/detail?id=343756 + DisableCompositingQueryAsserts disabler; const RenderStyle* newStyle = renderer()->style(); - if (compositor()->updateLayerCompositingState(this) - || needsCompositingLayersRebuiltForClip(oldStyle, newStyle) + + compositor()->updateLayerCompositingState(this); + // FIXME: this compositing logic should be pushed into the compositing code, not here. + if (needsCompositingLayersRebuiltForClip(oldStyle, newStyle) || needsCompositingLayersRebuiltForOverflow(oldStyle, newStyle) || needsCompositingLayersRebuiltForFilters(oldStyle, newStyle, didPaintWithFilters) || needsCompositingLayersRebuiltForBlending(oldStyle, newStyle)) { compositor()->setCompositingLayersNeedRebuild(); - } else if (compositingState() == PaintsIntoOwnBacking || compositingState() == HasOwnBackingButPaintsIntoAncestor) { - ASSERT(hasCompositedLayerMapping()); - compositedLayerMapping()->updateGraphicsLayerGeometry(); - } else if (compositingState() == PaintsIntoGroupedBacking) { - ASSERT(compositor()->layerSquashingEnabled()); - ASSERT(groupedMapping()); - // updateGraphicsLayerGeometry() is called to update the squashingLayer in case its size/position has changed. - // FIXME: Make sure to create a layout test that covers this scenario. - // FIXME: It is not expected that any other layers on the compositedLayerMapping would change. we should - // be able to just update the squashing layer only and save a lot of computation. - groupedMapping()->updateGraphicsLayerGeometry(); } } @@ -3869,7 +3938,15 @@ void RenderLayer::updateOrRemoveFilterEffectRenderer() void RenderLayer::filterNeedsRepaint() { - toElement(renderer()->node())->scheduleLayerUpdate(); + { + DeprecatedScheduleStyleRecalcDuringLayout marker(renderer()->document().lifecycle()); + // It's possible for scheduleLayerUpdate to schedule a style recalc, which + // is a problem because this function can be called while performing layout. + // Presumably this represents an illegal data flow of layout or compositing + // information into the style system. + toElement(renderer()->node())->scheduleLayerUpdate(); + } + if (renderer()->view()) { if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout()) renderer()->setShouldDoFullRepaintAfterLayout(true); @@ -3880,31 +3957,45 @@ void RenderLayer::filterNeedsRepaint() void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const { + computeSelfHitTestRects(rects); + for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) + child->addLayerHitTestRects(rects); +} + +void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const +{ if (!size().isEmpty()) { Vector rect; if (renderBox() && renderBox()->scrollsOverflow()) { // For scrolling layers, rects are taken to be in the space of the contents. - // We need to include both the entire contents, and also the bounding box - // of the layer in the space of it's parent (eg. for border / scroll bars). - rect.append(m_scrollableArea->overflowRect()); + // We need to include the bounding box of the layer in the space of its parent + // (eg. for border / scroll bars) and if it's composited then the entire contents + // as well as they may be on another composited layer. Skip reporting contents + // for non-composited layers as they'll get projected to the same layer as the + // bounding box. + if (compositingState() != NotComposited) + rect.append(m_scrollableArea->overflowRect()); + rects.set(this, rect); if (const RenderLayer* parentLayer = parent()) { LayerHitTestRects::iterator iter = rects.find(parentLayer); - if (iter == rects.end()) - iter = rects.add(parentLayer, Vector()).iterator; - iter->value.append(boundingBox(parentLayer)); + if (iter == rects.end()) { + rects.add(parentLayer, Vector()).storedValue->value.append(boundingBox(parentLayer)); + } else { + iter->value.append(boundingBox(parentLayer)); + } } } else { rect.append(localBoundingBox()); rects.set(this, rect); } } - - for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) - child->addLayerHitTestRects(rects); } +DisableCompositingQueryAsserts::DisableCompositingQueryAsserts() + : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { } + } // namespace WebCore #ifndef NDEBUG