Fix unused parameter compile warnings in WebKit/WebKit2
[WebKit-https.git] / Source / WebKit2 / UIProcess / DrawingAreaProxyImpl.cpp
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 "DrawingAreaProxyImpl.h"
28
29 #include "DrawingAreaMessages.h"
30 #include "DrawingAreaProxyMessages.h"
31 #include "LayerTreeContext.h"
32 #include "UpdateInfo.h"
33 #include "WebPageGroup.h"
34 #include "WebPageProxy.h"
35 #include "WebPreferences.h"
36 #include "WebProcessProxy.h"
37 #include <WebCore/Region.h>
38
39 #if USE(COORDINATED_GRAPHICS)
40 #include "LayerTreeCoordinatorProxy.h"
41 #endif
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 PassOwnPtr<DrawingAreaProxyImpl> DrawingAreaProxyImpl::create(WebPageProxy* webPageProxy)
48 {
49     return adoptPtr(new DrawingAreaProxyImpl(webPageProxy));
50 }
51
52 DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy* webPageProxy)
53     : DrawingAreaProxy(DrawingAreaTypeImpl, webPageProxy)
54     , m_currentBackingStoreStateID(0)
55     , m_nextBackingStoreStateID(0)
56     , m_isWaitingForDidUpdateBackingStoreState(false)
57     , m_hasReceivedFirstUpdate(false)
58     , m_isBackingStoreDiscardable(true)
59     , m_discardBackingStoreTimer(RunLoop::current(), this, &DrawingAreaProxyImpl::discardBackingStore)
60 {
61 #if USE(COORDINATED_GRAPHICS)
62     // Construct the proxy early to allow messages to be sent to the web process while AC is entered there.
63     if (webPageProxy->pageGroup()->preferences()->forceCompositingMode())
64         m_layerTreeCoordinatorProxy = adoptPtr(new LayerTreeCoordinatorProxy(this));
65 #endif
66 }
67
68 DrawingAreaProxyImpl::~DrawingAreaProxyImpl()
69 {
70 #if USE(ACCELERATED_COMPOSITING)
71     // Make sure to exit accelerated compositing mode.
72     if (isInAcceleratedCompositingMode())
73         exitAcceleratedCompositingMode();
74 #endif
75 }
76
77 void DrawingAreaProxyImpl::paint(BackingStore::PlatformGraphicsContext context, const IntRect& rect, Region& unpaintedRegion)
78 {
79     unpaintedRegion = rect;
80
81     if (isInAcceleratedCompositingMode())
82         return;
83
84     ASSERT(m_currentBackingStoreStateID <= m_nextBackingStoreStateID);
85     if (m_currentBackingStoreStateID < m_nextBackingStoreStateID) {
86         // Tell the web process to do a full backing store update now, in case we previously told
87         // it about our next state but didn't request an immediate update.
88         sendUpdateBackingStoreState(RespondImmediately);
89
90         // If we haven't yet received our first bits from the WebProcess then don't paint anything.
91         if (!m_hasReceivedFirstUpdate)
92             return;        
93         
94         if (m_isWaitingForDidUpdateBackingStoreState) {
95             // Wait for a DidUpdateBackingStoreState message that contains the new bits before we paint
96             // what's currently in the backing store.
97             waitForAndDispatchDidUpdateBackingStoreState();
98         }
99
100         // Dispatching DidUpdateBackingStoreState (either beneath sendUpdateBackingStoreState or
101         // beneath waitForAndDispatchDidUpdateBackingStoreState) could destroy our backing store or
102         // change the compositing mode.
103         if (!m_backingStore || isInAcceleratedCompositingMode())
104             return;
105     } else {
106         ASSERT(!m_isWaitingForDidUpdateBackingStoreState);
107         if (!m_backingStore) {
108             // The view has asked us to paint before the web process has painted anything. There's
109             // nothing we can do.
110             return;
111         }
112     }
113
114     m_backingStore->paint(context, rect);
115     unpaintedRegion.subtract(IntRect(IntPoint(), m_backingStore->size()));
116
117     discardBackingStoreSoon();
118 }
119
120 void DrawingAreaProxyImpl::sizeDidChange()
121 {
122     backingStoreStateDidChange(RespondImmediately);
123 }
124
125 void DrawingAreaProxyImpl::deviceScaleFactorDidChange()
126 {
127     backingStoreStateDidChange(RespondImmediately);
128 }
129
130 void DrawingAreaProxyImpl::layerHostingModeDidChange()
131 {
132     m_webPageProxy->process()->send(Messages::DrawingArea::SetLayerHostingMode(m_webPageProxy->layerHostingMode()), m_webPageProxy->pageID());
133 }
134
135 void DrawingAreaProxyImpl::visibilityDidChange()
136 {
137     if (!m_webPageProxy->suppressVisibilityUpdates()) {
138         if (!m_webPageProxy->isViewVisible()) {
139             // Suspend painting.
140             m_webPageProxy->process()->send(Messages::DrawingArea::SuspendPainting(), m_webPageProxy->pageID());
141             return;
142         }
143
144         // Resume painting.
145         m_webPageProxy->process()->send(Messages::DrawingArea::ResumePainting(), m_webPageProxy->pageID());
146     }
147
148 #if USE(ACCELERATED_COMPOSITING)
149     // If we don't have a backing store, go ahead and mark the backing store as being changed so
150     // that when paint we'll actually wait for something to paint and not flash white.
151     if (!m_backingStore && m_layerTreeContext.isEmpty())
152         backingStoreStateDidChange(DoNotRespondImmediately);
153 #endif
154 }
155
156 void DrawingAreaProxyImpl::setBackingStoreIsDiscardable(bool isBackingStoreDiscardable)
157 {
158     if (m_isBackingStoreDiscardable == isBackingStoreDiscardable)
159         return;
160
161     m_isBackingStoreDiscardable = isBackingStoreDiscardable;
162     if (m_isBackingStoreDiscardable)
163         discardBackingStoreSoon();
164     else
165         m_discardBackingStoreTimer.stop();
166 }
167
168 void DrawingAreaProxyImpl::waitForBackingStoreUpdateOnNextPaint()
169 {
170     m_hasReceivedFirstUpdate = true;
171 }
172
173 void DrawingAreaProxyImpl::update(uint64_t backingStoreStateID, const UpdateInfo& updateInfo)
174 {
175     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
176     if (backingStoreStateID < m_currentBackingStoreStateID)
177         return;
178
179     // FIXME: Handle the case where the view is hidden.
180
181     incorporateUpdate(updateInfo);
182     m_webPageProxy->process()->send(Messages::DrawingArea::DidUpdate(), m_webPageProxy->pageID());
183 }
184
185 void DrawingAreaProxyImpl::didUpdateBackingStoreState(uint64_t backingStoreStateID, const UpdateInfo& updateInfo, const LayerTreeContext& layerTreeContext)
186 {
187     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_nextBackingStoreStateID);
188     ASSERT_ARG(backingStoreStateID, backingStoreStateID > m_currentBackingStoreStateID);
189     m_currentBackingStoreStateID = backingStoreStateID;
190
191     m_isWaitingForDidUpdateBackingStoreState = false;
192
193     // Stop the responsiveness timer that was started in sendUpdateBackingStoreState.
194     m_webPageProxy->process()->responsivenessTimer()->stop();
195
196     if (m_nextBackingStoreStateID != m_currentBackingStoreStateID)
197         sendUpdateBackingStoreState(RespondImmediately);
198     else
199         m_hasReceivedFirstUpdate = true;
200
201 #if USE(ACCELERATED_COMPOSITING)
202     if (layerTreeContext != m_layerTreeContext) {
203         if (!m_layerTreeContext.isEmpty()) {
204             exitAcceleratedCompositingMode();
205             ASSERT(m_layerTreeContext.isEmpty());
206         }
207
208         if (!layerTreeContext.isEmpty()) {
209             enterAcceleratedCompositingMode(layerTreeContext);
210             ASSERT(layerTreeContext == m_layerTreeContext);
211         }            
212     }
213
214     if (isInAcceleratedCompositingMode()) {
215         ASSERT(!m_backingStore);
216         return;
217     }
218 #else
219     UNUSED_PARAM(layerTreeContext);
220 #endif
221
222     // If we have a backing store the right size, reuse it.
223     if (m_backingStore && (m_backingStore->size() != updateInfo.viewSize || m_backingStore->deviceScaleFactor() != updateInfo.deviceScaleFactor))
224         m_backingStore = nullptr;
225     incorporateUpdate(updateInfo);
226 }
227
228 void DrawingAreaProxyImpl::enterAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext& layerTreeContext)
229 {
230     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
231     if (backingStoreStateID < m_currentBackingStoreStateID)
232         return;
233
234 #if USE(ACCELERATED_COMPOSITING)
235     enterAcceleratedCompositingMode(layerTreeContext);
236 #else
237     UNUSED_PARAM(layerTreeContext);
238 #endif
239 }
240
241 void DrawingAreaProxyImpl::exitAcceleratedCompositingMode(uint64_t backingStoreStateID, const UpdateInfo& updateInfo)
242 {
243     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
244     if (backingStoreStateID < m_currentBackingStoreStateID)
245         return;
246
247 #if USE(ACCELERATED_COMPOSITING)
248     exitAcceleratedCompositingMode();
249 #endif
250
251     incorporateUpdate(updateInfo);
252 }
253
254 void DrawingAreaProxyImpl::updateAcceleratedCompositingMode(uint64_t backingStoreStateID, const LayerTreeContext& layerTreeContext)
255 {
256     ASSERT_ARG(backingStoreStateID, backingStoreStateID <= m_currentBackingStoreStateID);
257     if (backingStoreStateID < m_currentBackingStoreStateID)
258         return;
259
260 #if USE(ACCELERATED_COMPOSITING)
261     updateAcceleratedCompositingMode(layerTreeContext);
262 #else
263     UNUSED_PARAM(layerTreeContext);
264 #endif
265 }
266
267 void DrawingAreaProxyImpl::incorporateUpdate(const UpdateInfo& updateInfo)
268 {
269     ASSERT(!isInAcceleratedCompositingMode());
270
271     if (updateInfo.updateRectBounds.isEmpty())
272         return;
273
274     if (!m_backingStore)
275         m_backingStore = BackingStore::create(updateInfo.viewSize, updateInfo.deviceScaleFactor, m_webPageProxy);
276
277     m_backingStore->incorporateUpdate(updateInfo);
278
279     bool shouldScroll = !updateInfo.scrollRect.isEmpty();
280
281     if (shouldScroll)
282         m_webPageProxy->scrollView(updateInfo.scrollRect, updateInfo.scrollOffset);
283
284     for (size_t i = 0; i < updateInfo.updateRects.size(); ++i)
285         m_webPageProxy->setViewNeedsDisplay(updateInfo.updateRects[i]);
286
287     if (WebPageProxy::debugPaintFlags() & kWKDebugFlashBackingStoreUpdates)
288         m_webPageProxy->flashBackingStoreUpdates(updateInfo.updateRects);
289
290     if (shouldScroll)
291         m_webPageProxy->displayView();
292 }
293
294 void DrawingAreaProxyImpl::backingStoreStateDidChange(RespondImmediatelyOrNot respondImmediatelyOrNot)
295 {
296     ++m_nextBackingStoreStateID;
297     sendUpdateBackingStoreState(respondImmediatelyOrNot);
298 }
299
300 void DrawingAreaProxyImpl::sendUpdateBackingStoreState(RespondImmediatelyOrNot respondImmediatelyOrNot)
301 {
302     ASSERT(m_currentBackingStoreStateID < m_nextBackingStoreStateID);
303
304     if (!m_webPageProxy->isValid())
305         return;
306
307     if (m_isWaitingForDidUpdateBackingStoreState)
308         return;
309
310     if (m_webPageProxy->viewSize().isEmpty())
311         return;
312
313     m_isWaitingForDidUpdateBackingStoreState = respondImmediatelyOrNot == RespondImmediately;
314
315     m_webPageProxy->process()->send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, respondImmediatelyOrNot == RespondImmediately, m_webPageProxy->deviceScaleFactor(), m_size, m_scrollOffset), m_webPageProxy->pageID());
316     m_scrollOffset = IntSize();
317
318     if (m_isWaitingForDidUpdateBackingStoreState) {
319         // Start the responsiveness timer. We will stop it when we hear back from the WebProcess
320         // in didUpdateBackingStoreState.
321         m_webPageProxy->process()->responsivenessTimer()->start();
322     }
323
324 #if USE(ACCELERATED_COMPOSITING)
325     if (m_isWaitingForDidUpdateBackingStoreState && !m_layerTreeContext.isEmpty()) {
326         // Wait for the DidUpdateBackingStoreState message. Normally we do this in DrawingAreaProxyImpl::paint, but that
327         // function is never called when in accelerated compositing mode.
328         waitForAndDispatchDidUpdateBackingStoreState();
329     }
330 #endif
331 }
332
333 void DrawingAreaProxyImpl::waitForAndDispatchDidUpdateBackingStoreState()
334 {
335     ASSERT(m_isWaitingForDidUpdateBackingStoreState);
336
337     if (!m_webPageProxy->isValid())
338         return;
339     if (m_webPageProxy->process()->isLaunching())
340         return;
341
342 #if USE(ACCELERATED_COMPOSITING)
343     // FIXME: waitForAndDispatchImmediately will always return the oldest DidUpdateBackingStoreState message that
344     // hasn't yet been processed. But it might be better to skip ahead to some other DidUpdateBackingStoreState
345     // message, if multiple DidUpdateBackingStoreState messages are waiting to be processed. For instance, we could
346     // choose the most recent one, or the one that is closest to our current size.
347
348     // The timeout, in seconds, we use when waiting for a DidUpdateBackingStoreState message when we're asked to paint.
349     static const double didUpdateBackingStoreStateTimeout = 0.5;
350     m_webPageProxy->process()->connection()->waitForAndDispatchImmediately<Messages::DrawingAreaProxy::DidUpdateBackingStoreState>(m_webPageProxy->pageID(), didUpdateBackingStoreStateTimeout);
351 #endif
352 }
353
354 #if USE(ACCELERATED_COMPOSITING)
355 void DrawingAreaProxyImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
356 {
357     ASSERT(!isInAcceleratedCompositingMode());
358
359     m_backingStore = nullptr;
360     m_layerTreeContext = layerTreeContext;
361     m_webPageProxy->enterAcceleratedCompositingMode(layerTreeContext);
362 #if USE(COORDINATED_GRAPHICS)
363     if (!m_layerTreeCoordinatorProxy)
364         m_layerTreeCoordinatorProxy = adoptPtr(new LayerTreeCoordinatorProxy(this));
365 #endif
366 }
367
368 #if USE(COORDINATED_GRAPHICS)
369 void DrawingAreaProxyImpl::didReceiveLayerTreeCoordinatorProxyMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
370 {
371     if (m_layerTreeCoordinatorProxy)
372         m_layerTreeCoordinatorProxy->didReceiveLayerTreeCoordinatorProxyMessage(connection, messageID, arguments);
373 }
374
375 void DrawingAreaProxyImpl::setVisibleContentsRect(const WebCore::FloatRect& visibleContentsRect, float scale, const WebCore::FloatPoint& trajectoryVector)
376 {
377     if (m_layerTreeCoordinatorProxy)
378         m_layerTreeCoordinatorProxy->setVisibleContentsRect(visibleContentsRect, scale, trajectoryVector);
379 }
380
381 #endif
382
383 void DrawingAreaProxyImpl::exitAcceleratedCompositingMode()
384 {
385     ASSERT(isInAcceleratedCompositingMode());
386
387     m_layerTreeContext = LayerTreeContext();    
388     m_webPageProxy->exitAcceleratedCompositingMode();
389 }
390
391 void DrawingAreaProxyImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
392 {
393     ASSERT(isInAcceleratedCompositingMode());
394
395     m_layerTreeContext = layerTreeContext;
396     m_webPageProxy->updateAcceleratedCompositingMode(layerTreeContext);
397 }
398 #endif
399
400 void DrawingAreaProxyImpl::pageCustomRepresentationChanged()
401 {
402     m_webPageProxy->process()->send(Messages::DrawingArea::PageCustomRepresentationChanged(), m_webPageProxy->pageID());
403 }
404
405 void DrawingAreaProxyImpl::discardBackingStoreSoon()
406 {
407     if (!m_isBackingStoreDiscardable || m_discardBackingStoreTimer.isActive())
408         return;
409
410     // We'll wait this many seconds after the last paint before throwing away our backing store to save memory.
411     // FIXME: It would be smarter to make this delay based on how expensive painting is. See <http://webkit.org/b/55733>.
412     static const double discardBackingStoreDelay = 2;
413
414     m_discardBackingStoreTimer.startOneShot(discardBackingStoreDelay);
415 }
416
417 void DrawingAreaProxyImpl::discardBackingStore()
418 {
419     m_backingStore = nullptr;
420     backingStoreStateDidChange(DoNotRespondImmediately);
421 }
422
423 } // namespace WebKit