1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
|
/*
* Copyright (C) 2009, 2010, 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CompositedLayerMapping_h
#define CompositedLayerMapping_h
#include "core/rendering/RenderLayer.h"
#include "core/rendering/compositing/GraphicsLayerUpdater.h"
#include "platform/geometry/FloatPoint.h"
#include "platform/geometry/FloatPoint3D.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/graphics/GraphicsLayerClient.h"
namespace WebCore {
class RenderLayerCompositor;
// A GraphicsLayerPaintInfo contains all the info needed to paint a partial subtree of RenderLayers into a GraphicsLayer.
struct GraphicsLayerPaintInfo {
RenderLayer* renderLayer;
LayoutRect compositedBounds;
// The clip rect to apply, in the local coordinate space of the squashed layer, when painting it.
IntRect localClipRectForSquashedLayer;
// Offset describing where this squashed RenderLayer paints into the shared GraphicsLayer backing.
IntSize offsetFromRenderer;
bool offsetFromRendererSet;
LayoutSize subpixelAccumulation;
GraphicsLayerPaintingPhase paintingPhase;
bool isBackgroundLayer;
GraphicsLayerPaintInfo() : renderLayer(0), offsetFromRendererSet(false), isBackgroundLayer(false) { }
bool isEquivalentForSquashing(const GraphicsLayerPaintInfo& other)
{
// FIXME: offsetFromRenderer and compositedBounds should not be checked here, because
// they are not yet fixed at the time this function is used.
return renderLayer == other.renderLayer
&& paintingPhase == other.paintingPhase
&& isBackgroundLayer == other.isBackgroundLayer;
}
};
enum GraphicsLayerUpdateScope {
GraphicsLayerUpdateNone,
GraphicsLayerUpdateLocal,
GraphicsLayerUpdateSubtree,
};
// CompositedLayerMapping keeps track of how RenderLayers of the render tree correspond to
// GraphicsLayers of the composited layer tree. Each instance of CompositedLayerMapping
// manages a small cluster of GraphicsLayers and the references to which RenderLayers
// and paint phases contribute to each GraphicsLayer.
//
// Currently (Oct. 2013) there is one CompositedLayerMapping for each RenderLayer,
// but this is likely to evolve soon.
class CompositedLayerMapping FINAL : public GraphicsLayerClient {
WTF_MAKE_NONCOPYABLE(CompositedLayerMapping); WTF_MAKE_FAST_ALLOCATED;
public:
explicit CompositedLayerMapping(RenderLayer&);
virtual ~CompositedLayerMapping();
RenderLayer& owningLayer() const { return m_owningLayer; }
// Returns true if layer configuration changed.
bool updateGraphicsLayerConfiguration(GraphicsLayerUpdater::UpdateType);
// Update graphics layer position and bounds.
void updateGraphicsLayerGeometry(GraphicsLayerUpdater::UpdateType, const RenderLayer* compositingContainer, Vector<RenderLayer*>& layersNeedingPaintInvalidation);
// Update whether layer needs blending.
void updateContentsOpaque();
GraphicsLayer* mainGraphicsLayer() const { return m_graphicsLayer.get(); }
// Layer to clip children
bool hasClippingLayer() const { return m_childContainmentLayer; }
GraphicsLayer* clippingLayer() const { return m_childContainmentLayer.get(); }
// Layer to get clipped by ancestor
bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer; }
GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer.get(); }
bool hasContentsLayer() const { return m_foregroundLayer; }
GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
GraphicsLayer* backgroundLayer() const { return m_backgroundLayer.get(); }
bool backgroundLayerPaintsFixedRootBackground() const { return m_backgroundLayerPaintsFixedRootBackground; }
bool hasScrollingLayer() const { return m_scrollingLayer; }
GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
GraphicsLayer* scrollingBlockSelectionLayer() const { return m_scrollingBlockSelectionLayer.get(); }
bool hasMaskLayer() const { return m_maskLayer; }
GraphicsLayer* maskLayer() const { return m_maskLayer.get(); }
bool hasChildClippingMaskLayer() const { return m_childClippingMaskLayer; }
GraphicsLayer* childClippingMaskLayer() const { return m_childClippingMaskLayer.get(); }
GraphicsLayer* parentForSublayers() const;
GraphicsLayer* childForSuperlayers() const;
// localRootForOwningLayer does not include the m_squashingContainmentLayer, which is technically not associated with this CLM's owning layer.
GraphicsLayer* localRootForOwningLayer() const;
GraphicsLayer* childTransformLayer() const { return m_childTransformLayer.get(); }
GraphicsLayer* squashingContainmentLayer() const { return m_squashingContainmentLayer.get(); }
GraphicsLayer* squashingLayer() const { return m_squashingLayer.get(); }
// Contains the bottommost layer in the hierarchy that can contain the children transform.
GraphicsLayer* layerForChildrenTransform() const;
// Returns true for a composited layer that has no backing store of its own, so
// paints into some ancestor layer.
bool paintsIntoCompositedAncestor() const { return !(m_requiresOwnBackingStoreForAncestorReasons || m_requiresOwnBackingStoreForIntrinsicReasons); }
// Updates whether a backing store is needed based on the layer's compositing ancestor's
// properties; returns true if the need for a backing store for ancestor reasons changed.
bool updateRequiresOwnBackingStoreForAncestorReasons(const RenderLayer* compositingAncestor);
// Updates whether a backing store is needed for intrinsic reasons (that is, based on the
// layer's own properties or compositing reasons); returns true if the intrinsic need for
// a backing store changed.
bool updateRequiresOwnBackingStoreForIntrinsicReasons();
void setSquashingContentsNeedDisplay();
void setContentsNeedDisplay();
// r is in the coordinate space of the layer's render object
void setContentsNeedDisplayInRect(const IntRect&);
// Notification from the renderer that its content changed.
void contentChanged(ContentChangeType);
LayoutRect compositedBounds() const { return m_compositedBounds; }
IntRect pixelSnappedCompositedBounds() const;
void updateCompositedBounds(GraphicsLayerUpdater::UpdateType);
void positionOverflowControlsLayers(const IntSize& offsetFromRoot);
bool hasUnpositionedOverflowControlsLayers() const;
// Returns true if the assignment actually changed the assigned squashing layer.
bool updateSquashingLayerAssignment(RenderLayer* squashedLayer, const RenderLayer& owningLayer, size_t nextSquashedLayerIndex);
void removeRenderLayerFromSquashingGraphicsLayer(const RenderLayer*);
void finishAccumulatingSquashingLayers(size_t nextSquashedLayerIndex);
void updateRenderingContext();
void updateShouldFlattenTransform();
// GraphicsLayerClient interface
virtual void notifyAnimationStarted(const GraphicsLayer*, double monotonicTime) OVERRIDE;
virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip) OVERRIDE;
virtual bool isTrackingRepaints() const OVERRIDE;
PassOwnPtr<Vector<FloatRect> > collectTrackedRepaintRects() const;
#ifndef NDEBUG
virtual void verifyNotPainting() OVERRIDE;
#endif
LayoutRect contentsBox() const;
GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
void updateFilters(const RenderStyle*);
bool canCompositeFilters() const { return m_canCompositeFilters; }
void setBlendMode(blink::WebBlendMode);
void setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateScope scope) { m_pendingUpdateScope = std::max(static_cast<GraphicsLayerUpdateScope>(m_pendingUpdateScope), scope); }
void clearNeedsGraphicsLayerUpdate() { m_pendingUpdateScope = GraphicsLayerUpdateNone; }
bool shouldUpdateGraphicsLayer(GraphicsLayerUpdater::UpdateType updateType) const { return m_pendingUpdateScope > GraphicsLayerUpdateNone || updateType == GraphicsLayerUpdater::ForceUpdate; }
GraphicsLayerUpdater::UpdateType updateTypeForChildren(GraphicsLayerUpdater::UpdateType) const;
#if ASSERT_ENABLED
void assertNeedsToUpdateGraphicsLayerBitsCleared() { ASSERT(m_pendingUpdateScope == GraphicsLayerUpdateNone); }
#endif
virtual String debugName(const GraphicsLayer*) OVERRIDE;
LayoutSize contentOffsetInCompositingLayer() const;
LayoutPoint squashingOffsetFromTransformedAncestor()
{
return m_squashingLayerOffsetFromTransformedAncestor;
}
// If there is a squashed layer painting into this CLM that is an ancestor of the given RenderObject, return it. Otherwise return 0.
const GraphicsLayerPaintInfo* containingSquashedLayer(const RenderObject*);
void updateScrollingBlockSelection();
private:
static const GraphicsLayerPaintInfo* containingSquashedLayer(const RenderObject*, const Vector<GraphicsLayerPaintInfo>& layers);
// Helper methods to updateGraphicsLayerGeometry:
void computeGraphicsLayerParentLocation(const RenderLayer* compositingContainer, const IntRect& ancestorCompositingBounds, IntPoint& graphicsLayerParentLocation);
void updateSquashingLayerGeometry(const LayoutPoint& offsetFromCompositedAncestor, const IntPoint& graphicsLayerParentLocation, const RenderLayer& referenceLayer, Vector<GraphicsLayerPaintInfo>& layers, GraphicsLayer*, LayoutPoint* offsetFromTransformedAncestor, Vector<RenderLayer*>& layersNeedingPaintInvalidation);
void updateMainGraphicsLayerGeometry(const IntRect& relativeCompositingBounds, const IntRect& localCompositingBounds, IntPoint& graphicsLayerParentLocation);
void updateAncestorClippingLayerGeometry(const RenderLayer* compositingContainer, const IntPoint& snappedOffsetFromCompositedAncestor, IntPoint& graphicsLayerParentLocation);
void updateChildContainmentLayerGeometry(const IntRect& clippingBox, const IntRect& localCompositingBounds);
void updateChildTransformLayerGeometry();
void updateMaskLayerGeometry();
void updateTransformGeometry(const IntPoint& snappedOffsetFromCompositedAncestor, const IntRect& relativeCompositingBounds);
void updateForegroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize, const IntRect& clippingBox);
void updateBackgroundLayerGeometry(const FloatSize& relativeCompositingBoundsSize);
void updateReflectionLayerGeometry(Vector<RenderLayer*>& layersNeedingPaintInvalidation);
void updateScrollingLayerGeometry(const IntRect& localCompositingBounds);
void updateChildClippingMaskLayerGeometry();
void createPrimaryGraphicsLayer();
void destroyGraphicsLayers();
PassOwnPtr<GraphicsLayer> createGraphicsLayer(CompositingReasons);
bool toggleScrollbarLayerIfNeeded(OwnPtr<GraphicsLayer>&, bool needsLayer, CompositingReasons);
RenderLayerModelObject* renderer() const { return m_owningLayer.renderer(); }
RenderLayerCompositor* compositor() const { return m_owningLayer.compositor(); }
void updateInternalHierarchy();
void updatePaintingPhases();
bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
bool updateChildTransformLayer(bool needsChildTransformLayer);
bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer);
bool updateForegroundLayer(bool needsForegroundLayer);
bool updateBackgroundLayer(bool needsBackgroundLayer);
bool updateMaskLayer(bool needsMaskLayer);
bool updateClippingMaskLayers(bool needsChildClippingMaskLayer);
bool requiresHorizontalScrollbarLayer() const { return m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->horizontalScrollbar(); }
bool requiresVerticalScrollbarLayer() const { return m_owningLayer.scrollableArea() && m_owningLayer.scrollableArea()->verticalScrollbar(); }
bool requiresScrollCornerLayer() const { return m_owningLayer.scrollableArea() && !m_owningLayer.scrollableArea()->scrollCornerAndResizerRect().isEmpty(); }
bool updateScrollingLayers(bool scrollingLayers);
void updateScrollParent(RenderLayer*);
void updateClipParent(RenderLayer*);
bool updateSquashingLayers(bool needsSquashingLayers);
void updateDrawsContent();
void updateChildrenTransform();
void registerScrollingLayers();
// Also sets subpixelAccumulation on the layer.
void computeBoundsOfOwningLayer(const RenderLayer* compositedAncestor, IntRect& localCompositingBounds, IntRect& compositingBoundsRelativeToCompositedAncestor, LayoutPoint& offsetFromCompositedAncestor, IntPoint& snappedOffsetFromCompositedAncestor);
void setBackgroundLayerPaintsFixedRootBackground(bool);
GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
// Result is transform origin in pixels.
FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const;
void updateOpacity(const RenderStyle*);
void updateTransform(const RenderStyle*);
void updateLayerBlendMode(const RenderStyle*);
void updateIsRootForIsolatedGroup();
// Return the opacity value that this layer should use for compositing.
float compositingOpacity(float rendererOpacity) const;
bool isMainFrameRenderViewLayer() const;
bool paintsChildren() const;
// Returns true if this layer has content that needs to be rendered by painting into the backing store.
bool containsPaintedContent() const;
// Returns true if the RenderLayer just contains an image that we can composite directly.
bool isDirectlyCompositedImage() const;
void updateImageContents();
Color rendererBackgroundColor() const;
void updateBackgroundColor();
void updateContentsRect();
void updateAfterWidgetResize();
void updateCompositingReasons();
static bool hasVisibleNonCompositingDescendant(RenderLayer* parent);
void paintsIntoCompositedAncestorChanged();
void doPaintTask(GraphicsLayerPaintInfo&, GraphicsContext*, const IntRect& clip);
// Computes the background clip rect for the given squashed layer, up to any containing layer that is squashed into the
// same squashing layer and contains this squashed layer's clipping ancestor.
// The clip rect is returned in the coordinate space of the given squashed layer.
// If there is no such containing layer, returns the infinite rect.
// FIXME: unify this code with the code that sets up m_ancestorClippingLayer. They are doing very similar things.
static IntRect localClipRectForSquashedLayer(const RenderLayer& referenceLayer, const GraphicsLayerPaintInfo&, const Vector<GraphicsLayerPaintInfo>& layers);
RenderLayer& m_owningLayer;
// The hierarchy of layers that is maintained by the CompositedLayerMapping looks like this:
//
// + m_ancestorClippingLayer [OPTIONAL]
// + m_graphicsLayer
// + m_childContainmentLayer [OPTIONAL] <-OR-> m_scrollingLayer [OPTIONAL] <-OR-> m_childTransformLayer
// + m_scrollingContentsLayer [Present iff m_scrollingLayer is present]
// + m_scrollingBlockSelectionLayer [Present iff m_scrollingLayer is present]
//
// We need an ancestor clipping layer if our clipping ancestor is not our ancestor in the
// clipping tree. Here's what that might look like.
//
// Let A = the clipping ancestor,
// B = the clip descendant, and
// SC = the stacking context that is the ancestor of A and B in the stacking tree.
//
// SC
// + A = m_graphicsLayer
// | + m_childContainmentLayer
// | + ...
// ...
// |
// + B = m_ancestorClippingLayer [+]
// + m_graphicsLayer
// + ...
//
// In this case B is clipped by another layer that doesn't happen to be its ancestor: A.
// So we create an ancestor clipping layer for B, [+], which ensures that B is clipped
// as if it had been A's descendant.
OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // Only used if we are clipped by an ancestor which is not a stacking context.
OwnPtr<GraphicsLayer> m_graphicsLayer;
OwnPtr<GraphicsLayer> m_childContainmentLayer; // Only used if we have clipping on a stacking context with compositing children.
OwnPtr<GraphicsLayer> m_childTransformLayer; // Only used if we have perspective and no m_childContainmentLayer.
OwnPtr<GraphicsLayer> m_scrollingLayer; // Only used if the layer is using composited scrolling.
OwnPtr<GraphicsLayer> m_scrollingContentsLayer; // Only used if the layer is using composited scrolling.
OwnPtr<GraphicsLayer> m_scrollingBlockSelectionLayer; // Only used if the layer is using composited scrolling, but has no scrolling contents apart from block selection gaps.
// This layer is also added to the hierarchy by the RLB, but in a different way than
// the layers above. It's added to m_graphicsLayer as its mask layer (naturally) if
// we have a mask, and isn't part of the typical hierarchy (it has no children).
OwnPtr<GraphicsLayer> m_maskLayer; // Only used if we have a mask.
OwnPtr<GraphicsLayer> m_childClippingMaskLayer; // Only used if we have to clip child layers or accelerated contents with border radius or clip-path.
// There are two other (optional) layers whose painting is managed by the CompositedLayerMapping,
// but whose position in the hierarchy is maintained by the RenderLayerCompositor. These
// are the foreground and background layers. The foreground layer exists if we have composited
// descendants with negative z-order. We need the extra layer in this case because the layer
// needs to draw both below (for the background, say) and above (for the normal flow content, say)
// the negative z-order descendants and this is impossible with a single layer. The RLC handles
// inserting m_foregroundLayer in the correct position in our descendant list for us (right after
// the neg z-order dsecendants).
//
// The background layer is only created if this is the root layer and our background is entirely
// fixed. In this case we want to put the background in a separate composited layer so that when
// we scroll, we don't have to re-raster the background into position. This layer is also inserted
// into the tree by the RLC as it gets a special home. This layer becomes a descendant of the
// frame clipping layer. That is:
// ...
// + frame clipping layer
// + m_backgroundLayer
// + frame scrolling layer
// + root content layer
//
// With the hierarchy set up like this, the root content layer is able to scroll without affecting
// the background layer (or repainting).
OwnPtr<GraphicsLayer> m_foregroundLayer; // Only used in cases where we need to draw the foreground separately.
OwnPtr<GraphicsLayer> m_backgroundLayer; // Only used in cases where we need to draw the background separately.
OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
OwnPtr<GraphicsLayer> m_layerForScrollCorner;
// A squashing CLM has two possible squashing-related structures.
//
// If m_ancestorClippingLayer is present:
//
// m_ancestorClippingLayer
// + m_graphicsLayer
// + m_squashingLayer
//
// If not:
//
// m_squashingContainmentLayer
// + m_graphicsLayer
// + m_squashingLayer
OwnPtr<GraphicsLayer> m_squashingContainmentLayer; // Only used if any squashed layers exist and m_squashingContainmentLayer is not present, to contain the squashed layers as siblings to the rest of the GraphicsLayer tree chunk.
OwnPtr<GraphicsLayer> m_squashingLayer; // Only used if any squashed layers exist, this is the backing that squashed layers paint into.
Vector<GraphicsLayerPaintInfo> m_squashedLayers;
LayoutPoint m_squashingLayerOffsetFromTransformedAncestor;
LayoutRect m_compositedBounds;
unsigned m_pendingUpdateScope : 2;
unsigned m_isMainFrameRenderViewLayer : 1;
unsigned m_requiresOwnBackingStoreForIntrinsicReasons : 1;
unsigned m_requiresOwnBackingStoreForAncestorReasons : 1;
unsigned m_canCompositeFilters : 1;
unsigned m_backgroundLayerPaintsFixedRootBackground : 1;
unsigned m_scrollingContentsAreEmpty : 1;
};
} // namespace WebCore
#endif // CompositedLayerMapping_h
|