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#include "config.h"
27#include "LayerTreeHostCA.h"
28
29#include "DrawingAreaImpl.h"
30#include "WebPage.h"
31#include "WebProcess.h"
32#include <WebCore/Frame.h>
33#include <WebCore/FrameView.h>
34#include <WebCore/GraphicsLayerCA.h>
35#include <WebCore/Page.h>
36#include <WebCore/PlatformCALayer.h>
37#include <WebCore/Settings.h>
38
39using namespace WebCore;
40
41namespace WebKit {
42
43LayerTreeHostCA::LayerTreeHostCA(WebPage* webPage)
44    : LayerTreeHost(webPage)
45    , m_isValid(true)
46    , m_notifyAfterScheduledLayerFlush(false)
47{
48}
49
50void LayerTreeHostCA::initialize()
51{
52    // Create a root layer.
53    m_rootLayer = GraphicsLayer::create(this);
54#ifndef NDEBUG
55    m_rootLayer->setName("LayerTreeHost root layer");
56#endif
57    m_rootLayer->setDrawsContent(false);
58    m_rootLayer->setSize(m_webPage->size());
59    static_cast<GraphicsLayerCA*>(m_rootLayer.get())->platformCALayer()->setGeometryFlipped(true);
60
61    m_nonCompositedContentLayer = GraphicsLayer::create(this);
62    static_cast<GraphicsLayerCA*>(m_nonCompositedContentLayer.get())->setAllowTiledLayer(false);
63#ifndef NDEBUG
64    m_nonCompositedContentLayer->setName("LayerTreeHost non-composited content");
65#endif
66    m_nonCompositedContentLayer->setDrawsContent(true);
67    m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground());
68    m_nonCompositedContentLayer->setSize(m_webPage->size());
69    if (m_webPage->corePage()->settings()->acceleratedDrawingEnabled())
70        m_nonCompositedContentLayer->setAcceleratesDrawing(true);
71
72    m_rootLayer->addChild(m_nonCompositedContentLayer.get());
73
74    if (m_webPage->hasPageOverlay())
75        createPageOverlayLayer();
76
77    platformInitialize(m_layerTreeContext);
78
79    scheduleLayerFlush();
80}
81
82LayerTreeHostCA::~LayerTreeHostCA()
83{
84    ASSERT(!m_isValid);
85    ASSERT(!m_rootLayer);
86}
87
88const LayerTreeContext& LayerTreeHostCA::layerTreeContext()
89{
90    return m_layerTreeContext;
91}
92
93void LayerTreeHostCA::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush)
94{
95    m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush;
96}
97
98void LayerTreeHostCA::setRootCompositingLayer(GraphicsLayer* graphicsLayer)
99{
100    m_nonCompositedContentLayer->removeAllChildren();
101
102    // Add the accelerated layer tree hierarchy.
103    if (graphicsLayer)
104        m_nonCompositedContentLayer->addChild(graphicsLayer);
105}
106
107void LayerTreeHostCA::invalidate()
108{
109    ASSERT(m_isValid);
110    m_rootLayer = nullptr;
111    m_isValid = false;
112}
113
114void LayerTreeHostCA::setNonCompositedContentsNeedDisplay(const IntRect& rect)
115{
116    m_nonCompositedContentLayer->setNeedsDisplayInRect(rect);
117    if (m_pageOverlayLayer)
118        m_pageOverlayLayer->setNeedsDisplayInRect(rect);
119
120    scheduleLayerFlush();
121}
122
123void LayerTreeHostCA::scrollNonCompositedContents(const IntRect& scrollRect, const IntSize& scrollOffset)
124{
125    setNonCompositedContentsNeedDisplay(scrollRect);
126}
127
128void LayerTreeHostCA::sizeDidChange(const IntSize& newSize)
129{
130    m_rootLayer->setSize(newSize);
131    m_nonCompositedContentLayer->setSize(newSize);
132
133    if (m_pageOverlayLayer)
134        m_pageOverlayLayer->setSize(newSize);
135
136    scheduleLayerFlush();
137    flushPendingLayerChanges();
138}
139
140void LayerTreeHostCA::forceRepaint()
141{
142    scheduleLayerFlush();
143    flushPendingLayerChanges();
144}
145
146void LayerTreeHostCA::didInstallPageOverlay()
147{
148    createPageOverlayLayer();
149    scheduleLayerFlush();
150}
151
152void LayerTreeHostCA::didUninstallPageOverlay()
153{
154    destroyPageOverlayLayer();
155    scheduleLayerFlush();
156}
157
158void LayerTreeHostCA::setPageOverlayNeedsDisplay(const IntRect& rect)
159{
160    ASSERT(m_pageOverlayLayer);
161    m_pageOverlayLayer->setNeedsDisplayInRect(rect);
162    scheduleLayerFlush();
163}
164
165void LayerTreeHostCA::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time)
166{
167}
168
169void LayerTreeHostCA::notifySyncRequired(const WebCore::GraphicsLayer*)
170{
171}
172
173void LayerTreeHostCA::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const IntRect& clipRect)
174{
175    if (graphicsLayer == m_nonCompositedContentLayer) {
176        m_webPage->drawRect(graphicsContext, clipRect);
177        return;
178    }
179
180    if (graphicsLayer == m_pageOverlayLayer) {
181        m_webPage->drawPageOverlay(graphicsContext, clipRect);
182        return;
183    }
184}
185
186bool LayerTreeHostCA::showDebugBorders() const
187{
188    return m_webPage->corePage()->settings()->showDebugBorders();
189}
190
191bool LayerTreeHostCA::showRepaintCounter() const
192{
193    return m_webPage->corePage()->settings()->showRepaintCounter();
194}
195
196void LayerTreeHostCA::performScheduledLayerFlush()
197{
198    {
199        RefPtr<LayerTreeHostCA> protect(this);
200        m_webPage->layoutIfNeeded();
201
202        if (!m_isValid)
203            return;
204    }
205
206    if (!flushPendingLayerChanges())
207        return;
208
209    didPerformScheduledLayerFlush();
210}
211
212void LayerTreeHostCA::didPerformScheduledLayerFlush()
213{
214    if (m_notifyAfterScheduledLayerFlush) {
215        // Let the drawing area know that we've done a flush of the layer changes.
216        static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
217        m_notifyAfterScheduledLayerFlush = false;
218    }
219}
220
221bool LayerTreeHostCA::flushPendingLayerChanges()
222{
223    m_rootLayer->syncCompositingStateForThisLayerOnly();
224    m_nonCompositedContentLayer->syncCompositingStateForThisLayerOnly();
225    if (m_pageOverlayLayer)
226        m_pageOverlayLayer->syncCompositingStateForThisLayerOnly();
227
228    return m_webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes();
229}
230
231void LayerTreeHostCA::createPageOverlayLayer()
232{
233    ASSERT(!m_pageOverlayLayer);
234
235    m_pageOverlayLayer = GraphicsLayer::create(this);
236#ifndef NDEBUG
237    m_pageOverlayLayer->setName("LayerTreeHost page overlay content");
238#endif
239
240    m_pageOverlayLayer->setDrawsContent(true);
241    m_pageOverlayLayer->setSize(m_webPage->size());
242
243    m_rootLayer->addChild(m_pageOverlayLayer.get());
244}
245
246void LayerTreeHostCA::destroyPageOverlayLayer()
247{
248    ASSERT(m_pageOverlayLayer);
249    m_pageOverlayLayer->removeFromParent();
250    m_pageOverlayLayer = nullptr;
251}
252
253} // namespace WebKit
254