Skipping tests added with r191968 on win.
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / CoordinatedGraphics / CoordinatedDrawingArea.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28
29 #if USE(COORDINATED_GRAPHICS)
30 #include "CoordinatedDrawingArea.h"
31
32 #include "CoordinatedLayerTreeHost.h"
33 #include "DrawingAreaProxyMessages.h"
34 #include "LayerTreeContext.h"
35 #include "PageOverlayController.h"
36 #include "ShareableBitmap.h"
37 #include "UpdateInfo.h"
38 #include "WebPage.h"
39 #include "WebPageCreationParameters.h"
40 #include "WebPreferencesKeys.h"
41 #include "WebProcess.h"
42 #include <WebCore/GraphicsContext.h>
43 #include <WebCore/MainFrame.h>
44 #include <WebCore/Page.h>
45 #include <WebCore/PageOverlayController.h>
46 #include <WebCore/Settings.h>
47
48 using namespace WebCore;
49
50 namespace WebKit {
51
52 CoordinatedDrawingArea::~CoordinatedDrawingArea()
53 {
54     if (m_layerTreeHost)
55         m_layerTreeHost->invalidate();
56 }
57
58 CoordinatedDrawingArea::CoordinatedDrawingArea(WebPage& webPage, const WebPageCreationParameters& parameters)
59 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
60     : DrawingArea(DrawingAreaTypeCoordinated, webPage)
61 #else
62     : DrawingArea(DrawingAreaTypeImpl, webPage)
63 #endif
64     , m_backingStoreStateID(0)
65     , m_isPaintingEnabled(true)
66     , m_inUpdateBackingStoreState(false)
67     , m_shouldSendDidUpdateBackingStoreState(false)
68     , m_isWaitingForDidUpdate(false)
69     , m_compositingAccordingToProxyMessages(false)
70     , m_layerTreeStateIsFrozen(false)
71     , m_wantsToExitAcceleratedCompositingMode(false)
72     , m_isPaintingSuspended(!(parameters.viewState & ViewState::IsVisible))
73     , m_displayTimer(RunLoop::main(), this, &CoordinatedDrawingArea::displayTimerFired)
74     , m_exitCompositingTimer(RunLoop::main(), this, &CoordinatedDrawingArea::exitAcceleratedCompositingMode)
75 {
76     // Always use compositing in CoordinatedGraphics
77     enterAcceleratedCompositingMode(0);
78 }
79
80 void CoordinatedDrawingArea::setNeedsDisplay()
81 {
82     if (!m_isPaintingEnabled)
83         return;
84
85     if (m_layerTreeHost) {
86         ASSERT(m_dirtyRegion.isEmpty());
87         m_layerTreeHost->setNonCompositedContentsNeedDisplay();
88         return;
89     }
90
91     setNeedsDisplayInRect(m_webPage.bounds());
92 }
93
94 void CoordinatedDrawingArea::setNeedsDisplayInRect(const IntRect& rect)
95 {
96     if (!m_isPaintingEnabled)
97         return;
98
99     if (m_layerTreeHost) {
100         ASSERT(m_dirtyRegion.isEmpty());
101         m_layerTreeHost->setNonCompositedContentsNeedDisplayInRect(rect);
102         return;
103     }
104
105     IntRect dirtyRect = rect;
106     dirtyRect.intersect(m_webPage.bounds());
107
108     if (dirtyRect.isEmpty())
109         return;
110
111     m_dirtyRegion.unite(dirtyRect);
112     scheduleDisplay();
113 }
114
115 void CoordinatedDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollDelta)
116 {
117     if (!m_isPaintingEnabled)
118         return;
119
120     if (m_layerTreeHost) {
121         ASSERT(m_scrollRect.isEmpty());
122         ASSERT(m_scrollOffset.isEmpty());
123         ASSERT(m_dirtyRegion.isEmpty());
124
125         m_layerTreeHost->scrollNonCompositedContents(scrollRect);
126         return;
127     }
128
129     if (scrollRect.isEmpty())
130         return;
131
132     if (!m_scrollRect.isEmpty() && scrollRect != m_scrollRect) {
133         unsigned scrollArea = scrollRect.width() * scrollRect.height();
134         unsigned currentScrollArea = m_scrollRect.width() * m_scrollRect.height();
135
136         if (currentScrollArea >= scrollArea) {
137             // The rect being scrolled is at least as large as the rect we'd like to scroll.
138             // Go ahead and just invalidate the scroll rect.
139             setNeedsDisplayInRect(scrollRect);
140             return;
141         }
142
143         // Just repaint the entire current scroll rect, we'll scroll the new rect instead.
144         setNeedsDisplayInRect(m_scrollRect);
145         m_scrollRect = IntRect();
146         m_scrollOffset = IntSize();
147     }
148
149     // Get the part of the dirty region that is in the scroll rect.
150     Region dirtyRegionInScrollRect = intersect(scrollRect, m_dirtyRegion);
151     if (!dirtyRegionInScrollRect.isEmpty()) {
152         // There are parts of the dirty region that are inside the scroll rect.
153         // We need to subtract them from the region, move them and re-add them.
154         m_dirtyRegion.subtract(scrollRect);
155
156         // Move the dirty parts.
157         Region movedDirtyRegionInScrollRect = intersect(translate(dirtyRegionInScrollRect, scrollDelta), scrollRect);
158
159         // And add them back.
160         m_dirtyRegion.unite(movedDirtyRegionInScrollRect);
161     }
162
163     // Compute the scroll repaint region.
164     Region scrollRepaintRegion = subtract(scrollRect, translate(scrollRect, scrollDelta));
165
166     m_dirtyRegion.unite(scrollRepaintRegion);
167     scheduleDisplay();
168
169     m_scrollRect = scrollRect;
170     m_scrollOffset += scrollDelta;
171 }
172
173 void CoordinatedDrawingArea::pageBackgroundTransparencyChanged()
174 {
175     if (m_layerTreeHost)
176         m_layerTreeHost->pageBackgroundTransparencyChanged();
177 }
178
179 void CoordinatedDrawingArea::setLayerTreeStateIsFrozen(bool isFrozen)
180 {
181     if (m_layerTreeStateIsFrozen == isFrozen)
182         return;
183
184     m_layerTreeStateIsFrozen = isFrozen;
185
186     if (m_layerTreeHost)
187         m_layerTreeHost->setLayerFlushSchedulingEnabled(!isFrozen);
188
189     if (isFrozen)
190         m_exitCompositingTimer.stop();
191     else if (m_wantsToExitAcceleratedCompositingMode)
192         exitAcceleratedCompositingModeSoon();
193 }
194
195 void CoordinatedDrawingArea::forceRepaint()
196 {
197     setNeedsDisplay();
198
199     m_webPage.layoutIfNeeded();
200
201     if (m_layerTreeHost) {
202         // FIXME: We need to do the same work as the layerHostDidFlushLayers function here,
203         // but clearly it doesn't make sense to call the function with that name.
204         // Consider refactoring and renaming it.
205         if (m_compositingAccordingToProxyMessages)
206             m_layerTreeHost->forceRepaint();
207         else {
208             // Call setShouldNotifyAfterNextScheduledLayerFlush(false) here to
209             // prevent layerHostDidFlushLayers() from being called a second time.
210             m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false);
211             layerHostDidFlushLayers();
212         }
213         return;
214     }
215
216     m_isWaitingForDidUpdate = false;
217     display();
218 }
219
220 bool CoordinatedDrawingArea::forceRepaintAsync(uint64_t callbackID)
221 {
222     return m_layerTreeHost && m_layerTreeHost->forceRepaintAsync(callbackID);
223 }
224
225 void CoordinatedDrawingArea::setPaintingEnabled(bool paintingEnabled)
226 {
227     m_isPaintingEnabled = paintingEnabled;
228 }
229
230 void CoordinatedDrawingArea::updatePreferences(const WebPreferencesStore& store)
231 {
232     m_webPage.corePage()->settings().setForceCompositingMode(store.getBoolValueForKey(WebPreferencesKey::forceCompositingModeKey()));
233 }
234
235 void CoordinatedDrawingArea::mainFrameContentSizeChanged(const WebCore::IntSize&)
236 {
237     m_webPage.mainFrame()->pageOverlayController().didChangeDocumentSize();
238 }
239
240 void CoordinatedDrawingArea::layerHostDidFlushLayers()
241 {
242     ASSERT(m_layerTreeHost);
243
244     m_layerTreeHost->forceRepaint();
245
246     if (m_shouldSendDidUpdateBackingStoreState && !exitAcceleratedCompositingModePending()) {
247         sendDidUpdateBackingStoreState();
248         return;
249     }
250
251     if (!m_layerTreeHost)
252         return;
253
254     ASSERT(!m_compositingAccordingToProxyMessages);
255     if (!exitAcceleratedCompositingModePending()) {
256         m_webPage.send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(m_backingStoreStateID, m_layerTreeHost->layerTreeContext()));
257         m_compositingAccordingToProxyMessages = true;
258     }
259 }
260
261 GraphicsLayerFactory* CoordinatedDrawingArea::graphicsLayerFactory()
262 {
263     if (m_layerTreeHost)
264         return m_layerTreeHost->graphicsLayerFactory();
265
266     return 0;
267 }
268
269 void CoordinatedDrawingArea::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
270 {
271     // FIXME: Instead of using nested if statements, we should keep a compositing state
272     // enum in the CoordinatedDrawingArea object and have a changeAcceleratedCompositingState function
273     // that takes the new state.
274
275     if (graphicsLayer) {
276         if (!m_layerTreeHost) {
277             // We're actually entering accelerated compositing mode.
278             enterAcceleratedCompositingMode(graphicsLayer);
279         } else {
280             // We're already in accelerated compositing mode, but the root compositing layer changed.
281
282             m_exitCompositingTimer.stop();
283             m_wantsToExitAcceleratedCompositingMode = false;
284
285             // If we haven't sent the EnterAcceleratedCompositingMode message, make sure that the
286             // layer tree host calls us back after the next layer flush so we can send it then.
287             if (!m_compositingAccordingToProxyMessages)
288                 m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(true);
289
290             m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
291         }
292     } else {
293         if (m_layerTreeHost)
294             m_layerTreeHost->setRootCompositingLayer(0);
295     }
296 }
297
298 void CoordinatedDrawingArea::scheduleCompositingLayerFlush()
299 {
300     if (!m_layerTreeHost)
301         return;
302     m_layerTreeHost->scheduleLayerFlush();
303 }
304
305 void CoordinatedDrawingArea::scheduleCompositingLayerFlushImmediately()
306 {
307     scheduleCompositingLayerFlush();
308 }
309
310 void CoordinatedDrawingArea::updateBackingStoreState(uint64_t stateID, bool respondImmediately, float deviceScaleFactor, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset)
311 {
312     ASSERT(!m_inUpdateBackingStoreState);
313     m_inUpdateBackingStoreState = true;
314
315     ASSERT_ARG(stateID, stateID >= m_backingStoreStateID);
316     if (stateID != m_backingStoreStateID) {
317         m_backingStoreStateID = stateID;
318         m_shouldSendDidUpdateBackingStoreState = true;
319
320         m_webPage.setDeviceScaleFactor(deviceScaleFactor);
321         m_webPage.setSize(size);
322         m_webPage.layoutIfNeeded();
323         m_webPage.scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
324
325         if (m_layerTreeHost) {
326             // Coordinated Graphics sets the size of the root layer to contents size.
327             if (!m_webPage.useFixedLayout())
328                 m_layerTreeHost->sizeDidChange(m_webPage.size());
329         } else
330             m_dirtyRegion = m_webPage.bounds();
331     } else {
332         ASSERT(size == m_webPage.size());
333         if (!m_shouldSendDidUpdateBackingStoreState) {
334             // We've already sent a DidUpdateBackingStoreState message for this state. We have nothing more to do.
335             m_inUpdateBackingStoreState = false;
336             return;
337         }
338     }
339
340     // The UI process has updated to a new backing store state. Any Update messages we sent before
341     // this point will be ignored. We wait to set this to false until after updating the page's
342     // size so that any displays triggered by the relayout will be ignored. If we're supposed to
343     // respond to the UpdateBackingStoreState message immediately, we'll do a display anyway in
344     // sendDidUpdateBackingStoreState; otherwise we shouldn't do one right now.
345     m_isWaitingForDidUpdate = false;
346
347     if (respondImmediately) {
348         // Make sure to resume painting if we're supposed to respond immediately, otherwise we'll just
349         // send back an empty UpdateInfo struct.
350         if (m_isPaintingSuspended)
351             resumePainting();
352
353         sendDidUpdateBackingStoreState();
354     }
355
356     m_inUpdateBackingStoreState = false;
357 }
358
359 void CoordinatedDrawingArea::sendDidUpdateBackingStoreState()
360 {
361     ASSERT(!m_isWaitingForDidUpdate);
362     ASSERT(m_shouldSendDidUpdateBackingStoreState);
363
364     m_shouldSendDidUpdateBackingStoreState = false;
365
366     UpdateInfo updateInfo;
367
368     if (!m_isPaintingSuspended && !m_layerTreeHost)
369         display(updateInfo);
370
371     LayerTreeContext layerTreeContext;
372
373     if (m_isPaintingSuspended || m_layerTreeHost) {
374         updateInfo.viewSize = m_webPage.size();
375         updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
376
377         if (m_layerTreeHost) {
378             layerTreeContext = m_layerTreeHost->layerTreeContext();
379
380             // We don't want the layer tree host to notify after the next scheduled
381             // layer flush because that might end up sending an EnterAcceleratedCompositingMode
382             // message back to the UI process, but the updated layer tree context
383             // will be sent back in the DidUpdateBackingStoreState message.
384             m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false);
385             m_layerTreeHost->forceRepaint();
386         }
387     }
388
389     m_webPage.send(Messages::DrawingAreaProxy::DidUpdateBackingStoreState(m_backingStoreStateID, updateInfo, layerTreeContext));
390     m_compositingAccordingToProxyMessages = !layerTreeContext.isEmpty();
391 }
392
393 void CoordinatedDrawingArea::didUpdate()
394 {
395     // We might get didUpdate messages from the UI process even after we've
396     // entered accelerated compositing mode. Ignore them.
397     if (m_layerTreeHost)
398         return;
399
400     m_isWaitingForDidUpdate = false;
401
402     // Display if needed. We call displayTimerFired here since it will throttle updates to 60fps.
403     displayTimerFired();
404 }
405
406 void CoordinatedDrawingArea::suspendPainting()
407 {
408     ASSERT(!m_isPaintingSuspended);
409
410     if (m_layerTreeHost)
411         m_layerTreeHost->pauseRendering();
412
413     m_isPaintingSuspended = true;
414     m_displayTimer.stop();
415
416     m_webPage.corePage()->suspendScriptedAnimations();
417 }
418
419 void CoordinatedDrawingArea::resumePainting()
420 {
421     if (!m_isPaintingSuspended) {
422         // FIXME: We can get a call to resumePainting when painting is not suspended.
423         // This happens when sending a synchronous message to create a new page. See <rdar://problem/8976531>.
424         return;
425     }
426
427     if (m_layerTreeHost)
428         m_layerTreeHost->resumeRendering();
429
430     m_isPaintingSuspended = false;
431
432     // FIXME: We shouldn't always repaint everything here.
433     setNeedsDisplay();
434
435     m_webPage.corePage()->resumeScriptedAnimations();
436 }
437
438 void CoordinatedDrawingArea::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer)
439 {
440     m_exitCompositingTimer.stop();
441     m_wantsToExitAcceleratedCompositingMode = false;
442
443     ASSERT(!m_layerTreeHost);
444
445     m_layerTreeHost = LayerTreeHost::create(&m_webPage);
446     if (!m_inUpdateBackingStoreState)
447         m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(true);
448
449     m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
450
451     // Non-composited content will now be handled exclusively by the layer tree host.
452     m_dirtyRegion = Region();
453     m_scrollRect = IntRect();
454     m_scrollOffset = IntSize();
455     m_displayTimer.stop();
456     m_isWaitingForDidUpdate = false;
457 }
458
459 void CoordinatedDrawingArea::exitAcceleratedCompositingModeSoon()
460 {
461     if (m_layerTreeStateIsFrozen) {
462         m_wantsToExitAcceleratedCompositingMode = true;
463         return;
464     }
465
466     if (exitAcceleratedCompositingModePending())
467         return;
468
469     m_exitCompositingTimer.startOneShot(0);
470 }
471
472 void CoordinatedDrawingArea::scheduleDisplay()
473 {
474     ASSERT(!m_layerTreeHost);
475
476     if (m_isWaitingForDidUpdate)
477         return;
478
479     if (m_isPaintingSuspended)
480         return;
481
482     if (m_dirtyRegion.isEmpty())
483         return;
484
485     if (m_displayTimer.isActive())
486         return;
487
488     m_displayTimer.startOneShot(0);
489 }
490
491 void CoordinatedDrawingArea::displayTimerFired()
492 {
493     display();
494 }
495
496 void CoordinatedDrawingArea::display()
497 {
498     ASSERT(!m_layerTreeHost);
499     ASSERT(!m_isWaitingForDidUpdate);
500     ASSERT(!m_inUpdateBackingStoreState);
501
502     if (m_isPaintingSuspended)
503         return;
504
505     if (m_dirtyRegion.isEmpty())
506         return;
507
508     if (m_shouldSendDidUpdateBackingStoreState) {
509         sendDidUpdateBackingStoreState();
510         return;
511     }
512
513     UpdateInfo updateInfo;
514     display(updateInfo);
515
516     if (m_layerTreeHost) {
517         // The call to update caused layout which turned on accelerated compositing.
518         // Don't send an Update message in this case.
519         return;
520     }
521
522     m_webPage.send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo));
523     m_isWaitingForDidUpdate = true;
524 }
525
526 static bool shouldPaintBoundsRect(const IntRect& bounds, const Vector<IntRect>& rects)
527 {
528     const size_t rectThreshold = 10;
529     const double wastedSpaceThreshold = 0.75;
530
531     if (rects.size() <= 1 || rects.size() > rectThreshold)
532         return true;
533
534     // Attempt to guess whether or not we should use the region bounds rect or the individual rects.
535     // We do this by computing the percentage of "wasted space" in the bounds. If that wasted space
536     // is too large, then we will do individual rect painting instead.
537     unsigned boundsArea = bounds.width() * bounds.height();
538     unsigned rectsArea = 0;
539     for (auto& rect : rects)
540         rectsArea += rect.width() * rect.height();
541
542     double wastedSpace = 1 - (static_cast<double>(rectsArea) / boundsArea);
543
544     return wastedSpace <= wastedSpaceThreshold;
545 }
546
547 void CoordinatedDrawingArea::display(UpdateInfo& updateInfo)
548 {
549     ASSERT(!m_isPaintingSuspended);
550     ASSERT(!m_layerTreeHost);
551     ASSERT(!m_webPage.size().isEmpty());
552
553     m_webPage.layoutIfNeeded();
554
555     // The layout may have put the page into accelerated compositing mode. If the LayerTreeHost is
556     // in charge of displaying, we have nothing more to do.
557     if (m_layerTreeHost)
558         return;
559
560     updateInfo.viewSize = m_webPage.size();
561     updateInfo.deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
562
563     IntRect bounds = m_dirtyRegion.bounds();
564     ASSERT(m_webPage.bounds().contains(bounds));
565
566     IntSize bitmapSize = bounds.size();
567     float deviceScaleFactor = m_webPage.corePage()->deviceScaleFactor();
568     bitmapSize.scale(deviceScaleFactor);
569     RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(bitmapSize, ShareableBitmap::SupportsAlpha);
570     if (!bitmap)
571         return;
572
573     if (!bitmap->createHandle(updateInfo.bitmapHandle))
574         return;
575
576     Vector<IntRect> rects = m_dirtyRegion.rects();
577
578     if (shouldPaintBoundsRect(bounds, rects)) {
579         rects.clear();
580         rects.append(bounds);
581     }
582
583     updateInfo.scrollRect = m_scrollRect;
584     updateInfo.scrollOffset = m_scrollOffset;
585
586     m_dirtyRegion = Region();
587     m_scrollRect = IntRect();
588     m_scrollOffset = IntSize();
589
590     auto graphicsContext = bitmap->createGraphicsContext();
591     graphicsContext->applyDeviceScaleFactor(deviceScaleFactor);
592
593     updateInfo.updateRectBounds = bounds;
594
595     graphicsContext->translate(-bounds.x(), -bounds.y());
596
597     for (auto& rect : rects) {
598         m_webPage.drawRect(*graphicsContext, rect);
599         updateInfo.updateRects.append(rect);
600     }
601
602     // Layout can trigger more calls to setNeedsDisplay and we don't want to process them
603     // until the UI process has painted the update, so we stop the timer here.
604     m_displayTimer.stop();
605 }
606
607 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
608 void CoordinatedDrawingArea::didReceiveCoordinatedLayerTreeHostMessage(IPC::Connection& connection, IPC::MessageDecoder& decoder)
609 {
610     if (m_layerTreeHost)
611         m_layerTreeHost->didReceiveCoordinatedLayerTreeHostMessage(connection, decoder);
612 }
613 #endif
614
615 void CoordinatedDrawingArea::viewStateDidChange(ViewState::Flags changed, bool, const Vector<uint64_t>&)
616 {
617     if (changed & ViewState::IsVisible) {
618         if (m_webPage.isVisible())
619             resumePainting();
620         else
621             suspendPainting();
622     }
623 }
624
625 void CoordinatedDrawingArea::attachViewOverlayGraphicsLayer(WebCore::Frame* frame, WebCore::GraphicsLayer* viewOverlayRootLayer)
626 {
627     if (!frame->isMainFrame())
628         return;
629
630     if (!m_layerTreeHost)
631         return;
632
633     CoordinatedLayerTreeHost* coordinatedLayerTreeHost = static_cast<CoordinatedLayerTreeHost*>(m_layerTreeHost.get());
634     coordinatedLayerTreeHost->setViewOverlayRootLayer(viewOverlayRootLayer);
635 }
636
637 } // namespace WebKit
638 #endif // USE(COORDINATED_GRAPHICS)