#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"
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)
, m_staticInlinePosition(0)
, m_staticBlockPosition(0)
, m_enclosingPaginationLayer(0)
+ , m_3dRenderingContextRoot(0)
, m_groupedMapping(0)
, m_repainter(renderer)
, m_clipper(renderer)
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.
String RenderLayer::debugName() const
{
- if (isReflection())
+ if (isReflection()) {
+ ASSERT(m_reflectionInfo);
return m_reflectionInfo->debugName();
+ }
return renderer()->debugName();
}
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);
if (!renderer()->hasFilter())
return false;
+ // https://code.google.com/p/chromium/issues/detail?id=343759
+ DisableCompositingQueryAsserts disabler;
if (compositingState() != PaintsIntoOwnBacking)
return true;
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);
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 {
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<RenderStyle> 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();
bool RenderLayer::useRegionBasedColumns() const
{
- const Settings* settings = renderer()->document().settings();
- return settings && settings->regionBasedColumnsEnabled();
+ return renderer()->document().regionBasedColumnsEnabled();
}
void RenderLayer::updatePagination()
// 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<RenderLayer*>(this);
RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const
{
+ ASSERT(isAllowedToQueryCompositingState());
+
if ((includeSelf == IncludeSelf) && (compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking))
return const_cast<RenderLayer*>(this);
RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const
{
+ ASSERT(isAllowedToQueryCompositingState());
+
if (!renderer()->acceleratedCompositingForOverflowScrollEnabled())
return 0;
// 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
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())));
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();
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.
// 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);
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);
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);
}
}
}
-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;
// 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;
// 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);
}
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);
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);
// 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)
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())));
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);
// 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)
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)
// 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))
// 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());
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) {
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);
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);
}
}
LayoutRect unionBounds = boundingBoxRect;
+
bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (transform() && flags & PretendLayerHasOwnBacking);
if (flags & UseLocalClipRectIfPossible) {
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.
return PaintsIntoOwnBacking;
}
+bool RenderLayer::isAllowedToQueryCompositingState() const
+{
+ if (gCompositingQueryMode == CompositingQueriesAreAllowed)
+ return true;
+ return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCompositingUpdate;
+}
+
CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping()
{
if (!m_compositedLayerMapping) {
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())
bool RenderLayer::shouldBeSelfPaintingLayer() const
{
- return !m_isOverflowOnlyLayer
+ return m_layerType == NormalLayer
|| (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
|| needsCompositedScrolling();
}
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();
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
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.
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();
}
}
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);
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<LayoutRect> 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<LayoutRect>()).iterator;
- iter->value.append(boundingBox(parentLayer));
+ if (iter == rects.end()) {
+ rects.add(parentLayer, Vector<LayoutRect>()).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