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 "RenderLayerBacking.h"
31 
32 #include "AnimationController.h"
33 #include "CanvasRenderingContext.h"
34 #include "CanvasRenderingContext2D.h"
35 #include "CSSPropertyNames.h"
36 #include "CSSStyleSelector.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "GraphicsLayer.h"
40 #include "HTMLCanvasElement.h"
41 #include "HTMLElement.h"
42 #include "HTMLIFrameElement.h"
43 #include "HTMLMediaElement.h"
44 #include "HTMLNames.h"
45 #include "InspectorInstrumentation.h"
46 #include "KeyframeList.h"
47 #include "PluginViewBase.h"
48 #include "RenderApplet.h"
49 #include "RenderBox.h"
50 #include "RenderIFrame.h"
51 #include "RenderImage.h"
52 #include "RenderLayerCompositor.h"
53 #include "RenderEmbeddedObject.h"
54 #include "RenderVideo.h"
55 #include "RenderView.h"
56 #include "Settings.h"
57 
58 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
59 #include "GraphicsContext3D.h"
60 #endif
61 
62 using namespace std;
63 
64 namespace WebCore {
65 
66 using namespace HTMLNames;
67 
68 static bool hasBorderOutlineOrShadow(const RenderStyle*);
69 static bool hasBoxDecorationsOrBackground(const RenderObject*);
70 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
71 static IntRect clipBox(RenderBox* renderer);
72 
isAcceleratedCanvas(RenderObject * renderer)73 static inline bool isAcceleratedCanvas(RenderObject* renderer)
74 {
75 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
76     if (renderer->isCanvas()) {
77         HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
78         if (CanvasRenderingContext* context = canvas->renderingContext())
79             return context->isAccelerated();
80     }
81 #else
82     UNUSED_PARAM(renderer);
83 #endif
84     return false;
85 }
86 
RenderLayerBacking(RenderLayer * layer)87 RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
88     : m_owningLayer(layer)
89     , m_artificiallyInflatedBounds(false)
90 {
91     createGraphicsLayer();
92 }
93 
~RenderLayerBacking()94 RenderLayerBacking::~RenderLayerBacking()
95 {
96     updateClippingLayers(false, false);
97     updateOverflowControlsLayers(false, false, false);
98     updateForegroundLayer(false);
99     updateMaskLayer(false);
100     destroyGraphicsLayer();
101 }
102 
createGraphicsLayer()103 void RenderLayerBacking::createGraphicsLayer()
104 {
105     m_graphicsLayer = GraphicsLayer::create(this);
106 
107 #ifndef NDEBUG
108     m_graphicsLayer->setName(nameForLayer());
109 #endif  // NDEBUG
110 
111 #if USE(ACCELERATED_COMPOSITING)
112     ASSERT(renderer() && renderer()->document() && renderer()->document()->frame());
113     if (Frame* frame = renderer()->document()->frame())
114         m_graphicsLayer->setContentsScale(frame->pageScaleFactor());
115 #endif
116 
117     updateLayerOpacity(renderer()->style());
118     updateLayerTransform(renderer()->style());
119 }
120 
destroyGraphicsLayer()121 void RenderLayerBacking::destroyGraphicsLayer()
122 {
123     if (m_graphicsLayer)
124         m_graphicsLayer->removeFromParent();
125 
126     m_graphicsLayer = nullptr;
127     m_foregroundLayer = nullptr;
128     m_clippingLayer = nullptr;
129     m_maskLayer = nullptr;
130 }
131 
updateLayerOpacity(const RenderStyle * style)132 void RenderLayerBacking::updateLayerOpacity(const RenderStyle* style)
133 {
134     m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
135 }
136 
updateLayerTransform(const RenderStyle * style)137 void RenderLayerBacking::updateLayerTransform(const RenderStyle* style)
138 {
139     // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
140     // baked into it, and we don't want that.
141     TransformationMatrix t;
142     if (m_owningLayer->hasTransform()) {
143         style->applyTransform(t, toRenderBox(renderer())->borderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
144         makeMatrixRenderable(t, compositor()->canRender3DTransforms());
145     }
146 
147     m_graphicsLayer->setTransform(t);
148 }
149 
hasNonZeroTransformOrigin(const RenderObject * renderer)150 static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
151 {
152     RenderStyle* style = renderer->style();
153     return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
154         || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
155 }
156 
layerOrAncestorIsTransformed(RenderLayer * layer)157 static bool layerOrAncestorIsTransformed(RenderLayer* layer)
158 {
159     for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
160         if (curr->hasTransform())
161             return true;
162     }
163 
164     return false;
165 }
166 
167 #if ENABLE(FULLSCREEN_API)
layerOrAncestorIsFullScreen(RenderLayer * layer)168 static bool layerOrAncestorIsFullScreen(RenderLayer* layer)
169 {
170     // Don't traverse through the render layer tree if we do not yet have a full screen renderer.
171     if (!layer->renderer()->document()->fullScreenRenderer())
172         return false;
173 
174     for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
175         if (curr->renderer()->isRenderFullScreen())
176             return true;
177     }
178 
179     return false;
180 }
181 #endif
182 
updateCompositedBounds()183 void RenderLayerBacking::updateCompositedBounds()
184 {
185     IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
186 
187     // Clip to the size of the document or enclosing overflow-scroll layer.
188     // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
189     // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.  If this
190     // is a fullscreen renderer, don't clip to the viewport, as the renderer will be asked to
191     // display outside of the viewport bounds.
192     if (compositor()->compositingConsultsOverlap() && !layerOrAncestorIsTransformed(m_owningLayer)
193 #if ENABLE(FULLSCREEN_API)
194         && !layerOrAncestorIsFullScreen(m_owningLayer)
195 #endif
196         ) {
197         RenderView* view = m_owningLayer->renderer()->view();
198         RenderLayer* rootLayer = view->layer();
199 
200         // Start by clipping to the view's bounds.
201         IntRect clippingBounds = view->layoutOverflowRect();
202 
203         if (m_owningLayer != rootLayer)
204             clippingBounds.intersect(m_owningLayer->backgroundClipRect(rootLayer, true));
205 
206         int deltaX = 0;
207         int deltaY = 0;
208         m_owningLayer->convertToLayerCoords(rootLayer, deltaX, deltaY);
209         clippingBounds.move(-deltaX, -deltaY);
210 
211         layerBounds.intersect(clippingBounds);
212     }
213 
214     // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
215     // then we need to ensure that the compositing layer has non-zero size so that we can apply
216     // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
217     if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
218         layerBounds.setWidth(1);
219         layerBounds.setHeight(1);
220         m_artificiallyInflatedBounds = true;
221     } else
222         m_artificiallyInflatedBounds = false;
223 
224     setCompositedBounds(layerBounds);
225 }
226 
updateAfterWidgetResize()227 void RenderLayerBacking::updateAfterWidgetResize()
228 {
229     if (renderer()->isRenderPart()) {
230         if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
231             innerCompositor->frameViewDidChangeSize();
232             innerCompositor->frameViewDidChangeLocation(contentsBox().location());
233         }
234     }
235 }
236 
updateAfterLayout(UpdateDepth updateDepth,bool isUpdateRoot)237 void RenderLayerBacking::updateAfterLayout(UpdateDepth updateDepth, bool isUpdateRoot)
238 {
239     RenderLayerCompositor* layerCompositor = compositor();
240     if (!layerCompositor->compositingLayersNeedRebuild()) {
241         // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
242         // position of this layer's GraphicsLayer depends on the position of our compositing
243         // ancestor's GraphicsLayer. That cannot be determined until all the descendant
244         // RenderLayers of that ancestor have been processed via updateLayerPositions().
245         //
246         // The solution is to update compositing children of this layer here,
247         // via updateCompositingChildrenGeometry().
248         updateCompositedBounds();
249         layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, updateDepth);
250 
251         if (isUpdateRoot) {
252             updateGraphicsLayerGeometry();
253             layerCompositor->updateRootLayerPosition();
254         }
255     }
256 }
257 
updateGraphicsLayerConfiguration()258 bool RenderLayerBacking::updateGraphicsLayerConfiguration()
259 {
260     RenderLayerCompositor* compositor = this->compositor();
261     RenderObject* renderer = this->renderer();
262 
263     bool layerConfigChanged = false;
264     if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
265         layerConfigChanged = true;
266 
267     if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), compositor->clipsCompositingDescendants(m_owningLayer)))
268         layerConfigChanged = true;
269 
270     if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
271         layerConfigChanged = true;
272 
273     if (layerConfigChanged)
274         updateInternalHierarchy();
275 
276     if (updateMaskLayer(renderer->hasMask()))
277         m_graphicsLayer->setMaskLayer(m_maskLayer.get());
278 
279     if (m_owningLayer->hasReflection()) {
280         if (m_owningLayer->reflectionLayer()->backing()) {
281             GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer();
282             m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
283         }
284     } else
285         m_graphicsLayer->setReplicatedByLayer(0);
286 
287     if (isDirectlyCompositedImage())
288         updateImageContents();
289 
290     if ((renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing())
291         || (renderer->isApplet() && toRenderApplet(renderer)->allowsAcceleratedCompositing())) {
292         PluginViewBase* pluginViewBase = static_cast<PluginViewBase*>(toRenderWidget(renderer)->widget());
293         m_graphicsLayer->setContentsToMedia(pluginViewBase->platformLayer());
294     }
295 #if ENABLE(VIDEO)
296     else if (renderer->isVideo()) {
297         HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(renderer->node());
298         m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
299     }
300 #endif
301 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
302     else if (isAcceleratedCanvas(renderer)) {
303         HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
304         if (CanvasRenderingContext* context = canvas->renderingContext())
305             m_graphicsLayer->setContentsToCanvas(context->platformLayer());
306         layerConfigChanged = true;
307     }
308 #endif
309 
310     if (renderer->isRenderPart())
311         layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
312 
313     return layerConfigChanged;
314 }
315 
clipBox(RenderBox * renderer)316 static IntRect clipBox(RenderBox* renderer)
317 {
318     IntRect result = PaintInfo::infiniteRect();
319     if (renderer->hasOverflowClip())
320         result = renderer->overflowClipRect(0, 0);
321 
322     if (renderer->hasClip())
323         result.intersect(renderer->clipRect(0, 0));
324 
325     return result;
326 }
327 
updateGraphicsLayerGeometry()328 void RenderLayerBacking::updateGraphicsLayerGeometry()
329 {
330     // If we haven't built z-order lists yet, wait until later.
331     if (m_owningLayer->isStackingContext() && m_owningLayer->m_zOrderListsDirty)
332         return;
333 
334     // Set transform property, if it is not animating. We have to do this here because the transform
335     // is affected by the layer dimensions.
336     if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
337         updateLayerTransform(renderer()->style());
338 
339     // Set opacity, if it is not animating.
340     if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
341         updateLayerOpacity(renderer()->style());
342 
343     RenderStyle* style = renderer()->style();
344     m_graphicsLayer->setPreserves3D(style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection());
345     m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
346 
347     RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
348 
349     // We compute everything relative to the enclosing compositing layer.
350     IntRect ancestorCompositingBounds;
351     if (compAncestor) {
352         ASSERT(compAncestor->backing());
353         ancestorCompositingBounds = compAncestor->backing()->compositedBounds();
354     }
355 
356     IntRect localCompositingBounds = compositedBounds();
357 
358     IntRect relativeCompositingBounds(localCompositingBounds);
359     int deltaX = 0, deltaY = 0;
360     m_owningLayer->convertToLayerCoords(compAncestor, deltaX, deltaY);
361     relativeCompositingBounds.move(deltaX, deltaY);
362 
363     IntPoint graphicsLayerParentLocation;
364     if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
365         // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
366         // position relative to it.
367         IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
368         graphicsLayerParentLocation = clippingBox.location();
369     } else
370         graphicsLayerParentLocation = ancestorCompositingBounds.location();
371 
372     if (compAncestor && m_ancestorClippingLayer) {
373         // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
374         // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
375         // for a compositing layer, rootLayer is the layer itself.
376         IntRect parentClipRect = m_owningLayer->backgroundClipRect(compAncestor, true);
377         ASSERT(parentClipRect != PaintInfo::infiniteRect());
378         m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
379         m_ancestorClippingLayer->setSize(parentClipRect.size());
380 
381         // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
382         IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY);
383         m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset);
384 
385         // The primary layer is then parented in, and positioned relative to this clipping layer.
386         graphicsLayerParentLocation = parentClipRect.location();
387     }
388 
389     m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
390 
391     IntSize oldOffsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
392     m_graphicsLayer->setOffsetFromRenderer(localCompositingBounds.location() - IntPoint());
393 
394     // If the compositing layer offset changes, we need to repaint.
395     if (oldOffsetFromRenderer != m_graphicsLayer->offsetFromRenderer())
396         m_graphicsLayer->setNeedsDisplay();
397 
398     FloatSize oldSize = m_graphicsLayer->size();
399     FloatSize newSize = relativeCompositingBounds.size();
400     if (oldSize != newSize) {
401         m_graphicsLayer->setSize(newSize);
402         // A bounds change will almost always require redisplay. Usually that redisplay
403         // will happen because of a repaint elsewhere, but not always:
404         // e.g. see RenderView::setMaximalOutlineSize()
405         m_graphicsLayer->setNeedsDisplay();
406     }
407 
408     // If we have a layer that clips children, position it.
409     IntRect clippingBox;
410     if (m_clippingLayer) {
411         clippingBox = clipBox(toRenderBox(renderer()));
412         m_clippingLayer->setPosition(FloatPoint() + (clippingBox.location() - localCompositingBounds.location()));
413         m_clippingLayer->setSize(clippingBox.size());
414         m_clippingLayer->setOffsetFromRenderer(clippingBox.location() - IntPoint());
415     }
416 
417     if (m_maskLayer) {
418         if (m_maskLayer->size() != m_graphicsLayer->size()) {
419             m_maskLayer->setSize(m_graphicsLayer->size());
420             m_maskLayer->setNeedsDisplay();
421         }
422         m_maskLayer->setPosition(FloatPoint());
423         m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
424     }
425 
426     if (m_owningLayer->hasTransform()) {
427         const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
428 
429         // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
430         IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height());
431 
432         // Update properties that depend on layer dimensions
433         FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
434         // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
435         FloatPoint3D anchor(relativeCompositingBounds.width()  != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width()  : 0.5f,
436                             relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
437                             transformOrigin.z());
438         m_graphicsLayer->setAnchorPoint(anchor);
439 
440         RenderStyle* style = renderer()->style();
441         if (style->hasPerspective()) {
442             TransformationMatrix t = owningLayer()->perspectiveTransform();
443 
444             if (m_clippingLayer) {
445                 m_clippingLayer->setChildrenTransform(t);
446                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
447             }
448             else
449                 m_graphicsLayer->setChildrenTransform(t);
450         } else {
451             if (m_clippingLayer)
452                 m_clippingLayer->setChildrenTransform(TransformationMatrix());
453             else
454                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
455         }
456     } else {
457         m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
458     }
459 
460     if (m_foregroundLayer) {
461         FloatPoint foregroundPosition;
462         FloatSize foregroundSize = newSize;
463         IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
464         if (m_clippingLayer) {
465             // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
466             // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
467             foregroundSize = FloatSize(clippingBox.size());
468             foregroundOffset = clippingBox.location() - IntPoint();
469         }
470 
471         m_foregroundLayer->setPosition(foregroundPosition);
472         m_foregroundLayer->setSize(foregroundSize);
473         m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
474     }
475 
476     if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
477         RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
478         reflectionBacking->updateGraphicsLayerGeometry();
479 
480         // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
481         // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
482         FloatRect layerBounds = compositedBounds();
483         FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
484         reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location()));
485     }
486 
487     m_graphicsLayer->setContentsRect(contentsBox());
488     updateDrawsContent();
489     updateAfterWidgetResize();
490 }
491 
updateInternalHierarchy()492 void RenderLayerBacking::updateInternalHierarchy()
493 {
494     // m_foregroundLayer has to be inserted in the correct order with child layers,
495     // so it's not inserted here.
496     if (m_ancestorClippingLayer) {
497         m_ancestorClippingLayer->removeAllChildren();
498         m_graphicsLayer->removeFromParent();
499         m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
500     }
501 
502     if (m_clippingLayer) {
503         m_clippingLayer->removeFromParent();
504         m_graphicsLayer->addChild(m_clippingLayer.get());
505 
506         // The clip for child layers does not include space for overflow controls, so they exist as
507         // siblings of the clipping layer if we have one. Normal children of this layer are set as
508         // children of the clipping layer.
509         if (m_layerForHorizontalScrollbar) {
510             m_layerForHorizontalScrollbar->removeFromParent();
511             m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
512         }
513         if (m_layerForVerticalScrollbar) {
514             m_layerForVerticalScrollbar->removeFromParent();
515             m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
516         }
517         if (m_layerForScrollCorner) {
518             m_layerForScrollCorner->removeFromParent();
519             m_graphicsLayer->addChild(m_layerForScrollCorner.get());
520         }
521     }
522 }
523 
updateDrawsContent()524 void RenderLayerBacking::updateDrawsContent()
525 {
526     m_graphicsLayer->setDrawsContent(containsPaintedContent());
527 }
528 
529 // Return true if the layers changed.
updateClippingLayers(bool needsAncestorClip,bool needsDescendantClip)530 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
531 {
532     bool layersChanged = false;
533 
534     if (needsAncestorClip) {
535         if (!m_ancestorClippingLayer) {
536             m_ancestorClippingLayer = GraphicsLayer::create(this);
537 #ifndef NDEBUG
538             m_ancestorClippingLayer->setName("Ancestor clipping Layer");
539 #endif
540             m_ancestorClippingLayer->setMasksToBounds(true);
541             layersChanged = true;
542         }
543     } else if (m_ancestorClippingLayer) {
544         m_ancestorClippingLayer->removeFromParent();
545         m_ancestorClippingLayer = nullptr;
546         layersChanged = true;
547     }
548 
549     if (needsDescendantClip) {
550         if (!m_clippingLayer) {
551             m_clippingLayer = GraphicsLayer::create(this);
552 #ifndef NDEBUG
553             m_clippingLayer->setName("Child clipping Layer");
554 #endif
555             m_clippingLayer->setMasksToBounds(true);
556             layersChanged = true;
557         }
558     } else if (m_clippingLayer) {
559         m_clippingLayer->removeFromParent();
560         m_clippingLayer = nullptr;
561         layersChanged = true;
562     }
563 
564     return layersChanged;
565 }
566 
requiresHorizontalScrollbarLayer() const567 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
568 {
569 #if !PLATFORM(CHROMIUM)
570     if (!m_owningLayer->hasOverlayScrollbars())
571         return false;
572 #endif
573     return m_owningLayer->horizontalScrollbar();
574 }
575 
requiresVerticalScrollbarLayer() const576 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
577 {
578 #if !PLATFORM(CHROMIUM)
579     if (!m_owningLayer->hasOverlayScrollbars())
580         return false;
581 #endif
582     return m_owningLayer->verticalScrollbar();
583 }
584 
requiresScrollCornerLayer() const585 bool RenderLayerBacking::requiresScrollCornerLayer() const
586 {
587 #if !PLATFORM(CHROMIUM)
588     if (!m_owningLayer->hasOverlayScrollbars())
589         return false;
590 #endif
591     return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
592 }
593 
updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer,bool needsVerticalScrollbarLayer,bool needsScrollCornerLayer)594 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
595 {
596     bool layersChanged = false;
597     if (needsHorizontalScrollbarLayer) {
598         if (!m_layerForHorizontalScrollbar) {
599             m_layerForHorizontalScrollbar = GraphicsLayer::create(this);
600 #ifndef NDEBUG
601             m_layerForHorizontalScrollbar ->setName("horizontal scrollbar");
602 #endif
603             layersChanged = true;
604         }
605     } else if (m_layerForHorizontalScrollbar) {
606         m_layerForHorizontalScrollbar.clear();
607         layersChanged = true;
608     }
609 
610     if (needsVerticalScrollbarLayer) {
611         if (!m_layerForVerticalScrollbar) {
612             m_layerForVerticalScrollbar = GraphicsLayer::create(this);
613 #ifndef NDEBUG
614             m_layerForVerticalScrollbar->setName("vertical scrollbar");
615 #endif
616             layersChanged = true;
617         }
618     } else if (m_layerForVerticalScrollbar) {
619         m_layerForVerticalScrollbar.clear();
620         layersChanged = true;
621     }
622 
623     if (needsScrollCornerLayer) {
624         if (!m_layerForScrollCorner) {
625             m_layerForScrollCorner = GraphicsLayer::create(this);
626 #ifndef NDEBUG
627             m_layerForScrollCorner->setName("scroll corner");
628 #endif
629             layersChanged = true;
630         }
631     } else if (m_layerForScrollCorner) {
632         m_layerForScrollCorner.clear();
633         layersChanged = true;
634     }
635 
636     return layersChanged;
637 }
638 
updateForegroundLayer(bool needsForegroundLayer)639 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
640 {
641     bool layerChanged = false;
642     if (needsForegroundLayer) {
643         if (!m_foregroundLayer) {
644             m_foregroundLayer = GraphicsLayer::create(this);
645 #ifndef NDEBUG
646             m_foregroundLayer->setName(nameForLayer() + " (foreground)");
647 #endif
648             m_foregroundLayer->setDrawsContent(true);
649             m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
650             if (Frame* frame = renderer()->document()->frame())
651                 m_foregroundLayer->setContentsScale(frame->pageScaleFactor());
652             layerChanged = true;
653         }
654     } else if (m_foregroundLayer) {
655         m_foregroundLayer->removeFromParent();
656         m_foregroundLayer = nullptr;
657         layerChanged = true;
658     }
659 
660     if (layerChanged)
661         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
662 
663     return layerChanged;
664 }
665 
updateMaskLayer(bool needsMaskLayer)666 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
667 {
668     bool layerChanged = false;
669     if (needsMaskLayer) {
670         if (!m_maskLayer) {
671             m_maskLayer = GraphicsLayer::create(this);
672 #ifndef NDEBUG
673             m_maskLayer->setName("Mask");
674 #endif
675             m_maskLayer->setDrawsContent(true);
676             m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
677             if (Frame* frame = renderer()->document()->frame())
678                 m_maskLayer->setContentsScale(frame->pageScaleFactor());
679             layerChanged = true;
680         }
681     } else if (m_maskLayer) {
682         m_maskLayer = nullptr;
683         layerChanged = true;
684     }
685 
686     if (layerChanged)
687         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
688 
689     return layerChanged;
690 }
691 
paintingPhaseForPrimaryLayer() const692 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
693 {
694     unsigned phase = GraphicsLayerPaintBackground;
695     if (!m_foregroundLayer)
696         phase |= GraphicsLayerPaintForeground;
697     if (!m_maskLayer)
698         phase |= GraphicsLayerPaintMask;
699 
700     return static_cast<GraphicsLayerPaintingPhase>(phase);
701 }
702 
compositingOpacity(float rendererOpacity) const703 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
704 {
705     float finalOpacity = rendererOpacity;
706 
707     for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
708         // We only care about parents that are stacking contexts.
709         // Recall that opacity creates stacking context.
710         if (!curr->isStackingContext())
711             continue;
712 
713         // If we found a compositing layer, we want to compute opacity
714         // relative to it. So we can break here.
715         if (curr->isComposited())
716             break;
717 
718         finalOpacity *= curr->renderer()->opacity();
719     }
720 
721     return finalOpacity;
722 }
723 
hasBorderOutlineOrShadow(const RenderStyle * style)724 static bool hasBorderOutlineOrShadow(const RenderStyle* style)
725 {
726     return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow();
727 }
728 
hasBoxDecorationsOrBackground(const RenderObject * renderer)729 static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
730 {
731     return hasBorderOutlineOrShadow(renderer->style()) || renderer->hasBackground();
732 }
733 
hasBoxDecorationsOrBackgroundImage(const RenderStyle * style)734 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
735 {
736     return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage();
737 }
738 
rendererHasBackground() const739 bool RenderLayerBacking::rendererHasBackground() const
740 {
741     // FIXME: share more code here
742     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
743         RenderObject* htmlObject = renderer()->firstChild();
744         if (!htmlObject)
745             return false;
746 
747         if (htmlObject->hasBackground())
748             return true;
749 
750         RenderObject* bodyObject = htmlObject->firstChild();
751         if (!bodyObject)
752             return false;
753 
754         return bodyObject->hasBackground();
755     }
756 
757     return renderer()->hasBackground();
758 }
759 
rendererBackgroundColor() const760 const Color RenderLayerBacking::rendererBackgroundColor() const
761 {
762     // FIXME: share more code here
763     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
764         RenderObject* htmlObject = renderer()->firstChild();
765         if (htmlObject->hasBackground())
766             return htmlObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
767 
768         RenderObject* bodyObject = htmlObject->firstChild();
769         return bodyObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
770     }
771 
772     return renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
773 }
774 
775 // A "simple container layer" is a RenderLayer which has no visible content to render.
776 // It may have no children, or all its children may be themselves composited.
777 // This is a useful optimization, because it allows us to avoid allocating backing store.
isSimpleContainerCompositingLayer() const778 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
779 {
780     RenderObject* renderObject = renderer();
781     if (renderObject->isReplaced() ||       // replaced objects are not containers
782         renderObject->hasMask())            // masks require special treatment
783         return false;
784 
785     RenderStyle* style = renderObject->style();
786 
787     // Reject anything that has a border, a border-radius or outline,
788     // or any background (color or image).
789     // FIXME: we could optimize layers for simple backgrounds.
790     if (hasBoxDecorationsOrBackground(renderObject))
791         return false;
792 
793     if (m_owningLayer->hasOverflowControls())
794         return false;
795 
796     // If we have got this far and the renderer has no children, then we're ok.
797     if (!renderObject->firstChild())
798         return true;
799 
800     if (renderObject->node() && renderObject->node()->isDocumentNode()) {
801         // Look to see if the root object has a non-simple backgound
802         RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
803         if (!rootObject)
804             return false;
805 
806         style = rootObject->style();
807 
808         // Reject anything that has a border, a border-radius or outline,
809         // or is not a simple background (no background, or solid color).
810         if (hasBoxDecorationsOrBackgroundImage(style))
811             return false;
812 
813         // Now look at the body's renderer.
814         HTMLElement* body = renderObject->document()->body();
815         RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
816         if (!bodyObject)
817             return false;
818 
819         style = bodyObject->style();
820 
821         if (hasBoxDecorationsOrBackgroundImage(style))
822             return false;
823 
824         // Check to see if all the body's children are compositing layers.
825         if (hasNonCompositingDescendants())
826             return false;
827 
828         return true;
829     }
830 
831     // Check to see if all the renderer's children are compositing layers.
832     if (hasNonCompositingDescendants())
833         return false;
834 
835     return true;
836 }
837 
838 // Conservative test for having no rendered children.
hasNonCompositingDescendants() const839 bool RenderLayerBacking::hasNonCompositingDescendants() const
840 {
841     // Some HTML can cause whitespace text nodes to have renderers, like:
842     // <div>
843     // <img src=...>
844     // </div>
845     // so test for 0x0 RenderTexts here
846     for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
847         if (!child->hasLayer()) {
848             if (child->isRenderInline() || !child->isBox())
849                 return true;
850 
851             if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
852                 return true;
853         }
854     }
855 
856     if (m_owningLayer->isStackingContext()) {
857         // Use the m_hasCompositingDescendant bit to optimize?
858         if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
859             size_t listSize = negZOrderList->size();
860             for (size_t i = 0; i < listSize; ++i) {
861                 RenderLayer* curLayer = negZOrderList->at(i);
862                 if (!curLayer->isComposited())
863                     return true;
864             }
865         }
866 
867         if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
868             size_t listSize = posZOrderList->size();
869             for (size_t i = 0; i < listSize; ++i) {
870                 RenderLayer* curLayer = posZOrderList->at(i);
871                 if (!curLayer->isComposited())
872                     return true;
873             }
874         }
875     }
876 
877     if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
878         size_t listSize = normalFlowList->size();
879         for (size_t i = 0; i < listSize; ++i) {
880             RenderLayer* curLayer = normalFlowList->at(i);
881             if (!curLayer->isComposited())
882                 return true;
883         }
884     }
885 
886     return false;
887 }
888 
containsPaintedContent() const889 bool RenderLayerBacking::containsPaintedContent() const
890 {
891     if (isSimpleContainerCompositingLayer() || paintingGoesToWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
892         return false;
893 
894     if (isDirectlyCompositedImage())
895         return false;
896 
897     // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
898     // and set background color on the layer in that case, instead of allocating backing store and painting.
899 #if ENABLE(VIDEO)
900     if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
901         return hasBoxDecorationsOrBackground(renderer());
902 #endif
903 #if PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
904 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
905     if (isAcceleratedCanvas(renderer()))
906         return hasBoxDecorationsOrBackground(renderer());
907 #endif
908 
909     return true;
910 }
911 
912 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
913 // that require painting. Direct compositing saves backing store.
isDirectlyCompositedImage() const914 bool RenderLayerBacking::isDirectlyCompositedImage() const
915 {
916     RenderObject* renderObject = renderer();
917 
918     if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
919         return false;
920 
921     RenderImage* imageRenderer = toRenderImage(renderObject);
922     if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
923         if (cachedImage->hasImage())
924             return cachedImage->image()->isBitmapImage();
925     }
926 
927     return false;
928 }
929 
contentChanged(RenderLayer::ContentChangeType changeType)930 void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeType)
931 {
932     if ((changeType == RenderLayer::ImageChanged) && isDirectlyCompositedImage()) {
933         updateImageContents();
934         return;
935     }
936 
937     if ((changeType == RenderLayer::MaskImageChanged) && m_maskLayer) {
938         // The composited layer bounds relies on box->maskClipRect(), which changes
939         // when the mask image becomes available.
940         bool isUpdateRoot = true;
941         updateAfterLayout(CompositingChildren, isUpdateRoot);
942     }
943 
944 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
945     if ((changeType == RenderLayer::CanvasChanged) && isAcceleratedCanvas(renderer())) {
946         m_graphicsLayer->setContentsNeedsDisplay();
947         return;
948     }
949 #endif
950 }
951 
updateImageContents()952 void RenderLayerBacking::updateImageContents()
953 {
954     ASSERT(renderer()->isImage());
955     RenderImage* imageRenderer = toRenderImage(renderer());
956 
957     CachedImage* cachedImage = imageRenderer->cachedImage();
958     if (!cachedImage)
959         return;
960 
961     Image* image = cachedImage->image();
962     if (!image)
963         return;
964 
965     // We have to wait until the image is fully loaded before setting it on the layer.
966     if (!cachedImage->isLoaded())
967         return;
968 
969     // This is a no-op if the layer doesn't have an inner layer for the image.
970     m_graphicsLayer->setContentsToImage(image);
971     updateDrawsContent();
972 
973     // Image animation is "lazy", in that it automatically stops unless someone is drawing
974     // the image. So we have to kick the animation each time; this has the downside that the
975     // image will keep animating, even if its layer is not visible.
976     image->startAnimation();
977 }
978 
computeTransformOrigin(const IntRect & borderBox) const979 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
980 {
981     RenderStyle* style = renderer()->style();
982 
983     FloatPoint3D origin;
984     origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
985     origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
986     origin.setZ(style->transformOriginZ());
987 
988     return origin;
989 }
990 
computePerspectiveOrigin(const IntRect & borderBox) const991 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
992 {
993     RenderStyle* style = renderer()->style();
994 
995     float boxWidth = borderBox.width();
996     float boxHeight = borderBox.height();
997 
998     FloatPoint origin;
999     origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth));
1000     origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight));
1001 
1002     return origin;
1003 }
1004 
1005 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
contentOffsetInCompostingLayer() const1006 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1007 {
1008     return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1009 }
1010 
contentsBox() const1011 IntRect RenderLayerBacking::contentsBox() const
1012 {
1013     if (!renderer()->isBox())
1014         return IntRect();
1015 
1016     IntRect contentsRect;
1017 #if ENABLE(VIDEO)
1018     if (renderer()->isVideo()) {
1019         RenderVideo* videoRenderer = toRenderVideo(renderer());
1020         contentsRect = videoRenderer->videoBox();
1021     } else
1022 #endif
1023         contentsRect = toRenderBox(renderer())->contentBoxRect();
1024 
1025     IntSize contentOffset = contentOffsetInCompostingLayer();
1026     contentsRect.move(contentOffset);
1027     return contentsRect;
1028 }
1029 
paintingGoesToWindow() const1030 bool RenderLayerBacking::paintingGoesToWindow() const
1031 {
1032     if (m_owningLayer->isRootLayer())
1033         return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
1034 
1035     return false;
1036 }
1037 
setContentsNeedDisplay()1038 void RenderLayerBacking::setContentsNeedDisplay()
1039 {
1040     if (m_graphicsLayer && m_graphicsLayer->drawsContent())
1041         m_graphicsLayer->setNeedsDisplay();
1042 
1043     if (m_foregroundLayer && m_foregroundLayer->drawsContent())
1044         m_foregroundLayer->setNeedsDisplay();
1045 
1046     if (m_maskLayer && m_maskLayer->drawsContent())
1047         m_maskLayer->setNeedsDisplay();
1048 }
1049 
1050 // r is in the coordinate space of the layer's render object
setContentsNeedDisplayInRect(const IntRect & r)1051 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
1052 {
1053     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
1054         IntRect layerDirtyRect = r;
1055         layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
1056         m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
1057     }
1058 
1059     if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
1060         IntRect layerDirtyRect = r;
1061         layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
1062         m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
1063     }
1064 
1065     if (m_maskLayer && m_maskLayer->drawsContent()) {
1066         IntRect layerDirtyRect = r;
1067         layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
1068         m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
1069     }
1070 }
1071 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1072 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1073 {
1074     if (paintDirtyRect == clipRect)
1075         return;
1076     p->save();
1077     p->clip(clipRect);
1078 }
1079 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1080 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1081 {
1082     if (paintDirtyRect == clipRect)
1083         return;
1084     p->restore();
1085 }
1086 
1087 // Share this with RenderLayer::paintLayer, which would have to be educated about GraphicsLayerPaintingPhase?
paintIntoLayer(RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,GraphicsLayerPaintingPhase paintingPhase,RenderObject * paintingRoot)1088 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
1089                     const IntRect& paintDirtyRect,      // in the coords of rootLayer
1090                     PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
1091                     RenderObject* paintingRoot)
1092 {
1093     if (paintingGoesToWindow()) {
1094         ASSERT_NOT_REACHED();
1095         return;
1096     }
1097 
1098     m_owningLayer->updateLayerListsIfNeeded();
1099 
1100     // Calculate the clip rects we should use.
1101     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
1102     m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
1103 
1104     int x = layerBounds.x();        // layerBounds is computed relative to rootLayer
1105     int y = layerBounds.y();
1106     int tx = x - m_owningLayer->renderBoxX();
1107     int ty = y - m_owningLayer->renderBoxY();
1108 
1109     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
1110     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
1111     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
1112     // so it will be tested against as we decend through the renderers.
1113     RenderObject *paintingRootForRenderer = 0;
1114     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
1115         paintingRootForRenderer = paintingRoot;
1116 
1117     bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer();
1118 
1119     if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) {
1120         // Paint our background first, before painting any child layers.
1121         // Establish the clip used to paint our background.
1122         setClip(context, paintDirtyRect, damageRect);
1123 
1124         PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
1125         renderer()->paint(info, tx, ty);
1126 
1127         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1128         // z-index.  We paint after we painted the background/border, so that the scrollbars will
1129         // sit above the background/border.
1130         m_owningLayer->paintOverflowControls(context, x, y, damageRect);
1131 
1132         // Restore the clip.
1133         restoreClip(context, paintDirtyRect, damageRect);
1134 
1135         // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
1136         m_owningLayer->paintList(m_owningLayer->negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1137     }
1138 
1139     bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
1140     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
1141 
1142     if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) {
1143         // Set up the clip used when painting our children.
1144         setClip(context, paintDirtyRect, clipRectToApply);
1145         PaintInfo paintInfo(context, clipRectToApply,
1146                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
1147                                           forceBlackText, paintingRootForRenderer, 0);
1148         renderer()->paint(paintInfo, tx, ty);
1149 
1150         if (!selectionOnly) {
1151             paintInfo.phase = PaintPhaseFloat;
1152             renderer()->paint(paintInfo, tx, ty);
1153 
1154             paintInfo.phase = PaintPhaseForeground;
1155             renderer()->paint(paintInfo, tx, ty);
1156 
1157             paintInfo.phase = PaintPhaseChildOutlines;
1158             renderer()->paint(paintInfo, tx, ty);
1159         }
1160 
1161         // Now restore our clip.
1162         restoreClip(context, paintDirtyRect, clipRectToApply);
1163 
1164         if (!outlineRect.isEmpty()) {
1165             // Paint our own outline
1166             PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
1167             setClip(context, paintDirtyRect, outlineRect);
1168             renderer()->paint(paintInfo, tx, ty);
1169             restoreClip(context, paintDirtyRect, outlineRect);
1170         }
1171 
1172         // Paint any child layers that have overflow.
1173         m_owningLayer->paintList(m_owningLayer->normalFlowList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1174 
1175         // Now walk the sorted list of children with positive z-indices.
1176         m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1177     }
1178 
1179     if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) {
1180         if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
1181             setClip(context, paintDirtyRect, damageRect);
1182 
1183             // Paint the mask.
1184             PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
1185             renderer()->paint(paintInfo, tx, ty);
1186 
1187             // Restore the clip.
1188             restoreClip(context, paintDirtyRect, damageRect);
1189         }
1190     }
1191 
1192     ASSERT(!m_owningLayer->m_usedTransparency);
1193 }
1194 
paintScrollbar(Scrollbar * scrollbar,GraphicsContext & context,const IntRect & clip)1195 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1196 {
1197     if (!scrollbar)
1198         return;
1199 
1200     context.save();
1201     const IntRect& scrollbarRect = scrollbar->frameRect();
1202     context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1203     IntRect transformedClip = clip;
1204     transformedClip.move(scrollbarRect.x(), scrollbarRect.y());
1205     scrollbar->paint(&context, transformedClip);
1206     context.restore();
1207 }
1208 
1209 // Up-call from compositing layer drawing callback.
paintContents(const GraphicsLayer * graphicsLayer,GraphicsContext & context,GraphicsLayerPaintingPhase paintingPhase,const IntRect & clip)1210 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
1211 {
1212     if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
1213         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip);
1214 
1215         IntSize offset = graphicsLayer->offsetFromRenderer();
1216         context.translate(-offset);
1217 
1218         IntRect clipRect(clip);
1219         clipRect.move(offset);
1220 
1221         // The dirtyRect is in the coords of the painting root.
1222         IntRect dirtyRect = compositedBounds();
1223         dirtyRect.intersect(clipRect);
1224 
1225         // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
1226         paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
1227 
1228         InspectorInstrumentation::didPaint(cookie);
1229     } else if (graphicsLayer == layerForHorizontalScrollbar()) {
1230         paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
1231     } else if (graphicsLayer == layerForVerticalScrollbar()) {
1232         paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
1233     } else if (graphicsLayer == layerForScrollCorner()) {
1234         const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
1235         context.save();
1236         context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
1237         IntRect transformedClip = clip;
1238         transformedClip.move(scrollCornerAndResizer.x(), scrollCornerAndResizer.y());
1239         m_owningLayer->paintScrollCorner(&context, 0, 0, transformedClip);
1240         m_owningLayer->paintResizer(&context, 0, 0, transformedClip);
1241         context.restore();
1242     }
1243 }
1244 
showDebugBorders() const1245 bool RenderLayerBacking::showDebugBorders() const
1246 {
1247     return compositor() ? compositor()->compositorShowDebugBorders() : false;
1248 }
1249 
showRepaintCounter() const1250 bool RenderLayerBacking::showRepaintCounter() const
1251 {
1252     return compositor() ? compositor()->compositorShowRepaintCounter() : false;
1253 }
1254 
startAnimation(double timeOffset,const Animation * anim,const KeyframeList & keyframes)1255 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
1256 {
1257     bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
1258     bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
1259 
1260     if (!hasOpacity && !hasTransform)
1261         return false;
1262 
1263     KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1264     KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1265 
1266     size_t numKeyframes = keyframes.size();
1267     for (size_t i = 0; i < numKeyframes; ++i) {
1268         const KeyframeValue& currentKeyframe = keyframes[i];
1269         const RenderStyle* keyframeStyle = currentKeyframe.style();
1270         float key = currentKeyframe.key();
1271 
1272         if (!keyframeStyle)
1273             continue;
1274 
1275         // Get timing function.
1276         RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0;
1277 
1278         bool isFirstOrLastKeyframe = key == 0 || key == 1;
1279         if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
1280             transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
1281 
1282         if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
1283             opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
1284     }
1285 
1286     bool didAnimateTransform = false;
1287     bool didAnimateOpacity = false;
1288 
1289     if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) {
1290         didAnimateTransform = true;
1291         compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
1292     }
1293 
1294     if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) {
1295         didAnimateOpacity = true;
1296         compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
1297     }
1298 
1299     return didAnimateTransform || didAnimateOpacity;
1300 }
1301 
animationPaused(double timeOffset,const String & animationName)1302 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
1303 {
1304     m_graphicsLayer->pauseAnimation(animationName, timeOffset);
1305 }
1306 
animationFinished(const String & animationName)1307 void RenderLayerBacking::animationFinished(const String& animationName)
1308 {
1309     m_graphicsLayer->removeAnimation(animationName);
1310 }
1311 
startTransition(double timeOffset,int property,const RenderStyle * fromStyle,const RenderStyle * toStyle)1312 bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
1313 {
1314     bool didAnimateOpacity = false;
1315     bool didAnimateTransform = false;
1316     ASSERT(property != cAnimateAll);
1317 
1318     if (property == (int)CSSPropertyOpacity) {
1319         const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
1320         if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
1321             KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1322             opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
1323             opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
1324             // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
1325             if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
1326                 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
1327                 updateLayerOpacity(toStyle);
1328                 didAnimateOpacity = true;
1329             }
1330         }
1331     }
1332 
1333     if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
1334         const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
1335         if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
1336             KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1337             transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
1338             transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
1339             if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
1340                 // To ensure that the correct transform is visible when the animation ends, also set the final opacity.
1341                 updateLayerTransform(toStyle);
1342                 didAnimateTransform = true;
1343             }
1344         }
1345     }
1346 
1347     if (didAnimateOpacity)
1348         compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
1349 
1350     if (didAnimateTransform)
1351         compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
1352 
1353     return didAnimateOpacity || didAnimateTransform;
1354 }
1355 
transitionPaused(double timeOffset,int property)1356 void RenderLayerBacking::transitionPaused(double timeOffset, int property)
1357 {
1358     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1359     if (animatedProperty != AnimatedPropertyInvalid)
1360         m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
1361 }
1362 
transitionFinished(int property)1363 void RenderLayerBacking::transitionFinished(int property)
1364 {
1365     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1366     if (animatedProperty != AnimatedPropertyInvalid)
1367         m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
1368 }
1369 
notifyAnimationStarted(const GraphicsLayer *,double time)1370 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
1371 {
1372     renderer()->animation()->notifyAnimationStarted(renderer(), time);
1373 }
1374 
notifySyncRequired(const GraphicsLayer *)1375 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*)
1376 {
1377     if (!renderer()->documentBeingDestroyed())
1378         compositor()->scheduleLayerFlush();
1379 }
1380 
1381 // This is used for the 'freeze' API, for testing only.
suspendAnimations(double time)1382 void RenderLayerBacking::suspendAnimations(double time)
1383 {
1384     m_graphicsLayer->suspendAnimations(time);
1385 }
1386 
resumeAnimations()1387 void RenderLayerBacking::resumeAnimations()
1388 {
1389     m_graphicsLayer->resumeAnimations();
1390 }
1391 
compositedBounds() const1392 IntRect RenderLayerBacking::compositedBounds() const
1393 {
1394     return m_compositedBounds;
1395 }
1396 
setCompositedBounds(const IntRect & bounds)1397 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
1398 {
1399     m_compositedBounds = bounds;
1400 
1401 }
graphicsLayerToCSSProperty(AnimatedPropertyID property)1402 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
1403 {
1404     int cssProperty = CSSPropertyInvalid;
1405     switch (property) {
1406         case AnimatedPropertyWebkitTransform:
1407             cssProperty = CSSPropertyWebkitTransform;
1408             break;
1409         case AnimatedPropertyOpacity:
1410             cssProperty = CSSPropertyOpacity;
1411             break;
1412         case AnimatedPropertyBackgroundColor:
1413             cssProperty = CSSPropertyBackgroundColor;
1414             break;
1415         case AnimatedPropertyInvalid:
1416             ASSERT_NOT_REACHED();
1417     }
1418     return cssProperty;
1419 }
1420 
cssToGraphicsLayerProperty(int cssProperty)1421 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
1422 {
1423     switch (cssProperty) {
1424         case CSSPropertyWebkitTransform:
1425             return AnimatedPropertyWebkitTransform;
1426         case CSSPropertyOpacity:
1427             return AnimatedPropertyOpacity;
1428         case CSSPropertyBackgroundColor:
1429             return AnimatedPropertyBackgroundColor;
1430         // It's fine if we see other css properties here; they are just not accelerated.
1431     }
1432     return AnimatedPropertyInvalid;
1433 }
1434 
1435 #ifndef NDEBUG
nameForLayer() const1436 String RenderLayerBacking::nameForLayer() const
1437 {
1438     String name = renderer()->renderName();
1439     if (Node* node = renderer()->node()) {
1440         if (node->isElementNode())
1441             name += " " + static_cast<Element*>(node)->tagName();
1442         if (node->hasID())
1443             name += " \'" + static_cast<Element*>(node)->getIdAttribute() + "\'";
1444     }
1445 
1446     if (m_owningLayer->isReflection())
1447         name += " (reflection)";
1448 
1449     return name;
1450 }
1451 #endif
1452 
compositingLayerType() const1453 CompositingLayerType RenderLayerBacking::compositingLayerType() const
1454 {
1455     if (m_graphicsLayer->hasContentsLayer())
1456         return MediaCompositingLayer;
1457 
1458     if (m_graphicsLayer->drawsContent())
1459         return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
1460 
1461     return ContainerCompositingLayer;
1462 }
1463 
updateContentsScale(float scale)1464 void RenderLayerBacking::updateContentsScale(float scale)
1465 {
1466     if (m_graphicsLayer)
1467         m_graphicsLayer->setContentsScale(scale);
1468 
1469     if (m_foregroundLayer)
1470         m_foregroundLayer->setContentsScale(scale);
1471 
1472     if (m_maskLayer)
1473         m_maskLayer->setContentsScale(scale);
1474 }
1475 
1476 } // namespace WebCore
1477 
1478 #endif // USE(ACCELERATED_COMPOSITING)
1479