blob: eca5aa203d8de2a25d5f1ddb881dc5e600ccf115 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6
[email protected]55a124d02012-10-22 03:07:137#include "cc/layer_tree_host_impl.h"
[email protected]94f206c12012-08-25 00:09:148
[email protected]ad5d1422012-10-19 13:40:299#include "base/basictypes.h"
[email protected]4456eee22012-10-19 18:16:3810#include "base/debug/trace_event.h"
[email protected]aa0a9d32012-10-24 01:58:1011#include "cc/append_quads_data.h"
12#include "cc/damage_tracker.h"
13#include "cc/debug_rect_history.h"
14#include "cc/delay_based_time_source.h"
15#include "cc/font_atlas.h"
16#include "cc/frame_rate_counter.h"
[email protected]c4040a522012-10-21 15:01:4017#include "cc/gl_renderer.h"
[email protected]d50c6862012-10-23 02:08:3118#include "cc/heads_up_display_layer_impl.h"
19#include "cc/layer_iterator.h"
20#include "cc/layer_tree_host.h"
21#include "cc/layer_tree_host_common.h"
[email protected]55a124d02012-10-22 03:07:1322#include "cc/math_util.h"
23#include "cc/overdraw_metrics.h"
24#include "cc/page_scale_animation.h"
25#include "cc/prioritized_texture_manager.h"
26#include "cc/render_pass_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4027#include "cc/rendering_stats.h"
28#include "cc/scrollbar_animation_controller.h"
29#include "cc/scrollbar_layer_impl.h"
30#include "cc/settings.h"
[email protected]4456eee22012-10-19 18:16:3831#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4032#include "cc/software_renderer.h"
[email protected]a8461d82012-10-16 21:11:1433#include "cc/texture_uploader.h"
[email protected]94f206c12012-08-25 00:09:1434#include <wtf/CurrentTime.h>
[email protected]f8ad8342012-09-27 20:07:0235#include <algorithm>
[email protected]94f206c12012-08-25 00:09:1436
37using WebKit::WebTransformationMatrix;
38
39namespace {
40
[email protected]96baf3e2012-10-22 23:09:5541void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1442{
43 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5544 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1445 return;
46 }
47
[email protected]96baf3e2012-10-22 23:09:5548 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1449}
50
51} // namespace
52
[email protected]9c88e562012-09-14 22:21:3053namespace cc {
[email protected]94f206c12012-08-25 00:09:1454
[email protected]96baf3e2012-10-22 23:09:5555PinchZoomViewport::PinchZoomViewport()
[email protected]1c0c9bc2012-10-08 22:41:4856 : m_pageScaleFactor(1)
57 , m_pageScaleDelta(1)
58 , m_sentPageScaleDelta(1)
59 , m_minPageScaleFactor(0)
60 , m_maxPageScaleFactor(0)
61{
62}
63
[email protected]96baf3e2012-10-22 23:09:5564float PinchZoomViewport::totalPageScaleFactor() const
[email protected]1c0c9bc2012-10-08 22:41:4865{
66 return m_pageScaleFactor * m_pageScaleDelta;
67}
68
[email protected]96baf3e2012-10-22 23:09:5569void PinchZoomViewport::setPageScaleDelta(float delta)
[email protected]1c0c9bc2012-10-08 22:41:4870{
71 // Clamp to the current min/max limits.
72 float totalPageScaleFactor = m_pageScaleFactor * delta;
73 if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
74 delta = m_minPageScaleFactor / m_pageScaleFactor;
75 else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
76 delta = m_maxPageScaleFactor / m_pageScaleFactor;
77
78 if (delta == m_pageScaleDelta)
79 return;
80
81 m_pageScaleDelta = delta;
82}
83
[email protected]96baf3e2012-10-22 23:09:5584bool PinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:4885{
[email protected]1d993172012-10-18 18:15:0486 DCHECK(pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:4887
88 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
89 return false;
90
91 m_minPageScaleFactor = minPageScaleFactor;
92 m_maxPageScaleFactor = maxPageScaleFactor;
93
94 m_pageScaleFactor = pageScaleFactor;
95 return true;
96}
97
[email protected]96baf3e2012-10-22 23:09:5598FloatRect PinchZoomViewport::bounds() const
[email protected]1c0c9bc2012-10-08 22:41:4899{
100 FloatSize scaledViewportSize = m_layoutViewportSize;
101 scaledViewportSize.scale(1 / totalPageScaleFactor());
102
103 FloatRect bounds(FloatPoint(0, 0), scaledViewportSize);
104 bounds.setLocation(m_pinchViewportScrollDelta);
105
106 return bounds;
107}
108
[email protected]96baf3e2012-10-22 23:09:55109FloatSize PinchZoomViewport::applyScroll(FloatSize& delta)
[email protected]1c0c9bc2012-10-08 22:41:48110{
111 FloatSize overflow;
112 FloatRect pinchedBounds = bounds();
113
114 pinchedBounds.move(delta);
115 if (pinchedBounds.x() < 0) {
116 overflow.setWidth(pinchedBounds.x());
117 pinchedBounds.setX(0);
118 }
119
120 if (pinchedBounds.y() < 0) {
121 overflow.setHeight(pinchedBounds.y());
122 pinchedBounds.setY(0);
123 }
124
125 if (pinchedBounds.maxX() > m_layoutViewportSize.width()) {
126 overflow.setWidth(
127 pinchedBounds.maxX() - m_layoutViewportSize.width());
128 pinchedBounds.move(
129 m_layoutViewportSize.width() - pinchedBounds.maxX(), 0);
130 }
131
132 if (pinchedBounds.maxY() > m_layoutViewportSize.height()) {
133 overflow.setHeight(
134 pinchedBounds.maxY() - m_layoutViewportSize.height());
135 pinchedBounds.move(
136 0, m_layoutViewportSize.height() - pinchedBounds.maxY());
137 }
138 m_pinchViewportScrollDelta = pinchedBounds.location();
139
140 return overflow;
141}
142
[email protected]96baf3e2012-10-22 23:09:55143WebTransformationMatrix PinchZoomViewport::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:48144{
145 WebTransformationMatrix transform;
146 transform.scale(m_pageScaleDelta);
147
148 // If the pinch state is applied in the impl, then push it to the
149 // impl transform, otherwise the scale is handled by WebCore.
[email protected]65bfd9972012-10-19 03:39:37150 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48151 transform.scale(m_pageScaleFactor);
152 transform.translate(-m_pinchViewportScrollDelta.x(),
153 -m_pinchViewportScrollDelta.y());
154 }
155
156 return transform;
157}
158
[email protected]96baf3e2012-10-22 23:09:55159class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14160public:
[email protected]96baf3e2012-10-22 23:09:55161 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14162 {
[email protected]96baf3e2012-10-22 23:09:55163 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:14164 }
[email protected]96baf3e2012-10-22 23:09:55165 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:14166 {
167 m_timeSource->setClient(0);
168 m_timeSource->setActive(false);
169 }
170
171 virtual void onTimerTick() OVERRIDE
172 {
173 // FIXME: We require that animate be called on the impl thread. This
174 // avoids asserts in single threaded mode. Ideally background ticking
175 // would be handled by the proxy/scheduler and this could be removed.
176 DebugScopedSetImplThread impl;
177
178 m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
179 }
180
181 void setActive(bool active)
182 {
183 if (active != m_timeSource->active())
184 m_timeSource->setActive(active);
185 }
186
187private:
[email protected]96baf3e2012-10-22 23:09:55188 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14189 : m_layerTreeHostImpl(layerTreeHostImpl)
190 , m_timeSource(timeSource)
191 {
192 m_timeSource->setClient(this);
193 }
194
[email protected]96baf3e2012-10-22 23:09:55195 LayerTreeHostImpl* m_layerTreeHostImpl;
196 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20197
[email protected]96baf3e2012-10-22 23:09:55198 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14199};
200
[email protected]96baf3e2012-10-22 23:09:55201LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10202{
203}
204
[email protected]96baf3e2012-10-22 23:09:55205LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10206{
207}
208
[email protected]96baf3e2012-10-22 23:09:55209scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client)
[email protected]94f206c12012-08-25 00:09:14210{
[email protected]96baf3e2012-10-22 23:09:55211 return make_scoped_ptr(new LayerTreeHostImpl(settings, client));
[email protected]94f206c12012-08-25 00:09:14212}
213
[email protected]96baf3e2012-10-22 23:09:55214LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client)
[email protected]94f206c12012-08-25 00:09:14215 : m_client(client)
216 , m_sourceFrameNumber(-1)
217 , m_rootScrollLayerImpl(0)
218 , m_currentlyScrollingLayerImpl(0)
219 , m_hudLayerImpl(0)
220 , m_scrollingLayerIdFromPreviousTree(-1)
[email protected]31bfe272012-10-19 18:49:52221 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14222 , m_settings(settings)
223 , m_deviceScaleFactor(1)
224 , m_visible(true)
225 , m_contentsTexturesPurged(false)
[email protected]96baf3e2012-10-22 23:09:55226 , m_managedMemoryPolicy(PrioritizedTextureManager::defaultMemoryAllocationLimit(),
227 PriorityCalculator::allowEverythingCutoff(),
[email protected]a0a00842012-10-22 22:50:28228 0,
[email protected]96baf3e2012-10-22 23:09:55229 PriorityCalculator::allowNothingCutoff())
[email protected]94f206c12012-08-25 00:09:14230 , m_backgroundColor(0)
231 , m_hasTransparentBackground(false)
232 , m_needsAnimateLayers(false)
233 , m_pinchGestureActive(false)
[email protected]96baf3e2012-10-22 23:09:55234 , m_fpsCounter(FrameRateCounter::create())
235 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27236 , m_numImplThreadScrolls(0)
237 , m_numMainThreadScrolls(0)
[email protected]94f206c12012-08-25 00:09:14238{
[email protected]96baf3e2012-10-22 23:09:55239 DCHECK(Proxy::isImplThread());
[email protected]94f206c12012-08-25 00:09:14240 didVisibilityChange(this, m_visible);
241}
242
[email protected]96baf3e2012-10-22 23:09:55243LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14244{
[email protected]96baf3e2012-10-22 23:09:55245 DCHECK(Proxy::isImplThread());
246 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14247
248 if (m_rootLayerImpl)
249 clearRenderSurfaces();
250}
251
[email protected]96baf3e2012-10-22 23:09:55252void LayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14253{
254}
255
[email protected]96baf3e2012-10-22 23:09:55256void LayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14257{
[email protected]96baf3e2012-10-22 23:09:55258 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
[email protected]94f206c12012-08-25 00:09:14259 // Recompute max scroll position; must be after layer content bounds are
260 // updated.
261 updateMaxScrollPosition();
[email protected]3d21e022012-10-25 20:03:08262 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14263}
264
[email protected]96baf3e2012-10-22 23:09:55265bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14266{
[email protected]8db2213c2012-09-05 22:08:21267 // Note: If you are changing this function or any other function that might
268 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
269 // in the proper places and update the notifyIfCanDrawChanged test.
270
[email protected]94f206c12012-08-25 00:09:14271 if (!m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:55272 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14273 return false;
274 }
275 if (deviceViewportSize().isEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55276 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14277 return false;
278 }
279 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55280 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14281 return false;
282 }
283 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55284 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14285 return false;
286 }
287 return true;
288}
289
[email protected]96baf3e2012-10-22 23:09:55290GraphicsContext* LayerTreeHostImpl::context() const
[email protected]94f206c12012-08-25 00:09:14291{
292 return m_context.get();
293}
294
[email protected]96baf3e2012-10-22 23:09:55295void LayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
[email protected]94f206c12012-08-25 00:09:14296{
297 animatePageScale(monotonicTime);
298 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14299 animateScrollbars(monotonicTime);
300}
301
[email protected]96baf3e2012-10-22 23:09:55302void LayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
[email protected]94f206c12012-08-25 00:09:14303{
304 if (!m_rootScrollLayerImpl)
305 return;
306
307 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:48308 scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta());
309 float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor();
[email protected]94f206c12012-08-25 00:09:14310 IntSize scaledContentSize = contentSize();
[email protected]1c0c9bc2012-10-08 22:41:48311 scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta());
[email protected]94f206c12012-08-25 00:09:14312
[email protected]96baf3e2012-10-22 23:09:55313 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime);
[email protected]94f206c12012-08-25 00:09:14314
315 if (anchorPoint) {
316 IntSize windowAnchor(targetPosition);
317 windowAnchor.scale(scaleTotal / pageScale);
318 windowAnchor -= scrollTotal;
319 m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
320 } else
321 m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
322
323 m_client->setNeedsRedrawOnImplThread();
324 m_client->setNeedsCommitOnImplThread();
325}
326
[email protected]96baf3e2012-10-22 23:09:55327void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14328{
329 m_client->setNeedsRedrawOnImplThread();
330}
331
[email protected]96baf3e2012-10-22 23:09:55332void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14333{
334 // For now, we use damage tracking to compute a global scissor. To do this, we must
335 // compute all damage tracking before drawing anything, so that we know the root
336 // damage rect. The root damage rect is then used to scissor each surface.
337
338 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55339 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
340 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04341 DCHECK(renderSurface);
[email protected]4000abf2012-10-23 04:45:45342 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter());
[email protected]94f206c12012-08-25 00:09:14343 }
344}
345
[email protected]96baf3e2012-10-22 23:09:55346void LayerTreeHostImpl::updateRootScrollLayerImplTransform()
[email protected]1c0c9bc2012-10-08 22:41:48347{
348 if (m_rootScrollLayerImpl) {
349 m_rootScrollLayerImpl->setImplTransform(implTransform());
350 }
351}
352
[email protected]96baf3e2012-10-22 23:09:55353void LayerTreeHostImpl::calculateRenderSurfaceLayerList(LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14354{
[email protected]1d993172012-10-18 18:15:04355 DCHECK(renderSurfaceLayerList.empty());
356 DCHECK(m_rootLayerImpl);
357 DCHECK(m_renderer); // For maxTextureSize.
[email protected]94f206c12012-08-25 00:09:14358
359 {
[email protected]1c0c9bc2012-10-08 22:41:48360 updateRootScrollLayerImplTransform();
361
[email protected]96baf3e2012-10-22 23:09:55362 TRACE_EVENT0("cc", "LayerTreeHostImpl::calcDrawEtc");
[email protected]518ee582012-10-24 18:29:44363 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
364 LayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14365
366 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
367 }
368}
369
[email protected]96baf3e2012-10-22 23:09:55370void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16371{
[email protected]96baf3e2012-10-22 23:09:55372 RenderPass* pass = renderPass.get();
[email protected]f8ad8342012-09-27 20:07:02373 renderPasses.push_back(pass);
[email protected]87cea5372012-09-26 18:59:56374 renderPassesById.set(pass->id(), renderPass.Pass());
[email protected]467b3612012-08-28 07:41:16375}
376
[email protected]96baf3e2012-10-22 23:09:55377bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14378{
[email protected]1d993172012-10-18 18:15:04379 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14380
381 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
382
[email protected]96baf3e2012-10-22 23:09:55383 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14384
385 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14386 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55387 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16388 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14389 }
390
391 bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
[email protected]96baf3e2012-10-22 23:09:55392 OcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14393 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
394
395 if (settings().showOccludingRects)
396 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
397
398 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
[email protected]96baf3e2012-10-22 23:09:55399 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14400
401 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
402 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
403 // in the future.
404 bool drawFrame = true;
405
[email protected]96baf3e2012-10-22 23:09:55406 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
407 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
408 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
409 RenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14410
411 occlusionTracker.enterLayer(it);
412
[email protected]96baf3e2012-10-22 23:09:55413 AppendQuadsData appendQuadsData(targetRenderPass->id());
[email protected]89228202012-08-29 03:20:30414
[email protected]94f206c12012-08-25 00:09:14415 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55416 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
417 RenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]89228202012-08-29 03:20:30418 targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14419 } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) {
420 bool hasOcclusionFromOutsideTargetSurface;
[email protected]89228202012-08-29 03:20:30421 if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface))
422 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
423 else {
[email protected]94f206c12012-08-25 00:09:14424 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47425 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57426
427 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55428 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]7d929c02012-09-20 17:26:57429 while (frame.renderPassesById.contains(contributingRenderPassId)) {
[email protected]96baf3e2012-10-22 23:09:55430 RenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]7d929c02012-09-20 17:26:57431
[email protected]96baf3e2012-10-22 23:09:55432 AppendQuadsData appendQuadsData(renderPass->id());
[email protected]7d929c02012-09-20 17:26:57433 renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
434
435 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
436 }
437 }
438
[email protected]89228202012-08-29 03:20:30439 targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14440 }
441 }
442
[email protected]89228202012-08-29 03:20:30443 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
444 targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true);
445
446 if (appendQuadsData.hadMissingTiles) {
[email protected]94f206c12012-08-25 00:09:14447 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]65bfd9972012-10-19 03:39:37448 if (layerHasAnimatingTransform || Settings::jankInsteadOfCheckerboard())
[email protected]94f206c12012-08-25 00:09:14449 drawFrame = false;
450 }
451
452 occlusionTracker.leaveLayer(it);
453 }
454
[email protected]1d993172012-10-18 18:15:04455#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14456 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]1d993172012-10-18 18:15:04457 for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j)
458 DCHECK(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0);
459 DCHECK(frame.renderPassesById.contains(frame.renderPasses[i]->id()));
[email protected]94f206c12012-08-25 00:09:14460 }
461#endif
462
463 if (!m_hasTransparentBackground) {
[email protected]f8ad8342012-09-27 20:07:02464 frame.renderPasses.back()->setHasTransparentBackground(false);
465 frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14466 }
467
468 if (drawFrame)
469 occlusionTracker.overdrawMetrics().recordMetrics(this);
470
471 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
472 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
473 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
474
475 return drawFrame;
476}
477
[email protected]96baf3e2012-10-22 23:09:55478void LayerTreeHostImpl::animateLayersRecursive(LayerImpl* current, double monotonicTime, double wallClockTime, AnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
[email protected]94f206c12012-08-25 00:09:14479{
480 bool subtreeNeedsAnimateLayers = false;
481
[email protected]96baf3e2012-10-22 23:09:55482 LayerAnimationController* currentController = current->layerAnimationController();
[email protected]94f206c12012-08-25 00:09:14483
484 bool hadActiveAnimation = currentController->hasActiveAnimation();
485 currentController->animate(monotonicTime, events);
486 bool startedAnimation = events->size() > 0;
487
488 // We animated if we either ticked a running animation, or started a new animation.
489 if (hadActiveAnimation || startedAnimation)
490 didAnimate = true;
491
492 // If the current controller still has an active animation, we must continue animating layers.
493 if (currentController->hasActiveAnimation())
494 subtreeNeedsAnimateLayers = true;
495
496 for (size_t i = 0; i < current->children().size(); ++i) {
497 bool childNeedsAnimateLayers = false;
[email protected]0920e24f2012-09-20 03:34:03498 animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:14499 if (childNeedsAnimateLayers)
500 subtreeNeedsAnimateLayers = true;
501 }
502
503 needsAnimateLayers = subtreeNeedsAnimateLayers;
504}
505
[email protected]96baf3e2012-10-22 23:09:55506void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14507{
508 // Lazily create the timeSource adapter so that we can vary the interval for testing.
509 if (!m_timeSourceClientAdapter)
[email protected]96baf3e2012-10-22 23:09:55510 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), Proxy::currentThread()));
[email protected]94f206c12012-08-25 00:09:14511
512 m_timeSourceClientAdapter->setActive(enabled);
513}
514
[email protected]96baf3e2012-10-22 23:09:55515IntSize LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14516{
517 // TODO(aelias): Hardcoding the first child here is weird. Think of
518 // a cleaner way to get the contentBounds on the Impl side.
519 if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
520 return IntSize();
521 return m_rootScrollLayerImpl->children()[0]->contentBounds();
522}
523
[email protected]96baf3e2012-10-22 23:09:55524static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14525{
[email protected]96baf3e2012-10-22 23:09:55526 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]1d993172012-10-18 18:15:04527 DCHECK(it != frame.renderPassesById.end());
[email protected]87cea5372012-09-26 18:59:56528 return it->second;
[email protected]94f206c12012-08-25 00:09:14529}
530
[email protected]96baf3e2012-10-22 23:09:55531static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14532{
[email protected]96baf3e2012-10-22 23:09:55533 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
534 RenderPassList& renderPasses = frame.renderPasses;
535 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14536
537 // The pass was already removed by another quad - probably the original, and we are the replica.
[email protected]f8ad8342012-09-27 20:07:02538 if (toRemove == renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14539 return;
540
[email protected]96baf3e2012-10-22 23:09:55541 const RenderPass* removedPass = *toRemove;
[email protected]f8ad8342012-09-27 20:07:02542 frame.renderPasses.erase(toRemove);
[email protected]94f206c12012-08-25 00:09:14543
544 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]96baf3e2012-10-22 23:09:55545 const QuadList& quadList = removedPass->quadList();
546 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14547 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55548 DrawQuad* currentQuad = (*quadListIterator);
549 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14550 continue;
551
[email protected]96baf3e2012-10-22 23:09:55552 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::materialCast(currentQuad)->renderPassId();
[email protected]94f206c12012-08-25 00:09:14553 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
554 }
555}
556
[email protected]96baf3e2012-10-22 23:09:55557bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14558{
[email protected]1fea8142012-10-20 04:12:41559 return quad.contentsChangedSinceLastFrame().IsEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
[email protected]94f206c12012-08-25 00:09:14560}
561
[email protected]96baf3e2012-10-22 23:09:55562bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14563{
[email protected]96baf3e2012-10-22 23:09:55564 const RenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame);
565 const RenderPassList& renderPasses = frame.renderPasses;
566 RenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
[email protected]94f206c12012-08-25 00:09:14567
[email protected]f8ad8342012-09-27 20:07:02568 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
[email protected]94f206c12012-08-25 00:09:14569 if (renderPassAlreadyRemoved)
570 return false;
571
572 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]96baf3e2012-10-22 23:09:55573 const QuadList& quadList = (*foundPass)->quadList();
574 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
575 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14576
[email protected]96baf3e2012-10-22 23:09:55577 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14578 return false;
579
[email protected]96baf3e2012-10-22 23:09:55580 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame);
581 RenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
[email protected]f8ad8342012-09-27 20:07:02582 if (foundContributingPass != renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14583 return false;
584 }
585 return true;
586}
587
588// Defined for linking tests.
[email protected]96baf3e2012-10-22 23:09:55589template void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
590template void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14591
592// static
593template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55594void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14595{
596 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55597 const RenderPass* currentPass = frame.renderPasses[it];
598 const QuadList& quadList = currentPass->quadList();
599 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14600
601 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55602 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14603
[email protected]96baf3e2012-10-22 23:09:55604 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14605 continue;
606
[email protected]96baf3e2012-10-22 23:09:55607 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14608 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
609 continue;
610
611 // We are changing the vector in the middle of iteration. Because we
612 // delete render passes that draw into the current pass, we are
613 // guaranteed that any data from the iterator to the end will not
614 // change. So, capture the iterator position from the end of the
615 // list, and restore it after the change.
616 int positionFromEnd = frame.renderPasses.size() - it;
617 removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame);
618 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04619 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14620 }
621 }
622}
623
[email protected]96baf3e2012-10-22 23:09:55624bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14625{
[email protected]96baf3e2012-10-22 23:09:55626 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]1d993172012-10-18 18:15:04627 DCHECK(canDraw());
[email protected]94f206c12012-08-25 00:09:14628
629 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
630 frame.renderPasses.clear();
631 frame.renderPassesById.clear();
632 frame.renderSurfaceLayerList->clear();
633 frame.willDrawLayers.clear();
634
635 if (!calculateRenderPasses(frame))
636 return false;
637
638 // If we return true, then we expect drawLayers() to be called before this function is called again.
639 return true;
640}
641
[email protected]96baf3e2012-10-22 23:09:55642void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14643{
[email protected]a0a00842012-10-22 22:50:28644 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
645 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
646 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
[email protected]b1969fa2012-10-17 20:16:29647 if (evictedResources) {
648 setContentsTexturesPurged();
649 m_client->setNeedsCommitOnImplThread();
650 m_client->onCanDrawStateChanged(canDraw());
651 }
[email protected]3d21e022012-10-25 20:03:08652 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14653}
654
[email protected]96baf3e2012-10-22 23:09:55655void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14656{
[email protected]a0a00842012-10-22 22:50:28657 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14658 return;
[email protected]a0a00842012-10-22 22:50:28659 m_managedMemoryPolicy = policy;
660 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
661 // We always need to commit after changing the memory policy because the new
662 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14663 m_client->setNeedsCommitOnImplThread();
664}
665
[email protected]96baf3e2012-10-22 23:09:55666void LayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
[email protected]94f206c12012-08-25 00:09:14667{
668 m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds);
669}
670
[email protected]96baf3e2012-10-22 23:09:55671void LayerTreeHostImpl::drawLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14672{
[email protected]96baf3e2012-10-22 23:09:55673 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04674 DCHECK(canDraw());
675 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14676
677 // FIXME: use the frame begin time from the overall compositor scheduler.
678 // This value is currently inaccessible because it is up in Chromium's
679 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21680 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14681
682 if (m_settings.showDebugRects())
683 m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
684
685 // Because the contents of the HUD depend on everything else in the frame, the contents
686 // of its texture are updated as the last thing before the frame is drawn.
687 if (m_hudLayerImpl)
688 m_hudLayerImpl->updateHudTexture(m_resourceProvider.get());
689
690 m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
691
692 // Once a RenderPass has been drawn, its damage should be cleared in
693 // case the RenderPass will be reused next frame.
694 for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
695 frame.renderPasses[i]->setDamageRect(FloatRect());
696
697 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
698 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
699 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
700 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
701}
702
[email protected]96baf3e2012-10-22 23:09:55703void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14704{
705 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
706 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52707
708 // Once all layers have been drawn, pending texture uploads should no
709 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09710 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14711}
712
[email protected]96baf3e2012-10-22 23:09:55713void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14714{
715 if (m_renderer)
716 m_renderer->finish();
717}
718
[email protected]96baf3e2012-10-22 23:09:55719bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14720{
721 return m_renderer && m_renderer->isContextLost();
722}
723
[email protected]96baf3e2012-10-22 23:09:55724const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14725{
726 return m_renderer->capabilities();
727}
728
[email protected]96baf3e2012-10-22 23:09:55729bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14730{
[email protected]1d993172012-10-18 18:15:04731 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14732
733 m_fpsCounter->markEndOfFrame();
734 return m_renderer->swapBuffers();
735}
736
[email protected]96baf3e2012-10-22 23:09:55737const IntSize& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10738{
739 return m_deviceViewportSize;
740}
741
[email protected]96baf3e2012-10-22 23:09:55742const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10743{
744 return m_settings;
745}
746
[email protected]96baf3e2012-10-22 23:09:55747void LayerTreeHostImpl::didLoseContext()
[email protected]94f206c12012-08-25 00:09:14748{
749 m_client->didLoseContextOnImplThread();
750}
751
[email protected]96baf3e2012-10-22 23:09:55752void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14753{
754 m_client->onSwapBuffersCompleteOnImplThread();
755}
756
[email protected]96baf3e2012-10-22 23:09:55757void LayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
[email protected]94f206c12012-08-25 00:09:14758{
[email protected]1d993172012-10-18 18:15:04759 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14760 m_renderer->getFramebufferPixels(pixels, rect);
761}
762
[email protected]96baf3e2012-10-22 23:09:55763static LayerImpl* findRootScrollLayer(LayerImpl* layer)
[email protected]94f206c12012-08-25 00:09:14764{
765 if (!layer)
766 return 0;
767
768 if (layer->scrollable())
769 return layer;
770
771 for (size_t i = 0; i < layer->children().size(); ++i) {
[email protected]96baf3e2012-10-22 23:09:55772 LayerImpl* found = findRootScrollLayer(layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:14773 if (found)
774 return found;
775 }
776
777 return 0;
778}
779
780// Content layers can be either directly scrollable or contained in an outer
781// scrolling layer which applies the scroll transform. Given a content layer,
782// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55783static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14784{
785 if (!layerImpl)
786 return 0;
787
788 if (layerImpl->scrollable())
789 return layerImpl;
790
791 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
792 return layerImpl->parent();
793
794 return 0;
795}
796
[email protected]96baf3e2012-10-22 23:09:55797void LayerTreeHostImpl::setRootLayer(scoped_ptr<LayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:14798{
[email protected]e0bd43a2012-10-12 16:54:21799 m_rootLayerImpl = layer.Pass();
[email protected]94f206c12012-08-25 00:09:14800 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
801 m_currentlyScrollingLayerImpl = 0;
802
803 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
[email protected]96baf3e2012-10-22 23:09:55804 m_currentlyScrollingLayerImpl = LayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
[email protected]94f206c12012-08-25 00:09:14805
806 m_scrollingLayerIdFromPreviousTree = -1;
[email protected]8db2213c2012-09-05 22:08:21807
808 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14809}
810
[email protected]96baf3e2012-10-22 23:09:55811scoped_ptr<LayerImpl> LayerTreeHostImpl::detachLayerTree()
[email protected]94f206c12012-08-25 00:09:14812{
813 // Clear all data structures that have direct references to the layer tree.
814 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
815 m_currentlyScrollingLayerImpl = 0;
816 m_renderSurfaceLayerList.clear();
817
[email protected]e0bd43a2012-10-12 16:54:21818 return m_rootLayerImpl.Pass();
[email protected]94f206c12012-08-25 00:09:14819}
820
[email protected]96baf3e2012-10-22 23:09:55821void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14822{
[email protected]96baf3e2012-10-22 23:09:55823 DCHECK(Proxy::isImplThread());
[email protected]94f206c12012-08-25 00:09:14824
825 if (m_visible == visible)
826 return;
827 m_visible = visible;
828 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:28829 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:14830
831 if (!m_renderer)
832 return;
833
834 m_renderer->setVisible(visible);
835
836 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
837}
838
[email protected]96baf3e2012-10-22 23:09:55839bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<GraphicsContext> context)
[email protected]94f206c12012-08-25 00:09:14840{
[email protected]be3181652012-09-25 13:02:13841 // Since we will create a new resource provider, we cannot continue to use
842 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
843 // before we destroy the old resource provider.
[email protected]94f206c12012-08-25 00:09:14844 if (m_rootLayerImpl) {
845 clearRenderSurfaces();
846 sendDidLoseContextRecursive(m_rootLayerImpl.get());
847 }
[email protected]be3181652012-09-25 13:02:13848 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47849 m_renderer.reset();
[email protected]a7aa5562012-10-17 14:12:44850 m_resourceProvider.reset();
[email protected]e28efacd2012-10-06 17:07:49851 m_context.reset();
[email protected]94f206c12012-08-25 00:09:14852
[email protected]be3181652012-09-25 13:02:13853 if (!context->bindToClient(this))
854 return false;
855
[email protected]96baf3e2012-10-22 23:09:55856 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(context.get());
[email protected]be3181652012-09-25 13:02:13857 if (!resourceProvider)
858 return false;
859
860 if (context->context3D())
[email protected]96baf3e2012-10-22 23:09:55861 m_renderer = GLRenderer::create(this, resourceProvider.get());
[email protected]be3181652012-09-25 13:02:13862 else if (context->softwareDevice())
[email protected]96baf3e2012-10-22 23:09:55863 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), context->softwareDevice());
[email protected]be3181652012-09-25 13:02:13864 if (!m_renderer)
865 return false;
866
[email protected]a7aa5562012-10-17 14:12:44867 m_resourceProvider = resourceProvider.Pass();
[email protected]e28efacd2012-10-06 17:07:49868 m_context = context.Pass();
[email protected]94f206c12012-08-25 00:09:14869
[email protected]be3181652012-09-25 13:02:13870 if (!m_visible)
871 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:14872
[email protected]8db2213c2012-09-05 22:08:21873 m_client->onCanDrawStateChanged(canDraw());
874
[email protected]be3181652012-09-25 13:02:13875 return true;
[email protected]94f206c12012-08-25 00:09:14876}
877
[email protected]96baf3e2012-10-22 23:09:55878void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:09879{
880 m_contentsTexturesPurged = true;
881 m_client->onCanDrawStateChanged(canDraw());
882}
883
[email protected]96baf3e2012-10-22 23:09:55884void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:21885{
886 m_contentsTexturesPurged = false;
887 m_client->onCanDrawStateChanged(canDraw());
888}
889
[email protected]96baf3e2012-10-22 23:09:55890void LayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:14891{
892 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
893 return;
894
895 m_layoutViewportSize = layoutViewportSize;
896 m_deviceViewportSize = deviceViewportSize;
897
[email protected]1c0c9bc2012-10-08 22:41:48898 m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
899
[email protected]94f206c12012-08-25 00:09:14900 updateMaxScrollPosition();
901
902 if (m_renderer)
903 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:21904
905 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14906}
907
[email protected]96baf3e2012-10-22 23:09:55908static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:14909{
910 if (!layerImpl)
911 return;
912
913 if (layerImpl->scrollable()) {
914 // We need to convert impl-side scroll deltas to pageScale space.
915 FloatSize scrollDelta = layerImpl->scrollDelta();
916 scrollDelta.scale(pageScaleChange);
917 layerImpl->setScrollDelta(scrollDelta);
918 }
919
920 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:03921 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:14922}
923
[email protected]96baf3e2012-10-22 23:09:55924void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:14925{
926 if (deviceScaleFactor == m_deviceScaleFactor)
927 return;
928 m_deviceScaleFactor = deviceScaleFactor;
[email protected]c0dd24c2012-08-30 23:25:27929
930 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14931}
932
[email protected]96baf3e2012-10-22 23:09:55933float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:14934{
[email protected]1c0c9bc2012-10-08 22:41:48935 return m_pinchZoomViewport.pageScaleFactor();
936}
[email protected]94f206c12012-08-25 00:09:14937
[email protected]96baf3e2012-10-22 23:09:55938void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:48939{
940 if (!pageScaleFactor)
941 return;
[email protected]94f206c12012-08-25 00:09:14942
[email protected]1c0c9bc2012-10-08 22:41:48943 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
944 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:14945
[email protected]65bfd9972012-10-19 03:39:37946 if (!Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48947 if (pageScaleChange != 1)
948 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
949 }
[email protected]94f206c12012-08-25 00:09:14950
951 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:48952 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
953 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:14954}
955
[email protected]96baf3e2012-10-22 23:09:55956void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:14957{
[email protected]1c0c9bc2012-10-08 22:41:48958 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:14959
960 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14961}
962
[email protected]96baf3e2012-10-22 23:09:55963void LayerTreeHostImpl::updateMaxScrollPosition()
[email protected]94f206c12012-08-25 00:09:14964{
965 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
966 return;
967
968 FloatSize viewBounds = m_deviceViewportSize;
[email protected]96baf3e2012-10-22 23:09:55969 if (LayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:14970 // Compensate for non-overlay scrollbars.
971 if (clipLayer->masksToBounds()) {
972 viewBounds = clipLayer->bounds();
973 viewBounds.scale(m_deviceScaleFactor);
974 }
975 }
[email protected]94f206c12012-08-25 00:09:14976
[email protected]1c0c9bc2012-10-08 22:41:48977 IntSize contentBounds = contentSize();
[email protected]65bfd9972012-10-19 03:39:37978 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48979 // Pinch with pageScale scrolls entirely in layout space. contentSize
980 // returns the bounds including the page scale factor, so calculate the
981 // pre page-scale layout size here.
982 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
983 contentBounds.setWidth(contentBounds.width() / pageScaleFactor);
984 contentBounds.setHeight(contentBounds.height() / pageScaleFactor);
985 } else {
986 viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta());
987 }
988
989 IntSize maxScroll = contentBounds - expandedIntSize(viewBounds);
[email protected]94f206c12012-08-25 00:09:14990 maxScroll.scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:48991
[email protected]94f206c12012-08-25 00:09:14992 // The viewport may be larger than the contents in some cases, such as
993 // having a vertical scrollbar but no horizontal overflow.
994 maxScroll.clampNegativeToZero();
995
996 m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
997}
998
[email protected]96baf3e2012-10-22 23:09:55999void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141000{
1001 m_client->setNeedsRedrawOnImplThread();
1002}
1003
[email protected]96baf3e2012-10-22 23:09:551004bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141005{
1006 if (!m_rootLayerImpl)
1007 return false;
1008 if (!m_renderer)
1009 return false;
1010
1011 // We need both a non-empty render surface layer list and a root render
1012 // surface to be able to iterate over the visible layers.
1013 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
1014 return true;
1015
1016 // If we are called after setRootLayer() but before prepareToDraw(), we need
1017 // to recalculate the visible layers. This prevents being unable to scroll
1018 // during part of a commit.
1019 m_renderSurfaceLayerList.clear();
1020 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
1021
1022 return m_renderSurfaceLayerList.size();
1023}
1024
[email protected]96baf3e2012-10-22 23:09:551025InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141026{
[email protected]96baf3e2012-10-22 23:09:551027 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141028
[email protected]1d993172012-10-18 18:15:041029 DCHECK(!m_currentlyScrollingLayerImpl);
[email protected]94f206c12012-08-25 00:09:141030 clearCurrentlyScrollingLayer();
1031
1032 if (!ensureRenderSurfaceLayerList())
1033 return ScrollIgnored;
1034
1035 IntPoint deviceViewportPoint = viewportPoint;
1036 deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
1037
1038 // First find out which layer was hit from the saved list of visible layers
1039 // in the most recent frame.
[email protected]96baf3e2012-10-22 23:09:551040 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:141041
1042 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551043 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141044 for (; layerImpl; layerImpl = layerImpl->parent()) {
1045 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271046 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1047 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141048 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271049 }
[email protected]94f206c12012-08-25 00:09:141050
[email protected]96baf3e2012-10-22 23:09:551051 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141052 if (!scrollLayerImpl)
1053 continue;
1054
[email protected]31bfe272012-10-19 18:49:521055 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141056
1057 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271058 if (status == ScrollOnMainThread) {
1059 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141060 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271061 }
[email protected]94f206c12012-08-25 00:09:141062
1063 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1064 potentiallyScrollingLayerImpl = scrollLayerImpl;
1065 }
1066
1067 if (potentiallyScrollingLayerImpl) {
1068 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
[email protected]31bfe272012-10-19 18:49:521069 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141070 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1071 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521072 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271073 m_numImplThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141074 return ScrollStarted;
1075 }
1076 return ScrollIgnored;
1077}
1078
[email protected]96baf3e2012-10-22 23:09:551079static FloatSize scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, const FloatPoint& viewportPoint, const FloatSize& viewportDelta)
[email protected]94f206c12012-08-25 00:09:141080{
1081 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1082 // test in the first place.
[email protected]1d993172012-10-18 18:15:041083 DCHECK(layerImpl.screenSpaceTransform().isInvertible());
[email protected]94f206c12012-08-25 00:09:141084 WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse();
1085
[email protected]31bfe272012-10-19 18:49:521086 FloatPoint screenSpacePoint = viewportPoint;
1087 screenSpacePoint.scale(scaleFromViewportToScreenSpace, scaleFromViewportToScreenSpace);
1088
1089 FloatSize screenSpaceDelta = viewportDelta;
1090 screenSpaceDelta.scale(scaleFromViewportToScreenSpace, scaleFromViewportToScreenSpace);
1091
[email protected]94f206c12012-08-25 00:09:141092 // First project the scroll start and end points to local layer space to find the scroll delta
1093 // in layer coordinates.
1094 bool startClipped, endClipped;
1095 FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
[email protected]96baf3e2012-10-22 23:09:551096 FloatPoint localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1097 FloatPoint localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141098
1099 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041100 DCHECK(!startClipped);
1101 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141102 if (startClipped || endClipped)
1103 return FloatSize();
1104
[email protected]31bfe272012-10-19 18:49:521105 // localStartPoint and localEndPoint are in content space but we want to move them to layer space for scrolling.
1106 float widthScale = 1;
1107 float heightScale = 1;
1108 if (!layerImpl.contentBounds().isEmpty() && !layerImpl.bounds().isEmpty()) {
1109 widthScale = layerImpl.bounds().width() / static_cast<float>(layerImpl.contentBounds().width());
1110 heightScale = layerImpl.bounds().height() / static_cast<float>(layerImpl.contentBounds().height());
1111 }
1112 localStartPoint.scale(widthScale, heightScale);
1113 localEndPoint.scale(widthScale, heightScale);
1114
[email protected]94f206c12012-08-25 00:09:141115 // Apply the scroll delta.
1116 FloatSize previousDelta(layerImpl.scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481117 FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
1118
1119 if (viewport)
1120 viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141121
[email protected]31bfe272012-10-19 18:49:521122 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]94f206c12012-08-25 00:09:141123 FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
[email protected]31bfe272012-10-19 18:49:521124 FloatPoint actualLocalContentEndPoint = actualLocalEndPoint;
1125 actualLocalContentEndPoint.scale(1 / widthScale, 1 / heightScale);
1126
1127 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]96baf3e2012-10-22 23:09:551128 FloatPoint actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041129 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141130 if (endClipped)
1131 return FloatSize();
[email protected]31bfe272012-10-19 18:49:521132 FloatPoint actualViewportEndPoint = actualScreenSpaceEndPoint;
1133 actualViewportEndPoint.scale(1 / scaleFromViewportToScreenSpace, 1 / scaleFromViewportToScreenSpace);
1134 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141135}
1136
[email protected]96baf3e2012-10-22 23:09:551137static FloatSize scrollLayerWithLocalDelta(LayerImpl& layerImpl, const FloatSize& localDelta)
[email protected]94f206c12012-08-25 00:09:141138{
1139 FloatSize previousDelta(layerImpl.scrollDelta());
1140 layerImpl.scrollBy(localDelta);
1141 return layerImpl.scrollDelta() - previousDelta;
1142}
1143
[email protected]96baf3e2012-10-22 23:09:551144void LayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141145{
[email protected]96baf3e2012-10-22 23:09:551146 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]94f206c12012-08-25 00:09:141147 if (!m_currentlyScrollingLayerImpl)
1148 return;
1149
1150 FloatSize pendingDelta(scrollDelta);
1151
[email protected]96baf3e2012-10-22 23:09:551152 for (LayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141153 if (!layerImpl->scrollable())
1154 continue;
1155
[email protected]96baf3e2012-10-22 23:09:551156 PinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
[email protected]94f206c12012-08-25 00:09:141157 FloatSize appliedDelta;
[email protected]31bfe272012-10-19 18:49:521158 if (m_scrollDeltaIsInViewportSpace) {
1159 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1160 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1161 } else
[email protected]94f206c12012-08-25 00:09:141162 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1163
1164 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381165 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]94f206c12012-08-25 00:09:141166 if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared)
1167 continue;
1168
1169 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1170 // to scroll just one layer in one direction without affecting any of its parents.
1171 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551172 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]94f206c12012-08-25 00:09:141173 pendingDelta = FloatSize();
1174 break;
1175 }
1176
1177 // Allow further movement only on an axis perpendicular to the direction in which the layer
1178 // moved.
1179 FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width());
[email protected]96baf3e2012-10-22 23:09:551180 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141181
1182 if (flooredIntSize(pendingDelta).isZero())
1183 break;
1184 }
1185
1186 if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) {
1187 m_client->setNeedsCommitOnImplThread();
1188 m_client->setNeedsRedrawOnImplThread();
1189 }
1190}
1191
[email protected]96baf3e2012-10-22 23:09:551192void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141193{
1194 m_currentlyScrollingLayerImpl = 0;
1195 m_scrollingLayerIdFromPreviousTree = -1;
1196}
1197
[email protected]96baf3e2012-10-22 23:09:551198void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141199{
1200 clearCurrentlyScrollingLayer();
1201}
1202
[email protected]96baf3e2012-10-22 23:09:551203void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141204{
1205 m_pinchGestureActive = true;
1206 m_previousPinchAnchor = IntPoint();
1207
1208 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1209 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
1210}
1211
[email protected]96baf3e2012-10-22 23:09:551212void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
[email protected]94f206c12012-08-25 00:09:141213 const IntPoint& anchor)
1214{
[email protected]96baf3e2012-10-22 23:09:551215 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141216
1217 if (!m_rootScrollLayerImpl)
1218 return;
1219
1220 if (m_previousPinchAnchor == IntPoint::zero())
1221 m_previousPinchAnchor = anchor;
1222
1223 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1224 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481225 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1226 FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta,
1227 m_previousPinchAnchor.y() / pageScaleDelta);
1228 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1229 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1230 FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141231 FloatSize move = previousScaleAnchor - newScaleAnchor;
1232
1233 m_previousPinchAnchor = anchor;
1234
[email protected]65bfd9972012-10-19 03:39:371235 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:481236 // Compute the application of the delta with respect to the current page zoom of the page.
1237 move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor));
1238 }
1239
[email protected]65bfd9972012-10-19 03:39:371240 FloatSize scrollOverflow = Settings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move;
[email protected]1c0c9bc2012-10-08 22:41:481241 m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow));
[email protected]94f206c12012-08-25 00:09:141242
1243 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1244 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
1245
1246 m_client->setNeedsCommitOnImplThread();
1247 m_client->setNeedsRedrawOnImplThread();
1248}
1249
[email protected]96baf3e2012-10-22 23:09:551250void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141251{
1252 m_pinchGestureActive = false;
1253
1254 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1255 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
1256
1257 m_client->setNeedsCommitOnImplThread();
1258}
1259
[email protected]96baf3e2012-10-22 23:09:551260void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141261{
1262 float pageScale = m_pageScaleAnimation->finalPageScale();
1263 IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
[email protected]1c0c9bc2012-10-08 22:41:481264 scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
[email protected]94f206c12012-08-25 00:09:141265 makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
1266}
1267
[email protected]96baf3e2012-10-22 23:09:551268void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141269{
1270 if (!m_rootScrollLayerImpl)
1271 return;
1272
1273 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1274 // significant amount. This also ensures only one fake delta set will be
1275 // sent.
[email protected]23bbb412012-08-30 20:03:381276 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481277 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141278 return;
1279
1280 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1281 // out from the anchor point.
1282 IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481283 scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta());
1284 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1285 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]94f206c12012-08-25 00:09:141286 FloatSize scaledContentsSize = contentSize();
1287 scaledContentsSize.scale(pageScaleDeltaToSend);
1288
1289 FloatSize anchor = toSize(m_previousPinchAnchor);
1290 FloatSize scrollEnd = scrollBegin + anchor;
[email protected]1c0c9bc2012-10-08 22:41:481291 scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
[email protected]94f206c12012-08-25 00:09:141292 scrollEnd -= anchor;
1293 scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
1294 scrollEnd.scale(1 / pageScaleDeltaToSend);
1295 scrollEnd.scale(m_deviceScaleFactor);
1296
[email protected]1c0c9bc2012-10-08 22:41:481297 makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141298}
1299
[email protected]96baf3e2012-10-22 23:09:551300void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141301{
1302 if (!m_rootScrollLayerImpl)
1303 return;
1304
[email protected]96baf3e2012-10-22 23:09:551305 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141306 scroll.layerId = m_rootScrollLayerImpl->id();
1307 scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
1308 scrollInfo->scrolls.append(scroll);
1309 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481310 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1311 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141312}
1313
[email protected]96baf3e2012-10-22 23:09:551314static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141315{
1316 if (!layerImpl)
1317 return;
1318
1319 if (!layerImpl->scrollDelta().isZero()) {
1320 IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551321 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141322 scroll.layerId = layerImpl->id();
1323 scroll.scrollDelta = scrollDelta;
1324 scrollInfo->scrolls.append(scroll);
1325 layerImpl->setSentScrollDelta(scrollDelta);
1326 }
1327
1328 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031329 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141330}
1331
[email protected]96baf3e2012-10-22 23:09:551332scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141333{
[email protected]96baf3e2012-10-22 23:09:551334 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141335
1336 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481337 scrollInfo->pageScaleDelta = 1;
1338 m_pinchZoomViewport.setSentPageScaleDelta(1);
1339 // FIXME(aelias): Make these painting optimizations compatible with
1340 // compositor-side scaling.
[email protected]65bfd9972012-10-19 03:39:371341 if (!Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:481342 if (m_pinchGestureActive)
1343 computePinchZoomDeltas(scrollInfo.get());
1344 else if (m_pageScaleAnimation.get())
1345 computeDoubleTapZoomDeltas(scrollInfo.get());
1346 }
[email protected]a9f4bf22012-10-11 23:39:211347 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141348 }
1349
1350 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
[email protected]1c0c9bc2012-10-08 22:41:481351 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1352 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141353
[email protected]a9f4bf22012-10-11 23:39:211354 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141355}
1356
[email protected]96baf3e2012-10-22 23:09:551357WebTransformationMatrix LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481358{
1359 return m_pinchZoomViewport.implTransform();
1360}
1361
[email protected]96baf3e2012-10-22 23:09:551362void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141363{
1364 if (m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:551365 RenderSurfaceImpl* renderSurface = m_rootLayerImpl->renderSurface();
[email protected]94f206c12012-08-25 00:09:141366 if (renderSurface)
1367 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1368 }
1369}
1370
[email protected]96baf3e2012-10-22 23:09:551371void LayerTreeHostImpl::animatePageScale(double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141372{
1373 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1374 return;
1375
1376 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
1377
[email protected]1c0c9bc2012-10-08 22:41:481378 setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141379 IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]1c0c9bc2012-10-08 22:41:481380 nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]94f206c12012-08-25 00:09:141381 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1382 m_client->setNeedsRedrawOnImplThread();
1383
1384 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451385 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141386 m_client->setNeedsCommitOnImplThread();
1387 }
1388}
1389
[email protected]96baf3e2012-10-22 23:09:551390void LayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
[email protected]94f206c12012-08-25 00:09:141391{
[email protected]65bfd9972012-10-19 03:39:371392 if (!Settings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
[email protected]94f206c12012-08-25 00:09:141393 return;
1394
[email protected]96baf3e2012-10-22 23:09:551395 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141396
[email protected]96baf3e2012-10-22 23:09:551397 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
[email protected]94f206c12012-08-25 00:09:141398
1399 bool didAnimate = false;
1400 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1401
[email protected]d3143c732012-10-05 19:17:591402 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571403 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141404
1405 if (didAnimate)
1406 m_client->setNeedsRedrawOnImplThread();
1407
1408 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1409}
1410
[email protected]96baf3e2012-10-22 23:09:551411base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141412{
[email protected]4481ddb622012-09-20 16:33:471413 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141414}
1415
[email protected]96baf3e2012-10-22 23:09:551416void LayerTreeHostImpl::sendDidLoseContextRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141417{
[email protected]1d993172012-10-18 18:15:041418 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141419 current->didLoseContext();
1420 if (current->maskLayer())
1421 sendDidLoseContextRecursive(current->maskLayer());
1422 if (current->replicaLayer())
1423 sendDidLoseContextRecursive(current->replicaLayer());
1424 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031425 sendDidLoseContextRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141426}
1427
[email protected]96baf3e2012-10-22 23:09:551428static void clearRenderSurfacesOnLayerImplRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141429{
[email protected]1d993172012-10-18 18:15:041430 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141431 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]96baf3e2012-10-22 23:09:551432 clearRenderSurfacesOnLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141433 current->clearRenderSurface();
1434}
1435
[email protected]96baf3e2012-10-22 23:09:551436void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141437{
[email protected]96baf3e2012-10-22 23:09:551438 clearRenderSurfacesOnLayerImplRecursive(m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141439 m_renderSurfaceLayerList.clear();
1440}
1441
[email protected]96baf3e2012-10-22 23:09:551442std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141443{
[email protected]515e8d232012-09-10 19:15:271444 std::string str;
[email protected]94f206c12012-08-25 00:09:141445 if (m_rootLayerImpl) {
[email protected]515e8d232012-09-10 19:15:271446 str = m_rootLayerImpl->layerTreeAsText();
1447 str += "RenderSurfaces:\n";
1448 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141449 }
[email protected]515e8d232012-09-10 19:15:271450 return str;
[email protected]94f206c12012-08-25 00:09:141451}
1452
[email protected]96baf3e2012-10-22 23:09:551453void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141454{
1455 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271456 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141457
1458 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031459 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141460}
1461
[email protected]96baf3e2012-10-22 23:09:551462int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141463{
1464 return fpsCounter()->currentFrameNumber();
1465}
1466
[email protected]96baf3e2012-10-22 23:09:551467void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141468{
[email protected]8b9af6b2012-09-27 00:36:361469 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1470 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271471 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1472 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]94f206c12012-08-25 00:09:141473}
1474
[email protected]96baf3e2012-10-22 23:09:551475void LayerTreeHostImpl::animateScrollbars(double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141476{
1477 animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime);
1478}
1479
[email protected]96baf3e2012-10-22 23:09:551480void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141481{
1482 if (!layer)
1483 return;
1484
[email protected]96baf3e2012-10-22 23:09:551485 ScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]94f206c12012-08-25 00:09:141486 if (scrollbarController && scrollbarController->animate(monotonicTime))
1487 m_client->setNeedsRedrawOnImplThread();
1488
1489 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031490 animateScrollbarsRecursive(layer->children()[i], monotonicTime);
[email protected]94f206c12012-08-25 00:09:141491}
1492
[email protected]d3143c732012-10-05 19:17:591493} // namespace cc