• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if USE(ACCELERATED_COMPOSITING)
29 
30 #include "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 = 0;
127     m_foregroundLayer = 0;
128     m_clippingLayer = 0;
129     m_maskLayer = 0;
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     }
424 
425     if (m_owningLayer->hasTransform()) {
426         const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
427 
428         // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
429         IntRect layerBounds = IntRect(deltaX, deltaY, borderBox.width(), borderBox.height());
430 
431         // Update properties that depend on layer dimensions
432         FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
433         // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
434         FloatPoint3D anchor(relativeCompositingBounds.width()  != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width()  : 0.5f,
435                             relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
436                             transformOrigin.z());
437         m_graphicsLayer->setAnchorPoint(anchor);
438 
439         RenderStyle* style = renderer()->style();
440         if (style->hasPerspective()) {
441             TransformationMatrix t = owningLayer()->perspectiveTransform();
442 
443             if (m_clippingLayer) {
444                 m_clippingLayer->setChildrenTransform(t);
445                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
446             }
447             else
448                 m_graphicsLayer->setChildrenTransform(t);
449         } else {
450             if (m_clippingLayer)
451                 m_clippingLayer->setChildrenTransform(TransformationMatrix());
452             else
453                 m_graphicsLayer->setChildrenTransform(TransformationMatrix());
454         }
455     } else {
456         m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
457     }
458 
459     if (m_foregroundLayer) {
460         FloatPoint foregroundPosition;
461         FloatSize foregroundSize = newSize;
462         IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
463         if (m_clippingLayer) {
464             // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
465             // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
466             foregroundSize = FloatSize(clippingBox.size());
467             foregroundOffset = clippingBox.location() - IntPoint();
468         }
469 
470         m_foregroundLayer->setPosition(foregroundPosition);
471         m_foregroundLayer->setSize(foregroundSize);
472         m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
473     }
474 
475     if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
476         RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
477         reflectionBacking->updateGraphicsLayerGeometry();
478 
479         // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
480         // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
481         FloatRect layerBounds = compositedBounds();
482         FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
483         reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint() + (layerBounds.location() - reflectionLayerBounds.location()));
484     }
485 
486     m_graphicsLayer->setContentsRect(contentsBox());
487     updateDrawsContent();
488     updateAfterWidgetResize();
489 }
490 
updateInternalHierarchy()491 void RenderLayerBacking::updateInternalHierarchy()
492 {
493     // m_foregroundLayer has to be inserted in the correct order with child layers,
494     // so it's not inserted here.
495     if (m_ancestorClippingLayer) {
496         m_ancestorClippingLayer->removeAllChildren();
497         m_graphicsLayer->removeFromParent();
498         m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
499     }
500 
501     if (m_clippingLayer) {
502         m_clippingLayer->removeFromParent();
503         m_graphicsLayer->addChild(m_clippingLayer.get());
504 
505         // The clip for child layers does not include space for overflow controls, so they exist as
506         // siblings of the clipping layer if we have one. Normal children of this layer are set as
507         // children of the clipping layer.
508         if (m_layerForHorizontalScrollbar) {
509             m_layerForHorizontalScrollbar->removeFromParent();
510             m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
511         }
512         if (m_layerForVerticalScrollbar) {
513             m_layerForVerticalScrollbar->removeFromParent();
514             m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
515         }
516         if (m_layerForScrollCorner) {
517             m_layerForScrollCorner->removeFromParent();
518             m_graphicsLayer->addChild(m_layerForScrollCorner.get());
519         }
520     }
521 }
522 
updateDrawsContent()523 void RenderLayerBacking::updateDrawsContent()
524 {
525     m_graphicsLayer->setDrawsContent(containsPaintedContent());
526 }
527 
528 // Return true if the layers changed.
updateClippingLayers(bool needsAncestorClip,bool needsDescendantClip)529 bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
530 {
531     bool layersChanged = false;
532 
533     if (needsAncestorClip) {
534         if (!m_ancestorClippingLayer) {
535             m_ancestorClippingLayer = GraphicsLayer::create(this);
536 #ifndef NDEBUG
537             m_ancestorClippingLayer->setName("Ancestor clipping Layer");
538 #endif
539             m_ancestorClippingLayer->setMasksToBounds(true);
540             layersChanged = true;
541         }
542     } else if (m_ancestorClippingLayer) {
543         m_ancestorClippingLayer->removeFromParent();
544         m_ancestorClippingLayer = 0;
545         layersChanged = true;
546     }
547 
548     if (needsDescendantClip) {
549         if (!m_clippingLayer) {
550             m_clippingLayer = GraphicsLayer::create(this);
551 #ifndef NDEBUG
552             m_clippingLayer->setName("Child clipping Layer");
553 #endif
554             m_clippingLayer->setMasksToBounds(true);
555             layersChanged = true;
556         }
557     } else if (m_clippingLayer) {
558         m_clippingLayer->removeFromParent();
559         m_clippingLayer = 0;
560         layersChanged = true;
561     }
562 
563     return layersChanged;
564 }
565 
requiresHorizontalScrollbarLayer() const566 bool RenderLayerBacking::requiresHorizontalScrollbarLayer() const
567 {
568 #if !PLATFORM(CHROMIUM)
569     if (!m_owningLayer->hasOverlayScrollbars())
570         return false;
571 #endif
572     return m_owningLayer->horizontalScrollbar();
573 }
574 
requiresVerticalScrollbarLayer() const575 bool RenderLayerBacking::requiresVerticalScrollbarLayer() const
576 {
577 #if !PLATFORM(CHROMIUM)
578     if (!m_owningLayer->hasOverlayScrollbars())
579         return false;
580 #endif
581     return m_owningLayer->verticalScrollbar();
582 }
583 
requiresScrollCornerLayer() const584 bool RenderLayerBacking::requiresScrollCornerLayer() const
585 {
586 #if !PLATFORM(CHROMIUM)
587     if (!m_owningLayer->hasOverlayScrollbars())
588         return false;
589 #endif
590     return !m_owningLayer->scrollCornerAndResizerRect().isEmpty();
591 }
592 
updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer,bool needsVerticalScrollbarLayer,bool needsScrollCornerLayer)593 bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
594 {
595     bool layersChanged = false;
596     if (needsHorizontalScrollbarLayer) {
597         if (!m_layerForHorizontalScrollbar) {
598             m_layerForHorizontalScrollbar = GraphicsLayer::create(this);
599 #ifndef NDEBUG
600             m_layerForHorizontalScrollbar ->setName("horizontal scrollbar");
601 #endif
602             layersChanged = true;
603         }
604     } else if (m_layerForHorizontalScrollbar) {
605         m_layerForHorizontalScrollbar.clear();
606         layersChanged = true;
607     }
608 
609     if (needsVerticalScrollbarLayer) {
610         if (!m_layerForVerticalScrollbar) {
611             m_layerForVerticalScrollbar = GraphicsLayer::create(this);
612 #ifndef NDEBUG
613             m_layerForVerticalScrollbar->setName("vertical scrollbar");
614 #endif
615             layersChanged = true;
616         }
617     } else if (m_layerForVerticalScrollbar) {
618         m_layerForVerticalScrollbar.clear();
619         layersChanged = true;
620     }
621 
622     if (needsScrollCornerLayer) {
623         if (!m_layerForScrollCorner) {
624             m_layerForScrollCorner = GraphicsLayer::create(this);
625 #ifndef NDEBUG
626             m_layerForScrollCorner->setName("scroll corner");
627 #endif
628             layersChanged = true;
629         }
630     } else if (m_layerForScrollCorner) {
631         m_layerForScrollCorner.clear();
632         layersChanged = true;
633     }
634 
635     return layersChanged;
636 }
637 
updateForegroundLayer(bool needsForegroundLayer)638 bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
639 {
640     bool layerChanged = false;
641     if (needsForegroundLayer) {
642         if (!m_foregroundLayer) {
643             m_foregroundLayer = GraphicsLayer::create(this);
644 #ifndef NDEBUG
645             m_foregroundLayer->setName(nameForLayer() + " (foreground)");
646 #endif
647             m_foregroundLayer->setDrawsContent(true);
648             m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
649             if (Frame* frame = renderer()->document()->frame())
650                 m_foregroundLayer->setContentsScale(frame->pageScaleFactor());
651             layerChanged = true;
652         }
653     } else if (m_foregroundLayer) {
654         m_foregroundLayer->removeFromParent();
655         m_foregroundLayer = 0;
656         layerChanged = true;
657     }
658 
659     if (layerChanged)
660         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
661 
662     return layerChanged;
663 }
664 
updateMaskLayer(bool needsMaskLayer)665 bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
666 {
667     bool layerChanged = false;
668     if (needsMaskLayer) {
669         if (!m_maskLayer) {
670             m_maskLayer = GraphicsLayer::create(this);
671 #ifndef NDEBUG
672             m_maskLayer->setName("Mask");
673 #endif
674             m_maskLayer->setDrawsContent(true);
675             m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
676             if (Frame* frame = renderer()->document()->frame())
677                 m_maskLayer->setContentsScale(frame->pageScaleFactor());
678             layerChanged = true;
679         }
680     } else if (m_maskLayer) {
681         m_maskLayer = 0;
682         layerChanged = true;
683     }
684 
685     if (layerChanged)
686         m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
687 
688     return layerChanged;
689 }
690 
paintingPhaseForPrimaryLayer() const691 GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
692 {
693     unsigned phase = GraphicsLayerPaintBackground;
694     if (!m_foregroundLayer)
695         phase |= GraphicsLayerPaintForeground;
696     if (!m_maskLayer)
697         phase |= GraphicsLayerPaintMask;
698 
699     return static_cast<GraphicsLayerPaintingPhase>(phase);
700 }
701 
compositingOpacity(float rendererOpacity) const702 float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
703 {
704     float finalOpacity = rendererOpacity;
705 
706     for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
707         // We only care about parents that are stacking contexts.
708         // Recall that opacity creates stacking context.
709         if (!curr->isStackingContext())
710             continue;
711 
712         // If we found a compositing layer, we want to compute opacity
713         // relative to it. So we can break here.
714         if (curr->isComposited())
715             break;
716 
717         finalOpacity *= curr->renderer()->opacity();
718     }
719 
720     return finalOpacity;
721 }
722 
hasBorderOutlineOrShadow(const RenderStyle * style)723 static bool hasBorderOutlineOrShadow(const RenderStyle* style)
724 {
725     return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow();
726 }
727 
hasBoxDecorationsOrBackground(const RenderObject * renderer)728 static bool hasBoxDecorationsOrBackground(const RenderObject* renderer)
729 {
730     return hasBorderOutlineOrShadow(renderer->style()) || renderer->hasBackground();
731 }
732 
hasBoxDecorationsOrBackgroundImage(const RenderStyle * style)733 static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
734 {
735     return hasBorderOutlineOrShadow(style) || style->hasBackgroundImage();
736 }
737 
rendererHasBackground() const738 bool RenderLayerBacking::rendererHasBackground() const
739 {
740     // FIXME: share more code here
741     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
742         RenderObject* htmlObject = renderer()->firstChild();
743         if (!htmlObject)
744             return false;
745 
746         if (htmlObject->hasBackground())
747             return true;
748 
749         RenderObject* bodyObject = htmlObject->firstChild();
750         if (!bodyObject)
751             return false;
752 
753         return bodyObject->hasBackground();
754     }
755 
756     return renderer()->hasBackground();
757 }
758 
rendererBackgroundColor() const759 const Color RenderLayerBacking::rendererBackgroundColor() const
760 {
761     // FIXME: share more code here
762     if (renderer()->node() && renderer()->node()->isDocumentNode()) {
763         RenderObject* htmlObject = renderer()->firstChild();
764         if (htmlObject->hasBackground())
765             return htmlObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
766 
767         RenderObject* bodyObject = htmlObject->firstChild();
768         return bodyObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
769     }
770 
771     return renderer()->style()->visitedDependentColor(CSSPropertyBackgroundColor);
772 }
773 
774 // A "simple container layer" is a RenderLayer which has no visible content to render.
775 // It may have no children, or all its children may be themselves composited.
776 // This is a useful optimization, because it allows us to avoid allocating backing store.
isSimpleContainerCompositingLayer() const777 bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
778 {
779     RenderObject* renderObject = renderer();
780     if (renderObject->isReplaced() ||       // replaced objects are not containers
781         renderObject->hasMask())            // masks require special treatment
782         return false;
783 
784     RenderStyle* style = renderObject->style();
785 
786     // Reject anything that has a border, a border-radius or outline,
787     // or any background (color or image).
788     // FIXME: we could optimize layers for simple backgrounds.
789     if (hasBoxDecorationsOrBackground(renderObject))
790         return false;
791 
792     if (m_owningLayer->hasOverflowControls())
793         return false;
794 
795     // If we have got this far and the renderer has no children, then we're ok.
796     if (!renderObject->firstChild())
797         return true;
798 
799     if (renderObject->node() && renderObject->node()->isDocumentNode()) {
800         // Look to see if the root object has a non-simple backgound
801         RenderObject* rootObject = renderObject->document()->documentElement()->renderer();
802         if (!rootObject)
803             return false;
804 
805         style = rootObject->style();
806 
807         // Reject anything that has a border, a border-radius or outline,
808         // or is not a simple background (no background, or solid color).
809         if (hasBoxDecorationsOrBackgroundImage(style))
810             return false;
811 
812         // Now look at the body's renderer.
813         HTMLElement* body = renderObject->document()->body();
814         RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
815         if (!bodyObject)
816             return false;
817 
818         style = bodyObject->style();
819 
820         if (hasBoxDecorationsOrBackgroundImage(style))
821             return false;
822 
823         // Check to see if all the body's children are compositing layers.
824         if (hasNonCompositingDescendants())
825             return false;
826 
827         return true;
828     }
829 
830     // Check to see if all the renderer's children are compositing layers.
831     if (hasNonCompositingDescendants())
832         return false;
833 
834     return true;
835 }
836 
837 // Conservative test for having no rendered children.
hasNonCompositingDescendants() const838 bool RenderLayerBacking::hasNonCompositingDescendants() const
839 {
840     // Some HTML can cause whitespace text nodes to have renderers, like:
841     // <div>
842     // <img src=...>
843     // </div>
844     // so test for 0x0 RenderTexts here
845     for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
846         if (!child->hasLayer()) {
847             if (child->isRenderInline() || !child->isBox())
848                 return true;
849 
850             if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
851                 return true;
852         }
853     }
854 
855     if (m_owningLayer->isStackingContext()) {
856         // Use the m_hasCompositingDescendant bit to optimize?
857         if (Vector<RenderLayer*>* negZOrderList = m_owningLayer->negZOrderList()) {
858             size_t listSize = negZOrderList->size();
859             for (size_t i = 0; i < listSize; ++i) {
860                 RenderLayer* curLayer = negZOrderList->at(i);
861                 if (!curLayer->isComposited())
862                     return true;
863             }
864         }
865 
866         if (Vector<RenderLayer*>* posZOrderList = m_owningLayer->posZOrderList()) {
867             size_t listSize = posZOrderList->size();
868             for (size_t i = 0; i < listSize; ++i) {
869                 RenderLayer* curLayer = posZOrderList->at(i);
870                 if (!curLayer->isComposited())
871                     return true;
872             }
873         }
874     }
875 
876     if (Vector<RenderLayer*>* normalFlowList = m_owningLayer->normalFlowList()) {
877         size_t listSize = normalFlowList->size();
878         for (size_t i = 0; i < listSize; ++i) {
879             RenderLayer* curLayer = normalFlowList->at(i);
880             if (!curLayer->isComposited())
881                 return true;
882         }
883     }
884 
885     return false;
886 }
887 
containsPaintedContent() const888 bool RenderLayerBacking::containsPaintedContent() const
889 {
890     if (isSimpleContainerCompositingLayer() || paintingGoesToWindow() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
891         return false;
892 
893     if (isDirectlyCompositedImage())
894         return false;
895 
896     // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
897     // and set background color on the layer in that case, instead of allocating backing store and painting.
898 #if ENABLE(VIDEO)
899     if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
900         return hasBoxDecorationsOrBackground(renderer());
901 #endif
902 #if PLATFORM(MAC) && USE(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
903 #elif ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
904     if (isAcceleratedCanvas(renderer()))
905         return hasBoxDecorationsOrBackground(renderer());
906 #endif
907 
908     return true;
909 }
910 
911 // An image can be directly compositing if it's the sole content of the layer, and has no box decorations
912 // that require painting. Direct compositing saves backing store.
isDirectlyCompositedImage() const913 bool RenderLayerBacking::isDirectlyCompositedImage() const
914 {
915     RenderObject* renderObject = renderer();
916 
917     if (!renderObject->isImage() || hasBoxDecorationsOrBackground(renderObject) || renderObject->hasClip())
918         return false;
919 
920     RenderImage* imageRenderer = toRenderImage(renderObject);
921     if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
922         if (cachedImage->hasImage())
923             return cachedImage->image()->isBitmapImage();
924     }
925 
926     return false;
927 }
928 
contentChanged(RenderLayer::ContentChangeType changeType)929 void RenderLayerBacking::contentChanged(RenderLayer::ContentChangeType changeType)
930 {
931     if ((changeType == RenderLayer::ImageChanged) && isDirectlyCompositedImage()) {
932         updateImageContents();
933         return;
934     }
935 
936     if ((changeType == RenderLayer::MaskImageChanged) && m_maskLayer) {
937         // The composited layer bounds relies on box->maskClipRect(), which changes
938         // when the mask image becomes available.
939         bool isUpdateRoot = true;
940         updateAfterLayout(CompositingChildren, isUpdateRoot);
941     }
942 
943 #if ENABLE(WEBGL) || ENABLE(ACCELERATED_2D_CANVAS)
944     if ((changeType == RenderLayer::CanvasChanged) && isAcceleratedCanvas(renderer())) {
945         m_graphicsLayer->setContentsNeedsDisplay();
946         return;
947     }
948 #endif
949 }
950 
updateImageContents()951 void RenderLayerBacking::updateImageContents()
952 {
953     ASSERT(renderer()->isImage());
954     RenderImage* imageRenderer = toRenderImage(renderer());
955 
956     CachedImage* cachedImage = imageRenderer->cachedImage();
957     if (!cachedImage)
958         return;
959 
960     Image* image = cachedImage->image();
961     if (!image)
962         return;
963 
964     // We have to wait until the image is fully loaded before setting it on the layer.
965     if (!cachedImage->isLoaded())
966         return;
967 
968     // This is a no-op if the layer doesn't have an inner layer for the image.
969     m_graphicsLayer->setContentsToImage(image);
970 
971     // Image animation is "lazy", in that it automatically stops unless someone is drawing
972     // the image. So we have to kick the animation each time; this has the downside that the
973     // image will keep animating, even if its layer is not visible.
974     image->startAnimation();
975 }
976 
computeTransformOrigin(const IntRect & borderBox) const977 FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
978 {
979     RenderStyle* style = renderer()->style();
980 
981     FloatPoint3D origin;
982     origin.setX(style->transformOriginX().calcFloatValue(borderBox.width()));
983     origin.setY(style->transformOriginY().calcFloatValue(borderBox.height()));
984     origin.setZ(style->transformOriginZ());
985 
986     return origin;
987 }
988 
computePerspectiveOrigin(const IntRect & borderBox) const989 FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
990 {
991     RenderStyle* style = renderer()->style();
992 
993     float boxWidth = borderBox.width();
994     float boxHeight = borderBox.height();
995 
996     FloatPoint origin;
997     origin.setX(style->perspectiveOriginX().calcFloatValue(boxWidth));
998     origin.setY(style->perspectiveOriginY().calcFloatValue(boxHeight));
999 
1000     return origin;
1001 }
1002 
1003 // Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
contentOffsetInCompostingLayer() const1004 IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
1005 {
1006     return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
1007 }
1008 
contentsBox() const1009 IntRect RenderLayerBacking::contentsBox() const
1010 {
1011     if (!renderer()->isBox())
1012         return IntRect();
1013 
1014     IntRect contentsRect;
1015 #if ENABLE(VIDEO)
1016     if (renderer()->isVideo()) {
1017         RenderVideo* videoRenderer = toRenderVideo(renderer());
1018         contentsRect = videoRenderer->videoBox();
1019     } else
1020 #endif
1021         contentsRect = toRenderBox(renderer())->contentBoxRect();
1022 
1023     IntSize contentOffset = contentOffsetInCompostingLayer();
1024     contentsRect.move(contentOffset);
1025     return contentsRect;
1026 }
1027 
paintingGoesToWindow() const1028 bool RenderLayerBacking::paintingGoesToWindow() const
1029 {
1030     if (m_owningLayer->isRootLayer())
1031         return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
1032 
1033     return false;
1034 }
1035 
setContentsNeedDisplay()1036 void RenderLayerBacking::setContentsNeedDisplay()
1037 {
1038     if (m_graphicsLayer && m_graphicsLayer->drawsContent())
1039         m_graphicsLayer->setNeedsDisplay();
1040 
1041     if (m_foregroundLayer && m_foregroundLayer->drawsContent())
1042         m_foregroundLayer->setNeedsDisplay();
1043 
1044     if (m_maskLayer && m_maskLayer->drawsContent())
1045         m_maskLayer->setNeedsDisplay();
1046 }
1047 
1048 // r is in the coordinate space of the layer's render object
setContentsNeedDisplayInRect(const IntRect & r)1049 void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
1050 {
1051     if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
1052         IntRect layerDirtyRect = r;
1053         layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
1054         m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
1055     }
1056 
1057     if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
1058         IntRect layerDirtyRect = r;
1059         layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
1060         m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
1061     }
1062 
1063     if (m_maskLayer && m_maskLayer->drawsContent()) {
1064         IntRect layerDirtyRect = r;
1065         layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
1066         m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
1067     }
1068 }
1069 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1070 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1071 {
1072     if (paintDirtyRect == clipRect)
1073         return;
1074     p->save();
1075     p->clip(clipRect);
1076 }
1077 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)1078 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
1079 {
1080     if (paintDirtyRect == clipRect)
1081         return;
1082     p->restore();
1083 }
1084 
1085 // 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)1086 void RenderLayerBacking::paintIntoLayer(RenderLayer* rootLayer, GraphicsContext* context,
1087                     const IntRect& paintDirtyRect,      // in the coords of rootLayer
1088                     PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase,
1089                     RenderObject* paintingRoot)
1090 {
1091     if (paintingGoesToWindow()) {
1092         ASSERT_NOT_REACHED();
1093         return;
1094     }
1095 
1096     m_owningLayer->updateLayerListsIfNeeded();
1097 
1098     // Calculate the clip rects we should use.
1099     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
1100     m_owningLayer->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
1101 
1102     int x = layerBounds.x();        // layerBounds is computed relative to rootLayer
1103     int y = layerBounds.y();
1104     int tx = x - m_owningLayer->renderBoxX();
1105     int ty = y - m_owningLayer->renderBoxY();
1106 
1107     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
1108     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
1109     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
1110     // so it will be tested against as we decend through the renderers.
1111     RenderObject *paintingRootForRenderer = 0;
1112     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
1113         paintingRootForRenderer = paintingRoot;
1114 
1115     bool shouldPaint = (m_owningLayer->hasVisibleContent() || m_owningLayer->hasVisibleDescendant()) && m_owningLayer->isSelfPaintingLayer();
1116 
1117     if (shouldPaint && (paintingPhase & GraphicsLayerPaintBackground)) {
1118         // Paint our background first, before painting any child layers.
1119         // Establish the clip used to paint our background.
1120         setClip(context, paintDirtyRect, damageRect);
1121 
1122         PaintInfo info(context, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
1123         renderer()->paint(info, tx, ty);
1124 
1125         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1126         // z-index.  We paint after we painted the background/border, so that the scrollbars will
1127         // sit above the background/border.
1128         m_owningLayer->paintOverflowControls(context, x, y, damageRect);
1129 
1130         // Restore the clip.
1131         restoreClip(context, paintDirtyRect, damageRect);
1132 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
1133         // Paint the outline as part of the background phase in order for the
1134         // outline to not be a part of the scrollable content.
1135         if (!outlineRect.isEmpty()) {
1136             // Paint our own outline
1137             PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
1138             setClip(context, paintDirtyRect, outlineRect);
1139             renderer()->paint(paintInfo, tx, ty);
1140             restoreClip(context, paintDirtyRect, outlineRect);
1141         }
1142 #endif
1143 
1144         // Now walk the sorted list of children with negative z-indices. Only RenderLayers without compositing layers will paint.
1145         m_owningLayer->paintList(m_owningLayer->negZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1146     }
1147 
1148     bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
1149     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
1150 
1151     if (shouldPaint && (paintingPhase & GraphicsLayerPaintForeground)) {
1152         // Set up the clip used when painting our children.
1153         setClip(context, paintDirtyRect, clipRectToApply);
1154         PaintInfo paintInfo(context, clipRectToApply,
1155                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
1156                                           forceBlackText, paintingRootForRenderer, 0);
1157         renderer()->paint(paintInfo, tx, ty);
1158 
1159         if (!selectionOnly) {
1160             paintInfo.phase = PaintPhaseFloat;
1161             renderer()->paint(paintInfo, tx, ty);
1162 
1163             paintInfo.phase = PaintPhaseForeground;
1164             renderer()->paint(paintInfo, tx, ty);
1165 
1166             paintInfo.phase = PaintPhaseChildOutlines;
1167             renderer()->paint(paintInfo, tx, ty);
1168         }
1169 
1170         // Now restore our clip.
1171         restoreClip(context, paintDirtyRect, clipRectToApply);
1172 
1173 #if !ENABLE(ANDROID_OVERFLOW_SCROLL)
1174         // Do not paint the outline as part of the foreground since it will
1175         // appear inside the scrollable content.
1176         if (!outlineRect.isEmpty()) {
1177             // Paint our own outline
1178             PaintInfo paintInfo(context, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
1179             setClip(context, paintDirtyRect, outlineRect);
1180             renderer()->paint(paintInfo, tx, ty);
1181             restoreClip(context, paintDirtyRect, outlineRect);
1182         }
1183 #endif
1184 
1185         // Paint any child layers that have overflow.
1186         m_owningLayer->paintList(m_owningLayer->normalFlowList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1187 
1188         // Now walk the sorted list of children with positive z-indices.
1189         m_owningLayer->paintList(m_owningLayer->posZOrderList(), rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, 0, 0);
1190     }
1191 
1192     if (shouldPaint && (paintingPhase & GraphicsLayerPaintMask)) {
1193         if (renderer()->hasMask() && !selectionOnly && !damageRect.isEmpty()) {
1194             setClip(context, paintDirtyRect, damageRect);
1195 
1196             // Paint the mask.
1197             PaintInfo paintInfo(context, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
1198             renderer()->paint(paintInfo, tx, ty);
1199 
1200             // Restore the clip.
1201             restoreClip(context, paintDirtyRect, damageRect);
1202         }
1203     }
1204 
1205     ASSERT(!m_owningLayer->m_usedTransparency);
1206 }
1207 
paintScrollbar(Scrollbar * scrollbar,GraphicsContext & context,const IntRect & clip)1208 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1209 {
1210     if (!scrollbar)
1211         return;
1212 
1213     context.save();
1214     const IntRect& scrollbarRect = scrollbar->frameRect();
1215     context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1216     IntRect transformedClip = clip;
1217     transformedClip.move(scrollbarRect.x(), scrollbarRect.y());
1218     scrollbar->paint(&context, transformedClip);
1219     context.restore();
1220 }
1221 
1222 // Up-call from compositing layer drawing callback.
paintContents(const GraphicsLayer * graphicsLayer,GraphicsContext & context,GraphicsLayerPaintingPhase paintingPhase,const IntRect & clip)1223 void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
1224 {
1225     if (graphicsLayer == m_graphicsLayer.get() || graphicsLayer == m_foregroundLayer.get() || graphicsLayer == m_maskLayer.get()) {
1226         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willPaint(m_owningLayer->renderer()->frame(), clip);
1227 
1228         IntSize offset = graphicsLayer->offsetFromRenderer();
1229         context.translate(-offset);
1230 
1231         IntRect clipRect(clip);
1232         clipRect.move(offset);
1233 
1234         // The dirtyRect is in the coords of the painting root.
1235         IntRect dirtyRect = compositedBounds();
1236         dirtyRect.intersect(clipRect);
1237 
1238 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
1239         // If we encounter a scrollable layer, layers inside the scrollable layer
1240         // will need their entire content recorded.
1241         if (m_owningLayer->hasOverflowParent())
1242             dirtyRect.setSize(clip.size());
1243 #endif
1244 
1245         // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
1246         paintIntoLayer(m_owningLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase, renderer());
1247 
1248         InspectorInstrumentation::didPaint(cookie);
1249     } else if (graphicsLayer == layerForHorizontalScrollbar()) {
1250         paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
1251     } else if (graphicsLayer == layerForVerticalScrollbar()) {
1252         paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
1253     } else if (graphicsLayer == layerForScrollCorner()) {
1254         const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
1255         context.save();
1256         context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
1257         IntRect transformedClip = clip;
1258         transformedClip.move(scrollCornerAndResizer.x(), scrollCornerAndResizer.y());
1259         m_owningLayer->paintScrollCorner(&context, 0, 0, transformedClip);
1260         m_owningLayer->paintResizer(&context, 0, 0, transformedClip);
1261         context.restore();
1262     }
1263 }
1264 
showDebugBorders() const1265 bool RenderLayerBacking::showDebugBorders() const
1266 {
1267     return compositor() ? compositor()->compositorShowDebugBorders() : false;
1268 }
1269 
showRepaintCounter() const1270 bool RenderLayerBacking::showRepaintCounter() const
1271 {
1272     return compositor() ? compositor()->compositorShowRepaintCounter() : false;
1273 }
1274 
startAnimation(double timeOffset,const Animation * anim,const KeyframeList & keyframes)1275 bool RenderLayerBacking::startAnimation(double timeOffset, const Animation* anim, const KeyframeList& keyframes)
1276 {
1277     bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
1278     bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
1279 
1280     if (!hasOpacity && !hasTransform)
1281         return false;
1282 
1283     KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1284     KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1285 
1286     size_t numKeyframes = keyframes.size();
1287     for (size_t i = 0; i < numKeyframes; ++i) {
1288         const KeyframeValue& currentKeyframe = keyframes[i];
1289         const RenderStyle* keyframeStyle = currentKeyframe.style();
1290         float key = currentKeyframe.key();
1291 
1292         if (!keyframeStyle)
1293             continue;
1294 
1295         // Get timing function.
1296         RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0;
1297 
1298         bool isFirstOrLastKeyframe = key == 0 || key == 1;
1299         if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
1300             transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
1301 
1302         if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
1303             opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
1304     }
1305 
1306     bool didAnimateTransform = false;
1307     bool didAnimateOpacity = false;
1308 
1309     if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), anim, keyframes.animationName(), timeOffset)) {
1310         didAnimateTransform = true;
1311         compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
1312     }
1313 
1314     if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset)) {
1315         didAnimateOpacity = true;
1316         compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
1317     }
1318 
1319     return didAnimateTransform || didAnimateOpacity;
1320 }
1321 
animationPaused(double timeOffset,const String & animationName)1322 void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
1323 {
1324     m_graphicsLayer->pauseAnimation(animationName, timeOffset);
1325 }
1326 
animationFinished(const String & animationName)1327 void RenderLayerBacking::animationFinished(const String& animationName)
1328 {
1329     m_graphicsLayer->removeAnimation(animationName);
1330 }
1331 
startTransition(double timeOffset,int property,const RenderStyle * fromStyle,const RenderStyle * toStyle)1332 bool RenderLayerBacking::startTransition(double timeOffset, int property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
1333 {
1334     bool didAnimateOpacity = false;
1335     bool didAnimateTransform = false;
1336     ASSERT(property != cAnimateAll);
1337 
1338     if (property == (int)CSSPropertyOpacity) {
1339         const Animation* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
1340         if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
1341             KeyframeValueList opacityVector(AnimatedPropertyOpacity);
1342             opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
1343             opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
1344             // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
1345             if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
1346                 // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
1347                 updateLayerOpacity(toStyle);
1348                 didAnimateOpacity = true;
1349             }
1350         }
1351     }
1352 
1353     if (property == (int)CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
1354         const Animation* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
1355         if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
1356             KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
1357             transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
1358             transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
1359             if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->borderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
1360                 // To ensure that the correct transform is visible when the animation ends, also set the final opacity.
1361                 updateLayerTransform(toStyle);
1362                 didAnimateTransform = true;
1363             }
1364         }
1365     }
1366 
1367     if (didAnimateOpacity)
1368         compositor()->didStartAcceleratedAnimation(CSSPropertyOpacity);
1369 
1370     if (didAnimateTransform)
1371         compositor()->didStartAcceleratedAnimation(CSSPropertyWebkitTransform);
1372 
1373     return didAnimateOpacity || didAnimateTransform;
1374 }
1375 
transitionPaused(double timeOffset,int property)1376 void RenderLayerBacking::transitionPaused(double timeOffset, int property)
1377 {
1378     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1379     if (animatedProperty != AnimatedPropertyInvalid)
1380         m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
1381 }
1382 
transitionFinished(int property)1383 void RenderLayerBacking::transitionFinished(int property)
1384 {
1385     AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
1386     if (animatedProperty != AnimatedPropertyInvalid)
1387         m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
1388 }
1389 
notifyAnimationStarted(const GraphicsLayer *,double time)1390 void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
1391 {
1392     renderer()->animation()->notifyAnimationStarted(renderer(), time);
1393 }
1394 
notifySyncRequired(const GraphicsLayer *)1395 void RenderLayerBacking::notifySyncRequired(const GraphicsLayer*)
1396 {
1397     if (!renderer()->documentBeingDestroyed())
1398         compositor()->scheduleLayerFlush();
1399 }
1400 
1401 // This is used for the 'freeze' API, for testing only.
suspendAnimations(double time)1402 void RenderLayerBacking::suspendAnimations(double time)
1403 {
1404     m_graphicsLayer->suspendAnimations(time);
1405 }
1406 
resumeAnimations()1407 void RenderLayerBacking::resumeAnimations()
1408 {
1409     m_graphicsLayer->resumeAnimations();
1410 }
1411 
compositedBounds() const1412 IntRect RenderLayerBacking::compositedBounds() const
1413 {
1414     return m_compositedBounds;
1415 }
1416 
setCompositedBounds(const IntRect & bounds)1417 void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
1418 {
1419     m_compositedBounds = bounds;
1420 
1421 }
graphicsLayerToCSSProperty(AnimatedPropertyID property)1422 int RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
1423 {
1424     int cssProperty = CSSPropertyInvalid;
1425     switch (property) {
1426         case AnimatedPropertyWebkitTransform:
1427             cssProperty = CSSPropertyWebkitTransform;
1428             break;
1429         case AnimatedPropertyOpacity:
1430             cssProperty = CSSPropertyOpacity;
1431             break;
1432         case AnimatedPropertyBackgroundColor:
1433             cssProperty = CSSPropertyBackgroundColor;
1434             break;
1435         case AnimatedPropertyInvalid:
1436             ASSERT_NOT_REACHED();
1437     }
1438     return cssProperty;
1439 }
1440 
cssToGraphicsLayerProperty(int cssProperty)1441 AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(int cssProperty)
1442 {
1443     switch (cssProperty) {
1444         case CSSPropertyWebkitTransform:
1445             return AnimatedPropertyWebkitTransform;
1446         case CSSPropertyOpacity:
1447             return AnimatedPropertyOpacity;
1448         case CSSPropertyBackgroundColor:
1449             return AnimatedPropertyBackgroundColor;
1450         // It's fine if we see other css properties here; they are just not accelerated.
1451     }
1452     return AnimatedPropertyInvalid;
1453 }
1454 
1455 #ifndef NDEBUG
nameForLayer() const1456 String RenderLayerBacking::nameForLayer() const
1457 {
1458     String name = renderer()->renderName();
1459     if (Node* node = renderer()->node()) {
1460         if (node->isElementNode())
1461             name += " " + static_cast<Element*>(node)->tagName();
1462         if (node->hasID())
1463             name += " \'" + static_cast<Element*>(node)->getIdAttribute() + "\'";
1464     }
1465 
1466     if (m_owningLayer->isReflection())
1467         name += " (reflection)";
1468 
1469     return name;
1470 }
1471 #endif
1472 
compositingLayerType() const1473 CompositingLayerType RenderLayerBacking::compositingLayerType() const
1474 {
1475     if (m_graphicsLayer->hasContentsLayer())
1476         return MediaCompositingLayer;
1477 
1478     if (m_graphicsLayer->drawsContent())
1479         return m_graphicsLayer->usingTiledLayer() ? TiledCompositingLayer : NormalCompositingLayer;
1480 
1481     return ContainerCompositingLayer;
1482 }
1483 
updateContentsScale(float scale)1484 void RenderLayerBacking::updateContentsScale(float scale)
1485 {
1486     if (m_graphicsLayer)
1487         m_graphicsLayer->setContentsScale(scale);
1488 
1489     if (m_foregroundLayer)
1490         m_foregroundLayer->setContentsScale(scale);
1491 
1492     if (m_maskLayer)
1493         m_maskLayer->setContentsScale(scale);
1494 }
1495 
1496 } // namespace WebCore
1497 
1498 #endif // USE(ACCELERATED_COMPOSITING)
1499