blob: 21207b1985ce6b3e78df6a04af1c795f626975fb [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
[email protected]55a124d02012-10-22 03:07:135#include "cc/layer_tree_host_impl.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]ac7c7f52012-11-08 06:26:507#include <algorithm>
8
[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]c9c1ebe2012-11-05 20:46:1317#include "cc/geometry.h"
[email protected]c4040a522012-10-21 15:01:4018#include "cc/gl_renderer.h"
[email protected]d50c6862012-10-23 02:08:3119#include "cc/heads_up_display_layer_impl.h"
20#include "cc/layer_iterator.h"
21#include "cc/layer_tree_host.h"
22#include "cc/layer_tree_host_common.h"
[email protected]55a124d02012-10-22 03:07:1323#include "cc/math_util.h"
24#include "cc/overdraw_metrics.h"
25#include "cc/page_scale_animation.h"
[email protected]3b10a302012-11-07 21:16:4026#include "cc/prioritized_resource_manager.h"
[email protected]55a124d02012-10-22 03:07:1327#include "cc/render_pass_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4028#include "cc/rendering_stats.h"
29#include "cc/scrollbar_animation_controller.h"
30#include "cc/scrollbar_layer_impl.h"
31#include "cc/settings.h"
[email protected]4456eee22012-10-19 18:16:3832#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4033#include "cc/software_renderer.h"
[email protected]a8461d82012-10-16 21:11:1434#include "cc/texture_uploader.h"
[email protected]d455d552012-11-02 00:19:0635#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1336#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1437
38using WebKit::WebTransformationMatrix;
39
40namespace {
41
[email protected]96baf3e2012-10-22 23:09:5542void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1443{
44 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5545 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1446 return;
47 }
48
[email protected]96baf3e2012-10-22 23:09:5549 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1450}
51
52} // namespace
53
[email protected]9c88e562012-09-14 22:21:3054namespace cc {
[email protected]94f206c12012-08-25 00:09:1455
[email protected]96baf3e2012-10-22 23:09:5556PinchZoomViewport::PinchZoomViewport()
[email protected]1c0c9bc2012-10-08 22:41:4857 : m_pageScaleFactor(1)
58 , m_pageScaleDelta(1)
59 , m_sentPageScaleDelta(1)
60 , m_minPageScaleFactor(0)
61 , m_maxPageScaleFactor(0)
62{
63}
64
[email protected]96baf3e2012-10-22 23:09:5565float PinchZoomViewport::totalPageScaleFactor() const
[email protected]1c0c9bc2012-10-08 22:41:4866{
67 return m_pageScaleFactor * m_pageScaleDelta;
68}
69
[email protected]96baf3e2012-10-22 23:09:5570void PinchZoomViewport::setPageScaleDelta(float delta)
[email protected]1c0c9bc2012-10-08 22:41:4871{
72 // Clamp to the current min/max limits.
73 float totalPageScaleFactor = m_pageScaleFactor * delta;
74 if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
75 delta = m_minPageScaleFactor / m_pageScaleFactor;
76 else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
77 delta = m_maxPageScaleFactor / m_pageScaleFactor;
78
79 if (delta == m_pageScaleDelta)
80 return;
81
82 m_pageScaleDelta = delta;
83}
84
[email protected]96baf3e2012-10-22 23:09:5585bool PinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:4886{
[email protected]1d993172012-10-18 18:15:0487 DCHECK(pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:4888
89 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
90 return false;
91
92 m_minPageScaleFactor = minPageScaleFactor;
93 m_maxPageScaleFactor = maxPageScaleFactor;
94
95 m_pageScaleFactor = pageScaleFactor;
96 return true;
97}
98
[email protected]aad0a0072012-11-01 18:15:5899gfx::RectF PinchZoomViewport::bounds() const
[email protected]1c0c9bc2012-10-08 22:41:48100{
[email protected]2e6486012012-11-10 00:03:19101 gfx::RectF bounds(gfx::PointF(), m_layoutViewportSize);
102 bounds.Scale(1 / totalPageScaleFactor());
103 bounds += m_pinchViewportScrollDelta;
[email protected]1c0c9bc2012-10-08 22:41:48104 return bounds;
105}
106
[email protected]c9c1ebe2012-11-05 20:46:13107gfx::Vector2dF PinchZoomViewport::applyScroll(const gfx::Vector2dF& delta)
[email protected]1c0c9bc2012-10-08 22:41:48108{
[email protected]d0f98362012-11-01 23:02:38109 gfx::Vector2dF overflow;
[email protected]2e6486012012-11-10 00:03:19110 gfx::RectF pinchedBounds = bounds() + delta;
[email protected]1c0c9bc2012-10-08 22:41:48111
[email protected]1c0c9bc2012-10-08 22:41:48112 if (pinchedBounds.x() < 0) {
[email protected]d0f98362012-11-01 23:02:38113 overflow.set_x(pinchedBounds.x());
114 pinchedBounds.set_x(0);
[email protected]1c0c9bc2012-10-08 22:41:48115 }
116
117 if (pinchedBounds.y() < 0) {
[email protected]d0f98362012-11-01 23:02:38118 overflow.set_y(pinchedBounds.y());
119 pinchedBounds.set_y(0);
[email protected]1c0c9bc2012-10-08 22:41:48120 }
121
[email protected]d0f98362012-11-01 23:02:38122 if (pinchedBounds.right() > m_layoutViewportSize.width()) {
123 overflow.set_x(pinchedBounds.right() - m_layoutViewportSize.width());
[email protected]2e6486012012-11-10 00:03:19124 pinchedBounds += gfx::Vector2dF(m_layoutViewportSize.width() - pinchedBounds.right(), 0);
[email protected]1c0c9bc2012-10-08 22:41:48125 }
126
[email protected]d0f98362012-11-01 23:02:38127 if (pinchedBounds.bottom() > m_layoutViewportSize.height()) {
128 overflow.set_y(pinchedBounds.bottom() - m_layoutViewportSize.height());
[email protected]2e6486012012-11-10 00:03:19129 pinchedBounds += gfx::Vector2dF(0, m_layoutViewportSize.height() - pinchedBounds.bottom());
[email protected]1c0c9bc2012-10-08 22:41:48130 }
[email protected]c9c1ebe2012-11-05 20:46:13131 m_pinchViewportScrollDelta = pinchedBounds.OffsetFromOrigin();
[email protected]1c0c9bc2012-10-08 22:41:48132
[email protected]c9c1ebe2012-11-05 20:46:13133 return overflow;
[email protected]1c0c9bc2012-10-08 22:41:48134}
135
[email protected]96baf3e2012-10-22 23:09:55136WebTransformationMatrix PinchZoomViewport::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:48137{
138 WebTransformationMatrix transform;
139 transform.scale(m_pageScaleDelta);
140
141 // If the pinch state is applied in the impl, then push it to the
142 // impl transform, otherwise the scale is handled by WebCore.
[email protected]65bfd9972012-10-19 03:39:37143 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48144 transform.scale(m_pageScaleFactor);
145 transform.translate(-m_pinchViewportScrollDelta.x(),
146 -m_pinchViewportScrollDelta.y());
147 }
148
149 return transform;
150}
151
[email protected]96baf3e2012-10-22 23:09:55152class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14153public:
[email protected]96baf3e2012-10-22 23:09:55154 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14155 {
[email protected]96baf3e2012-10-22 23:09:55156 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:14157 }
[email protected]96baf3e2012-10-22 23:09:55158 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:14159 {
160 m_timeSource->setClient(0);
161 m_timeSource->setActive(false);
162 }
163
164 virtual void onTimerTick() OVERRIDE
165 {
[email protected]30faac92012-10-29 00:06:29166 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]94f206c12012-08-25 00:09:14167 }
168
169 void setActive(bool active)
170 {
171 if (active != m_timeSource->active())
172 m_timeSource->setActive(active);
173 }
174
175private:
[email protected]96baf3e2012-10-22 23:09:55176 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14177 : m_layerTreeHostImpl(layerTreeHostImpl)
178 , m_timeSource(timeSource)
179 {
180 m_timeSource->setClient(this);
181 }
182
[email protected]96baf3e2012-10-22 23:09:55183 LayerTreeHostImpl* m_layerTreeHostImpl;
184 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20185
[email protected]96baf3e2012-10-22 23:09:55186 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14187};
188
[email protected]96baf3e2012-10-22 23:09:55189LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10190{
191}
192
[email protected]96baf3e2012-10-22 23:09:55193LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10194{
195}
196
[email protected]61de5812012-11-08 07:03:44197scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14198{
[email protected]61de5812012-11-08 07:03:44199 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
[email protected]94f206c12012-08-25 00:09:14200}
201
[email protected]61de5812012-11-08 07:03:44202LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14203 : m_client(client)
[email protected]61de5812012-11-08 07:03:44204 , m_proxy(proxy)
[email protected]94f206c12012-08-25 00:09:14205 , m_sourceFrameNumber(-1)
206 , m_rootScrollLayerImpl(0)
207 , m_currentlyScrollingLayerImpl(0)
208 , m_hudLayerImpl(0)
209 , m_scrollingLayerIdFromPreviousTree(-1)
[email protected]31bfe272012-10-19 18:49:52210 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14211 , m_settings(settings)
212 , m_deviceScaleFactor(1)
213 , m_visible(true)
214 , m_contentsTexturesPurged(false)
[email protected]3b10a302012-11-07 21:16:40215 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
[email protected]96baf3e2012-10-22 23:09:55216 PriorityCalculator::allowEverythingCutoff(),
[email protected]a0a00842012-10-22 22:50:28217 0,
[email protected]96baf3e2012-10-22 23:09:55218 PriorityCalculator::allowNothingCutoff())
[email protected]94f206c12012-08-25 00:09:14219 , m_backgroundColor(0)
220 , m_hasTransparentBackground(false)
221 , m_needsAnimateLayers(false)
222 , m_pinchGestureActive(false)
[email protected]61de5812012-11-08 07:03:44223 , m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
[email protected]96baf3e2012-10-22 23:09:55224 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27225 , m_numImplThreadScrolls(0)
226 , m_numMainThreadScrolls(0)
[email protected]94f206c12012-08-25 00:09:14227{
[email protected]61de5812012-11-08 07:03:44228 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14229 didVisibilityChange(this, m_visible);
230}
231
[email protected]96baf3e2012-10-22 23:09:55232LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14233{
[email protected]61de5812012-11-08 07:03:44234 DCHECK(m_proxy->isImplThread());
[email protected]96baf3e2012-10-22 23:09:55235 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14236
237 if (m_rootLayerImpl)
238 clearRenderSurfaces();
239}
240
[email protected]96baf3e2012-10-22 23:09:55241void LayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14242{
243}
244
[email protected]96baf3e2012-10-22 23:09:55245void LayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14246{
[email protected]96baf3e2012-10-22 23:09:55247 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
[email protected]94f206c12012-08-25 00:09:14248 // Recompute max scroll position; must be after layer content bounds are
249 // updated.
[email protected]c9c1ebe2012-11-05 20:46:13250 updateMaxScrollOffset();
[email protected]3d21e022012-10-25 20:03:08251 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14252}
253
[email protected]96baf3e2012-10-22 23:09:55254bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14255{
[email protected]8db2213c2012-09-05 22:08:21256 // Note: If you are changing this function or any other function that might
257 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
258 // in the proper places and update the notifyIfCanDrawChanged test.
259
[email protected]94f206c12012-08-25 00:09:14260 if (!m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:55261 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14262 return false;
263 }
[email protected]aad0a0072012-11-01 18:15:58264 if (deviceViewportSize().IsEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55265 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14266 return false;
267 }
268 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55269 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14270 return false;
271 }
272 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55273 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14274 return false;
275 }
276 return true;
277}
278
[email protected]96baf3e2012-10-22 23:09:55279GraphicsContext* LayerTreeHostImpl::context() const
[email protected]94f206c12012-08-25 00:09:14280{
281 return m_context.get();
282}
283
[email protected]30faac92012-10-29 00:06:29284void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:14285{
286 animatePageScale(monotonicTime);
287 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14288 animateScrollbars(monotonicTime);
289}
290
[email protected]69a2a5be2012-11-14 06:51:44291void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration)
[email protected]94f206c12012-08-25 00:09:14292{
293 if (!m_rootScrollLayerImpl)
294 return;
295
[email protected]c9c1ebe2012-11-05 20:46:13296 gfx::Vector2dF scrollTotal = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
[email protected]f6250742012-11-09 04:46:56297 gfx::SizeF scaledContentSize = contentSize();
298 if (!Settings::pageScalePinchZoomEnabled()) {
299 scrollTotal.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]01a15a72012-11-10 09:34:28300 scaledContentSize.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]f6250742012-11-09 04:46:56301 }
[email protected]01a15a72012-11-10 09:34:28302 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14303
[email protected]30faac92012-10-29 00:06:29304 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
[email protected]f6250742012-11-09 04:46:56305 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, m_pinchZoomViewport.totalPageScaleFactor(), viewportSize, scaledContentSize, startTimeSeconds);
[email protected]94f206c12012-08-25 00:09:14306
307 if (anchorPoint) {
[email protected]69a2a5be2012-11-14 06:51:44308 gfx::Vector2dF anchor(targetOffset);
[email protected]f6250742012-11-09 04:46:56309 if (!Settings::pageScalePinchZoomEnabled())
310 anchor.Scale(1 / pageScale);
311 m_pageScaleAnimation->zoomWithAnchor(anchor, pageScale, duration.InSecondsF());
312 } else {
[email protected]69a2a5be2012-11-14 06:51:44313 gfx::Vector2dF scaledTargetOffset = targetOffset;
[email protected]f6250742012-11-09 04:46:56314 if (!Settings::pageScalePinchZoomEnabled())
[email protected]69a2a5be2012-11-14 06:51:44315 scaledTargetOffset.Scale(1 / pageScale);
316 m_pageScaleAnimation->zoomTo(scaledTargetOffset, pageScale, duration.InSecondsF());
[email protected]f6250742012-11-09 04:46:56317 }
[email protected]94f206c12012-08-25 00:09:14318
319 m_client->setNeedsRedrawOnImplThread();
320 m_client->setNeedsCommitOnImplThread();
321}
322
[email protected]96baf3e2012-10-22 23:09:55323void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14324{
325 m_client->setNeedsRedrawOnImplThread();
326}
327
[email protected]96baf3e2012-10-22 23:09:55328void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14329{
330 // For now, we use damage tracking to compute a global scissor. To do this, we must
331 // compute all damage tracking before drawing anything, so that we know the root
332 // damage rect. The root damage rect is then used to scissor each surface.
333
334 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55335 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
336 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04337 DCHECK(renderSurface);
[email protected]4000abf2012-10-23 04:45:45338 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter());
[email protected]94f206c12012-08-25 00:09:14339 }
340}
341
[email protected]96baf3e2012-10-22 23:09:55342void LayerTreeHostImpl::updateRootScrollLayerImplTransform()
[email protected]1c0c9bc2012-10-08 22:41:48343{
344 if (m_rootScrollLayerImpl) {
345 m_rootScrollLayerImpl->setImplTransform(implTransform());
346 }
347}
348
[email protected]96baf3e2012-10-22 23:09:55349void LayerTreeHostImpl::calculateRenderSurfaceLayerList(LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14350{
[email protected]1d993172012-10-18 18:15:04351 DCHECK(renderSurfaceLayerList.empty());
352 DCHECK(m_rootLayerImpl);
353 DCHECK(m_renderer); // For maxTextureSize.
[email protected]94f206c12012-08-25 00:09:14354
355 {
[email protected]1c0c9bc2012-10-08 22:41:48356 updateRootScrollLayerImplTransform();
357
[email protected]96baf3e2012-10-22 23:09:55358 TRACE_EVENT0("cc", "LayerTreeHostImpl::calcDrawEtc");
[email protected]518ee582012-10-24 18:29:44359 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
360 LayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14361
362 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
363 }
364}
365
[email protected]96baf3e2012-10-22 23:09:55366void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16367{
[email protected]96baf3e2012-10-22 23:09:55368 RenderPass* pass = renderPass.get();
[email protected]f8ad8342012-09-27 20:07:02369 renderPasses.push_back(pass);
[email protected]87cea5372012-09-26 18:59:56370 renderPassesById.set(pass->id(), renderPass.Pass());
[email protected]467b3612012-08-28 07:41:16371}
372
[email protected]96baf3e2012-10-22 23:09:55373bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14374{
[email protected]1d993172012-10-18 18:15:04375 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14376
377 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
378
[email protected]96baf3e2012-10-22 23:09:55379 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14380
381 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14382 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55383 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16384 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14385 }
386
[email protected]86ed46c2012-11-12 19:59:02387 bool recordMetricsForFrame = Settings::traceOverdraw() && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
[email protected]96baf3e2012-10-22 23:09:55388 OcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14389 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
390
391 if (settings().showOccludingRects)
392 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
393
394 // 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:55395 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14396
397 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
398 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
399 // in the future.
400 bool drawFrame = true;
401
[email protected]96baf3e2012-10-22 23:09:55402 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
403 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
404 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
405 RenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14406
407 occlusionTracker.enterLayer(it);
408
[email protected]96baf3e2012-10-22 23:09:55409 AppendQuadsData appendQuadsData(targetRenderPass->id());
[email protected]89228202012-08-29 03:20:30410
[email protected]94f206c12012-08-25 00:09:14411 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55412 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
413 RenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]89228202012-08-29 03:20:30414 targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData);
[email protected]aad0a0072012-11-01 18:15:58415 } else if (it.representsItself() && !it->visibleContentRect().IsEmpty()) {
[email protected]94f206c12012-08-25 00:09:14416 bool hasOcclusionFromOutsideTargetSurface;
[email protected]710ffc02012-10-30 21:42:02417 bool implDrawTransformIsUnknown = false;
418 if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
[email protected]89228202012-08-29 03:20:30419 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
420 else {
[email protected]94f206c12012-08-25 00:09:14421 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47422 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57423
424 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55425 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]7d929c02012-09-20 17:26:57426 while (frame.renderPassesById.contains(contributingRenderPassId)) {
[email protected]96baf3e2012-10-22 23:09:55427 RenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]7d929c02012-09-20 17:26:57428
[email protected]96baf3e2012-10-22 23:09:55429 AppendQuadsData appendQuadsData(renderPass->id());
[email protected]7d929c02012-09-20 17:26:57430 renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
431
432 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
433 }
434 }
435
[email protected]89228202012-08-29 03:20:30436 targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14437 }
438 }
439
[email protected]89228202012-08-29 03:20:30440 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
441 targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true);
442
443 if (appendQuadsData.hadMissingTiles) {
[email protected]94f206c12012-08-25 00:09:14444 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]22619922012-11-14 17:58:10445 if (layerHasAnimatingTransform)
[email protected]94f206c12012-08-25 00:09:14446 drawFrame = false;
447 }
448
449 occlusionTracker.leaveLayer(it);
450 }
451
[email protected]1d993172012-10-18 18:15:04452#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14453 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]1d993172012-10-18 18:15:04454 for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j)
455 DCHECK(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0);
456 DCHECK(frame.renderPassesById.contains(frame.renderPasses[i]->id()));
[email protected]94f206c12012-08-25 00:09:14457 }
458#endif
459
460 if (!m_hasTransparentBackground) {
[email protected]f8ad8342012-09-27 20:07:02461 frame.renderPasses.back()->setHasTransparentBackground(false);
462 frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14463 }
464
465 if (drawFrame)
466 occlusionTracker.overdrawMetrics().recordMetrics(this);
467
468 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
469 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
470 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
471
472 return drawFrame;
473}
474
[email protected]30faac92012-10-29 00:06:29475void LayerTreeHostImpl::animateLayersRecursive(LayerImpl* current, base::TimeTicks monotonicTime, base::Time wallClockTime, AnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
[email protected]94f206c12012-08-25 00:09:14476{
477 bool subtreeNeedsAnimateLayers = false;
478
[email protected]96baf3e2012-10-22 23:09:55479 LayerAnimationController* currentController = current->layerAnimationController();
[email protected]94f206c12012-08-25 00:09:14480
481 bool hadActiveAnimation = currentController->hasActiveAnimation();
[email protected]30faac92012-10-29 00:06:29482 double monotonicTimeSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
483 currentController->animate(monotonicTimeSeconds, events);
[email protected]94f206c12012-08-25 00:09:14484 bool startedAnimation = events->size() > 0;
485
486 // We animated if we either ticked a running animation, or started a new animation.
487 if (hadActiveAnimation || startedAnimation)
488 didAnimate = true;
489
490 // If the current controller still has an active animation, we must continue animating layers.
491 if (currentController->hasActiveAnimation())
492 subtreeNeedsAnimateLayers = true;
493
494 for (size_t i = 0; i < current->children().size(); ++i) {
495 bool childNeedsAnimateLayers = false;
[email protected]0920e24f2012-09-20 03:34:03496 animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:14497 if (childNeedsAnimateLayers)
498 subtreeNeedsAnimateLayers = true;
499 }
500
501 needsAnimateLayers = subtreeNeedsAnimateLayers;
502}
503
[email protected]96baf3e2012-10-22 23:09:55504void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14505{
506 // Lazily create the timeSource adapter so that we can vary the interval for testing.
507 if (!m_timeSourceClientAdapter)
[email protected]61de5812012-11-08 07:03:44508 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->currentThread()));
[email protected]94f206c12012-08-25 00:09:14509
510 m_timeSourceClientAdapter->setActive(enabled);
511}
512
[email protected]aad0a0072012-11-01 18:15:58513gfx::Size LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14514{
515 // TODO(aelias): Hardcoding the first child here is weird. Think of
516 // a cleaner way to get the contentBounds on the Impl side.
517 if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
[email protected]aad0a0072012-11-01 18:15:58518 return gfx::Size();
[email protected]94f206c12012-08-25 00:09:14519 return m_rootScrollLayerImpl->children()[0]->contentBounds();
520}
521
[email protected]96baf3e2012-10-22 23:09:55522static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14523{
[email protected]96baf3e2012-10-22 23:09:55524 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]1d993172012-10-18 18:15:04525 DCHECK(it != frame.renderPassesById.end());
[email protected]87cea5372012-09-26 18:59:56526 return it->second;
[email protected]94f206c12012-08-25 00:09:14527}
528
[email protected]96baf3e2012-10-22 23:09:55529static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14530{
[email protected]96baf3e2012-10-22 23:09:55531 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
532 RenderPassList& renderPasses = frame.renderPasses;
533 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14534
535 // The pass was already removed by another quad - probably the original, and we are the replica.
[email protected]f8ad8342012-09-27 20:07:02536 if (toRemove == renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14537 return;
538
[email protected]96baf3e2012-10-22 23:09:55539 const RenderPass* removedPass = *toRemove;
[email protected]f8ad8342012-09-27 20:07:02540 frame.renderPasses.erase(toRemove);
[email protected]94f206c12012-08-25 00:09:14541
542 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]96baf3e2012-10-22 23:09:55543 const QuadList& quadList = removedPass->quadList();
544 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14545 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55546 DrawQuad* currentQuad = (*quadListIterator);
547 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14548 continue;
549
[email protected]96baf3e2012-10-22 23:09:55550 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::materialCast(currentQuad)->renderPassId();
[email protected]94f206c12012-08-25 00:09:14551 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
552 }
553}
554
[email protected]96baf3e2012-10-22 23:09:55555bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14556{
[email protected]1fea8142012-10-20 04:12:41557 return quad.contentsChangedSinceLastFrame().IsEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
[email protected]94f206c12012-08-25 00:09:14558}
559
[email protected]96baf3e2012-10-22 23:09:55560bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14561{
[email protected]96baf3e2012-10-22 23:09:55562 const RenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame);
563 const RenderPassList& renderPasses = frame.renderPasses;
564 RenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
[email protected]94f206c12012-08-25 00:09:14565
[email protected]f8ad8342012-09-27 20:07:02566 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
[email protected]94f206c12012-08-25 00:09:14567 if (renderPassAlreadyRemoved)
568 return false;
569
570 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]96baf3e2012-10-22 23:09:55571 const QuadList& quadList = (*foundPass)->quadList();
572 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
573 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14574
[email protected]96baf3e2012-10-22 23:09:55575 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14576 return false;
577
[email protected]96baf3e2012-10-22 23:09:55578 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame);
579 RenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
[email protected]f8ad8342012-09-27 20:07:02580 if (foundContributingPass != renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14581 return false;
582 }
583 return true;
584}
585
586// Defined for linking tests.
[email protected]52347c842012-11-02 21:06:20587template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
588template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14589
590// static
591template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55592void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14593{
594 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55595 const RenderPass* currentPass = frame.renderPasses[it];
596 const QuadList& quadList = currentPass->quadList();
597 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14598
599 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55600 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14601
[email protected]96baf3e2012-10-22 23:09:55602 if (currentQuad->material() != DrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14603 continue;
604
[email protected]96baf3e2012-10-22 23:09:55605 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14606 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
607 continue;
608
609 // We are changing the vector in the middle of iteration. Because we
610 // delete render passes that draw into the current pass, we are
611 // guaranteed that any data from the iterator to the end will not
612 // change. So, capture the iterator position from the end of the
613 // list, and restore it after the change.
614 int positionFromEnd = frame.renderPasses.size() - it;
615 removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame);
616 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04617 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14618 }
619 }
620}
621
[email protected]96baf3e2012-10-22 23:09:55622bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14623{
[email protected]96baf3e2012-10-22 23:09:55624 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]1d993172012-10-18 18:15:04625 DCHECK(canDraw());
[email protected]94f206c12012-08-25 00:09:14626
627 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
628 frame.renderPasses.clear();
629 frame.renderPassesById.clear();
630 frame.renderSurfaceLayerList->clear();
631 frame.willDrawLayers.clear();
632
633 if (!calculateRenderPasses(frame))
634 return false;
635
636 // If we return true, then we expect drawLayers() to be called before this function is called again.
637 return true;
638}
639
[email protected]96baf3e2012-10-22 23:09:55640void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14641{
[email protected]a0a00842012-10-22 22:50:28642 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
643 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
644 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
[email protected]b1969fa2012-10-17 20:16:29645 if (evictedResources) {
646 setContentsTexturesPurged();
647 m_client->setNeedsCommitOnImplThread();
648 m_client->onCanDrawStateChanged(canDraw());
649 }
[email protected]3d21e022012-10-25 20:03:08650 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14651}
652
[email protected]61de5812012-11-08 07:03:44653bool LayerTreeHostImpl::hasImplThread() const
654{
655 return m_proxy->hasImplThread();
656}
657
[email protected]96baf3e2012-10-22 23:09:55658void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14659{
[email protected]a0a00842012-10-22 22:50:28660 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14661 return;
[email protected]61de5812012-11-08 07:03:44662
[email protected]a0a00842012-10-22 22:50:28663 m_managedMemoryPolicy = policy;
[email protected]61de5812012-11-08 07:03:44664 if (!m_proxy->hasImplThread()) {
665 // FIXME: In single-thread mode, this can be called on the main thread
666 // by GLRenderer::onMemoryAllocationChanged.
667 DebugScopedSetImplThread implThread(m_proxy);
668 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
669 } else {
670 DCHECK(m_proxy->isImplThread());
671 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
672 }
[email protected]a0a00842012-10-22 22:50:28673 // We always need to commit after changing the memory policy because the new
674 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14675 m_client->setNeedsCommitOnImplThread();
676}
677
[email protected]96baf3e2012-10-22 23:09:55678void LayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
[email protected]94f206c12012-08-25 00:09:14679{
[email protected]30faac92012-10-29 00:06:29680 base::TimeTicks timebase = base::TimeTicks::FromInternalValue(monotonicTimebase * base::Time::kMicrosecondsPerSecond);
681 base::TimeDelta interval = base::TimeDelta::FromMicroseconds(intervalInSeconds * base::Time::kMicrosecondsPerSecond);
682 m_client->onVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14683}
684
[email protected]96baf3e2012-10-22 23:09:55685void LayerTreeHostImpl::drawLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14686{
[email protected]96baf3e2012-10-22 23:09:55687 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04688 DCHECK(canDraw());
689 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14690
691 // FIXME: use the frame begin time from the overall compositor scheduler.
692 // This value is currently inaccessible because it is up in Chromium's
693 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21694 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14695
696 if (m_settings.showDebugRects())
697 m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
698
699 // Because the contents of the HUD depend on everything else in the frame, the contents
700 // of its texture are updated as the last thing before the frame is drawn.
701 if (m_hudLayerImpl)
702 m_hudLayerImpl->updateHudTexture(m_resourceProvider.get());
703
704 m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
705
706 // Once a RenderPass has been drawn, its damage should be cleared in
707 // case the RenderPass will be reused next frame.
708 for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
[email protected]d0f98362012-11-01 23:02:38709 frame.renderPasses[i]->setDamageRect(gfx::RectF());
[email protected]94f206c12012-08-25 00:09:14710
711 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
712 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
713 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
714 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
715}
716
[email protected]96baf3e2012-10-22 23:09:55717void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14718{
719 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
720 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52721
722 // Once all layers have been drawn, pending texture uploads should no
723 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09724 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14725}
726
[email protected]96baf3e2012-10-22 23:09:55727void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14728{
729 if (m_renderer)
730 m_renderer->finish();
731}
732
[email protected]96baf3e2012-10-22 23:09:55733bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14734{
735 return m_renderer && m_renderer->isContextLost();
736}
737
[email protected]96baf3e2012-10-22 23:09:55738const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14739{
740 return m_renderer->capabilities();
741}
742
[email protected]96baf3e2012-10-22 23:09:55743bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14744{
[email protected]1d993172012-10-18 18:15:04745 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14746
747 m_fpsCounter->markEndOfFrame();
748 return m_renderer->swapBuffers();
749}
750
[email protected]aad0a0072012-11-01 18:15:58751const gfx::Size& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10752{
753 return m_deviceViewportSize;
754}
755
[email protected]96baf3e2012-10-22 23:09:55756const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10757{
758 return m_settings;
759}
760
[email protected]96baf3e2012-10-22 23:09:55761void LayerTreeHostImpl::didLoseContext()
[email protected]94f206c12012-08-25 00:09:14762{
763 m_client->didLoseContextOnImplThread();
764}
765
[email protected]96baf3e2012-10-22 23:09:55766void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14767{
768 m_client->onSwapBuffersCompleteOnImplThread();
769}
770
[email protected]aad0a0072012-11-01 18:15:58771void LayerTreeHostImpl::readback(void* pixels, const gfx::Rect& rect)
[email protected]94f206c12012-08-25 00:09:14772{
[email protected]1d993172012-10-18 18:15:04773 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14774 m_renderer->getFramebufferPixels(pixels, rect);
775}
776
[email protected]96baf3e2012-10-22 23:09:55777static LayerImpl* findRootScrollLayer(LayerImpl* layer)
[email protected]94f206c12012-08-25 00:09:14778{
779 if (!layer)
780 return 0;
781
782 if (layer->scrollable())
783 return layer;
784
785 for (size_t i = 0; i < layer->children().size(); ++i) {
[email protected]96baf3e2012-10-22 23:09:55786 LayerImpl* found = findRootScrollLayer(layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:14787 if (found)
788 return found;
789 }
790
791 return 0;
792}
793
794// Content layers can be either directly scrollable or contained in an outer
795// scrolling layer which applies the scroll transform. Given a content layer,
796// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55797static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14798{
799 if (!layerImpl)
800 return 0;
801
802 if (layerImpl->scrollable())
803 return layerImpl;
804
805 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
806 return layerImpl->parent();
807
808 return 0;
809}
810
[email protected]96baf3e2012-10-22 23:09:55811void LayerTreeHostImpl::setRootLayer(scoped_ptr<LayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:14812{
[email protected]e0bd43a2012-10-12 16:54:21813 m_rootLayerImpl = layer.Pass();
[email protected]94f206c12012-08-25 00:09:14814 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
815 m_currentlyScrollingLayerImpl = 0;
816
817 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
[email protected]96baf3e2012-10-22 23:09:55818 m_currentlyScrollingLayerImpl = LayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
[email protected]94f206c12012-08-25 00:09:14819
820 m_scrollingLayerIdFromPreviousTree = -1;
[email protected]8db2213c2012-09-05 22:08:21821
822 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14823}
824
[email protected]96baf3e2012-10-22 23:09:55825scoped_ptr<LayerImpl> LayerTreeHostImpl::detachLayerTree()
[email protected]94f206c12012-08-25 00:09:14826{
827 // Clear all data structures that have direct references to the layer tree.
828 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
829 m_currentlyScrollingLayerImpl = 0;
830 m_renderSurfaceLayerList.clear();
831
[email protected]e0bd43a2012-10-12 16:54:21832 return m_rootLayerImpl.Pass();
[email protected]94f206c12012-08-25 00:09:14833}
834
[email protected]96baf3e2012-10-22 23:09:55835void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14836{
[email protected]61de5812012-11-08 07:03:44837 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14838
839 if (m_visible == visible)
840 return;
841 m_visible = visible;
842 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:28843 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:14844
845 if (!m_renderer)
846 return;
847
848 m_renderer->setVisible(visible);
849
850 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
851}
852
[email protected]96baf3e2012-10-22 23:09:55853bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<GraphicsContext> context)
[email protected]94f206c12012-08-25 00:09:14854{
[email protected]be3181652012-09-25 13:02:13855 // Since we will create a new resource provider, we cannot continue to use
856 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
857 // before we destroy the old resource provider.
[email protected]94f206c12012-08-25 00:09:14858 if (m_rootLayerImpl) {
859 clearRenderSurfaces();
860 sendDidLoseContextRecursive(m_rootLayerImpl.get());
861 }
[email protected]be3181652012-09-25 13:02:13862 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47863 m_renderer.reset();
[email protected]a7aa5562012-10-17 14:12:44864 m_resourceProvider.reset();
[email protected]e28efacd2012-10-06 17:07:49865 m_context.reset();
[email protected]94f206c12012-08-25 00:09:14866
[email protected]be3181652012-09-25 13:02:13867 if (!context->bindToClient(this))
868 return false;
869
[email protected]96baf3e2012-10-22 23:09:55870 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(context.get());
[email protected]be3181652012-09-25 13:02:13871 if (!resourceProvider)
872 return false;
873
874 if (context->context3D())
[email protected]96baf3e2012-10-22 23:09:55875 m_renderer = GLRenderer::create(this, resourceProvider.get());
[email protected]be3181652012-09-25 13:02:13876 else if (context->softwareDevice())
[email protected]96baf3e2012-10-22 23:09:55877 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), context->softwareDevice());
[email protected]be3181652012-09-25 13:02:13878 if (!m_renderer)
879 return false;
880
[email protected]a7aa5562012-10-17 14:12:44881 m_resourceProvider = resourceProvider.Pass();
[email protected]e28efacd2012-10-06 17:07:49882 m_context = context.Pass();
[email protected]94f206c12012-08-25 00:09:14883
[email protected]be3181652012-09-25 13:02:13884 if (!m_visible)
885 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:14886
[email protected]8db2213c2012-09-05 22:08:21887 m_client->onCanDrawStateChanged(canDraw());
888
[email protected]be3181652012-09-25 13:02:13889 return true;
[email protected]94f206c12012-08-25 00:09:14890}
891
[email protected]96baf3e2012-10-22 23:09:55892void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:09893{
894 m_contentsTexturesPurged = true;
895 m_client->onCanDrawStateChanged(canDraw());
896}
897
[email protected]96baf3e2012-10-22 23:09:55898void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:21899{
900 m_contentsTexturesPurged = false;
901 m_client->onCanDrawStateChanged(canDraw());
902}
903
[email protected]aad0a0072012-11-01 18:15:58904void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:14905{
906 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
907 return;
908
909 m_layoutViewportSize = layoutViewportSize;
910 m_deviceViewportSize = deviceViewportSize;
911
[email protected]c9c1ebe2012-11-05 20:46:13912 m_pinchZoomViewport.setLayoutViewportSize(layoutViewportSize);
[email protected]1c0c9bc2012-10-08 22:41:48913
[email protected]c9c1ebe2012-11-05 20:46:13914 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:14915
916 if (m_renderer)
917 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:21918
919 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14920}
921
[email protected]96baf3e2012-10-22 23:09:55922static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:14923{
924 if (!layerImpl)
925 return;
926
927 if (layerImpl->scrollable()) {
928 // We need to convert impl-side scroll deltas to pageScale space.
[email protected]c9c1ebe2012-11-05 20:46:13929 gfx::Vector2dF scrollDelta = layerImpl->scrollDelta();
930 scrollDelta.Scale(pageScaleChange);
[email protected]94f206c12012-08-25 00:09:14931 layerImpl->setScrollDelta(scrollDelta);
932 }
933
934 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:03935 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:14936}
937
[email protected]96baf3e2012-10-22 23:09:55938void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:14939{
940 if (deviceScaleFactor == m_deviceScaleFactor)
941 return;
942 m_deviceScaleFactor = deviceScaleFactor;
[email protected]c0dd24c2012-08-30 23:25:27943
[email protected]c9c1ebe2012-11-05 20:46:13944 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:14945}
946
[email protected]96baf3e2012-10-22 23:09:55947float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:14948{
[email protected]1c0c9bc2012-10-08 22:41:48949 return m_pinchZoomViewport.pageScaleFactor();
950}
[email protected]94f206c12012-08-25 00:09:14951
[email protected]96baf3e2012-10-22 23:09:55952void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:48953{
954 if (!pageScaleFactor)
955 return;
[email protected]94f206c12012-08-25 00:09:14956
[email protected]1c0c9bc2012-10-08 22:41:48957 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
958 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:14959
[email protected]65bfd9972012-10-19 03:39:37960 if (!Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48961 if (pageScaleChange != 1)
962 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
963 }
[email protected]94f206c12012-08-25 00:09:14964
965 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:48966 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
967 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:14968}
969
[email protected]96baf3e2012-10-22 23:09:55970void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:14971{
[email protected]1c0c9bc2012-10-08 22:41:48972 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:14973
[email protected]c9c1ebe2012-11-05 20:46:13974 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:14975}
976
[email protected]c9c1ebe2012-11-05 20:46:13977void LayerTreeHostImpl::updateMaxScrollOffset()
[email protected]94f206c12012-08-25 00:09:14978{
979 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
980 return;
981
[email protected]aad0a0072012-11-01 18:15:58982 gfx::SizeF viewBounds = m_deviceViewportSize;
[email protected]96baf3e2012-10-22 23:09:55983 if (LayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:14984 // Compensate for non-overlay scrollbars.
[email protected]01a15a72012-11-10 09:34:28985 if (clipLayer->masksToBounds())
986 viewBounds = gfx::ScaleSize(clipLayer->bounds(), m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14987 }
[email protected]94f206c12012-08-25 00:09:14988
[email protected]aad0a0072012-11-01 18:15:58989 gfx::Size contentBounds = contentSize();
[email protected]65bfd9972012-10-19 03:39:37990 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48991 // Pinch with pageScale scrolls entirely in layout space. contentSize
992 // returns the bounds including the page scale factor, so calculate the
993 // pre page-scale layout size here.
994 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
[email protected]aad0a0072012-11-01 18:15:58995 contentBounds.set_width(contentBounds.width() / pageScaleFactor);
996 contentBounds.set_height(contentBounds.height() / pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:48997 } else {
[email protected]01a15a72012-11-10 09:34:28998 viewBounds.Scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:48999 }
1000
[email protected]c9c1ebe2012-11-05 20:46:131001 gfx::Vector2dF maxScroll = BottomRight(gfx::Rect(contentBounds)) - BottomRight(gfx::RectF(viewBounds));
1002 maxScroll.Scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:481003
[email protected]94f206c12012-08-25 00:09:141004 // The viewport may be larger than the contents in some cases, such as
1005 // having a vertical scrollbar but no horizontal overflow.
[email protected]fe07b642012-11-10 00:07:591006 maxScroll.ClampToMin(gfx::Vector2dF());
[email protected]94f206c12012-08-25 00:09:141007
[email protected]c9c1ebe2012-11-05 20:46:131008 m_rootScrollLayerImpl->setMaxScrollOffset(gfx::ToFlooredVector2d(maxScroll));
[email protected]94f206c12012-08-25 00:09:141009}
1010
[email protected]96baf3e2012-10-22 23:09:551011void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141012{
1013 m_client->setNeedsRedrawOnImplThread();
1014}
1015
[email protected]96baf3e2012-10-22 23:09:551016bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141017{
1018 if (!m_rootLayerImpl)
1019 return false;
1020 if (!m_renderer)
1021 return false;
1022
1023 // We need both a non-empty render surface layer list and a root render
1024 // surface to be able to iterate over the visible layers.
1025 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
1026 return true;
1027
1028 // If we are called after setRootLayer() but before prepareToDraw(), we need
1029 // to recalculate the visible layers. This prevents being unable to scroll
1030 // during part of a commit.
1031 m_renderSurfaceLayerList.clear();
1032 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
1033
1034 return m_renderSurfaceLayerList.size();
1035}
1036
[email protected]c9c1ebe2012-11-05 20:46:131037InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141038{
[email protected]96baf3e2012-10-22 23:09:551039 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141040
[email protected]1d993172012-10-18 18:15:041041 DCHECK(!m_currentlyScrollingLayerImpl);
[email protected]94f206c12012-08-25 00:09:141042 clearCurrentlyScrollingLayer();
1043
1044 if (!ensureRenderSurfaceLayerList())
1045 return ScrollIgnored;
1046
[email protected]faf56352012-11-09 21:44:131047 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141048
1049 // First find out which layer was hit from the saved list of visible layers
1050 // in the most recent frame.
[email protected]96baf3e2012-10-22 23:09:551051 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:141052
1053 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551054 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141055 for (; layerImpl; layerImpl = layerImpl->parent()) {
1056 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271057 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1058 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141059 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271060 }
[email protected]94f206c12012-08-25 00:09:141061
[email protected]96baf3e2012-10-22 23:09:551062 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141063 if (!scrollLayerImpl)
1064 continue;
1065
[email protected]31bfe272012-10-19 18:49:521066 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141067
1068 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271069 if (status == ScrollOnMainThread) {
1070 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141071 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271072 }
[email protected]94f206c12012-08-25 00:09:141073
1074 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1075 potentiallyScrollingLayerImpl = scrollLayerImpl;
1076 }
1077
1078 if (potentiallyScrollingLayerImpl) {
1079 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
[email protected]31bfe272012-10-19 18:49:521080 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141081 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1082 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521083 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271084 m_numImplThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141085 return ScrollStarted;
1086 }
1087 return ScrollIgnored;
1088}
1089
[email protected]c9c1ebe2012-11-05 20:46:131090static gfx::Vector2dF scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::Vector2dF viewportDelta)
[email protected]94f206c12012-08-25 00:09:141091{
1092 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1093 // test in the first place.
[email protected]1d993172012-10-18 18:15:041094 DCHECK(layerImpl.screenSpaceTransform().isInvertible());
[email protected]94f206c12012-08-25 00:09:141095 WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse();
1096
[email protected]faf56352012-11-09 21:44:131097 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521098
[email protected]c9c1ebe2012-11-05 20:46:131099 gfx::Vector2dF screenSpaceDelta = viewportDelta;
1100 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521101
[email protected]94f206c12012-08-25 00:09:141102 // First project the scroll start and end points to local layer space to find the scroll delta
1103 // in layer coordinates.
1104 bool startClipped, endClipped;
[email protected]d455d552012-11-02 00:19:061105 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1106 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1107 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141108
1109 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041110 DCHECK(!startClipped);
1111 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141112 if (startClipped || endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131113 return gfx::Vector2dF();
[email protected]94f206c12012-08-25 00:09:141114
[email protected]31bfe272012-10-19 18:49:521115 // localStartPoint and localEndPoint are in content space but we want to move them to layer space for scrolling.
[email protected]aad0a0072012-11-01 18:15:581116 float widthScale = 1 / layerImpl.contentsScaleX();
1117 float heightScale = 1 / layerImpl.contentsScaleY();
[email protected]faf56352012-11-09 21:44:131118 localStartPoint.Scale(widthScale, heightScale);
1119 localEndPoint.Scale(widthScale, heightScale);
[email protected]31bfe272012-10-19 18:49:521120
[email protected]94f206c12012-08-25 00:09:141121 // Apply the scroll delta.
[email protected]c9c1ebe2012-11-05 20:46:131122 gfx::Vector2dF previousDelta = layerImpl.scrollDelta();
1123 gfx::Vector2dF unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
[email protected]1c0c9bc2012-10-08 22:41:481124
1125 if (viewport)
1126 viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141127
[email protected]31bfe272012-10-19 18:49:521128 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]d455d552012-11-02 00:19:061129 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
[email protected]faf56352012-11-09 21:44:131130 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint, 1 / widthScale, 1 / heightScale);
[email protected]31bfe272012-10-19 18:49:521131
1132 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]d455d552012-11-02 00:19:061133 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041134 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141135 if (endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131136 return gfx::Vector2dF();
[email protected]faf56352012-11-09 21:44:131137 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoint, 1 / scaleFromViewportToScreenSpace);
[email protected]c9c1ebe2012-11-05 20:46:131138 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141139}
1140
[email protected]c9c1ebe2012-11-05 20:46:131141static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vector2dF localDelta)
[email protected]94f206c12012-08-25 00:09:141142{
[email protected]c9c1ebe2012-11-05 20:46:131143 gfx::Vector2dF previousDelta(layerImpl.scrollDelta());
[email protected]94f206c12012-08-25 00:09:141144 layerImpl.scrollBy(localDelta);
1145 return layerImpl.scrollDelta() - previousDelta;
1146}
1147
[email protected]a9710962012-11-14 20:11:021148bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint,
1149 const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141150{
[email protected]96baf3e2012-10-22 23:09:551151 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]94f206c12012-08-25 00:09:141152 if (!m_currentlyScrollingLayerImpl)
[email protected]a9710962012-11-14 20:11:021153 return false;
[email protected]94f206c12012-08-25 00:09:141154
[email protected]c9c1ebe2012-11-05 20:46:131155 gfx::Vector2dF pendingDelta = scrollDelta;
[email protected]94f206c12012-08-25 00:09:141156
[email protected]96baf3e2012-10-22 23:09:551157 for (LayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141158 if (!layerImpl->scrollable())
1159 continue;
1160
[email protected]96baf3e2012-10-22 23:09:551161 PinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
[email protected]c9c1ebe2012-11-05 20:46:131162 gfx::Vector2dF appliedDelta;
[email protected]31bfe272012-10-19 18:49:521163 if (m_scrollDeltaIsInViewportSpace) {
1164 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1165 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1166 } else
[email protected]94f206c12012-08-25 00:09:141167 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1168
1169 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381170 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]c9c1ebe2012-11-05 20:46:131171 if (appliedDelta.LengthSquared() < moveThresholdSquared)
[email protected]94f206c12012-08-25 00:09:141172 continue;
1173
1174 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1175 // to scroll just one layer in one direction without affecting any of its parents.
1176 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551177 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]c9c1ebe2012-11-05 20:46:131178 pendingDelta = gfx::Vector2d();
[email protected]94f206c12012-08-25 00:09:141179 break;
1180 }
1181
1182 // Allow further movement only on an axis perpendicular to the direction in which the layer
1183 // moved.
[email protected]c9c1ebe2012-11-05 20:46:131184 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x());
[email protected]96baf3e2012-10-22 23:09:551185 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141186
[email protected]c9c1ebe2012-11-05 20:46:131187 if (gfx::ToFlooredVector2d(pendingDelta).IsZero())
[email protected]94f206c12012-08-25 00:09:141188 break;
1189 }
1190
[email protected]c9c1ebe2012-11-05 20:46:131191 if (!scrollDelta.IsZero() && gfx::ToFlooredVector2d(pendingDelta).IsZero()) {
[email protected]94f206c12012-08-25 00:09:141192 m_client->setNeedsCommitOnImplThread();
1193 m_client->setNeedsRedrawOnImplThread();
[email protected]a9710962012-11-14 20:11:021194 return true;
[email protected]94f206c12012-08-25 00:09:141195 }
[email protected]a9710962012-11-14 20:11:021196 return false;
[email protected]94f206c12012-08-25 00:09:141197}
1198
[email protected]96baf3e2012-10-22 23:09:551199void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141200{
1201 m_currentlyScrollingLayerImpl = 0;
1202 m_scrollingLayerIdFromPreviousTree = -1;
1203}
1204
[email protected]96baf3e2012-10-22 23:09:551205void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141206{
1207 clearCurrentlyScrollingLayer();
1208}
1209
[email protected]96baf3e2012-10-22 23:09:551210void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141211{
1212 m_pinchGestureActive = true;
[email protected]c9c1ebe2012-11-05 20:46:131213 m_previousPinchAnchor = gfx::Point();
[email protected]94f206c12012-08-25 00:09:141214
1215 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1216 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
1217}
1218
[email protected]c9c1ebe2012-11-05 20:46:131219void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor)
[email protected]94f206c12012-08-25 00:09:141220{
[email protected]96baf3e2012-10-22 23:09:551221 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141222
1223 if (!m_rootScrollLayerImpl)
1224 return;
1225
[email protected]c9c1ebe2012-11-05 20:46:131226 if (m_previousPinchAnchor == gfx::Point())
[email protected]94f206c12012-08-25 00:09:141227 m_previousPinchAnchor = anchor;
1228
1229 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1230 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481231 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]faf56352012-11-09 21:44:131232 gfx::PointF previousScaleAnchor = gfx::ScalePoint(m_previousPinchAnchor, 1 / pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:481233 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1234 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]faf56352012-11-09 21:44:131235 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:131236 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor;
[email protected]94f206c12012-08-25 00:09:141237
1238 m_previousPinchAnchor = anchor;
1239
[email protected]65bfd9972012-10-19 03:39:371240 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:481241 // Compute the application of the delta with respect to the current page zoom of the page.
[email protected]c9c1ebe2012-11-05 20:46:131242 move.Scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor));
[email protected]1c0c9bc2012-10-08 22:41:481243 }
1244
[email protected]c9c1ebe2012-11-05 20:46:131245 gfx::Vector2dF scrollOverflow = Settings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move;
1246 m_rootScrollLayerImpl->scrollBy(scrollOverflow);
[email protected]94f206c12012-08-25 00:09:141247
1248 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1249 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
1250
1251 m_client->setNeedsCommitOnImplThread();
1252 m_client->setNeedsRedrawOnImplThread();
1253}
1254
[email protected]96baf3e2012-10-22 23:09:551255void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141256{
1257 m_pinchGestureActive = false;
1258
1259 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1260 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
1261
1262 m_client->setNeedsCommitOnImplThread();
1263}
1264
[email protected]96baf3e2012-10-22 23:09:551265void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141266{
[email protected]f6250742012-11-09 04:46:561267 gfx::Vector2dF scaledScrollOffset = m_pageScaleAnimation->targetScrollOffset();
1268 if (!Settings::pageScalePinchZoomEnabled())
1269 scaledScrollOffset.Scale(m_pinchZoomViewport.pageScaleFactor());
1270 makeScrollAndScaleSet(scrollInfo, ToFlooredVector2d(scaledScrollOffset), m_pageScaleAnimation->targetPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141271}
1272
[email protected]96baf3e2012-10-22 23:09:551273void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141274{
1275 if (!m_rootScrollLayerImpl)
1276 return;
1277
1278 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1279 // significant amount. This also ensures only one fake delta set will be
1280 // sent.
[email protected]23bbb412012-08-30 20:03:381281 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481282 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141283 return;
1284
1285 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1286 // out from the anchor point.
[email protected]c9c1ebe2012-11-05 20:46:131287 gfx::Vector2dF scrollBegin = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
1288 scrollBegin.Scale(m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:481289 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1290 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]01a15a72012-11-10 09:34:281291 gfx::SizeF scaledContentsSize = gfx::ScaleSize(contentSize(), pageScaleDeltaToSend);
[email protected]94f206c12012-08-25 00:09:141292
[email protected]c9c1ebe2012-11-05 20:46:131293 gfx::Vector2d anchorOffset = m_previousPinchAnchor.OffsetFromOrigin();
1294 gfx::Vector2dF scrollEnd = scrollBegin + anchorOffset;
1295 scrollEnd.Scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
1296 scrollEnd -= anchorOffset;
[email protected]fe07b642012-11-10 00:07:591297 scrollEnd.ClampToMax(BottomRight(gfx::RectF(scaledContentsSize)) - BottomRight(gfx::Rect(m_deviceViewportSize)));
1298 scrollEnd.ClampToMin(gfx::Vector2d());
[email protected]c9c1ebe2012-11-05 20:46:131299 scrollEnd.Scale(1 / pageScaleDeltaToSend);
1300 scrollEnd.Scale(m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141301
[email protected]c9c1ebe2012-11-05 20:46:131302 makeScrollAndScaleSet(scrollInfo, gfx::ToRoundedVector2d(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141303}
1304
[email protected]c9c1ebe2012-11-05 20:46:131305void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141306{
1307 if (!m_rootScrollLayerImpl)
1308 return;
1309
[email protected]96baf3e2012-10-22 23:09:551310 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141311 scroll.layerId = m_rootScrollLayerImpl->id();
[email protected]c9c1ebe2012-11-05 20:46:131312 scroll.scrollDelta = scrollOffset - m_rootScrollLayerImpl->scrollOffset();
[email protected]787465c2012-10-29 01:12:271313 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141314 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481315 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1316 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141317}
1318
[email protected]96baf3e2012-10-22 23:09:551319static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141320{
1321 if (!layerImpl)
1322 return;
1323
[email protected]c9c1ebe2012-11-05 20:46:131324 if (!layerImpl->scrollDelta().IsZero()) {
1325 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551326 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141327 scroll.layerId = layerImpl->id();
1328 scroll.scrollDelta = scrollDelta;
[email protected]787465c2012-10-29 01:12:271329 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141330 layerImpl->setSentScrollDelta(scrollDelta);
1331 }
1332
1333 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031334 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141335}
1336
[email protected]96baf3e2012-10-22 23:09:551337scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141338{
[email protected]96baf3e2012-10-22 23:09:551339 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141340
1341 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481342 scrollInfo->pageScaleDelta = 1;
1343 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]f6250742012-11-09 04:46:561344 // FIXME(aelias): Make pinch-zoom painting optimization compatible with
[email protected]1c0c9bc2012-10-08 22:41:481345 // compositor-side scaling.
[email protected]f6250742012-11-09 04:46:561346 if (!Settings::pageScalePinchZoomEnabled() && m_pinchGestureActive)
1347 computePinchZoomDeltas(scrollInfo.get());
1348 else if (m_pageScaleAnimation.get())
1349 computeDoubleTapZoomDeltas(scrollInfo.get());
[email protected]a9f4bf22012-10-11 23:39:211350 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141351 }
1352
1353 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
[email protected]1c0c9bc2012-10-08 22:41:481354 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1355 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141356
[email protected]a9f4bf22012-10-11 23:39:211357 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141358}
1359
[email protected]96baf3e2012-10-22 23:09:551360WebTransformationMatrix LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481361{
1362 return m_pinchZoomViewport.implTransform();
1363}
1364
[email protected]96baf3e2012-10-22 23:09:551365void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141366{
1367 if (m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:551368 RenderSurfaceImpl* renderSurface = m_rootLayerImpl->renderSurface();
[email protected]94f206c12012-08-25 00:09:141369 if (renderSurface)
1370 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1371 }
1372}
1373
[email protected]30faac92012-10-29 00:06:291374void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141375{
1376 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1377 return;
1378
[email protected]30faac92012-10-29 00:06:291379 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]c9c1ebe2012-11-05 20:46:131380 gfx::Vector2dF scrollTotal = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
[email protected]94f206c12012-08-25 00:09:141381
[email protected]f6250742012-11-09 04:46:561382 setPageScaleDelta(m_pageScaleAnimation->pageScaleFactorAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]c9c1ebe2012-11-05 20:46:131383 gfx::Vector2dF nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]f6250742012-11-09 04:46:561384
1385 if (!Settings::pageScalePinchZoomEnabled())
1386 nextScroll.Scale(m_pinchZoomViewport.pageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141387 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1388 m_client->setNeedsRedrawOnImplThread();
1389
1390 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451391 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141392 m_client->setNeedsCommitOnImplThread();
1393 }
1394}
1395
[email protected]30faac92012-10-29 00:06:291396void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:141397{
[email protected]65bfd9972012-10-19 03:39:371398 if (!Settings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
[email protected]94f206c12012-08-25 00:09:141399 return;
1400
[email protected]96baf3e2012-10-22 23:09:551401 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141402
[email protected]96baf3e2012-10-22 23:09:551403 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
[email protected]94f206c12012-08-25 00:09:141404
1405 bool didAnimate = false;
1406 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1407
[email protected]d3143c732012-10-05 19:17:591408 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571409 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141410
1411 if (didAnimate)
1412 m_client->setNeedsRedrawOnImplThread();
1413
1414 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1415}
1416
[email protected]96baf3e2012-10-22 23:09:551417base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141418{
[email protected]4481ddb622012-09-20 16:33:471419 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141420}
1421
[email protected]96baf3e2012-10-22 23:09:551422void LayerTreeHostImpl::sendDidLoseContextRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141423{
[email protected]1d993172012-10-18 18:15:041424 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141425 current->didLoseContext();
1426 if (current->maskLayer())
1427 sendDidLoseContextRecursive(current->maskLayer());
1428 if (current->replicaLayer())
1429 sendDidLoseContextRecursive(current->replicaLayer());
1430 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031431 sendDidLoseContextRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141432}
1433
[email protected]96baf3e2012-10-22 23:09:551434static void clearRenderSurfacesOnLayerImplRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141435{
[email protected]1d993172012-10-18 18:15:041436 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141437 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]96baf3e2012-10-22 23:09:551438 clearRenderSurfacesOnLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141439 current->clearRenderSurface();
1440}
1441
[email protected]96baf3e2012-10-22 23:09:551442void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141443{
[email protected]96baf3e2012-10-22 23:09:551444 clearRenderSurfacesOnLayerImplRecursive(m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141445 m_renderSurfaceLayerList.clear();
1446}
1447
[email protected]96baf3e2012-10-22 23:09:551448std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141449{
[email protected]515e8d232012-09-10 19:15:271450 std::string str;
[email protected]94f206c12012-08-25 00:09:141451 if (m_rootLayerImpl) {
[email protected]515e8d232012-09-10 19:15:271452 str = m_rootLayerImpl->layerTreeAsText();
1453 str += "RenderSurfaces:\n";
1454 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141455 }
[email protected]515e8d232012-09-10 19:15:271456 return str;
[email protected]94f206c12012-08-25 00:09:141457}
1458
[email protected]96baf3e2012-10-22 23:09:551459void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141460{
1461 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271462 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141463
1464 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031465 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141466}
1467
[email protected]96baf3e2012-10-22 23:09:551468int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141469{
1470 return fpsCounter()->currentFrameNumber();
1471}
1472
[email protected]96baf3e2012-10-22 23:09:551473void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141474{
[email protected]8b9af6b2012-09-27 00:36:361475 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1476 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271477 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1478 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]94f206c12012-08-25 00:09:141479}
1480
[email protected]30faac92012-10-29 00:06:291481void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141482{
[email protected]30faac92012-10-29 00:06:291483 animateScrollbarsRecursive(m_rootLayerImpl.get(), time);
[email protected]94f206c12012-08-25 00:09:141484}
1485
[email protected]30faac92012-10-29 00:06:291486void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141487{
1488 if (!layer)
1489 return;
1490
[email protected]96baf3e2012-10-22 23:09:551491 ScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]30faac92012-10-29 00:06:291492 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]94f206c12012-08-25 00:09:141493 if (scrollbarController && scrollbarController->animate(monotonicTime))
1494 m_client->setNeedsRedrawOnImplThread();
1495
1496 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]30faac92012-10-29 00:06:291497 animateScrollbarsRecursive(layer->children()[i], time);
[email protected]94f206c12012-08-25 00:09:141498}
1499
[email protected]d3143c732012-10-05 19:17:591500} // namespace cc