150b93d148fd98247e67772de16fde74c90e3e6e
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCLayerTreeHostImpl.cpp
1 /*
2  * Copyright (C) 2011 Google 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'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCLayerTreeHostImpl.h"
28
29 #include "Extensions3D.h"
30 #include "GraphicsContext3D.h"
31 #include "LayerRendererChromium.h"
32 #include "TraceEvent.h"
33 #include "cc/CCLayerTreeHost.h"
34 #include "cc/CCThreadTask.h"
35 #include <wtf/CurrentTime.h>
36
37 namespace WebCore {
38
39 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCSettings& settings, CCLayerTreeHostImplClient* client)
40 {
41     return adoptPtr(new CCLayerTreeHostImpl(settings, client));
42 }
43
44 CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTreeHostImplClient* client)
45     : m_client(client)
46     , m_sourceFrameNumber(-1)
47     , m_frameNumber(0)
48     , m_settings(settings)
49     , m_visible(true)
50     , m_haveWheelEventHandlers(false)
51     , m_pageScale(1)
52     , m_pageScaleDelta(1)
53     , m_sentPageScaleDelta(1)
54     , m_minPageScale(0)
55     , m_maxPageScale(0)
56     , m_pinchGestureActive(false)
57 {
58     ASSERT(CCProxy::isImplThread());
59 }
60
61 CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
62 {
63     ASSERT(CCProxy::isImplThread());
64     TRACE_EVENT("CCLayerTreeHostImpl::~CCLayerTreeHostImpl()", this, 0);
65     if (m_layerRenderer)
66         m_layerRenderer->close();
67 }
68
69 void CCLayerTreeHostImpl::beginCommit()
70 {
71 }
72
73 void CCLayerTreeHostImpl::commitComplete()
74 {
75     // Recompute max scroll position; must be after layer content bounds are
76     // updated.
77     updateMaxScrollPosition();
78 }
79
80 GraphicsContext3D* CCLayerTreeHostImpl::context()
81 {
82     return m_layerRenderer ? m_layerRenderer->context() : 0;
83 }
84
85 void CCLayerTreeHostImpl::animate(double frameBeginTimeMs)
86 {
87 }
88
89 void CCLayerTreeHostImpl::drawLayers()
90 {
91     TRACE_EVENT("CCLayerTreeHostImpl::drawLayers", this, 0);
92     ASSERT(m_layerRenderer);
93     if (m_layerRenderer->rootLayer())
94         m_layerRenderer->drawLayers();
95
96     ++m_frameNumber;
97 }
98
99 void CCLayerTreeHostImpl::finishAllRendering()
100 {
101     m_layerRenderer->finish();
102 }
103
104 bool CCLayerTreeHostImpl::isContextLost()
105 {
106     ASSERT(m_layerRenderer);
107     return m_layerRenderer->isContextLost();
108 }
109
110 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const
111 {
112     return m_layerRenderer->capabilities();
113 }
114
115 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
116 {
117     return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
118 }
119
120 void CCLayerTreeHostImpl::swapBuffers()
121 {
122     ASSERT(m_layerRenderer && !isContextLost());
123     m_layerRenderer->swapBuffers();
124 }
125
126 void CCLayerTreeHostImpl::onSwapBuffersComplete()
127 {
128     m_client->onSwapBuffersCompleteOnImplThread();
129 }
130
131 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
132 {
133     ASSERT(m_layerRenderer && !isContextLost());
134     m_layerRenderer->getFramebufferPixels(pixels, rect);
135 }
136
137 static CCLayerImpl* findScrollLayer(CCLayerImpl* layer)
138 {
139     if (!layer)
140         return 0;
141
142     if (layer->scrollable())
143         return layer;
144
145     for (size_t i = 0; i < layer->children().size(); ++i) {
146         CCLayerImpl* found = findScrollLayer(layer->children()[i].get());
147         if (found)
148             return found;
149     }
150
151     return 0;
152 }
153
154 void CCLayerTreeHostImpl::setRootLayer(PassRefPtr<CCLayerImpl> layer)
155 {
156     m_rootLayerImpl = layer;
157
158     // FIXME: Currently, this only finds the first scrollable layer.
159     m_scrollLayerImpl = findScrollLayer(m_rootLayerImpl.get());
160 }
161
162 void CCLayerTreeHostImpl::setVisible(bool visible)
163 {
164     if (m_visible == visible)
165         return;
166     m_visible = visible;
167
168     if (m_layerRenderer)
169         m_layerRenderer->setVisible(visible);
170 }
171
172 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D> context)
173 {
174     OwnPtr<LayerRendererChromium> layerRenderer;
175     layerRenderer = LayerRendererChromium::create(this, context);
176
177     // If creation failed, and we had asked for accelerated painting, disable accelerated painting
178     // and try creating the renderer again.
179     if (!layerRenderer && m_settings.acceleratePainting) {
180         m_settings.acceleratePainting = false;
181
182         layerRenderer = LayerRendererChromium::create(this, context);
183     }
184
185     if (m_layerRenderer)
186         m_layerRenderer->close();
187
188     m_layerRenderer = layerRenderer.release();
189     return m_layerRenderer;
190 }
191
192 void CCLayerTreeHostImpl::setViewport(const IntSize& viewportSize)
193 {
194     if (viewportSize == m_viewportSize)
195         return;
196
197     m_viewportSize = viewportSize;
198     updateMaxScrollPosition();
199     m_layerRenderer->viewportChanged();
200 }
201
202 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
203 {
204     if (!pageScale)
205         return;
206
207     if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
208         return;
209
210     m_minPageScale = minPageScale;
211     m_maxPageScale = maxPageScale;
212
213     float pageScaleChange = pageScale / m_pageScale;
214     m_pageScale = pageScale;
215     m_sentPageScaleDelta = 1;
216
217     // Clamp delta to limits and refresh display matrix.
218     setPageScaleDelta(m_pageScaleDelta);
219     applyPageScaleDeltaToScrollLayer();
220
221     adjustScrollsForPageScaleChange(pageScaleChange);
222 }
223
224 void CCLayerTreeHostImpl::adjustScrollsForPageScaleChange(float pageScaleChange)
225 {
226     if (pageScaleChange == 1)
227         return;
228
229     // We also need to convert impl-side scroll deltas to pageScale space.
230     if (m_scrollLayerImpl) {
231         IntSize scrollDelta = m_scrollLayerImpl->scrollDelta();
232         scrollDelta.scale(pageScaleChange);
233         m_scrollLayerImpl->setScrollDelta(scrollDelta);
234     }
235 }
236
237 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
238 {
239     // Clamp to the current min/max limits.
240     float finalMagnifyScale = m_pageScale * delta;
241     if (m_minPageScale && finalMagnifyScale < m_minPageScale)
242         delta = m_minPageScale / m_pageScale;
243     else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
244         delta = m_maxPageScale / m_pageScale;
245
246     if (delta == m_pageScaleDelta)
247         return;
248
249     m_pageScaleDelta = delta;
250
251     updateMaxScrollPosition();
252     applyPageScaleDeltaToScrollLayer();
253 }
254
255 void CCLayerTreeHostImpl::applyPageScaleDeltaToScrollLayer()
256 {
257     if (m_scrollLayerImpl)
258         m_scrollLayerImpl->setPageScaleDelta(m_pageScaleDelta * m_sentPageScaleDelta);
259 }
260
261 void CCLayerTreeHostImpl::updateMaxScrollPosition()
262 {
263     if (!m_scrollLayerImpl || !m_scrollLayerImpl->children().size())
264         return;
265
266     FloatSize viewBounds = m_viewportSize;
267     viewBounds.scale(1 / m_pageScaleDelta);
268
269     // TODO(aelias): Hardcoding the first child here is weird. Think of
270     // a cleaner way to get the contentBounds on the Impl side.
271     IntSize maxScroll = m_scrollLayerImpl->children()[0]->contentBounds() - expandedIntSize(viewBounds);
272     // The viewport may be larger than the contents in some cases, such as
273     // having a vertical scrollbar but no horizontal overflow.
274     maxScroll.clampNegativeToZero();
275
276     m_scrollLayerImpl->setMaxScrollPosition(maxScroll);
277
278     // TODO(aelias): Also update sublayers.
279 }
280
281 void CCLayerTreeHostImpl::setZoomAnimatorTransform(const TransformationMatrix& zoom)
282 {
283     if (!m_scrollLayerImpl)
284         return;
285
286     m_scrollLayerImpl->setZoomAnimatorTransform(zoom);
287 }
288
289 double CCLayerTreeHostImpl::currentTimeMs() const
290 {
291     return monotonicallyIncreasingTime() * 1000.0;
292 }
293
294 void CCLayerTreeHostImpl::setNeedsRedraw()
295 {
296     m_client->setNeedsRedrawOnImplThread();
297 }
298
299 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint&)
300 {
301     // TODO: Check for scrollable sublayers.
302     if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable())
303         return ScrollIgnored;
304
305     return ScrollStarted;
306 }
307
308 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
309 {
310     TRACE_EVENT("CCLayerTreeHostImpl::scrollBy", this, 0);
311     if (!m_scrollLayerImpl)
312         return;
313
314     m_scrollLayerImpl->scrollBy(scrollDelta);
315     m_client->setNeedsCommitOnImplThread();
316     m_client->setNeedsRedrawOnImplThread();
317 }
318
319 void CCLayerTreeHostImpl::scrollEnd()
320 {
321 }
322
323 bool CCLayerTreeHostImpl::haveWheelEventHandlers()
324 {
325     return m_haveWheelEventHandlers;
326 }
327
328 void CCLayerTreeHostImpl::pinchGestureBegin()
329 {
330     m_pinchGestureActive = true;
331 }
332
333 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
334                                              const IntPoint& anchor)
335 {
336     TRACE_EVENT("CCLayerTreeHostImpl::pinchGestureUpdate", this, 0);
337
338     if (magnifyDelta == 1.0)
339         return;
340     if (!m_scrollLayerImpl)
341         return;
342
343     // Keep the center-of-pinch anchor specified by (x, y) in a stable
344     // position over the course of the magnify.
345     FloatPoint prevScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
346     setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
347     FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
348
349     FloatSize move = prevScaleAnchor - newScaleAnchor;
350
351     m_scrollLayerImpl->scrollBy(roundedIntSize(move));
352     m_client->setNeedsCommitOnImplThread();
353     m_client->setNeedsRedrawOnImplThread();
354 }
355
356 void CCLayerTreeHostImpl::pinchGestureEnd()
357 {
358     m_pinchGestureActive = false;
359
360     m_client->setNeedsCommitOnImplThread();
361 }
362
363 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
364 {
365     OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
366     bool didMove = m_scrollLayerImpl && (!m_scrollLayerImpl->scrollDelta().isZero() || m_pageScaleDelta != 1.0f);
367     if (!didMove || m_pinchGestureActive) {
368         m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
369         return scrollInfo.release();
370     }
371
372     m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
373     m_pageScale = m_pageScale * m_sentPageScaleDelta;
374     setPageScaleDelta(1);
375
376     // FIXME: track scrolls from layers other than the root
377     CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
378     scroll.layerId = m_scrollLayerImpl->id();
379     scroll.scrollDelta = m_scrollLayerImpl->scrollDelta();
380     scrollInfo->scrolls.append(scroll);
381
382     m_scrollLayerImpl->setScrollPosition(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta());
383     m_scrollLayerImpl->setPosition(m_scrollLayerImpl->position() - m_scrollLayerImpl->scrollDelta());
384     m_scrollLayerImpl->setSentScrollDelta(m_scrollLayerImpl->scrollDelta());
385     m_scrollLayerImpl->setScrollDelta(IntSize());
386
387     adjustScrollsForPageScaleChange(m_sentPageScaleDelta);
388
389     return scrollInfo.release();
390 }
391
392 }