1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef RenderLayerCompositor_h
27 #define RenderLayerCompositor_h
28 
29 #include "ChromeClient.h"
30 #include "RenderLayer.h"
31 #include "RenderLayerBacking.h"
32 
33 namespace WebCore {
34 
35 #define PROFILE_LAYER_REBUILD 0
36 
37 class GraphicsLayer;
38 class RenderEmbeddedObject;
39 class RenderPart;
40 #if ENABLE(VIDEO)
41 class RenderVideo;
42 #endif
43 
44 enum CompositingUpdateType {
45     CompositingUpdateAfterLayoutOrStyleChange,
46     CompositingUpdateOnPaitingOrHitTest,
47     CompositingUpdateOnScroll
48 };
49 
50 // RenderLayerCompositor manages the hierarchy of
51 // composited RenderLayers. It determines which RenderLayers
52 // become compositing, and creates and maintains a hierarchy of
53 // GraphicsLayers based on the RenderLayer painting order.
54 //
55 // There is one RenderLayerCompositor per RenderView.
56 
57 class RenderLayerCompositor : public GraphicsLayerClient {
58 public:
59     RenderLayerCompositor(RenderView*);
60     ~RenderLayerCompositor();
61 
62     // Return true if this RenderView is in "compositing mode" (i.e. has one or more
63     // composited RenderLayers)
inCompositingMode()64     bool inCompositingMode() const { return m_compositing; }
65     // This will make a compositing layer at the root automatically, and hook up to
66     // the native view/window system.
67     void enableCompositingMode(bool enable = true);
68 
69     // Returns true if the accelerated compositing is enabled
hasAcceleratedCompositing()70     bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
71 
72     bool canRender3DTransforms() const;
73 
74     // Copy the accelerated compositing related flags from Settings
75     void cacheAcceleratedCompositingFlags();
76 
77     // Called when the layer hierarchy needs to be updated (compositing layers have been
78     // created, destroyed or re-parented).
79     void setCompositingLayersNeedRebuild(bool needRebuild = true);
compositingLayersNeedRebuild()80     bool compositingLayersNeedRebuild() const { return m_compositingLayersNeedRebuild; }
81 
82     // Controls whether or not to consult geometry when deciding which layers need
83     // to be composited. Defaults to true.
setCompositingConsultsOverlap(bool b)84     void setCompositingConsultsOverlap(bool b) { m_compositingConsultsOverlap = b; }
compositingConsultsOverlap()85     bool compositingConsultsOverlap() const { return m_compositingConsultsOverlap; }
86 
87     // GraphicsLayers buffer state, which gets pushed to the underlying platform layers
88     // at specific times.
89     void scheduleLayerFlush();
90     void flushPendingLayerChanges();
isFlushingLayers()91     bool isFlushingLayers() const { return m_flushingLayers; }
92 
93     // flushPendingLayerChanges() flushes the entire GraphicsLayer tree, which can cross frame boundaries.
94     // This call returns the rootmost compositor that is being flushed (including self).
95     RenderLayerCompositor* enclosingCompositorFlushingLayers() const;
96 
97     // Rebuild the tree of compositing layers
98     void updateCompositingLayers(CompositingUpdateType = CompositingUpdateAfterLayoutOrStyleChange, RenderLayer* updateRoot = 0);
99     // This is only used when state changes and we do not exepect a style update or layout to happen soon (e.g. when
100     // we discover that an iframe is overlapped during painting).
101     void scheduleCompositingLayerUpdate();
102     bool compositingLayerUpdatePending() const;
103 
104     // Update the compositing state of the given layer. Returns true if that state changed.
105     enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater };
106     bool updateLayerCompositingState(RenderLayer*, CompositingChangeRepaint = CompositingChangeRepaintNow);
107 
108     // Update the geometry for compositing children of compositingAncestor.
109     void updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth);
110 
111     // Whether layer's backing needs a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow).
112     bool clippedByAncestor(RenderLayer*) const;
113     // Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
114     bool clipsCompositingDescendants(const RenderLayer*) const;
115 
116     // Whether the given layer needs an extra 'contents' layer.
117     bool needsContentsCompositingLayer(const RenderLayer*) const;
118     // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
119     // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
120     IntRect calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer);
121 
122     // Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
123     void repaintOnCompositingChange(RenderLayer*);
124 
125     // Notify us that a layer has been added or removed
126     void layerWasAdded(RenderLayer* parent, RenderLayer* child);
127     void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child);
128 
129     // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
130     RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
131 
132     // Repaint parts of all composited layers that intersect the given absolute rectangle.
133     void repaintCompositedLayersAbsoluteRect(const IntRect&);
134 
135     RenderLayer* rootRenderLayer() const;
136     GraphicsLayer* rootPlatformLayer() const;
137 
138     enum RootLayerAttachment {
139         RootLayerUnattached,
140         RootLayerAttachedViaChromeClient,
141         RootLayerAttachedViaEnclosingFrame
142     };
143 
rootLayerAttachment()144     RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
145     void updateRootLayerAttachment();
146     void updateRootLayerPosition();
147 
148     void didMoveOnscreen();
149     void willMoveOffscreen();
150 
151     void didStartAcceleratedAnimation(CSSPropertyID);
152 
153 #if ENABLE(VIDEO)
154     // Use by RenderVideo to ask if it should try to use accelerated compositing.
155     bool canAccelerateVideoRendering(RenderVideo*) const;
156 #endif
157 
158     // Walk the tree looking for layers with 3d transforms. Useful in case you need
159     // to know if there is non-affine content, e.g. for drawing into an image.
160     bool has3DContent() const;
161 
162     // Most platforms connect compositing layer trees between iframes and their parent document.
163     // Some (currently just Mac) allow iframes to do their own compositing.
164     static bool allowsIndependentlyCompositedFrames(const FrameView*);
165     bool shouldPropagateCompositingToEnclosingFrame() const;
166 
167     HTMLFrameOwnerElement* enclosingFrameElement() const;
168 
169     static RenderLayerCompositor* frameContentsCompositor(RenderPart*);
170     // Return true if the layers changed.
171     static bool parentFrameContentLayers(RenderPart*);
172 
173     // Update the geometry of the layers used for clipping and scrolling in frames.
174     void frameViewDidChangeLocation(const IntPoint& contentsOffset);
175     void frameViewDidChangeSize();
176     void frameViewDidScroll(const IntPoint& = IntPoint());
177 
178     String layerTreeAsText(bool showDebugInfo = false);
179 
180     // These are named to avoid conflicts with the functions in GraphicsLayerClient
181     // These return the actual internal variables.
compositorShowDebugBorders()182     bool compositorShowDebugBorders() const { return m_showDebugBorders; }
compositorShowRepaintCounter()183     bool compositorShowRepaintCounter() const { return m_showRepaintCounter; }
184 
185     void updateContentsScale(float, RenderLayer* = 0);
186 
layerForHorizontalScrollbar()187     GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
layerForVerticalScrollbar()188     GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
layerForScrollCorner()189     GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
190 
191 private:
192     // GraphicsLayerClient Implementation
notifyAnimationStarted(const GraphicsLayer *,double)193     virtual void notifyAnimationStarted(const GraphicsLayer*, double) { }
notifySyncRequired(const GraphicsLayer *)194     virtual void notifySyncRequired(const GraphicsLayer*) { scheduleLayerFlush(); }
195     virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&);
196 
197     // These calls return false always. They are saying that the layers associated with this client
198     // (the clipLayer and scrollLayer) should never show debugging info.
showDebugBorders()199     virtual bool showDebugBorders() const { return false; }
showRepaintCounter()200     virtual bool showRepaintCounter() const { return false; }
201 
202     // Whether the given RL needs a compositing layer.
203     bool needsToBeComposited(const RenderLayer*) const;
204     // Whether the layer has an intrinsic need for compositing layer.
205     bool requiresCompositingLayer(const RenderLayer*) const;
206     // Whether the layer could ever be composited.
207     bool canBeComposited(const RenderLayer*) const;
208 
209     // Make or destroy the backing for this layer; returns true if backing changed.
210     bool updateBacking(RenderLayer*, CompositingChangeRepaint shouldRepaint);
211 
212     // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
213     void recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect);
214 
215     typedef HashMap<RenderLayer*, IntRect> OverlapMap;
216     static void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
217     static bool overlapsCompositedLayers(OverlapMap&, const IntRect& layerBounds);
218 
219     void updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*);
220 
221     // Returns true if any layer's compositing changed
222     void computeCompositingRequirements(RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged);
223 
224     // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer.
225     void rebuildCompositingLayerTree(RenderLayer* layer, const struct CompositingState&, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer);
226 
227     // Recurses down the tree, updating layer geometry only.
228     void updateLayerTreeGeometry(RenderLayer*);
229 
230     // Hook compositing layers together
231     void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
232     void removeCompositedChildren(RenderLayer*);
233 
234     bool layerHas3DContent(const RenderLayer*) const;
235 
236     void ensureRootPlatformLayer();
237     void destroyRootPlatformLayer();
238 
239     void attachRootPlatformLayer(RootLayerAttachment);
240     void detachRootPlatformLayer();
241 
242     void rootLayerAttachmentChanged();
243 
244     void updateOverflowControlsLayers();
245 
246     void scheduleNeedsStyleRecalc(Element*);
247     void notifyIFramesOfCompositingChange();
248 
249     // Whether a running transition or animation enforces the need for a compositing layer.
250     bool requiresCompositingForAnimation(RenderObject*) const;
251     bool requiresCompositingForTransform(RenderObject*) const;
252     bool requiresCompositingForVideo(RenderObject*) const;
253     bool requiresCompositingForCanvas(RenderObject*) const;
254     bool requiresCompositingForPlugin(RenderObject*) const;
255     bool requiresCompositingForFrame(RenderObject*) const;
256     bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const;
257     bool requiresCompositingForFullScreen(RenderObject*) const;
258 
259     bool requiresScrollLayer(RootLayerAttachment) const;
260     bool requiresHorizontalScrollbarLayer() const;
261     bool requiresVerticalScrollbarLayer() const;
262     bool requiresScrollCornerLayer() const;
263 
264 private:
265     RenderView* m_renderView;
266     OwnPtr<GraphicsLayer> m_rootPlatformLayer;
267     Timer<RenderLayerCompositor> m_updateCompositingLayersTimer;
268 
269     bool m_hasAcceleratedCompositing;
270     ChromeClient::CompositingTriggerFlags m_compositingTriggers;
271 
272     bool m_showDebugBorders;
273     bool m_showRepaintCounter;
274     bool m_compositingConsultsOverlap;
275 
276     // When true, we have to wait until layout has happened before we can decide whether to enter compositing mode,
277     // because only then do we know the final size of plugins and iframes.
278     // FIXME: once set, this is never cleared.
279     mutable bool m_compositingDependsOnGeometry;
280 
281     bool m_compositing;
282     bool m_compositingLayersNeedRebuild;
283     bool m_flushingLayers;
284     bool m_forceCompositingMode;
285 
286     RootLayerAttachment m_rootLayerAttachment;
287 
288     // Enclosing clipping layer for iframe content
289     OwnPtr<GraphicsLayer> m_clipLayer;
290     OwnPtr<GraphicsLayer> m_scrollLayer;
291 
292     // Enclosing layer for overflow controls and the clipping layer
293     OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;
294 
295     // Layers for overflow controls
296     OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
297     OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
298     OwnPtr<GraphicsLayer> m_layerForScrollCorner;
299 #if PROFILE_LAYER_REBUILD
300     int m_rootLayerUpdateCount;
301 #endif
302 };
303 
304 
305 } // namespace WebCore
306 
307 #endif // RenderLayerCompositor_h
308