1/*
2 * Copyright (C) 2010 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 GraphicsLayerCA_h
27#define GraphicsLayerCA_h
28
29#if USE(ACCELERATED_COMPOSITING)
30
31#include "GraphicsLayer.h"
32#include "Image.h"
33#include "PlatformCAAnimation.h"
34#include "PlatformCALayerClient.h"
35#include <wtf/HashMap.h>
36#include <wtf/HashSet.h>
37#include <wtf/RetainPtr.h>
38#include <wtf/text/StringHash.h>
39
40// Enable this to add a light red wash over the visible portion of Tiled Layers, as computed
41// by flushCompositingState().
42// #define VISIBLE_TILE_WASH
43
44namespace WebCore {
45
46class PlatformCALayer;
47class TransformState;
48
49class GraphicsLayerCA : public GraphicsLayer, public PlatformCALayerClient {
50public:
51    // The width and height of a single tile in a tiled layer. Should be large enough to
52    // avoid lots of small tiles (and therefore lots of drawing callbacks), but small enough
53    // to keep the overall tile cost low.
54    static const int kTiledLayerTileSize = 512;
55
56    GraphicsLayerCA(GraphicsLayerClient*);
57    virtual ~GraphicsLayerCA();
58
59    virtual void setName(const String&);
60
61    virtual PlatformLayer* platformLayer() const;
62    virtual PlatformCALayer* platformCALayer() const { return primaryLayer(); }
63
64    virtual bool setChildren(const Vector<GraphicsLayer*>&);
65    virtual void addChild(GraphicsLayer*);
66    virtual void addChildAtIndex(GraphicsLayer*, int index);
67    virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling);
68    virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling);
69    virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild);
70
71    virtual void removeFromParent();
72
73    virtual void setMaskLayer(GraphicsLayer*);
74    virtual void setReplicatedLayer(GraphicsLayer*);
75
76    virtual void setPosition(const FloatPoint&);
77    virtual void setAnchorPoint(const FloatPoint3D&);
78    virtual void setSize(const FloatSize&);
79    virtual void setBoundsOrigin(const FloatPoint&);
80
81    virtual void setTransform(const TransformationMatrix&);
82
83    virtual void setChildrenTransform(const TransformationMatrix&);
84
85    virtual void setPreserves3D(bool);
86    virtual void setMasksToBounds(bool);
87    virtual void setDrawsContent(bool);
88    virtual void setContentsVisible(bool);
89    virtual void setAcceleratesDrawing(bool);
90
91    virtual void setBackgroundColor(const Color&);
92
93    virtual void setContentsOpaque(bool);
94    virtual void setBackfaceVisibility(bool);
95
96    // return true if we started an animation
97    virtual void setOpacity(float);
98
99#if ENABLE(CSS_FILTERS)
100    virtual bool setFilters(const FilterOperations&);
101#endif
102
103    virtual void setNeedsDisplay();
104    virtual void setNeedsDisplayInRect(const FloatRect&);
105    virtual void setContentsNeedsDisplay();
106
107    virtual void setContentsRect(const IntRect&);
108
109    virtual void suspendAnimations(double time);
110    virtual void resumeAnimations();
111
112    virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& animationName, double timeOffset);
113    virtual void pauseAnimation(const String& animationName, double timeOffset);
114    virtual void removeAnimation(const String& animationName);
115
116    virtual void setContentsToImage(Image*);
117    virtual void setContentsToMedia(PlatformLayer*);
118    virtual void setContentsToCanvas(PlatformLayer*);
119    virtual void setContentsToSolidColor(const Color&);
120
121    virtual bool hasContentsLayer() const { return m_contentsLayer; }
122
123    virtual void setShowDebugBorder(bool) OVERRIDE;
124    virtual void setShowRepaintCounter(bool) OVERRIDE;
125
126    virtual void setDebugBackgroundColor(const Color&);
127    virtual void setDebugBorder(const Color&, float borderWidth);
128
129    virtual void layerDidDisplay(PlatformLayer*);
130
131    virtual void setMaintainsPixelAlignment(bool);
132    virtual void deviceOrPageScaleFactorChanged();
133
134    struct CommitState {
135        bool ancestorHasTransformAnimation;
136        int treeDepth;
137        CommitState()
138            : ancestorHasTransformAnimation(false)
139            , treeDepth(0)
140        { }
141    };
142    void recursiveCommitChanges(const CommitState&, const TransformState&, float pageScaleFactor = 1, const FloatPoint& positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false);
143
144    virtual void flushCompositingState(const FloatRect&);
145    virtual void flushCompositingStateForThisLayerOnly();
146
147    virtual bool visibleRectChangeRequiresFlush(const FloatRect& visibleRect) const OVERRIDE;
148
149    virtual TiledBacking* tiledBacking() const OVERRIDE;
150
151    bool allowTiledLayer() const { return m_allowTiledLayer; }
152    virtual void setAllowTiledLayer(bool b);
153
154protected:
155    virtual void setOpacityInternal(float);
156
157private:
158    virtual void willBeDestroyed();
159
160    // PlatformCALayerClient overrides
161    virtual void platformCALayerLayoutSublayersOfLayer(PlatformCALayer*) { }
162    virtual bool platformCALayerRespondsToLayoutChanges() const { return false; }
163
164    virtual void platformCALayerAnimationStarted(CFTimeInterval beginTime);
165    virtual CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return contentsOrientation(); }
166    virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& clip);
167    virtual bool platformCALayerShowDebugBorders() const { return isShowingDebugBorder(); }
168    virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const;
169    virtual int platformCALayerIncrementRepaintCount() { return incrementRepaintCount(); }
170
171    virtual bool platformCALayerContentsOpaque() const { return contentsOpaque(); }
172    virtual bool platformCALayerDrawsContent() const { return drawsContent(); }
173    virtual void platformCALayerLayerDidDisplay(PlatformLayer* layer) { return layerDidDisplay(layer); }
174    virtual void platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) OVERRIDE;
175    virtual float platformCALayerDeviceScaleFactor() OVERRIDE;
176
177    virtual double backingStoreMemoryEstimate() const;
178
179    virtual bool shouldRepaintOnSizeChange() const OVERRIDE;
180
181    void updateOpacityOnLayer();
182
183#if ENABLE(CSS_FILTERS)
184    void updateFilters();
185#endif
186
187    PlatformCALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); }
188    PlatformCALayer* hostLayerForSublayers() const;
189    PlatformCALayer* layerForSuperlayer() const;
190    PlatformCALayer* animatedLayer(AnimatedPropertyID) const;
191
192    typedef String CloneID; // Identifier for a given clone, based on original/replica branching down the tree.
193    static bool isReplicatedRootClone(const CloneID& cloneID) { return cloneID[0U] & 1; }
194
195    typedef HashMap<CloneID, RefPtr<PlatformCALayer> > LayerMap;
196    LayerMap* primaryLayerClones() const { return m_structuralLayer.get() ? m_structuralLayerClones.get() : m_layerClones.get(); }
197    LayerMap* animatedLayerClones(AnimatedPropertyID) const;
198
199    bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset);
200    bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset, const IntSize& boxSize);
201#if ENABLE(CSS_FILTERS)
202    bool createFilterAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset);
203#endif
204
205    // Return autoreleased animation (use RetainPtr?)
206    PassRefPtr<PlatformCAAnimation> createBasicAnimation(const Animation*, const String& keyPath, bool additive);
207    PassRefPtr<PlatformCAAnimation> createKeyframeAnimation(const Animation*, const String&, bool additive);
208    void setupAnimation(PlatformCAAnimation*, const Animation*, bool additive);
209
210    const TimingFunction* timingFunctionForAnimationValue(const AnimationValue&, const Animation&);
211
212    bool setAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
213    bool setAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
214
215    bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
216    bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
217
218#if ENABLE(CSS_FILTERS)
219    bool setFilterAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, int internalFilterPropertyIndex);
220    bool setFilterAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, int internalFilterPropertyIndex, FilterOperation::OperationType);
221#endif
222
223    bool isRunningTransformAnimation() const;
224
225    bool animationIsRunning(const String& animationName) const
226    {
227        return m_runningAnimations.find(animationName) != m_runningAnimations.end();
228    }
229
230    void commitLayerChangesBeforeSublayers(CommitState&, float pageScaleFactor, const FloatPoint& positionRelativeToBase, const FloatRect& oldVisibleRect);
231    void commitLayerChangesAfterSublayers(CommitState&);
232
233    FloatPoint computePositionRelativeToBase(float& pageScale) const;
234
235    bool requiresTiledLayer(float pageScaleFactor) const;
236    void swapFromOrToTiledLayer(bool useTiledLayer);
237
238    CompositingCoordinatesOrientation defaultContentsOrientation() const;
239
240    void setupContentsLayer(PlatformCALayer*);
241    PlatformCALayer* contentsLayer() const { return m_contentsLayer.get(); }
242
243    virtual void setReplicatedByLayer(GraphicsLayer*);
244
245    virtual void getDebugBorderInfo(Color&, float& width) const;
246    virtual void dumpAdditionalProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const;
247
248    void computePixelAlignment(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase,
249        FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const;
250    enum ComputeVisibleRectFlag { RespectAnimatingTransforms = 1 << 0 };
251    typedef unsigned ComputeVisibleRectFlags;
252    FloatRect computeVisibleRect(TransformState&, ComputeVisibleRectFlags = RespectAnimatingTransforms) const;
253    const FloatRect& visibleRect() const { return m_visibleRect; }
254
255    static FloatRect adjustTiledLayerVisibleRect(TiledBacking*, const FloatRect& oldVisibleRect, const FloatRect& newVisibleRect, const FloatSize& oldSize, const FloatSize& newSize);
256
257    bool recursiveVisibleRectChangeRequiresFlush(const TransformState&) const;
258
259    virtual bool canThrottleLayerFlush() const;
260
261    // Used to track the path down the tree for replica layers.
262    struct ReplicaState {
263        static const size_t maxReplicaDepth = 16;
264        enum ReplicaBranchType { ChildBranch = 0, ReplicaBranch = 1 };
265        ReplicaState(ReplicaBranchType firstBranch)
266            : m_replicaDepth(0)
267        {
268            push(firstBranch);
269        }
270
271        // Called as we walk down the tree to build replicas.
272        void push(ReplicaBranchType branchType)
273        {
274            m_replicaBranches.append(branchType);
275            if (branchType == ReplicaBranch)
276                ++m_replicaDepth;
277        }
278
279        void setBranchType(ReplicaBranchType branchType)
280        {
281            ASSERT(!m_replicaBranches.isEmpty());
282
283            if (m_replicaBranches.last() != branchType) {
284                if (branchType == ReplicaBranch)
285                    ++m_replicaDepth;
286                else
287                    --m_replicaDepth;
288            }
289
290            m_replicaBranches.last() = branchType;
291        }
292
293        void pop()
294        {
295            if (m_replicaBranches.last() == ReplicaBranch)
296                --m_replicaDepth;
297            m_replicaBranches.removeLast();
298        }
299
300        size_t depth() const { return m_replicaBranches.size(); }
301        size_t replicaDepth() const { return m_replicaDepth; }
302
303        CloneID cloneID() const;
304
305    private:
306        Vector<ReplicaBranchType> m_replicaBranches;
307        size_t m_replicaDepth;
308    };
309    PassRefPtr<PlatformCALayer>replicatedLayerRoot(ReplicaState&);
310
311    enum CloneLevel { RootCloneLevel, IntermediateCloneLevel };
312    PassRefPtr<PlatformCALayer> fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState&, CloneLevel);
313
314    PassRefPtr<PlatformCALayer> cloneLayer(PlatformCALayer *, CloneLevel);
315    PassRefPtr<PlatformCALayer> findOrMakeClone(CloneID, PlatformCALayer *, LayerMap*, CloneLevel);
316
317    void ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel);
318
319    bool hasCloneLayers() const { return m_layerClones; }
320    void removeCloneLayers();
321    FloatPoint positionForCloneRootLayer() const;
322
323    void propagateLayerChangeToReplicas();
324
325    // All these "update" methods will be called inside a BEGIN_BLOCK_OBJC_EXCEPTIONS/END_BLOCK_OBJC_EXCEPTIONS block.
326    void updateLayerNames();
327    void updateSublayerList(bool maxLayerDepthReached = false);
328    void updateGeometry(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase);
329    void updateTransform();
330    void updateChildrenTransform();
331    void updateMasksToBounds();
332    void updateContentsVisibility();
333    void updateContentsOpaque(float pageScaleFactor);
334    void updateBackfaceVisibility();
335    void updateStructuralLayer();
336    void updateLayerDrawsContent();
337    void updateBackgroundColor();
338
339    void updateContentsImage();
340    void updateContentsMediaLayer();
341    void updateContentsCanvasLayer();
342    void updateContentsColorLayer();
343    void updateContentsRect();
344    void updateMaskLayer();
345    void updateReplicatedLayers();
346
347    void updateAnimations();
348    void updateContentsNeedsDisplay();
349    void updateAcceleratesDrawing();
350    void updateDebugBorder();
351    void updateVisibleRect(const FloatRect& oldVisibleRect);
352    void updateContentsScale(float pageScaleFactor);
353
354    enum StructuralLayerPurpose {
355        NoStructuralLayer = 0,
356        StructuralLayerForPreserves3D,
357        StructuralLayerForReplicaFlattening
358    };
359    void ensureStructuralLayer(StructuralLayerPurpose);
360    StructuralLayerPurpose structuralLayerPurpose() const;
361
362    void setAnimationOnLayer(PlatformCAAnimation*, AnimatedPropertyID, const String& animationName, int index, int subIndex, double timeOffset);
363    bool removeCAAnimationFromLayer(AnimatedPropertyID, const String& animationName, int index, int subINdex);
364    void pauseCAAnimationOnLayer(AnimatedPropertyID, const String& animationName, int index, int subIndex, double timeOffset);
365
366    enum MoveOrCopy { Move, Copy };
367    static void moveOrCopyLayerAnimation(MoveOrCopy, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer);
368    void moveOrCopyAnimations(MoveOrCopy, PlatformCALayer * fromLayer, PlatformCALayer * toLayer);
369
370    bool appendToUncommittedAnimations(const KeyframeValueList&, const TransformOperations*, const Animation*, const String& animationName, const IntSize& boxSize, int animationIndex, double timeOffset, bool isMatrixAnimation);
371#if ENABLE(CSS_FILTERS)
372    bool appendToUncommittedAnimations(const KeyframeValueList&, const FilterOperation*, const Animation*, const String& animationName, int animationIndex, double timeOffset);
373#endif
374
375    enum LayerChange {
376        NoChange = 0,
377        NameChanged = 1 << 1,
378        ChildrenChanged = 1 << 2, // also used for content layer, and preserves-3d, and size if tiling changes?
379        GeometryChanged = 1 << 3,
380        TransformChanged = 1 << 4,
381        ChildrenTransformChanged = 1 << 5,
382        Preserves3DChanged = 1 << 6,
383        MasksToBoundsChanged = 1 << 7,
384        DrawsContentChanged = 1 << 8,
385        BackgroundColorChanged = 1 << 9,
386        ContentsOpaqueChanged = 1 << 10,
387        BackfaceVisibilityChanged = 1 << 11,
388        OpacityChanged = 1 << 12,
389        AnimationChanged = 1 << 13,
390        DirtyRectsChanged = 1 << 14,
391        ContentsImageChanged = 1 << 15,
392        ContentsMediaLayerChanged = 1 << 16,
393        ContentsCanvasLayerChanged = 1 << 17,
394        ContentsColorLayerChanged = 1 << 18,
395        ContentsRectChanged = 1 << 19,
396        MaskLayerChanged = 1 << 20,
397        ReplicatedLayerChanged = 1 << 21,
398        ContentsNeedsDisplay = 1 << 22,
399        AcceleratesDrawingChanged = 1 << 23,
400        ContentsScaleChanged = 1 << 24,
401        ContentsVisibilityChanged = 1 << 25,
402        VisibleRectChanged = 1 << 26,
403        FiltersChanged = 1 << 27,
404        TilesAdded = 1 < 28,
405        DebugIndicatorsChanged = 1 << 29
406    };
407    typedef unsigned LayerChangeFlags;
408    void noteLayerPropertyChanged(LayerChangeFlags flags);
409    void noteSublayersChanged();
410    void noteChangesForScaleSensitiveProperties();
411
412    void repaintLayerDirtyRects();
413
414    RefPtr<PlatformCALayer> m_layer; // The main layer
415    RefPtr<PlatformCALayer> m_structuralLayer; // A layer used for structural reasons, like preserves-3d or replica-flattening. Is the parent of m_layer.
416    RefPtr<PlatformCALayer> m_contentsLayer; // A layer used for inner content, like image and video
417
418    // References to clones of our layers, for replicated layers.
419    OwnPtr<LayerMap> m_layerClones;
420    OwnPtr<LayerMap> m_structuralLayerClones;
421    OwnPtr<LayerMap> m_contentsLayerClones;
422
423#ifdef VISIBLE_TILE_WASH
424    RefPtr<PlatformCALayer> m_visibleTileWashLayer;
425#endif
426    FloatRect m_visibleRect;
427    FloatSize m_sizeAtLastVisibleRectUpdate;
428
429    enum ContentsLayerPurpose {
430        NoContentsLayer = 0,
431        ContentsLayerForImage,
432        ContentsLayerForMedia,
433        ContentsLayerForCanvas,
434        ContentsLayerForBackgroundColor
435    };
436
437    ContentsLayerPurpose m_contentsLayerPurpose;
438    bool m_allowTiledLayer : 1;
439    bool m_isPageTiledBackingLayer : 1;
440
441    Color m_contentsSolidColor;
442
443    RetainPtr<CGImageRef> m_uncorrectedContentsImage;
444    RetainPtr<CGImageRef> m_pendingContentsImage;
445
446    // This represents the animation of a single property. There may be multiple transform animations for
447    // a single transition or keyframe animation, so index is used to distinguish these.
448    struct LayerPropertyAnimation {
449        LayerPropertyAnimation(PassRefPtr<PlatformCAAnimation> caAnimation, const String& animationName, AnimatedPropertyID property, int index, int subIndex, double timeOffset)
450        : m_animation(caAnimation)
451        , m_name(animationName)
452        , m_property(property)
453        , m_index(index)
454        , m_subIndex(subIndex)
455        , m_timeOffset(timeOffset)
456        { }
457
458        RefPtr<PlatformCAAnimation> m_animation;
459        String m_name;
460        AnimatedPropertyID m_property;
461        int m_index;
462        int m_subIndex;
463        double m_timeOffset;
464    };
465
466    // Uncommitted transitions and animations.
467    Vector<LayerPropertyAnimation> m_uncomittedAnimations;
468
469    enum Action { Remove, Pause };
470    struct AnimationProcessingAction {
471        AnimationProcessingAction(Action action = Remove, double timeOffset = 0)
472            : action(action)
473            , timeOffset(timeOffset)
474        {
475        }
476        Action action;
477        double timeOffset; // only used for pause
478    };
479    typedef HashMap<String, AnimationProcessingAction> AnimationsToProcessMap;
480    AnimationsToProcessMap m_animationsToProcess;
481
482    // Map of animation names to their associated lists of property animations, so we can remove/pause them.
483    typedef HashMap<String, Vector<LayerPropertyAnimation> > AnimationsMap;
484    AnimationsMap m_runningAnimations;
485
486    Vector<FloatRect> m_dirtyRects;
487    FloatSize m_pixelAlignmentOffset;
488
489    LayerChangeFlags m_uncommittedChanges;
490};
491
492} // namespace WebCore
493
494
495#endif // USE(ACCELERATED_COMPOSITING)
496
497#endif // GraphicsLayerCA_h
498