1708a9806761f55b7a7317b1fdb2ae59fb643478
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / compositing / CompositingLayerAssigner.cpp
1 /*
2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2014 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "core/rendering/compositing/CompositingLayerAssigner.h"
29
30 #include "core/rendering/compositing/CompositedLayerMapping.h"
31 #include "platform/TraceEvent.h"
32
33 namespace blink {
34
35 // We will only allow squashing if the bbox-area:squashed-area doesn't exceed
36 // the ratio |gSquashingSparsityTolerance|:1.
37 static uint64_t gSquashingSparsityTolerance = 6;
38
39 CompositingLayerAssigner::CompositingLayerAssigner(RenderLayerCompositor* compositor)
40     : m_compositor(compositor)
41     , m_layerSquashingEnabled(compositor->layerSquashingEnabled())
42     , m_layersChanged(false)
43 {
44 }
45
46 CompositingLayerAssigner::~CompositingLayerAssigner()
47 {
48 }
49
50 void CompositingLayerAssigner::assign(RenderLayer* updateRoot, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
51 {
52     TRACE_EVENT0("blink", "CompositingLayerAssigner::assign");
53
54     SquashingState squashingState;
55     assignLayersToBackingsInternal(updateRoot, squashingState, layersNeedingPaintInvalidation);
56     if (squashingState.hasMostRecentMapping)
57         squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex);
58 }
59
60 void CompositingLayerAssigner::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMapping* newCompositedLayerMapping, bool hasNewCompositedLayerMapping)
61 {
62     // The most recent backing is done accumulating any more squashing layers.
63     if (hasMostRecentMapping)
64         mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex);
65
66     nextSquashedLayerIndex = 0;
67     boundingRect = IntRect();
68     mostRecentMapping = newCompositedLayerMapping;
69     hasMostRecentMapping = hasNewCompositedLayerMapping;
70     haveAssignedBackingsToEntireSquashingLayerSubtree = false;
71 }
72
73 bool CompositingLayerAssigner::squashingWouldExceedSparsityTolerance(const RenderLayer* candidate, const CompositingLayerAssigner::SquashingState& squashingState)
74 {
75     IntRect bounds = candidate->clippedAbsoluteBoundingBox();
76     IntRect newBoundingRect = squashingState.boundingRect;
77     newBoundingRect.unite(bounds);
78     const uint64_t newBoundingRectArea = newBoundingRect.size().area();
79     const uint64_t newSquashedArea = squashingState.totalAreaOfSquashedRects + bounds.size().area();
80     return newBoundingRectArea > gSquashingSparsityTolerance * newSquashedArea;
81 }
82
83 bool CompositingLayerAssigner::needsOwnBacking(const RenderLayer* layer) const
84 {
85     if (!m_compositor->canBeComposited(layer))
86         return false;
87
88     // If squashing is disabled, then layers that would have been squashed should just be separately composited.
89     bool needsOwnBackingForDisabledSquashing = !m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons());
90
91     return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (m_compositor->staleInCompositingMode() && layer->isRootLayer());
92 }
93
94 CompositingStateTransitionType CompositingLayerAssigner::computeCompositedLayerUpdate(RenderLayer* layer)
95 {
96     CompositingStateTransitionType update = NoCompositingStateChange;
97     if (needsOwnBacking(layer)) {
98         if (!layer->hasCompositedLayerMapping()) {
99             update = AllocateOwnCompositedLayerMapping;
100         }
101     } else {
102         if (layer->hasCompositedLayerMapping())
103             update = RemoveOwnCompositedLayerMapping;
104
105         if (m_layerSquashingEnabled) {
106             if (!layer->subtreeIsInvisible() && requiresSquashing(layer->compositingReasons())) {
107                 // We can't compute at this time whether the squashing layer update is a no-op,
108                 // since that requires walking the render layer tree.
109                 update = PutInSquashingLayer;
110             } else if (layer->groupedMapping() || layer->lostGroupedMapping()) {
111                 update = RemoveFromSquashingLayer;
112             }
113         }
114     }
115     return update;
116 }
117
118 CompositingReasons CompositingLayerAssigner::getReasonsPreventingSquashing(const RenderLayer* layer, const CompositingLayerAssigner::SquashingState& squashingState)
119 {
120     if (!squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree)
121         return CompositingReasonSquashingWouldBreakPaintOrder;
122
123     // FIXME: this special case for video exists only to deal with corner cases
124     // where a RenderVideo does not report that it needs to be directly composited.
125     // Video does not currently support sharing a backing, but this could be
126     // generalized in the future. The following layout tests fail if we permit the
127     // video to share a backing with other layers.
128     //
129     // compositing/video/video-controls-layer-creation.html
130     // virtual/softwarecompositing/video/video-controls-layer-creation.html
131     if (layer->renderer()->isVideo())
132         return CompositingReasonSquashingVideoIsDisallowed;
133
134     // Don't squash iframes, frames or plugins.
135     // FIXME: this is only necessary because there is frame code that assumes that composited frames are not squashed.
136     if (layer->renderer()->isRenderPart())
137         return CompositingReasonSquashingRenderPartIsDisallowed;
138
139     if (layer->reflectionInfo())
140         return CompositingReasonSquashingReflectionIsDisallowed;
141
142     if (squashingWouldExceedSparsityTolerance(layer, squashingState))
143         return CompositingReasonSquashingSparsityExceeded;
144
145     // FIXME: this is not efficient, since it walks up the tree . We should store these values on the CompositingInputsCache.
146     ASSERT(squashingState.hasMostRecentMapping);
147     const RenderLayer& squashingLayer = squashingState.mostRecentMapping->owningLayer();
148
149     if (layer->clippingContainer() != squashingLayer.clippingContainer() && !squashingLayer.compositedLayerMapping()->containingSquashedLayer(layer->clippingContainer()))
150         return CompositingReasonSquashingClippingContainerMismatch;
151
152     // Composited descendants need to be clipped by a child containment graphics layer, which would not be available if the layer is
153     // squashed (and therefore has no CLM nor a child containment graphics layer).
154     if (m_compositor->clipsCompositingDescendants(layer))
155         return CompositingReasonSquashedLayerClipsCompositingDescendants;
156
157     if (layer->scrollsWithRespectTo(&squashingLayer))
158         return CompositingReasonScrollsWithRespectToSquashingLayer;
159
160     const RenderLayer::AncestorDependentCompositingInputs& compositingInputs = layer->ancestorDependentCompositingInputs();
161     const RenderLayer::AncestorDependentCompositingInputs& squashingLayerCompositingInputs = squashingLayer.ancestorDependentCompositingInputs();
162
163     if (compositingInputs.opacityAncestor != squashingLayerCompositingInputs.opacityAncestor)
164         return CompositingReasonSquashingOpacityAncestorMismatch;
165
166     if (compositingInputs.transformAncestor != squashingLayerCompositingInputs.transformAncestor)
167         return CompositingReasonSquashingTransformAncestorMismatch;
168
169     if (compositingInputs.filterAncestor != squashingLayerCompositingInputs.filterAncestor)
170         return CompositingReasonSquashingFilterAncestorMismatch;
171
172     return CompositingReasonNone;
173 }
174
175 void CompositingLayerAssigner::updateSquashingAssignment(RenderLayer* layer, SquashingState& squashingState, const CompositingStateTransitionType compositedLayerUpdate,
176     Vector<RenderLayer*>& layersNeedingPaintInvalidation)
177 {
178     // NOTE: In the future as we generalize this, the background of this layer may need to be assigned to a different backing than
179     // the squashed RenderLayer's own primary contents. This would happen when we have a composited negative z-index element that needs
180     // to paint on top of the background, but below the layer's main contents. For now, because we always composite layers
181     // when they have a composited negative z-index child, such layers will never need squashing so it is not yet an issue.
182     if (compositedLayerUpdate == PutInSquashingLayer) {
183         // A layer that is squashed with other layers cannot have its own CompositedLayerMapping.
184         ASSERT(!layer->hasCompositedLayerMapping());
185         ASSERT(squashingState.hasMostRecentMapping);
186
187         bool changedSquashingLayer =
188             squashingState.mostRecentMapping->updateSquashingLayerAssignment(layer, squashingState.mostRecentMapping->owningLayer(), squashingState.nextSquashedLayerIndex);
189         if (!changedSquashingLayer)
190             return;
191
192         // If we've modified the collection of squashed layers, we must update
193         // the graphics layer geometry.
194         squashingState.mostRecentMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
195
196         layer->clipper().clearClipRectsIncludingDescendants();
197
198         // Issue a paint invalidation, since |layer| may have been added to an already-existing squashing layer.
199         layersNeedingPaintInvalidation.append(layer);
200         m_layersChanged = true;
201     } else if (compositedLayerUpdate == RemoveFromSquashingLayer) {
202         if (layer->groupedMapping()) {
203             // Before removing |layer| from an already-existing squashing layer that may have other content, issue a paint invalidation.
204             m_compositor->paintInvalidationOnCompositingChange(layer);
205             layer->groupedMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
206             layer->setGroupedMapping(0);
207         }
208
209         // If we need to issue paint invalidations, do so now that we've removed it from a squashed layer.
210         layersNeedingPaintInvalidation.append(layer);
211         m_layersChanged = true;
212
213         layer->setLostGroupedMapping(false);
214     }
215 }
216
217 void CompositingLayerAssigner::assignLayersToBackingsForReflectionLayer(RenderLayer* reflectionLayer, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
218 {
219     CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(reflectionLayer);
220     if (compositedLayerUpdate != NoCompositingStateChange) {
221         layersNeedingPaintInvalidation.append(reflectionLayer);
222         m_layersChanged = true;
223         m_compositor->allocateOrClearCompositedLayerMapping(reflectionLayer, compositedLayerUpdate);
224     }
225     m_compositor->updateDirectCompositingReasons(reflectionLayer);
226
227     // FIXME: Why do we updateGraphicsLayerConfiguration here instead of in the GraphicsLayerUpdater?
228     if (reflectionLayer->hasCompositedLayerMapping())
229         reflectionLayer->compositedLayerMapping()->updateGraphicsLayerConfiguration();
230 }
231
232 void CompositingLayerAssigner::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
233 {
234     if (m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons())) {
235         CompositingReasons reasonsPreventingSquashing = getReasonsPreventingSquashing(layer, squashingState);
236         if (reasonsPreventingSquashing)
237             layer->setCompositingReasons(layer->compositingReasons() | reasonsPreventingSquashing);
238     }
239
240     CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(layer);
241
242     if (m_compositor->allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate)) {
243         layersNeedingPaintInvalidation.append(layer);
244         m_layersChanged = true;
245     }
246
247     // FIXME: special-casing reflection layers here is not right.
248     if (layer->reflectionInfo())
249         assignLayersToBackingsForReflectionLayer(layer->reflectionInfo()->reflectionLayer(), layersNeedingPaintInvalidation);
250
251     // Add this layer to a squashing backing if needed.
252     if (m_layerSquashingEnabled) {
253         updateSquashingAssignment(layer, squashingState, compositedLayerUpdate, layersNeedingPaintInvalidation);
254
255         const bool layerIsSquashed = compositedLayerUpdate == PutInSquashingLayer || (compositedLayerUpdate == NoCompositingStateChange && layer->groupedMapping());
256         if (layerIsSquashed) {
257             squashingState.nextSquashedLayerIndex++;
258             IntRect layerBounds = layer->clippedAbsoluteBoundingBox();
259             squashingState.totalAreaOfSquashedRects += layerBounds.size().area();
260             squashingState.boundingRect.unite(layerBounds);
261         }
262     }
263
264     if (layer->stackingNode()->isStackingContext()) {
265         RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
266         while (RenderLayerStackingNode* curNode = iterator.next())
267             assignLayersToBackingsInternal(curNode->layer(), squashingState, layersNeedingPaintInvalidation);
268     }
269
270     if (m_layerSquashingEnabled) {
271         // At this point, if the layer is to be "separately" composited, then its backing becomes the most recent in paint-order.
272         if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) {
273             ASSERT(!requiresSquashing(layer->compositingReasons()));
274             squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping());
275         }
276     }
277
278     if (layer->scrollParent())
279         layer->scrollParent()->scrollableArea()->setTopmostScrollChild(layer);
280
281     if (layer->needsCompositedScrolling())
282         layer->scrollableArea()->setTopmostScrollChild(0);
283
284     RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
285     while (RenderLayerStackingNode* curNode = iterator.next())
286         assignLayersToBackingsInternal(curNode->layer(), squashingState, layersNeedingPaintInvalidation);
287
288     if (squashingState.hasMostRecentMapping && &squashingState.mostRecentMapping->owningLayer() == layer)
289         squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree = true;
290 }
291
292 }