1 /*
2 * Copyright (C) 2009, 2010 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 #include "RenderLayerCompositor.h"
30
31 #include "AnimationController.h"
32 #include "CanvasRenderingContext.h"
33 #include "CSSPropertyNames.h"
34 #include "Chrome.h"
35 #include "ChromeClient.h"
36 #include "Frame.h"
37 #include "FrameView.h"
38 #include "GraphicsLayer.h"
39 #include "HTMLCanvasElement.h"
40 #include "HTMLIFrameElement.h"
41 #include "HTMLNames.h"
42 #include "HitTestResult.h"
43 #include "NodeList.h"
44 #include "Page.h"
45 #include "RenderApplet.h"
46 #include "RenderEmbeddedObject.h"
47 #include "RenderFullScreen.h"
48 #include "RenderIFrame.h"
49 #include "RenderLayerBacking.h"
50 #include "RenderReplica.h"
51 #include "RenderVideo.h"
52 #include "RenderView.h"
53 #include "Settings.h"
54
55 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
56 #include "HTMLMediaElement.h"
57 #endif
58
59 #if PROFILE_LAYER_REBUILD
60 #include <wtf/CurrentTime.h>
61 #endif
62
63 #ifndef NDEBUG
64 #include "RenderTreeAsText.h"
65 #endif
66
67 #if ENABLE(3D_RENDERING)
68 // This symbol is used to determine from a script whether 3D rendering is enabled (via 'nm').
69 bool WebCoreHas3DRendering = true;
70 #endif
71
72 namespace WebCore {
73
74 using namespace HTMLNames;
75
76 struct CompositingState {
CompositingStateWebCore::CompositingState77 CompositingState(RenderLayer* compAncestor)
78 : m_compositingAncestor(compAncestor)
79 , m_subtreeIsCompositing(false)
80 #ifndef NDEBUG
81 , m_depth(0)
82 #endif
83 {
84 }
85
86 RenderLayer* m_compositingAncestor;
87 bool m_subtreeIsCompositing;
88 #ifndef NDEBUG
89 int m_depth;
90 #endif
91 };
92
RenderLayerCompositor(RenderView * renderView)93 RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
94 : m_renderView(renderView)
95 , m_updateCompositingLayersTimer(this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
96 , m_hasAcceleratedCompositing(true)
97 , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers))
98 , m_showDebugBorders(false)
99 , m_showRepaintCounter(false)
100 , m_compositingConsultsOverlap(true)
101 , m_compositingDependsOnGeometry(false)
102 , m_compositing(false)
103 , m_compositingLayersNeedRebuild(false)
104 , m_flushingLayers(false)
105 , m_forceCompositingMode(false)
106 , m_rootLayerAttachment(RootLayerUnattached)
107 #if PROFILE_LAYER_REBUILD
108 , m_rootLayerUpdateCount(0)
109 #endif // PROFILE_LAYER_REBUILD
110 {
111 Settings* settings = m_renderView->document()->settings();
112
113 // Even when forcing compositing mode, ignore child frames, or this will trigger
114 // layer creation from the enclosing RenderIFrame.
115 ASSERT(m_renderView->document()->frame());
116 if (settings && settings->forceCompositingMode() && settings->acceleratedCompositingEnabled()
117 && !m_renderView->document()->frame()->tree()->parent()) {
118 m_forceCompositingMode = true;
119 enableCompositingMode();
120 }
121 }
122
~RenderLayerCompositor()123 RenderLayerCompositor::~RenderLayerCompositor()
124 {
125 ASSERT(m_rootLayerAttachment == RootLayerUnattached);
126 }
127
enableCompositingMode(bool enable)128 void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
129 {
130 if (enable != m_compositing) {
131 m_compositing = enable;
132
133 if (m_compositing) {
134 ensureRootPlatformLayer();
135 notifyIFramesOfCompositingChange();
136 } else
137 destroyRootPlatformLayer();
138 }
139 }
140
cacheAcceleratedCompositingFlags()141 void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
142 {
143 bool hasAcceleratedCompositing = false;
144 bool showDebugBorders = false;
145 bool showRepaintCounter = false;
146
147 if (Settings* settings = m_renderView->document()->settings()) {
148 hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
149 showDebugBorders = settings->showDebugBorders();
150 showRepaintCounter = settings->showRepaintCounter();
151 }
152
153 // We allow the chrome to override the settings, in case the page is rendered
154 // on a chrome that doesn't allow accelerated compositing.
155 if (hasAcceleratedCompositing) {
156 Frame* frame = m_renderView->frameView()->frame();
157 Page* page = frame ? frame->page() : 0;
158 if (page) {
159 ChromeClient* chromeClient = page->chrome()->client();
160 m_compositingTriggers = chromeClient->allowedCompositingTriggers();
161 hasAcceleratedCompositing = m_compositingTriggers;
162 }
163 }
164
165 if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter)
166 setCompositingLayersNeedRebuild();
167
168 m_hasAcceleratedCompositing = hasAcceleratedCompositing;
169 m_showDebugBorders = showDebugBorders;
170 m_showRepaintCounter = showRepaintCounter;
171 }
172
canRender3DTransforms() const173 bool RenderLayerCompositor::canRender3DTransforms() const
174 {
175 return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
176 }
177
setCompositingLayersNeedRebuild(bool needRebuild)178 void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
179 {
180 if (inCompositingMode())
181 m_compositingLayersNeedRebuild = needRebuild;
182 }
183
scheduleLayerFlush()184 void RenderLayerCompositor::scheduleLayerFlush()
185 {
186 Frame* frame = m_renderView->frameView()->frame();
187 Page* page = frame ? frame->page() : 0;
188 if (!page)
189 return;
190
191 page->chrome()->client()->scheduleCompositingLayerSync();
192 }
193
flushPendingLayerChanges()194 void RenderLayerCompositor::flushPendingLayerChanges()
195 {
196 ASSERT(!m_flushingLayers);
197 m_flushingLayers = true;
198
199 // FIXME: FrameView::syncCompositingStateRecursive() calls this for each
200 // frame, so when compositing layers are connected between frames, we'll
201 // end up syncing subframe's layers multiple times.
202 // https://bugs.webkit.org/show_bug.cgi?id=52489
203 if (GraphicsLayer* rootLayer = rootPlatformLayer())
204 rootLayer->syncCompositingState();
205
206 ASSERT(m_flushingLayers);
207 m_flushingLayers = false;
208 }
209
enclosingCompositorFlushingLayers() const210 RenderLayerCompositor* RenderLayerCompositor::enclosingCompositorFlushingLayers() const
211 {
212 if (!m_renderView->frameView())
213 return 0;
214
215 for (Frame* frame = m_renderView->frameView()->frame(); frame; frame = frame->tree()->parent()) {
216 RenderLayerCompositor* compositor = frame->contentRenderer() ? frame->contentRenderer()->compositor() : 0;
217 if (compositor->isFlushingLayers())
218 return compositor;
219 }
220
221 return 0;
222 }
223
scheduleCompositingLayerUpdate()224 void RenderLayerCompositor::scheduleCompositingLayerUpdate()
225 {
226 if (!m_updateCompositingLayersTimer.isActive())
227 m_updateCompositingLayersTimer.startOneShot(0);
228 }
229
compositingLayerUpdatePending() const230 bool RenderLayerCompositor::compositingLayerUpdatePending() const
231 {
232 return m_updateCompositingLayersTimer.isActive();
233 }
234
updateCompositingLayersTimerFired(Timer<RenderLayerCompositor> *)235 void RenderLayerCompositor::updateCompositingLayersTimerFired(Timer<RenderLayerCompositor>*)
236 {
237 updateCompositingLayers();
238 }
239
updateCompositingLayers(CompositingUpdateType updateType,RenderLayer * updateRoot)240 void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
241 {
242 m_updateCompositingLayersTimer.stop();
243
244 if (!m_compositingDependsOnGeometry && !m_compositing)
245 return;
246
247 bool checkForHierarchyUpdate = m_compositingDependsOnGeometry;
248 bool needGeometryUpdate = false;
249
250 switch (updateType) {
251 case CompositingUpdateAfterLayoutOrStyleChange:
252 case CompositingUpdateOnPaitingOrHitTest:
253 checkForHierarchyUpdate = true;
254 break;
255 case CompositingUpdateOnScroll:
256 if (m_compositingConsultsOverlap)
257 checkForHierarchyUpdate = true; // Overlap can change with scrolling, so need to check for hierarchy updates.
258
259 needGeometryUpdate = true;
260 break;
261 }
262
263 if (!checkForHierarchyUpdate && !needGeometryUpdate)
264 return;
265
266 bool needHierarchyUpdate = m_compositingLayersNeedRebuild;
267 if (!updateRoot || m_compositingConsultsOverlap) {
268 // Only clear the flag if we're updating the entire hierarchy.
269 m_compositingLayersNeedRebuild = false;
270 updateRoot = rootRenderLayer();
271 }
272
273 #if PROFILE_LAYER_REBUILD
274 ++m_rootLayerUpdateCount;
275
276 double startTime = WTF::currentTime();
277 #endif
278
279 if (checkForHierarchyUpdate) {
280 // Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers.
281 // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex.
282 CompositingState compState(updateRoot);
283 bool layersChanged = false;
284 if (m_compositingConsultsOverlap) {
285 OverlapMap overlapTestRequestMap;
286 computeCompositingRequirements(updateRoot, &overlapTestRequestMap, compState, layersChanged);
287 } else
288 computeCompositingRequirements(updateRoot, 0, compState, layersChanged);
289
290 needHierarchyUpdate |= layersChanged;
291 }
292
293 if (needHierarchyUpdate) {
294 // Update the hierarchy of the compositing layers.
295 CompositingState compState(updateRoot);
296 Vector<GraphicsLayer*> childList;
297 rebuildCompositingLayerTree(updateRoot, compState, childList);
298
299 // Host the document layer in the RenderView's root layer.
300 if (updateRoot == rootRenderLayer()) {
301 if (childList.isEmpty())
302 destroyRootPlatformLayer();
303 else
304 m_rootPlatformLayer->setChildren(childList);
305 }
306 } else if (needGeometryUpdate) {
307 // We just need to do a geometry update. This is only used for position:fixed scrolling;
308 // most of the time, geometry is updated via RenderLayer::styleChanged().
309 updateLayerTreeGeometry(updateRoot);
310 }
311
312 #if PROFILE_LAYER_REBUILD
313 double endTime = WTF::currentTime();
314 if (updateRoot == rootRenderLayer())
315 fprintf(stderr, "Update %d: computeCompositingRequirements for the world took %fms\n",
316 m_rootLayerUpdateCount, 1000.0 * (endTime - startTime));
317 #endif
318 ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
319
320 if (!hasAcceleratedCompositing())
321 enableCompositingMode(false);
322 }
323
updateBacking(RenderLayer * layer,CompositingChangeRepaint shouldRepaint)324 bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
325 {
326 bool layerChanged = false;
327
328 if (needsToBeComposited(layer)) {
329 enableCompositingMode();
330
331 // 3D transforms turn off the testing of overlap.
332 if (requiresCompositingForTransform(layer->renderer()))
333 setCompositingConsultsOverlap(false);
334
335 if (!layer->backing()) {
336
337 // If we need to repaint, do so before making backing
338 if (shouldRepaint == CompositingChangeRepaintNow)
339 repaintOnCompositingChange(layer);
340
341 layer->ensureBacking();
342
343 #if PLATFORM(MAC) && USE(CA)
344 if (m_renderView->document()->settings()->acceleratedDrawingEnabled())
345 layer->backing()->graphicsLayer()->setAcceleratesDrawing(true);
346 else if (layer->renderer()->isCanvas()) {
347 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(layer->renderer()->node());
348 if (canvas->renderingContext() && canvas->renderingContext()->isAccelerated())
349 layer->backing()->graphicsLayer()->setAcceleratesDrawing(true);
350 }
351 #endif
352 layerChanged = true;
353 }
354 } else {
355 if (layer->backing()) {
356 // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to
357 // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection
358 // are both either composited, or not composited.
359 if (layer->isReflection()) {
360 RenderLayer* sourceLayer = toRenderBoxModelObject(layer->renderer()->parent())->layer();
361 if (RenderLayerBacking* backing = sourceLayer->backing()) {
362 ASSERT(backing->graphicsLayer()->replicaLayer() == layer->backing()->graphicsLayer());
363 backing->graphicsLayer()->setReplicatedByLayer(0);
364 }
365 }
366
367 layer->clearBacking();
368 layerChanged = true;
369
370 // The layer's cached repaints rects are relative to the repaint container, so change when
371 // compositing changes; we need to update them here.
372 layer->computeRepaintRects();
373
374 // If we need to repaint, do so now that we've removed the backing
375 if (shouldRepaint == CompositingChangeRepaintNow)
376 repaintOnCompositingChange(layer);
377 }
378 }
379
380 #if ENABLE(VIDEO)
381 if (layerChanged && layer->renderer()->isVideo()) {
382 // If it's a video, give the media player a chance to hook up to the layer.
383 RenderVideo* video = toRenderVideo(layer->renderer());
384 video->acceleratedRenderingStateChanged();
385 }
386 #endif
387
388 if (layerChanged && layer->renderer()->isRenderPart()) {
389 RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
390 if (innerCompositor && innerCompositor->inCompositingMode())
391 innerCompositor->updateRootLayerAttachment();
392 }
393
394 return layerChanged;
395 }
396
updateLayerCompositingState(RenderLayer * layer,CompositingChangeRepaint shouldRepaint)397 bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
398 {
399 bool layerChanged = updateBacking(layer, shouldRepaint);
400
401 // See if we need content or clipping layers. Methods called here should assume
402 // that the compositing state of descendant layers has not been updated yet.
403 if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration())
404 layerChanged = true;
405
406 return layerChanged;
407 }
408
repaintOnCompositingChange(RenderLayer * layer)409 void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
410 {
411 // If the renderer is not attached yet, no need to repaint.
412 if (layer->renderer() != m_renderView && !layer->renderer()->parent())
413 return;
414
415 RenderBoxModelObject* repaintContainer = layer->renderer()->containerForRepaint();
416 if (!repaintContainer)
417 repaintContainer = m_renderView;
418
419 layer->repaintIncludingNonCompositingDescendants(repaintContainer);
420 if (repaintContainer == m_renderView) {
421 // The contents of this layer may be moving between the window
422 // and a GraphicsLayer, so we need to make sure the window system
423 // synchronizes those changes on the screen.
424 m_renderView->frameView()->setNeedsOneShotDrawingSynchronization();
425 }
426 }
427
428 // The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
429 // RenderLayers that are rendered by the composited RenderLayer.
calculateCompositedBounds(const RenderLayer * layer,const RenderLayer * ancestorLayer)430 IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer)
431 {
432 if (!canBeComposited(layer))
433 return IntRect();
434
435 IntRect boundingBoxRect = layer->localBoundingBox();
436 if (layer->renderer()->isRoot()) {
437 // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
438 // then it has to be big enough to cover the viewport in order to display the background. This is akin
439 // to the code in RenderBox::paintRootBoxFillLayers().
440 if (m_renderView->frameView()) {
441 int rw = m_renderView->frameView()->contentsWidth();
442 int rh = m_renderView->frameView()->contentsHeight();
443
444 boundingBoxRect.setWidth(max(boundingBoxRect.width(), rw - boundingBoxRect.x()));
445 boundingBoxRect.setHeight(max(boundingBoxRect.height(), rh - boundingBoxRect.y()));
446 }
447 }
448
449 IntRect unionBounds = boundingBoxRect;
450
451 if (layer->renderer()->hasOverflowClip() || layer->renderer()->hasMask()) {
452 int ancestorRelX = 0, ancestorRelY = 0;
453 layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
454 boundingBoxRect.move(ancestorRelX, ancestorRelY);
455 return boundingBoxRect;
456 }
457
458 if (RenderLayer* reflection = layer->reflectionLayer()) {
459 if (!reflection->isComposited()) {
460 IntRect childUnionBounds = calculateCompositedBounds(reflection, layer);
461 unionBounds.unite(childUnionBounds);
462 }
463 }
464
465 ASSERT(layer->isStackingContext() || (!layer->m_posZOrderList || layer->m_posZOrderList->size() == 0));
466
467 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
468 size_t listSize = negZOrderList->size();
469 for (size_t i = 0; i < listSize; ++i) {
470 RenderLayer* curLayer = negZOrderList->at(i);
471 if (!curLayer->isComposited()) {
472 IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
473 unionBounds.unite(childUnionBounds);
474 }
475 }
476 }
477
478 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
479 size_t listSize = posZOrderList->size();
480 for (size_t i = 0; i < listSize; ++i) {
481 RenderLayer* curLayer = posZOrderList->at(i);
482 if (!curLayer->isComposited()) {
483 IntRect childUnionBounds = calculateCompositedBounds(curLayer, layer);
484 unionBounds.unite(childUnionBounds);
485 }
486 }
487 }
488
489 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
490 size_t listSize = normalFlowList->size();
491 for (size_t i = 0; i < listSize; ++i) {
492 RenderLayer* curLayer = normalFlowList->at(i);
493 if (!curLayer->isComposited()) {
494 IntRect curAbsBounds = calculateCompositedBounds(curLayer, layer);
495 unionBounds.unite(curAbsBounds);
496 }
497 }
498 }
499
500 if (layer->paintsWithTransform(PaintBehaviorNormal)) {
501 TransformationMatrix* affineTrans = layer->transform();
502 boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
503 unionBounds = affineTrans->mapRect(unionBounds);
504 }
505
506 int ancestorRelX = 0, ancestorRelY = 0;
507 layer->convertToLayerCoords(ancestorLayer, ancestorRelX, ancestorRelY);
508 unionBounds.move(ancestorRelX, ancestorRelY);
509
510 return unionBounds;
511 }
512
layerWasAdded(RenderLayer *,RenderLayer *)513 void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
514 {
515 setCompositingLayersNeedRebuild();
516 }
517
layerWillBeRemoved(RenderLayer * parent,RenderLayer * child)518 void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
519 {
520 if (!child->isComposited() || parent->renderer()->documentBeingDestroyed())
521 return;
522
523 setCompositingParent(child, 0);
524
525 RenderLayer* compLayer = parent->enclosingCompositingLayer();
526 if (compLayer) {
527 ASSERT(compLayer->backing());
528 IntRect compBounds = child->backing()->compositedBounds();
529
530 int offsetX = 0, offsetY = 0;
531 child->convertToLayerCoords(compLayer, offsetX, offsetY);
532 compBounds.move(offsetX, offsetY);
533
534 compLayer->setBackingNeedsRepaintInRect(compBounds);
535
536 // The contents of this layer may be moving from a GraphicsLayer to the window,
537 // so we need to make sure the window system synchronizes those changes on the screen.
538 m_renderView->frameView()->setNeedsOneShotDrawingSynchronization();
539 }
540
541 setCompositingLayersNeedRebuild();
542 }
543
enclosingNonStackingClippingLayer(const RenderLayer * layer) const544 RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
545 {
546 for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) {
547 if (curr->isStackingContext())
548 return 0;
549
550 if (curr->renderer()->hasOverflowClip() || curr->renderer()->hasClip())
551 return curr;
552 }
553 return 0;
554 }
555
addToOverlapMap(OverlapMap & overlapMap,RenderLayer * layer,IntRect & layerBounds,bool & boundsComputed)556 void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
557 {
558 if (layer->isRootLayer())
559 return;
560
561 if (!boundsComputed) {
562 layerBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
563 // Empty rects never intersect, but we need them to for the purposes of overlap testing.
564 if (layerBounds.isEmpty())
565 layerBounds.setSize(IntSize(1, 1));
566 boundsComputed = true;
567 }
568
569 overlapMap.add(layer, layerBounds);
570 }
571
overlapsCompositedLayers(OverlapMap & overlapMap,const IntRect & layerBounds)572 bool RenderLayerCompositor::overlapsCompositedLayers(OverlapMap& overlapMap, const IntRect& layerBounds)
573 {
574 RenderLayerCompositor::OverlapMap::const_iterator end = overlapMap.end();
575 for (RenderLayerCompositor::OverlapMap::const_iterator it = overlapMap.begin(); it != end; ++it) {
576 const IntRect& bounds = it->second;
577 if (layerBounds.intersects(bounds))
578 return true;
579 }
580
581 return false;
582 }
583
584 // Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
585 // For the z-order children of a compositing layer:
586 // If a child layers has a compositing layer, then all subsequent layers must
587 // be compositing in order to render above that layer.
588 //
589 // If a child in the negative z-order list is compositing, then the layer itself
590 // must be compositing so that its contents render over that child.
591 // This implies that its positive z-index children must also be compositing.
592 //
computeCompositingRequirements(RenderLayer * layer,OverlapMap * overlapMap,struct CompositingState & compositingState,bool & layersChanged)593 void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* layer, OverlapMap* overlapMap, struct CompositingState& compositingState, bool& layersChanged)
594 {
595 layer->updateLayerPosition();
596 layer->updateZOrderLists();
597 layer->updateNormalFlowList();
598
599 // Clear the flag
600 layer->setHasCompositingDescendant(false);
601
602 bool mustOverlapCompositedLayers = compositingState.m_subtreeIsCompositing;
603
604 bool haveComputedBounds = false;
605 IntRect absBounds;
606 if (overlapMap && !overlapMap->isEmpty()) {
607 // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
608 absBounds = layer->renderer()->localToAbsoluteQuad(FloatRect(layer->localBoundingBox())).enclosingBoundingBox();
609 // Empty rects never intersect, but we need them to for the purposes of overlap testing.
610 if (absBounds.isEmpty())
611 absBounds.setSize(IntSize(1, 1));
612 haveComputedBounds = true;
613 mustOverlapCompositedLayers = overlapsCompositedLayers(*overlapMap, absBounds);
614 }
615
616 layer->setMustOverlapCompositedLayers(mustOverlapCompositedLayers);
617
618 // The children of this layer don't need to composite, unless there is
619 // a compositing layer among them, so start by inheriting the compositing
620 // ancestor with m_subtreeIsCompositing set to false.
621 CompositingState childState(compositingState.m_compositingAncestor);
622 #ifndef NDEBUG
623 ++childState.m_depth;
624 #endif
625
626 bool willBeComposited = needsToBeComposited(layer);
627 if (willBeComposited) {
628 // Tell the parent it has compositing descendants.
629 compositingState.m_subtreeIsCompositing = true;
630 // This layer now acts as the ancestor for kids.
631 childState.m_compositingAncestor = layer;
632 if (overlapMap)
633 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
634 }
635
636 #if ENABLE(VIDEO)
637 // Video is special. It's a replaced element with a content layer, but has shadow content
638 // for the controller that must render in front. Without this, the controls fail to show
639 // when the video element is a stacking context (e.g. due to opacity or transform).
640 if (willBeComposited && layer->renderer()->isVideo())
641 childState.m_subtreeIsCompositing = true;
642 #endif
643
644 if (layer->isStackingContext()) {
645 ASSERT(!layer->m_zOrderListsDirty);
646 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
647 size_t listSize = negZOrderList->size();
648 for (size_t i = 0; i < listSize; ++i) {
649 RenderLayer* curLayer = negZOrderList->at(i);
650 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
651
652 // If we have to make a layer for this child, make one now so we can have a contents layer
653 // (since we need to ensure that the -ve z-order child renders underneath our contents).
654 if (!willBeComposited && childState.m_subtreeIsCompositing) {
655 // make layer compositing
656 layer->setMustOverlapCompositedLayers(true);
657 childState.m_compositingAncestor = layer;
658 if (overlapMap)
659 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
660 willBeComposited = true;
661 }
662 }
663 }
664 }
665
666 ASSERT(!layer->m_normalFlowListDirty);
667 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
668 size_t listSize = normalFlowList->size();
669 for (size_t i = 0; i < listSize; ++i) {
670 RenderLayer* curLayer = normalFlowList->at(i);
671 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
672 }
673 }
674
675 if (layer->isStackingContext()) {
676 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
677 size_t listSize = posZOrderList->size();
678 for (size_t i = 0; i < listSize; ++i) {
679 RenderLayer* curLayer = posZOrderList->at(i);
680 computeCompositingRequirements(curLayer, overlapMap, childState, layersChanged);
681 }
682 }
683 }
684
685 // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled).
686 if (layer->isRootLayer()) {
687 if (inCompositingMode() && m_hasAcceleratedCompositing)
688 willBeComposited = true;
689 }
690
691 ASSERT(willBeComposited == needsToBeComposited(layer));
692
693 // If we have a software transform, and we have layers under us, we need to also
694 // be composited. Also, if we have opacity < 1, then we need to be a layer so that
695 // the child layers are opaque, then rendered with opacity on this layer.
696 if (!willBeComposited && canBeComposited(layer) && childState.m_subtreeIsCompositing && requiresCompositingWhenDescendantsAreCompositing(layer->renderer())) {
697 layer->setMustOverlapCompositedLayers(true);
698 if (overlapMap)
699 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
700 willBeComposited = true;
701 }
702
703 ASSERT(willBeComposited == needsToBeComposited(layer));
704 if (layer->reflectionLayer())
705 layer->reflectionLayer()->setMustOverlapCompositedLayers(willBeComposited);
706
707 // Subsequent layers in the parent stacking context also need to composite.
708 if (childState.m_subtreeIsCompositing)
709 compositingState.m_subtreeIsCompositing = true;
710
711 // Set the flag to say that this SC has compositing children.
712 layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
713
714 // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping,
715 // so test that again.
716 if (!willBeComposited && canBeComposited(layer) && clipsCompositingDescendants(layer)) {
717 if (overlapMap)
718 addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
719 willBeComposited = true;
720 }
721
722 // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
723 // to be composited, then we can drop out of compositing mode altogether.
724 if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode) {
725 enableCompositingMode(false);
726 willBeComposited = false;
727 }
728
729 // If the layer is going into compositing mode, repaint its old location.
730 ASSERT(willBeComposited == needsToBeComposited(layer));
731 if (!layer->isComposited() && willBeComposited)
732 repaintOnCompositingChange(layer);
733
734 // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree().
735 if (updateBacking(layer, CompositingChangeRepaintNow))
736 layersChanged = true;
737
738 if (layer->reflectionLayer() && updateLayerCompositingState(layer->reflectionLayer(), CompositingChangeRepaintNow))
739 layersChanged = true;
740 }
741
setCompositingParent(RenderLayer * childLayer,RenderLayer * parentLayer)742 void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
743 {
744 ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer);
745 ASSERT(childLayer->isComposited());
746
747 // It's possible to be called with a parent that isn't yet composited when we're doing
748 // partial updates as required by painting or hit testing. Just bail in that case;
749 // we'll do a full layer update soon.
750 if (!parentLayer || !parentLayer->isComposited())
751 return;
752
753 if (parentLayer) {
754 GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers();
755 GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers();
756
757 hostingLayer->addChild(hostedLayer);
758 } else
759 childLayer->backing()->childForSuperlayers()->removeFromParent();
760 }
761
removeCompositedChildren(RenderLayer * layer)762 void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
763 {
764 ASSERT(layer->isComposited());
765
766 GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers();
767 hostingLayer->removeAllChildren();
768 }
769
770 #if ENABLE(VIDEO)
canAccelerateVideoRendering(RenderVideo * o) const771 bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
772 {
773 if (!m_hasAcceleratedCompositing)
774 return false;
775
776 return o->supportsAcceleratedRendering();
777 }
778 #endif
779
rebuildCompositingLayerTree(RenderLayer * layer,const CompositingState & compositingState,Vector<GraphicsLayer * > & childLayersOfEnclosingLayer)780 void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, const CompositingState& compositingState, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer)
781 {
782 // Make the layer compositing if necessary, and set up clipping and content layers.
783 // Note that we can only do work here that is independent of whether the descendant layers
784 // have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
785
786 RenderLayerBacking* layerBacking = layer->backing();
787 if (layerBacking) {
788 // The compositing state of all our children has been updated already, so now
789 // we can compute and cache the composited bounds for this layer.
790 layerBacking->updateCompositedBounds();
791
792 if (RenderLayer* reflection = layer->reflectionLayer()) {
793 if (reflection->backing())
794 reflection->backing()->updateCompositedBounds();
795 }
796
797 layerBacking->updateGraphicsLayerConfiguration();
798 layerBacking->updateGraphicsLayerGeometry();
799
800 if (!layer->parent())
801 updateRootLayerPosition();
802 }
803
804 // If this layer has backing, then we are collecting its children, otherwise appending
805 // to the compositing child list of an enclosing layer.
806 Vector<GraphicsLayer*> layerChildren;
807 Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer;
808
809 CompositingState childState = compositingState;
810 if (layer->isComposited())
811 childState.m_compositingAncestor = layer;
812
813 #ifndef NDEBUG
814 ++childState.m_depth;
815 #endif
816
817 // The children of this stacking context don't need to composite, unless there is
818 // a compositing layer among them, so start by assuming false.
819 childState.m_subtreeIsCompositing = false;
820
821 if (layer->isStackingContext()) {
822 ASSERT(!layer->m_zOrderListsDirty);
823
824 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
825 size_t listSize = negZOrderList->size();
826 for (size_t i = 0; i < listSize; ++i) {
827 RenderLayer* curLayer = negZOrderList->at(i);
828 rebuildCompositingLayerTree(curLayer, childState, childList);
829 }
830 }
831
832 // If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
833 if (layerBacking && layerBacking->foregroundLayer())
834 childList.append(layerBacking->foregroundLayer());
835 }
836
837 ASSERT(!layer->m_normalFlowListDirty);
838 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
839 size_t listSize = normalFlowList->size();
840 for (size_t i = 0; i < listSize; ++i) {
841 RenderLayer* curLayer = normalFlowList->at(i);
842 rebuildCompositingLayerTree(curLayer, childState, childList);
843 }
844 }
845
846 if (layer->isStackingContext()) {
847 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
848 size_t listSize = posZOrderList->size();
849 for (size_t i = 0; i < listSize; ++i) {
850 RenderLayer* curLayer = posZOrderList->at(i);
851 rebuildCompositingLayerTree(curLayer, childState, childList);
852 }
853 }
854 }
855
856 if (layerBacking) {
857 bool parented = false;
858 if (layer->renderer()->isRenderPart())
859 parented = parentFrameContentLayers(toRenderPart(layer->renderer()));
860
861 // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
862 // Otherwise, the overflow control layers are normal children.
863 if (!layerBacking->hasClippingLayer()) {
864 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) {
865 overflowControlLayer->removeFromParent();
866 layerChildren.append(overflowControlLayer);
867 }
868
869 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForVerticalScrollbar()) {
870 overflowControlLayer->removeFromParent();
871 layerChildren.append(overflowControlLayer);
872 }
873
874 if (GraphicsLayer* overflowControlLayer = layerBacking->layerForScrollCorner()) {
875 overflowControlLayer->removeFromParent();
876 layerChildren.append(overflowControlLayer);
877 }
878 }
879
880 if (!parented)
881 layerBacking->parentForSublayers()->setChildren(layerChildren);
882
883 #if ENABLE(FULLSCREEN_API)
884 // For the sake of clients of the full screen renderer, don't reparent
885 // the full screen layer out from under them if they're in the middle of
886 // animating.
887 if (layer->renderer()->isRenderFullScreen() && toRenderFullScreen(layer->renderer())->isAnimating())
888 return;
889 #endif
890 childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers());
891 }
892 }
893
frameViewDidChangeLocation(const IntPoint & contentsOffset)894 void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
895 {
896 if (m_overflowControlsHostLayer)
897 m_overflowControlsHostLayer->setPosition(contentsOffset);
898 }
899
frameViewDidChangeSize()900 void RenderLayerCompositor::frameViewDidChangeSize()
901 {
902 if (m_clipLayer) {
903 FrameView* frameView = m_renderView->frameView();
904 m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
905
906 IntPoint scrollPosition = frameView->scrollPosition();
907 m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
908 updateOverflowControlsLayers();
909 }
910 }
911
frameViewDidScroll(const IntPoint & scrollPosition)912 void RenderLayerCompositor::frameViewDidScroll(const IntPoint& scrollPosition)
913 {
914 if (m_scrollLayer)
915 m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
916 }
917
layerTreeAsText(bool showDebugInfo)918 String RenderLayerCompositor::layerTreeAsText(bool showDebugInfo)
919 {
920 if (compositingLayerUpdatePending())
921 updateCompositingLayers();
922
923 if (!m_rootPlatformLayer)
924 return String();
925
926 // We skip dumping the scroll and clip layers to keep layerTreeAsText output
927 // similar between platforms.
928 return m_rootPlatformLayer->layerTreeAsText(showDebugInfo ? LayerTreeAsTextDebug : LayerTreeAsTextBehaviorNormal);
929 }
930
frameContentsCompositor(RenderPart * renderer)931 RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
932 {
933 if (!renderer->node()->isFrameOwnerElement())
934 return 0;
935
936 HTMLFrameOwnerElement* element = static_cast<HTMLFrameOwnerElement*>(renderer->node());
937 if (Document* contentDocument = element->contentDocument()) {
938 if (RenderView* view = contentDocument->renderView())
939 return view->compositor();
940 }
941 return 0;
942 }
943
parentFrameContentLayers(RenderPart * renderer)944 bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
945 {
946 RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
947 if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
948 return false;
949
950 RenderLayer* layer = renderer->layer();
951 if (!layer->isComposited())
952 return false;
953
954 RenderLayerBacking* backing = layer->backing();
955 GraphicsLayer* hostingLayer = backing->parentForSublayers();
956 GraphicsLayer* rootLayer = innerCompositor->rootPlatformLayer();
957 if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
958 hostingLayer->removeAllChildren();
959 hostingLayer->addChild(rootLayer);
960 }
961 return true;
962 }
963
964 // This just updates layer geometry without changing the hierarchy.
updateLayerTreeGeometry(RenderLayer * layer)965 void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer)
966 {
967 if (RenderLayerBacking* layerBacking = layer->backing()) {
968 // The compositing state of all our children has been updated already, so now
969 // we can compute and cache the composited bounds for this layer.
970 layerBacking->updateCompositedBounds();
971
972 if (RenderLayer* reflection = layer->reflectionLayer()) {
973 if (reflection->backing())
974 reflection->backing()->updateCompositedBounds();
975 }
976
977 layerBacking->updateGraphicsLayerConfiguration();
978 layerBacking->updateGraphicsLayerGeometry();
979
980 if (!layer->parent())
981 updateRootLayerPosition();
982 }
983
984 if (layer->isStackingContext()) {
985 ASSERT(!layer->m_zOrderListsDirty);
986
987 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
988 size_t listSize = negZOrderList->size();
989 for (size_t i = 0; i < listSize; ++i)
990 updateLayerTreeGeometry(negZOrderList->at(i));
991 }
992 }
993
994 ASSERT(!layer->m_normalFlowListDirty);
995 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
996 size_t listSize = normalFlowList->size();
997 for (size_t i = 0; i < listSize; ++i)
998 updateLayerTreeGeometry(normalFlowList->at(i));
999 }
1000
1001 if (layer->isStackingContext()) {
1002 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
1003 size_t listSize = posZOrderList->size();
1004 for (size_t i = 0; i < listSize; ++i)
1005 updateLayerTreeGeometry(posZOrderList->at(i));
1006 }
1007 }
1008 }
1009
1010 // Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
updateCompositingDescendantGeometry(RenderLayer * compositingAncestor,RenderLayer * layer,RenderLayerBacking::UpdateDepth updateDepth)1011 void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, RenderLayerBacking::UpdateDepth updateDepth)
1012 {
1013 if (layer != compositingAncestor) {
1014 if (RenderLayerBacking* layerBacking = layer->backing()) {
1015 layerBacking->updateCompositedBounds();
1016
1017 if (RenderLayer* reflection = layer->reflectionLayer()) {
1018 if (reflection->backing())
1019 reflection->backing()->updateCompositedBounds();
1020 }
1021
1022 layerBacking->updateGraphicsLayerGeometry();
1023 if (updateDepth == RenderLayerBacking::CompositingChildren)
1024 return;
1025 }
1026 }
1027
1028 if (layer->reflectionLayer())
1029 updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionLayer(), updateDepth);
1030
1031 if (!layer->hasCompositingDescendant())
1032 return;
1033
1034 if (layer->isStackingContext()) {
1035 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
1036 size_t listSize = negZOrderList->size();
1037 for (size_t i = 0; i < listSize; ++i)
1038 updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), updateDepth);
1039 }
1040 }
1041
1042 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
1043 size_t listSize = normalFlowList->size();
1044 for (size_t i = 0; i < listSize; ++i)
1045 updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), updateDepth);
1046 }
1047
1048 if (layer->isStackingContext()) {
1049 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
1050 size_t listSize = posZOrderList->size();
1051 for (size_t i = 0; i < listSize; ++i)
1052 updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), updateDepth);
1053 }
1054 }
1055 }
1056
1057
repaintCompositedLayersAbsoluteRect(const IntRect & absRect)1058 void RenderLayerCompositor::repaintCompositedLayersAbsoluteRect(const IntRect& absRect)
1059 {
1060 recursiveRepaintLayerRect(rootRenderLayer(), absRect);
1061 }
1062
recursiveRepaintLayerRect(RenderLayer * layer,const IntRect & rect)1063 void RenderLayerCompositor::recursiveRepaintLayerRect(RenderLayer* layer, const IntRect& rect)
1064 {
1065 // FIXME: This method does not work correctly with transforms.
1066 if (layer->isComposited())
1067 layer->setBackingNeedsRepaintInRect(rect);
1068
1069 if (layer->hasCompositingDescendant()) {
1070 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
1071 size_t listSize = negZOrderList->size();
1072 for (size_t i = 0; i < listSize; ++i) {
1073 RenderLayer* curLayer = negZOrderList->at(i);
1074 int x = 0;
1075 int y = 0;
1076 curLayer->convertToLayerCoords(layer, x, y);
1077 IntRect childRect(rect);
1078 childRect.move(-x, -y);
1079 recursiveRepaintLayerRect(curLayer, childRect);
1080 }
1081 }
1082
1083 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
1084 size_t listSize = posZOrderList->size();
1085 for (size_t i = 0; i < listSize; ++i) {
1086 RenderLayer* curLayer = posZOrderList->at(i);
1087 int x = 0;
1088 int y = 0;
1089 curLayer->convertToLayerCoords(layer, x, y);
1090 IntRect childRect(rect);
1091 childRect.move(-x, -y);
1092 recursiveRepaintLayerRect(curLayer, childRect);
1093 }
1094 }
1095 }
1096 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
1097 size_t listSize = normalFlowList->size();
1098 for (size_t i = 0; i < listSize; ++i) {
1099 RenderLayer* curLayer = normalFlowList->at(i);
1100 int x = 0;
1101 int y = 0;
1102 curLayer->convertToLayerCoords(layer, x, y);
1103 IntRect childRect(rect);
1104 childRect.move(-x, -y);
1105 recursiveRepaintLayerRect(curLayer, childRect);
1106 }
1107 }
1108 }
1109
rootRenderLayer() const1110 RenderLayer* RenderLayerCompositor::rootRenderLayer() const
1111 {
1112 return m_renderView->layer();
1113 }
1114
rootPlatformLayer() const1115 GraphicsLayer* RenderLayerCompositor::rootPlatformLayer() const
1116 {
1117 if (m_overflowControlsHostLayer)
1118 return m_overflowControlsHostLayer.get();
1119 return m_rootPlatformLayer.get();
1120 }
1121
didMoveOnscreen()1122 void RenderLayerCompositor::didMoveOnscreen()
1123 {
1124 if (!inCompositingMode() || m_rootLayerAttachment != RootLayerUnattached)
1125 return;
1126
1127 RootLayerAttachment attachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
1128 attachRootPlatformLayer(attachment);
1129 }
1130
willMoveOffscreen()1131 void RenderLayerCompositor::willMoveOffscreen()
1132 {
1133 if (!inCompositingMode() || m_rootLayerAttachment == RootLayerUnattached)
1134 return;
1135
1136 detachRootPlatformLayer();
1137 }
1138
updateRootLayerPosition()1139 void RenderLayerCompositor::updateRootLayerPosition()
1140 {
1141 if (m_rootPlatformLayer) {
1142 m_rootPlatformLayer->setSize(FloatSize(m_renderView->docWidth(), m_renderView->docHeight()));
1143 m_rootPlatformLayer->setPosition(FloatPoint(m_renderView->docLeft(), m_renderView->docTop()));
1144 }
1145 if (m_clipLayer) {
1146 FrameView* frameView = m_renderView->frameView();
1147 m_clipLayer->setSize(frameView->visibleContentRect(false /* exclude scrollbars */).size());
1148 }
1149 }
1150
didStartAcceleratedAnimation(CSSPropertyID property)1151 void RenderLayerCompositor::didStartAcceleratedAnimation(CSSPropertyID property)
1152 {
1153 // If an accelerated animation or transition runs, we have to turn off overlap checking because
1154 // we don't do layout for every frame, but we have to ensure that the layering is
1155 // correct between the animating object and other objects on the page.
1156 if (property == CSSPropertyWebkitTransform)
1157 setCompositingConsultsOverlap(false);
1158 }
1159
has3DContent() const1160 bool RenderLayerCompositor::has3DContent() const
1161 {
1162 return layerHas3DContent(rootRenderLayer());
1163 }
1164
allowsIndependentlyCompositedFrames(const FrameView * view)1165 bool RenderLayerCompositor::allowsIndependentlyCompositedFrames(const FrameView* view)
1166 {
1167 #if PLATFORM(MAC)
1168 // frames are only independently composited in Mac pre-WebKit2.
1169 return view->platformWidget();
1170 #endif
1171 return false;
1172 }
1173
shouldPropagateCompositingToEnclosingFrame() const1174 bool RenderLayerCompositor::shouldPropagateCompositingToEnclosingFrame() const
1175 {
1176 // Parent document content needs to be able to render on top of a composited frame, so correct behavior
1177 // is to have the parent document become composited too. However, this can cause problems on platforms that
1178 // use native views for frames (like Mac), so disable that behavior on those platforms for now.
1179 HTMLFrameOwnerElement* ownerElement = enclosingFrameElement();
1180 RenderObject* renderer = ownerElement ? ownerElement->renderer() : 0;
1181
1182 // If we are the top-level frame, don't propagate.
1183 if (!ownerElement)
1184 return false;
1185
1186 if (!allowsIndependentlyCompositedFrames(m_renderView->frameView()))
1187 return true;
1188
1189 if (!renderer || !renderer->isRenderPart())
1190 return false;
1191
1192 // On Mac, only propagate compositing if the frame is overlapped in the parent
1193 // document, or the parent is already compositing, or the main frame is scaled.
1194 Frame* frame = m_renderView->frameView()->frame();
1195 Page* page = frame ? frame->page() : 0;
1196 if (page->mainFrame()->pageScaleFactor() != 1)
1197 return true;
1198
1199 RenderPart* frameRenderer = toRenderPart(renderer);
1200 if (frameRenderer->widget()) {
1201 ASSERT(frameRenderer->widget()->isFrameView());
1202 FrameView* view = static_cast<FrameView*>(frameRenderer->widget());
1203 if (view->isOverlappedIncludingAncestors() || view->hasCompositingAncestor())
1204 return true;
1205 }
1206
1207 return false;
1208 }
1209
enclosingFrameElement() const1210 HTMLFrameOwnerElement* RenderLayerCompositor::enclosingFrameElement() const
1211 {
1212 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
1213 return (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(objectTag)) ? ownerElement : 0;
1214
1215 return 0;
1216 }
1217
needsToBeComposited(const RenderLayer * layer) const1218 bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
1219 {
1220 if (!canBeComposited(layer))
1221 return false;
1222
1223 return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers() || (inCompositingMode() && layer->isRootLayer());
1224 }
1225
1226 // Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
1227 // Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
1228 // static
requiresCompositingLayer(const RenderLayer * layer) const1229 bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const
1230 {
1231 RenderObject* renderer = layer->renderer();
1232 // The compositing state of a reflection should match that of its reflected layer.
1233 if (layer->isReflection()) {
1234 renderer = renderer->parent(); // The RenderReplica's parent is the object being reflected.
1235 layer = toRenderBoxModelObject(renderer)->layer();
1236 }
1237 // The root layer always has a compositing layer, but it may not have backing.
1238 return requiresCompositingForTransform(renderer)
1239 || requiresCompositingForVideo(renderer)
1240 || requiresCompositingForCanvas(renderer)
1241 || requiresCompositingForPlugin(renderer)
1242 || requiresCompositingForFrame(renderer)
1243 || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
1244 || clipsCompositingDescendants(layer)
1245 || requiresCompositingForAnimation(renderer)
1246 || requiresCompositingForFullScreen(renderer);
1247 }
1248
canBeComposited(const RenderLayer * layer) const1249 bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
1250 {
1251 return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer();
1252 }
1253
1254 // Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
1255 // up to the enclosing compositing ancestor. This is required because compositing layers are parented
1256 // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
1257 // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
1258 // but a sibling in the z-order hierarchy.
clippedByAncestor(RenderLayer * layer) const1259 bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
1260 {
1261 if (!layer->isComposited() || !layer->parent())
1262 return false;
1263
1264 RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
1265 if (!compositingAncestor)
1266 return false;
1267
1268 // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
1269 // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
1270 // and layer.
1271 RenderLayer* computeClipRoot = 0;
1272 RenderLayer* curr = layer;
1273 while (curr) {
1274 RenderLayer* next = curr->parent();
1275 if (next == compositingAncestor) {
1276 computeClipRoot = curr;
1277 break;
1278 }
1279 curr = next;
1280 }
1281
1282 if (!computeClipRoot || computeClipRoot == layer)
1283 return false;
1284
1285 IntRect backgroundRect = layer->backgroundClipRect(computeClipRoot, true);
1286 return backgroundRect != PaintInfo::infiniteRect();
1287 }
1288
1289 // Return true if the given layer is a stacking context and has compositing child
1290 // layers that it needs to clip. In this case we insert a clipping GraphicsLayer
1291 // into the hierarchy between this layer and its children in the z-order hierarchy.
clipsCompositingDescendants(const RenderLayer * layer) const1292 bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
1293 {
1294 return layer->hasCompositingDescendant() &&
1295 (layer->renderer()->hasOverflowClip() || layer->renderer()->hasClip());
1296 }
1297
requiresCompositingForTransform(RenderObject * renderer) const1298 bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const
1299 {
1300 if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
1301 return false;
1302
1303 RenderStyle* style = renderer->style();
1304 // Note that we ask the renderer if it has a transform, because the style may have transforms,
1305 // but the renderer may be an inline that doesn't suppport them.
1306 return renderer->hasTransform() && (style->transform().has3DOperation() || style->transformStyle3D() == TransformStyle3DPreserve3D || style->hasPerspective());
1307 }
1308
requiresCompositingForVideo(RenderObject * renderer) const1309 bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const
1310 {
1311 if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
1312 return false;
1313 #if ENABLE(VIDEO)
1314 if (renderer->isVideo()) {
1315 RenderVideo* video = toRenderVideo(renderer);
1316 return video->shouldDisplayVideo() && canAccelerateVideoRendering(video);
1317 }
1318 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1319 else if (renderer->isRenderPart()) {
1320 if (!m_hasAcceleratedCompositing)
1321 return false;
1322
1323 Node* node = renderer->node();
1324 if (!node || (!node->hasTagName(HTMLNames::videoTag) && !node->hasTagName(HTMLNames::audioTag)))
1325 return false;
1326
1327 HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(node);
1328 return mediaElement->player() ? mediaElement->player()->supportsAcceleratedRendering() : false;
1329 }
1330 #endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1331 #else
1332 UNUSED_PARAM(renderer);
1333 #endif
1334 return false;
1335 }
1336
requiresCompositingForCanvas(RenderObject * renderer) const1337 bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const
1338 {
1339 if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
1340 return false;
1341
1342 if (renderer->isCanvas()) {
1343 HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
1344 return canvas->renderingContext() && canvas->renderingContext()->isAccelerated();
1345 }
1346 return false;
1347 }
1348
requiresCompositingForPlugin(RenderObject * renderer) const1349 bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const
1350 {
1351 if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
1352 return false;
1353
1354 bool composite = (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing())
1355 || (renderer->isApplet() && toRenderApplet(renderer)->allowsAcceleratedCompositing());
1356 if (!composite)
1357 return false;
1358
1359 m_compositingDependsOnGeometry = true;
1360
1361 RenderWidget* pluginRenderer = toRenderWidget(renderer);
1362 // If we can't reliably know the size of the plugin yet, don't change compositing state.
1363 if (pluginRenderer->needsLayout())
1364 return pluginRenderer->hasLayer() && pluginRenderer->layer()->isComposited();
1365
1366 // Don't go into compositing mode if height or width are zero, or size is 1x1.
1367 IntRect contentBox = pluginRenderer->contentBoxRect();
1368 return contentBox.height() * contentBox.width() > 1;
1369 }
1370
requiresCompositingForFrame(RenderObject * renderer) const1371 bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const
1372 {
1373 if (!renderer->isRenderPart())
1374 return false;
1375
1376 RenderPart* frameRenderer = toRenderPart(renderer);
1377
1378 if (!frameRenderer->requiresAcceleratedCompositing())
1379 return false;
1380
1381 m_compositingDependsOnGeometry = true;
1382
1383 RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer);
1384 if (!innerCompositor || !innerCompositor->shouldPropagateCompositingToEnclosingFrame())
1385 return false;
1386
1387 // If we can't reliably know the size of the iframe yet, don't change compositing state.
1388 if (renderer->needsLayout())
1389 return frameRenderer->hasLayer() && frameRenderer->layer()->isComposited();
1390
1391 // Don't go into compositing mode if height or width are zero.
1392 IntRect contentBox = frameRenderer->contentBoxRect();
1393 return contentBox.height() * contentBox.width() > 0;
1394 }
1395
requiresCompositingForAnimation(RenderObject * renderer) const1396 bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
1397 {
1398 if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
1399 return false;
1400
1401 if (AnimationController* animController = renderer->animation()) {
1402 return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
1403 || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
1404 }
1405 return false;
1406 }
1407
requiresCompositingWhenDescendantsAreCompositing(RenderObject * renderer) const1408 bool RenderLayerCompositor::requiresCompositingWhenDescendantsAreCompositing(RenderObject* renderer) const
1409 {
1410 return renderer->hasTransform() || renderer->isTransparent() || renderer->hasMask() || renderer->hasReflection();
1411 }
1412
requiresCompositingForFullScreen(RenderObject * renderer) const1413 bool RenderLayerCompositor::requiresCompositingForFullScreen(RenderObject* renderer) const
1414 {
1415 #if ENABLE(FULLSCREEN_API)
1416 return renderer->isRenderFullScreen() && toRenderFullScreen(renderer)->isAnimating();
1417 #else
1418 UNUSED_PARAM(renderer);
1419 return false;
1420 #endif
1421 }
1422
1423 // If an element has negative z-index children, those children render in front of the
1424 // layer background, so we need an extra 'contents' layer for the foreground of the layer
1425 // object.
needsContentsCompositingLayer(const RenderLayer * layer) const1426 bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
1427 {
1428 return (layer->m_negZOrderList && layer->m_negZOrderList->size() > 0);
1429 }
1430
requiresScrollLayer(RootLayerAttachment attachment) const1431 bool RenderLayerCompositor::requiresScrollLayer(RootLayerAttachment attachment) const
1432 {
1433 // We need to handle our own scrolling if we're:
1434 return !m_renderView->frameView()->platformWidget() // viewless (i.e. non-Mac, or Mac in WebKit2)
1435 || attachment == RootLayerAttachedViaEnclosingFrame; // a composited frame on Mac
1436 }
1437
paintScrollbar(Scrollbar * scrollbar,GraphicsContext & context,const IntRect & clip)1438 static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
1439 {
1440 if (!scrollbar)
1441 return;
1442
1443 context.save();
1444 const IntRect& scrollbarRect = scrollbar->frameRect();
1445 context.translate(-scrollbarRect.x(), -scrollbarRect.y());
1446 IntRect transformedClip = clip;
1447 transformedClip.move(scrollbarRect.x(), scrollbarRect.y());
1448 scrollbar->paint(&context, transformedClip);
1449 context.restore();
1450 }
1451
paintContents(const GraphicsLayer * graphicsLayer,GraphicsContext & context,GraphicsLayerPaintingPhase,const IntRect & clip)1452 void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
1453 {
1454 if (graphicsLayer == layerForHorizontalScrollbar())
1455 paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip);
1456 else if (graphicsLayer == layerForVerticalScrollbar())
1457 paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip);
1458 else if (graphicsLayer == layerForScrollCorner()) {
1459 const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect();
1460 context.save();
1461 context.translate(-scrollCorner.x(), -scrollCorner.y());
1462 IntRect transformedClip = clip;
1463 transformedClip.move(scrollCorner.x(), scrollCorner.y());
1464 m_renderView->frameView()->paintScrollCorner(&context, transformedClip);
1465 context.restore();
1466 }
1467 }
1468
shouldCompositeOverflowControls(ScrollView * view)1469 static bool shouldCompositeOverflowControls(ScrollView* view)
1470 {
1471 if (view->platformWidget())
1472 return false;
1473 #if !PLATFORM(CHROMIUM)
1474 if (!view->hasOverlayScrollbars())
1475 return false;
1476 #endif
1477 return true;
1478 }
1479
requiresHorizontalScrollbarLayer() const1480 bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
1481 {
1482 ScrollView* view = m_renderView->frameView();
1483 return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
1484 }
1485
requiresVerticalScrollbarLayer() const1486 bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
1487 {
1488 ScrollView* view = m_renderView->frameView();
1489 return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
1490 }
1491
requiresScrollCornerLayer() const1492 bool RenderLayerCompositor::requiresScrollCornerLayer() const
1493 {
1494 ScrollView* view = m_renderView->frameView();
1495 return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
1496 }
1497
updateOverflowControlsLayers()1498 void RenderLayerCompositor::updateOverflowControlsLayers()
1499 {
1500 bool layersChanged = false;
1501
1502 if (requiresHorizontalScrollbarLayer()) {
1503 m_layerForHorizontalScrollbar = GraphicsLayer::create(this);
1504 #ifndef NDEBUG
1505 m_layerForHorizontalScrollbar->setName("horizontal scrollbar");
1506 #endif
1507 m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
1508 layersChanged = true;
1509 } else if (m_layerForHorizontalScrollbar) {
1510 m_layerForHorizontalScrollbar->removeFromParent();
1511 m_layerForHorizontalScrollbar = nullptr;
1512 layersChanged = true;
1513 }
1514
1515 if (requiresVerticalScrollbarLayer()) {
1516 m_layerForVerticalScrollbar = GraphicsLayer::create(this);
1517 #ifndef NDEBUG
1518 m_layerForVerticalScrollbar->setName("vertical scrollbar");
1519 #endif
1520 m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
1521 layersChanged = true;
1522 } else if (m_layerForVerticalScrollbar) {
1523 m_layerForVerticalScrollbar->removeFromParent();
1524 m_layerForVerticalScrollbar = nullptr;
1525 layersChanged = true;
1526 }
1527
1528 if (requiresScrollCornerLayer()) {
1529 m_layerForScrollCorner = GraphicsLayer::create(this);
1530 #ifndef NDEBUG
1531 m_layerForScrollCorner->setName("scroll corner");
1532 #endif
1533 m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
1534 layersChanged = true;
1535 } else if (m_layerForScrollCorner) {
1536 m_layerForScrollCorner->removeFromParent();
1537 m_layerForScrollCorner = nullptr;
1538 layersChanged = true;
1539 }
1540
1541 if (layersChanged)
1542 m_renderView->frameView()->positionScrollbarLayers();
1543 }
1544
ensureRootPlatformLayer()1545 void RenderLayerCompositor::ensureRootPlatformLayer()
1546 {
1547 RootLayerAttachment expectedAttachment = shouldPropagateCompositingToEnclosingFrame() ? RootLayerAttachedViaEnclosingFrame : RootLayerAttachedViaChromeClient;
1548 if (expectedAttachment == m_rootLayerAttachment)
1549 return;
1550
1551 if (!m_rootPlatformLayer) {
1552 m_rootPlatformLayer = GraphicsLayer::create(0);
1553 #ifndef NDEBUG
1554 m_rootPlatformLayer->setName("Root platform");
1555 #endif
1556 m_rootPlatformLayer->setSize(FloatSize(m_renderView->maxXLayoutOverflow(), m_renderView->maxYLayoutOverflow()));
1557 m_rootPlatformLayer->setPosition(FloatPoint());
1558
1559 // Need to clip to prevent transformed content showing outside this frame
1560 m_rootPlatformLayer->setMasksToBounds(true);
1561 }
1562
1563 if (requiresScrollLayer(expectedAttachment)) {
1564 if (!m_overflowControlsHostLayer) {
1565 ASSERT(!m_scrollLayer);
1566 ASSERT(!m_clipLayer);
1567
1568 // Create a layer to host the clipping layer and the overflow controls layers.
1569 m_overflowControlsHostLayer = GraphicsLayer::create(0);
1570 #ifndef NDEBUG
1571 m_overflowControlsHostLayer->setName("overflow controls host");
1572 #endif
1573
1574 // Create a clipping layer if this is an iframe
1575 m_clipLayer = GraphicsLayer::create(this);
1576 #ifndef NDEBUG
1577 m_clipLayer->setName("iframe Clipping");
1578 #endif
1579 m_clipLayer->setMasksToBounds(true);
1580
1581 m_scrollLayer = GraphicsLayer::create(this);
1582 #ifndef NDEBUG
1583 m_scrollLayer->setName("iframe scrolling");
1584 #endif
1585
1586 // Hook them up
1587 m_overflowControlsHostLayer->addChild(m_clipLayer.get());
1588 m_clipLayer->addChild(m_scrollLayer.get());
1589 m_scrollLayer->addChild(m_rootPlatformLayer.get());
1590
1591 frameViewDidChangeSize();
1592 frameViewDidScroll(m_renderView->frameView()->scrollPosition());
1593 }
1594 } else {
1595 if (m_overflowControlsHostLayer) {
1596 m_overflowControlsHostLayer = nullptr;
1597 m_clipLayer = nullptr;
1598 m_scrollLayer = nullptr;
1599 }
1600 }
1601
1602 // Check to see if we have to change the attachment
1603 if (m_rootLayerAttachment != RootLayerUnattached)
1604 detachRootPlatformLayer();
1605
1606 attachRootPlatformLayer(expectedAttachment);
1607 }
1608
destroyRootPlatformLayer()1609 void RenderLayerCompositor::destroyRootPlatformLayer()
1610 {
1611 if (!m_rootPlatformLayer)
1612 return;
1613
1614 detachRootPlatformLayer();
1615
1616 if (m_layerForHorizontalScrollbar) {
1617 m_layerForHorizontalScrollbar->removeFromParent();
1618 m_layerForHorizontalScrollbar = nullptr;
1619 if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar())
1620 m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
1621 }
1622
1623 if (m_layerForVerticalScrollbar) {
1624 m_layerForVerticalScrollbar->removeFromParent();
1625 m_layerForVerticalScrollbar = nullptr;
1626 if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar())
1627 m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
1628 }
1629
1630 if (m_layerForScrollCorner) {
1631 m_layerForScrollCorner = nullptr;
1632 m_renderView->frameView()->invalidateScrollCorner();
1633 }
1634
1635 if (m_overflowControlsHostLayer) {
1636 m_overflowControlsHostLayer = nullptr;
1637 m_clipLayer = nullptr;
1638 m_scrollLayer = nullptr;
1639 }
1640 ASSERT(!m_scrollLayer);
1641 m_rootPlatformLayer = nullptr;
1642 }
1643
attachRootPlatformLayer(RootLayerAttachment attachment)1644 void RenderLayerCompositor::attachRootPlatformLayer(RootLayerAttachment attachment)
1645 {
1646 if (!m_rootPlatformLayer)
1647 return;
1648
1649 switch (attachment) {
1650 case RootLayerUnattached:
1651 ASSERT_NOT_REACHED();
1652 break;
1653 case RootLayerAttachedViaChromeClient: {
1654 Frame* frame = m_renderView->frameView()->frame();
1655 Page* page = frame ? frame->page() : 0;
1656 if (!page)
1657 return;
1658
1659 page->chrome()->client()->attachRootGraphicsLayer(frame, rootPlatformLayer());
1660 break;
1661 }
1662 case RootLayerAttachedViaEnclosingFrame: {
1663 // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
1664 // for the frame's renderer in the parent document.
1665 scheduleNeedsStyleRecalc(m_renderView->document()->ownerElement());
1666 break;
1667 }
1668 }
1669
1670 m_rootLayerAttachment = attachment;
1671 rootLayerAttachmentChanged();
1672 }
1673
detachRootPlatformLayer()1674 void RenderLayerCompositor::detachRootPlatformLayer()
1675 {
1676 if (!m_rootPlatformLayer || m_rootLayerAttachment == RootLayerUnattached)
1677 return;
1678
1679 switch (m_rootLayerAttachment) {
1680 case RootLayerAttachedViaEnclosingFrame: {
1681 // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
1682 // for the frame's renderer in the parent document.
1683 if (m_overflowControlsHostLayer)
1684 m_overflowControlsHostLayer->removeFromParent();
1685 else
1686 m_rootPlatformLayer->removeFromParent();
1687
1688 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
1689 scheduleNeedsStyleRecalc(ownerElement);
1690 break;
1691 }
1692 case RootLayerAttachedViaChromeClient: {
1693 Frame* frame = m_renderView->frameView()->frame();
1694 Page* page = frame ? frame->page() : 0;
1695 if (!page)
1696 return;
1697
1698 page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
1699 }
1700 break;
1701 case RootLayerUnattached:
1702 break;
1703 }
1704
1705 m_rootLayerAttachment = RootLayerUnattached;
1706 rootLayerAttachmentChanged();
1707 }
1708
updateRootLayerAttachment()1709 void RenderLayerCompositor::updateRootLayerAttachment()
1710 {
1711 ensureRootPlatformLayer();
1712 }
1713
rootLayerAttachmentChanged()1714 void RenderLayerCompositor::rootLayerAttachmentChanged()
1715 {
1716 // The attachment can affect whether the RenderView layer's paintingGoesToWindow() behavior,
1717 // so call updateGraphicsLayerGeometry() to udpate that.
1718 RenderLayer* layer = m_renderView->layer();
1719 if (RenderLayerBacking* backing = layer ? layer->backing() : 0)
1720 backing->updateDrawsContent();
1721 }
1722
needsStyleRecalcCallback(Node * node)1723 static void needsStyleRecalcCallback(Node* node)
1724 {
1725 node->setNeedsStyleRecalc(SyntheticStyleChange);
1726 }
1727
scheduleNeedsStyleRecalc(Element * element)1728 void RenderLayerCompositor::scheduleNeedsStyleRecalc(Element* element)
1729 {
1730 if (ContainerNode::postAttachCallbacksAreSuspended())
1731 ContainerNode::queuePostAttachCallback(needsStyleRecalcCallback, element);
1732 else
1733 element->setNeedsStyleRecalc(SyntheticStyleChange);
1734 }
1735
1736 // IFrames are special, because we hook compositing layers together across iframe boundaries
1737 // when both parent and iframe content are composited. So when this frame becomes composited, we have
1738 // to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
notifyIFramesOfCompositingChange()1739 void RenderLayerCompositor::notifyIFramesOfCompositingChange()
1740 {
1741 Frame* frame = m_renderView->frameView() ? m_renderView->frameView()->frame() : 0;
1742 if (!frame)
1743 return;
1744
1745 for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->traverseNext(frame)) {
1746 if (child->document() && child->document()->ownerElement())
1747 scheduleNeedsStyleRecalc(child->document()->ownerElement());
1748 }
1749
1750 // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so
1751 // we need to schedule a style recalc in our parent document.
1752 if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
1753 scheduleNeedsStyleRecalc(ownerElement);
1754 }
1755
layerHas3DContent(const RenderLayer * layer) const1756 bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
1757 {
1758 const RenderStyle* style = layer->renderer()->style();
1759
1760 if (style &&
1761 (style->transformStyle3D() == TransformStyle3DPreserve3D ||
1762 style->hasPerspective() ||
1763 style->transform().has3DOperation()))
1764 return true;
1765
1766 if (layer->isStackingContext()) {
1767 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
1768 size_t listSize = negZOrderList->size();
1769 for (size_t i = 0; i < listSize; ++i) {
1770 RenderLayer* curLayer = negZOrderList->at(i);
1771 if (layerHas3DContent(curLayer))
1772 return true;
1773 }
1774 }
1775
1776 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
1777 size_t listSize = posZOrderList->size();
1778 for (size_t i = 0; i < listSize; ++i) {
1779 RenderLayer* curLayer = posZOrderList->at(i);
1780 if (layerHas3DContent(curLayer))
1781 return true;
1782 }
1783 }
1784 }
1785
1786 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
1787 size_t listSize = normalFlowList->size();
1788 for (size_t i = 0; i < listSize; ++i) {
1789 RenderLayer* curLayer = normalFlowList->at(i);
1790 if (layerHas3DContent(curLayer))
1791 return true;
1792 }
1793 }
1794 return false;
1795 }
1796
updateContentsScale(float scale,RenderLayer * layer)1797 void RenderLayerCompositor::updateContentsScale(float scale, RenderLayer* layer)
1798 {
1799 if (!layer)
1800 layer = rootRenderLayer();
1801
1802 layer->updateContentsScale(scale);
1803
1804 if (layer->isStackingContext()) {
1805 if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
1806 size_t listSize = negZOrderList->size();
1807 for (size_t i = 0; i < listSize; ++i)
1808 updateContentsScale(scale, negZOrderList->at(i));
1809 }
1810
1811 if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
1812 size_t listSize = posZOrderList->size();
1813 for (size_t i = 0; i < listSize; ++i)
1814 updateContentsScale(scale, posZOrderList->at(i));
1815 }
1816 }
1817
1818 if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
1819 size_t listSize = normalFlowList->size();
1820 for (size_t i = 0; i < listSize; ++i)
1821 updateContentsScale(scale, normalFlowList->at(i));
1822 }
1823 }
1824
1825 } // namespace WebCore
1826
1827 #endif // USE(ACCELERATED_COMPOSITING)
1828
1829