1/* 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) 5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com) 6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 7 * Copyright (C) 2010, 2012 Google Inc. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Library General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Library General Public License for more details. 18 * 19 * You should have received a copy of the GNU Library General Public License 20 * along with this library; see the file COPYING.LIB. If not, write to 21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA. 23 */ 24 25#include "config.h" 26#include "core/rendering/RenderLayerModelObject.h" 27 28#include "core/frame/LocalFrame.h" 29#include "core/rendering/RenderLayer.h" 30#include "core/rendering/RenderView.h" 31#include "core/rendering/compositing/CompositedLayerMapping.h" 32 33namespace blink { 34 35bool RenderLayerModelObject::s_wasFloating = false; 36 37RenderLayerModelObject::RenderLayerModelObject(ContainerNode* node) 38 : RenderObject(node) 39{ 40} 41 42RenderLayerModelObject::~RenderLayerModelObject() 43{ 44 // Our layer should have been destroyed and cleared by now 45 ASSERT(!hasLayer()); 46 ASSERT(!m_layer); 47} 48 49void RenderLayerModelObject::destroyLayer() 50{ 51 setHasLayer(false); 52 m_layer = nullptr; 53} 54 55void RenderLayerModelObject::createLayer(LayerType type) 56{ 57 ASSERT(!m_layer); 58 m_layer = adoptPtr(new RenderLayer(this, type)); 59 setHasLayer(true); 60 m_layer->insertOnlyThisLayer(); 61} 62 63bool RenderLayerModelObject::hasSelfPaintingLayer() const 64{ 65 return m_layer && m_layer->isSelfPaintingLayer(); 66} 67 68ScrollableArea* RenderLayerModelObject::scrollableArea() const 69{ 70 return m_layer ? m_layer->scrollableArea() : 0; 71} 72 73void RenderLayerModelObject::willBeDestroyed() 74{ 75 if (isPositioned()) { 76 // Don't use this->view() because the document's renderView has been set to 0 during destruction. 77 if (LocalFrame* frame = this->frame()) { 78 if (FrameView* frameView = frame->view()) { 79 if (style()->hasViewportConstrainedPosition()) 80 frameView->removeViewportConstrainedObject(this); 81 } 82 } 83 } 84 85 RenderObject::willBeDestroyed(); 86 87 destroyLayer(); 88} 89 90void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle& newStyle) 91{ 92 s_wasFloating = isFloating(); 93 94 if (RenderStyle* oldStyle = style()) { 95 if (parent() && diff.needsPaintInvalidationLayer()) { 96 if (oldStyle->hasAutoClip() != newStyle.hasAutoClip() 97 || oldStyle->clip() != newStyle.clip()) 98 layer()->clipper().clearClipRectsIncludingDescendants(); 99 } 100 } 101 102 RenderObject::styleWillChange(diff, newStyle); 103} 104 105void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 106{ 107 bool hadTransform = hasTransform(); 108 bool hadLayer = hasLayer(); 109 bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer(); 110 111 RenderObject::styleDidChange(diff, oldStyle); 112 updateFromStyle(); 113 114 LayerType type = layerTypeRequired(); 115 if (type != NoLayer) { 116 if (!layer() && layerCreationAllowedForSubtree()) { 117 if (s_wasFloating && isFloating()) 118 setChildNeedsLayout(); 119 createLayer(type); 120 if (parent() && !needsLayout()) { 121 // FIXME: We should call a specialized version of this function. 122 layer()->updateLayerPositionsAfterLayout(); 123 } 124 } 125 } else if (layer() && layer()->parent()) { 126 setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit. 127 setHasReflection(false); 128 layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer 129 if (s_wasFloating && isFloating()) 130 setChildNeedsLayout(); 131 if (hadTransform) 132 setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); 133 } 134 135 if (layer()) { 136 // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer 137 // from the style. 138 layer()->setLayerType(type); 139 140 layer()->styleChanged(diff, oldStyle); 141 if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting) 142 setChildNeedsLayout(); 143 } 144 145 if (FrameView *frameView = view()->frameView()) { 146 bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition(); 147 bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition(); 148 if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { 149 if (newStyleIsViewportConstained && layer()) 150 frameView->addViewportConstrainedObject(this); 151 else 152 frameView->removeViewportConstrainedObject(this); 153 } 154 } 155} 156 157void RenderLayerModelObject::addLayerHitTestRects(LayerHitTestRects& rects, const RenderLayer* currentLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const 158{ 159 if (hasLayer()) { 160 if (isRenderView()) { 161 // RenderView is handled with a special fast-path, but it needs to know the current layer. 162 RenderObject::addLayerHitTestRects(rects, layer(), LayoutPoint(), LayoutRect()); 163 } else { 164 // Since a RenderObject never lives outside it's container RenderLayer, we can switch 165 // to marking entire layers instead. This may sometimes mark more than necessary (when 166 // a layer is made of disjoint objects) but in practice is a significant performance 167 // savings. 168 layer()->addLayerHitTestRects(rects); 169 } 170 } else { 171 RenderObject::addLayerHitTestRects(rects, currentLayer, layerOffset, containerRect); 172 } 173} 174 175void RenderLayerModelObject::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState) 176{ 177 ASSERT(!needsLayout()); 178 179 if (!shouldCheckForPaintInvalidation(paintInvalidationState)) 180 return; 181 182 bool establishesNewPaintInvalidationContainer = isPaintInvalidationContainer(); 183 const RenderLayerModelObject& newPaintInvalidationContainer = *adjustCompositedContainerForSpecialAncestors(establishesNewPaintInvalidationContainer ? this : &paintInvalidationState.paintInvalidationContainer()); 184 // FIXME: This assert should be re-enabled when we move paint invalidation to after compositing update. crbug.com/360286 185 // ASSERT(&newPaintInvalidationContainer == containerForPaintInvalidation()); 186 187 InvalidationReason reason = invalidatePaintIfNeeded(paintInvalidationState, newPaintInvalidationContainer); 188 clearPaintInvalidationState(paintInvalidationState); 189 190 PaintInvalidationState childTreeWalkState(paintInvalidationState, *this, newPaintInvalidationContainer); 191 if (reason == InvalidationLocationChange || reason == InvalidationFull) 192 childTreeWalkState.setForceCheckForPaintInvalidation(); 193 invalidatePaintOfSubtreesIfNeeded(childTreeWalkState); 194} 195 196void RenderLayerModelObject::setBackingNeedsPaintInvalidationInRect(const LayoutRect& r) const 197{ 198 // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here, 199 // so assert but check that the layer is composited. 200 ASSERT(compositingState() != NotComposited); 201 202 WebInvalidationDebugAnnotations annotations = WebInvalidationDebugAnnotationsNone; 203 if (!hadPaintInvalidation()) 204 annotations = WebInvalidationDebugAnnotationsFirstPaint; 205 // FIXME: The callers assume they are calling a const function but this function has a side effect. 206 const_cast<RenderLayerModelObject*>(this)->setHadPaintInvalidation(); 207 208 // FIXME: generalize accessors to backing GraphicsLayers so that this code is squashing-agnostic. 209 if (layer()->groupedMapping()) { 210 LayoutRect paintInvalidationRect = r; 211 if (GraphicsLayer* squashingLayer = layer()->groupedMapping()->squashingLayer()) { 212 // Note: the subpixel accumulation of layer() does not need to be added here. It is already taken into account. 213 squashingLayer->setNeedsDisplayInRect(pixelSnappedIntRect(paintInvalidationRect), annotations); 214 } 215 } else { 216 layer()->compositedLayerMapping()->setContentsNeedDisplayInRect(r, annotations); 217 } 218} 219 220} // namespace blink 221 222