1/*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 * Copyright (C) 2012 Company 100, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29
30#if USE(COORDINATED_GRAPHICS)
31#include "CoordinatedLayerTreeHost.h"
32
33#include "CoordinatedDrawingArea.h"
34#include "CoordinatedGraphicsArgumentCoders.h"
35#include "CoordinatedLayerTreeHostProxyMessages.h"
36#include "GraphicsContext.h"
37#include "WebCoordinatedSurface.h"
38#include "WebCoreArgumentCoders.h"
39#include "WebPage.h"
40#include "WebPageProxyMessages.h"
41#include <WebCore/Frame.h>
42#include <WebCore/FrameView.h>
43#include <WebCore/Settings.h>
44#include <wtf/CurrentTime.h>
45
46using namespace WebCore;
47
48namespace WebKit {
49
50PassRefPtr<CoordinatedLayerTreeHost> CoordinatedLayerTreeHost::create(WebPage* webPage)
51{
52    return adoptRef(new CoordinatedLayerTreeHost(webPage));
53}
54
55CoordinatedLayerTreeHost::~CoordinatedLayerTreeHost()
56{
57}
58
59CoordinatedLayerTreeHost::CoordinatedLayerTreeHost(WebPage* webPage)
60    : LayerTreeHost(webPage)
61    , m_notifyAfterScheduledLayerFlush(false)
62    , m_isValid(true)
63    , m_isSuspended(false)
64    , m_isWaitingForRenderer(true)
65    , m_layerFlushTimer(this, &CoordinatedLayerTreeHost::layerFlushTimerFired)
66    , m_layerFlushSchedulingEnabled(true)
67    , m_forceRepaintAsyncCallbackID(0)
68{
69    m_coordinator = std::make_unique<CompositingCoordinator>(webPage->corePage(), this);
70
71    m_coordinator->createRootLayer(webPage->size());
72    m_layerTreeContext.contextID = toCoordinatedGraphicsLayer(m_coordinator->rootLayer())->id();
73
74    CoordinatedSurface::setFactory(createCoordinatedSurface);
75
76    scheduleLayerFlush();
77}
78
79void CoordinatedLayerTreeHost::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
80{
81    if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
82        return;
83
84    m_layerFlushSchedulingEnabled = layerFlushingEnabled;
85
86    if (m_layerFlushSchedulingEnabled) {
87        scheduleLayerFlush();
88        return;
89    }
90
91    cancelPendingLayerFlush();
92}
93
94void CoordinatedLayerTreeHost::scheduleLayerFlush()
95{
96    if (!m_layerFlushSchedulingEnabled)
97        return;
98
99    if (!m_layerFlushTimer.isActive() || m_layerFlushTimer.nextFireInterval() > 0)
100        m_layerFlushTimer.startOneShot(0);
101}
102
103void CoordinatedLayerTreeHost::cancelPendingLayerFlush()
104{
105    m_layerFlushTimer.stop();
106}
107
108void CoordinatedLayerTreeHost::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush)
109{
110    m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush;
111}
112
113void CoordinatedLayerTreeHost::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer)
114{
115    m_coordinator->setRootCompositingLayer(graphicsLayer, m_webPage->pageOverlayController().viewOverlayRootLayer());
116}
117
118void CoordinatedLayerTreeHost::invalidate()
119{
120    cancelPendingLayerFlush();
121
122    ASSERT(m_isValid);
123    m_coordinator->clearRootLayer();
124    m_isValid = false;
125}
126
127void CoordinatedLayerTreeHost::forceRepaint()
128{
129    // This is necessary for running layout tests. Since in this case we are not waiting for a UIProcess to reply nicely.
130    // Instead we are just triggering forceRepaint. But we still want to have the scripted animation callbacks being executed.
131    m_coordinator->syncDisplayState();
132
133    // We need to schedule another flush, otherwise the forced paint might cancel a later expected flush.
134    // This is aligned with LayerTreeHostCA.
135    scheduleLayerFlush();
136
137    if (m_isWaitingForRenderer)
138        return;
139
140    m_coordinator->flushPendingLayerChanges();
141}
142
143bool CoordinatedLayerTreeHost::forceRepaintAsync(uint64_t callbackID)
144{
145    // We expect the UI process to not require a new repaint until the previous one has finished.
146    ASSERT(!m_forceRepaintAsyncCallbackID);
147    m_forceRepaintAsyncCallbackID = callbackID;
148    scheduleLayerFlush();
149    return true;
150}
151
152void CoordinatedLayerTreeHost::sizeDidChange(const WebCore::IntSize& newSize)
153{
154    m_coordinator->sizeDidChange(newSize);
155    scheduleLayerFlush();
156}
157
158void CoordinatedLayerTreeHost::setVisibleContentsRect(const FloatRect& rect, const FloatPoint& trajectoryVector)
159{
160    m_coordinator->setVisibleContentsRect(rect, trajectoryVector);
161    scheduleLayerFlush();
162}
163
164void CoordinatedLayerTreeHost::renderNextFrame()
165{
166    m_isWaitingForRenderer = false;
167    scheduleLayerFlush();
168    m_coordinator->renderNextFrame();
169}
170
171void CoordinatedLayerTreeHost::purgeBackingStores()
172{
173    m_coordinator->purgeBackingStores();
174}
175
176void CoordinatedLayerTreeHost::didFlushRootLayer(const FloatRect& visibleContentRect)
177{
178    m_webPage->pageOverlayController().flushPageOverlayLayers(visibleContentRect);
179}
180
181void CoordinatedLayerTreeHost::performScheduledLayerFlush()
182{
183    if (m_isSuspended || m_isWaitingForRenderer)
184        return;
185
186    m_coordinator->syncDisplayState();
187
188    if (!m_isValid)
189        return;
190
191    bool didSync = m_coordinator->flushPendingLayerChanges();
192
193    if (m_forceRepaintAsyncCallbackID) {
194        m_webPage->send(Messages::WebPageProxy::VoidCallback(m_forceRepaintAsyncCallbackID));
195        m_forceRepaintAsyncCallbackID = 0;
196    }
197
198    if (m_notifyAfterScheduledLayerFlush && didSync) {
199        static_cast<CoordinatedDrawingArea*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
200        m_notifyAfterScheduledLayerFlush = false;
201    }
202}
203
204void CoordinatedLayerTreeHost::layerFlushTimerFired(Timer<CoordinatedLayerTreeHost>*)
205{
206    performScheduledLayerFlush();
207}
208
209void CoordinatedLayerTreeHost::paintLayerContents(const GraphicsLayer*, GraphicsContext&, const IntRect&)
210{
211}
212
213void CoordinatedLayerTreeHost::commitSceneState(const WebCore::CoordinatedGraphicsState& state)
214{
215    m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CommitCoordinatedGraphicsState(state));
216    m_isWaitingForRenderer = true;
217}
218
219PassRefPtr<CoordinatedSurface> CoordinatedLayerTreeHost::createCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags)
220{
221    return WebCoordinatedSurface::create(size, flags);
222}
223
224void CoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
225{
226    m_coordinator->deviceOrPageScaleFactorChanged();
227    m_webPage->pageOverlayController().didChangeDeviceScaleFactor();
228}
229
230void CoordinatedLayerTreeHost::pageBackgroundTransparencyChanged()
231{
232}
233
234GraphicsLayerFactory* CoordinatedLayerTreeHost::graphicsLayerFactory()
235{
236    return m_coordinator.get();
237}
238
239#if ENABLE(REQUEST_ANIMATION_FRAME)
240void CoordinatedLayerTreeHost::scheduleAnimation()
241{
242    if (m_isWaitingForRenderer)
243        return;
244
245    if (m_layerFlushTimer.isActive())
246        return;
247
248    scheduleLayerFlush();
249    m_layerFlushTimer.startOneShot(m_coordinator->nextAnimationServiceTime());
250}
251#endif
252
253void CoordinatedLayerTreeHost::setBackgroundColor(const WebCore::Color& color)
254{
255    m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetBackgroundColor(color));
256}
257
258void CoordinatedLayerTreeHost::commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset)
259{
260    m_coordinator->commitScrollOffset(layerID, offset);
261}
262
263} // namespace WebKit
264#endif // USE(COORDINATED_GRAPHICS)
265