2009-07-01 Simon Fraser <simon.fraser@apple.com>
[WebKit-https.git] / WebCore / rendering / RenderLayerBacking.cpp
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
54 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
55     : m_owningLayer(layer)
56     , m_ancestorClippingLayer(0)
57     , m_graphicsLayer(0)
58     , m_contentsLayer(0)
59     , m_clippingLayer(0)
60     , m_hasDirectlyCompositedContent(false)
61 {
62     createGraphicsLayer();
63 }
64
65 RenderLayerBacking::~RenderLayerBacking()
66 {
67     updateClippingLayers(false, false);
68     updateContentsLayer(false);
69     destroyGraphicsLayer();
70 }
71
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
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_contentsLayer;
103     m_contentsLayer = 0;
104
105     delete m_clippingLayer;
106     m_clippingLayer = 0;
107 }
108
109 void RenderLayerBacking::updateLayerOpacity()
110 {
111     m_graphicsLayer->setOpacity(compositingOpacity(renderer()->opacity()), 0, 0);
112 }
113
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
129 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth)
130 {
131     RenderLayerCompositor* layerCompositor = compositor();
132     if (!layerCompositor->compositingLayersNeedUpdate()) {
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
150 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
151 {
152     RenderLayerCompositor* compositor = this->compositor();
153
154     bool layerConfigChanged = false;
155     if (updateContentsLayer(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
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_contentsLayer) {
296         // The contents layer is always coincidental with the graphicsLayer for now.
297         m_contentsLayer->setPosition(IntPoint(0, 0));
298         m_contentsLayer->setSize(newSize);
299         m_contentsLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
300     }
301
302     m_graphicsLayer->updateContentsRect();
303     if (!m_hasDirectlyCompositedContent)
304         m_graphicsLayer->setDrawsContent(!isSimpleContainerCompositingLayer() && !paintingGoesToWindow());
305 }
306
307 void RenderLayerBacking::updateInternalHierarchy()
308 {
309     // m_contentsLayer 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.
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
366 bool RenderLayerBacking::updateContentsLayer(bool needsContentsLayer)
367 {
368     bool layerChanged = false;
369     if (needsContentsLayer) {
370         if (!m_contentsLayer) {
371             m_contentsLayer = GraphicsLayer::createGraphicsLayer(this);
372 #ifndef NDEBUG
373             m_contentsLayer->setName("Contents");
374 #endif
375             m_contentsLayer->setDrawsContent(true);
376             m_contentsLayer->setDrawingPhase(GraphicsLayerPaintForegroundMask);
377             m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintBackgroundMask);
378             layerChanged = true;
379         }
380     } else if (m_contentsLayer) {
381         m_contentsLayer->removeFromParent();
382         delete m_contentsLayer;
383         m_contentsLayer = 0;
384         m_graphicsLayer->setDrawingPhase(GraphicsLayerPaintAllMask);
385         layerChanged = true;
386     }
387     return layerChanged;
388 }
389
390 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
411 static bool hasBorderOutlineOrShadow(const RenderStyle* style)
412 {
413     return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow();
414 }
415
416 static bool hasBoxDecorations(const RenderStyle* style)
417 {
418     return hasBorderOutlineOrShadow(style) || style->hasBackground();
419 }
420
421 static bool hasBoxDecorationsWithBackgroundImage(const RenderStyle* style)
422 {
423     return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage();
424 }
425
426 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
449 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.
469 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
526 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.
581 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     
601 void RenderLayerBacking::rendererContentChanged()
602 {
603     if (canUseDirectCompositing() && renderer()->isImage())
604         updateImageContents();
605 }
606
607 void RenderLayerBacking::updateImageContents()
608 {
609     ASSERT(renderer()->isImage());
610     RenderImage* imageRenderer = static_cast<RenderImage*>(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
633 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
645 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.
660 IntSize RenderLayerBacking::contentOffsetInCompostingLayer()
661 {
662     return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
663 }
664
665 IntRect RenderLayerBacking::contentsBox(const GraphicsLayer*)
666 {
667     if (!renderer()->isBox())
668         return IntRect();
669
670     IntRect contentsRect;
671 #if ENABLE(VIDEO)
672     if (renderer()->isVideo()) {
673         RenderVideo* videoRenderer = static_cast<RenderVideo*>(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.
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.
691 FloatPoint RenderLayerBacking::contentsToGraphicsLayerCoordinates(const GraphicsLayer* graphicsLayer, const FloatPoint& point)
692 {
693     return point - FloatSize(graphicsLayer->offsetFromRenderer());
694 }
695
696 bool RenderLayerBacking::paintingGoesToWindow() const
697 {
698     return m_owningLayer->isRootLayer();
699 }
700
701 void RenderLayerBacking::setContentsNeedDisplay()
702 {
703     bool needViewUpdate = false;
704
705     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
706         m_graphicsLayer->setNeedsDisplay();
707         needViewUpdate = true;
708     }
709     
710     if (m_contentsLayer && m_contentsLayer->drawsContent()) {
711         m_contentsLayer->setNeedsDisplay();
712         needViewUpdate = true;
713     }
714     
715     // Make sure layout happens before we get rendered again.
716     if (needViewUpdate)
717         compositor()->scheduleViewUpdate();
718 }
719
720 // r is in the coordinate space of the layer's render object
721 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
722 {
723     bool needViewUpdate = false;
724
725     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
726         FloatPoint dirtyOrigin = contentsToGraphicsLayerCoordinates(m_graphicsLayer, FloatPoint(r.x(), r.y()));
727         FloatRect dirtyRect(dirtyOrigin, r.size());
728         FloatRect bounds(FloatPoint(), m_graphicsLayer->size());
729         if (bounds.intersects(dirtyRect)) {
730             m_graphicsLayer->setNeedsDisplayInRect(dirtyRect);
731             needViewUpdate = true;
732         }
733     }
734
735     if (m_contentsLayer && m_contentsLayer->drawsContent()) {
736         // FIXME: do incremental repaint
737         m_contentsLayer->setNeedsDisplay();
738         needViewUpdate = true;
739     }
740
741     // Make sure layout happens before we get rendered again.
742     if (needViewUpdate)
743         compositor()->scheduleViewUpdate();
744 }
745
746 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
747 {
748     if (paintDirtyRect == clipRect)
749         return;
750     p->save();
751     p->clip(clipRect);
752 }
753
754 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
755 {
756     if (paintDirtyRect == clipRect)
757         return;
758     p->restore();
759 }
760
761 // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
762 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
763                     const IntRect& paintDirtyRect,      // in the coords of rootLayer
764                     PaintRestriction paintRestriction, GraphicsLayerPaintingPhase paintingPhase,
765                     RenderObject* paintingRoot)
766 {
767     if (paintingGoesToWindow()) {
768         ASSERT_NOT_REACHED();
769         return;
770     }
771     
772     m_owningLayer->updateLayerListsIfNeeded();
773     
774     // Paint the reflection first if we have one.
775     if (m_owningLayer->hasReflection()) {
776         // Mark that we are now inside replica painting.
777         m_owningLayer->setPaintingInsideReflection(true);
778         m_owningLayer->reflectionLayer()->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot, 0, RenderLayer::PaintLayerPaintingReflection);
779         m_owningLayer->setPaintingInsideReflection(false);
780     }
781
782     // Calculate the clip rects we should use.
783     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
784     m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
785     
786     int x = layerBounds.x();        // layerBounds is computed relative to rootLayer
787     int y = layerBounds.y();
788     int tx = x - m_owningLayer->renderBoxX();
789     int ty = y - m_owningLayer->renderBoxY();
790
791     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
792     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
793     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
794     // so it will be tested against as we decend through the renderers.
795     RenderObject *paintingRootForRenderer = 0;
796     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
797         paintingRootForRenderer = paintingRoot;
798
799     bool shouldPaint = m_owningLayer->hasVisibleContent() && m_owningLayer->isSelfPaintingLayer();
800
801     if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackgroundMask)) {
802         // If this is the root then we need to send in a bigger bounding box
803         // because we'll be painting the background as well (see RenderBox::paintRootBoxDecorations()).
804         IntRect paintBox = clipRectToApply;
805         
806         // FIXME: do we need this code?
807         if (renderer()->node() && renderer()->node()->isDocumentNode() && renderer()->document()->isHTMLDocument()) {
808             RenderBox* box = toRenderBox(renderer());
809             int w = box->width();
810             int h = box->height();
811             
812             int rw;
813             int rh;
814             if (box->view()->frameView()) {
815                 rw = box->view()->frameView()->contentsWidth();
816                 rh = box->view()->frameView()->contentsHeight();
817             } else {
818                 rw = box->view()->width();
819                 rh = box->view()->height();
820             }
821             
822             int bx = tx - box->marginLeft();
823             int by = ty - box->marginTop();
824             int bw = max(w + box->marginLeft() + box->marginRight() + box->borderLeft() + box->borderRight(), rw);
825             int bh = max(h + box->marginTop() + box->marginBottom() + box->borderTop() + box->borderBottom(), rh);
826             paintBox = IntRect(bx, by, bw, bh);
827         }
828
829         // Paint our background first, before painting any child layers.
830         // Establish the clip used to paint our background.
831         setClip(context, paintDirtyRect, damageRect);
832         
833         RenderObject::PaintInfo info(context, paintBox, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
834         renderer()->paint(info, tx, ty);
835
836         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
837         // z-index.  We paint after we painted the background/border, so that the scrollbars will
838         // sit above the background/border.
839         m_owningLayer->paintOverflowControls(context, x, y, damageRect);
840         
841         // Restore the clip.
842         restoreClip(context, paintDirtyRect, damageRect);
843     }
844                 
845     if (shouldPaint && (paintingPhase & GraphicsLayerPaintForegroundMask)) {
846         // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
847         // FIXME: should these be painted as background?
848         Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList();
849         if (negZOrderList) {
850             for (Vector<RenderLayer*>::iterator it = negZOrderList->begin(); it != negZOrderList->end(); ++it)
851                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
852         }
853
854         bool forceBlackText = paintRestriction == PaintRestrictionSelectionOnlyBlackText;
855         bool selectionOnly  = paintRestriction == PaintRestrictionSelectionOnly || paintRestriction == PaintRestrictionSelectionOnlyBlackText;
856
857         // Set up the clip used when painting our children.
858         setClip(context, paintDirtyRect, clipRectToApply);
859         RenderObject::PaintInfo paintInfo(context, clipRectToApply, 
860                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
861                                           forceBlackText, paintingRootForRenderer, 0);
862         renderer()->paint(paintInfo, tx, ty);
863
864         if (!selectionOnly) {
865             paintInfo.phase = PaintPhaseFloat;
866             renderer()->paint(paintInfo, tx, ty);
867
868             paintInfo.phase = PaintPhaseForeground;
869             renderer()->paint(paintInfo, tx, ty);
870
871             paintInfo.phase = PaintPhaseChildOutlines;
872             renderer()->paint(paintInfo, tx, ty);
873         }
874
875         // Now restore our clip.
876         restoreClip(context, paintDirtyRect, clipRectToApply);
877
878         if (!outlineRect.isEmpty()) {
879             // Paint our own outline
880             RenderObject::PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
881             setClip(context, paintDirtyRect, outlineRect);
882             renderer()->paint(paintInfo, tx, ty);
883             restoreClip(context, paintDirtyRect, outlineRect);
884         }
885
886         // Paint any child layers that have overflow.
887         Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList();
888         if (normalFlowList) {
889             for (Vector<RenderLayer*>::iterator it = normalFlowList->begin(); it != normalFlowList->end(); ++it)
890                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
891         }
892
893         // Now walk the sorted list of children with positive z-indices.
894         Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList();
895         if (posZOrderList) {
896             for (Vector<RenderLayer*>::iterator it = posZOrderList->begin(); it != posZOrderList->end(); ++it)
897                 it[0]->paintLayer(rootLayer, context, paintDirtyRect, paintRestriction, paintingRoot);
898         }
899         
900         if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
901             setClip(context, paintDirtyRect, damageRect);
902
903             // Paint the mask.
904             RenderObject::PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
905             renderer()->paint(paintInfo, tx, ty);
906             
907             // Restore the clip.
908             restoreClip(context, paintDirtyRect, damageRect);
909         }
910     }
911
912     ASSERT(!m_owningLayer->m_usedTransparency);
913 }
914
915 // Up-call from compositing layer drawing callback.
916 void RenderLayerBacking::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase drawingPhase, const IntRect& clip)
917 {
918     // We have to use the same root as for hit testing, because both methods
919     // can compute and cache clipRects.
920     IntRect enclosingBBox = compositedBounds();
921
922     IntRect clipRect(clip);
923     
924     // Set up the coordinate space to be in the layer's rendering coordinates.
925     context.translate(-enclosingBBox.x(), -enclosingBBox.y());
926
927     // Offset the clip.
928     clipRect.move(enclosingBBox.x(), enclosingBBox.y());
929     
930     // The dirtyRect is in the coords of the painting root.
931     IntRect dirtyRect = enclosingBBox;
932     dirtyRect.intersect(clipRect);
933
934     paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintRestrictionNone, drawingPhase, renderer());
935 }
936
937 bool RenderLayerBacking::startAnimation(double beginTime, const Animation* anim, const KeyframeList& keyframes)
938 {
939     bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
940     bool hasTransform = keyframes.containsProperty(CSSPropertyWebkitTransform);
941     
942     if (!hasOpacity && !hasTransform)
943         return false;
944     
945     GraphicsLayer::TransformValueList transformVector;
946     GraphicsLayer::FloatValueList opacityVector;
947
948     for (Vector<KeyframeValue>::const_iterator it = keyframes.beginKeyframes(); it != keyframes.endKeyframes(); ++it) {
949         const RenderStyle* keyframeStyle = it->style();
950         float key = it->key();
951
952         if (!keyframeStyle)
953             continue;
954             
955         // get timing function
956         const TimingFunction* tf = keyframeStyle->hasAnimations() ? &((*keyframeStyle->animations()).animation(0)->timingFunction()) : 0;
957         
958         if (hasTransform)
959             transformVector.insert(key, &(keyframeStyle->transform()), tf);
960
961         if (hasOpacity)
962             opacityVector.insert(key, keyframeStyle->opacity(), tf);
963     }
964
965     bool didAnimateTransform = !hasTransform;
966     bool didAnimateOpacity = !hasOpacity;
967     
968     if (hasTransform && m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, beginTime, false))
969         didAnimateTransform = true;
970
971     if (hasOpacity && m_graphicsLayer->animateFloat(AnimatedPropertyOpacity, opacityVector, anim, beginTime))
972         didAnimateOpacity = true;
973     
974     return didAnimateTransform && didAnimateOpacity;
975 }
976
977 bool RenderLayerBacking::startTransition(double beginTime, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
978 {
979     bool didAnimate = false;
980     ASSERT(property != cAnimateAll);
981
982     if (property == (int)CSSPropertyOpacity) {
983         const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
984         if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
985             // If beginTime is not 0, we are restarting this transition, so first set the from value
986             // in case it was smashed by a previous animation.
987             if (beginTime > 0)
988                 m_graphicsLayer->setOpacity(compositingOpacity(fromStyle->opacity()), 0, 0);
989
990             if (m_graphicsLayer->setOpacity(compositingOpacity(toStyle->opacity()), opacityAnim, beginTime))
991                 didAnimate = true;
992         }
993     }
994
995     if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
996         // We get a TransformOperation, which is a linked list of primitive operations and their arguments.
997         // Arguments can be floats or Length values, which need to be converted to numbers using
998         // val.calcFloatValue(renderer()->width()) (or height()).
999         const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
1000         if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
1001             GraphicsLayer::TransformValueList transformVector;
1002             transformVector.insert(0, &fromStyle->transform(), 0);        
1003             transformVector.insert(1, &toStyle->transform(), 0);        
1004             if (m_graphicsLayer->animateTransform(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, beginTime, true))
1005                 didAnimate = true;
1006         }
1007     }
1008     
1009     return didAnimate;
1010 }
1011
1012 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
1013 {
1014     renderer()->animation()->notifyAnimationStarted(renderer(), time);
1015 }
1016
1017 void RenderLayerBacking::animationFinished(const String& name, int index, bool reset)
1018 {
1019     m_graphicsLayer->removeFinishedAnimations(name, index, reset);
1020 }
1021
1022 void RenderLayerBacking::transitionFinished(int property)
1023 {
1024     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1025     if (animatedProperty != AnimatedPropertyInvalid)
1026         m_graphicsLayer->removeFinishedTransitions(animatedProperty);
1027 }
1028
1029 void RenderLayerBacking::suspendAnimations()
1030 {
1031     m_graphicsLayer->suspendAnimations();
1032 }
1033
1034 void RenderLayerBacking::resumeAnimations()
1035 {
1036     m_graphicsLayer->resumeAnimations();
1037 }
1038
1039 IntRect RenderLayerBacking::compositedBounds() const
1040 {
1041     return m_compositedBounds;
1042 }
1043
1044 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
1045 {
1046     m_compositedBounds = bounds;
1047
1048 }
1049 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
1050 {
1051     int cssProperty = CSSPropertyInvalid;
1052     switch (property) {
1053         case AnimatedPropertyWebkitTransform:
1054             cssProperty = CSSPropertyWebkitTransform;
1055             break;
1056         case AnimatedPropertyOpacity:
1057             cssProperty = CSSPropertyOpacity;
1058             break;
1059         case AnimatedPropertyBackgroundColor:
1060             cssProperty = CSSPropertyBackgroundColor;
1061             break;
1062         case AnimatedPropertyInvalid:
1063             ASSERT_NOT_REACHED();
1064     }
1065     return cssProperty;
1066 }
1067
1068 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
1069 {
1070     switch (cssProperty) {
1071         case CSSPropertyWebkitTransform:
1072             return AnimatedPropertyWebkitTransform;
1073         case CSSPropertyOpacity:
1074             return AnimatedPropertyOpacity;
1075         case CSSPropertyBackgroundColor:
1076             return AnimatedPropertyBackgroundColor;
1077         // It's fine if we see other css properties here; they are just not accelerated.
1078     }
1079     return AnimatedPropertyInvalid;
1080 }
1081
1082 } // namespace WebCore
1083
1084 #endif // USE(ACCELERATED_COMPOSITING)