blob: fa0aba24a68c15951ebcaa9c86ab8f540b5ba3e8 [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]de4afb5e2012-12-20 00:11:3412#include "base/stl_util.h"
[email protected]aa0a9d32012-10-24 01:58:1013#include "cc/append_quads_data.h"
[email protected]bf189f62012-12-18 03:42:1114#include "cc/compositor_frame_metadata.h"
[email protected]aa0a9d32012-10-24 01:58:1015#include "cc/damage_tracker.h"
16#include "cc/debug_rect_history.h"
17#include "cc/delay_based_time_source.h"
[email protected]ea9d8f22012-12-08 03:39:2918#include "cc/delegating_renderer.h"
[email protected]aa0a9d32012-10-24 01:58:1019#include "cc/frame_rate_counter.h"
[email protected]c4040a522012-10-21 15:01:4020#include "cc/gl_renderer.h"
[email protected]d50c6862012-10-23 02:08:3121#include "cc/heads_up_display_layer_impl.h"
22#include "cc/layer_iterator.h"
23#include "cc/layer_tree_host.h"
24#include "cc/layer_tree_host_common.h"
[email protected]8bef40572012-12-11 21:38:0825#include "cc/layer_tree_impl.h"
[email protected]55a124d02012-10-22 03:07:1326#include "cc/math_util.h"
27#include "cc/overdraw_metrics.h"
28#include "cc/page_scale_animation.h"
[email protected]3b10a302012-11-07 21:16:4029#include "cc/prioritized_resource_manager.h"
[email protected]f57bbc02012-11-21 07:02:1530#include "cc/quad_culler.h"
[email protected]55a124d02012-10-22 03:07:1331#include "cc/render_pass_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4032#include "cc/rendering_stats.h"
33#include "cc/scrollbar_animation_controller.h"
34#include "cc/scrollbar_layer_impl.h"
[email protected]f57bbc02012-11-21 07:02:1535#include "cc/shared_quad_state.h"
[email protected]4456eee22012-10-19 18:16:3836#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4037#include "cc/software_renderer.h"
[email protected]f57bbc02012-11-21 07:02:1538#include "cc/solid_color_draw_quad.h"
[email protected]a8461d82012-10-16 21:11:1439#include "cc/texture_uploader.h"
[email protected]3ba4cae2013-01-16 03:58:3840#include "cc/top_controls_manager.h"
[email protected]d3afa112012-12-08 06:24:2841#include "cc/util.h"
[email protected]d455d552012-11-02 00:19:0642#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1343#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1444
[email protected]94f206c12012-08-25 00:09:1445namespace {
46
[email protected]96baf3e2012-10-22 23:09:5547void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1448{
49 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5550 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1451 return;
52 }
53
[email protected]96baf3e2012-10-22 23:09:5554 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1455}
56
57} // namespace
58
[email protected]9c88e562012-09-14 22:21:3059namespace cc {
[email protected]94f206c12012-08-25 00:09:1460
[email protected]96baf3e2012-10-22 23:09:5561class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:1462public:
[email protected]96baf3e2012-10-22 23:09:5563 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:1464 {
[email protected]96baf3e2012-10-22 23:09:5565 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:1466 }
[email protected]96baf3e2012-10-22 23:09:5567 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:1468 {
69 m_timeSource->setClient(0);
70 m_timeSource->setActive(false);
71 }
72
73 virtual void onTimerTick() OVERRIDE
74 {
[email protected]373974232013-01-10 22:20:5075 // In single threaded mode we attempt to simulate changing the current
76 // thread by maintaining a fake thread id. When we switch from one
77 // thread to another, we construct DebugScopedSetXXXThread objects that
78 // update the thread id. This lets DCHECKS that ensure we're on the
79 // right thread to work correctly in single threaded mode. The problem
80 // here is that the timer tasks are run via the message loop, and when
81 // they run, we've had no chance to construct a DebugScopedSetXXXThread
82 // object. The result is that we report that we're running on the main
83 // thread. In multi-threaded mode, this timer is run on the compositor
84 // thread, so to keep this consistent in single-threaded mode, we'll
85 // construct a DebugScopedSetImplThread object. There is no need to do
86 // this in multi-threaded mode since the real thread id's will be
87 // correct. In fact, setting fake thread id's interferes with the real
88 // thread id's and causes breakage.
89 scoped_ptr<DebugScopedSetImplThread> setImplThread;
90 if (!m_layerTreeHostImpl->proxy()->hasImplThread())
91 setImplThread.reset(new DebugScopedSetImplThread(m_layerTreeHostImpl->proxy()));
92
[email protected]eabe5002013-01-12 22:07:4893 m_layerTreeHostImpl->activatePendingTreeIfNeeded();
[email protected]30faac92012-10-29 00:06:2994 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]94f206c12012-08-25 00:09:1495 }
96
97 void setActive(bool active)
98 {
99 if (active != m_timeSource->active())
100 m_timeSource->setActive(active);
101 }
102
103private:
[email protected]96baf3e2012-10-22 23:09:55104 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14105 : m_layerTreeHostImpl(layerTreeHostImpl)
106 , m_timeSource(timeSource)
107 {
108 m_timeSource->setClient(this);
109 }
110
[email protected]96baf3e2012-10-22 23:09:55111 LayerTreeHostImpl* m_layerTreeHostImpl;
112 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20113
[email protected]96baf3e2012-10-22 23:09:55114 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14115};
116
[email protected]96baf3e2012-10-22 23:09:55117LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10118{
119}
120
[email protected]96baf3e2012-10-22 23:09:55121LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10122{
123}
124
[email protected]61de5812012-11-08 07:03:44125scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14126{
[email protected]61de5812012-11-08 07:03:44127 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
[email protected]94f206c12012-08-25 00:09:14128}
129
[email protected]61de5812012-11-08 07:03:44130LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14131 : m_client(client)
[email protected]61de5812012-11-08 07:03:44132 , m_proxy(proxy)
[email protected]31bfe272012-10-19 18:49:52133 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14134 , m_settings(settings)
[email protected]f511afb2012-11-30 01:55:20135 , m_debugState(settings.initialDebugState)
[email protected]94f206c12012-08-25 00:09:14136 , m_deviceScaleFactor(1)
137 , m_visible(true)
138 , m_contentsTexturesPurged(false)
[email protected]3b10a302012-11-07 21:16:40139 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
[email protected]9b0b79a02013-01-02 22:47:27140 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
[email protected]a0a00842012-10-22 22:50:28141 0,
[email protected]9b0b79a02013-01-02 22:47:27142 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING)
[email protected]0ede3bb2012-12-09 09:14:39143 , m_needsUpdateDrawProperties(false)
[email protected]94f206c12012-08-25 00:09:14144 , m_pinchGestureActive(false)
[email protected]61de5812012-11-08 07:03:44145 , m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
[email protected]96baf3e2012-10-22 23:09:55146 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27147 , m_numImplThreadScrolls(0)
148 , m_numMainThreadScrolls(0)
[email protected]b2136f12012-11-30 02:45:53149 , m_cumulativeNumLayersDrawn(0)
[email protected]f2bbb4e2012-12-07 21:40:49150 , m_cumulativeNumMissingTiles(0)
[email protected]d3afa112012-12-08 06:24:28151 , m_lastSentMemoryVisibleBytes(0)
152 , m_lastSentMemoryVisibleAndNearbyBytes(0)
153 , m_lastSentMemoryUseBytes(0)
[email protected]de4afb5e2012-12-20 00:11:34154 , m_animationRegistrar(AnimationRegistrar::create())
[email protected]94f206c12012-08-25 00:09:14155{
[email protected]61de5812012-11-08 07:03:44156 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14157 didVisibilityChange(this, m_visible);
[email protected]3b31c6ac2012-12-06 21:27:29158
[email protected]3ba4cae2013-01-16 03:58:38159 if (settings.calculateTopControlsPosition)
160 m_topControlsManager = TopControlsManager::Create(this, settings.topControlsHeightPx);
161
[email protected]2e7ca422012-12-20 02:57:27162 // LTHI always has an active tree.
[email protected]3b31c6ac2012-12-06 21:27:29163 m_activeTree = LayerTreeImpl::create(this);
[email protected]94f206c12012-08-25 00:09:14164}
165
[email protected]96baf3e2012-10-22 23:09:55166LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14167{
[email protected]61de5812012-11-08 07:03:44168 DCHECK(m_proxy->isImplThread());
[email protected]96baf3e2012-10-22 23:09:55169 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14170
[email protected]de4afb5e2012-12-20 00:11:34171 if (rootLayer()) {
[email protected]94f206c12012-08-25 00:09:14172 clearRenderSurfaces();
[email protected]de4afb5e2012-12-20 00:11:34173 // The layer trees must be destroyed before the layer tree host. We've
174 // made a contract with our animation controllers that the registrar
175 // will outlive them, and we must make good.
176 m_activeTree.reset();
177 m_pendingTree.reset();
178 }
[email protected]94f206c12012-08-25 00:09:14179}
180
[email protected]96baf3e2012-10-22 23:09:55181void LayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14182{
183}
184
[email protected]96baf3e2012-10-22 23:09:55185void LayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14186{
[email protected]96baf3e2012-10-22 23:09:55187 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
[email protected]0ede3bb2012-12-09 09:14:39188
189 // Impl-side painting needs an update immediately post-commit to have the
190 // opportunity to create tilings. Other paths can call updateDrawProperties
191 // more lazily when needed prior to drawing.
192 setNeedsUpdateDrawProperties();
193 if (m_settings.implSidePainting)
194 updateDrawProperties();
195
[email protected]94f206c12012-08-25 00:09:14196 // Recompute max scroll position; must be after layer content bounds are
197 // updated.
[email protected]c9c1ebe2012-11-05 20:46:13198 updateMaxScrollOffset();
[email protected]3d21e022012-10-25 20:03:08199 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14200}
201
[email protected]96baf3e2012-10-22 23:09:55202bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14203{
[email protected]8db2213c2012-09-05 22:08:21204 // Note: If you are changing this function or any other function that might
205 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
206 // in the proper places and update the notifyIfCanDrawChanged test.
207
[email protected]3b31c6ac2012-12-06 21:27:29208 if (!rootLayer()) {
[email protected]96baf3e2012-10-22 23:09:55209 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14210 return false;
211 }
[email protected]aad0a0072012-11-01 18:15:58212 if (deviceViewportSize().IsEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55213 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14214 return false;
215 }
216 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55217 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14218 return false;
219 }
220 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55221 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14222 return false;
223 }
224 return true;
225}
226
[email protected]3be2171d2012-12-06 06:13:20227OutputSurface* LayerTreeHostImpl::outputSurface() const
[email protected]94f206c12012-08-25 00:09:14228{
[email protected]3be2171d2012-12-06 06:13:20229 return m_outputSurface.get();
[email protected]94f206c12012-08-25 00:09:14230}
231
[email protected]30faac92012-10-29 00:06:29232void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:14233{
234 animatePageScale(monotonicTime);
235 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14236 animateScrollbars(monotonicTime);
[email protected]3ba4cae2013-01-16 03:58:38237 if (m_topControlsManager)
238 m_topControlsManager->Animate(monotonicTime);
[email protected]94f206c12012-08-25 00:09:14239}
240
[email protected]8947cbe2012-11-28 05:27:43241void LayerTreeHostImpl::manageTiles()
242{
243 DCHECK(m_tileManager);
244 m_tileManager->ManageTiles();
[email protected]9b0b79a02013-01-02 22:47:27245
246 size_t memoryRequiredBytes;
247 size_t memoryNiceToHaveBytes;
248 size_t memoryUsedBytes;
249 m_tileManager->GetMemoryStats(&memoryRequiredBytes,
250 &memoryNiceToHaveBytes,
251 &memoryUsedBytes);
252 sendManagedMemoryStats(memoryRequiredBytes,
253 memoryNiceToHaveBytes,
254 memoryUsedBytes);
[email protected]8947cbe2012-11-28 05:27:43255}
256
[email protected]69a2a5be2012-11-14 06:51:44257void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration)
[email protected]94f206c12012-08-25 00:09:14258{
[email protected]3b31c6ac2012-12-06 21:27:29259 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:14260 return;
261
[email protected]3b31c6ac2012-12-06 21:27:29262 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]f6250742012-11-09 04:46:56263 gfx::SizeF scaledContentSize = contentSize();
[email protected]9bdcfd642012-11-14 21:24:26264 if (!m_settings.pageScalePinchZoomEnabled) {
[email protected]a823df82013-01-10 02:38:17265 scrollTotal.Scale(1 / m_pinchZoomViewport.page_scale_factor());
266 scaledContentSize.Scale(1 / m_pinchZoomViewport.page_scale_factor());
[email protected]f6250742012-11-09 04:46:56267 }
[email protected]01a15a72012-11-10 09:34:28268 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14269
[email protected]30faac92012-10-29 00:06:29270 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
[email protected]a823df82013-01-10 02:38:17271 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, m_pinchZoomViewport.total_page_scale_factor(), viewportSize, scaledContentSize, startTimeSeconds);
[email protected]94f206c12012-08-25 00:09:14272
273 if (anchorPoint) {
[email protected]69a2a5be2012-11-14 06:51:44274 gfx::Vector2dF anchor(targetOffset);
[email protected]9bdcfd642012-11-14 21:24:26275 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:56276 anchor.Scale(1 / pageScale);
277 m_pageScaleAnimation->zoomWithAnchor(anchor, pageScale, duration.InSecondsF());
278 } else {
[email protected]69a2a5be2012-11-14 06:51:44279 gfx::Vector2dF scaledTargetOffset = targetOffset;
[email protected]9bdcfd642012-11-14 21:24:26280 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]69a2a5be2012-11-14 06:51:44281 scaledTargetOffset.Scale(1 / pageScale);
282 m_pageScaleAnimation->zoomTo(scaledTargetOffset, pageScale, duration.InSecondsF());
[email protected]f6250742012-11-09 04:46:56283 }
[email protected]94f206c12012-08-25 00:09:14284
[email protected]0ede3bb2012-12-09 09:14:39285 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:14286 m_client->setNeedsRedrawOnImplThread();
287 m_client->setNeedsCommitOnImplThread();
288}
289
[email protected]96baf3e2012-10-22 23:09:55290void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14291{
292 m_client->setNeedsRedrawOnImplThread();
293}
294
[email protected]2f1acc262012-11-16 21:42:22295bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint)
296{
[email protected]df8f44f2013-01-08 08:00:31297 if (!ensureRenderSurfaceLayerList())
298 return false;
[email protected]2f1acc262012-11-16 21:42:22299
300 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
301
302 // First find out which layer was hit from the saved list of visible layers
303 // in the most recent frame.
[email protected]76ffd9e2012-12-20 19:12:47304 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, activeTree()->RenderSurfaceLayerList());
[email protected]2f1acc262012-11-16 21:42:22305
[email protected]35d2edd22012-12-13 02:19:05306 // Walk up the hierarchy and look for a layer with a touch event handler region that the given point hits.
307 for (; layerImpl; layerImpl = layerImpl->parent()) {
308 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint,layerImpl))
309 return true;
310 }
[email protected]2f1acc262012-11-16 21:42:22311
312 return false;
313}
314
[email protected]96baf3e2012-10-22 23:09:55315void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14316{
317 // For now, we use damage tracking to compute a global scissor. To do this, we must
318 // compute all damage tracking before drawing anything, so that we know the root
319 // damage rect. The root damage rect is then used to scissor each surface.
320
321 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55322 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
323 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04324 DCHECK(renderSurface);
[email protected]1940c4e2012-12-04 05:08:15325 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:14326 }
327}
328
[email protected]0ede3bb2012-12-09 09:14:39329void LayerTreeHostImpl::updateDrawProperties()
330{
331 if (!needsUpdateDrawProperties())
332 return;
333
[email protected]76ffd9e2012-12-20 19:12:47334 if (!m_renderer) { // For maxTextureSize.
335 // This will get set if renderer gets initialized.
336 m_needsUpdateDrawProperties = false;
[email protected]2d692992012-12-19 01:19:32337 return;
[email protected]94f206c12012-08-25 00:09:14338 }
[email protected]2e7ca422012-12-20 02:57:27339
[email protected]3ba4cae2013-01-16 03:58:38340 if (m_topControlsManager)
341 m_topControlsManager->UpdateDrawPositions();
[email protected]76ffd9e2012-12-20 19:12:47342 activeTree()->UpdateDrawProperties();
343 if (pendingTree())
344 pendingTree()->UpdateDrawProperties();
345
346 m_needsUpdateDrawProperties = false;
[email protected]94f206c12012-08-25 00:09:14347}
348
[email protected]96baf3e2012-10-22 23:09:55349void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16350{
[email protected]20062042012-12-21 22:16:36351 renderPassesById[renderPass->id] = renderPass.get();
[email protected]ead39c52013-01-09 07:22:45352 renderPasses.push_back(renderPass.Pass());
[email protected]f57bbc02012-11-21 07:02:15353}
354
355static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
356{
357 bool forSurface = false;
358 QuadCuller quadCuller(targetRenderPass->quad_list,
359 targetRenderPass->shared_quad_state_list,
360 layer,
361 occlusionTracker,
362 layer->showDebugBorders(),
363 forSurface);
364 layer->appendQuads(quadCuller, appendQuadsData);
365}
366
367static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, LayerImpl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
368{
369 bool forSurface = true;
370 QuadCuller quadCuller(targetRenderPass->quad_list,
371 targetRenderPass->shared_quad_state_list,
372 layer,
373 occlusionTracker,
374 layer->showDebugBorders(),
375 forSurface);
376
377 bool isReplica = false;
378 layer->renderSurface()->appendQuads(quadCuller,
379 appendQuadsData,
380 isReplica,
381 contributingRenderPass->id);
382
383 // Add replica after the surface so that it appears below the surface.
384 if (layer->hasReplica()) {
385 isReplica = true;
386 layer->renderSurface()->appendQuads(quadCuller,
387 appendQuadsData,
388 isReplica,
389 contributingRenderPass->id);
390 }
391}
392
393static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* rootLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTracker)
394{
395 if (!rootLayer || !SkColorGetA(screenBackgroundColor))
396 return;
397
398 Region fillRegion = occlusionTracker.computeVisibleRegionInScreen();
399 if (fillRegion.IsEmpty())
400 return;
401
402 bool forSurface = false;
403 QuadCuller quadCuller(targetRenderPass->quad_list,
404 targetRenderPass->shared_quad_state_list,
405 rootLayer,
406 occlusionTracker,
407 rootLayer->showDebugBorders(),
408 forSurface);
409
410 // Manually create the quad state for the gutter quads, as the root layer
411 // doesn't have any bounds and so can't generate this itself.
412 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
413
[email protected]f57bbc02012-11-21 07:02:15414 gfx::Rect rootTargetRect = rootLayer->renderSurface()->contentRect();
415 float opacity = 1;
416 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadState::Create());
417 sharedQuadState->SetAll(rootLayer->drawTransform(),
418 rootTargetRect,
419 rootTargetRect,
[email protected]dc462d782012-11-21 21:43:01420 rootTargetRect,
421 false,
[email protected]f57bbc02012-11-21 07:02:15422 opacity);
423
424 AppendQuadsData appendQuadsData;
[email protected]bda41962013-01-07 18:46:17425
426 gfx::Transform transformToLayerSpace(gfx::Transform::kSkipInitialization);
427 bool didInvert = rootLayer->screenSpaceTransform().GetInverse(&transformToLayerSpace);
428 DCHECK(didInvert);
[email protected]f57bbc02012-11-21 07:02:15429 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects.next()) {
430 // The root layer transform is composed of translations and scales only,
[email protected]bda41962013-01-07 18:46:17431 // no perspective, so mapping is sufficient (as opposed to projecting).
[email protected]f57bbc02012-11-21 07:02:15432 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fillRects.rect());
433 // Skip the quad culler and just append the quads directly to avoid
434 // occlusion checks.
435 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
436 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor);
437 quadCuller.append(quad.PassAs<DrawQuad>(), appendQuadsData);
438 }
[email protected]467b3612012-08-28 07:41:16439}
440
[email protected]96baf3e2012-10-22 23:09:55441bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14442{
[email protected]ead39c52013-01-09 07:22:45443 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14444
[email protected]2e7ca422012-12-20 02:57:27445 if (!canDraw() || !rootLayer())
[email protected]2d692992012-12-19 01:19:32446 return false;
447
[email protected]0ede3bb2012-12-09 09:14:39448 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14449
[email protected]96baf3e2012-10-22 23:09:55450 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14451
452 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14453 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55454 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16455 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14456 }
457
[email protected]9bdcfd642012-11-14 21:24:26458 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
[email protected]3b31c6ac2012-12-06 21:27:29459 OcclusionTrackerImpl occlusionTracker(rootLayer()->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14460 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
461
[email protected]f511afb2012-11-30 01:55:20462 if (m_debugState.showOccludingRects)
[email protected]94f206c12012-08-25 00:09:14463 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
[email protected]f511afb2012-11-30 01:55:20464 if (m_debugState.showNonOccludingRects)
[email protected]4d8804e2012-11-15 01:51:10465 occlusionTracker.setNonOccludingScreenSpaceRectsContainer(&frame.nonOccludingScreenSpaceRects);
[email protected]94f206c12012-08-25 00:09:14466
467 // 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:55468 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14469
470 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
471 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
472 // in the future.
473 bool drawFrame = true;
474
[email protected]eabe5002013-01-12 22:07:48475 // Make sure we have the most recent info regarding which textures have been uploaded.
476 checkForCompletedSetPixels();
477
[email protected]96baf3e2012-10-22 23:09:55478 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
479 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
480 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
[email protected]20062042012-12-21 22:16:36481 RenderPass* targetRenderPass = frame.renderPassesById[targetRenderPassId];
[email protected]94f206c12012-08-25 00:09:14482
483 occlusionTracker.enterLayer(it);
484
[email protected]f57bbc02012-11-21 07:02:15485 AppendQuadsData appendQuadsData(targetRenderPass->id);
[email protected]89228202012-08-29 03:20:30486
[email protected]94f206c12012-08-25 00:09:14487 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55488 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
[email protected]20062042012-12-21 22:16:36489 RenderPass* contributingRenderPass = frame.renderPassesById[contributingRenderPassId];
[email protected]f57bbc02012-11-21 07:02:15490 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributingRenderPass, occlusionTracker, appendQuadsData);
[email protected]aad0a0072012-11-01 18:15:58491 } else if (it.representsItself() && !it->visibleContentRect().IsEmpty()) {
[email protected]94f206c12012-08-25 00:09:14492 bool hasOcclusionFromOutsideTargetSurface;
[email protected]710ffc02012-10-30 21:42:02493 bool implDrawTransformIsUnknown = false;
494 if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
[email protected]89228202012-08-29 03:20:30495 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
496 else {
[email protected]2e7ca422012-12-20 02:57:27497 DCHECK_EQ(activeTree(), it->layerTreeImpl());
[email protected]94f206c12012-08-25 00:09:14498 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47499 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57500
501 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55502 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]20062042012-12-21 22:16:36503 while (frame.renderPassesById.find(contributingRenderPassId) != frame.renderPassesById.end()) {
504 RenderPass* renderPass = frame.renderPassesById[contributingRenderPassId];
[email protected]7d929c02012-09-20 17:26:57505
[email protected]f57bbc02012-11-21 07:02:15506 AppendQuadsData appendQuadsData(renderPass->id);
507 appendQuadsForLayer(renderPass, *it, occlusionTracker, appendQuadsData);
[email protected]7d929c02012-09-20 17:26:57508
509 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
510 }
511 }
512
[email protected]f57bbc02012-11-21 07:02:15513 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14514 }
[email protected]9c2be6a2012-11-27 19:16:10515
[email protected]b2136f12012-11-30 02:45:53516 ++m_cumulativeNumLayersDrawn;
[email protected]94f206c12012-08-25 00:09:14517 }
518
[email protected]89228202012-08-29 03:20:30519 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
[email protected]f57bbc02012-11-21 07:02:15520 targetRenderPass->has_occlusion_from_outside_target_surface = true;
[email protected]89228202012-08-29 03:20:30521
[email protected]f2bbb4e2012-12-07 21:40:49522 if (appendQuadsData.numMissingTiles) {
523 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles;
[email protected]94f206c12012-08-25 00:09:14524 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]22619922012-11-14 17:58:10525 if (layerHasAnimatingTransform)
[email protected]94f206c12012-08-25 00:09:14526 drawFrame = false;
527 }
528
529 occlusionTracker.leaveLayer(it);
530 }
531
[email protected]1d993172012-10-18 18:15:04532#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14533 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]f57bbc02012-11-21 07:02:15534 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j)
535 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state);
[email protected]20062042012-12-21 22:16:36536 DCHECK(frame.renderPassesById.find(frame.renderPasses[i]->id)
537 != frame.renderPassesById.end());
[email protected]94f206c12012-08-25 00:09:14538 }
539#endif
540
[email protected]a30290142013-01-05 01:27:00541 if (!activeTree()->has_transparent_background()) {
[email protected]ead39c52013-01-09 07:22:45542 frame.renderPasses.back()->has_transparent_background = false;
543 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), activeTree()->background_color(), occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14544 }
545
546 if (drawFrame)
547 occlusionTracker.overdrawMetrics().recordMetrics(this);
548
549 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
550 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
551 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
552
553 return drawFrame;
554}
555
[email protected]96baf3e2012-10-22 23:09:55556void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14557{
558 // Lazily create the timeSource adapter so that we can vary the interval for testing.
559 if (!m_timeSourceClientAdapter)
[email protected]61de5812012-11-08 07:03:44560 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->currentThread()));
[email protected]94f206c12012-08-25 00:09:14561
562 m_timeSourceClientAdapter->setActive(enabled);
563}
564
[email protected]aad0a0072012-11-01 18:15:58565gfx::Size LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14566{
[email protected]caa567d2012-12-20 07:56:16567 return activeTree()->ContentSize();
[email protected]94f206c12012-08-25 00:09:14568}
569
[email protected]96baf3e2012-10-22 23:09:55570static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14571{
[email protected]96baf3e2012-10-22 23:09:55572 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]20062042012-12-21 22:16:36573 return it != frame.renderPassesById.end() ? it->second : NULL;
[email protected]94f206c12012-08-25 00:09:14574}
575
[email protected]96baf3e2012-10-22 23:09:55576static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14577{
[email protected]96baf3e2012-10-22 23:09:55578 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
[email protected]20062042012-12-21 22:16:36579 // The pass was already removed by another quad - probably the original, and we are the replica.
580 if (!removeRenderPass)
581 return;
[email protected]96baf3e2012-10-22 23:09:55582 RenderPassList& renderPasses = frame.renderPasses;
583 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14584
[email protected]20062042012-12-21 22:16:36585 DCHECK(toRemove != renderPasses.end());
[email protected]94f206c12012-08-25 00:09:14586
[email protected]ead39c52013-01-09 07:22:45587 scoped_ptr<RenderPass> removedPass = renderPasses.take(toRemove);
588 frame.renderPasses.erase(toRemove);
[email protected]20062042012-12-21 22:16:36589 frame.renderPassesById.erase(removeRenderPassId);
[email protected]94f206c12012-08-25 00:09:14590
591 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]f57bbc02012-11-21 07:02:15592 const QuadList& quadList = removedPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55593 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14594 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55595 DrawQuad* currentQuad = (*quadListIterator);
[email protected]1bc93f62012-11-17 19:29:50596 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14597 continue;
598
[email protected]c22418b2012-11-20 23:06:26599 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id;
[email protected]94f206c12012-08-25 00:09:14600 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
601 }
602}
603
[email protected]96baf3e2012-10-22 23:09:55604bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14605{
[email protected]ec2eb5f2012-12-16 04:42:27606 if (!quad.contents_changed_since_last_frame.IsEmpty()) {
607 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
608 return false;
609 } else if (!m_renderer.haveCachedResourcesForRenderPassId(quad.render_pass_id)) {
610 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
611 return false;
612 }
613 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
614 return true;
[email protected]94f206c12012-08-25 00:09:14615}
616
[email protected]96baf3e2012-10-22 23:09:55617bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14618{
[email protected]c22418b2012-11-20 23:06:26619 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame);
[email protected]20062042012-12-21 22:16:36620 if (!renderPass)
[email protected]94f206c12012-08-25 00:09:14621 return false;
622
623 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]20062042012-12-21 22:16:36624 const QuadList& quadList = renderPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55625 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
626 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14627
[email protected]1bc93f62012-11-17 19:29:50628 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14629 return false;
630
[email protected]c22418b2012-11-20 23:06:26631 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id, frame);
[email protected]20062042012-12-21 22:16:36632 if (contributingPass)
[email protected]94f206c12012-08-25 00:09:14633 return false;
634 }
635 return true;
636}
637
638// Defined for linking tests.
[email protected]52347c842012-11-02 21:06:20639template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
640template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14641
642// static
643template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55644void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14645{
646 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55647 const RenderPass* currentPass = frame.renderPasses[it];
[email protected]f57bbc02012-11-21 07:02:15648 const QuadList& quadList = currentPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55649 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14650
651 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55652 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14653
[email protected]1bc93f62012-11-17 19:29:50654 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14655 continue;
656
[email protected]96baf3e2012-10-22 23:09:55657 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14658 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
659 continue;
660
661 // We are changing the vector in the middle of iteration. Because we
662 // delete render passes that draw into the current pass, we are
663 // guaranteed that any data from the iterator to the end will not
664 // change. So, capture the iterator position from the end of the
665 // list, and restore it after the change.
666 int positionFromEnd = frame.renderPasses.size() - it;
[email protected]c22418b2012-11-20 23:06:26667 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame);
[email protected]94f206c12012-08-25 00:09:14668 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04669 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14670 }
671 }
672}
673
[email protected]96baf3e2012-10-22 23:09:55674bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14675{
[email protected]96baf3e2012-10-22 23:09:55676 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]94f206c12012-08-25 00:09:14677
[email protected]76ffd9e2012-12-20 19:12:47678 updateDrawProperties();
[email protected]2e7ca422012-12-20 02:57:27679
[email protected]76ffd9e2012-12-20 19:12:47680 frame.renderSurfaceLayerList = &activeTree()->RenderSurfaceLayerList();
[email protected]94f206c12012-08-25 00:09:14681 frame.renderPasses.clear();
682 frame.renderPassesById.clear();
[email protected]94f206c12012-08-25 00:09:14683 frame.willDrawLayers.clear();
684
685 if (!calculateRenderPasses(frame))
686 return false;
687
688 // If we return true, then we expect drawLayers() to be called before this function is called again.
689 return true;
690}
691
[email protected]96baf3e2012-10-22 23:09:55692void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14693{
[email protected]a0a00842012-10-22 22:50:28694 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
695 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
[email protected]9b0b79a02013-01-02 22:47:27696 ManagedMemoryPolicy::priorityCutoffToValue(
697 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible));
[email protected]b1969fa2012-10-17 20:16:29698 if (evictedResources) {
699 setContentsTexturesPurged();
700 m_client->setNeedsCommitOnImplThread();
701 m_client->onCanDrawStateChanged(canDraw());
702 }
[email protected]3d21e022012-10-25 20:03:08703 m_client->sendManagedMemoryStats();
[email protected]8947cbe2012-11-28 05:27:43704
705 if (m_tileManager) {
[email protected]8947cbe2012-11-28 05:27:43706 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState());
[email protected]9b0b79a02013-01-02 22:47:27707 new_state.memory_limit_in_bytes = m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible;
708 new_state.memory_limit_policy = ManagedMemoryPolicy::priorityCutoffToTileMemoryLimitPolicy(
709 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
[email protected]8947cbe2012-11-28 05:27:43710 m_tileManager->SetGlobalState(new_state);
711 }
[email protected]94f206c12012-08-25 00:09:14712}
713
[email protected]61de5812012-11-08 07:03:44714bool LayerTreeHostImpl::hasImplThread() const
715{
716 return m_proxy->hasImplThread();
717}
718
[email protected]8947cbe2012-11-28 05:27:43719void LayerTreeHostImpl::ScheduleManageTiles()
720{
721 if (m_client)
722 m_client->setNeedsManageTilesOnImplThread();
723}
724
[email protected]f35e2322012-12-15 21:45:52725bool LayerTreeHostImpl::shouldClearRootRenderPass() const
726{
727 return m_settings.shouldClearRootRenderPass;
728}
729
[email protected]96baf3e2012-10-22 23:09:55730void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14731{
[email protected]a0a00842012-10-22 22:50:28732 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14733 return;
[email protected]61de5812012-11-08 07:03:44734
[email protected]a0a00842012-10-22 22:50:28735 m_managedMemoryPolicy = policy;
[email protected]61de5812012-11-08 07:03:44736 if (!m_proxy->hasImplThread()) {
737 // FIXME: In single-thread mode, this can be called on the main thread
738 // by GLRenderer::onMemoryAllocationChanged.
739 DebugScopedSetImplThread implThread(m_proxy);
740 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
741 } else {
742 DCHECK(m_proxy->isImplThread());
743 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
744 }
[email protected]a0a00842012-10-22 22:50:28745 // We always need to commit after changing the memory policy because the new
746 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14747 m_client->setNeedsCommitOnImplThread();
748}
749
[email protected]a46f32932012-12-07 21:43:16750void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval)
[email protected]94f206c12012-08-25 00:09:14751{
[email protected]30faac92012-10-29 00:06:29752 m_client->onVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14753}
754
[email protected]b6f3d7e2012-12-08 00:11:21755void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack)
[email protected]a46f32932012-12-07 21:43:16756{
[email protected]b6f3d7e2012-12-08 00:11:21757 if (!m_renderer)
758 return;
759
760 // TODO(piman): We may need to do some validation on this ack before processing it.
761 m_renderer->receiveCompositorFrameAck(ack);
[email protected]a46f32932012-12-07 21:43:16762}
763
[email protected]3b31c6ac2012-12-06 21:27:29764void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl*)
765{
[email protected]a46f32932012-12-07 21:43:16766 m_client->onCanDrawStateChanged(canDraw());
[email protected]3b31c6ac2012-12-06 21:27:29767}
768
[email protected]bf189f62012-12-18 03:42:11769CompositorFrameMetadata LayerTreeHostImpl::makeCompositorFrameMetadata() const
770{
[email protected]bf189f62012-12-18 03:42:11771 CompositorFrameMetadata metadata;
[email protected]a823df82013-01-10 02:38:17772 metadata.page_scale_factor = m_pinchZoomViewport.total_page_scale_factor();
773 metadata.viewport_size = m_pinchZoomViewport.Bounds().size();
[email protected]f2b5a5be2013-01-08 00:34:36774 metadata.root_layer_size = contentSize();
[email protected]a823df82013-01-10 02:38:17775 metadata.min_page_scale_factor = m_pinchZoomViewport.min_page_scale_factor();
776 metadata.max_page_scale_factor = m_pinchZoomViewport.max_page_scale_factor();
[email protected]3ba4cae2013-01-16 03:58:38777 if (m_topControlsManager) {
778 metadata.location_bar_offset = gfx::Vector2dF(0.f, m_topControlsManager->controls_top_offset());
779 metadata.location_bar_content_translation = gfx::Vector2dF(0.f, m_topControlsManager->content_top_offset());
780 }
[email protected]bf189f62012-12-18 03:42:11781
[email protected]05469632013-01-16 03:41:00782 if (!rootScrollLayer())
783 return metadata;
784
785 metadata.root_scroll_offset = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
786 if (!m_settings.pageScalePinchZoomEnabled)
787 metadata.root_scroll_offset.Scale(1 / m_pinchZoomViewport.page_scale_factor());
788
[email protected]bf189f62012-12-18 03:42:11789 return metadata;
790}
791
[email protected]85167c72012-12-04 03:56:07792void LayerTreeHostImpl::drawLayers(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14793{
[email protected]96baf3e2012-10-22 23:09:55794 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04795 DCHECK(canDraw());
[email protected]ead39c52013-01-09 07:22:45796 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14797
798 // FIXME: use the frame begin time from the overall compositor scheduler.
799 // This value is currently inaccessible because it is up in Chromium's
800 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21801 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14802
[email protected]f511afb2012-11-30 01:55:20803 if (m_debugState.showHudRects())
[email protected]3b31c6ac2012-12-06 21:27:29804 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenSpaceRects, m_debugState);
[email protected]94f206c12012-08-25 00:09:14805
806 // Because the contents of the HUD depend on everything else in the frame, the contents
807 // of its texture are updated as the last thing before the frame is drawn.
[email protected]3b31c6ac2012-12-06 21:27:29808 if (m_activeTree->hud_layer())
809 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get());
[email protected]94f206c12012-08-25 00:09:14810
[email protected]20062042012-12-21 22:16:36811 m_renderer->drawFrame(frame.renderPasses);
[email protected]85167c72012-12-04 03:56:07812 // The render passes should be consumed by the renderer.
[email protected]ead39c52013-01-09 07:22:45813 DCHECK(frame.renderPasses.empty());
[email protected]20062042012-12-21 22:16:36814 frame.renderPassesById.clear();
[email protected]94f206c12012-08-25 00:09:14815
816 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
817 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
818 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
[email protected]3b31c6ac2012-12-06 21:27:29819 rootLayer()->resetAllChangeTrackingForSubtree();
[email protected]94f206c12012-08-25 00:09:14820}
821
[email protected]96baf3e2012-10-22 23:09:55822void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14823{
824 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
825 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52826
827 // Once all layers have been drawn, pending texture uploads should no
828 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09829 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14830}
831
[email protected]96baf3e2012-10-22 23:09:55832void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14833{
834 if (m_renderer)
835 m_renderer->finish();
836}
837
[email protected]96baf3e2012-10-22 23:09:55838bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14839{
840 return m_renderer && m_renderer->isContextLost();
841}
842
[email protected]96baf3e2012-10-22 23:09:55843const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14844{
845 return m_renderer->capabilities();
846}
847
[email protected]96baf3e2012-10-22 23:09:55848bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14849{
[email protected]1d993172012-10-18 18:15:04850 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14851
852 m_fpsCounter->markEndOfFrame();
853 return m_renderer->swapBuffers();
854}
855
[email protected]aad0a0072012-11-01 18:15:58856const gfx::Size& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10857{
858 return m_deviceViewportSize;
859}
860
[email protected]96baf3e2012-10-22 23:09:55861const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10862{
863 return m_settings;
864}
865
[email protected]3be2171d2012-12-06 06:13:20866void LayerTreeHostImpl::didLoseOutputSurface()
[email protected]94f206c12012-08-25 00:09:14867{
[email protected]3be2171d2012-12-06 06:13:20868 m_client->didLoseOutputSurfaceOnImplThread();
[email protected]94f206c12012-08-25 00:09:14869}
870
[email protected]96baf3e2012-10-22 23:09:55871void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14872{
873 m_client->onSwapBuffersCompleteOnImplThread();
874}
875
[email protected]aad0a0072012-11-01 18:15:58876void LayerTreeHostImpl::readback(void* pixels, const gfx::Rect& rect)
[email protected]94f206c12012-08-25 00:09:14877{
[email protected]1d993172012-10-18 18:15:04878 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14879 m_renderer->getFramebufferPixels(pixels, rect);
880}
881
[email protected]8bef40572012-12-11 21:38:08882LayerImpl* LayerTreeHostImpl::rootLayer() const
883{
884 return m_activeTree->RootLayer();
885}
886
887LayerImpl* LayerTreeHostImpl::rootScrollLayer() const
888{
889 return m_activeTree->root_scroll_layer();
890}
891
892LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const
893{
894 return m_activeTree->currently_scrolling_layer();
895}
896
[email protected]94f206c12012-08-25 00:09:14897// Content layers can be either directly scrollable or contained in an outer
898// scrolling layer which applies the scroll transform. Given a content layer,
899// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55900static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14901{
902 if (!layerImpl)
903 return 0;
904
905 if (layerImpl->scrollable())
906 return layerImpl;
907
908 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
909 return layerImpl->parent();
910
911 return 0;
912}
913
[email protected]3ba4cae2013-01-16 03:58:38914LayerTreeImpl* LayerTreeHostImpl::activeTree()
915{
916 return m_activeTree.get();
917}
918
[email protected]2e7ca422012-12-20 02:57:27919void LayerTreeHostImpl::createPendingTree()
920{
921 CHECK(!m_pendingTree);
922 m_pendingTree = LayerTreeImpl::create(this);
923 m_client->onCanDrawStateChanged(canDraw());
924 m_client->onHasPendingTreeStateChanged(pendingTree());
925}
926
[email protected]eabe5002013-01-12 22:07:48927void LayerTreeHostImpl::checkForCompletedSetPixels()
928{
929 if (m_tileManager)
930 m_tileManager->CheckForCompletedSetPixels();
931}
932
[email protected]2e7ca422012-12-20 02:57:27933void LayerTreeHostImpl::activatePendingTreeIfNeeded()
934{
935 if (!pendingTree())
936 return;
937
[email protected]eabe5002013-01-12 22:07:48938 checkForCompletedSetPixels();
939
[email protected]b0a917c8d2013-01-12 17:42:25940 // It's always fine to activate to an empty tree. Otherwise, only
941 // activate once all visible resources in pending tree are ready.
942 if (activeTree()->RootLayer() &&
943 !pendingTree()->AreVisibleResourcesReady())
944 return;
[email protected]2e7ca422012-12-20 02:57:27945
[email protected]2e7ca422012-12-20 02:57:27946 activatePendingTree();
947}
948
949void LayerTreeHostImpl::activatePendingTree()
950{
951 CHECK(m_pendingTree);
[email protected]1e0f8d62013-01-09 07:41:35952
953 m_activeTree->PushPersistedState(m_pendingTree.get());
[email protected]2e7ca422012-12-20 02:57:27954 m_activeTree.swap(m_pendingTree);
955 // TODO(enne): consider recycling this tree to prevent layer churn
956 m_pendingTree.reset();
[email protected]37386f052013-01-13 00:42:22957 m_activeTree->DidBecomeActive();
958
[email protected]2e7ca422012-12-20 02:57:27959 m_client->onCanDrawStateChanged(canDraw());
960 m_client->onHasPendingTreeStateChanged(pendingTree());
[email protected]eabe5002013-01-12 22:07:48961 m_client->setNeedsRedrawOnImplThread();
[email protected]2e7ca422012-12-20 02:57:27962}
963
[email protected]96baf3e2012-10-22 23:09:55964void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14965{
[email protected]61de5812012-11-08 07:03:44966 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14967
968 if (m_visible == visible)
969 return;
970 m_visible = visible;
971 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:28972 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:14973
974 if (!m_renderer)
975 return;
976
977 m_renderer->setVisible(visible);
978
[email protected]de4afb5e2012-12-20 00:11:34979 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_animation_controllers().empty());
[email protected]94f206c12012-08-25 00:09:14980}
981
[email protected]3be2171d2012-12-06 06:13:20982bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurface)
[email protected]94f206c12012-08-25 00:09:14983{
[email protected]be3181652012-09-25 13:02:13984 // Since we will create a new resource provider, we cannot continue to use
985 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
986 // before we destroy the old resource provider.
[email protected]45c4b1e2013-01-16 02:19:40987 if (rootLayer())
[email protected]94f206c12012-08-25 00:09:14988 clearRenderSurfaces();
[email protected]45c4b1e2013-01-16 02:19:40989 if (activeTree()->RootLayer())
990 sendDidLoseOutputSurfaceRecursive(activeTree()->RootLayer());
991 if (pendingTree() && pendingTree()->RootLayer())
992 sendDidLoseOutputSurfaceRecursive(pendingTree()->RootLayer());
993
[email protected]be3181652012-09-25 13:02:13994 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47995 m_renderer.reset();
[email protected]8947cbe2012-11-28 05:27:43996 m_tileManager.reset();
[email protected]a7aa5562012-10-17 14:12:44997 m_resourceProvider.reset();
[email protected]3be2171d2012-12-06 06:13:20998 m_outputSurface.reset();
[email protected]94f206c12012-08-25 00:09:14999
[email protected]a46f32932012-12-07 21:43:161000 if (!outputSurface->BindToClient(this))
[email protected]be3181652012-09-25 13:02:131001 return false;
1002
[email protected]3be2171d2012-12-06 06:13:201003 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(outputSurface.get());
[email protected]be3181652012-09-25 13:02:131004 if (!resourceProvider)
1005 return false;
1006
[email protected]8947cbe2012-11-28 05:27:431007 if (m_settings.implSidePainting)
[email protected]876e9e82012-12-04 20:12:141008 m_tileManager.reset(new TileManager(this, resourceProvider.get(), m_settings.numRasterThreads));
[email protected]8947cbe2012-11-28 05:27:431009
[email protected]ea9d8f22012-12-08 03:39:291010 if (outputSurface->Capabilities().has_parent_compositor)
[email protected]05469632013-01-16 03:41:001011 m_renderer = DelegatingRenderer::Create(this, outputSurface.get(), resourceProvider.get());
[email protected]ea9d8f22012-12-08 03:39:291012 else if (outputSurface->Context3D())
[email protected]bf189f62012-12-18 03:42:111013 m_renderer = GLRenderer::create(this, outputSurface.get(), resourceProvider.get());
[email protected]a46f32932012-12-07 21:43:161014 else if (outputSurface->SoftwareDevice())
1015 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), outputSurface->SoftwareDevice());
[email protected]be3181652012-09-25 13:02:131016 if (!m_renderer)
1017 return false;
1018
[email protected]76ffd9e2012-12-20 19:12:471019 setNeedsUpdateDrawProperties();
[email protected]a7aa5562012-10-17 14:12:441020 m_resourceProvider = resourceProvider.Pass();
[email protected]3be2171d2012-12-06 06:13:201021 m_outputSurface = outputSurface.Pass();
[email protected]94f206c12012-08-25 00:09:141022
[email protected]be3181652012-09-25 13:02:131023 if (!m_visible)
1024 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:141025
[email protected]8db2213c2012-09-05 22:08:211026 m_client->onCanDrawStateChanged(canDraw());
1027
[email protected]be3181652012-09-25 13:02:131028 return true;
[email protected]94f206c12012-08-25 00:09:141029}
1030
[email protected]96baf3e2012-10-22 23:09:551031void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:091032{
1033 m_contentsTexturesPurged = true;
1034 m_client->onCanDrawStateChanged(canDraw());
1035}
1036
[email protected]96baf3e2012-10-22 23:09:551037void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:211038{
1039 m_contentsTexturesPurged = false;
1040 m_client->onCanDrawStateChanged(canDraw());
1041}
1042
[email protected]aad0a0072012-11-01 18:15:581043void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:141044{
1045 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
1046 return;
1047
1048 m_layoutViewportSize = layoutViewportSize;
1049 m_deviceViewportSize = deviceViewportSize;
1050
[email protected]a823df82013-01-10 02:38:171051 m_pinchZoomViewport.set_layout_viewport_size(layoutViewportSize);
[email protected]1c0c9bc2012-10-08 22:41:481052
[email protected]c9c1ebe2012-11-05 20:46:131053 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141054
1055 if (m_renderer)
1056 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:211057
1058 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:141059}
1060
[email protected]96baf3e2012-10-22 23:09:551061static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:141062{
1063 if (!layerImpl)
1064 return;
1065
1066 if (layerImpl->scrollable()) {
1067 // We need to convert impl-side scroll deltas to pageScale space.
[email protected]c9c1ebe2012-11-05 20:46:131068 gfx::Vector2dF scrollDelta = layerImpl->scrollDelta();
1069 scrollDelta.Scale(pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141070 layerImpl->setScrollDelta(scrollDelta);
1071 }
1072
1073 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031074 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141075}
1076
[email protected]96baf3e2012-10-22 23:09:551077void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:141078{
1079 if (deviceScaleFactor == m_deviceScaleFactor)
1080 return;
1081 m_deviceScaleFactor = deviceScaleFactor;
[email protected]a823df82013-01-10 02:38:171082 m_pinchZoomViewport.set_device_scale_factor(m_deviceScaleFactor);
[email protected]c0dd24c2012-08-30 23:25:271083
[email protected]c9c1ebe2012-11-05 20:46:131084 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141085}
1086
[email protected]96baf3e2012-10-22 23:09:551087float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:141088{
[email protected]a823df82013-01-10 02:38:171089 return m_pinchZoomViewport.page_scale_factor();
[email protected]1c0c9bc2012-10-08 22:41:481090}
[email protected]94f206c12012-08-25 00:09:141091
[email protected]96baf3e2012-10-22 23:09:551092void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:481093{
1094 if (!pageScaleFactor)
1095 return;
[email protected]94f206c12012-08-25 00:09:141096
[email protected]a823df82013-01-10 02:38:171097 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.page_scale_factor();
1098 m_pinchZoomViewport.SetPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:141099
[email protected]0ede3bb2012-12-09 09:14:391100 if (!m_settings.pageScalePinchZoomEnabled && pageScaleChange != 1)
1101 adjustScrollsForPageScaleChange(rootScrollLayer(), pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141102
1103 // Clamp delta to limits and refresh display matrix.
[email protected]a823df82013-01-10 02:38:171104 setPageScaleDelta(m_pinchZoomViewport.page_scale_delta() / m_pinchZoomViewport.sent_page_scale_delta());
1105 m_pinchZoomViewport.set_sent_page_scale_delta(1);
[email protected]94f206c12012-08-25 00:09:141106}
1107
[email protected]96baf3e2012-10-22 23:09:551108void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:141109{
[email protected]a823df82013-01-10 02:38:171110 m_pinchZoomViewport.set_page_scale_delta(delta);
[email protected]94f206c12012-08-25 00:09:141111
[email protected]c9c1ebe2012-11-05 20:46:131112 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141113}
1114
[email protected]c9c1ebe2012-11-05 20:46:131115void LayerTreeHostImpl::updateMaxScrollOffset()
[email protected]94f206c12012-08-25 00:09:141116{
[email protected]caa567d2012-12-20 07:56:161117 activeTree()->UpdateMaxScrollOffset();
1118 if (pendingTree())
1119 pendingTree()->UpdateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141120}
1121
[email protected]3ba4cae2013-01-16 03:58:381122void LayerTreeHostImpl::setNeedsUpdateDrawProperties()
1123{
1124 m_needsUpdateDrawProperties = true;
1125}
1126
[email protected]96baf3e2012-10-22 23:09:551127void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141128{
1129 m_client->setNeedsRedrawOnImplThread();
1130}
1131
[email protected]96baf3e2012-10-22 23:09:551132bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141133{
[email protected]0ede3bb2012-12-09 09:14:391134 updateDrawProperties();
[email protected]76ffd9e2012-12-20 19:12:471135 return activeTree()->RenderSurfaceLayerList().size();
[email protected]94f206c12012-08-25 00:09:141136}
1137
[email protected]c9c1ebe2012-11-05 20:46:131138InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141139{
[email protected]96baf3e2012-10-22 23:09:551140 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141141
[email protected]3ba4cae2013-01-16 03:58:381142 if (m_topControlsManager)
1143 m_topControlsManager->ScrollBegin();
1144
[email protected]3b31c6ac2012-12-06 21:27:291145 DCHECK(!currentlyScrollingLayer());
[email protected]94f206c12012-08-25 00:09:141146 clearCurrentlyScrollingLayer();
1147
1148 if (!ensureRenderSurfaceLayerList())
1149 return ScrollIgnored;
1150
[email protected]faf56352012-11-09 21:44:131151 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141152
1153 // First find out which layer was hit from the saved list of visible layers
1154 // in the most recent frame.
[email protected]76ffd9e2012-12-20 19:12:471155 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, activeTree()->RenderSurfaceLayerList());
[email protected]94f206c12012-08-25 00:09:141156
1157 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551158 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141159 for (; layerImpl; layerImpl = layerImpl->parent()) {
1160 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271161 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1162 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141163 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271164 }
[email protected]94f206c12012-08-25 00:09:141165
[email protected]96baf3e2012-10-22 23:09:551166 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141167 if (!scrollLayerImpl)
1168 continue;
1169
[email protected]31bfe272012-10-19 18:49:521170 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141171
1172 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271173 if (status == ScrollOnMainThread) {
1174 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141175 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271176 }
[email protected]94f206c12012-08-25 00:09:141177
1178 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1179 potentiallyScrollingLayerImpl = scrollLayerImpl;
1180 }
1181
1182 if (potentiallyScrollingLayerImpl) {
[email protected]3b31c6ac2012-12-06 21:27:291183 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImpl);
[email protected]31bfe272012-10-19 18:49:521184 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141185 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1186 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521187 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271188 m_numImplThreadScrolls++;
[email protected]0ede3bb2012-12-09 09:14:391189 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141190 return ScrollStarted;
1191 }
1192 return ScrollIgnored;
1193}
1194
[email protected]c9c1ebe2012-11-05 20:46:131195static gfx::Vector2dF scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::Vector2dF viewportDelta)
[email protected]94f206c12012-08-25 00:09:141196{
1197 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1198 // test in the first place.
[email protected]c8686a02012-11-27 08:29:001199 DCHECK(layerImpl.screenSpaceTransform().IsInvertible());
[email protected]bda41962013-01-07 18:46:171200 gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
1201 bool didInvert = layerImpl.screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform);
1202 // TODO: With the advent of impl-side crolling for non-root layers, we may
1203 // need to explicitly handle uninvertible transforms here.
1204 DCHECK(didInvert);
[email protected]94f206c12012-08-25 00:09:141205
[email protected]faf56352012-11-09 21:44:131206 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521207
[email protected]c9c1ebe2012-11-05 20:46:131208 gfx::Vector2dF screenSpaceDelta = viewportDelta;
1209 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521210
[email protected]94f206c12012-08-25 00:09:141211 // First project the scroll start and end points to local layer space to find the scroll delta
1212 // in layer coordinates.
1213 bool startClipped, endClipped;
[email protected]d455d552012-11-02 00:19:061214 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1215 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1216 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141217
1218 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041219 DCHECK(!startClipped);
1220 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141221 if (startClipped || endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131222 return gfx::Vector2dF();
[email protected]94f206c12012-08-25 00:09:141223
[email protected]31bfe272012-10-19 18:49:521224 // 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:581225 float widthScale = 1 / layerImpl.contentsScaleX();
1226 float heightScale = 1 / layerImpl.contentsScaleY();
[email protected]faf56352012-11-09 21:44:131227 localStartPoint.Scale(widthScale, heightScale);
1228 localEndPoint.Scale(widthScale, heightScale);
[email protected]31bfe272012-10-19 18:49:521229
[email protected]94f206c12012-08-25 00:09:141230 // Apply the scroll delta.
[email protected]c9c1ebe2012-11-05 20:46:131231 gfx::Vector2dF previousDelta = layerImpl.scrollDelta();
1232 gfx::Vector2dF unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
[email protected]caa567d2012-12-20 07:56:161233 gfx::Vector2dF scrollAmount = localEndPoint - localStartPoint;
[email protected]1c0c9bc2012-10-08 22:41:481234
[email protected]aeaa50a2012-11-21 20:12:371235 gfx::Vector2dF viewportAppliedPan;
[email protected]1c0c9bc2012-10-08 22:41:481236 if (viewport)
[email protected]a823df82013-01-10 02:38:171237 viewportAppliedPan = unscrolled - viewport->ApplyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141238
[email protected]31bfe272012-10-19 18:49:521239 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]aeaa50a2012-11-21 20:12:371240 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() + viewportAppliedPan - previousDelta;
[email protected]faf56352012-11-09 21:44:131241 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint, 1 / widthScale, 1 / heightScale);
[email protected]31bfe272012-10-19 18:49:521242
1243 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]d455d552012-11-02 00:19:061244 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041245 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141246 if (endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131247 return gfx::Vector2dF();
[email protected]faf56352012-11-09 21:44:131248 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoint, 1 / scaleFromViewportToScreenSpace);
[email protected]c9c1ebe2012-11-05 20:46:131249 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141250}
1251
[email protected]c9c1ebe2012-11-05 20:46:131252static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vector2dF localDelta)
[email protected]94f206c12012-08-25 00:09:141253{
[email protected]c9c1ebe2012-11-05 20:46:131254 gfx::Vector2dF previousDelta(layerImpl.scrollDelta());
[email protected]94f206c12012-08-25 00:09:141255 layerImpl.scrollBy(localDelta);
1256 return layerImpl.scrollDelta() - previousDelta;
1257}
1258
[email protected]a9710962012-11-14 20:11:021259bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint,
1260 const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141261{
[email protected]96baf3e2012-10-22 23:09:551262 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]3b31c6ac2012-12-06 21:27:291263 if (!currentlyScrollingLayer())
[email protected]a9710962012-11-14 20:11:021264 return false;
[email protected]94f206c12012-08-25 00:09:141265
[email protected]c9c1ebe2012-11-05 20:46:131266 gfx::Vector2dF pendingDelta = scrollDelta;
[email protected]1ca52a3a2012-12-04 22:47:101267 bool didScroll = false;
[email protected]94f206c12012-08-25 00:09:141268
[email protected]3b31c6ac2012-12-06 21:27:291269 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141270 if (!layerImpl->scrollable())
1271 continue;
1272
[email protected]dbed4272012-12-06 08:50:481273 PinchZoomViewport* viewport = NULL;
[email protected]3b31c6ac2012-12-06 21:27:291274 if (m_settings.pageScalePinchZoomEnabled && layerImpl == rootScrollLayer())
[email protected]dbed4272012-12-06 08:50:481275 viewport = &m_pinchZoomViewport;
[email protected]c9c1ebe2012-11-05 20:46:131276 gfx::Vector2dF appliedDelta;
[email protected]3ba4cae2013-01-16 03:58:381277 if (m_topControlsManager && layerImpl == rootScrollLayer())
1278 pendingDelta = m_topControlsManager->ScrollBy(pendingDelta);
1279
[email protected]31bfe272012-10-19 18:49:521280 if (m_scrollDeltaIsInViewportSpace) {
1281 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1282 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1283 } else
[email protected]94f206c12012-08-25 00:09:141284 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1285
1286 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381287 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]c9c1ebe2012-11-05 20:46:131288 if (appliedDelta.LengthSquared() < moveThresholdSquared)
[email protected]94f206c12012-08-25 00:09:141289 continue;
[email protected]1ca52a3a2012-12-04 22:47:101290 didScroll = true;
[email protected]94f206c12012-08-25 00:09:141291
1292 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1293 // to scroll just one layer in one direction without affecting any of its parents.
1294 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551295 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]c9c1ebe2012-11-05 20:46:131296 pendingDelta = gfx::Vector2d();
[email protected]94f206c12012-08-25 00:09:141297 break;
1298 }
1299
1300 // Allow further movement only on an axis perpendicular to the direction in which the layer
1301 // moved.
[email protected]c9c1ebe2012-11-05 20:46:131302 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x());
[email protected]96baf3e2012-10-22 23:09:551303 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141304
[email protected]c9c1ebe2012-11-05 20:46:131305 if (gfx::ToFlooredVector2d(pendingDelta).IsZero())
[email protected]94f206c12012-08-25 00:09:141306 break;
1307 }
1308
[email protected]1ca52a3a2012-12-04 22:47:101309 if (didScroll) {
[email protected]94f206c12012-08-25 00:09:141310 m_client->setNeedsCommitOnImplThread();
1311 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391312 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141313 }
[email protected]1ca52a3a2012-12-04 22:47:101314 return didScroll;
[email protected]94f206c12012-08-25 00:09:141315}
1316
[email protected]96baf3e2012-10-22 23:09:551317void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141318{
[email protected]3b31c6ac2012-12-06 21:27:291319 m_activeTree->ClearCurrentlyScrollingLayer();
[email protected]94f206c12012-08-25 00:09:141320}
1321
[email protected]96baf3e2012-10-22 23:09:551322void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141323{
[email protected]3ba4cae2013-01-16 03:58:381324 if (m_topControlsManager)
1325 m_topControlsManager->ScrollEnd();
[email protected]94f206c12012-08-25 00:09:141326 clearCurrentlyScrollingLayer();
1327}
1328
[email protected]96baf3e2012-10-22 23:09:551329void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141330{
1331 m_pinchGestureActive = true;
[email protected]c9c1ebe2012-11-05 20:46:131332 m_previousPinchAnchor = gfx::Point();
[email protected]94f206c12012-08-25 00:09:141333
[email protected]3b31c6ac2012-12-06 21:27:291334 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1335 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureBegin();
[email protected]94f206c12012-08-25 00:09:141336}
1337
[email protected]c9c1ebe2012-11-05 20:46:131338void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor)
[email protected]94f206c12012-08-25 00:09:141339{
[email protected]96baf3e2012-10-22 23:09:551340 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141341
[email protected]3b31c6ac2012-12-06 21:27:291342 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141343 return;
1344
[email protected]94f206c12012-08-25 00:09:141345 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1346 // position over the course of the magnify.
[email protected]a823df82013-01-10 02:38:171347 float pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
[email protected]c77745d2012-11-20 04:11:571348 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:481349 setPageScaleDelta(pageScaleDelta * magnifyDelta);
[email protected]a823df82013-01-10 02:38:171350 pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
[email protected]faf56352012-11-09 21:44:131351 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:131352 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor;
[email protected]94f206c12012-08-25 00:09:141353
1354 m_previousPinchAnchor = anchor;
1355
[email protected]9bdcfd642012-11-14 21:24:261356 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481357 // Compute the application of the delta with respect to the current page zoom of the page.
[email protected]a823df82013-01-10 02:38:171358 move.Scale(1 / m_pinchZoomViewport.page_scale_factor());
[email protected]1c0c9bc2012-10-08 22:41:481359 }
1360
[email protected]a823df82013-01-10 02:38:171361 gfx::Vector2dF scrollOverflow = m_settings.pageScalePinchZoomEnabled ? m_pinchZoomViewport.ApplyScroll(move) : move;
[email protected]3b31c6ac2012-12-06 21:27:291362 rootScrollLayer()->scrollBy(scrollOverflow);
[email protected]94f206c12012-08-25 00:09:141363
[email protected]3b31c6ac2012-12-06 21:27:291364 if (rootScrollLayer()->scrollbarAnimationController())
1365 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureUpdate();
[email protected]94f206c12012-08-25 00:09:141366
1367 m_client->setNeedsCommitOnImplThread();
1368 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391369 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141370}
1371
[email protected]96baf3e2012-10-22 23:09:551372void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141373{
1374 m_pinchGestureActive = false;
1375
[email protected]3b31c6ac2012-12-06 21:27:291376 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1377 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:141378
1379 m_client->setNeedsCommitOnImplThread();
1380}
1381
[email protected]96baf3e2012-10-22 23:09:551382void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141383{
[email protected]f6250742012-11-09 04:46:561384 gfx::Vector2dF scaledScrollOffset = m_pageScaleAnimation->targetScrollOffset();
[email protected]9bdcfd642012-11-14 21:24:261385 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]a823df82013-01-10 02:38:171386 scaledScrollOffset.Scale(m_pinchZoomViewport.page_scale_factor());
[email protected]f6250742012-11-09 04:46:561387 makeScrollAndScaleSet(scrollInfo, ToFlooredVector2d(scaledScrollOffset), m_pageScaleAnimation->targetPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141388}
1389
[email protected]96baf3e2012-10-22 23:09:551390void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141391{
[email protected]3b31c6ac2012-12-06 21:27:291392 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141393 return;
1394
1395 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1396 // significant amount. This also ensures only one fake delta set will be
1397 // sent.
[email protected]23bbb412012-08-30 20:03:381398 const float pinchZoomOutSensitivity = 0.95f;
[email protected]a823df82013-01-10 02:38:171399 if (m_pinchZoomViewport.page_scale_delta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141400 return;
1401
1402 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1403 // out from the anchor point.
[email protected]3b31c6ac2012-12-06 21:27:291404 gfx::Vector2dF scrollBegin = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]a823df82013-01-10 02:38:171405 scrollBegin.Scale(m_pinchZoomViewport.page_scale_delta());
1406 float scaleBegin = m_pinchZoomViewport.total_page_scale_factor();
1407 float pageScaleDeltaToSend = m_pinchZoomViewport.min_page_scale_factor() / m_pinchZoomViewport.page_scale_factor();
[email protected]01a15a72012-11-10 09:34:281408 gfx::SizeF scaledContentsSize = gfx::ScaleSize(contentSize(), pageScaleDeltaToSend);
[email protected]94f206c12012-08-25 00:09:141409
[email protected]c9c1ebe2012-11-05 20:46:131410 gfx::Vector2d anchorOffset = m_previousPinchAnchor.OffsetFromOrigin();
1411 gfx::Vector2dF scrollEnd = scrollBegin + anchorOffset;
[email protected]a823df82013-01-10 02:38:171412 scrollEnd.Scale(m_pinchZoomViewport.min_page_scale_factor() / scaleBegin);
[email protected]c9c1ebe2012-11-05 20:46:131413 scrollEnd -= anchorOffset;
[email protected]0eef4b882012-11-20 20:28:071414 scrollEnd.ClampToMax(gfx::RectF(scaledContentsSize).bottom_right() - gfx::Rect(m_deviceViewportSize).bottom_right());
[email protected]fe07b642012-11-10 00:07:591415 scrollEnd.ClampToMin(gfx::Vector2d());
[email protected]c9c1ebe2012-11-05 20:46:131416 scrollEnd.Scale(1 / pageScaleDeltaToSend);
1417 scrollEnd.Scale(m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141418
[email protected]a823df82013-01-10 02:38:171419 makeScrollAndScaleSet(scrollInfo, gfx::ToRoundedVector2d(scrollEnd), m_pinchZoomViewport.min_page_scale_factor());
[email protected]94f206c12012-08-25 00:09:141420}
1421
[email protected]c9c1ebe2012-11-05 20:46:131422void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141423{
[email protected]3b31c6ac2012-12-06 21:27:291424 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141425 return;
1426
[email protected]96baf3e2012-10-22 23:09:551427 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]3b31c6ac2012-12-06 21:27:291428 scroll.layerId = rootScrollLayer()->id();
1429 scroll.scrollDelta = scrollOffset - rootScrollLayer()->scrollOffset();
[email protected]787465c2012-10-29 01:12:271430 scrollInfo->scrolls.push_back(scroll);
[email protected]caa567d2012-12-20 07:56:161431 activeTree()->root_scroll_layer()->setSentScrollDelta(scroll.scrollDelta);
[email protected]a823df82013-01-10 02:38:171432 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.page_scale_factor();
1433 m_pinchZoomViewport.set_sent_page_scale_delta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141434}
1435
[email protected]96baf3e2012-10-22 23:09:551436static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141437{
1438 if (!layerImpl)
1439 return;
1440
[email protected]c9c1ebe2012-11-05 20:46:131441 if (!layerImpl->scrollDelta().IsZero()) {
1442 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551443 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141444 scroll.layerId = layerImpl->id();
1445 scroll.scrollDelta = scrollDelta;
[email protected]787465c2012-10-29 01:12:271446 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141447 layerImpl->setSentScrollDelta(scrollDelta);
1448 }
1449
1450 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031451 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141452}
1453
[email protected]96baf3e2012-10-22 23:09:551454scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141455{
[email protected]96baf3e2012-10-22 23:09:551456 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141457
1458 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481459 scrollInfo->pageScaleDelta = 1;
[email protected]a823df82013-01-10 02:38:171460 m_pinchZoomViewport.set_sent_page_scale_delta(1);
[email protected]f6250742012-11-09 04:46:561461 // FIXME(aelias): Make pinch-zoom painting optimization compatible with
[email protected]1c0c9bc2012-10-08 22:41:481462 // compositor-side scaling.
[email protected]9bdcfd642012-11-14 21:24:261463 if (!m_settings.pageScalePinchZoomEnabled && m_pinchGestureActive)
[email protected]f6250742012-11-09 04:46:561464 computePinchZoomDeltas(scrollInfo.get());
1465 else if (m_pageScaleAnimation.get())
1466 computeDoubleTapZoomDeltas(scrollInfo.get());
[email protected]a9f4bf22012-10-11 23:39:211467 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141468 }
1469
[email protected]3b31c6ac2012-12-06 21:27:291470 collectScrollDeltas(scrollInfo.get(), rootLayer());
[email protected]a823df82013-01-10 02:38:171471 scrollInfo->pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
1472 m_pinchZoomViewport.set_sent_page_scale_delta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141473
[email protected]a9f4bf22012-10-11 23:39:211474 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141475}
1476
[email protected]c8686a02012-11-27 08:29:001477gfx::Transform LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481478{
[email protected]a823df82013-01-10 02:38:171479 return m_pinchZoomViewport.ImplTransform(m_settings.pageScalePinchZoomEnabled);
[email protected]1c0c9bc2012-10-08 22:41:481480}
1481
[email protected]96baf3e2012-10-22 23:09:551482void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141483{
[email protected]3b31c6ac2012-12-06 21:27:291484 if (rootLayer()) {
1485 RenderSurfaceImpl* renderSurface = rootLayer()->renderSurface();
[email protected]94f206c12012-08-25 00:09:141486 if (renderSurface)
1487 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1488 }
1489}
1490
[email protected]30faac92012-10-29 00:06:291491void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141492{
[email protected]3b31c6ac2012-12-06 21:27:291493 if (!m_pageScaleAnimation || !rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141494 return;
1495
[email protected]30faac92012-10-29 00:06:291496 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]3b31c6ac2012-12-06 21:27:291497 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]94f206c12012-08-25 00:09:141498
[email protected]a823df82013-01-10 02:38:171499 setPageScaleDelta(m_pageScaleAnimation->pageScaleFactorAtTime(monotonicTime) / m_pinchZoomViewport.page_scale_factor());
[email protected]c9c1ebe2012-11-05 20:46:131500 gfx::Vector2dF nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]f6250742012-11-09 04:46:561501
[email protected]9bdcfd642012-11-14 21:24:261502 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]a823df82013-01-10 02:38:171503 nextScroll.Scale(m_pinchZoomViewport.page_scale_factor());
[email protected]3b31c6ac2012-12-06 21:27:291504 rootScrollLayer()->scrollBy(nextScroll - scrollTotal);
[email protected]94f206c12012-08-25 00:09:141505 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391506 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141507
1508 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451509 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141510 m_client->setNeedsCommitOnImplThread();
1511 }
1512}
1513
[email protected]30faac92012-10-29 00:06:291514void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:141515{
[email protected]de4afb5e2012-12-20 00:11:341516 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_animation_controllers().empty() || !rootLayer())
[email protected]94f206c12012-08-25 00:09:141517 return;
1518
[email protected]96baf3e2012-10-22 23:09:551519 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141520
[email protected]de4afb5e2012-12-20 00:11:341521 double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
[email protected]df1ec1a2012-12-08 17:01:181522
[email protected]de4afb5e2012-12-20 00:11:341523 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
1524 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->active_animation_controllers();
1525 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); iter != copy.end(); ++iter)
1526 (*iter).second->animate(monotonicSeconds, events.get());
[email protected]94f206c12012-08-25 00:09:141527
[email protected]d3143c732012-10-05 19:17:591528 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571529 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141530
[email protected]de4afb5e2012-12-20 00:11:341531 m_client->setNeedsRedrawOnImplThread();
1532 setNeedsUpdateDrawProperties();
1533 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_animation_controllers().empty());
[email protected]94f206c12012-08-25 00:09:141534}
1535
[email protected]96baf3e2012-10-22 23:09:551536base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141537{
[email protected]4481ddb622012-09-20 16:33:471538 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141539}
1540
[email protected]3be2171d2012-12-06 06:13:201541void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141542{
[email protected]1d993172012-10-18 18:15:041543 DCHECK(current);
[email protected]3be2171d2012-12-06 06:13:201544 current->didLoseOutputSurface();
[email protected]94f206c12012-08-25 00:09:141545 if (current->maskLayer())
[email protected]3be2171d2012-12-06 06:13:201546 sendDidLoseOutputSurfaceRecursive(current->maskLayer());
[email protected]94f206c12012-08-25 00:09:141547 if (current->replicaLayer())
[email protected]3be2171d2012-12-06 06:13:201548 sendDidLoseOutputSurfaceRecursive(current->replicaLayer());
[email protected]94f206c12012-08-25 00:09:141549 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]3be2171d2012-12-06 06:13:201550 sendDidLoseOutputSurfaceRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141551}
1552
[email protected]96baf3e2012-10-22 23:09:551553void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141554{
[email protected]76ffd9e2012-12-20 19:12:471555 activeTree()->ClearRenderSurfaces();
1556 if (pendingTree())
1557 pendingTree()->ClearRenderSurfaces();
[email protected]94f206c12012-08-25 00:09:141558}
1559
[email protected]96baf3e2012-10-22 23:09:551560std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141561{
[email protected]515e8d232012-09-10 19:15:271562 std::string str;
[email protected]3b31c6ac2012-12-06 21:27:291563 if (rootLayer()) {
1564 str = rootLayer()->layerTreeAsText();
[email protected]515e8d232012-09-10 19:15:271565 str += "RenderSurfaces:\n";
[email protected]3b31c6ac2012-12-06 21:27:291566 dumpRenderSurfaces(&str, 1, rootLayer());
[email protected]94f206c12012-08-25 00:09:141567 }
[email protected]515e8d232012-09-10 19:15:271568 return str;
[email protected]94f206c12012-08-25 00:09:141569}
1570
[email protected]4a23c374c2012-12-08 08:38:551571std::string LayerTreeHostImpl::layerTreeAsJson() const
1572{
1573 std::string str;
1574 if (rootLayer()) {
1575 scoped_ptr<base::Value> json(rootLayer()->layerTreeAsJson());
1576 base::JSONWriter::WriteWithOptions(
1577 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1578 }
1579 return str;
1580}
1581
[email protected]96baf3e2012-10-22 23:09:551582void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141583{
1584 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271585 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141586
1587 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031588 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141589}
1590
[email protected]96baf3e2012-10-22 23:09:551591int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141592{
1593 return fpsCounter()->currentFrameNumber();
1594}
1595
[email protected]96baf3e2012-10-22 23:09:551596void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141597{
[email protected]8b9af6b2012-09-27 00:36:361598 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1599 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271600 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1601 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]b2136f12012-11-30 02:45:531602 stats->numLayersDrawn = m_cumulativeNumLayersDrawn;
[email protected]f2bbb4e2012-12-07 21:40:491603 stats->numMissingTiles = m_cumulativeNumMissingTiles;
[email protected]4d3c5c912012-11-30 05:55:021604
1605 if (m_tileManager)
[email protected]ee371e02012-12-16 20:13:441606 m_tileManager->GetRenderingStats(stats);
[email protected]94f206c12012-08-25 00:09:141607}
1608
[email protected]d3afa112012-12-08 06:24:281609void LayerTreeHostImpl::sendManagedMemoryStats(
1610 size_t memoryVisibleBytes,
1611 size_t memoryVisibleAndNearbyBytes,
1612 size_t memoryUseBytes)
1613{
1614 if (!renderer())
1615 return;
1616
1617 // Round the numbers being sent up to the next 8MB, to throttle the rate
1618 // at which we spam the GPU process.
1619 static const size_t roundingStep = 8 * 1024 * 1024;
1620 memoryVisibleBytes = RoundUp(memoryVisibleBytes, roundingStep);
1621 memoryVisibleAndNearbyBytes = RoundUp(memoryVisibleAndNearbyBytes, roundingStep);
1622 memoryUseBytes = RoundUp(memoryUseBytes, roundingStep);
1623 if (m_lastSentMemoryVisibleBytes == memoryVisibleBytes &&
1624 m_lastSentMemoryVisibleAndNearbyBytes == memoryVisibleAndNearbyBytes &&
1625 m_lastSentMemoryUseBytes == memoryUseBytes) {
1626 return;
1627 }
1628 m_lastSentMemoryVisibleBytes = memoryVisibleBytes;
1629 m_lastSentMemoryVisibleAndNearbyBytes = memoryVisibleAndNearbyBytes;
1630 m_lastSentMemoryUseBytes = memoryUseBytes;
1631
1632 renderer()->sendManagedMemoryStats(m_lastSentMemoryVisibleBytes,
1633 m_lastSentMemoryVisibleAndNearbyBytes,
1634 m_lastSentMemoryUseBytes);
1635}
1636
[email protected]30faac92012-10-29 00:06:291637void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141638{
[email protected]3b31c6ac2012-12-06 21:27:291639 animateScrollbarsRecursive(rootLayer(), time);
[email protected]94f206c12012-08-25 00:09:141640}
1641
[email protected]30faac92012-10-29 00:06:291642void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141643{
1644 if (!layer)
1645 return;
1646
[email protected]96baf3e2012-10-22 23:09:551647 ScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]30faac92012-10-29 00:06:291648 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]94f206c12012-08-25 00:09:141649 if (scrollbarController && scrollbarController->animate(monotonicTime))
1650 m_client->setNeedsRedrawOnImplThread();
1651
1652 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]30faac92012-10-29 00:06:291653 animateScrollbarsRecursive(layer->children()[i], time);
[email protected]94f206c12012-08-25 00:09:141654}
1655
[email protected]b9dcf43a2013-01-09 00:15:291656// static
1657LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* layer)
1658{
1659 if (!layer)
1660 return NULL;
1661
1662 if (layer->drawsContent())
1663 return layer;
1664
1665 for (LayerImpl::LayerList::const_iterator it = layer->children().begin();
1666 it != layer->children().end(); ++it) {
1667 LayerImpl* nccr = getNonCompositedContentLayerRecursive(*it);
1668 if (nccr)
1669 return nccr;
1670 }
1671
1672 return NULL;
1673}
1674
1675skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture()
1676{
1677 LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree();
1678 LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer());
1679 return layer ? layer->getPicture() : skia::RefPtr<SkPicture>();
1680}
1681
[email protected]d3143c732012-10-05 19:17:591682} // namespace cc