[wk2] All intrinsic content size changes should go through the 0-delay timer
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / mac / TiledCoreAnimationDrawingArea.mm
1 /*
2  * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "TiledCoreAnimationDrawingArea.h"
28
29 #if ENABLE(THREADED_SCROLLING)
30
31 #import "ColorSpaceData.h"
32 #import "DrawingAreaProxyMessages.h"
33 #import "EventDispatcher.h"
34 #import "LayerHostingContext.h"
35 #import "LayerTreeContext.h"
36 #import "WebFrame.h"
37 #import "WebPage.h"
38 #import "WebPageCreationParameters.h"
39 #import "WebPageProxyMessages.h"
40 #import "WebProcess.h"
41 #import <QuartzCore/QuartzCore.h>
42 #import <WebCore/Frame.h>
43 #import <WebCore/FrameView.h>
44 #import <WebCore/GraphicsContext.h>
45 #import <WebCore/GraphicsLayerCA.h>
46 #import <WebCore/Page.h>
47 #import <WebCore/RenderView.h>
48 #import <WebCore/ScrollingCoordinator.h>
49 #import <WebCore/ScrollingThread.h>
50 #import <WebCore/ScrollingTree.h>
51 #import <WebCore/Settings.h>
52 #import <WebCore/TiledBacking.h>
53 #import <wtf/MainThread.h>
54
55 @interface CATransaction (Details)
56 + (void)synchronize;
57 @end
58
59 using namespace WebCore;
60
61 namespace WebKit {
62
63 PassOwnPtr<TiledCoreAnimationDrawingArea> TiledCoreAnimationDrawingArea::create(WebPage* webPage, const WebPageCreationParameters& parameters)
64 {
65     return adoptPtr(new TiledCoreAnimationDrawingArea(webPage, parameters));
66 }
67
68 TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(WebPage* webPage, const WebPageCreationParameters& parameters)
69     : DrawingArea(DrawingAreaTypeTiledCoreAnimation, webPage)
70     , m_layerTreeStateIsFrozen(false)
71     , m_layerFlushScheduler(this)
72     , m_isPaintingSuspended(!parameters.isVisible)
73     , m_updateIntrinsicContentSizeTimer(this, &TiledCoreAnimationDrawingArea::updateIntrinsicContentSizeTimerFired)
74 {
75     Page* page = m_webPage->corePage();
76
77     page->settings()->setScrollingCoordinatorEnabled(true);
78     page->settings()->setForceCompositingMode(true);
79
80     WebProcess::shared().eventDispatcher().addScrollingTreeForPage(webPage);
81
82     m_rootLayer = [CALayer layer];
83
84     CGRect rootLayerFrame = m_webPage->bounds();
85     m_rootLayer.get().frame = rootLayerFrame;
86     m_rootLayer.get().opaque = YES;
87     m_rootLayer.get().geometryFlipped = YES;
88
89     updateLayerHostingContext();
90     setColorSpace(parameters.colorSpace);
91
92     LayerTreeContext layerTreeContext;
93     layerTreeContext.contextID = m_layerHostingContext->contextID();
94     m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(0, layerTreeContext));
95 }
96
97 TiledCoreAnimationDrawingArea::~TiledCoreAnimationDrawingArea()
98 {
99     WebProcess::shared().eventDispatcher().removeScrollingTreeForPage(m_webPage);
100
101     m_layerFlushScheduler.invalidate();
102 }
103
104 void TiledCoreAnimationDrawingArea::setNeedsDisplay()
105 {
106 }
107
108 void TiledCoreAnimationDrawingArea::setNeedsDisplayInRect(const IntRect& rect)
109 {
110 }
111
112 void TiledCoreAnimationDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollDelta)
113 {
114 }
115
116 void TiledCoreAnimationDrawingArea::invalidateAllPageOverlays()
117 {
118     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
119         it->value->setNeedsDisplay();
120 }
121
122 void TiledCoreAnimationDrawingArea::didChangeScrollOffsetForAnyFrame()
123 {
124     invalidateAllPageOverlays();
125 }
126
127 void TiledCoreAnimationDrawingArea::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
128 {
129     CALayer *rootCompositingLayer = graphicsLayer ? graphicsLayer->platformLayer() : nil;
130
131     if (m_layerTreeStateIsFrozen) {
132         m_pendingRootCompositingLayer = rootCompositingLayer;
133         return;
134     }
135
136     setRootCompositingLayer(rootCompositingLayer);
137 }
138
139 void TiledCoreAnimationDrawingArea::forceRepaint()
140 {
141     if (m_layerTreeStateIsFrozen)
142         return;
143
144     for (Frame* frame = m_webPage->corePage()->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
145         FrameView* frameView = frame->view();
146         if (!frameView || !frameView->tiledBacking())
147             continue;
148
149         frameView->tiledBacking()->forceRepaint();
150     }
151
152     flushLayers();
153     [CATransaction flush];
154     [CATransaction synchronize];
155 }
156
157 bool TiledCoreAnimationDrawingArea::forceRepaintAsync(uint64_t callbackID)
158 {
159     if (m_layerTreeStateIsFrozen)
160         return false;
161
162     dispatchAfterEnsuringUpdatedScrollPosition(bind(^{
163         m_webPage->drawingArea()->forceRepaint();
164         m_webPage->send(Messages::WebPageProxy::VoidCallback(callbackID));
165     }));
166     return true;
167 }
168
169 void TiledCoreAnimationDrawingArea::setLayerTreeStateIsFrozen(bool layerTreeStateIsFrozen)
170 {
171     if (m_layerTreeStateIsFrozen == layerTreeStateIsFrozen)
172         return;
173
174     m_layerTreeStateIsFrozen = layerTreeStateIsFrozen;
175     if (m_layerTreeStateIsFrozen)
176         m_layerFlushScheduler.suspend();
177     else
178         m_layerFlushScheduler.resume();
179 }
180
181 bool TiledCoreAnimationDrawingArea::layerTreeStateIsFrozen() const
182 {
183     return m_layerTreeStateIsFrozen;
184 }
185
186 void TiledCoreAnimationDrawingArea::scheduleCompositingLayerFlush()
187 {
188     m_layerFlushScheduler.schedule();
189 }
190
191 void TiledCoreAnimationDrawingArea::didInstallPageOverlay(PageOverlay* pageOverlay)
192 {
193     m_webPage->corePage()->scrollingCoordinator()->setForceMainThreadScrollLayerPositionUpdates(true);
194
195     createPageOverlayLayer(pageOverlay);
196 }
197
198 void TiledCoreAnimationDrawingArea::didUninstallPageOverlay(PageOverlay* pageOverlay)
199 {
200     destroyPageOverlayLayer(pageOverlay);
201     scheduleCompositingLayerFlush();
202
203     if (m_pageOverlayLayers.size())
204         return;
205
206     if (Page* page = m_webPage->corePage())
207         page->scrollingCoordinator()->setForceMainThreadScrollLayerPositionUpdates(false);
208 }
209
210 void TiledCoreAnimationDrawingArea::setPageOverlayNeedsDisplay(PageOverlay* pageOverlay, const IntRect& rect)
211 {
212     GraphicsLayer* layer = m_pageOverlayLayers.get(pageOverlay);
213
214     if (!layer)
215         return;
216
217     if (!layer->drawsContent()) {
218         layer->setDrawsContent(true);
219         layer->setSize(expandedIntSize(FloatSize(m_rootLayer.get().frame.size)));
220     }
221
222     layer->setNeedsDisplayInRect(rect);
223     scheduleCompositingLayerFlush();
224 }
225
226 void TiledCoreAnimationDrawingArea::updatePreferences(const WebPreferencesStore&)
227 {
228     Settings* settings = m_webPage->corePage()->settings();
229     bool scrollingPerformanceLoggingEnabled = m_webPage->scrollingPerformanceLoggingEnabled();
230     ScrollingThread::dispatch(bind(&ScrollingTree::setScrollingPerformanceLoggingEnabled, m_webPage->corePage()->scrollingCoordinator()->scrollingTree(), scrollingPerformanceLoggingEnabled));
231
232     if (TiledBacking* tiledBacking = mainFrameTiledBacking())
233         tiledBacking->setAggressivelyRetainsTiles(settings->aggressiveTileRetentionEnabled());
234
235     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it) {
236         it->value->setAcceleratesDrawing(settings->acceleratedDrawingEnabled());
237         it->value->setShowDebugBorder(settings->showDebugBorders());
238         it->value->setShowRepaintCounter(settings->showRepaintCounter());
239     }
240
241     // Soon we want pages with fixed positioned elements to be able to be scrolled by the ScrollingCoordinator.
242     // As a part of that work, we have to composite fixed position elements, and we have to allow those
243     // elements to create a stacking context.
244     settings->setAcceleratedCompositingForFixedPositionEnabled(true);
245     settings->setFixedPositionCreatesStackingContext(true);
246
247     bool showTiledScrollingIndicator = settings->showTiledScrollingIndicator();
248     if (showTiledScrollingIndicator == !!m_debugInfoLayer)
249         return;
250
251     updateDebugInfoLayer(showTiledScrollingIndicator);
252 }
253
254 void TiledCoreAnimationDrawingArea::mainFrameContentSizeChanged(const IntSize&)
255 {
256     if (!m_webPage->minimumLayoutWidth())
257         return;
258
259     if (m_inUpdateGeometry)
260         return;
261
262     if (!m_updateIntrinsicContentSizeTimer.isActive())
263         m_updateIntrinsicContentSizeTimer.startOneShot(0);
264 }
265
266 void TiledCoreAnimationDrawingArea::updateIntrinsicContentSizeTimerFired(Timer<TiledCoreAnimationDrawingArea>*)
267 {
268     Frame* frame = m_webPage->corePage()->mainFrame();
269     if (!frame)
270         return;
271
272     FrameView* frameView = frame->view();
273     if (!frameView)
274         return;
275
276     IntSize contentSize = frameView->contentsSize();
277
278     if (m_lastSentIntrinsicContentSize == contentSize)
279         return;
280
281     m_lastSentIntrinsicContentSize = contentSize;
282     m_webPage->send(Messages::DrawingAreaProxy::IntrinsicContentSizeDidChange(contentSize));
283 }
284
285 void TiledCoreAnimationDrawingArea::dispatchAfterEnsuringUpdatedScrollPosition(const Function<void ()>& functionRef)
286 {
287     m_webPage->ref();
288     m_webPage->corePage()->scrollingCoordinator()->commitTreeStateIfNeeded();
289
290     if (!m_layerTreeStateIsFrozen)
291         m_layerFlushScheduler.suspend();
292
293     Function<void ()> function = functionRef;
294
295     // It is possible for the drawing area to be destroyed before the bound block
296     // is invoked, so grab a reference to the web page here so we can access the drawing area through it.
297     // (The web page is already kept alive by dispatchAfterEnsuringUpdatedScrollPosition).
298     WebPage* webPage = m_webPage;
299
300     ScrollingThread::dispatchBarrier(bind(^{
301         DrawingArea* drawingArea = webPage->drawingArea();
302         if (!drawingArea)
303             return;
304
305         function();
306
307         if (!m_layerTreeStateIsFrozen)
308             m_layerFlushScheduler.resume();
309
310         webPage->deref();
311     }));
312 }
313
314 void TiledCoreAnimationDrawingArea::notifyAnimationStarted(const GraphicsLayer*, double)
315 {
316 }
317
318 void TiledCoreAnimationDrawingArea::notifyFlushRequired(const GraphicsLayer*)
319 {
320 }
321
322 void TiledCoreAnimationDrawingArea::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const IntRect& clipRect)
323 {
324     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it) {
325         if (it->value == graphicsLayer) {
326             m_webPage->drawPageOverlay(it->key, graphicsContext, clipRect);
327             break;
328         }
329     }
330 }
331
332 float TiledCoreAnimationDrawingArea::deviceScaleFactor() const
333 {
334     return m_webPage->corePage()->deviceScaleFactor();
335 }
336
337 bool TiledCoreAnimationDrawingArea::flushLayers()
338 {
339     ASSERT(!m_layerTreeStateIsFrozen);
340
341     // This gets called outside of the normal event loop so wrap in an autorelease pool
342     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
343
344     m_webPage->layoutIfNeeded();
345
346     if (m_pendingRootCompositingLayer) {
347         setRootCompositingLayer(m_pendingRootCompositingLayer.get());
348         m_pendingRootCompositingLayer = nullptr;
349     }
350
351     IntRect visibleRect = enclosingIntRect(m_rootLayer.get().frame);
352     if (!m_webPage->mainFrameIsScrollable())
353         visibleRect.intersect(enclosingIntRect(m_exposedRect));
354     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it) {
355         GraphicsLayer* layer = it->value.get();
356         layer->flushCompositingState(visibleRect);
357     }
358
359     bool returnValue = m_webPage->corePage()->mainFrame()->view()->flushCompositingStateIncludingSubframes();
360
361     [pool drain];
362     return returnValue;
363 }
364
365 void TiledCoreAnimationDrawingArea::suspendPainting()
366 {
367     ASSERT(!m_isPaintingSuspended);
368     m_isPaintingSuspended = true;
369
370     [m_rootLayer.get() setValue:(id)kCFBooleanTrue forKey:@"NSCAViewRenderPaused"];
371     [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidPauseNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:m_rootLayer.get() forKey:@"layer"]];
372
373     m_webPage->corePage()->suspendScriptedAnimations();
374 }
375
376 void TiledCoreAnimationDrawingArea::resumePainting()
377 {
378     if (!m_isPaintingSuspended) {
379         // FIXME: We can get a call to resumePainting when painting is not suspended.
380         // This happens when sending a synchronous message to create a new page. See <rdar://problem/8976531>.
381         return;
382     }
383     m_isPaintingSuspended = false;
384
385     [m_rootLayer.get() setValue:(id)kCFBooleanFalse forKey:@"NSCAViewRenderPaused"];
386     [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidResumeNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:m_rootLayer.get() forKey:@"layer"]];
387
388     if (m_webPage->windowIsVisible()) {
389         m_webPage->corePage()->resumeScriptedAnimations();
390
391         Frame* frame = m_webPage->corePage()->mainFrame();
392         if (!frame)
393             return;
394
395         FrameView* frameView = frame->view();
396         if (!frameView)
397             return;
398
399         frameView->resumeAnimatingImages();
400     }
401 }
402
403 void TiledCoreAnimationDrawingArea::setExposedRect(const FloatRect& exposedRect)
404 {
405     // FIXME: This should be mapped through the scroll offset, but we need to keep it up to date.
406     m_exposedRect = exposedRect;
407
408     mainFrameTiledBacking()->setExposedRect(exposedRect);
409
410     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
411         if (TiledBacking* tiledBacking = it->value->tiledBacking())
412             tiledBacking->setExposedRect(exposedRect);
413 }
414
415 void TiledCoreAnimationDrawingArea::mainFrameScrollabilityChanged(bool)
416 {
417     updateMainFrameClipsToExposedRect();
418 }
419
420 void TiledCoreAnimationDrawingArea::updateGeometry(const IntSize& viewSize, const IntSize& layerPosition)
421 {
422     m_inUpdateGeometry = true;
423
424     IntSize size = viewSize;
425     IntSize contentSize = IntSize(-1, -1);
426
427     if (!m_webPage->minimumLayoutWidth())
428         m_webPage->setSize(size);
429
430     m_webPage->layoutIfNeeded();
431
432     if (m_webPage->minimumLayoutWidth()) {
433         contentSize = m_webPage->mainWebFrame()->contentBounds().size();
434         size = contentSize;
435     }
436
437     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it) {
438         GraphicsLayer* layer = it->value.get();
439         if (layer->drawsContent())
440             layer->setSize(viewSize);
441     }
442
443     if (!m_layerTreeStateIsFrozen)
444         flushLayers();
445
446     invalidateAllPageOverlays();
447
448     [CATransaction begin];
449     [CATransaction setDisableActions:YES];
450
451     m_rootLayer.get().frame = CGRectMake(layerPosition.width(), layerPosition.height(), viewSize.width(), viewSize.height());
452
453     [CATransaction commit];
454     
455     [CATransaction flush];
456     [CATransaction synchronize];
457
458     m_webPage->send(Messages::DrawingAreaProxy::DidUpdateGeometry());
459
460     if (m_webPage->minimumLayoutWidth() && !m_updateIntrinsicContentSizeTimer.isActive())
461         m_updateIntrinsicContentSizeTimer.startOneShot(0);
462
463     m_inUpdateGeometry = false;
464 }
465
466 void TiledCoreAnimationDrawingArea::setDeviceScaleFactor(float deviceScaleFactor)
467 {
468     m_webPage->setDeviceScaleFactor(deviceScaleFactor);
469
470     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
471         it->value->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
472 }
473
474 void TiledCoreAnimationDrawingArea::setLayerHostingMode(uint32_t opaqueLayerHostingMode)
475 {
476     LayerHostingMode layerHostingMode = static_cast<LayerHostingMode>(opaqueLayerHostingMode);
477     if (layerHostingMode == m_webPage->layerHostingMode())
478         return;
479
480     m_webPage->setLayerHostingMode(layerHostingMode);
481
482     updateLayerHostingContext();
483
484     // Finally, inform the UIProcess that the context has changed.
485     LayerTreeContext layerTreeContext;
486     layerTreeContext.contextID = m_layerHostingContext->contextID();
487     m_webPage->send(Messages::DrawingAreaProxy::UpdateAcceleratedCompositingMode(0, layerTreeContext));
488 }
489
490 void TiledCoreAnimationDrawingArea::setColorSpace(const ColorSpaceData& colorSpace)
491 {
492     m_layerHostingContext->setColorSpace(colorSpace.cgColorSpace.get());
493 }
494
495 void TiledCoreAnimationDrawingArea::updateLayerHostingContext()
496 {
497     RetainPtr<CGColorSpaceRef> colorSpace;
498
499     // Invalidate the old context.
500     if (m_layerHostingContext) {
501         colorSpace = m_layerHostingContext->colorSpace();
502         m_layerHostingContext->invalidate();
503         m_layerHostingContext = nullptr;
504     }
505
506     // Create a new context and set it up.
507     switch (m_webPage->layerHostingMode()) {
508     case LayerHostingModeDefault:
509         m_layerHostingContext = LayerHostingContext::createForPort(WebProcess::shared().compositingRenderServerPort());
510         break;
511 #if HAVE(LAYER_HOSTING_IN_WINDOW_SERVER)
512     case LayerHostingModeInWindowServer:
513         m_layerHostingContext = LayerHostingContext::createForWindowServer();
514         break;
515 #endif
516     }
517
518     if (m_hasRootCompositingLayer)
519         m_layerHostingContext->setRootLayer(m_rootLayer.get());
520
521     if (colorSpace)
522         m_layerHostingContext->setColorSpace(colorSpace.get());
523 }
524
525 void TiledCoreAnimationDrawingArea::updateMainFrameClipsToExposedRect()
526 {
527     bool isScrollable = m_webPage->mainFrameIsScrollable();
528
529     if (TiledBacking* tiledBacking = mainFrameTiledBacking())
530         tiledBacking->setClipsToExposedRect(!isScrollable);
531
532     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
533         if (TiledBacking* tiledBacking = it->value->tiledBacking())
534             tiledBacking->setClipsToExposedRect(!isScrollable);
535
536     Frame* frame = m_webPage->corePage()->mainFrame();
537     if (!frame)
538         return;
539
540     FrameView* frameView = frame->view();
541     if (!frameView)
542         return;
543
544     frameView->adjustTiledBackingCoverage();
545 }
546
547 void TiledCoreAnimationDrawingArea::setRootCompositingLayer(CALayer *layer)
548 {
549     ASSERT(!m_layerTreeStateIsFrozen);
550
551     bool hadRootCompositingLayer = m_hasRootCompositingLayer;
552     m_hasRootCompositingLayer = !!layer;
553
554     [CATransaction begin];
555     [CATransaction setDisableActions:YES];
556
557     m_rootLayer.get().sublayers = m_hasRootCompositingLayer ? [NSArray arrayWithObject:layer] : [NSArray array];
558
559     if (hadRootCompositingLayer != m_hasRootCompositingLayer)
560         m_layerHostingContext->setRootLayer(m_hasRootCompositingLayer ? m_rootLayer.get() : 0);
561
562     for (PageOverlayLayerMap::iterator it = m_pageOverlayLayers.begin(), end = m_pageOverlayLayers.end(); it != end; ++it)
563         [m_rootLayer.get() addSublayer:it->value->platformLayer()];
564
565     if (TiledBacking* tiledBacking = mainFrameTiledBacking()) {
566         tiledBacking->setAggressivelyRetainsTiles(m_webPage->corePage()->settings()->aggressiveTileRetentionEnabled());
567         tiledBacking->setExposedRect(m_exposedRect);
568     }
569
570     updateMainFrameClipsToExposedRect();
571
572     updateDebugInfoLayer(m_webPage->corePage()->settings()->showTiledScrollingIndicator());
573
574     [CATransaction commit];
575 }
576
577 void TiledCoreAnimationDrawingArea::createPageOverlayLayer(PageOverlay* pageOverlay)
578 {
579     OwnPtr<GraphicsLayer> layer = GraphicsLayer::create(graphicsLayerFactory(), this);
580 #ifndef NDEBUG
581     layer->setName("page overlay content");
582 #endif
583
584     layer->setAcceleratesDrawing(m_webPage->corePage()->settings()->acceleratedDrawingEnabled());
585     layer->setShowDebugBorder(m_webPage->corePage()->settings()->showDebugBorders());
586     layer->setShowRepaintCounter(m_webPage->corePage()->settings()->showRepaintCounter());
587
588     m_pageOverlayPlatformLayers.set(layer.get(), layer->platformLayer());
589
590     if (TiledBacking* tiledBacking = layer->tiledBacking()) {
591         tiledBacking->setExposedRect(m_exposedRect);
592         tiledBacking->setClipsToExposedRect(!m_webPage->mainFrameIsScrollable());
593     }
594
595     [CATransaction begin];
596     [CATransaction setDisableActions:YES];
597
598     [m_rootLayer.get() addSublayer:layer->platformLayer()];
599
600     [CATransaction commit];
601
602     m_pageOverlayLayers.add(pageOverlay, layer.release());
603 }
604
605 void TiledCoreAnimationDrawingArea::destroyPageOverlayLayer(PageOverlay* pageOverlay)
606 {
607     OwnPtr<GraphicsLayer> layer = m_pageOverlayLayers.take(pageOverlay);
608     ASSERT(layer);
609
610     [CATransaction begin];
611     [CATransaction setDisableActions:YES];
612
613     [layer->platformLayer() removeFromSuperlayer];
614
615     [CATransaction commit];
616
617     m_pageOverlayPlatformLayers.remove(layer.get());
618 }
619
620 void TiledCoreAnimationDrawingArea::didCommitChangesForLayer(const GraphicsLayer* layer) const
621 {
622     RetainPtr<CALayer> oldPlatformLayer = m_pageOverlayPlatformLayers.get(layer);
623
624     if (!oldPlatformLayer)
625         return;
626
627     if (oldPlatformLayer.get() == layer->platformLayer())
628         return;
629
630     [CATransaction begin];
631     [CATransaction setDisableActions:YES];
632
633     [m_rootLayer.get() insertSublayer:layer->platformLayer() above:oldPlatformLayer.get()];
634     [oldPlatformLayer.get() removeFromSuperlayer];
635
636     [CATransaction commit];
637
638     if (TiledBacking* tiledBacking = layer->tiledBacking()) {
639         tiledBacking->setExposedRect(m_exposedRect);
640         tiledBacking->setClipsToExposedRect(!m_webPage->mainFrameIsScrollable());
641     }
642
643     m_pageOverlayPlatformLayers.set(layer, layer->platformLayer());
644 }
645
646 TiledBacking* TiledCoreAnimationDrawingArea::mainFrameTiledBacking() const
647 {
648     Frame* frame = m_webPage->corePage()->mainFrame();
649     if (!frame)
650         return 0;
651     
652     FrameView* frameView = frame->view();
653     return frameView ? frameView->tiledBacking() : 0;
654 }
655
656 void TiledCoreAnimationDrawingArea::updateDebugInfoLayer(bool showLayer)
657 {
658     if (showLayer) {
659         if (TiledBacking* tiledBacking = mainFrameTiledBacking())
660             m_debugInfoLayer = tiledBacking->tiledScrollingIndicatorLayer();
661         
662         if (m_debugInfoLayer) {
663 #ifndef NDEBUG
664             [m_debugInfoLayer.get() setName:@"Debug Info"];
665 #endif
666             [m_rootLayer.get() addSublayer:m_debugInfoLayer.get()];
667         }
668     } else if (m_debugInfoLayer) {
669         [m_debugInfoLayer.get() removeFromSuperlayer];
670         m_debugInfoLayer = nullptr;
671     }
672 }
673
674 } // namespace WebKit
675
676 #endif // ENABLE(THREADED_SCROLLING)