[ThreadedCompositor] Add support for HiDPI
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / CoordinatedGraphics / ThreadedCoordinatedLayerTreeHost.cpp
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  * Copyright (C) 2014 Igalia S.L.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "ThreadedCoordinatedLayerTreeHost.h"
31
32 #if USE(COORDINATED_GRAPHICS_THREADED)
33
34 #include "DrawingAreaImpl.h"
35 #include "NotImplemented.h"
36 #include "ThreadSafeCoordinatedSurface.h"
37 #include "WebPage.h"
38 #include <WebCore/CoordinatedGraphicsLayer.h>
39 #include <WebCore/CoordinatedGraphicsState.h>
40 #include <WebCore/Frame.h>
41 #include <WebCore/FrameView.h>
42 #include <WebCore/GraphicsContext.h>
43 #include <WebCore/MainFrame.h>
44 #include <WebCore/Page.h>
45 #include <wtf/CurrentTime.h>
46
47 using namespace WebCore;
48
49 namespace WebKit {
50
51 Ref<ThreadedCoordinatedLayerTreeHost> ThreadedCoordinatedLayerTreeHost::create(WebPage* webPage)
52 {
53     return adoptRef(*new ThreadedCoordinatedLayerTreeHost(webPage));
54 }
55
56 ThreadedCoordinatedLayerTreeHost::~ThreadedCoordinatedLayerTreeHost()
57 {
58 }
59
60 ThreadedCoordinatedLayerTreeHost::ThreadedCoordinatedLayerTreeHost(WebPage* webPage)
61     : LayerTreeHost(webPage)
62     , m_forceRepaintAsyncCallbackID(0)
63     , m_contentLayer(nullptr)
64     , m_viewOverlayRootLayer(nullptr)
65     , m_notifyAfterScheduledLayerFlush(false)
66     , m_isSuspended(false)
67     , m_isWaitingForRenderer(false)
68     , m_layerFlushTimer(RunLoop::main(), this, &ThreadedCoordinatedLayerTreeHost::performScheduledLayerFlush)
69     , m_layerFlushSchedulingEnabled(true)
70 {
71     m_coordinator = std::make_unique<CompositingCoordinator>(m_webPage->corePage(), this);
72
73     m_coordinator->createRootLayer(m_webPage->size());
74
75     CoordinatedSurface::setFactory(createCoordinatedSurface);
76
77     m_compositor = ThreadedCompositor::create(this);
78     scheduleLayerFlush();
79 }
80
81 PassRefPtr<CoordinatedSurface> ThreadedCoordinatedLayerTreeHost::createCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags)
82 {
83     return ThreadSafeCoordinatedSurface::create(size, flags);
84 }
85
86 void ThreadedCoordinatedLayerTreeHost::scheduleLayerFlush()
87 {
88     if (!m_layerFlushSchedulingEnabled)
89         return;
90
91     if (!m_layerFlushTimer.isActive())
92         m_layerFlushTimer.startOneShot(0);
93 }
94
95 void ThreadedCoordinatedLayerTreeHost::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
96 {
97     if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
98         return;
99
100     m_layerFlushSchedulingEnabled = layerFlushingEnabled;
101
102     if (m_layerFlushSchedulingEnabled) {
103         scheduleLayerFlush();
104         return;
105     }
106
107     cancelPendingLayerFlush();
108 }
109
110 void ThreadedCoordinatedLayerTreeHost::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush)
111 {
112     m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush;
113 }
114
115 void ThreadedCoordinatedLayerTreeHost::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer)
116 {
117     m_contentLayer = graphicsLayer;
118     updateRootLayers();
119 }
120
121 void ThreadedCoordinatedLayerTreeHost::invalidate()
122 {
123     notImplemented();
124 }
125
126 void ThreadedCoordinatedLayerTreeHost::scrollNonCompositedContents(const WebCore::IntRect& rect)
127 {
128     m_compositor->scrollTo(rect.location());
129     scheduleLayerFlush();
130 }
131
132 void ThreadedCoordinatedLayerTreeHost::forceRepaint()
133 {
134     notImplemented();
135 }
136
137 bool ThreadedCoordinatedLayerTreeHost::forceRepaintAsync(uint64_t callbackID)
138 {
139     // We expect the UI process to not require a new repaint until the previous one has finished.
140     ASSERT(!m_forceRepaintAsyncCallbackID);
141     m_forceRepaintAsyncCallbackID = callbackID;
142     scheduleLayerFlush();
143     return true;
144 }
145
146 void ThreadedCoordinatedLayerTreeHost::sizeDidChange(const WebCore::IntSize& newSize)
147 {
148     m_coordinator->sizeDidChange(newSize);
149     m_compositor->didChangeContentsSize(newSize);
150 }
151
152 void ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
153 {
154     m_coordinator->deviceOrPageScaleFactorChanged();
155     m_compositor->setDeviceScaleFactor(m_webPage->deviceScaleFactor());
156 }
157
158 void ThreadedCoordinatedLayerTreeHost::pauseRendering()
159 {
160     m_isSuspended = true;
161 }
162
163 void ThreadedCoordinatedLayerTreeHost::resumeRendering()
164 {
165     m_isSuspended = false;
166     scheduleLayerFlush();
167 }
168
169 GraphicsLayerFactory* ThreadedCoordinatedLayerTreeHost::graphicsLayerFactory()
170 {
171     return m_coordinator.get();
172 }
173
174 void ThreadedCoordinatedLayerTreeHost::viewportSizeChanged(const WebCore::IntSize& size)
175 {
176     m_compositor->didChangeViewportSize(size);
177 }
178
179 void ThreadedCoordinatedLayerTreeHost::didChangeViewportProperties(const WebCore::ViewportAttributes& attr)
180 {
181     m_compositor->didChangeViewportAttribute(attr);
182 }
183
184 void ThreadedCoordinatedLayerTreeHost::compositorDidFlushLayers()
185 {
186     static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
187 }
188
189 void ThreadedCoordinatedLayerTreeHost::didScaleFactorChanged(float scale, const IntPoint& origin)
190 {
191     m_webPage->scalePage(scale, origin);
192 }
193
194 void ThreadedCoordinatedLayerTreeHost::updateRootLayers()
195 {
196     if (!m_contentLayer && !m_viewOverlayRootLayer)
197         return;
198
199     m_coordinator->setRootCompositingLayer(m_contentLayer, m_viewOverlayRootLayer);
200 }
201
202 void ThreadedCoordinatedLayerTreeHost::setViewOverlayRootLayer(GraphicsLayer* viewOverlayRootLayer)
203 {
204     m_viewOverlayRootLayer = viewOverlayRootLayer;
205     updateRootLayers();
206 }
207
208 #if PLATFORM(GTK)
209 void ThreadedCoordinatedLayerTreeHost::setNativeSurfaceHandleForCompositing(uint64_t handle)
210 {
211     m_layerTreeContext.contextID = handle;
212     m_compositor->setNativeSurfaceHandleForCompositing(handle);
213 }
214 #endif
215
216 #if ENABLE(REQUEST_ANIMATION_FRAME)
217 void ThreadedCoordinatedLayerTreeHost::scheduleAnimation()
218 {
219     if (m_isWaitingForRenderer)
220         return;
221
222     if (m_layerFlushTimer.isActive())
223         return;
224
225     m_layerFlushTimer.startOneShot(m_coordinator->nextAnimationServiceTime());
226     scheduleLayerFlush();
227 }
228 #endif
229
230 void ThreadedCoordinatedLayerTreeHost::setVisibleContentsRect(const FloatRect& rect, const FloatPoint& trajectoryVector, float scale)
231 {
232     m_coordinator->setVisibleContentsRect(rect, trajectoryVector);
233     if (m_lastScrollPosition != roundedIntPoint(rect.location())) {
234         m_lastScrollPosition = roundedIntPoint(rect.location());
235
236         if (!m_webPage->corePage()->mainFrame().view()->useFixedLayout())
237             m_webPage->corePage()->mainFrame().view()->notifyScrollPositionChanged(m_lastScrollPosition);
238     }
239
240     if (m_lastScaleFactor != scale) {
241         m_lastScaleFactor = scale;
242         didScaleFactorChanged(m_lastScaleFactor, m_lastScrollPosition);
243     }
244
245     scheduleLayerFlush();
246 }
247
248 void ThreadedCoordinatedLayerTreeHost::cancelPendingLayerFlush()
249 {
250     m_layerFlushTimer.stop();
251 }
252
253 void ThreadedCoordinatedLayerTreeHost::performScheduledLayerFlush()
254 {
255     if (m_isSuspended || m_isWaitingForRenderer)
256         return;
257
258     m_coordinator->syncDisplayState();
259     bool didSync = m_coordinator->flushPendingLayerChanges();
260
261     if (m_notifyAfterScheduledLayerFlush && didSync) {
262         compositorDidFlushLayers();
263         m_notifyAfterScheduledLayerFlush = false;
264     }
265 }
266
267 void ThreadedCoordinatedLayerTreeHost::purgeBackingStores()
268 {
269     m_coordinator->purgeBackingStores();
270 }
271
272 void ThreadedCoordinatedLayerTreeHost::renderNextFrame()
273 {
274     m_isWaitingForRenderer = false;
275     m_coordinator->renderNextFrame();
276     scheduleLayerFlush();
277 }
278
279 void ThreadedCoordinatedLayerTreeHost::commitScrollOffset(uint32_t layerID, const IntSize& offset)
280 {
281     m_coordinator->commitScrollOffset(layerID, offset);
282 }
283
284 void ThreadedCoordinatedLayerTreeHost::notifyFlushRequired()
285 {
286     scheduleLayerFlush();
287 }
288
289 void ThreadedCoordinatedLayerTreeHost::commitSceneState(const CoordinatedGraphicsState& state)
290 {
291     m_isWaitingForRenderer = true;
292     m_compositor->updateSceneState(state);
293 }
294
295 void ThreadedCoordinatedLayerTreeHost::paintLayerContents(const GraphicsLayer*, GraphicsContext&, const IntRect&)
296 {
297 }
298
299 } // namespace WebKit
300
301 #endif // USE(COORDINATED_GRAPHICS)