Skip to content
  • simon.fraser@apple.com's avatar
    2010-01-15 Simon Fraser <simon.fraser@apple.com> · 823f73c8
    simon.fraser@apple.com authored
            Reviewed by Dan Bernstein and Adele Peterson.
    
            Support reflections on composited layers
            https://bugs.webkit.org/show_bug.cgi?id=31885
    
            Implement reflections (via -webkit-box-reflect:) on compositing layers.
    
            We add to the GraphicsLayer the notion of having a replica, and being a replicated layer.
            The replica layer is not parented in the tree, but referenced by another layer.
            RenderLayerBacking sets this up when it finds RenderLayers for reflections.
    
            GraphicsLayerCA implements rendering of replica layers by cloning CA layers,
            and copying their properties, including animations and contents. Deep reflections
            are supported by a hash of clone layers on each GraphicsLayerCA, indexed by
            the path down the tree to each replica instance.
    
            When GraphicsLayerCA properties are changed, in most cases the clones must also
            be updated.
    
            Tests: compositing/masks/direct-image-mask.html
                   compositing/reflections/animation-inside-reflection.html
                   compositing/reflections/compositing-change-inside-reflection.html
                   compositing/reflections/deeply-nested-reflections.html
                   compositing/reflections/masked-reflection-on-composited.html
                   compositing/reflections/nested-reflection-anchor-point.html
                   compositing/reflections/nested-reflection-animated.html
                   compositing/reflections/nested-reflection-mask-change.html
                   compositing/reflections/nested-reflection-on-overflow.html
                   compositing/reflections/nested-reflection-opacity.html
                   compositing/reflections/nested-reflection-size-change.html
                   compositing/reflections/nested-reflection-transformed.html
                   compositing/reflections/nested-reflection-transition.html
                   compositing/reflections/nested-reflection.html
                   compositing/reflections/reflection-opacity.html
                   compositing/reflections/reflection-ordering.html
                   compositing/reflections/reflection-positioning.html
                   compositing/reflections/transform-inside-reflection.html
    
            * platform/graphics/GraphicsLayer.h:
            (WebCore::GraphicsLayer::isReplicated): Returns true when this layer has a replicated layer.
            (WebCore::GraphicsLayer::replicatedLayerPosition):
            (WebCore::GraphicsLayer::setReplicatedLayerPosition): The position of the replica layer must be
            special-cased; we cannot just copy the position of the original.
            (WebCore::GraphicsLayer::didDisplay): Method that indicates that the contents of the layer changed,
            which gives us a chance to update clone layers.
            (WebCore::GraphicsLayer::replicaLayer): reference to the replica layer.
            (WebCore::GraphicsLayer::replicatedLayer): reference to the layer that this (replica) layer is replicating.
            (WebCore::GraphicsLayer::setReplicatedLayer):
    
            * platform/graphics/GraphicsLayer.cpp:
            (WebCore::GraphicsLayer::GraphicsLayer):
            (WebCore::GraphicsLayer::setReplicatedByLayer): Hook up a replica with its replicated layer.
            (WebCore::GraphicsLayer::dumpProperties):
    
            * platform/graphics/mac/GraphicsLayerCA.h:
            (WebCore::GraphicsLayerCA::primaryLayer): Returns a CALayer, since structural layers may not be WebLayers.
            (WebCore::GraphicsLayerCA::isReplicatedRootClone): Given a cloneID (string representation of the path to a clone
            down the tree, which is a bitstring of 1 (replica), or 0 (non-replica)), returns true if this ID represents the
            root of a replica tree.
            (WebCore::GraphicsLayerCA::primaryLayerClones): Returns a pointer to the hash map of clones of the primary layers.
    
            (WebCore::GraphicsLayerCA::ReplicaState::ReplicaState): Small struct used to track original/clone branching
            down the tree during recursion, to build cloneID paths.
    
            (WebCore::GraphicsLayerCA::hasCloneLayers): returns true if this layer has clone layers.
    
            * platform/graphics/mac/GraphicsLayerCA.mm:
            (WebCore::GraphicsLayerCA::~GraphicsLayerCA): remove the clone layers.
            (WebCore::GraphicsLayerCA::setChildren): call noteSublayersChanged() since we may have to update replicas too.
            (WebCore::GraphicsLayerCA::addChild): ditto
            (WebCore::GraphicsLayerCA::addChildAtIndex): ditto
            (WebCore::GraphicsLayerCA::addChildBelow): ditto
            (WebCore::GraphicsLayerCA::addChildAbove): ditto
            (WebCore::GraphicsLayerCA::replaceChild): ditto
            (WebCore::GraphicsLayerCA::removeFromParent): ditto
            (WebCore::GraphicsLayerCA::setMaskLayer): call propagateLayerChangeToReplicas()
            (WebCore::GraphicsLayerCA::setReplicatedLayer): note replica changed.
            (WebCore::GraphicsLayerCA::setReplicatedByLayer): ditto
            (WebCore::GraphicsLayerCA::moveOrCopyAllAnimationsForProperty): Enhanced to allow moving or copying animations.
            (WebCore::GraphicsLayerCA::moveOrCopyAnimationsForProperty): Ditto.
            (WebCore::GraphicsLayerCA::setContentsToImage): call noteSublayersChanged()
            (WebCore::GraphicsLayerCA::setContentsToVideo): call noteSublayersChanged()
            (WebCore::GraphicsLayerCA::didDisplay): here is our chance to copy updated contents to clone layers.
            (WebCore::GraphicsLayerCA::recursiveCommitChanges):
            (WebCore::GraphicsLayerCA::commitLayerChangesBeforeSublayers): pre-order commit, for things that need to be
                committed before we recurse on children.
            (WebCore::GraphicsLayerCA::commitLayerChangesAfterSublayers): post-order commit, for things that need to be
                committed after we recurse on children, like clones.
            (WebCore::GraphicsLayerCA::updateLayerNames): New method to match the other 'update' methods.
            (WebCore::GraphicsLayerCA::updateSublayerList): Insert replica layers into the hierarchy.
            (WebCore::GraphicsLayerCA::updateLayerPosition): update clones.
            (WebCore::GraphicsLayerCA::updateLayerSize): ditto
            (WebCore::GraphicsLayerCA::updateAnchorPoint): ditto
            (WebCore::GraphicsLayerCA::updateTransform): ditto
            (WebCore::GraphicsLayerCA::updateChildrenTransform): ditto
            (WebCore::GraphicsLayerCA::updateMasksToBounds): ditto
            (WebCore::GraphicsLayerCA::updateContentsOpaque): ditto
            (WebCore::GraphicsLayerCA::updateBackfaceVisibility): ditto
            (WebCore::GraphicsLayerCA::updateStructuralLayer): call ensureStructuralLayer()
            (WebCore::moveAnimation): utility to move a CAAnimation from one layer to another.
            (WebCore::GraphicsLayerCA::ensureStructuralLayer): refactored code which creates enclosing CALayers for reflection
            flattening, or CATransformLayers for preserve-3d.
            (WebCore::GraphicsLayerCA::structuralLayerPurpose): indicates why we need a structural layer.
            (WebCore::GraphicsLayerCA::updateLayerDrawsContent): update clones
            (WebCore::GraphicsLayerCA::updateContentsImage): ditto
            (WebCore::GraphicsLayerCA::updateContentsRect): ditto
            (WebCore::GraphicsLayerCA::updateMaskLayer): ditto
            (WebCore::GraphicsLayerCA::updateReplicatedLayers): This is where we ask for the tree of layers for the replica
            and its children, and attach them as sublayers.
            (WebCore::GraphicsLayerCA::ReplicaState::cloneID): Build a bitstring from the array of original/clone values; this
            string serves to identify clones in the hash map.
            (WebCore::GraphicsLayerCA::replicatedLayerRoot): Request the tree of clone layers, set its position and transform,
            and return it.
            (WebCore::GraphicsLayerCA::setAnimationOnLayer): update clones
            (WebCore::GraphicsLayerCA::removeAnimationFromLayer): ditto
            (WebCore::GraphicsLayerCA::pauseAnimationOnLayer): ditto
            (WebCore::GraphicsLayerCA::setContentsToGraphicsContext3D): udpate sublayers.
            (WebCore::GraphicsLayerCA::suspendAnimations): update clones.
            (WebCore::GraphicsLayerCA::resumeAnimations): ditto
            (WebCore::GraphicsLayerCA::animatedLayerClones): return the hash map for clones of the appropriate layer for the given property.
            (WebCore::GraphicsLayerCA::ensureCloneLayers): create and return clones for the CALayers for this layer.
            (WebCore::GraphicsLayerCA::removeCloneLayers): clear out the clone layers.
            (WebCore::GraphicsLayerCA::positionForCloneRootLayer): the root of a clonal subtree needs its position and transform to be special-cased,
            since it doesn't just copy those properties from the original.
            (WebCore::GraphicsLayerCA::propagateLayerChangeToReplicas): push the change flags onto the replica.
            (WebCore::GraphicsLayerCA::fetchCloneLayers): recurse down sublayers, creating clones of the CALayers along the way, and returning
            the root of the clone tree.
            (WebCore::copyAnimation): utility to copy an animation from one layer to another. Animations can be shared between layers.
            (WebCore::GraphicsLayerCA::cloneLayer): utility to clone a CALayer, copying those properties which GraphicsLayerCA makes use of
            (WebCore::GraphicsLayerCA::setOpacityInternal): push opacity changes to clones.
            (WebCore::GraphicsLayerCA::updateOpacityOnLayer): ditto
            (WebCore::GraphicsLayerCA::noteSublayersChanged): set the ChildrenChanged flag, and proprate changes to the replica, if any.
    
            * platform/graphics/mac/WebLayer.mm:
            (-[WebLayer display]): override -display so we know when to update the contents of clone layers
    
            * platform/graphics/mac/WebTiledLayer.mm:
            (-[WebTiledLayer display]): ditto.
    
            * rendering/RenderLayer.h:
            (WebCore::RenderLayer::isReflection): New method that returns true if the renderer is a replica.
    
            * rendering/RenderLayer.cpp:
            (WebCore::RenderLayer::RenderLayer): initialize m_isReflection
            (WebCore::RenderLayer::updateReflectionStyle): call setIsReflection
    
            * rendering/RenderLayerBacking.cpp:
            (WebCore::RenderLayerBacking::createGraphicsLayer): Put a name on the reflection layer.
            (WebCore::RenderLayerBacking::updateGraphicsLayerConfiguration): Hook up the GraphicsLayers for the reflection.
            (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry): Reflection overrides preserve-3d (you have to flatten to reflect).
            Also hook up updating the reflection layer geometry, and the relica position.
    
            (WebCore::RenderLayerBacking::paintIntoLayer): We no longer paint the reflection in software.
    
            * rendering/RenderLayerCompositor.cpp:
            (WebCore::RenderLayerCompositor::computeCompositingRequirements): Hook reflection layers into the compositing logic.
            (WebCore::RenderLayerCompositor::canAccelerateVideoRendering): No longer have to push video into software if it's reflected.
            (WebCore::RenderLayerCompositor::rebuildCompositingLayerTree): Update the bounds of the reflection layer.
            (WebCore::RenderLayerCompositor::updateCompositingDescendantGeometry): ditto
            (WebCore::RenderLayerCompositor::requiresCompositingWhenDescendantsAreCompositing): a compositing descendant forces
            a reflection ancestor to composite now.
            (WebCore::RenderLayerBacking::containsPaintedContent): Reflection layers don't paint anything.
            (WebCore::RenderLayerBacking::isDirectlyCompositedImage): No need to fall out of direct compositing mode
            for masks or reflections any more.
            (WebCore::RenderLayerBacking::paintIntoLayer): No need to paint the reflection manually now.
    
            * rendering/RenderObject.h:
            (WebCore::RenderObject::isReplica):
            * rendering/RenderReplica.h:
            (WebCore::RenderReplica::isReplica):
            New method used to determine if a render is a replica.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53357 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    823f73c8