1 /*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
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 "TiledDrawingArea.h"
28
29 #if ENABLE(TILED_BACKING_STORE)
30
31 #include "DrawingAreaMessageKinds.h"
32 #include "DrawingAreaProxyMessageKinds.h"
33 #include "MessageID.h"
34 #include "UpdateChunk.h"
35 #include "WebCore/Frame.h"
36 #include "WebCore/FrameView.h"
37 #include "WebCoreArgumentCoders.h"
38 #include "WebFrame.h"
39 #include "WebPage.h"
40 #include "WebProcess.h"
41
42 using namespace WebCore;
43
44 namespace WebKit {
45
TiledDrawingArea(WebPage * webPage)46 TiledDrawingArea::TiledDrawingArea(WebPage* webPage)
47 : DrawingArea(DrawingAreaTypeTiled, webPage)
48 , m_isWaitingForUpdate(false)
49 , m_shouldPaint(true)
50 , m_displayTimer(WebProcess::shared().runLoop(), this, &TiledDrawingArea::display)
51 , m_tileUpdateTimer(WebProcess::shared().runLoop(), this, &TiledDrawingArea::tileUpdateTimerFired)
52 {
53 }
54
~TiledDrawingArea()55 TiledDrawingArea::~TiledDrawingArea()
56 {
57 }
58
scroll(const IntRect & scrollRect,const IntSize & scrollDelta)59 void TiledDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollDelta)
60 {
61 // FIXME: Do something much smarter.
62 setNeedsDisplay(scrollRect);
63 }
64
setNeedsDisplay(const IntRect & rect)65 void TiledDrawingArea::setNeedsDisplay(const IntRect& rect)
66 {
67 // FIXME: Collect a set of rects/region instead of just the union of all rects.
68 m_dirtyRect.unite(rect);
69 scheduleDisplay();
70 }
71
display()72 void TiledDrawingArea::display()
73 {
74 if (!m_shouldPaint)
75 return;
76
77 if (m_dirtyRect.isEmpty())
78 return;
79
80 m_webPage->layoutIfNeeded();
81
82 IntRect dirtyRect = m_dirtyRect;
83 m_dirtyRect = IntRect();
84
85 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::Invalidate, m_webPage->pageID(), CoreIPC::In(dirtyRect));
86
87 m_displayTimer.stop();
88 }
89
scheduleDisplay()90 void TiledDrawingArea::scheduleDisplay()
91 {
92 if (!m_shouldPaint)
93 return;
94
95 if (m_displayTimer.isActive())
96 return;
97
98 m_displayTimer.startOneShot(0);
99 }
100
setSize(const IntSize & viewSize)101 void TiledDrawingArea::setSize(const IntSize& viewSize)
102 {
103 ASSERT(m_shouldPaint);
104 ASSERT_ARG(viewSize, !viewSize.isEmpty());
105
106 m_webPage->setSize(viewSize);
107
108 scheduleDisplay();
109
110 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::DidSetSize, m_webPage->pageID(), CoreIPC::In(viewSize));
111 }
112
suspendPainting()113 void TiledDrawingArea::suspendPainting()
114 {
115 ASSERT(m_shouldPaint);
116
117 m_shouldPaint = false;
118 m_displayTimer.stop();
119 }
120
resumePainting()121 void TiledDrawingArea::resumePainting()
122 {
123 ASSERT(!m_shouldPaint);
124
125 m_shouldPaint = true;
126
127 // Display if needed.
128 display();
129 }
130
didUpdate()131 void TiledDrawingArea::didUpdate()
132 {
133 // Display if needed.
134 display();
135 }
136
updateTile(int tileID,const IntRect & dirtyRect,float scale)137 void TiledDrawingArea::updateTile(int tileID, const IntRect& dirtyRect, float scale)
138 {
139 m_webPage->layoutIfNeeded();
140
141 UpdateChunk updateChunk(dirtyRect);
142 paintIntoUpdateChunk(&updateChunk, scale);
143
144 unsigned pendingUpdateCount = m_pendingUpdates.size();
145 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::TileUpdated, m_webPage->pageID(), CoreIPC::In(tileID, updateChunk, scale, pendingUpdateCount));
146 }
147
tileUpdateTimerFired()148 void TiledDrawingArea::tileUpdateTimerFired()
149 {
150 ASSERT(!m_pendingUpdates.isEmpty());
151
152 UpdateMap::iterator it = m_pendingUpdates.begin();
153 TileUpdate update = it->second;
154 m_pendingUpdates.remove(it);
155
156 updateTile(update.tileID, update.dirtyRect, update.scale);
157
158 if (m_pendingUpdates.isEmpty())
159 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::AllTileUpdatesProcessed, m_webPage->pageID(), CoreIPC::In());
160 else
161 m_tileUpdateTimer.startOneShot(0.001);
162 }
163
didReceiveMessage(CoreIPC::Connection *,CoreIPC::MessageID messageID,CoreIPC::ArgumentDecoder * arguments)164 void TiledDrawingArea::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
165 {
166 switch (messageID.get<DrawingAreaLegacyMessage::Kind>()) {
167 case DrawingAreaLegacyMessage::SetSize: {
168 IntSize size;
169 if (!arguments->decode(CoreIPC::Out(size)))
170 return;
171
172 setSize(size);
173 break;
174 }
175 case DrawingAreaLegacyMessage::SuspendPainting:
176 suspendPainting();
177 break;
178 case DrawingAreaLegacyMessage::ResumePainting:
179 resumePainting();
180 break;
181 case DrawingAreaLegacyMessage::CancelTileUpdate: {
182 int tileID;
183 if (!arguments->decode(CoreIPC::Out(tileID)))
184 return;
185 UpdateMap::iterator it = m_pendingUpdates.find(tileID);
186 if (it != m_pendingUpdates.end()) {
187 m_pendingUpdates.remove(it);
188 if (m_pendingUpdates.isEmpty()) {
189 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::AllTileUpdatesProcessed, m_webPage->pageID(), CoreIPC::In());
190 m_tileUpdateTimer.stop();
191 }
192 }
193 break;
194 }
195 case DrawingAreaLegacyMessage::RequestTileUpdate: {
196 TileUpdate update;
197 if (!arguments->decode(CoreIPC::Out(update.tileID, update.dirtyRect, update.scale)))
198 return;
199 UpdateMap::iterator it = m_pendingUpdates.find(update.tileID);
200 if (it != m_pendingUpdates.end())
201 it->second.dirtyRect.unite(update.dirtyRect);
202 else {
203 m_pendingUpdates.add(update.tileID, update);
204 if (!m_tileUpdateTimer.isActive())
205 m_tileUpdateTimer.startOneShot(0);
206 }
207 break;
208 }
209 case DrawingAreaLegacyMessage::TakeSnapshot: {
210 IntSize targetSize;
211 IntRect contentsRect;
212
213 if (!arguments->decode(CoreIPC::Out(targetSize, contentsRect)))
214 return;
215
216 m_webPage->layoutIfNeeded();
217
218 contentsRect.intersect(IntRect(IntPoint::zero(), m_webPage->mainFrame()->coreFrame()->view()->contentsSize()));
219
220 float targetScale = float(targetSize.width()) / contentsRect.width();
221
222 UpdateChunk updateChunk(IntRect(IntPoint(contentsRect.x() * targetScale, contentsRect.y() * targetScale), targetSize));
223 paintIntoUpdateChunk(&updateChunk, targetScale);
224
225 WebProcess::shared().connection()->deprecatedSend(DrawingAreaProxyLegacyMessage::SnapshotTaken, m_webPage->pageID(), CoreIPC::In(updateChunk));
226 break;
227 }
228 default:
229 ASSERT_NOT_REACHED();
230 break;
231 }
232 }
233
234 } // namespace WebKit
235
236 #endif // TILED_BACKING_STORE
237