blob: e7874b66876abe4d2bc36bb9462bd36a68f3e419 [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]4a23c374c2012-12-08 08:38:5511#include "base/json/json_writer.h"
[email protected]aa0a9d32012-10-24 01:58:1012#include "cc/append_quads_data.h"
13#include "cc/damage_tracker.h"
14#include "cc/debug_rect_history.h"
15#include "cc/delay_based_time_source.h"
[email protected]ea9d8f22012-12-08 03:39:2916#include "cc/delegating_renderer.h"
[email protected]aa0a9d32012-10-24 01:58:1017#include "cc/frame_rate_counter.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]8bef40572012-12-11 21:38:0823#include "cc/layer_tree_impl.h"
[email protected]55a124d02012-10-22 03:07:1324#include "cc/math_util.h"
25#include "cc/overdraw_metrics.h"
26#include "cc/page_scale_animation.h"
[email protected]3b10a302012-11-07 21:16:4027#include "cc/prioritized_resource_manager.h"
[email protected]f57bbc02012-11-21 07:02:1528#include "cc/quad_culler.h"
[email protected]55a124d02012-10-22 03:07:1329#include "cc/render_pass_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4030#include "cc/rendering_stats.h"
31#include "cc/scrollbar_animation_controller.h"
32#include "cc/scrollbar_layer_impl.h"
[email protected]f57bbc02012-11-21 07:02:1533#include "cc/shared_quad_state.h"
[email protected]4456eee22012-10-19 18:16:3834#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4035#include "cc/software_renderer.h"
[email protected]f57bbc02012-11-21 07:02:1536#include "cc/solid_color_draw_quad.h"
[email protected]a8461d82012-10-16 21:11:1437#include "cc/texture_uploader.h"
[email protected]d3afa112012-12-08 06:24:2838#include "cc/util.h"
[email protected]d455d552012-11-02 00:19:0639#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1340#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1441
[email protected]94f206c12012-08-25 00:09:1442namespace {
43
[email protected]96baf3e2012-10-22 23:09:5544void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1445{
46 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5547 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1448 return;
49 }
50
[email protected]96baf3e2012-10-22 23:09:5551 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1452}
53
54} // namespace
55
[email protected]9c88e562012-09-14 22:21:3056namespace cc {
[email protected]94f206c12012-08-25 00:09:1457
[email protected]96baf3e2012-10-22 23:09:5558PinchZoomViewport::PinchZoomViewport()
[email protected]1c0c9bc2012-10-08 22:41:4859 : m_pageScaleFactor(1)
60 , m_pageScaleDelta(1)
61 , m_sentPageScaleDelta(1)
62 , m_minPageScaleFactor(0)
63 , m_maxPageScaleFactor(0)
[email protected]e39bf212012-11-22 21:04:0364 , m_deviceScaleFactor(1)
[email protected]1c0c9bc2012-10-08 22:41:4865{
66}
67
[email protected]96baf3e2012-10-22 23:09:5568float PinchZoomViewport::totalPageScaleFactor() const
[email protected]1c0c9bc2012-10-08 22:41:4869{
70 return m_pageScaleFactor * m_pageScaleDelta;
71}
72
[email protected]96baf3e2012-10-22 23:09:5573void PinchZoomViewport::setPageScaleDelta(float delta)
[email protected]1c0c9bc2012-10-08 22:41:4874{
75 // Clamp to the current min/max limits.
76 float totalPageScaleFactor = m_pageScaleFactor * delta;
77 if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
78 delta = m_minPageScaleFactor / m_pageScaleFactor;
79 else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
80 delta = m_maxPageScaleFactor / m_pageScaleFactor;
81
82 if (delta == m_pageScaleDelta)
83 return;
84
85 m_pageScaleDelta = delta;
86}
87
[email protected]96baf3e2012-10-22 23:09:5588bool PinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:4889{
[email protected]1d993172012-10-18 18:15:0490 DCHECK(pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:4891
92 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
93 return false;
94
95 m_minPageScaleFactor = minPageScaleFactor;
96 m_maxPageScaleFactor = maxPageScaleFactor;
97
98 m_pageScaleFactor = pageScaleFactor;
99 return true;
100}
101
[email protected]aad0a0072012-11-01 18:15:58102gfx::RectF PinchZoomViewport::bounds() const
[email protected]1c0c9bc2012-10-08 22:41:48103{
[email protected]2e6486012012-11-10 00:03:19104 gfx::RectF bounds(gfx::PointF(), m_layoutViewportSize);
105 bounds.Scale(1 / totalPageScaleFactor());
[email protected]e39bf212012-11-22 21:04:03106 bounds += m_zoomedViewportOffset;
[email protected]1c0c9bc2012-10-08 22:41:48107 return bounds;
108}
109
[email protected]c9c1ebe2012-11-05 20:46:13110gfx::Vector2dF PinchZoomViewport::applyScroll(const gfx::Vector2dF& delta)
[email protected]1c0c9bc2012-10-08 22:41:48111{
[email protected]d0f98362012-11-01 23:02:38112 gfx::Vector2dF overflow;
[email protected]2e6486012012-11-10 00:03:19113 gfx::RectF pinchedBounds = bounds() + delta;
[email protected]1c0c9bc2012-10-08 22:41:48114
[email protected]1c0c9bc2012-10-08 22:41:48115 if (pinchedBounds.x() < 0) {
[email protected]d0f98362012-11-01 23:02:38116 overflow.set_x(pinchedBounds.x());
117 pinchedBounds.set_x(0);
[email protected]1c0c9bc2012-10-08 22:41:48118 }
119
120 if (pinchedBounds.y() < 0) {
[email protected]d0f98362012-11-01 23:02:38121 overflow.set_y(pinchedBounds.y());
122 pinchedBounds.set_y(0);
[email protected]1c0c9bc2012-10-08 22:41:48123 }
124
[email protected]d0f98362012-11-01 23:02:38125 if (pinchedBounds.right() > m_layoutViewportSize.width()) {
126 overflow.set_x(pinchedBounds.right() - m_layoutViewportSize.width());
[email protected]2e6486012012-11-10 00:03:19127 pinchedBounds += gfx::Vector2dF(m_layoutViewportSize.width() - pinchedBounds.right(), 0);
[email protected]1c0c9bc2012-10-08 22:41:48128 }
129
[email protected]d0f98362012-11-01 23:02:38130 if (pinchedBounds.bottom() > m_layoutViewportSize.height()) {
131 overflow.set_y(pinchedBounds.bottom() - m_layoutViewportSize.height());
[email protected]2e6486012012-11-10 00:03:19132 pinchedBounds += gfx::Vector2dF(0, m_layoutViewportSize.height() - pinchedBounds.bottom());
[email protected]1c0c9bc2012-10-08 22:41:48133 }
[email protected]e39bf212012-11-22 21:04:03134 m_zoomedViewportOffset = pinchedBounds.OffsetFromOrigin();
[email protected]1c0c9bc2012-10-08 22:41:48135
[email protected]c9c1ebe2012-11-05 20:46:13136 return overflow;
[email protected]1c0c9bc2012-10-08 22:41:48137}
138
[email protected]c8686a02012-11-27 08:29:00139gfx::Transform PinchZoomViewport::implTransform(bool pageScalePinchZoomEnabled) const
[email protected]1c0c9bc2012-10-08 22:41:48140{
[email protected]c8686a02012-11-27 08:29:00141 gfx::Transform transform;
142 transform.Scale(m_pageScaleDelta, m_pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:48143
144 // If the pinch state is applied in the impl, then push it to the
145 // impl transform, otherwise the scale is handled by WebCore.
[email protected]9bdcfd642012-11-14 21:24:26146 if (pageScalePinchZoomEnabled) {
[email protected]c8686a02012-11-27 08:29:00147 transform.Scale(m_pageScaleFactor, m_pageScaleFactor);
[email protected]e39bf212012-11-22 21:04:03148 // The offset needs to be scaled by deviceScaleFactor as this transform
149 // needs to work with physical pixels.
150 gfx::Vector2dF zoomedDeviceViewportOffset = gfx::ScaleVector2d(m_zoomedViewportOffset, m_deviceScaleFactor);
[email protected]c8686a02012-11-27 08:29:00151 transform.Translate(-zoomedDeviceViewportOffset.x(), -zoomedDeviceViewportOffset.y());
[email protected]1c0c9bc2012-10-08 22:41:48152 }
153
154 return transform;
155}
156
[email protected]96baf3e2012-10-22 23:09:55157class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14158public:
[email protected]96baf3e2012-10-22 23:09:55159 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14160 {
[email protected]96baf3e2012-10-22 23:09:55161 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:14162 }
[email protected]96baf3e2012-10-22 23:09:55163 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:14164 {
165 m_timeSource->setClient(0);
166 m_timeSource->setActive(false);
167 }
168
169 virtual void onTimerTick() OVERRIDE
170 {
[email protected]30faac92012-10-29 00:06:29171 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]94f206c12012-08-25 00:09:14172 }
173
174 void setActive(bool active)
175 {
176 if (active != m_timeSource->active())
177 m_timeSource->setActive(active);
178 }
179
180private:
[email protected]96baf3e2012-10-22 23:09:55181 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14182 : m_layerTreeHostImpl(layerTreeHostImpl)
183 , m_timeSource(timeSource)
184 {
185 m_timeSource->setClient(this);
186 }
187
[email protected]96baf3e2012-10-22 23:09:55188 LayerTreeHostImpl* m_layerTreeHostImpl;
189 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20190
[email protected]96baf3e2012-10-22 23:09:55191 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14192};
193
[email protected]96baf3e2012-10-22 23:09:55194LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10195{
196}
197
[email protected]96baf3e2012-10-22 23:09:55198LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10199{
200}
201
[email protected]61de5812012-11-08 07:03:44202scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14203{
[email protected]61de5812012-11-08 07:03:44204 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
[email protected]94f206c12012-08-25 00:09:14205}
206
[email protected]61de5812012-11-08 07:03:44207LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14208 : m_client(client)
[email protected]61de5812012-11-08 07:03:44209 , m_proxy(proxy)
[email protected]31bfe272012-10-19 18:49:52210 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14211 , m_settings(settings)
[email protected]f511afb2012-11-30 01:55:20212 , m_debugState(settings.initialDebugState)
[email protected]94f206c12012-08-25 00:09:14213 , m_deviceScaleFactor(1)
214 , m_visible(true)
215 , m_contentsTexturesPurged(false)
[email protected]3b10a302012-11-07 21:16:40216 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
[email protected]96baf3e2012-10-22 23:09:55217 PriorityCalculator::allowEverythingCutoff(),
[email protected]a0a00842012-10-22 22:50:28218 0,
[email protected]96baf3e2012-10-22 23:09:55219 PriorityCalculator::allowNothingCutoff())
[email protected]94f206c12012-08-25 00:09:14220 , m_backgroundColor(0)
221 , m_hasTransparentBackground(false)
[email protected]df1ec1a2012-12-08 17:01:18222 , m_needsAnimateLayers(false)
[email protected]0ede3bb2012-12-09 09:14:39223 , m_needsUpdateDrawProperties(false)
[email protected]94f206c12012-08-25 00:09:14224 , m_pinchGestureActive(false)
[email protected]61de5812012-11-08 07:03:44225 , m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
[email protected]96baf3e2012-10-22 23:09:55226 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27227 , m_numImplThreadScrolls(0)
228 , m_numMainThreadScrolls(0)
[email protected]b2136f12012-11-30 02:45:53229 , m_cumulativeNumLayersDrawn(0)
[email protected]f2bbb4e2012-12-07 21:40:49230 , m_cumulativeNumMissingTiles(0)
[email protected]d3afa112012-12-08 06:24:28231 , m_lastSentMemoryVisibleBytes(0)
232 , m_lastSentMemoryVisibleAndNearbyBytes(0)
233 , m_lastSentMemoryUseBytes(0)
[email protected]94f206c12012-08-25 00:09:14234{
[email protected]61de5812012-11-08 07:03:44235 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14236 didVisibilityChange(this, m_visible);
[email protected]3b31c6ac2012-12-06 21:27:29237
238 // TODO(nduca): For now, assume we have an active tree. This will be removed
239 // in future patches.
240 m_activeTree = LayerTreeImpl::create(this);
[email protected]94f206c12012-08-25 00:09:14241}
242
[email protected]96baf3e2012-10-22 23:09:55243LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14244{
[email protected]61de5812012-11-08 07:03:44245 DCHECK(m_proxy->isImplThread());
[email protected]96baf3e2012-10-22 23:09:55246 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14247
[email protected]df1ec1a2012-12-08 17:01:18248 if (rootLayer())
[email protected]94f206c12012-08-25 00:09:14249 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]0ede3bb2012-12-09 09:14:39259
260 // Impl-side painting needs an update immediately post-commit to have the
261 // opportunity to create tilings. Other paths can call updateDrawProperties
262 // more lazily when needed prior to drawing.
263 setNeedsUpdateDrawProperties();
264 if (m_settings.implSidePainting)
265 updateDrawProperties();
266
[email protected]94f206c12012-08-25 00:09:14267 // Recompute max scroll position; must be after layer content bounds are
268 // updated.
[email protected]c9c1ebe2012-11-05 20:46:13269 updateMaxScrollOffset();
[email protected]3d21e022012-10-25 20:03:08270 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14271}
272
[email protected]96baf3e2012-10-22 23:09:55273bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14274{
[email protected]8db2213c2012-09-05 22:08:21275 // Note: If you are changing this function or any other function that might
276 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
277 // in the proper places and update the notifyIfCanDrawChanged test.
278
[email protected]3b31c6ac2012-12-06 21:27:29279 if (!rootLayer()) {
[email protected]96baf3e2012-10-22 23:09:55280 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14281 return false;
282 }
[email protected]aad0a0072012-11-01 18:15:58283 if (deviceViewportSize().IsEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55284 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14285 return false;
286 }
287 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55288 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14289 return false;
290 }
291 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55292 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14293 return false;
294 }
295 return true;
296}
297
[email protected]3be2171d2012-12-06 06:13:20298OutputSurface* LayerTreeHostImpl::outputSurface() const
[email protected]94f206c12012-08-25 00:09:14299{
[email protected]3be2171d2012-12-06 06:13:20300 return m_outputSurface.get();
[email protected]94f206c12012-08-25 00:09:14301}
302
[email protected]30faac92012-10-29 00:06:29303void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:14304{
305 animatePageScale(monotonicTime);
306 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14307 animateScrollbars(monotonicTime);
308}
309
[email protected]8947cbe2012-11-28 05:27:43310void LayerTreeHostImpl::manageTiles()
311{
312 DCHECK(m_tileManager);
313 m_tileManager->ManageTiles();
314}
315
[email protected]69a2a5be2012-11-14 06:51:44316void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration)
[email protected]94f206c12012-08-25 00:09:14317{
[email protected]3b31c6ac2012-12-06 21:27:29318 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:14319 return;
320
[email protected]3b31c6ac2012-12-06 21:27:29321 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]f6250742012-11-09 04:46:56322 gfx::SizeF scaledContentSize = contentSize();
[email protected]9bdcfd642012-11-14 21:24:26323 if (!m_settings.pageScalePinchZoomEnabled) {
[email protected]f6250742012-11-09 04:46:56324 scrollTotal.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]01a15a72012-11-10 09:34:28325 scaledContentSize.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]f6250742012-11-09 04:46:56326 }
[email protected]01a15a72012-11-10 09:34:28327 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14328
[email protected]30faac92012-10-29 00:06:29329 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
[email protected]f6250742012-11-09 04:46:56330 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, m_pinchZoomViewport.totalPageScaleFactor(), viewportSize, scaledContentSize, startTimeSeconds);
[email protected]94f206c12012-08-25 00:09:14331
332 if (anchorPoint) {
[email protected]69a2a5be2012-11-14 06:51:44333 gfx::Vector2dF anchor(targetOffset);
[email protected]9bdcfd642012-11-14 21:24:26334 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:56335 anchor.Scale(1 / pageScale);
336 m_pageScaleAnimation->zoomWithAnchor(anchor, pageScale, duration.InSecondsF());
337 } else {
[email protected]69a2a5be2012-11-14 06:51:44338 gfx::Vector2dF scaledTargetOffset = targetOffset;
[email protected]9bdcfd642012-11-14 21:24:26339 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]69a2a5be2012-11-14 06:51:44340 scaledTargetOffset.Scale(1 / pageScale);
341 m_pageScaleAnimation->zoomTo(scaledTargetOffset, pageScale, duration.InSecondsF());
[email protected]f6250742012-11-09 04:46:56342 }
[email protected]94f206c12012-08-25 00:09:14343
[email protected]0ede3bb2012-12-09 09:14:39344 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:14345 m_client->setNeedsRedrawOnImplThread();
346 m_client->setNeedsCommitOnImplThread();
347}
348
[email protected]96baf3e2012-10-22 23:09:55349void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14350{
351 m_client->setNeedsRedrawOnImplThread();
352}
353
[email protected]2f1acc262012-11-16 21:42:22354bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint)
355{
356
357 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
358
359 // First find out which layer was hit from the saved list of visible layers
360 // in the most recent frame.
[email protected]35d2edd22012-12-13 02:19:05361 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]2f1acc262012-11-16 21:42:22362
[email protected]35d2edd22012-12-13 02:19:05363 // Walk up the hierarchy and look for a layer with a touch event handler region that the given point hits.
364 for (; layerImpl; layerImpl = layerImpl->parent()) {
365 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint,layerImpl))
366 return true;
367 }
[email protected]2f1acc262012-11-16 21:42:22368
369 return false;
370}
371
[email protected]96baf3e2012-10-22 23:09:55372void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14373{
374 // For now, we use damage tracking to compute a global scissor. To do this, we must
375 // compute all damage tracking before drawing anything, so that we know the root
376 // damage rect. The root damage rect is then used to scissor each surface.
377
378 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55379 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
380 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04381 DCHECK(renderSurface);
[email protected]1940c4e2012-12-04 05:08:15382 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter().get());
[email protected]94f206c12012-08-25 00:09:14383 }
384}
385
[email protected]96baf3e2012-10-22 23:09:55386void LayerTreeHostImpl::updateRootScrollLayerImplTransform()
[email protected]1c0c9bc2012-10-08 22:41:48387{
[email protected]3b31c6ac2012-12-06 21:27:29388 if (rootScrollLayer()) {
389 rootScrollLayer()->setImplTransform(implTransform());
[email protected]1c0c9bc2012-10-08 22:41:48390 }
391}
392
[email protected]0ede3bb2012-12-09 09:14:39393void LayerTreeHostImpl::updateDrawProperties()
394{
395 if (!needsUpdateDrawProperties())
396 return;
397
398 m_renderSurfaceLayerList.clear();
399 m_needsUpdateDrawProperties = false;
400
401 if (!rootLayer())
402 return;
403
404 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
405}
406
[email protected]96baf3e2012-10-22 23:09:55407void LayerTreeHostImpl::calculateRenderSurfaceLayerList(LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14408{
[email protected]1d993172012-10-18 18:15:04409 DCHECK(renderSurfaceLayerList.empty());
[email protected]3b31c6ac2012-12-06 21:27:29410 DCHECK(rootLayer());
[email protected]1d993172012-10-18 18:15:04411 DCHECK(m_renderer); // For maxTextureSize.
[email protected]94f206c12012-08-25 00:09:14412 {
[email protected]1c0c9bc2012-10-08 22:41:48413 updateRootScrollLayerImplTransform();
414
[email protected]96baf3e2012-10-22 23:09:55415 TRACE_EVENT0("cc", "LayerTreeHostImpl::calcDrawEtc");
[email protected]518ee582012-10-24 18:29:44416 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
[email protected]10aabcc32012-12-13 09:18:59417 LayerTreeHostCommon::calculateDrawProperties(rootLayer(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, rendererCapabilities().maxTextureSize, m_settings.canUseLCDText, renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14418 }
419}
420
[email protected]96baf3e2012-10-22 23:09:55421void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16422{
[email protected]96baf3e2012-10-22 23:09:55423 RenderPass* pass = renderPass.get();
[email protected]f8ad8342012-09-27 20:07:02424 renderPasses.push_back(pass);
[email protected]f57bbc02012-11-21 07:02:15425 renderPassesById.set(pass->id, renderPass.Pass());
426}
427
428static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
429{
430 bool forSurface = false;
431 QuadCuller quadCuller(targetRenderPass->quad_list,
432 targetRenderPass->shared_quad_state_list,
433 layer,
434 occlusionTracker,
435 layer->showDebugBorders(),
436 forSurface);
437 layer->appendQuads(quadCuller, appendQuadsData);
438}
439
440static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, LayerImpl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
441{
442 bool forSurface = true;
443 QuadCuller quadCuller(targetRenderPass->quad_list,
444 targetRenderPass->shared_quad_state_list,
445 layer,
446 occlusionTracker,
447 layer->showDebugBorders(),
448 forSurface);
449
450 bool isReplica = false;
451 layer->renderSurface()->appendQuads(quadCuller,
452 appendQuadsData,
453 isReplica,
454 contributingRenderPass->id);
455
456 // Add replica after the surface so that it appears below the surface.
457 if (layer->hasReplica()) {
458 isReplica = true;
459 layer->renderSurface()->appendQuads(quadCuller,
460 appendQuadsData,
461 isReplica,
462 contributingRenderPass->id);
463 }
464}
465
466static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* rootLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTracker)
467{
468 if (!rootLayer || !SkColorGetA(screenBackgroundColor))
469 return;
470
471 Region fillRegion = occlusionTracker.computeVisibleRegionInScreen();
472 if (fillRegion.IsEmpty())
473 return;
474
475 bool forSurface = false;
476 QuadCuller quadCuller(targetRenderPass->quad_list,
477 targetRenderPass->shared_quad_state_list,
478 rootLayer,
479 occlusionTracker,
480 rootLayer->showDebugBorders(),
481 forSurface);
482
483 // Manually create the quad state for the gutter quads, as the root layer
484 // doesn't have any bounds and so can't generate this itself.
485 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
486
[email protected]c8686a02012-11-27 08:29:00487 DCHECK(rootLayer->screenSpaceTransform().IsInvertible());
[email protected]f57bbc02012-11-21 07:02:15488
489 gfx::Rect rootTargetRect = rootLayer->renderSurface()->contentRect();
490 float opacity = 1;
491 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadState::Create());
492 sharedQuadState->SetAll(rootLayer->drawTransform(),
493 rootTargetRect,
494 rootTargetRect,
[email protected]dc462d782012-11-21 21:43:01495 rootTargetRect,
496 false,
[email protected]f57bbc02012-11-21 07:02:15497 opacity);
498
499 AppendQuadsData appendQuadsData;
[email protected]c8686a02012-11-27 08:29:00500 gfx::Transform transformToLayerSpace = MathUtil::inverse(rootLayer->screenSpaceTransform());
[email protected]f57bbc02012-11-21 07:02:15501 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects.next()) {
502 // The root layer transform is composed of translations and scales only,
503 // no perspective, so mapping is sufficient.
504 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fillRects.rect());
505 // Skip the quad culler and just append the quads directly to avoid
506 // occlusion checks.
507 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
508 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor);
509 quadCuller.append(quad.PassAs<DrawQuad>(), appendQuadsData);
510 }
[email protected]467b3612012-08-28 07:41:16511}
512
[email protected]96baf3e2012-10-22 23:09:55513bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14514{
[email protected]1d993172012-10-18 18:15:04515 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14516
[email protected]0ede3bb2012-12-09 09:14:39517 updateDrawProperties();
518 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14519
[email protected]96baf3e2012-10-22 23:09:55520 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14521
522 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14523 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55524 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16525 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14526 }
527
[email protected]9bdcfd642012-11-14 21:24:26528 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
[email protected]3b31c6ac2012-12-06 21:27:29529 OcclusionTrackerImpl occlusionTracker(rootLayer()->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14530 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
531
[email protected]f511afb2012-11-30 01:55:20532 if (m_debugState.showOccludingRects)
[email protected]94f206c12012-08-25 00:09:14533 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
[email protected]f511afb2012-11-30 01:55:20534 if (m_debugState.showNonOccludingRects)
[email protected]4d8804e2012-11-15 01:51:10535 occlusionTracker.setNonOccludingScreenSpaceRectsContainer(&frame.nonOccludingScreenSpaceRects);
[email protected]94f206c12012-08-25 00:09:14536
537 // 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:55538 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14539
540 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
541 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
542 // in the future.
543 bool drawFrame = true;
544
[email protected]96baf3e2012-10-22 23:09:55545 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
546 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
547 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
548 RenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14549
550 occlusionTracker.enterLayer(it);
551
[email protected]f57bbc02012-11-21 07:02:15552 AppendQuadsData appendQuadsData(targetRenderPass->id);
[email protected]89228202012-08-29 03:20:30553
[email protected]94f206c12012-08-25 00:09:14554 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55555 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
556 RenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]f57bbc02012-11-21 07:02:15557 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributingRenderPass, occlusionTracker, appendQuadsData);
[email protected]aad0a0072012-11-01 18:15:58558 } else if (it.representsItself() && !it->visibleContentRect().IsEmpty()) {
[email protected]94f206c12012-08-25 00:09:14559 bool hasOcclusionFromOutsideTargetSurface;
[email protected]710ffc02012-10-30 21:42:02560 bool implDrawTransformIsUnknown = false;
561 if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
[email protected]89228202012-08-29 03:20:30562 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
563 else {
[email protected]ff762fb2012-12-12 19:18:37564 DCHECK_EQ(this->activeTree(), it->layerTreeImpl());
[email protected]94f206c12012-08-25 00:09:14565 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47566 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57567
568 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55569 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]7d929c02012-09-20 17:26:57570 while (frame.renderPassesById.contains(contributingRenderPassId)) {
[email protected]96baf3e2012-10-22 23:09:55571 RenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]7d929c02012-09-20 17:26:57572
[email protected]f57bbc02012-11-21 07:02:15573 AppendQuadsData appendQuadsData(renderPass->id);
574 appendQuadsForLayer(renderPass, *it, occlusionTracker, appendQuadsData);
[email protected]7d929c02012-09-20 17:26:57575
576 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
577 }
578 }
579
[email protected]f57bbc02012-11-21 07:02:15580 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14581 }
[email protected]9c2be6a2012-11-27 19:16:10582
[email protected]b2136f12012-11-30 02:45:53583 ++m_cumulativeNumLayersDrawn;
[email protected]94f206c12012-08-25 00:09:14584 }
585
[email protected]89228202012-08-29 03:20:30586 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
[email protected]f57bbc02012-11-21 07:02:15587 targetRenderPass->has_occlusion_from_outside_target_surface = true;
[email protected]89228202012-08-29 03:20:30588
[email protected]f2bbb4e2012-12-07 21:40:49589 if (appendQuadsData.numMissingTiles) {
590 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles;
[email protected]94f206c12012-08-25 00:09:14591 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]22619922012-11-14 17:58:10592 if (layerHasAnimatingTransform)
[email protected]94f206c12012-08-25 00:09:14593 drawFrame = false;
594 }
595
596 occlusionTracker.leaveLayer(it);
597 }
598
[email protected]1d993172012-10-18 18:15:04599#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14600 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]f57bbc02012-11-21 07:02:15601 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j)
602 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state);
603 DCHECK(frame.renderPassesById.contains(frame.renderPasses[i]->id));
[email protected]94f206c12012-08-25 00:09:14604 }
605#endif
606
607 if (!m_hasTransparentBackground) {
[email protected]f57bbc02012-11-21 07:02:15608 frame.renderPasses.back()->has_transparent_background = false;
[email protected]3b31c6ac2012-12-06 21:27:29609 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), m_backgroundColor, occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14610 }
611
612 if (drawFrame)
613 occlusionTracker.overdrawMetrics().recordMetrics(this);
614
615 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
616 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
617 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
618
619 return drawFrame;
620}
621
[email protected]df1ec1a2012-12-08 17:01:18622void LayerTreeHostImpl::animateLayersRecursive(LayerImpl* current, base::TimeTicks monotonicTime, base::Time wallClockTime, AnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
623{
624 bool subtreeNeedsAnimateLayers = false;
625
626 LayerAnimationController* currentController = current->layerAnimationController();
627
628 bool hadActiveAnimation = currentController->hasActiveAnimation();
629 double monotonicTimeSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
630 currentController->animate(monotonicTimeSeconds, events);
631 bool startedAnimation = events->size() > 0;
632
633 // We animated if we either ticked a running animation, or started a new animation.
634 if (hadActiveAnimation || startedAnimation)
635 didAnimate = true;
636
637 // If the current controller still has an active animation, we must continue animating layers.
638 if (currentController->hasActiveAnimation())
639 subtreeNeedsAnimateLayers = true;
640
641 for (size_t i = 0; i < current->children().size(); ++i) {
642 bool childNeedsAnimateLayers = false;
643 animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
644 if (childNeedsAnimateLayers)
645 subtreeNeedsAnimateLayers = true;
646 }
647
648 needsAnimateLayers = subtreeNeedsAnimateLayers;
649}
650
[email protected]96baf3e2012-10-22 23:09:55651void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14652{
653 // Lazily create the timeSource adapter so that we can vary the interval for testing.
654 if (!m_timeSourceClientAdapter)
[email protected]61de5812012-11-08 07:03:44655 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->currentThread()));
[email protected]94f206c12012-08-25 00:09:14656
657 m_timeSourceClientAdapter->setActive(enabled);
658}
659
[email protected]aad0a0072012-11-01 18:15:58660gfx::Size LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14661{
662 // TODO(aelias): Hardcoding the first child here is weird. Think of
663 // a cleaner way to get the contentBounds on the Impl side.
[email protected]3b31c6ac2012-12-06 21:27:29664 if (!rootScrollLayer() || rootScrollLayer()->children().isEmpty())
[email protected]aad0a0072012-11-01 18:15:58665 return gfx::Size();
[email protected]3b31c6ac2012-12-06 21:27:29666 return rootScrollLayer()->children()[0]->contentBounds();
[email protected]94f206c12012-08-25 00:09:14667}
668
[email protected]96baf3e2012-10-22 23:09:55669static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14670{
[email protected]96baf3e2012-10-22 23:09:55671 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]1d993172012-10-18 18:15:04672 DCHECK(it != frame.renderPassesById.end());
[email protected]87cea5372012-09-26 18:59:56673 return it->second;
[email protected]94f206c12012-08-25 00:09:14674}
675
[email protected]96baf3e2012-10-22 23:09:55676static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14677{
[email protected]96baf3e2012-10-22 23:09:55678 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
679 RenderPassList& renderPasses = frame.renderPasses;
680 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14681
682 // The pass was already removed by another quad - probably the original, and we are the replica.
[email protected]f8ad8342012-09-27 20:07:02683 if (toRemove == renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14684 return;
685
[email protected]96baf3e2012-10-22 23:09:55686 const RenderPass* removedPass = *toRemove;
[email protected]f8ad8342012-09-27 20:07:02687 frame.renderPasses.erase(toRemove);
[email protected]94f206c12012-08-25 00:09:14688
689 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]f57bbc02012-11-21 07:02:15690 const QuadList& quadList = removedPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55691 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14692 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55693 DrawQuad* currentQuad = (*quadListIterator);
[email protected]1bc93f62012-11-17 19:29:50694 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14695 continue;
696
[email protected]c22418b2012-11-20 23:06:26697 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id;
[email protected]94f206c12012-08-25 00:09:14698 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
699 }
700}
701
[email protected]96baf3e2012-10-22 23:09:55702bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14703{
[email protected]ec2eb5f2012-12-16 04:42:27704 if (!quad.contents_changed_since_last_frame.IsEmpty()) {
705 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
706 return false;
707 } else if (!m_renderer.haveCachedResourcesForRenderPassId(quad.render_pass_id)) {
708 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
709 return false;
710 }
711 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
712 return true;
[email protected]94f206c12012-08-25 00:09:14713}
714
[email protected]96baf3e2012-10-22 23:09:55715bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14716{
[email protected]c22418b2012-11-20 23:06:26717 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame);
[email protected]96baf3e2012-10-22 23:09:55718 const RenderPassList& renderPasses = frame.renderPasses;
719 RenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
[email protected]94f206c12012-08-25 00:09:14720
[email protected]f8ad8342012-09-27 20:07:02721 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
[email protected]94f206c12012-08-25 00:09:14722 if (renderPassAlreadyRemoved)
723 return false;
724
725 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]f57bbc02012-11-21 07:02:15726 const QuadList& quadList = (*foundPass)->quad_list;
[email protected]96baf3e2012-10-22 23:09:55727 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
728 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14729
[email protected]1bc93f62012-11-17 19:29:50730 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14731 return false;
732
[email protected]c22418b2012-11-20 23:06:26733 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id, frame);
[email protected]96baf3e2012-10-22 23:09:55734 RenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
[email protected]f8ad8342012-09-27 20:07:02735 if (foundContributingPass != renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14736 return false;
737 }
738 return true;
739}
740
741// Defined for linking tests.
[email protected]52347c842012-11-02 21:06:20742template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
743template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14744
745// static
746template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55747void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14748{
749 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55750 const RenderPass* currentPass = frame.renderPasses[it];
[email protected]f57bbc02012-11-21 07:02:15751 const QuadList& quadList = currentPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55752 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14753
754 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55755 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14756
[email protected]1bc93f62012-11-17 19:29:50757 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14758 continue;
759
[email protected]96baf3e2012-10-22 23:09:55760 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14761 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
762 continue;
763
764 // We are changing the vector in the middle of iteration. Because we
765 // delete render passes that draw into the current pass, we are
766 // guaranteed that any data from the iterator to the end will not
767 // change. So, capture the iterator position from the end of the
768 // list, and restore it after the change.
769 int positionFromEnd = frame.renderPasses.size() - it;
[email protected]c22418b2012-11-20 23:06:26770 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame);
[email protected]94f206c12012-08-25 00:09:14771 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04772 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14773 }
774 }
775}
776
[email protected]96baf3e2012-10-22 23:09:55777bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14778{
[email protected]96baf3e2012-10-22 23:09:55779 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]1d993172012-10-18 18:15:04780 DCHECK(canDraw());
[email protected]94f206c12012-08-25 00:09:14781
[email protected]d142a47d2012-12-07 08:18:37782 if (m_tileManager)
783 m_tileManager->CheckForCompletedSetPixels();
784
[email protected]94f206c12012-08-25 00:09:14785 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
786 frame.renderPasses.clear();
787 frame.renderPassesById.clear();
[email protected]94f206c12012-08-25 00:09:14788 frame.willDrawLayers.clear();
789
790 if (!calculateRenderPasses(frame))
791 return false;
792
793 // If we return true, then we expect drawLayers() to be called before this function is called again.
794 return true;
795}
796
[email protected]96baf3e2012-10-22 23:09:55797void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14798{
[email protected]a0a00842012-10-22 22:50:28799 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
800 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
801 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
[email protected]b1969fa2012-10-17 20:16:29802 if (evictedResources) {
803 setContentsTexturesPurged();
804 m_client->setNeedsCommitOnImplThread();
805 m_client->onCanDrawStateChanged(canDraw());
806 }
[email protected]3d21e022012-10-25 20:03:08807 m_client->sendManagedMemoryStats();
[email protected]8947cbe2012-11-28 05:27:43808
809 if (m_tileManager) {
810 // TODO(nduca): Pass something useful into the memory manager.
811 LOG(INFO) << "Setting up initial tile manager policy";
812 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState());
813 new_state.memory_limit_in_bytes = PrioritizedResourceManager::defaultMemoryAllocationLimit();
814 new_state.memory_limit_policy = ALLOW_ANYTHING;
815 m_tileManager->SetGlobalState(new_state);
816 }
[email protected]94f206c12012-08-25 00:09:14817}
818
[email protected]61de5812012-11-08 07:03:44819bool LayerTreeHostImpl::hasImplThread() const
820{
821 return m_proxy->hasImplThread();
822}
823
[email protected]8947cbe2012-11-28 05:27:43824void LayerTreeHostImpl::ScheduleManageTiles()
825{
826 if (m_client)
827 m_client->setNeedsManageTilesOnImplThread();
828}
829
[email protected]d142a47d2012-12-07 08:18:37830void LayerTreeHostImpl::ScheduleCheckForCompletedSetPixels()
[email protected]6edd39e2012-11-28 06:49:18831{
[email protected]d142a47d2012-12-07 08:18:37832 // CheckForCompletedSetPixels() should be called before we draw and
833 // preferably only once per vsync interval. For now just make sure
834 // a redraw is scheduled and call CheckForCompletedSetPixels() in
835 // prepareToDraw().
[email protected]6edd39e2012-11-28 06:49:18836 if (m_client)
837 m_client->setNeedsRedrawOnImplThread();
838}
839
[email protected]f35e2322012-12-15 21:45:52840bool LayerTreeHostImpl::shouldClearRootRenderPass() const
841{
842 return m_settings.shouldClearRootRenderPass;
843}
844
[email protected]96baf3e2012-10-22 23:09:55845void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14846{
[email protected]a0a00842012-10-22 22:50:28847 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14848 return;
[email protected]61de5812012-11-08 07:03:44849
[email protected]a0a00842012-10-22 22:50:28850 m_managedMemoryPolicy = policy;
[email protected]61de5812012-11-08 07:03:44851 if (!m_proxy->hasImplThread()) {
852 // FIXME: In single-thread mode, this can be called on the main thread
853 // by GLRenderer::onMemoryAllocationChanged.
854 DebugScopedSetImplThread implThread(m_proxy);
855 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
856 } else {
857 DCHECK(m_proxy->isImplThread());
858 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
859 }
[email protected]a0a00842012-10-22 22:50:28860 // We always need to commit after changing the memory policy because the new
861 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14862 m_client->setNeedsCommitOnImplThread();
863}
864
[email protected]a46f32932012-12-07 21:43:16865void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval)
[email protected]94f206c12012-08-25 00:09:14866{
[email protected]30faac92012-10-29 00:06:29867 m_client->onVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14868}
869
[email protected]b6f3d7e2012-12-08 00:11:21870void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack)
[email protected]a46f32932012-12-07 21:43:16871{
[email protected]b6f3d7e2012-12-08 00:11:21872 if (!m_renderer)
873 return;
874
875 // TODO(piman): We may need to do some validation on this ack before processing it.
876 m_renderer->receiveCompositorFrameAck(ack);
[email protected]a46f32932012-12-07 21:43:16877}
878
[email protected]3b31c6ac2012-12-06 21:27:29879void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl*)
880{
[email protected]a46f32932012-12-07 21:43:16881 m_client->onCanDrawStateChanged(canDraw());
[email protected]3b31c6ac2012-12-06 21:27:29882}
883
[email protected]85167c72012-12-04 03:56:07884void LayerTreeHostImpl::drawLayers(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14885{
[email protected]96baf3e2012-10-22 23:09:55886 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04887 DCHECK(canDraw());
888 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14889
890 // FIXME: use the frame begin time from the overall compositor scheduler.
891 // This value is currently inaccessible because it is up in Chromium's
892 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21893 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14894
[email protected]f511afb2012-11-30 01:55:20895 if (m_debugState.showHudRects())
[email protected]3b31c6ac2012-12-06 21:27:29896 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenSpaceRects, m_debugState);
[email protected]94f206c12012-08-25 00:09:14897
898 // Because the contents of the HUD depend on everything else in the frame, the contents
899 // of its texture are updated as the last thing before the frame is drawn.
[email protected]3b31c6ac2012-12-06 21:27:29900 if (m_activeTree->hud_layer())
901 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get());
[email protected]94f206c12012-08-25 00:09:14902
903 m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
904
[email protected]85167c72012-12-04 03:56:07905 // The render passes should be consumed by the renderer.
906 DCHECK(frame.renderPasses.empty());
907 DCHECK(frame.renderPassesById.empty());
[email protected]94f206c12012-08-25 00:09:14908
909 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
910 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
911 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
[email protected]3b31c6ac2012-12-06 21:27:29912 rootLayer()->resetAllChangeTrackingForSubtree();
[email protected]94f206c12012-08-25 00:09:14913}
914
[email protected]96baf3e2012-10-22 23:09:55915void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14916{
917 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
918 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52919
920 // Once all layers have been drawn, pending texture uploads should no
921 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09922 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14923}
924
[email protected]96baf3e2012-10-22 23:09:55925void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14926{
927 if (m_renderer)
928 m_renderer->finish();
929}
930
[email protected]96baf3e2012-10-22 23:09:55931bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14932{
933 return m_renderer && m_renderer->isContextLost();
934}
935
[email protected]96baf3e2012-10-22 23:09:55936const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14937{
938 return m_renderer->capabilities();
939}
940
[email protected]96baf3e2012-10-22 23:09:55941bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14942{
[email protected]1d993172012-10-18 18:15:04943 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14944
945 m_fpsCounter->markEndOfFrame();
946 return m_renderer->swapBuffers();
947}
948
[email protected]aad0a0072012-11-01 18:15:58949const gfx::Size& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10950{
951 return m_deviceViewportSize;
952}
953
[email protected]96baf3e2012-10-22 23:09:55954const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10955{
956 return m_settings;
957}
958
[email protected]3be2171d2012-12-06 06:13:20959void LayerTreeHostImpl::didLoseOutputSurface()
[email protected]94f206c12012-08-25 00:09:14960{
[email protected]3be2171d2012-12-06 06:13:20961 m_client->didLoseOutputSurfaceOnImplThread();
[email protected]94f206c12012-08-25 00:09:14962}
963
[email protected]96baf3e2012-10-22 23:09:55964void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14965{
966 m_client->onSwapBuffersCompleteOnImplThread();
967}
968
[email protected]aad0a0072012-11-01 18:15:58969void LayerTreeHostImpl::readback(void* pixels, const gfx::Rect& rect)
[email protected]94f206c12012-08-25 00:09:14970{
[email protected]1d993172012-10-18 18:15:04971 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14972 m_renderer->getFramebufferPixels(pixels, rect);
973}
974
[email protected]8bef40572012-12-11 21:38:08975LayerImpl* LayerTreeHostImpl::rootLayer() const
976{
977 return m_activeTree->RootLayer();
978}
979
980LayerImpl* LayerTreeHostImpl::rootScrollLayer() const
981{
982 return m_activeTree->root_scroll_layer();
983}
984
985LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const
986{
987 return m_activeTree->currently_scrolling_layer();
988}
989
[email protected]94f206c12012-08-25 00:09:14990// Content layers can be either directly scrollable or contained in an outer
991// scrolling layer which applies the scroll transform. Given a content layer,
992// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55993static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14994{
995 if (!layerImpl)
996 return 0;
997
998 if (layerImpl->scrollable())
999 return layerImpl;
1000
1001 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
1002 return layerImpl->parent();
1003
1004 return 0;
1005}
1006
[email protected]96baf3e2012-10-22 23:09:551007void LayerTreeHostImpl::setRootLayer(scoped_ptr<LayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:141008{
[email protected]0ede3bb2012-12-09 09:14:391009 m_activeTree->SetRootLayer(layer.Pass());
1010 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141011}
1012
[email protected]96baf3e2012-10-22 23:09:551013scoped_ptr<LayerImpl> LayerTreeHostImpl::detachLayerTree()
[email protected]94f206c12012-08-25 00:09:141014{
[email protected]0ede3bb2012-12-09 09:14:391015 scoped_ptr<LayerImpl> layer = m_activeTree->DetachLayerTree();
1016 m_renderSurfaceLayerList.clear();
1017 setNeedsUpdateDrawProperties();
1018 return layer.Pass();
[email protected]94f206c12012-08-25 00:09:141019}
1020
[email protected]96baf3e2012-10-22 23:09:551021void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:141022{
[email protected]61de5812012-11-08 07:03:441023 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:141024
1025 if (m_visible == visible)
1026 return;
1027 m_visible = visible;
1028 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:281029 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:141030
1031 if (!m_renderer)
1032 return;
1033
1034 m_renderer->setVisible(visible);
1035
[email protected]df1ec1a2012-12-08 17:01:181036 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:141037}
1038
[email protected]3be2171d2012-12-06 06:13:201039bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurface)
[email protected]94f206c12012-08-25 00:09:141040{
[email protected]be3181652012-09-25 13:02:131041 // Since we will create a new resource provider, we cannot continue to use
1042 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
1043 // before we destroy the old resource provider.
[email protected]3b31c6ac2012-12-06 21:27:291044 if (rootLayer()) {
[email protected]94f206c12012-08-25 00:09:141045 clearRenderSurfaces();
[email protected]3b31c6ac2012-12-06 21:27:291046 sendDidLoseOutputSurfaceRecursive(rootLayer());
[email protected]94f206c12012-08-25 00:09:141047 }
[email protected]be3181652012-09-25 13:02:131048 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:471049 m_renderer.reset();
[email protected]8947cbe2012-11-28 05:27:431050 m_tileManager.reset();
[email protected]a7aa5562012-10-17 14:12:441051 m_resourceProvider.reset();
[email protected]3be2171d2012-12-06 06:13:201052 m_outputSurface.reset();
[email protected]94f206c12012-08-25 00:09:141053
[email protected]a46f32932012-12-07 21:43:161054 if (!outputSurface->BindToClient(this))
[email protected]be3181652012-09-25 13:02:131055 return false;
1056
[email protected]3be2171d2012-12-06 06:13:201057 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(outputSurface.get());
[email protected]be3181652012-09-25 13:02:131058 if (!resourceProvider)
1059 return false;
1060
[email protected]8947cbe2012-11-28 05:27:431061 if (m_settings.implSidePainting)
[email protected]876e9e82012-12-04 20:12:141062 m_tileManager.reset(new TileManager(this, resourceProvider.get(), m_settings.numRasterThreads));
[email protected]8947cbe2012-11-28 05:27:431063
[email protected]ea9d8f22012-12-08 03:39:291064 if (outputSurface->Capabilities().has_parent_compositor)
1065 m_renderer = DelegatingRenderer::Create(this, resourceProvider.get());
1066 else if (outputSurface->Context3D())
[email protected]96baf3e2012-10-22 23:09:551067 m_renderer = GLRenderer::create(this, resourceProvider.get());
[email protected]a46f32932012-12-07 21:43:161068 else if (outputSurface->SoftwareDevice())
1069 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), outputSurface->SoftwareDevice());
[email protected]be3181652012-09-25 13:02:131070 if (!m_renderer)
1071 return false;
1072
[email protected]a7aa5562012-10-17 14:12:441073 m_resourceProvider = resourceProvider.Pass();
[email protected]3be2171d2012-12-06 06:13:201074 m_outputSurface = outputSurface.Pass();
[email protected]94f206c12012-08-25 00:09:141075
[email protected]be3181652012-09-25 13:02:131076 if (!m_visible)
1077 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:141078
[email protected]8db2213c2012-09-05 22:08:211079 m_client->onCanDrawStateChanged(canDraw());
1080
[email protected]be3181652012-09-25 13:02:131081 return true;
[email protected]94f206c12012-08-25 00:09:141082}
1083
[email protected]96baf3e2012-10-22 23:09:551084void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:091085{
1086 m_contentsTexturesPurged = true;
1087 m_client->onCanDrawStateChanged(canDraw());
1088}
1089
[email protected]96baf3e2012-10-22 23:09:551090void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:211091{
1092 m_contentsTexturesPurged = false;
1093 m_client->onCanDrawStateChanged(canDraw());
1094}
1095
[email protected]aad0a0072012-11-01 18:15:581096void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:141097{
1098 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
1099 return;
1100
1101 m_layoutViewportSize = layoutViewportSize;
1102 m_deviceViewportSize = deviceViewportSize;
1103
[email protected]c9c1ebe2012-11-05 20:46:131104 m_pinchZoomViewport.setLayoutViewportSize(layoutViewportSize);
[email protected]1c0c9bc2012-10-08 22:41:481105
[email protected]c9c1ebe2012-11-05 20:46:131106 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141107
1108 if (m_renderer)
1109 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:211110
1111 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:141112}
1113
[email protected]96baf3e2012-10-22 23:09:551114static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:141115{
1116 if (!layerImpl)
1117 return;
1118
1119 if (layerImpl->scrollable()) {
1120 // We need to convert impl-side scroll deltas to pageScale space.
[email protected]c9c1ebe2012-11-05 20:46:131121 gfx::Vector2dF scrollDelta = layerImpl->scrollDelta();
1122 scrollDelta.Scale(pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141123 layerImpl->setScrollDelta(scrollDelta);
1124 }
1125
1126 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031127 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141128}
1129
[email protected]96baf3e2012-10-22 23:09:551130void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:141131{
1132 if (deviceScaleFactor == m_deviceScaleFactor)
1133 return;
1134 m_deviceScaleFactor = deviceScaleFactor;
[email protected]e39bf212012-11-22 21:04:031135 m_pinchZoomViewport.setDeviceScaleFactor(m_deviceScaleFactor);
[email protected]c0dd24c2012-08-30 23:25:271136
[email protected]c9c1ebe2012-11-05 20:46:131137 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141138}
1139
[email protected]96baf3e2012-10-22 23:09:551140float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:141141{
[email protected]1c0c9bc2012-10-08 22:41:481142 return m_pinchZoomViewport.pageScaleFactor();
1143}
[email protected]94f206c12012-08-25 00:09:141144
[email protected]96baf3e2012-10-22 23:09:551145void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:481146{
1147 if (!pageScaleFactor)
1148 return;
[email protected]94f206c12012-08-25 00:09:141149
[email protected]1c0c9bc2012-10-08 22:41:481150 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
1151 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:141152
[email protected]0ede3bb2012-12-09 09:14:391153 if (!m_settings.pageScalePinchZoomEnabled && pageScaleChange != 1)
1154 adjustScrollsForPageScaleChange(rootScrollLayer(), pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141155
1156 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:481157 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
1158 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:141159}
1160
[email protected]96baf3e2012-10-22 23:09:551161void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:141162{
[email protected]1c0c9bc2012-10-08 22:41:481163 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:141164
[email protected]c9c1ebe2012-11-05 20:46:131165 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141166}
1167
[email protected]c9c1ebe2012-11-05 20:46:131168void LayerTreeHostImpl::updateMaxScrollOffset()
[email protected]94f206c12012-08-25 00:09:141169{
[email protected]3b31c6ac2012-12-06 21:27:291170 if (!rootScrollLayer() || !rootScrollLayer()->children().size())
[email protected]94f206c12012-08-25 00:09:141171 return;
1172
[email protected]aad0a0072012-11-01 18:15:581173 gfx::SizeF viewBounds = m_deviceViewportSize;
[email protected]3b31c6ac2012-12-06 21:27:291174 if (LayerImpl* clipLayer = rootScrollLayer()->parent()) {
[email protected]94f206c12012-08-25 00:09:141175 // Compensate for non-overlay scrollbars.
[email protected]01a15a72012-11-10 09:34:281176 if (clipLayer->masksToBounds())
1177 viewBounds = gfx::ScaleSize(clipLayer->bounds(), m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141178 }
[email protected]94f206c12012-08-25 00:09:141179
[email protected]aad0a0072012-11-01 18:15:581180 gfx::Size contentBounds = contentSize();
[email protected]9bdcfd642012-11-14 21:24:261181 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481182 // Pinch with pageScale scrolls entirely in layout space. contentSize
1183 // returns the bounds including the page scale factor, so calculate the
1184 // pre page-scale layout size here.
1185 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
[email protected]aad0a0072012-11-01 18:15:581186 contentBounds.set_width(contentBounds.width() / pageScaleFactor);
1187 contentBounds.set_height(contentBounds.height() / pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:481188 } else {
[email protected]01a15a72012-11-10 09:34:281189 viewBounds.Scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:481190 }
1191
[email protected]0eef4b882012-11-20 20:28:071192 gfx::Vector2dF maxScroll = gfx::Rect(contentBounds).bottom_right() - gfx::RectF(viewBounds).bottom_right();
[email protected]c9c1ebe2012-11-05 20:46:131193 maxScroll.Scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:481194
[email protected]94f206c12012-08-25 00:09:141195 // The viewport may be larger than the contents in some cases, such as
1196 // having a vertical scrollbar but no horizontal overflow.
[email protected]fe07b642012-11-10 00:07:591197 maxScroll.ClampToMin(gfx::Vector2dF());
[email protected]94f206c12012-08-25 00:09:141198
[email protected]3b31c6ac2012-12-06 21:27:291199 rootScrollLayer()->setMaxScrollOffset(gfx::ToFlooredVector2d(maxScroll));
[email protected]94f206c12012-08-25 00:09:141200}
1201
[email protected]96baf3e2012-10-22 23:09:551202void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141203{
1204 m_client->setNeedsRedrawOnImplThread();
1205}
1206
[email protected]96baf3e2012-10-22 23:09:551207bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141208{
[email protected]0ede3bb2012-12-09 09:14:391209 // TODO(enne): See http://crbug.com/164949. This function should really
1210 // just call updateDrawProperties(), but that breaks a number of
1211 // impl transform tests that don't expect the tree to be updated.
[email protected]3b31c6ac2012-12-06 21:27:291212 if (!rootLayer())
[email protected]94f206c12012-08-25 00:09:141213 return false;
1214 if (!m_renderer)
1215 return false;
1216
1217 // We need both a non-empty render surface layer list and a root render
1218 // surface to be able to iterate over the visible layers.
[email protected]3b31c6ac2012-12-06 21:27:291219 if (m_renderSurfaceLayerList.size() && rootLayer()->renderSurface())
[email protected]94f206c12012-08-25 00:09:141220 return true;
1221
1222 // If we are called after setRootLayer() but before prepareToDraw(), we need
1223 // to recalculate the visible layers. This prevents being unable to scroll
1224 // during part of a commit.
[email protected]0ede3bb2012-12-09 09:14:391225 setNeedsUpdateDrawProperties();
1226 updateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141227
1228 return m_renderSurfaceLayerList.size();
1229}
1230
[email protected]c9c1ebe2012-11-05 20:46:131231InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141232{
[email protected]96baf3e2012-10-22 23:09:551233 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141234
[email protected]3b31c6ac2012-12-06 21:27:291235 DCHECK(!currentlyScrollingLayer());
[email protected]94f206c12012-08-25 00:09:141236 clearCurrentlyScrollingLayer();
1237
1238 if (!ensureRenderSurfaceLayerList())
1239 return ScrollIgnored;
1240
[email protected]faf56352012-11-09 21:44:131241 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141242
1243 // First find out which layer was hit from the saved list of visible layers
1244 // in the most recent frame.
[email protected]96baf3e2012-10-22 23:09:551245 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:141246
1247 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551248 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141249 for (; layerImpl; layerImpl = layerImpl->parent()) {
1250 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271251 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1252 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141253 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271254 }
[email protected]94f206c12012-08-25 00:09:141255
[email protected]96baf3e2012-10-22 23:09:551256 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141257 if (!scrollLayerImpl)
1258 continue;
1259
[email protected]31bfe272012-10-19 18:49:521260 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141261
1262 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271263 if (status == ScrollOnMainThread) {
1264 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141265 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271266 }
[email protected]94f206c12012-08-25 00:09:141267
1268 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1269 potentiallyScrollingLayerImpl = scrollLayerImpl;
1270 }
1271
1272 if (potentiallyScrollingLayerImpl) {
[email protected]3b31c6ac2012-12-06 21:27:291273 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImpl);
[email protected]31bfe272012-10-19 18:49:521274 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141275 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1276 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521277 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271278 m_numImplThreadScrolls++;
[email protected]0ede3bb2012-12-09 09:14:391279 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141280 return ScrollStarted;
1281 }
1282 return ScrollIgnored;
1283}
1284
[email protected]c9c1ebe2012-11-05 20:46:131285static gfx::Vector2dF scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::Vector2dF viewportDelta)
[email protected]94f206c12012-08-25 00:09:141286{
1287 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1288 // test in the first place.
[email protected]c8686a02012-11-27 08:29:001289 DCHECK(layerImpl.screenSpaceTransform().IsInvertible());
1290 gfx::Transform inverseScreenSpaceTransform = MathUtil::inverse(layerImpl.screenSpaceTransform());
[email protected]94f206c12012-08-25 00:09:141291
[email protected]faf56352012-11-09 21:44:131292 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521293
[email protected]c9c1ebe2012-11-05 20:46:131294 gfx::Vector2dF screenSpaceDelta = viewportDelta;
1295 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521296
[email protected]94f206c12012-08-25 00:09:141297 // First project the scroll start and end points to local layer space to find the scroll delta
1298 // in layer coordinates.
1299 bool startClipped, endClipped;
[email protected]d455d552012-11-02 00:19:061300 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1301 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1302 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141303
1304 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041305 DCHECK(!startClipped);
1306 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141307 if (startClipped || endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131308 return gfx::Vector2dF();
[email protected]94f206c12012-08-25 00:09:141309
[email protected]31bfe272012-10-19 18:49:521310 // 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:581311 float widthScale = 1 / layerImpl.contentsScaleX();
1312 float heightScale = 1 / layerImpl.contentsScaleY();
[email protected]faf56352012-11-09 21:44:131313 localStartPoint.Scale(widthScale, heightScale);
1314 localEndPoint.Scale(widthScale, heightScale);
[email protected]31bfe272012-10-19 18:49:521315
[email protected]94f206c12012-08-25 00:09:141316 // Apply the scroll delta.
[email protected]c9c1ebe2012-11-05 20:46:131317 gfx::Vector2dF previousDelta = layerImpl.scrollDelta();
1318 gfx::Vector2dF unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
[email protected]1c0c9bc2012-10-08 22:41:481319
[email protected]aeaa50a2012-11-21 20:12:371320 gfx::Vector2dF viewportAppliedPan;
[email protected]1c0c9bc2012-10-08 22:41:481321 if (viewport)
[email protected]aeaa50a2012-11-21 20:12:371322 viewportAppliedPan = unscrolled - viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141323
[email protected]31bfe272012-10-19 18:49:521324 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]aeaa50a2012-11-21 20:12:371325 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() + viewportAppliedPan - previousDelta;
[email protected]faf56352012-11-09 21:44:131326 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint, 1 / widthScale, 1 / heightScale);
[email protected]31bfe272012-10-19 18:49:521327
1328 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]d455d552012-11-02 00:19:061329 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041330 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141331 if (endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131332 return gfx::Vector2dF();
[email protected]faf56352012-11-09 21:44:131333 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoint, 1 / scaleFromViewportToScreenSpace);
[email protected]c9c1ebe2012-11-05 20:46:131334 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141335}
1336
[email protected]c9c1ebe2012-11-05 20:46:131337static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vector2dF localDelta)
[email protected]94f206c12012-08-25 00:09:141338{
[email protected]c9c1ebe2012-11-05 20:46:131339 gfx::Vector2dF previousDelta(layerImpl.scrollDelta());
[email protected]94f206c12012-08-25 00:09:141340 layerImpl.scrollBy(localDelta);
1341 return layerImpl.scrollDelta() - previousDelta;
1342}
1343
[email protected]a9710962012-11-14 20:11:021344bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint,
1345 const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141346{
[email protected]96baf3e2012-10-22 23:09:551347 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]3b31c6ac2012-12-06 21:27:291348 if (!currentlyScrollingLayer())
[email protected]a9710962012-11-14 20:11:021349 return false;
[email protected]94f206c12012-08-25 00:09:141350
[email protected]c9c1ebe2012-11-05 20:46:131351 gfx::Vector2dF pendingDelta = scrollDelta;
[email protected]1ca52a3a2012-12-04 22:47:101352 bool didScroll = false;
[email protected]94f206c12012-08-25 00:09:141353
[email protected]3b31c6ac2012-12-06 21:27:291354 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141355 if (!layerImpl->scrollable())
1356 continue;
1357
[email protected]dbed4272012-12-06 08:50:481358 PinchZoomViewport* viewport = NULL;
[email protected]3b31c6ac2012-12-06 21:27:291359 if (m_settings.pageScalePinchZoomEnabled && layerImpl == rootScrollLayer())
[email protected]dbed4272012-12-06 08:50:481360 viewport = &m_pinchZoomViewport;
[email protected]c9c1ebe2012-11-05 20:46:131361 gfx::Vector2dF appliedDelta;
[email protected]31bfe272012-10-19 18:49:521362 if (m_scrollDeltaIsInViewportSpace) {
1363 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1364 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1365 } else
[email protected]94f206c12012-08-25 00:09:141366 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1367
1368 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381369 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]c9c1ebe2012-11-05 20:46:131370 if (appliedDelta.LengthSquared() < moveThresholdSquared)
[email protected]94f206c12012-08-25 00:09:141371 continue;
[email protected]1ca52a3a2012-12-04 22:47:101372 didScroll = true;
[email protected]94f206c12012-08-25 00:09:141373
1374 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1375 // to scroll just one layer in one direction without affecting any of its parents.
1376 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551377 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]c9c1ebe2012-11-05 20:46:131378 pendingDelta = gfx::Vector2d();
[email protected]94f206c12012-08-25 00:09:141379 break;
1380 }
1381
1382 // Allow further movement only on an axis perpendicular to the direction in which the layer
1383 // moved.
[email protected]c9c1ebe2012-11-05 20:46:131384 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x());
[email protected]96baf3e2012-10-22 23:09:551385 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141386
[email protected]c9c1ebe2012-11-05 20:46:131387 if (gfx::ToFlooredVector2d(pendingDelta).IsZero())
[email protected]94f206c12012-08-25 00:09:141388 break;
1389 }
1390
[email protected]1ca52a3a2012-12-04 22:47:101391 if (didScroll) {
[email protected]94f206c12012-08-25 00:09:141392 m_client->setNeedsCommitOnImplThread();
1393 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391394 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141395 }
[email protected]1ca52a3a2012-12-04 22:47:101396 return didScroll;
[email protected]94f206c12012-08-25 00:09:141397}
1398
[email protected]96baf3e2012-10-22 23:09:551399void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141400{
[email protected]3b31c6ac2012-12-06 21:27:291401 m_activeTree->ClearCurrentlyScrollingLayer();
[email protected]94f206c12012-08-25 00:09:141402}
1403
[email protected]96baf3e2012-10-22 23:09:551404void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141405{
1406 clearCurrentlyScrollingLayer();
1407}
1408
[email protected]96baf3e2012-10-22 23:09:551409void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141410{
1411 m_pinchGestureActive = true;
[email protected]c9c1ebe2012-11-05 20:46:131412 m_previousPinchAnchor = gfx::Point();
[email protected]94f206c12012-08-25 00:09:141413
[email protected]3b31c6ac2012-12-06 21:27:291414 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1415 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureBegin();
[email protected]94f206c12012-08-25 00:09:141416}
1417
[email protected]c9c1ebe2012-11-05 20:46:131418void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor)
[email protected]94f206c12012-08-25 00:09:141419{
[email protected]96baf3e2012-10-22 23:09:551420 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141421
[email protected]3b31c6ac2012-12-06 21:27:291422 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141423 return;
1424
[email protected]94f206c12012-08-25 00:09:141425 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1426 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481427 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]c77745d2012-11-20 04:11:571428 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:481429 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1430 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]faf56352012-11-09 21:44:131431 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:131432 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor;
[email protected]94f206c12012-08-25 00:09:141433
1434 m_previousPinchAnchor = anchor;
1435
[email protected]9bdcfd642012-11-14 21:24:261436 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481437 // Compute the application of the delta with respect to the current page zoom of the page.
[email protected]e39bf212012-11-22 21:04:031438 move.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]1c0c9bc2012-10-08 22:41:481439 }
1440
[email protected]9bdcfd642012-11-14 21:24:261441 gfx::Vector2dF scrollOverflow = m_settings.pageScalePinchZoomEnabled ? m_pinchZoomViewport.applyScroll(move) : move;
[email protected]3b31c6ac2012-12-06 21:27:291442 rootScrollLayer()->scrollBy(scrollOverflow);
[email protected]94f206c12012-08-25 00:09:141443
[email protected]3b31c6ac2012-12-06 21:27:291444 if (rootScrollLayer()->scrollbarAnimationController())
1445 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureUpdate();
[email protected]94f206c12012-08-25 00:09:141446
1447 m_client->setNeedsCommitOnImplThread();
1448 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391449 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141450}
1451
[email protected]96baf3e2012-10-22 23:09:551452void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141453{
1454 m_pinchGestureActive = false;
1455
[email protected]3b31c6ac2012-12-06 21:27:291456 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1457 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:141458
1459 m_client->setNeedsCommitOnImplThread();
1460}
1461
[email protected]96baf3e2012-10-22 23:09:551462void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141463{
[email protected]f6250742012-11-09 04:46:561464 gfx::Vector2dF scaledScrollOffset = m_pageScaleAnimation->targetScrollOffset();
[email protected]9bdcfd642012-11-14 21:24:261465 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:561466 scaledScrollOffset.Scale(m_pinchZoomViewport.pageScaleFactor());
1467 makeScrollAndScaleSet(scrollInfo, ToFlooredVector2d(scaledScrollOffset), m_pageScaleAnimation->targetPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141468}
1469
[email protected]96baf3e2012-10-22 23:09:551470void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141471{
[email protected]3b31c6ac2012-12-06 21:27:291472 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141473 return;
1474
1475 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1476 // significant amount. This also ensures only one fake delta set will be
1477 // sent.
[email protected]23bbb412012-08-30 20:03:381478 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481479 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141480 return;
1481
1482 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1483 // out from the anchor point.
[email protected]3b31c6ac2012-12-06 21:27:291484 gfx::Vector2dF scrollBegin = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]c9c1ebe2012-11-05 20:46:131485 scrollBegin.Scale(m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:481486 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1487 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]01a15a72012-11-10 09:34:281488 gfx::SizeF scaledContentsSize = gfx::ScaleSize(contentSize(), pageScaleDeltaToSend);
[email protected]94f206c12012-08-25 00:09:141489
[email protected]c9c1ebe2012-11-05 20:46:131490 gfx::Vector2d anchorOffset = m_previousPinchAnchor.OffsetFromOrigin();
1491 gfx::Vector2dF scrollEnd = scrollBegin + anchorOffset;
1492 scrollEnd.Scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
1493 scrollEnd -= anchorOffset;
[email protected]0eef4b882012-11-20 20:28:071494 scrollEnd.ClampToMax(gfx::RectF(scaledContentsSize).bottom_right() - gfx::Rect(m_deviceViewportSize).bottom_right());
[email protected]fe07b642012-11-10 00:07:591495 scrollEnd.ClampToMin(gfx::Vector2d());
[email protected]c9c1ebe2012-11-05 20:46:131496 scrollEnd.Scale(1 / pageScaleDeltaToSend);
1497 scrollEnd.Scale(m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141498
[email protected]c9c1ebe2012-11-05 20:46:131499 makeScrollAndScaleSet(scrollInfo, gfx::ToRoundedVector2d(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141500}
1501
[email protected]c9c1ebe2012-11-05 20:46:131502void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141503{
[email protected]3b31c6ac2012-12-06 21:27:291504 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141505 return;
1506
[email protected]96baf3e2012-10-22 23:09:551507 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]3b31c6ac2012-12-06 21:27:291508 scroll.layerId = rootScrollLayer()->id();
1509 scroll.scrollDelta = scrollOffset - rootScrollLayer()->scrollOffset();
[email protected]787465c2012-10-29 01:12:271510 scrollInfo->scrolls.push_back(scroll);
[email protected]3b31c6ac2012-12-06 21:27:291511 rootScrollLayer()->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481512 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1513 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141514}
1515
[email protected]96baf3e2012-10-22 23:09:551516static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141517{
1518 if (!layerImpl)
1519 return;
1520
[email protected]c9c1ebe2012-11-05 20:46:131521 if (!layerImpl->scrollDelta().IsZero()) {
1522 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551523 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141524 scroll.layerId = layerImpl->id();
1525 scroll.scrollDelta = scrollDelta;
[email protected]787465c2012-10-29 01:12:271526 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141527 layerImpl->setSentScrollDelta(scrollDelta);
1528 }
1529
1530 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031531 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141532}
1533
[email protected]96baf3e2012-10-22 23:09:551534scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141535{
[email protected]96baf3e2012-10-22 23:09:551536 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141537
1538 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481539 scrollInfo->pageScaleDelta = 1;
1540 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]f6250742012-11-09 04:46:561541 // FIXME(aelias): Make pinch-zoom painting optimization compatible with
[email protected]1c0c9bc2012-10-08 22:41:481542 // compositor-side scaling.
[email protected]9bdcfd642012-11-14 21:24:261543 if (!m_settings.pageScalePinchZoomEnabled && m_pinchGestureActive)
[email protected]f6250742012-11-09 04:46:561544 computePinchZoomDeltas(scrollInfo.get());
1545 else if (m_pageScaleAnimation.get())
1546 computeDoubleTapZoomDeltas(scrollInfo.get());
[email protected]a9f4bf22012-10-11 23:39:211547 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141548 }
1549
[email protected]3b31c6ac2012-12-06 21:27:291550 collectScrollDeltas(scrollInfo.get(), rootLayer());
[email protected]1c0c9bc2012-10-08 22:41:481551 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1552 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141553
[email protected]a9f4bf22012-10-11 23:39:211554 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141555}
1556
[email protected]c8686a02012-11-27 08:29:001557gfx::Transform LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481558{
[email protected]9bdcfd642012-11-14 21:24:261559 return m_pinchZoomViewport.implTransform(m_settings.pageScalePinchZoomEnabled);
[email protected]1c0c9bc2012-10-08 22:41:481560}
1561
[email protected]96baf3e2012-10-22 23:09:551562void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141563{
[email protected]3b31c6ac2012-12-06 21:27:291564 if (rootLayer()) {
1565 RenderSurfaceImpl* renderSurface = rootLayer()->renderSurface();
[email protected]94f206c12012-08-25 00:09:141566 if (renderSurface)
1567 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1568 }
1569}
1570
[email protected]30faac92012-10-29 00:06:291571void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141572{
[email protected]3b31c6ac2012-12-06 21:27:291573 if (!m_pageScaleAnimation || !rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141574 return;
1575
[email protected]30faac92012-10-29 00:06:291576 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]3b31c6ac2012-12-06 21:27:291577 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]94f206c12012-08-25 00:09:141578
[email protected]f6250742012-11-09 04:46:561579 setPageScaleDelta(m_pageScaleAnimation->pageScaleFactorAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]c9c1ebe2012-11-05 20:46:131580 gfx::Vector2dF nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]f6250742012-11-09 04:46:561581
[email protected]9bdcfd642012-11-14 21:24:261582 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:561583 nextScroll.Scale(m_pinchZoomViewport.pageScaleFactor());
[email protected]3b31c6ac2012-12-06 21:27:291584 rootScrollLayer()->scrollBy(nextScroll - scrollTotal);
[email protected]94f206c12012-08-25 00:09:141585 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391586 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141587
1588 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451589 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141590 m_client->setNeedsCommitOnImplThread();
1591 }
1592}
1593
[email protected]30faac92012-10-29 00:06:291594void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:141595{
[email protected]df1ec1a2012-12-08 17:01:181596 if (!m_settings.acceleratedAnimationEnabled || !m_needsAnimateLayers || !rootLayer())
[email protected]94f206c12012-08-25 00:09:141597 return;
1598
[email protected]96baf3e2012-10-22 23:09:551599 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141600
[email protected]0a9fd4d2012-12-07 07:37:081601 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
[email protected]df1ec1a2012-12-08 17:01:181602
1603 bool didAnimate = false;
1604 animateLayersRecursive(rootLayer(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:141605
[email protected]d3143c732012-10-05 19:17:591606 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571607 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141608
[email protected]0ede3bb2012-12-09 09:14:391609 if (didAnimate) {
[email protected]df1ec1a2012-12-08 17:01:181610 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391611 setNeedsUpdateDrawProperties();
1612 }
[email protected]df1ec1a2012-12-08 17:01:181613
1614 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:141615}
1616
[email protected]96baf3e2012-10-22 23:09:551617base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141618{
[email protected]4481ddb622012-09-20 16:33:471619 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141620}
1621
[email protected]3be2171d2012-12-06 06:13:201622void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141623{
[email protected]1d993172012-10-18 18:15:041624 DCHECK(current);
[email protected]3be2171d2012-12-06 06:13:201625 current->didLoseOutputSurface();
[email protected]94f206c12012-08-25 00:09:141626 if (current->maskLayer())
[email protected]3be2171d2012-12-06 06:13:201627 sendDidLoseOutputSurfaceRecursive(current->maskLayer());
[email protected]94f206c12012-08-25 00:09:141628 if (current->replicaLayer())
[email protected]3be2171d2012-12-06 06:13:201629 sendDidLoseOutputSurfaceRecursive(current->replicaLayer());
[email protected]94f206c12012-08-25 00:09:141630 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]3be2171d2012-12-06 06:13:201631 sendDidLoseOutputSurfaceRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141632}
1633
[email protected]96baf3e2012-10-22 23:09:551634static void clearRenderSurfacesOnLayerImplRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141635{
[email protected]1d993172012-10-18 18:15:041636 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141637 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]96baf3e2012-10-22 23:09:551638 clearRenderSurfacesOnLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141639 current->clearRenderSurface();
1640}
1641
[email protected]96baf3e2012-10-22 23:09:551642void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141643{
[email protected]3b31c6ac2012-12-06 21:27:291644 clearRenderSurfacesOnLayerImplRecursive(rootLayer());
[email protected]94f206c12012-08-25 00:09:141645 m_renderSurfaceLayerList.clear();
[email protected]0ede3bb2012-12-09 09:14:391646 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141647}
1648
[email protected]96baf3e2012-10-22 23:09:551649std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141650{
[email protected]515e8d232012-09-10 19:15:271651 std::string str;
[email protected]3b31c6ac2012-12-06 21:27:291652 if (rootLayer()) {
1653 str = rootLayer()->layerTreeAsText();
[email protected]515e8d232012-09-10 19:15:271654 str += "RenderSurfaces:\n";
[email protected]3b31c6ac2012-12-06 21:27:291655 dumpRenderSurfaces(&str, 1, rootLayer());
[email protected]94f206c12012-08-25 00:09:141656 }
[email protected]515e8d232012-09-10 19:15:271657 return str;
[email protected]94f206c12012-08-25 00:09:141658}
1659
[email protected]4a23c374c2012-12-08 08:38:551660std::string LayerTreeHostImpl::layerTreeAsJson() const
1661{
1662 std::string str;
1663 if (rootLayer()) {
1664 scoped_ptr<base::Value> json(rootLayer()->layerTreeAsJson());
1665 base::JSONWriter::WriteWithOptions(
1666 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1667 }
1668 return str;
1669}
1670
[email protected]96baf3e2012-10-22 23:09:551671void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141672{
1673 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271674 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141675
1676 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031677 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141678}
1679
[email protected]96baf3e2012-10-22 23:09:551680int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141681{
1682 return fpsCounter()->currentFrameNumber();
1683}
1684
[email protected]96baf3e2012-10-22 23:09:551685void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141686{
[email protected]8b9af6b2012-09-27 00:36:361687 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1688 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271689 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1690 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]b2136f12012-11-30 02:45:531691 stats->numLayersDrawn = m_cumulativeNumLayersDrawn;
[email protected]f2bbb4e2012-12-07 21:40:491692 stats->numMissingTiles = m_cumulativeNumMissingTiles;
[email protected]4d3c5c912012-11-30 05:55:021693
1694 if (m_tileManager)
[email protected]ee371e02012-12-16 20:13:441695 m_tileManager->GetRenderingStats(stats);
[email protected]94f206c12012-08-25 00:09:141696}
1697
[email protected]d3afa112012-12-08 06:24:281698void LayerTreeHostImpl::sendManagedMemoryStats(
1699 size_t memoryVisibleBytes,
1700 size_t memoryVisibleAndNearbyBytes,
1701 size_t memoryUseBytes)
1702{
1703 if (!renderer())
1704 return;
1705
1706 // Round the numbers being sent up to the next 8MB, to throttle the rate
1707 // at which we spam the GPU process.
1708 static const size_t roundingStep = 8 * 1024 * 1024;
1709 memoryVisibleBytes = RoundUp(memoryVisibleBytes, roundingStep);
1710 memoryVisibleAndNearbyBytes = RoundUp(memoryVisibleAndNearbyBytes, roundingStep);
1711 memoryUseBytes = RoundUp(memoryUseBytes, roundingStep);
1712 if (m_lastSentMemoryVisibleBytes == memoryVisibleBytes &&
1713 m_lastSentMemoryVisibleAndNearbyBytes == memoryVisibleAndNearbyBytes &&
1714 m_lastSentMemoryUseBytes == memoryUseBytes) {
1715 return;
1716 }
1717 m_lastSentMemoryVisibleBytes = memoryVisibleBytes;
1718 m_lastSentMemoryVisibleAndNearbyBytes = memoryVisibleAndNearbyBytes;
1719 m_lastSentMemoryUseBytes = memoryUseBytes;
1720
1721 renderer()->sendManagedMemoryStats(m_lastSentMemoryVisibleBytes,
1722 m_lastSentMemoryVisibleAndNearbyBytes,
1723 m_lastSentMemoryUseBytes);
1724}
1725
[email protected]30faac92012-10-29 00:06:291726void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141727{
[email protected]3b31c6ac2012-12-06 21:27:291728 animateScrollbarsRecursive(rootLayer(), time);
[email protected]94f206c12012-08-25 00:09:141729}
1730
[email protected]30faac92012-10-29 00:06:291731void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141732{
1733 if (!layer)
1734 return;
1735
[email protected]96baf3e2012-10-22 23:09:551736 ScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]30faac92012-10-29 00:06:291737 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]94f206c12012-08-25 00:09:141738 if (scrollbarController && scrollbarController->animate(monotonicTime))
1739 m_client->setNeedsRedrawOnImplThread();
1740
1741 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]30faac92012-10-29 00:06:291742 animateScrollbarsRecursive(layer->children()[i], time);
[email protected]94f206c12012-08-25 00:09:141743}
1744
[email protected]d3143c732012-10-05 19:17:591745} // namespace cc