Upstream version 11.39.250.0
[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/inspector/InspectorTraceEvents.h"
31 #include "core/rendering/compositing/CompositedLayerMapping.h"
32 #include "platform/TraceEvent.h"
33
34 namespace blink {
35
36 // We will only allow squashing if the bbox-area:squashed-area doesn't exceed
37 // the ratio |gSquashingSparsityTolerance|:1.
38 static uint64_t gSquashingSparsityTolerance = 6;
39
40 CompositingLayerAssigner::CompositingLayerAssigner(RenderLayerCompositor* compositor)
41     : m_compositor(compositor)
42     , m_layerSquashingEnabled(compositor->layerSquashingEnabled())
43     , m_layersChanged(false)
44 {
45 }
46
47 CompositingLayerAssigner::~CompositingLayerAssigner()
48 {
49 }
50
51 void CompositingLayerAssigner::assign(RenderLayer* updateRoot, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
52 {
53     TRACE_EVENT0("blink", "CompositingLayerAssigner::assign");
54
55     SquashingState squashingState;
56     assignLayersToBackingsInternal(updateRoot, squashingState, layersNeedingPaintInvalidation);
57     if (squashingState.hasMostRecentMapping)
58         squashingState.mostRecentMapping->finishAccumulatingSquashingLayers(squashingState.nextSquashedLayerIndex);
59 }
60
61 void CompositingLayerAssigner::SquashingState::updateSquashingStateForNewMapping(CompositedLayerMapping* newCompositedLayerMapping, bool hasNewCompositedLayerMapping)
62 {
63     // The most recent backing is done accumulating any more squashing layers.
64     if (hasMostRecentMapping)
65         mostRecentMapping->finishAccumulatingSquashingLayers(nextSquashedLayerIndex);
66
67     nextSquashedLayerIndex = 0;
68     boundingRect = IntRect();
69     mostRecentMapping = newCompositedLayerMapping;
70     hasMostRecentMapping = hasNewCompositedLayerMapping;
71     haveAssignedBackingsToEntireSquashingLayerSubtree = false;
72 }
73
74 bool CompositingLayerAssigner::squashingWouldExceedSparsityTolerance(const RenderLayer* candidate, const CompositingLayerAssigner::SquashingState& squashingState)
75 {
76     IntRect bounds = candidate->clippedAbsoluteBoundingBox();
77     IntRect newBoundingRect = squashingState.boundingRect;
78     newBoundingRect.unite(bounds);
79     const uint64_t newBoundingRectArea = newBoundingRect.size().area();
80     const uint64_t newSquashedArea = squashingState.totalAreaOfSquashedRects + bounds.size().area();
81     return newBoundingRectArea > gSquashingSparsityTolerance * newSquashedArea;
82 }
83
84 bool CompositingLayerAssigner::needsOwnBacking(const RenderLayer* layer) const
85 {
86     if (!m_compositor->canBeComposited(layer))
87         return false;
88
89     // If squashing is disabled, then layers that would have been squashed should just be separately composited.
90     bool needsOwnBackingForDisabledSquashing = !m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons());
91
92     return requiresCompositing(layer->compositingReasons()) || needsOwnBackingForDisabledSquashing || (m_compositor->staleInCompositingMode() && layer->isRootLayer());
93 }
94
95 CompositingStateTransitionType CompositingLayerAssigner::computeCompositedLayerUpdate(RenderLayer* layer)
96 {
97     CompositingStateTransitionType update = NoCompositingStateChange;
98     if (needsOwnBacking(layer)) {
99         if (!layer->hasCompositedLayerMapping()) {
100             update = AllocateOwnCompositedLayerMapping;
101         }
102     } else {
103         if (layer->hasCompositedLayerMapping())
104             update = RemoveOwnCompositedLayerMapping;
105
106         if (m_layerSquashingEnabled) {
107             if (!layer->subtreeIsInvisible() && requiresSquashing(layer->compositingReasons())) {
108                 // We can't compute at this time whether the squashing layer update is a no-op,
109                 // since that requires walking the render layer tree.
110                 update = PutInSquashingLayer;
111             } else if (layer->groupedMapping() || layer->lostGroupedMapping()) {
112                 update = RemoveFromSquashingLayer;
113             }
114         }
115     }
116     return update;
117 }
118
119 CompositingReasons CompositingLayerAssigner::getReasonsPreventingSquashing(const RenderLayer* layer, const CompositingLayerAssigner::SquashingState& squashingState)
120 {
121     if (!squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree)
122         return CompositingReasonSquashingWouldBreakPaintOrder;
123
124     ASSERT(squashingState.hasMostRecentMapping);
125     const RenderLayer& squashingLayer = squashingState.mostRecentMapping->owningLayer();
126
127     // FIXME: this special case for video exists only to deal with corner cases
128     // where a RenderVideo does not report that it needs to be directly composited.
129     // Video does not currently support sharing a backing, but this could be
130     // generalized in the future. The following layout tests fail if we permit the
131     // video to share a backing with other layers.
132     //
133     // compositing/video/video-controls-layer-creation.html
134     if (layer->renderer()->isVideo() || squashingLayer.renderer()->isVideo())
135         return CompositingReasonSquashingVideoIsDisallowed;
136
137     // Don't squash iframes, frames or plugins.
138     // FIXME: this is only necessary because there is frame code that assumes that composited frames are not squashed.
139     if (layer->renderer()->isRenderPart() || squashingLayer.renderer()->isRenderPart())
140         return CompositingReasonSquashingRenderPartIsDisallowed;
141
142     if (layer->reflectionInfo())
143         return CompositingReasonSquashingReflectionIsDisallowed;
144
145     if (squashingWouldExceedSparsityTolerance(layer, squashingState))
146         return CompositingReasonSquashingSparsityExceeded;
147
148     if (layer->renderer()->hasBlendMode())
149         return CompositingReasonSquashingBlendingIsDisallowed;
150
151     // FIXME: this is not efficient, since it walks up the tree. We should store these values on the CompositingInputsCache.
152     if (layer->clippingContainer() != squashingLayer.clippingContainer() && !squashingLayer.compositedLayerMapping()->containingSquashedLayer(layer->clippingContainer(), squashingState.nextSquashedLayerIndex))
153         return CompositingReasonSquashingClippingContainerMismatch;
154
155     // Composited descendants need to be clipped by a child containment graphics layer, which would not be available if the layer is
156     // squashed (and therefore has no CLM nor a child containment graphics layer).
157     if (m_compositor->clipsCompositingDescendants(layer))
158         return CompositingReasonSquashedLayerClipsCompositingDescendants;
159
160     if (layer->scrollsWithRespectTo(&squashingLayer))
161         return CompositingReasonScrollsWithRespectToSquashingLayer;
162
163     const RenderLayer::AncestorDependentCompositingInputs& compositingInputs = layer->ancestorDependentCompositingInputs();
164     const RenderLayer::AncestorDependentCompositingInputs& squashingLayerCompositingInputs = squashingLayer.ancestorDependentCompositingInputs();
165
166     if (compositingInputs.opacityAncestor != squashingLayerCompositingInputs.opacityAncestor)
167         return CompositingReasonSquashingOpacityAncestorMismatch;
168
169     if (compositingInputs.transformAncestor != squashingLayerCompositingInputs.transformAncestor)
170         return CompositingReasonSquashingTransformAncestorMismatch;
171
172     if (layer->hasFilter() || compositingInputs.filterAncestor != squashingLayerCompositingInputs.filterAncestor)
173         return CompositingReasonSquashingFilterMismatch;
174
175     return CompositingReasonNone;
176 }
177
178 void CompositingLayerAssigner::updateSquashingAssignment(RenderLayer* layer, SquashingState& squashingState, const CompositingStateTransitionType compositedLayerUpdate,
179     Vector<RenderLayer*>& layersNeedingPaintInvalidation)
180 {
181     // NOTE: In the future as we generalize this, the background of this layer may need to be assigned to a different backing than
182     // the squashed RenderLayer's own primary contents. This would happen when we have a composited negative z-index element that needs
183     // to paint on top of the background, but below the layer's main contents. For now, because we always composite layers
184     // when they have a composited negative z-index child, such layers will never need squashing so it is not yet an issue.
185     if (compositedLayerUpdate == PutInSquashingLayer) {
186         // A layer that is squashed with other layers cannot have its own CompositedLayerMapping.
187         ASSERT(!layer->hasCompositedLayerMapping());
188         ASSERT(squashingState.hasMostRecentMapping);
189
190         bool changedSquashingLayer =
191             squashingState.mostRecentMapping->updateSquashingLayerAssignment(layer, squashingState.mostRecentMapping->owningLayer(), squashingState.nextSquashedLayerIndex);
192         if (!changedSquashingLayer)
193             return;
194
195         // If we've modified the collection of squashed layers, we must update
196         // the graphics layer geometry.
197         squashingState.mostRecentMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
198
199         layer->clipper().clearClipRectsIncludingDescendants();
200
201         // Issue a paint invalidation, since |layer| may have been added to an already-existing squashing layer.
202         TRACE_LAYER_INVALIDATION(layer, InspectorLayerInvalidationTrackingEvent::AddedToSquashingLayer);
203         layersNeedingPaintInvalidation.append(layer);
204         m_layersChanged = true;
205     } else if (compositedLayerUpdate == RemoveFromSquashingLayer) {
206         if (layer->groupedMapping()) {
207             // Before removing |layer| from an already-existing squashing layer that may have other content, issue a paint invalidation.
208             m_compositor->paintInvalidationOnCompositingChange(layer);
209             layer->groupedMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree);
210             layer->setGroupedMapping(0);
211         }
212
213         // If we need to issue paint invalidations, do so now that we've removed it from a squashed layer.
214         TRACE_LAYER_INVALIDATION(layer, InspectorLayerInvalidationTrackingEvent::RemovedFromSquashingLayer);
215         layersNeedingPaintInvalidation.append(layer);
216         m_layersChanged = true;
217
218         layer->setLostGroupedMapping(false);
219     }
220 }
221
222 void CompositingLayerAssigner::assignLayersToBackingsForReflectionLayer(RenderLayer* reflectionLayer, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
223 {
224     CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(reflectionLayer);
225     if (compositedLayerUpdate != NoCompositingStateChange) {
226         TRACE_LAYER_INVALIDATION(reflectionLayer, InspectorLayerInvalidationTrackingEvent::ReflectionLayerChanged);
227         layersNeedingPaintInvalidation.append(reflectionLayer);
228         m_layersChanged = true;
229         m_compositor->allocateOrClearCompositedLayerMapping(reflectionLayer, compositedLayerUpdate);
230     }
231     m_compositor->updateDirectCompositingReasons(reflectionLayer);
232
233     // FIXME: Why do we updateGraphicsLayerConfiguration here instead of in the GraphicsLayerUpdater?
234     if (reflectionLayer->hasCompositedLayerMapping())
235         reflectionLayer->compositedLayerMapping()->updateGraphicsLayerConfiguration();
236 }
237
238 void CompositingLayerAssigner::assignLayersToBackingsInternal(RenderLayer* layer, SquashingState& squashingState, Vector<RenderLayer*>& layersNeedingPaintInvalidation)
239 {
240     if (m_layerSquashingEnabled && requiresSquashing(layer->compositingReasons())) {
241         CompositingReasons reasonsPreventingSquashing = getReasonsPreventingSquashing(layer, squashingState);
242         if (reasonsPreventingSquashing)
243             layer->setCompositingReasons(layer->compositingReasons() | reasonsPreventingSquashing);
244     }
245
246     CompositingStateTransitionType compositedLayerUpdate = computeCompositedLayerUpdate(layer);
247
248     if (m_compositor->allocateOrClearCompositedLayerMapping(layer, compositedLayerUpdate)) {
249         TRACE_LAYER_INVALIDATION(layer, InspectorLayerInvalidationTrackingEvent::NewCompositedLayer);
250         layersNeedingPaintInvalidation.append(layer);
251         m_layersChanged = true;
252     }
253
254     // FIXME: special-casing reflection layers here is not right.
255     if (layer->reflectionInfo())
256         assignLayersToBackingsForReflectionLayer(layer->reflectionInfo()->reflectionLayer(), layersNeedingPaintInvalidation);
257
258     // Add this layer to a squashing backing if needed.
259     if (m_layerSquashingEnabled) {
260         updateSquashingAssignment(layer, squashingState, compositedLayerUpdate, layersNeedingPaintInvalidation);
261
262         const bool layerIsSquashed = compositedLayerUpdate == PutInSquashingLayer || (compositedLayerUpdate == NoCompositingStateChange && layer->groupedMapping());
263         if (layerIsSquashed) {
264             squashingState.nextSquashedLayerIndex++;
265             IntRect layerBounds = layer->clippedAbsoluteBoundingBox();
266             squashingState.totalAreaOfSquashedRects += layerBounds.size().area();
267             squashingState.boundingRect.unite(layerBounds);
268         }
269     }
270
271     if (layer->stackingNode()->isStackingContext()) {
272         RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NegativeZOrderChildren);
273         while (RenderLayerStackingNode* curNode = iterator.next())
274             assignLayersToBackingsInternal(curNode->layer(), squashingState, layersNeedingPaintInvalidation);
275     }
276
277     if (m_layerSquashingEnabled) {
278         // At this point, if the layer is to be "separately" composited, then its backing becomes the most recent in paint-order.
279         if (layer->compositingState() == PaintsIntoOwnBacking || layer->compositingState() == HasOwnBackingButPaintsIntoAncestor) {
280             ASSERT(!requiresSquashing(layer->compositingReasons()));
281             squashingState.updateSquashingStateForNewMapping(layer->compositedLayerMapping(), layer->hasCompositedLayerMapping());
282         }
283     }
284
285     if (layer->scrollParent())
286         layer->scrollParent()->scrollableArea()->setTopmostScrollChild(layer);
287
288     if (layer->needsCompositedScrolling())
289         layer->scrollableArea()->setTopmostScrollChild(0);
290
291     RenderLayerStackingNodeIterator iterator(*layer->stackingNode(), NormalFlowChildren | PositiveZOrderChildren);
292     while (RenderLayerStackingNode* curNode = iterator.next())
293         assignLayersToBackingsInternal(curNode->layer(), squashingState, layersNeedingPaintInvalidation);
294
295     if (squashingState.hasMostRecentMapping && &squashingState.mostRecentMapping->owningLayer() == layer)
296         squashingState.haveAssignedBackingsToEntireSquashingLayerSubtree = true;
297 }
298
299 }