[GTK] Configures but fails to link with ENABLE_OPENGL=OFF
[WebKit-https.git] / Source / WebKit2 / UIProcess / AcceleratedDrawingAreaProxy.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
4  * Copyright (C) 2016 Igalia S.L.
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 #include "AcceleratedDrawingAreaProxy.h"
30
31 #include "DrawingAreaMessages.h"
32 #include "DrawingAreaProxyMessages.h"
33 #include "LayerTreeContext.h"
34 #include "UpdateInfo.h"
35 #include "WebPageProxy.h"
36 #include "WebPreferences.h"
37 #include "WebProcessProxy.h"
38 #include <WebCore/Region.h>
39
40 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
41 #include "CoordinatedLayerTreeHostProxy.h"
42 #endif
43
44 #if PLATFORM(WAYLAND)
45 #include "WaylandCompositor.h"
46 #include <WebCore/PlatformDisplay.h>
47 #endif
48
49 using namespace WebCore;
50
51 namespace WebKit {
52
53 AcceleratedDrawingAreaProxy::AcceleratedDrawingAreaProxy(WebPageProxy& webPageProxy)
54 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
55     : DrawingAreaProxy(DrawingAreaTypeCoordinated, webPageProxy)
56 #else
57     : DrawingAreaProxy(DrawingAreaTypeImpl, webPageProxy)
58 #endif
59 {
60 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
61     // Construct the proxy early to allow messages to be sent to the web process while AC is entered there.
62     m_coordinatedLayerTreeHostProxy = std::make_unique<CoordinatedLayerTreeHostProxy>(webPageProxy);
63 #endif
64 }
65
66 AcceleratedDrawingAreaProxy::~AcceleratedDrawingAreaProxy()
67 {
68     // Make sure to exit accelerated compositing mode.
69     if (isInAcceleratedCompositingMode())
70         exitAcceleratedCompositingMode();
71 }
72
73 bool AcceleratedDrawingAreaProxy::alwaysUseCompositing() const
74 {
75     return m_webPageProxy.preferences().acceleratedCompositingEnabled() && m_webPageProxy.preferences().forceCompositingMode();
76 }
77
78 void AcceleratedDrawingAreaProxy::dispatchAfterEnsuringDrawing(std::function<void(CallbackBase::Error)> callbackFunction)
79 {
80     if (!m_webPageProxy.isValid()) {
81         callbackFunction(CallbackBase::Error::OwnerWasInvalidated);
82         return;
83     }
84
85     RunLoop::main().dispatch([callbackFunction] {
86         callbackFunction(CallbackBase::Error::None);
87     });
88 }
89
90 void AcceleratedDrawingAreaProxy::sizeDidChange()
91 {
92     backingStoreStateDidChange(RespondImmediately);
93 }
94
95 void AcceleratedDrawingAreaProxy::deviceScaleFactorDidChange()
96 {
97     backingStoreStateDidChange(RespondImmediately);
98 }
99
100 void AcceleratedDrawingAreaProxy::visibilityDidChange()
101 {
102     // If we don't have a backing store, go ahead and mark the backing store as being changed so
103     // that when paint we'll actually wait for something to paint and not flash white.
104     if (m_layerTreeContext.isEmpty())
105         backingStoreStateDidChange(DoNotRespondImmediately);
106 }
107
108 void AcceleratedDrawingAreaProxy::waitForBackingStoreUpdateOnNextPaint()
109 {
110     m_hasReceivedFirstUpdate = true;
111 }
112
113 void AcceleratedDrawingAreaProxy::didUpdateBackingStoreState(uint64_t backingStoreStateID, const UpdateInfo& updateInfo, const LayerTreeContext& layerTreeContext)
114 {
115     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_nextBackingStoreStateID);
116     ASSERT_ARG(backingStoreStateID, backingStoreStateID > m_currentBackingStoreStateID);
117     m_currentBackingStoreStateID = backingStoreStateID;
118
119     m_isWaitingForDidUpdateBackingStoreState = false;
120
121     // Stop the responsiveness timer that was started in sendUpdateBackingStoreState.
122     m_webPageProxy.process().responsivenessTimer().stop();
123
124     if (layerTreeContext != m_layerTreeContext) {
125         if (layerTreeContext.isEmpty() && !m_layerTreeContext.isEmpty()) {
126             exitAcceleratedCompositingMode();
127             ASSERT(m_layerTreeContext.isEmpty());
128         } else if (!layerTreeContext.isEmpty() && m_layerTreeContext.isEmpty()) {
129             enterAcceleratedCompositingMode(layerTreeContext);
130             ASSERT(layerTreeContext == m_layerTreeContext);
131         } else {
132             updateAcceleratedCompositingMode(layerTreeContext);
133             ASSERT(layerTreeContext == m_layerTreeContext);
134         }
135     }
136
137     if (m_nextBackingStoreStateID != m_currentBackingStoreStateID)
138         sendUpdateBackingStoreState(RespondImmediately);
139     else {
140         m_hasReceivedFirstUpdate = true;
141
142 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(GTK) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
143         if (m_pendingNativeSurfaceHandleForCompositing) {
144             setNativeSurfaceHandleForCompositing(m_pendingNativeSurfaceHandleForCompositing);
145             m_pendingNativeSurfaceHandleForCompositing = 0;
146         }
147 #endif
148     }
149 }
150
151 void AcceleratedDrawingAreaProxy::enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext& layerTreeContext)
152 {
153     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
154     if (backingStoreStateID < m_currentBackingStoreStateID)
155         return;
156
157     enterAcceleratedCompositingMode(layerTreeContext);
158 }
159
160 void AcceleratedDrawingAreaProxy::exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo& updateInfo)
161 {
162     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
163     if (backingStoreStateID < m_currentBackingStoreStateID)
164         return;
165
166     exitAcceleratedCompositingMode();
167 }
168
169 void AcceleratedDrawingAreaProxy::updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext& layerTreeContext)
170 {
171     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
172     if (backingStoreStateID < m_currentBackingStoreStateID)
173         return;
174
175     updateAcceleratedCompositingMode(layerTreeContext);
176 }
177
178 void AcceleratedDrawingAreaProxy::backingStoreStateDidChange(RespondImmediatelyOrNot respondImmediatelyOrNot)
179 {
180     ++m_nextBackingStoreStateID;
181     sendUpdateBackingStoreState(respondImmediatelyOrNot);
182 }
183
184 void AcceleratedDrawingAreaProxy::sendUpdateBackingStoreState(RespondImmediatelyOrNot respondImmediatelyOrNot)
185 {
186     ASSERT(m_currentBackingStoreStateID < m_nextBackingStoreStateID);
187
188     if (!m_webPageProxy.isValid())
189         return;
190
191     if (m_isWaitingForDidUpdateBackingStoreState)
192         return;
193
194     if (m_webPageProxy.viewSize().isEmpty() && !m_webPageProxy.useFixedLayout())
195         return;
196
197     m_isWaitingForDidUpdateBackingStoreState = respondImmediatelyOrNot == RespondImmediately;
198
199     m_webPageProxy.process().send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, respondImmediatelyOrNot == RespondImmediately, m_webPageProxy.deviceScaleFactor(), m_size, m_scrollOffset), m_webPageProxy.pageID());
200     m_scrollOffset = IntSize();
201
202     if (m_isWaitingForDidUpdateBackingStoreState) {
203         // Start the responsiveness timer. We will stop it when we hear back from the WebProcess
204         // in didUpdateBackingStoreState.
205         m_webPageProxy.process().responsivenessTimer().start();
206     }
207
208     if (m_isWaitingForDidUpdateBackingStoreState && !m_layerTreeContext.isEmpty()) {
209         // Wait for the DidUpdateBackingStoreState message. Normally we do this in AcceleratedDrawingAreaProxy::paint, but that
210         // function is never called when in accelerated compositing mode.
211         waitForAndDispatchDidUpdateBackingStoreState();
212     }
213 }
214
215 void AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState()
216 {
217     ASSERT(m_isWaitingForDidUpdateBackingStoreState);
218
219     if (!m_webPageProxy.isValid())
220         return;
221     if (m_webPageProxy.process().state() == WebProcessProxy::State::Launching)
222         return;
223     if (!m_webPageProxy.isViewVisible())
224         return;
225
226 #if PLATFORM(WAYLAND) && USE(EGL)
227     // Never block the UI process in Wayland when waiting for DidUpdateBackingStoreState after a resize,
228     // because the nested compositor needs to handle the web process requests that happens while resizing.
229     if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland && WaylandCompositor::singleton().isRunning())
230         return;
231 #endif
232
233     // FIXME: waitForAndDispatchImmediately will always return the oldest DidUpdateBackingStoreState message that
234     // hasn't yet been processed. But it might be better to skip ahead to some other DidUpdateBackingStoreState
235     // message, if multiple DidUpdateBackingStoreState messages are waiting to be processed. For instance, we could
236     // choose the most recent one, or the one that is closest to our current size.
237
238     // The timeout, in seconds, we use when waiting for a DidUpdateBackingStoreState message when we're asked to paint.
239     m_webPageProxy.process().connection()->waitForAndDispatchImmediately<Messages::DrawingAreaProxy::DidUpdateBackingStoreState>(m_webPageProxy.pageID(), std::chrono::milliseconds(500));
240 }
241
242 void AcceleratedDrawingAreaProxy::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
243 {
244     ASSERT(alwaysUseCompositing() || !isInAcceleratedCompositingMode());
245
246     m_layerTreeContext = layerTreeContext;
247     m_webPageProxy.enterAcceleratedCompositingMode(layerTreeContext);
248 }
249
250 void AcceleratedDrawingAreaProxy::exitAcceleratedCompositingMode()
251 {
252     ASSERT(isInAcceleratedCompositingMode());
253
254     m_layerTreeContext = LayerTreeContext();
255     m_webPageProxy.exitAcceleratedCompositingMode();
256 }
257
258 void AcceleratedDrawingAreaProxy::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
259 {
260     ASSERT(isInAcceleratedCompositingMode());
261
262     m_layerTreeContext = layerTreeContext;
263     m_webPageProxy.updateAcceleratedCompositingMode(layerTreeContext);
264 }
265
266 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(GTK) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
267 void AcceleratedDrawingAreaProxy::setNativeSurfaceHandleForCompositing(uint64_t handle)
268 {
269     if (!m_hasReceivedFirstUpdate) {
270         m_pendingNativeSurfaceHandleForCompositing = handle;
271         return;
272     }
273     m_webPageProxy.process().send(Messages::DrawingArea::SetNativeSurfaceHandleForCompositing(handle), m_webPageProxy.pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
274 }
275
276 void AcceleratedDrawingAreaProxy::destroyNativeSurfaceHandleForCompositing()
277 {
278     if (m_pendingNativeSurfaceHandleForCompositing) {
279         m_pendingNativeSurfaceHandleForCompositing = 0;
280         return;
281     }
282     bool handled;
283     m_webPageProxy.process().sendSync(Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing(), Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing::Reply(handled), m_webPageProxy.pageID());
284 }
285 #endif
286
287 } // namespace WebKit