1/*
2 * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2019 Igalia S.L.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include "AcceleratedSurface.h"
30#include "CallbackID.h"
31#include "CompositingCoordinator.h"
32#include "LayerTreeContext.h"
33#include "OptionalCallbackID.h"
34#include "SimpleViewportController.h"
35#include "ThreadedCompositor.h"
36#include "ThreadedDisplayRefreshMonitor.h"
37#include <WebCore/PlatformScreen.h>
38#include <wtf/Forward.h>
39#include <wtf/OptionSet.h>
40#include <wtf/RunLoop.h>
41
42#if USE(COORDINATED_GRAPHICS)
43#include <WebCore/NicosiaSceneIntegration.h>
44#endif
45
46namespace WebCore {
47class IntRect;
48class IntSize;
49class GraphicsLayer;
50class GraphicsLayerFactory;
51struct CoordinatedGraphicsState;
52struct ViewportAttributes;
53}
54
55namespace WebKit {
56
57class WebPage;
58
59class LayerTreeHost
60#if USE(COORDINATED_GRAPHICS)
61 final : public CompositingCoordinator::Client, public AcceleratedSurface::Client, public Nicosia::SceneIntegration::Client
62#endif
63{
64 WTF_MAKE_FAST_ALLOCATED;
65public:
66 explicit LayerTreeHost(WebPage&);
67 ~LayerTreeHost();
68
69 const LayerTreeContext& layerTreeContext() const { return m_layerTreeContext; }
70 void setLayerFlushSchedulingEnabled(bool);
71 void setShouldNotifyAfterNextScheduledLayerFlush(bool);
72
73 void scheduleLayerFlush();
74 void cancelPendingLayerFlush();
75 void setRootCompositingLayer(WebCore::GraphicsLayer*);
76 void setViewOverlayRootLayer(WebCore::GraphicsLayer*);
77 void invalidate();
78
79 void scrollNonCompositedContents(const WebCore::IntRect&);
80 void forceRepaint();
81 bool forceRepaintAsync(CallbackID);
82 void sizeDidChange(const WebCore::IntSize& newSize);
83
84 void pauseRendering();
85 void resumeRendering();
86
87 WebCore::GraphicsLayerFactory* graphicsLayerFactory();
88
89 void contentsSizeChanged(const WebCore::IntSize&);
90 void didChangeViewportAttributes(WebCore::ViewportAttributes&&);
91
92 void setIsDiscardable(bool);
93
94 void deviceOrPageScaleFactorChanged();
95
96#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
97 RefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(WebCore::PlatformDisplayID);
98#endif
99
100private:
101#if USE(COORDINATED_GRAPHICS)
102 void layerFlushTimerFired();
103 void didChangeViewport();
104 void renderNextFrame(bool);
105
106 // CompositingCoordinator::Client
107 void didFlushRootLayer(const WebCore::FloatRect& visibleContentRect) override;
108 void notifyFlushRequired() override { scheduleLayerFlush(); };
109 void commitSceneState(const WebCore::CoordinatedGraphicsState&) override;
110 RefPtr<Nicosia::SceneIntegration> sceneIntegration() override;
111
112 // AcceleratedSurface::Client
113 void frameComplete() override;
114
115 // Nicosia::SceneIntegration::Client
116 void requestUpdate() override;
117
118 uint64_t nativeSurfaceHandleForCompositing();
119 void didDestroyGLContext();
120 void willRenderFrame();
121 void didRenderFrame();
122 void requestDisplayRefreshMonitorUpdate();
123 void handleDisplayRefreshMonitorUpdate(bool);
124
125 class CompositorClient final : public ThreadedCompositor::Client, public ThreadedDisplayRefreshMonitor::Client {
126 WTF_MAKE_NONCOPYABLE(CompositorClient);
127 public:
128 CompositorClient(LayerTreeHost& layerTreeHost)
129 : m_layerTreeHost(layerTreeHost)
130 {
131 }
132
133 private:
134 uint64_t nativeSurfaceHandleForCompositing() override
135 {
136 return m_layerTreeHost.nativeSurfaceHandleForCompositing();
137 }
138
139 void didDestroyGLContext() override
140 {
141 m_layerTreeHost.didDestroyGLContext();
142 }
143
144 void resize(const WebCore::IntSize& size) override
145 {
146 if (m_layerTreeHost.m_surface)
147 m_layerTreeHost.m_surface->clientResize(size);
148 }
149
150 void willRenderFrame() override
151 {
152 m_layerTreeHost.willRenderFrame();
153 }
154
155 void didRenderFrame() override
156 {
157 m_layerTreeHost.didRenderFrame();
158 }
159
160 void requestDisplayRefreshMonitorUpdate() override
161 {
162 m_layerTreeHost.requestDisplayRefreshMonitorUpdate();
163 }
164
165 void handleDisplayRefreshMonitorUpdate(bool hasBeenRescheduled) override
166 {
167 m_layerTreeHost.handleDisplayRefreshMonitorUpdate(hasBeenRescheduled);
168 }
169
170 LayerTreeHost& m_layerTreeHost;
171 };
172
173 enum class DiscardableSyncActions {
174 UpdateSize = 1 << 1,
175 UpdateViewport = 1 << 2,
176 UpdateScale = 1 << 3
177 };
178#endif // USE(COORDINATED_GRAPHICS)
179
180 WebPage& m_webPage;
181 LayerTreeContext m_layerTreeContext;
182#if USE(COORDINATED_GRAPHICS)
183 bool m_layerFlushSchedulingEnabled { true };
184 bool m_notifyAfterScheduledLayerFlush { false };
185 bool m_isSuspended { false };
186 bool m_isValid { true };
187 bool m_isWaitingForRenderer { false };
188 bool m_scheduledWhileWaitingForRenderer { false };
189 float m_lastPageScaleFactor { 1 };
190 WebCore::IntPoint m_lastScrollPosition;
191 bool m_isDiscardable { false };
192 OptionSet<DiscardableSyncActions> m_discardableSyncActions;
193 WebCore::GraphicsLayer* m_viewOverlayRootLayer { nullptr };
194 CompositingCoordinator m_coordinator;
195 CompositorClient m_compositorClient;
196 std::unique_ptr<AcceleratedSurface> m_surface;
197 RefPtr<ThreadedCompositor> m_compositor;
198 SimpleViewportController m_viewportController;
199 struct {
200 OptionalCallbackID callbackID;
201 bool needsFreshFlush { false };
202 } m_forceRepaintAsync;
203 RunLoop::Timer<LayerTreeHost> m_layerFlushTimer;
204 Ref<Nicosia::SceneIntegration> m_sceneIntegration;
205#endif // USE(COORDINATED_GRAPHICS)
206};
207
208#if !USE(COORDINATED_GRAPHICS)
209inline LayerTreeHost::LayerTreeHost(WebPage& webPage) : m_webPage(webPage) { }
210inline LayerTreeHost::~LayerTreeHost() { }
211inline void LayerTreeHost::setLayerFlushSchedulingEnabled(bool) { }
212inline void LayerTreeHost::setShouldNotifyAfterNextScheduledLayerFlush(bool) { }
213inline void LayerTreeHost::scheduleLayerFlush() { }
214inline void LayerTreeHost::cancelPendingLayerFlush() { }
215inline void LayerTreeHost::setRootCompositingLayer(WebCore::GraphicsLayer*) { }
216inline void LayerTreeHost::setViewOverlayRootLayer(WebCore::GraphicsLayer*) { }
217inline void LayerTreeHost::invalidate() { }
218inline void LayerTreeHost::scrollNonCompositedContents(const WebCore::IntRect&) { }
219inline void LayerTreeHost::forceRepaint() { }
220inline bool LayerTreeHost::forceRepaintAsync(CallbackID) { return false; }
221inline void LayerTreeHost::sizeDidChange(const WebCore::IntSize&) { }
222inline void LayerTreeHost::pauseRendering() { }
223inline void LayerTreeHost::resumeRendering() { }
224inline WebCore::GraphicsLayerFactory* LayerTreeHost::graphicsLayerFactory() { return nullptr; }
225inline void LayerTreeHost::contentsSizeChanged(const WebCore::IntSize&) { }
226inline void LayerTreeHost::didChangeViewportAttributes(WebCore::ViewportAttributes&&) { }
227inline void LayerTreeHost::setIsDiscardable(bool) { }
228inline void LayerTreeHost::deviceOrPageScaleFactorChanged() { }
229#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
230inline RefPtr<WebCore::DisplayRefreshMonitor> LayerTreeHost::createDisplayRefreshMonitor(WebCore::PlatformDisplayID) { return nullptr; }
231#endif
232#endif
233
234} // namespace WebKit
235