2011-02-04 Anders Carlsson <andersca@apple.com>
[WebKit.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 "Region.h"
33 #include "UpdateInfo.h"
34 #include "WebPageProxy.h"
35 #include "WebProcessProxy.h"
36
37 #ifndef __APPLE__
38 #error "This drawing area is not ready for use by other ports yet."
39 #endif
40
41 using namespace WebCore;
42
43 namespace WebKit {
44
45 PassOwnPtr<DrawingAreaProxyImpl> DrawingAreaProxyImpl::create(WebPageProxy* webPageProxy)
46 {
47     return adoptPtr(new DrawingAreaProxyImpl(webPageProxy));
48 }
49
50 DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy* webPageProxy)
51     : DrawingAreaProxy(DrawingAreaInfo::Impl, webPageProxy)
52     , m_isWaitingForDidSetSize(false)
53     , m_lastDidSetSizeSequenceNumber(0)
54 {
55 }
56
57 DrawingAreaProxyImpl::~DrawingAreaProxyImpl()
58 {
59     // Make sure to exit accelerated compositing mode.
60     if (isInAcceleratedCompositingMode())
61         exitAcceleratedCompositingMode();
62 }
63
64 void DrawingAreaProxyImpl::paint(BackingStore::PlatformGraphicsContext context, const IntRect& rect, Region& unpaintedRegion)
65 {
66     unpaintedRegion = rect;
67
68     if (!m_backingStore)
69         return;
70
71     ASSERT(!isInAcceleratedCompositingMode());
72
73     if (m_isWaitingForDidSetSize) {
74         // Wait for a DidSetSize message that contains the new bits before we paint
75         // what's currently in the backing store.
76         waitForAndDispatchDidSetSize();
77     }
78
79     // Dispatching DidSetSize could change the compositing mode, return if that happens.
80     if (isInAcceleratedCompositingMode())
81         return;
82
83     m_backingStore->paint(context, rect);
84     unpaintedRegion.subtract(IntRect(IntPoint(), m_backingStore->size()));
85 }
86
87 void DrawingAreaProxyImpl::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*)
88 {
89     ASSERT_NOT_REACHED();
90 }
91
92 void DrawingAreaProxyImpl::didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, CoreIPC::ArgumentEncoder*)
93 {
94     ASSERT_NOT_REACHED();
95 }
96
97 bool DrawingAreaProxyImpl::paint(const WebCore::IntRect&, PlatformDrawingContext)
98 {
99     ASSERT_NOT_REACHED();
100     return false;
101 }
102
103 void DrawingAreaProxyImpl::sizeDidChange()
104 {
105     sendSetSize();
106 }
107
108 void DrawingAreaProxyImpl::visibilityDidChange()
109 {
110     if (!m_webPageProxy->isViewVisible()) {
111         // Suspend painting.
112         m_webPageProxy->process()->send(Messages::DrawingArea::SuspendPainting(), m_webPageProxy->pageID());
113         return;
114     }
115
116     // Resume painting.
117     m_webPageProxy->process()->send(Messages::DrawingArea::ResumePainting(), m_webPageProxy->pageID());
118 }
119
120 void DrawingAreaProxyImpl::setPageIsVisible(bool)
121 {
122 }
123
124 void DrawingAreaProxyImpl::attachCompositingContext(uint32_t contextID)
125 {
126     ASSERT_NOT_REACHED();
127 }
128
129 void DrawingAreaProxyImpl::detachCompositingContext()
130 {
131     ASSERT_NOT_REACHED();
132 }
133
134 void DrawingAreaProxyImpl::update(uint64_t sequenceNumber, const UpdateInfo& updateInfo)
135 {
136     if (sequenceNumber < m_lastDidSetSizeSequenceNumber)
137         return;
138
139     // FIXME: Handle the case where the view is hidden.
140
141     incorporateUpdate(updateInfo);
142     m_webPageProxy->process()->send(Messages::DrawingArea::DidUpdate(), m_webPageProxy->pageID());
143 }
144
145 void DrawingAreaProxyImpl::didSetSize(uint64_t sequenceNumber, const UpdateInfo& updateInfo, const LayerTreeContext& layerTreeContext)
146 {
147     ASSERT(sequenceNumber > m_lastDidSetSizeSequenceNumber);
148     m_lastDidSetSizeSequenceNumber = sequenceNumber;
149
150     ASSERT(m_isWaitingForDidSetSize);
151     m_isWaitingForDidSetSize = false;
152
153     if (m_size != updateInfo.viewSize)
154         sendSetSize();
155
156     if (layerTreeContext != m_layerTreeContext) {
157         if (!m_layerTreeContext.isEmpty()) {
158             exitAcceleratedCompositingMode();
159             ASSERT(m_layerTreeContext.isEmpty());
160         }
161
162         if (!layerTreeContext.isEmpty()) {
163             enterAcceleratedCompositingMode(layerTreeContext);
164             ASSERT(layerTreeContext == m_layerTreeContext);
165         }            
166     }
167
168     if (isInAcceleratedCompositingMode()) {
169         ASSERT(!m_backingStore);
170         return;
171     }
172
173     m_backingStore = nullptr;
174     incorporateUpdate(updateInfo);
175 }
176
177 void DrawingAreaProxyImpl::enterAcceleratedCompositingMode(uint64_t sequenceNumber, const LayerTreeContext& layerTreeContext)
178 {
179     if (sequenceNumber < m_lastDidSetSizeSequenceNumber)
180         return;
181
182     enterAcceleratedCompositingMode(layerTreeContext);
183 }
184
185 void DrawingAreaProxyImpl::exitAcceleratedCompositingMode(uint64_t sequenceNumber, const UpdateInfo& updateInfo)
186 {
187     if (sequenceNumber < m_lastDidSetSizeSequenceNumber)
188         return;
189
190     exitAcceleratedCompositingMode();
191
192     incorporateUpdate(updateInfo);
193 }
194
195 void DrawingAreaProxyImpl::incorporateUpdate(const UpdateInfo& updateInfo)
196 {
197     ASSERT(!isInAcceleratedCompositingMode());
198
199     if (updateInfo.updateRectBounds.isEmpty())
200         return;
201
202     if (!m_backingStore)
203         m_backingStore = BackingStore::create(updateInfo.viewSize, m_webPageProxy);
204
205     m_backingStore->incorporateUpdate(updateInfo);
206
207     bool shouldScroll = !updateInfo.scrollRect.isEmpty();
208
209     if (shouldScroll)
210         m_webPageProxy->scrollView(updateInfo.scrollRect, updateInfo.scrollOffset);
211     
212     for (size_t i = 0; i < updateInfo.updateRects.size(); ++i)
213         m_webPageProxy->setViewNeedsDisplay(updateInfo.updateRects[i]);
214
215     if (shouldScroll)
216         m_webPageProxy->displayView();
217 }
218
219 void DrawingAreaProxyImpl::sendSetSize()
220 {
221     if (!m_webPageProxy->isValid())
222         return;
223
224     if (m_isWaitingForDidSetSize)
225         return;
226
227     m_isWaitingForDidSetSize = true;
228     m_webPageProxy->process()->send(Messages::DrawingArea::SetSize(m_size), m_webPageProxy->pageID());
229
230     if (!m_layerTreeContext.isEmpty()) {
231         // Wait for the DidSetSize message. Normally we don this in DrawingAreaProxyImpl::paint, but that
232         // function is never called when in accelerated compositing mode.
233         waitForAndDispatchDidSetSize();
234     }
235 }
236
237 void DrawingAreaProxyImpl::waitForAndDispatchDidSetSize()
238 {
239     ASSERT(m_isWaitingForDidSetSize);
240
241     if (!m_webPageProxy->isValid())
242         return;
243     if (m_webPageProxy->process()->isLaunching())
244         return;
245     
246     // The timeout, in seconds, we use when waiting for a DidSetSize message when we're asked to paint.
247     static const double didSetSizeTimeout = 0.5;
248     m_webPageProxy->process()->connection()->waitForAndDispatchImmediately<Messages::DrawingAreaProxy::DidSetSize>(m_webPageProxy->pageID(), didSetSizeTimeout);
249 }
250
251 void DrawingAreaProxyImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
252 {
253     ASSERT(!isInAcceleratedCompositingMode());
254
255     m_backingStore = nullptr;
256     m_layerTreeContext = layerTreeContext;
257     m_webPageProxy->enterAcceleratedCompositingMode(layerTreeContext);
258 }
259
260 void DrawingAreaProxyImpl::exitAcceleratedCompositingMode()
261 {
262     ASSERT(isInAcceleratedCompositingMode());
263
264     m_layerTreeContext = LayerTreeContext();    
265     m_webPageProxy->exitAcceleratedCompositingMode();
266 }
267
268 } // namespace WebKit