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