• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "config.h"
27 
28 #if USE(ACCELERATED_COMPOSITING)
29 
30 #include "AnimationController.h"
31 #include "CSSPropertyNames.h"
32 #include "CSSStyleSelector.h"
33 #include "FrameView.h"
34 #include "GraphicsContext.h"
35 #include "GraphicsLayer.h"
36 #include "HTMLElement.h"
37 #include "HTMLNames.h"
38 #include "RenderBox.h"
39 #include "RenderImage.h"
40 #include "RenderLayerCompositor.h"
41 #include "RenderVideo.h"
42 #include "RenderView.h"
43 
44 #include "RenderLayerBacking.h"
45 
46 using namespace std;
47 
48 namespace WebCore {
49 
50 static bool hasBorderOutlineOrShadow(const RenderStyle*);
51 static bool hasBoxDecorations(const RenderStyle*);
52 static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle*);
53 
RenderLayerBacking(RenderLayer * layer)54 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
55     : m_owningLayer(layer)
56     , m_ancestorClippingLayer(0)
57     , m_graphicsLayer(0)
58     , m_foregroundLayer(0)
59     , m_clippingLayer(0)
60     , m_hasDirectlyCompositedContent(false)
61 {
62     createGraphicsLayer();
63 }
64 
~RenderLayerBacking()65 RenderLayerBacking::~RenderLayerBacking()
66 {
67     updateClippingLayers(false, false);
68     updateForegroundLayer(false);
69     destroyGraphicsLayer();
70 }
71 
createGraphicsLayer()72 void RenderLayerBacking::createGraphicsLayer()
73 {
74     m_graphicsLayer = GraphicsLayer::createGraphicsLayer(this);
75 
76 #ifndef NDEBUG
77     if (renderer()->node()) {
78         if (renderer()->node()->isDocumentNode())
79             m_graphicsLayer->setName("Document Node");
80         else {
81             if (renderer()->node()->isHTMLElement() && renderer()->node()->hasID())
82                 m_graphicsLayer->setName(renderer()->renderName() + String(" ") + static_cast<HTMLElement*>(renderer()->node())->id());
83             else
84                 m_graphicsLayer->setName(renderer()->renderName());
85         }
86     } else
87         m_graphicsLayer->setName("Anonymous Node");
88 #endif  // NDEBUG
89 
90     updateLayerOpacity();
91     updateLayerTransform();
92 }
93 
destroyGraphicsLayer()94 void RenderLayerBacking::destroyGraphicsLayer()
95 {
96     if (m_graphicsLayer)
97         m_graphicsLayer->removeFromParent();
98 
99     delete m_graphicsLayer;
100     m_graphicsLayer = 0;
101 
102     delete m_foregroundLayer;
103     m_foregroundLayer = 0;
104 
105     delete m_clippingLayer;
106     m_clippingLayer = 0;
107 }
108 
updateLayerOpacity()109 void RenderLayerBacking::updateLayerOpacity()
110 {
111     m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()));
112 }
113 
updateLayerTransform()114 void RenderLayerBacking::updateLayerTransform()
115 {
116     RenderStyle* style = renderer()->style();
117 
118     // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
119     // baked into it, and we don't want that.
120     TransformationMatrix t;
121     if (m_owningLayer->hasTransform()) {
122         style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
123         makeMatrixRenderable(t, compositor()->hasAcceleratedCompositing());
124     }
125 
126     m_graphicsLayer->setTransform(t);
127 }
128 
updateAfterLayout(UpdateDepth updateDepth)129 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth)
130 {
131     RenderLayerCompositor* layerCompositor = compositor();
132     if (!layerCompositor->compositingLayersNeedRebuild()) {
133         // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
134         // position of this layer's GraphicsLayer depends on the position of our compositing
135         // ancestor's GraphicsLayer. That cannot be determined until all the descendant
136         // RenderLayers of that ancestor have been processed via updateLayerPositions().
137         //
138         // The solution is to update compositing children of this layer here,
139         // via updateCompositingChildrenGeometry().
140         setCompositedBounds(layerCompositor->calculateCompositedBounds(m_owningLayer, m_owningLayer));
141         layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth);
142 
143         if (!m_owningLayer->parent()) {
144             updateGraphicsLayerGeometry();
145             layerCompositor->updateRootLayerPosition();
146         }
147     }
148 }
149 
updateGraphicsLayerConfiguration()150 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
151 {
152     RenderLayerCompositor* compositor = this->compositor();
153 
154     bool layerConfigChanged = false;
155     if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
156         layerConfigChanged = true;
157 
158     if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
159         layerConfigChanged = true;
160 
161     m_hasDirectlyCompositedContent = false;
162     if (canUseDirectCompositing()) {
163         if (renderer()->isImage()) {
164             updateImageContents();
165             m_hasDirectlyCompositedContent = true;
166             m_graphicsLayer->setDrawsContent(false);
167         }
168 
169         if (rendererHasBackground())
170             m_graphicsLayer->setBackgroundColor(rendererBackgroundColor());
171         else
172             m_graphicsLayer->clearBackgroundColor();
173     }
174 
175     return layerConfigChanged;
176 }
177 
updateGraphicsLayerGeometry()178 void RenderLayerBacking::updateGraphicsLayerGeometry()
179 {
180     // If we haven't built z-order lists yet, wait until later.
181     if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
182         return;
183 
184     // Set transform property, if it is not animating. We have to do this here because the transform
185     // is affected by the layer dimensions.
186     if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyWebkitTransform))
187         updateLayerTransform();
188 
189     // Set opacity, if it is not animating.
190     if (!renderer()->animation()->isAnimatingPropertyOnRenderer(renderer(), CSSPropertyOpacity))
191         updateLayerOpacity();
192 
193     RenderStyle* style = renderer()->style();
194     m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D);
195     m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
196 
197     RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
198 
199     // We compute everything relative to the enclosing compositing layer.
200     IntRect ancestorCompositingBounds;
201     if (compAncestor) {
202         ASSERT(compAncestor->backing());
203         ancestorCompositingBounds = compAncestor->backing()->compositedBounds();
204     }
205 
206     IntRect localCompositingBounds = compositedBounds();
207 
208     IntRect relativeCompositingBounds(localCompositingBounds);
209     int deltaX = 0, deltaY = 0;
210     m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY);
211     relativeCompositingBounds.move(deltaX, deltaY);
212 
213     IntPoint graphicsLayerParentLocation;
214     if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
215         // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
216         // position relative to it.
217         graphicsLayerParentLocation = toRenderBox(compAncestor->renderer())->overflowClipRect(0, 0).location();
218     } else
219         graphicsLayerParentLocation = ancestorCompositingBounds.location();
220 
221     if (compAncestor && m_ancestorClippingLayer) {
222         // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
223         // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
224         // for a compositing layer, rootLayer is the layer itself.
225         ClipRects parentRects;
226         m_owningLayer->parentClipRects(compAncestor, parentRects, true);
227         IntRect parentClipRect = parentRects.overflowClipRect();
228 
229         m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
230         m_ancestorClippingLayer->setSize(parentClipRect.size());
231 
232         // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
233         IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY);
234         m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset);
235 
236         // The primary layer is then parented in, and positioned relative to this clipping layer.
237         graphicsLayerParentLocation = parentClipRect.location();
238     }
239 
240     m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
241     m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
242 
243     FloatSize oldSize = m_graphicsLayer->size();
244     FloatSize newSize = relativeCompositingBounds.size();
245     if (oldSize != newSize) {
246         m_graphicsLayer->setSize(newSize);
247         // A bounds change will almost always require redisplay. Usually that redisplay
248         // will happen because of a repaint elsewhere, but not always:
249         // e.g. see RenderView::setMaximalOutlineSize()
250         m_graphicsLayer->setNeedsDisplay();
251     }
252 
253     // If we have a layer that clips children, position it.
254     if (m_clippingLayer) {
255         IntRect clippingBox = toRenderBox(renderer())->overflowClipRect(0, 0);
256         m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
257         m_clippingLayer->setSize(clippingBox.size());
258         m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
259     }
260 
261     if (m_owningLayer->hasTransform()) {
262         const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
263 
264         // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
265         IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height());
266 
267         // Update properties that depend on layer dimensions
268         FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
269         // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
270         FloatPoint3D anchor(relativeCompositingBounds.width()  != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width()  : 0.5f,
271                             relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
272                             transformOrigin.z());
273         m_graphicsLayer->setAnchorPoint(anchor);
274 
275         RenderStyle* style = renderer()->style();
276         if (style->hasPerspective()) {
277             TransformationMatrix t = owningLayer()->perspectiveTransform();
278 
279             if (m_clippingLayer) {
280                 m_clippingLayer->setChildrenTransform(t);
281                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
282             }
283             else
284                 m_graphicsLayer->setChildrenTransform(t);
285         } else {
286             if (m_clippingLayer)
287                 m_clippingLayer->setChildrenTransform(TransformationMatrix());
288             else
289                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
290         }
291     } else {
292         m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
293     }
294 
295     if (m_foregroundLayer) {
296         // The contents layer is always coincidental with the graphicsLayer for now.
297         m_foregroundLayer->setPosition(IntPoint(0, 0));
298         m_foregroundLayer->setSize(newSize);
299         m_foregroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
300     }
301 
302     m_graphicsLayer->setContentsRect(contentsBox());
303     if (!m_hasDirectlyCompositedContent)
304         m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow());
305 }
306 
updateInternalHierarchy()307 void RenderLayerBacking::updateInternalHierarchy()
308 {
309     // m_foregroundLayer has to be inserted in the correct order with child layers,
310     // so it's not inserted here.
311     if (m_ancestorClippingLayer) {
312         m_ancestorClippingLayer->removeAllChildren();
313         m_graphicsLayer->removeFromParent();
314         m_ancestorClippingLayer->addChild(m_graphicsLayer);
315     }
316 
317     if (m_clippingLayer) {
318         m_clippingLayer->removeFromParent();
319         m_graphicsLayer->addChild(m_clippingLayer);
320     }
321 }
322 
323 // Return true if the layers changed.
updateClippingLayers(bool needsAncestorClip,bool needsDescendantClip)324 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
325 {
326     bool layersChanged = false;
327 
328     if (needsAncestorClip) {
329         if (!m_ancestorClippingLayer) {
330             m_ancestorClippingLayer = GraphicsLayer::createGraphicsLayer(this);
331 #ifndef NDEBUG
332             m_ancestorClippingLayer->setName("Ancestor clipping Layer");
333 #endif
334             m_ancestorClippingLayer->setMasksToBounds(true);
335             layersChanged = true;
336         }
337     } else if (m_ancestorClippingLayer) {
338         m_ancestorClippingLayer->removeFromParent();
339         delete m_ancestorClippingLayer;
340         m_ancestorClippingLayer = 0;
341         layersChanged = true;
342     }
343 
344     if (needsDescendantClip) {
345         if (!m_clippingLayer) {
346             m_clippingLayer = GraphicsLayer::createGraphicsLayer(0);
347 #ifndef NDEBUG
348             m_clippingLayer->setName("Child clipping Layer");
349 #endif
350             m_clippingLayer->setMasksToBounds(true);
351             layersChanged = true;
352         }
353     } else if (m_clippingLayer) {
354         m_clippingLayer->removeFromParent();
355         delete m_clippingLayer;
356         m_clippingLayer = 0;
357         layersChanged = true;
358     }
359 
360     if (layersChanged)
361         updateInternalHierarchy();
362 
363     return layersChanged;
364 }
365 
updateForegroundLayer(bool needsForegroundLayer)366 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
367 {
368     bool layerChanged = false;
369     if (needsForegroundLayer) {
370         if (!m_foregroundLayer) {
371             m_foregroundLayer = GraphicsLayer::createGraphicsLayer(this);
372 #ifndef NDEBUG
373             m_foregroundLayer->setName("Contents");
374 #endif
375             m_foregroundLayer->setDrawsContent(true);
376             m_foregroundLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
377             m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask);
378             layerChanged = true;
379         }
380     } else if (m_foregroundLayer) {
381         m_foregroundLayer->removeFromParent();
382         delete m_foregroundLayer;
383         m_foregroundLayer = 0;
384         m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask);
385         layerChanged = true;
386     }
387     return layerChanged;
388 }
389 
compositingOpacity(float rendererOpacity) const390 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
391 {
392     float finalOpacity = rendererOpacity;
393 
394     for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
395         // We only care about parents that are stacking contexts.
396         // Recall that opacity creates stacking context.
397         if (!curr->isStackingContext())
398             continue;
399 
400         // If we found a compositing layer, we want to compute opacity
401         // relative to it. So we can break here.
402         if (curr->isComposited())
403             break;
404 
405         finalOpacity *= curr->renderer()->opacity();
406     }
407 
408     return finalOpacity;
409 }
410 
hasBorderOutlineOrShadow(const RenderStyle * style)411 static bool hasBorderOutlineOrShadow(const RenderStyle* style)
412 {
413     return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow();
414 }
415 
hasBoxDecorations(const RenderStyle * style)416 static bool hasBoxDecorations(const RenderStyle* style)
417 {
418     return hasBorderOutlineOrShadow(style) || style->hasBackground();
419 }
420 
hasBoxDecorationsWithBackgroundImage(const RenderStyle * style)421 static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle* style)
422 {
423     return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage();
424 }
425 
rendererHasBackground() const426 bool RenderLayerBacking::rendererHasBackground() const
427 {
428     // FIXME: share more code here
429     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
430         RenderObject* htmlObject = renderer()->firstChild();
431         if (!htmlObject)
432             return false;
433 
434         RenderStyle* style = htmlObject->style();
435         if (style->hasBackground())
436             return true;
437 
438         RenderObject* bodyObject = htmlObject->firstChild();
439         if (!bodyObject)
440             return false;
441 
442         style = bodyObject->style();
443         return style->hasBackground();
444     }
445 
446     return renderer()->style()->hasBackground();
447 }
448 
rendererBackgroundColor() const449 const Color& RenderLayerBacking::rendererBackgroundColor() const
450 {
451     // FIXME: share more code here
452     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
453         RenderObject* htmlObject = renderer()->firstChild();
454         RenderStyle* style = htmlObject->style();
455         if (style->hasBackground())
456             return style->backgroundColor();
457 
458         RenderObject* bodyObject = htmlObject->firstChild();
459         style = bodyObject->style();
460         return style->backgroundColor();
461     }
462 
463     return renderer()->style()->backgroundColor();
464 }
465 
466 // A "simple container layer" is a RenderLayer which has no visible content to render.
467 // It may have no children, or all its children may be themselves composited.
468 // This is a useful optimization, because it allows us to avoid allocating backing store.
isSimpleContainerCompositingLayer() const469 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
470 {
471     RenderObject* renderObject = renderer();
472     if (renderObject->isReplaced() ||       // replaced objects are not containers
473         renderObject->hasMask())            // masks require special treatment
474         return false;
475 
476     RenderStyle* style = renderObject->style();
477 
478     // Reject anything that has a border, a border-radius or outline,
479     // or any background (color or image).
480     // FIXME: we could optimize layers for simple backgrounds.
481     if (hasBoxDecorations(style))
482         return false;
483 
484     // If we have got this far and the renderer has no children, then we're ok.
485     if (!renderObject->firstChild())
486         return true;
487 
488     if (renderObject->node() && renderObject->node()->isDocumentNode()) {
489         // Look to see if the root object has a non-simple backgound
490         RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
491         if (!rootObject)
492             return false;
493 
494         style = rootObject->style();
495 
496         // Reject anything that has a border, a border-radius or outline,
497         // or is not a simple background (no background, or solid color).
498         if (hasBoxDecorationsWithBackgroundImage(style))
499             return false;
500 
501         // Now look at the body's renderer.
502         HTMLElement* body = renderObject->document()->body();
503         RenderObject* bodyObject = (body && body->hasLocalName(HTMLNames::bodyTag)) ? body->renderer() : 0;
504         if (!bodyObject)
505             return false;
506 
507         style = bodyObject->style();
508 
509         if (hasBoxDecorationsWithBackgroundImage(style))
510             return false;
511 
512         // Ceck to see if all the body's children are compositing layers.
513         if (hasNonCompositingContent())
514             return false;
515 
516         return true;
517     }
518 
519     // Check to see if all the renderer's children are compositing layers.
520     if (hasNonCompositingContent())
521         return false;
522 
523     return true;
524 }
525 
hasNonCompositingContent() const526 bool RenderLayerBacking::hasNonCompositingContent() const
527 {
528     // Conservative test for having no rendered children.
529 
530     // Some HTML can cause whitespace text nodes to have renderers, like:
531     // <div>
532     // <img src=...>
533     // </div>
534     // so test for 0x0 RenderTexts here
535     for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
536         if (!child->hasLayer()) {
537             if (child->isRenderInline() || !child->isBox())
538                 return true;
539 
540             if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
541                 return true;
542         }
543     }
544 
545     // FIXME: test for overflow controls.
546     if (m_owningLayer->isStackingContext()) {
547         // Use the m_hasCompositingDescendant bit to optimize?
548         if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
549             size_t listSize = negZOrderList->size();
550             for (size_t i = 0; i < listSize; ++i) {
551                 RenderLayer* curLayer = negZOrderList->at(i);
552                 if (!curLayer->isComposited())
553                     return true;
554             }
555         }
556 
557         if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
558             size_t listSize = posZOrderList->size();
559             for (size_t i = 0; i < listSize; ++i) {
560                 RenderLayer* curLayer = posZOrderList->at(i);
561                 if (!curLayer->isComposited())
562                     return true;
563             }
564         }
565     }
566 
567     if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
568         size_t listSize = normalFlowList->size();
569         for (size_t i = 0; i < listSize; ++i) {
570             RenderLayer* curLayer = normalFlowList->at(i);
571             if (!curLayer->isComposited())
572                 return true;
573         }
574     }
575 
576     return false;
577 }
578 
579 // A layer can use direct compositing if the render layer's object is a replaced object and has no children.
580 // This allows the GraphicsLayer to display the RenderLayer contents directly; it's used for images.
canUseDirectCompositing() const581 bool RenderLayerBacking::canUseDirectCompositing() const
582 {
583     RenderObject* renderObject = renderer();
584 
585     // Reject anything that isn't an image
586     if (!renderObject->isImage() && !renderObject->isVideo())
587         return false;
588 
589     if (renderObject->hasMask() || renderObject->hasReflection())
590         return false;
591 
592     // Video can use an inner layer even if it has box decorations; we draw those into another layer.
593     if (renderObject->isVideo())
594         return true;
595 
596     // Reject anything that would require the image to be drawn via the GraphicsContext,
597     // like border, shadows etc. Solid background color is OK.
598     return !hasBoxDecorationsWithBackgroundImage(renderObject->style());
599 }
600 
rendererContentChanged()601 void RenderLayerBacking::rendererContentChanged()
602 {
603     if (canUseDirectCompositing() && renderer()->isImage())
604         updateImageContents();
605 }
606 
updateImageContents()607 void RenderLayerBacking::updateImageContents()
608 {
609     ASSERT(renderer()->isImage());
610     RenderImage* imageRenderer = toRenderImage(renderer());
611 
612     CachedImage* cachedImage = imageRenderer->cachedImage();
613     if (!cachedImage)
614         return;
615 
616     Image* image = cachedImage->image();
617     if (!image)
618         return;
619 
620     // We have to wait until the image is fully loaded before setting it on the layer.
621     if (!cachedImage->isLoaded())
622         return;
623 
624     // This is a no-op if the layer doesn't have an inner layer for the image.
625     m_graphicsLayer->setContentsToImage(image);
626 
627     // Image animation is "lazy", in that it automatically stops unless someone is drawing
628     // the image. So we have to kick the animation each time; this has the downside that the
629     // image will keep animating, even if its layer is not visible.
630     image->startAnimation();
631 }
632 
computeTransformOrigin(const IntRect & borderBox) const633 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
634 {
635     RenderStyle* style = renderer()->style();
636 
637     FloatPoint3D origin;
638     origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
639     origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
640     origin.setZ(style->transformOriginZ());
641 
642     return origin;
643 }
644 
computePerspectiveOrigin(const IntRect & borderBox) const645 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
646 {
647     RenderStyle* style = renderer()->style();
648 
649     float boxWidth = borderBox.width();
650     float boxHeight = borderBox.height();
651 
652     FloatPoint origin;
653     origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth));
654     origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight));
655 
656     return origin;
657 }
658 
659 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
contentOffsetInCompostingLayer() const660 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
661 {
662     return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
663 }
664 
contentsBox() const665 IntRect RenderLayerBacking::contentsBox() const
666 {
667     if (!renderer()->isBox())
668         return IntRect();
669 
670     IntRect contentsRect;
671 #if ENABLE(VIDEO)
672     if (renderer()->isVideo()) {
673         RenderVideo* videoRenderer = toRenderVideo(renderer());
674         contentsRect = videoRenderer->videoBox();
675     } else
676 #endif
677         contentsRect = toRenderBox(renderer())->contentBoxRect();
678 
679     IntSize contentOffset = contentOffsetInCompostingLayer();
680     contentsRect.move(contentOffset);
681     return contentsRect;
682 }
683 
684 // Map the given point from coordinates in the GraphicsLayer to RenderLayer coordinates.
graphicsLayerToContentsCoordinates(const GraphicsLayer * graphicsLayer,const FloatPoint & point)685 FloatPoint RenderLayerBacking::graphicsLayerToContentsCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point)
686 {
687     return point + FloatSize(graphicsLayer->offsetFromRenderer());
688 }
689 
690 // Map the given point from coordinates in the RenderLayer to GraphicsLayer coordinates.
contentsToGraphicsLayerCoordinates(const GraphicsLayer * graphicsLayer,const FloatPoint & point)691 FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point)
692 {
693     return point - FloatSize(graphicsLayer->offsetFromRenderer());
694 }
695 
paintingGoesToWindow() const696 bool RenderLayerBacking::paintingGoesToWindow() const
697 {
698     return m_owningLayer->isRootLayer();
699 }
700 
setContentsNeedDisplay()701 void RenderLayerBacking::setContentsNeedDisplay()
702 {
703     if (m_graphicsLayer && m_graphicsLayer->drawsContent())
704         m_graphicsLayer->setNeedsDisplay();
705 
706     if (m_foregroundLayer && m_foregroundLayer->drawsContent())
707         m_foregroundLayer->setNeedsDisplay();
708 }
709 
710 // r is in the coordinate space of the layer's render object
setContentsNeedDisplayInRect(const IntRect & r)711 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
712 {
713     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
714         FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y()));
715         FloatRect dirtyRect(dirtyOrigin, r.size());
716         FloatRect bounds(FloatPoint(), m_graphicsLayer->size());
717         if (bounds.intersects(dirtyRect))
718             m_graphicsLayer->setNeedsDisplayInRect(dirtyRect);
719     }
720 
721     if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
722         // FIXME: do incremental repaint
723         m_foregroundLayer->setNeedsDisplay();
724     }
725 }
726 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)727 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
728 {
729     if (paintDirtyRect == clipRect)
730         return;
731     p->save();
732     p->clip(clipRect);
733 }
734 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)735 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
736 {
737     if (paintDirtyRect == clipRect)
738         return;
739     p->restore();
740 }
741 
742 // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
paintIntoLayer(RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintRestriction paintRestriction,GraphicsLayerPaintingPhase paintingPhase,RenderObject * paintingRoot)743 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
744                     const IntRect& paintDirtyRect,      // in the coords of rootLayer
745                     PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
746                     RenderObject* paintingRoot)
747 {
748     if (paintingGoesToWindow()) {
749         ASSERT_NOT_REACHED();
750         return;
751     }
752 
753     m_owningLayer->updateLayerListsIfNeeded();
754 
755     // Paint the reflection first if we have one.
756     if (m_owningLayer->hasReflection()) {
757         // Mark that we are now inside replica painting.
758         m_owningLayer->setPaintingInsideReflection(true);
759         m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection);
760         m_owningLayer->setPaintingInsideReflection(false);
761     }
762 
763     // Calculate the clip rects we should use.
764     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
765     m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
766 
767     int x = layerBounds.x();        // layerBounds is computed relative to rootLayer
768     int y = layerBounds.y();
769     int tx = x - m_owningLayer->renderBoxX();
770     int ty = y - m_owningLayer->renderBoxY();
771 
772     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
773     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
774     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
775     // so it will be tested against as we decend through the renderers.
776     RenderObject *paintingRootForRenderer = 0;
777     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
778         paintingRootForRenderer = paintingRoot;
779 
780     bool shouldPaint = m_owningLayer->hasVisibleContent() && m_owningLayer->isSelfPaintingLayer();
781 
782     if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackgroundMask)) {
783         // If this is the root then we need to send in a bigger bounding box
784         // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
785         IntRect paintBox = clipRectToApply;
786 
787         // FIXME: do we need this code?
788         if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
789             RenderBox* box = toRenderBox(renderer());
790             int w = box->width();
791             int h = box->height();
792 
793             int rw;
794             int rh;
795             if (box->view()->frameView()) {
796                 rw = box->view()->frameView()->contentsWidth();
797                 rh = box->view()->frameView()->contentsHeight();
798             } else {
799                 rw = box->view()->width();
800                 rh = box->view()->height();
801             }
802 
803             int bx = tx - box->marginLeft();
804             int by = ty - box->marginTop();
805             int bw = max(w + box->marginLeft() + box->marginRight() + box->borderLeft() + box->borderRight(), rw);
806             int bh = max(h + box->marginTop() + box->marginBottom() + box->borderTop() + box->borderBottom(), rh);
807             paintBox = IntRect(bx, by, bw, bh);
808         }
809 
810         // Paint our background first, before painting any child layers.
811         // Establish the clip used to paint our background.
812         setClip(context, paintDirtyRect, damageRect);
813 
814         RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
815         renderer()->paint(info, tx, ty);
816 
817         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
818         // z-index.  We paint after we painted the background/border, so that the scrollbars will
819         // sit above the background/border.
820         m_owningLayer->paintOverflowControls(context, x, y, damageRect);
821 
822         // Restore the clip.
823         restoreClip(context, paintDirtyRect, damageRect);
824     }
825 
826     if (shouldPaint && (paintingPhase & GraphicsLayerPaintForegroundMask)) {
827         // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
828         // FIXME: should these be painted as background?
829         Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
830         if (negZOrderList) {
831             for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it)
832                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
833         }
834 
835         bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
836         bool selectionOnly  = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
837 
838         // Set up the clip used when painting our children.
839         setClip(context, paintDirtyRect, clipRectToApply);
840         RenderObject::PaintInfo paintInfo(context, clipRectToApply,
841                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
842                                           forceBlackText, paintingRootForRenderer, 0);
843         renderer()->paint(paintInfo, tx, ty);
844 
845         if (!selectionOnly) {
846             paintInfo.phase = PaintPhaseFloat;
847             renderer()->paint(paintInfo, tx, ty);
848 
849             paintInfo.phase = PaintPhaseForeground;
850             renderer()->paint(paintInfo, tx, ty);
851 
852             paintInfo.phase = PaintPhaseChildOutlines;
853             renderer()->paint(paintInfo, tx, ty);
854         }
855 
856         // Now restore our clip.
857         restoreClip(context, paintDirtyRect, clipRectToApply);
858 
859         if (!outlineRect.isEmpty()) {
860             // Paint our own outline
861             RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
862             setClip(context, paintDirtyRect, outlineRect);
863             renderer()->paint(paintInfo, tx, ty);
864             restoreClip(context, paintDirtyRect, outlineRect);
865         }
866 
867         // Paint any child layers that have overflow.
868         Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList();
869         if (normalFlowList) {
870             for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it)
871                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
872         }
873 
874         // Now walk the sorted list of children with positive z-indices.
875         Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
876         if (posZOrderList) {
877             for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it)
878                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
879         }
880 
881         if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
882             setClip(context, paintDirtyRect, damageRect);
883 
884             // Paint the mask.
885             RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
886             renderer()->paint(paintInfo, tx, ty);
887 
888             // Restore the clip.
889             restoreClip(context, paintDirtyRect, damageRect);
890         }
891     }
892 
893     ASSERT(!m_owningLayer->m_usedTransparency);
894 }
895 
896 // Up-call from compositing layer drawing callback.
paintContents(const GraphicsLayer *,GraphicsContext & context,GraphicsLayerPaintingPhase drawingPhase,const IntRect & clip)897 void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip)
898 {
899     // We have to use the same root as for hit testing, because both methods
900     // can compute and cache clipRects.
901     IntRect enclosingBBox = compositedBounds();
902 
903     IntRect clipRect(clip);
904 
905     // Set up the coordinate space to be in the layer's rendering coordinates.
906     context.translate(-enclosingBBox.x(), -enclosingBBox.y());
907 
908     // Offset the clip.
909     clipRect.move(enclosingBBox.x(), enclosingBBox.y());
910 
911     // The dirtyRect is in the coords of the painting root.
912     IntRect dirtyRect = enclosingBBox;
913     dirtyRect.intersect(clipRect);
914 
915     paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, drawingPhase, renderer());
916 }
917 
startAnimation(double beginTime,const Animation * anim,const KeyframeList & keyframes)918 bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes)
919 {
920     bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
921     bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform);
922 
923     if (!hasOpacity && !hasTransform)
924         return false;
925 
926     KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
927     KeyframeValueList opacityVector(AnimatedPropertyOpacity);
928 
929     for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) {
930         const RenderStyle* keyframeStyle = it->style();
931         float key = it->key();
932 
933         if (!keyframeStyle)
934             continue;
935 
936         // get timing function
937         const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
938 
939         if (hasTransform)
940             transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
941 
942         if (hasOpacity)
943             opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
944     }
945 
946     bool didAnimateTransform = !hasTransform;
947     bool didAnimateOpacity = !hasOpacity;
948 
949     if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), beginTime))
950         didAnimateTransform = true;
951 
952     if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), beginTime))
953         didAnimateOpacity = true;
954 
955     bool runningAcceleratedAnimation = didAnimateTransform && didAnimateOpacity;
956     if (runningAcceleratedAnimation)
957         compositor()->didStartAcceleratedAnimation();
958 
959     return runningAcceleratedAnimation;
960 }
961 
startTransition(double beginTime,int property,const RenderStyle * fromStyle,const RenderStyle * toStyle)962 bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
963 {
964     bool didAnimate = false;
965     ASSERT(property != cAnimateAll);
966 
967     if (property == (int)CSSPropertyOpacity) {
968         const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
969         if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
970             KeyframeValueList opacityVector(AnimatedPropertyOpacity);
971             opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
972             opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
973             if (m_graphicsLayer->addAnimation(opacityVector, toRenderBox(renderer())->borderBoxRect().size(), opacityAnim, String(), beginTime))
974                 didAnimate = true;
975         }
976     }
977 
978     if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
979         const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
980         if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
981             KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
982             transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
983             transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
984             if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, String(), beginTime))
985                 didAnimate = true;
986         }
987     }
988 
989     if (didAnimate)
990         compositor()->didStartAcceleratedAnimation();
991 
992     return didAnimate;
993 }
994 
notifyAnimationStarted(const GraphicsLayer *,double time)995 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
996 {
997     renderer()->animation()->notifyAnimationStarted(renderer(), time);
998 }
999 
notifySyncRequired(const GraphicsLayer *)1000 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*)
1001 {
1002     if (!renderer()->documentBeingDestroyed())
1003         compositor()->scheduleSync();
1004 }
1005 
animationFinished(const String & animationName)1006 void RenderLayerBacking::animationFinished(const String& animationName)
1007 {
1008     m_graphicsLayer->removeAnimationsForKeyframes(animationName);
1009 }
1010 
animationPaused(const String & animationName)1011 void RenderLayerBacking::animationPaused(const String& animationName)
1012 {
1013     m_graphicsLayer->pauseAnimation(animationName);
1014 }
1015 
transitionFinished(int property)1016 void RenderLayerBacking::transitionFinished(int property)
1017 {
1018     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1019     if (animatedProperty != AnimatedPropertyInvalid)
1020         m_graphicsLayer->removeAnimationsForProperty(animatedProperty);
1021 }
1022 
suspendAnimations(double time)1023 void RenderLayerBacking::suspendAnimations(double time)
1024 {
1025     m_graphicsLayer->suspendAnimations(time);
1026 }
1027 
resumeAnimations()1028 void RenderLayerBacking::resumeAnimations()
1029 {
1030     m_graphicsLayer->resumeAnimations();
1031 }
1032 
compositedBounds() const1033 IntRect RenderLayerBacking::compositedBounds() const
1034 {
1035     return m_compositedBounds;
1036 }
1037 
setCompositedBounds(const IntRect & bounds)1038 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
1039 {
1040     m_compositedBounds = bounds;
1041 
1042 }
graphicsLayerToCSSProperty(AnimatedPropertyID property)1043 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
1044 {
1045     int cssProperty = CSSPropertyInvalid;
1046     switch (property) {
1047         case AnimatedPropertyWebkitTransform:
1048             cssProperty = CSSPropertyWebkitTransform;
1049             break;
1050         case AnimatedPropertyOpacity:
1051             cssProperty = CSSPropertyOpacity;
1052             break;
1053         case AnimatedPropertyBackgroundColor:
1054             cssProperty = CSSPropertyBackgroundColor;
1055             break;
1056         case AnimatedPropertyInvalid:
1057             ASSERT_NOT_REACHED();
1058     }
1059     return cssProperty;
1060 }
1061 
cssToGraphicsLayerProperty(int cssProperty)1062 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
1063 {
1064     switch (cssProperty) {
1065         case CSSPropertyWebkitTransform:
1066             return AnimatedPropertyWebkitTransform;
1067         case CSSPropertyOpacity:
1068             return AnimatedPropertyOpacity;
1069         case CSSPropertyBackgroundColor:
1070             return AnimatedPropertyBackgroundColor;
1071         // It's fine if we see other css properties here; they are just not accelerated.
1072     }
1073     return AnimatedPropertyInvalid;
1074 }
1075 
1076 } // namespace WebCore
1077 
1078 #endif // USE(ACCELERATED_COMPOSITING)
1079