blob: 31f8ac9e31eb63d345fbb636e7c6ead8a43a2504 [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]d3afa112012-12-08 06:24:2840#include "cc/util.h"
[email protected]d455d552012-11-02 00:19:0641#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1342#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1443
[email protected]94f206c12012-08-25 00:09:1444namespace {
45
[email protected]96baf3e2012-10-22 23:09:5546void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1447{
48 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5549 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1450 return;
51 }
52
[email protected]96baf3e2012-10-22 23:09:5553 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1454}
55
56} // namespace
57
[email protected]9c88e562012-09-14 22:21:3058namespace cc {
[email protected]94f206c12012-08-25 00:09:1459
[email protected]96baf3e2012-10-22 23:09:5560class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:1461public:
[email protected]96baf3e2012-10-22 23:09:5562 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:1463 {
[email protected]96baf3e2012-10-22 23:09:5564 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:1465 }
[email protected]96baf3e2012-10-22 23:09:5566 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:1467 {
68 m_timeSource->setClient(0);
69 m_timeSource->setActive(false);
70 }
71
72 virtual void onTimerTick() OVERRIDE
73 {
[email protected]373974232013-01-10 22:20:5074 // In single threaded mode we attempt to simulate changing the current
75 // thread by maintaining a fake thread id. When we switch from one
76 // thread to another, we construct DebugScopedSetXXXThread objects that
77 // update the thread id. This lets DCHECKS that ensure we're on the
78 // right thread to work correctly in single threaded mode. The problem
79 // here is that the timer tasks are run via the message loop, and when
80 // they run, we've had no chance to construct a DebugScopedSetXXXThread
81 // object. The result is that we report that we're running on the main
82 // thread. In multi-threaded mode, this timer is run on the compositor
83 // thread, so to keep this consistent in single-threaded mode, we'll
84 // construct a DebugScopedSetImplThread object. There is no need to do
85 // this in multi-threaded mode since the real thread id's will be
86 // correct. In fact, setting fake thread id's interferes with the real
87 // thread id's and causes breakage.
88 scoped_ptr<DebugScopedSetImplThread> setImplThread;
89 if (!m_layerTreeHostImpl->proxy()->hasImplThread())
90 setImplThread.reset(new DebugScopedSetImplThread(m_layerTreeHostImpl->proxy()));
91
[email protected]30faac92012-10-29 00:06:2992 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]94f206c12012-08-25 00:09:1493 }
94
95 void setActive(bool active)
96 {
97 if (active != m_timeSource->active())
98 m_timeSource->setActive(active);
99 }
100
101private:
[email protected]96baf3e2012-10-22 23:09:55102 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14103 : m_layerTreeHostImpl(layerTreeHostImpl)
104 , m_timeSource(timeSource)
105 {
106 m_timeSource->setClient(this);
107 }
108
[email protected]96baf3e2012-10-22 23:09:55109 LayerTreeHostImpl* m_layerTreeHostImpl;
110 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20111
[email protected]96baf3e2012-10-22 23:09:55112 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14113};
114
[email protected]96baf3e2012-10-22 23:09:55115LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10116{
117}
118
[email protected]96baf3e2012-10-22 23:09:55119LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10120{
121}
122
[email protected]61de5812012-11-08 07:03:44123scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14124{
[email protected]61de5812012-11-08 07:03:44125 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
[email protected]94f206c12012-08-25 00:09:14126}
127
[email protected]61de5812012-11-08 07:03:44128LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14129 : m_client(client)
[email protected]61de5812012-11-08 07:03:44130 , m_proxy(proxy)
[email protected]31bfe272012-10-19 18:49:52131 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14132 , m_settings(settings)
[email protected]f511afb2012-11-30 01:55:20133 , m_debugState(settings.initialDebugState)
[email protected]94f206c12012-08-25 00:09:14134 , m_deviceScaleFactor(1)
135 , m_visible(true)
136 , m_contentsTexturesPurged(false)
[email protected]3b10a302012-11-07 21:16:40137 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
[email protected]9b0b79a02013-01-02 22:47:27138 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
[email protected]a0a00842012-10-22 22:50:28139 0,
[email protected]9b0b79a02013-01-02 22:47:27140 ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING)
[email protected]0ede3bb2012-12-09 09:14:39141 , m_needsUpdateDrawProperties(false)
[email protected]94f206c12012-08-25 00:09:14142 , m_pinchGestureActive(false)
[email protected]61de5812012-11-08 07:03:44143 , m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
[email protected]96baf3e2012-10-22 23:09:55144 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27145 , m_numImplThreadScrolls(0)
146 , m_numMainThreadScrolls(0)
[email protected]b2136f12012-11-30 02:45:53147 , m_cumulativeNumLayersDrawn(0)
[email protected]f2bbb4e2012-12-07 21:40:49148 , m_cumulativeNumMissingTiles(0)
[email protected]d3afa112012-12-08 06:24:28149 , m_lastSentMemoryVisibleBytes(0)
150 , m_lastSentMemoryVisibleAndNearbyBytes(0)
151 , m_lastSentMemoryUseBytes(0)
[email protected]de4afb5e2012-12-20 00:11:34152 , m_animationRegistrar(AnimationRegistrar::create())
[email protected]94f206c12012-08-25 00:09:14153{
[email protected]61de5812012-11-08 07:03:44154 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14155 didVisibilityChange(this, m_visible);
[email protected]3b31c6ac2012-12-06 21:27:29156
[email protected]2e7ca422012-12-20 02:57:27157 // LTHI always has an active tree.
[email protected]3b31c6ac2012-12-06 21:27:29158 m_activeTree = LayerTreeImpl::create(this);
[email protected]94f206c12012-08-25 00:09:14159}
160
[email protected]96baf3e2012-10-22 23:09:55161LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14162{
[email protected]61de5812012-11-08 07:03:44163 DCHECK(m_proxy->isImplThread());
[email protected]96baf3e2012-10-22 23:09:55164 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14165
[email protected]de4afb5e2012-12-20 00:11:34166 if (rootLayer()) {
[email protected]94f206c12012-08-25 00:09:14167 clearRenderSurfaces();
[email protected]de4afb5e2012-12-20 00:11:34168 // The layer trees must be destroyed before the layer tree host. We've
169 // made a contract with our animation controllers that the registrar
170 // will outlive them, and we must make good.
171 m_activeTree.reset();
172 m_pendingTree.reset();
173 }
[email protected]94f206c12012-08-25 00:09:14174}
175
[email protected]96baf3e2012-10-22 23:09:55176void LayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14177{
178}
179
[email protected]96baf3e2012-10-22 23:09:55180void LayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14181{
[email protected]96baf3e2012-10-22 23:09:55182 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
[email protected]0ede3bb2012-12-09 09:14:39183
184 // Impl-side painting needs an update immediately post-commit to have the
185 // opportunity to create tilings. Other paths can call updateDrawProperties
186 // more lazily when needed prior to drawing.
187 setNeedsUpdateDrawProperties();
188 if (m_settings.implSidePainting)
189 updateDrawProperties();
190
[email protected]94f206c12012-08-25 00:09:14191 // Recompute max scroll position; must be after layer content bounds are
192 // updated.
[email protected]c9c1ebe2012-11-05 20:46:13193 updateMaxScrollOffset();
[email protected]3d21e022012-10-25 20:03:08194 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14195}
196
[email protected]96baf3e2012-10-22 23:09:55197bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14198{
[email protected]8db2213c2012-09-05 22:08:21199 // Note: If you are changing this function or any other function that might
200 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
201 // in the proper places and update the notifyIfCanDrawChanged test.
202
[email protected]2e7ca422012-12-20 02:57:27203 // TODO(enne): Since prepareToDraw is the only place that currently does
204 // tree activiation, this allows prepareToDraw to be entered even if the
205 // active tree can't draw. This could cause flashing, though. This should
206 // probably be refactored such that the scheduler handles the tree
207 // activation rather than prepareToDrwa.
208 if (pendingTree())
209 return true;
210
[email protected]3b31c6ac2012-12-06 21:27:29211 if (!rootLayer()) {
[email protected]96baf3e2012-10-22 23:09:55212 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14213 return false;
214 }
[email protected]aad0a0072012-11-01 18:15:58215 if (deviceViewportSize().IsEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55216 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14217 return false;
218 }
219 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55220 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14221 return false;
222 }
223 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55224 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14225 return false;
226 }
227 return true;
228}
229
[email protected]3be2171d2012-12-06 06:13:20230OutputSurface* LayerTreeHostImpl::outputSurface() const
[email protected]94f206c12012-08-25 00:09:14231{
[email protected]3be2171d2012-12-06 06:13:20232 return m_outputSurface.get();
[email protected]94f206c12012-08-25 00:09:14233}
234
[email protected]30faac92012-10-29 00:06:29235void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:14236{
237 animatePageScale(monotonicTime);
238 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14239 animateScrollbars(monotonicTime);
240}
241
[email protected]8947cbe2012-11-28 05:27:43242void LayerTreeHostImpl::manageTiles()
243{
244 DCHECK(m_tileManager);
245 m_tileManager->ManageTiles();
[email protected]9b0b79a02013-01-02 22:47:27246
247 size_t memoryRequiredBytes;
248 size_t memoryNiceToHaveBytes;
249 size_t memoryUsedBytes;
250 m_tileManager->GetMemoryStats(&memoryRequiredBytes,
251 &memoryNiceToHaveBytes,
252 &memoryUsedBytes);
253 sendManagedMemoryStats(memoryRequiredBytes,
254 memoryNiceToHaveBytes,
255 memoryUsedBytes);
[email protected]8947cbe2012-11-28 05:27:43256}
257
[email protected]69a2a5be2012-11-14 06:51:44258void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration)
[email protected]94f206c12012-08-25 00:09:14259{
[email protected]3b31c6ac2012-12-06 21:27:29260 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:14261 return;
262
[email protected]3b31c6ac2012-12-06 21:27:29263 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]f6250742012-11-09 04:46:56264 gfx::SizeF scaledContentSize = contentSize();
[email protected]9bdcfd642012-11-14 21:24:26265 if (!m_settings.pageScalePinchZoomEnabled) {
[email protected]a823df82013-01-10 02:38:17266 scrollTotal.Scale(1 / m_pinchZoomViewport.page_scale_factor());
267 scaledContentSize.Scale(1 / m_pinchZoomViewport.page_scale_factor());
[email protected]f6250742012-11-09 04:46:56268 }
[email protected]01a15a72012-11-10 09:34:28269 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14270
[email protected]30faac92012-10-29 00:06:29271 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
[email protected]a823df82013-01-10 02:38:17272 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, m_pinchZoomViewport.total_page_scale_factor(), viewportSize, scaledContentSize, startTimeSeconds);
[email protected]94f206c12012-08-25 00:09:14273
274 if (anchorPoint) {
[email protected]69a2a5be2012-11-14 06:51:44275 gfx::Vector2dF anchor(targetOffset);
[email protected]9bdcfd642012-11-14 21:24:26276 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:56277 anchor.Scale(1 / pageScale);
278 m_pageScaleAnimation->zoomWithAnchor(anchor, pageScale, duration.InSecondsF());
279 } else {
[email protected]69a2a5be2012-11-14 06:51:44280 gfx::Vector2dF scaledTargetOffset = targetOffset;
[email protected]9bdcfd642012-11-14 21:24:26281 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]69a2a5be2012-11-14 06:51:44282 scaledTargetOffset.Scale(1 / pageScale);
283 m_pageScaleAnimation->zoomTo(scaledTargetOffset, pageScale, duration.InSecondsF());
[email protected]f6250742012-11-09 04:46:56284 }
[email protected]94f206c12012-08-25 00:09:14285
[email protected]0ede3bb2012-12-09 09:14:39286 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:14287 m_client->setNeedsRedrawOnImplThread();
288 m_client->setNeedsCommitOnImplThread();
289}
290
[email protected]96baf3e2012-10-22 23:09:55291void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14292{
293 m_client->setNeedsRedrawOnImplThread();
294}
295
[email protected]2f1acc262012-11-16 21:42:22296bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint)
297{
[email protected]df8f44f2013-01-08 08:00:31298 if (!ensureRenderSurfaceLayerList())
299 return false;
[email protected]2f1acc262012-11-16 21:42:22300
301 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
302
303 // First find out which layer was hit from the saved list of visible layers
304 // in the most recent frame.
[email protected]76ffd9e2012-12-20 19:12:47305 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, activeTree()->RenderSurfaceLayerList());
[email protected]2f1acc262012-11-16 21:42:22306
[email protected]35d2edd22012-12-13 02:19:05307 // Walk up the hierarchy and look for a layer with a touch event handler region that the given point hits.
308 for (; layerImpl; layerImpl = layerImpl->parent()) {
309 if (LayerTreeHostCommon::layerHasTouchEventHandlersAt(deviceViewportPoint,layerImpl))
310 return true;
311 }
[email protected]2f1acc262012-11-16 21:42:22312
313 return false;
314}
315
[email protected]96baf3e2012-10-22 23:09:55316void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14317{
318 // For now, we use damage tracking to compute a global scissor. To do this, we must
319 // compute all damage tracking before drawing anything, so that we know the root
320 // damage rect. The root damage rect is then used to scissor each surface.
321
322 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55323 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
324 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04325 DCHECK(renderSurface);
[email protected]1940c4e2012-12-04 05:08:15326 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:14327 }
328}
329
[email protected]0ede3bb2012-12-09 09:14:39330void LayerTreeHostImpl::updateDrawProperties()
331{
332 if (!needsUpdateDrawProperties())
333 return;
334
[email protected]76ffd9e2012-12-20 19:12:47335 if (!m_renderer) { // For maxTextureSize.
336 // This will get set if renderer gets initialized.
337 m_needsUpdateDrawProperties = false;
[email protected]2d692992012-12-19 01:19:32338 return;
[email protected]94f206c12012-08-25 00:09:14339 }
[email protected]2e7ca422012-12-20 02:57:27340
[email protected]76ffd9e2012-12-20 19:12:47341 activeTree()->UpdateDrawProperties();
342 if (pendingTree())
343 pendingTree()->UpdateDrawProperties();
344
345 m_needsUpdateDrawProperties = false;
[email protected]94f206c12012-08-25 00:09:14346}
347
[email protected]96baf3e2012-10-22 23:09:55348void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16349{
[email protected]20062042012-12-21 22:16:36350 renderPassesById[renderPass->id] = renderPass.get();
[email protected]ead39c52013-01-09 07:22:45351 renderPasses.push_back(renderPass.Pass());
[email protected]f57bbc02012-11-21 07:02:15352}
353
354static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
355{
356 bool forSurface = false;
357 QuadCuller quadCuller(targetRenderPass->quad_list,
358 targetRenderPass->shared_quad_state_list,
359 layer,
360 occlusionTracker,
361 layer->showDebugBorders(),
362 forSurface);
363 layer->appendQuads(quadCuller, appendQuadsData);
364}
365
366static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, LayerImpl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
367{
368 bool forSurface = true;
369 QuadCuller quadCuller(targetRenderPass->quad_list,
370 targetRenderPass->shared_quad_state_list,
371 layer,
372 occlusionTracker,
373 layer->showDebugBorders(),
374 forSurface);
375
376 bool isReplica = false;
377 layer->renderSurface()->appendQuads(quadCuller,
378 appendQuadsData,
379 isReplica,
380 contributingRenderPass->id);
381
382 // Add replica after the surface so that it appears below the surface.
383 if (layer->hasReplica()) {
384 isReplica = true;
385 layer->renderSurface()->appendQuads(quadCuller,
386 appendQuadsData,
387 isReplica,
388 contributingRenderPass->id);
389 }
390}
391
392static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* rootLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTracker)
393{
394 if (!rootLayer || !SkColorGetA(screenBackgroundColor))
395 return;
396
397 Region fillRegion = occlusionTracker.computeVisibleRegionInScreen();
398 if (fillRegion.IsEmpty())
399 return;
400
401 bool forSurface = false;
402 QuadCuller quadCuller(targetRenderPass->quad_list,
403 targetRenderPass->shared_quad_state_list,
404 rootLayer,
405 occlusionTracker,
406 rootLayer->showDebugBorders(),
407 forSurface);
408
409 // Manually create the quad state for the gutter quads, as the root layer
410 // doesn't have any bounds and so can't generate this itself.
411 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
412
[email protected]f57bbc02012-11-21 07:02:15413 gfx::Rect rootTargetRect = rootLayer->renderSurface()->contentRect();
414 float opacity = 1;
415 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadState::Create());
416 sharedQuadState->SetAll(rootLayer->drawTransform(),
417 rootTargetRect,
418 rootTargetRect,
[email protected]dc462d782012-11-21 21:43:01419 rootTargetRect,
420 false,
[email protected]f57bbc02012-11-21 07:02:15421 opacity);
422
423 AppendQuadsData appendQuadsData;
[email protected]bda41962013-01-07 18:46:17424
425 gfx::Transform transformToLayerSpace(gfx::Transform::kSkipInitialization);
426 bool didInvert = rootLayer->screenSpaceTransform().GetInverse(&transformToLayerSpace);
427 DCHECK(didInvert);
[email protected]f57bbc02012-11-21 07:02:15428 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects.next()) {
429 // The root layer transform is composed of translations and scales only,
[email protected]bda41962013-01-07 18:46:17430 // no perspective, so mapping is sufficient (as opposed to projecting).
[email protected]f57bbc02012-11-21 07:02:15431 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fillRects.rect());
432 // Skip the quad culler and just append the quads directly to avoid
433 // occlusion checks.
434 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
435 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor);
436 quadCuller.append(quad.PassAs<DrawQuad>(), appendQuadsData);
437 }
[email protected]467b3612012-08-28 07:41:16438}
439
[email protected]96baf3e2012-10-22 23:09:55440bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14441{
[email protected]ead39c52013-01-09 07:22:45442 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14443
[email protected]2e7ca422012-12-20 02:57:27444 if (!canDraw() || !rootLayer())
[email protected]2d692992012-12-19 01:19:32445 return false;
446
[email protected]0ede3bb2012-12-09 09:14:39447 trackDamageForAllSurfaces(rootLayer(), *frame.renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14448
[email protected]96baf3e2012-10-22 23:09:55449 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14450
451 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14452 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55453 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16454 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14455 }
456
[email protected]9bdcfd642012-11-14 21:24:26457 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
[email protected]3b31c6ac2012-12-06 21:27:29458 OcclusionTrackerImpl occlusionTracker(rootLayer()->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14459 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
460
[email protected]f511afb2012-11-30 01:55:20461 if (m_debugState.showOccludingRects)
[email protected]94f206c12012-08-25 00:09:14462 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
[email protected]f511afb2012-11-30 01:55:20463 if (m_debugState.showNonOccludingRects)
[email protected]4d8804e2012-11-15 01:51:10464 occlusionTracker.setNonOccludingScreenSpaceRectsContainer(&frame.nonOccludingScreenSpaceRects);
[email protected]94f206c12012-08-25 00:09:14465
466 // 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:55467 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14468
469 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
470 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
471 // in the future.
472 bool drawFrame = true;
473
[email protected]96baf3e2012-10-22 23:09:55474 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
475 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
476 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
[email protected]20062042012-12-21 22:16:36477 RenderPass* targetRenderPass = frame.renderPassesById[targetRenderPassId];
[email protected]94f206c12012-08-25 00:09:14478
479 occlusionTracker.enterLayer(it);
480
[email protected]f57bbc02012-11-21 07:02:15481 AppendQuadsData appendQuadsData(targetRenderPass->id);
[email protected]89228202012-08-29 03:20:30482
[email protected]94f206c12012-08-25 00:09:14483 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55484 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
[email protected]20062042012-12-21 22:16:36485 RenderPass* contributingRenderPass = frame.renderPassesById[contributingRenderPassId];
[email protected]f57bbc02012-11-21 07:02:15486 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributingRenderPass, occlusionTracker, appendQuadsData);
[email protected]aad0a0072012-11-01 18:15:58487 } else if (it.representsItself() && !it->visibleContentRect().IsEmpty()) {
[email protected]94f206c12012-08-25 00:09:14488 bool hasOcclusionFromOutsideTargetSurface;
[email protected]710ffc02012-10-30 21:42:02489 bool implDrawTransformIsUnknown = false;
490 if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
[email protected]89228202012-08-29 03:20:30491 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
492 else {
[email protected]2e7ca422012-12-20 02:57:27493 DCHECK_EQ(activeTree(), it->layerTreeImpl());
[email protected]94f206c12012-08-25 00:09:14494 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47495 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57496
497 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55498 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]20062042012-12-21 22:16:36499 while (frame.renderPassesById.find(contributingRenderPassId) != frame.renderPassesById.end()) {
500 RenderPass* renderPass = frame.renderPassesById[contributingRenderPassId];
[email protected]7d929c02012-09-20 17:26:57501
[email protected]f57bbc02012-11-21 07:02:15502 AppendQuadsData appendQuadsData(renderPass->id);
503 appendQuadsForLayer(renderPass, *it, occlusionTracker, appendQuadsData);
[email protected]7d929c02012-09-20 17:26:57504
505 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
506 }
507 }
508
[email protected]f57bbc02012-11-21 07:02:15509 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14510 }
[email protected]9c2be6a2012-11-27 19:16:10511
[email protected]b2136f12012-11-30 02:45:53512 ++m_cumulativeNumLayersDrawn;
[email protected]94f206c12012-08-25 00:09:14513 }
514
[email protected]89228202012-08-29 03:20:30515 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
[email protected]f57bbc02012-11-21 07:02:15516 targetRenderPass->has_occlusion_from_outside_target_surface = true;
[email protected]89228202012-08-29 03:20:30517
[email protected]f2bbb4e2012-12-07 21:40:49518 if (appendQuadsData.numMissingTiles) {
519 m_cumulativeNumMissingTiles += appendQuadsData.numMissingTiles;
[email protected]94f206c12012-08-25 00:09:14520 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]22619922012-11-14 17:58:10521 if (layerHasAnimatingTransform)
[email protected]94f206c12012-08-25 00:09:14522 drawFrame = false;
523 }
524
525 occlusionTracker.leaveLayer(it);
526 }
527
[email protected]1d993172012-10-18 18:15:04528#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14529 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]f57bbc02012-11-21 07:02:15530 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j)
531 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state);
[email protected]20062042012-12-21 22:16:36532 DCHECK(frame.renderPassesById.find(frame.renderPasses[i]->id)
533 != frame.renderPassesById.end());
[email protected]94f206c12012-08-25 00:09:14534 }
535#endif
536
[email protected]a30290142013-01-05 01:27:00537 if (!activeTree()->has_transparent_background()) {
[email protected]ead39c52013-01-09 07:22:45538 frame.renderPasses.back()->has_transparent_background = false;
539 appendQuadsToFillScreen(frame.renderPasses.back(), rootLayer(), activeTree()->background_color(), occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14540 }
541
542 if (drawFrame)
543 occlusionTracker.overdrawMetrics().recordMetrics(this);
544
545 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
546 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
547 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
548
549 return drawFrame;
550}
551
[email protected]96baf3e2012-10-22 23:09:55552void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14553{
554 // Lazily create the timeSource adapter so that we can vary the interval for testing.
555 if (!m_timeSourceClientAdapter)
[email protected]61de5812012-11-08 07:03:44556 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->currentThread()));
[email protected]94f206c12012-08-25 00:09:14557
558 m_timeSourceClientAdapter->setActive(enabled);
559}
560
[email protected]aad0a0072012-11-01 18:15:58561gfx::Size LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14562{
[email protected]caa567d2012-12-20 07:56:16563 return activeTree()->ContentSize();
[email protected]94f206c12012-08-25 00:09:14564}
565
[email protected]96baf3e2012-10-22 23:09:55566static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14567{
[email protected]96baf3e2012-10-22 23:09:55568 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]20062042012-12-21 22:16:36569 return it != frame.renderPassesById.end() ? it->second : NULL;
[email protected]94f206c12012-08-25 00:09:14570}
571
[email protected]96baf3e2012-10-22 23:09:55572static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14573{
[email protected]96baf3e2012-10-22 23:09:55574 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
[email protected]20062042012-12-21 22:16:36575 // The pass was already removed by another quad - probably the original, and we are the replica.
576 if (!removeRenderPass)
577 return;
[email protected]96baf3e2012-10-22 23:09:55578 RenderPassList& renderPasses = frame.renderPasses;
579 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14580
[email protected]20062042012-12-21 22:16:36581 DCHECK(toRemove != renderPasses.end());
[email protected]94f206c12012-08-25 00:09:14582
[email protected]ead39c52013-01-09 07:22:45583 scoped_ptr<RenderPass> removedPass = renderPasses.take(toRemove);
584 frame.renderPasses.erase(toRemove);
[email protected]20062042012-12-21 22:16:36585 frame.renderPassesById.erase(removeRenderPassId);
[email protected]94f206c12012-08-25 00:09:14586
587 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]f57bbc02012-11-21 07:02:15588 const QuadList& quadList = removedPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55589 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14590 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55591 DrawQuad* currentQuad = (*quadListIterator);
[email protected]1bc93f62012-11-17 19:29:50592 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14593 continue;
594
[email protected]c22418b2012-11-20 23:06:26595 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id;
[email protected]94f206c12012-08-25 00:09:14596 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
597 }
598}
599
[email protected]96baf3e2012-10-22 23:09:55600bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14601{
[email protected]ec2eb5f2012-12-16 04:42:27602 if (!quad.contents_changed_since_last_frame.IsEmpty()) {
603 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have damage");
604 return false;
605 } else if (!m_renderer.haveCachedResourcesForRenderPassId(quad.render_pass_id)) {
606 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures have no texture");
607 return false;
608 }
609 TRACE_EVENT0("cc", "CullRenderPassesWithCachedTextures dropped!");
610 return true;
[email protected]94f206c12012-08-25 00:09:14611}
612
[email protected]96baf3e2012-10-22 23:09:55613bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14614{
[email protected]c22418b2012-11-20 23:06:26615 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame);
[email protected]20062042012-12-21 22:16:36616 if (!renderPass)
[email protected]94f206c12012-08-25 00:09:14617 return false;
618
619 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]20062042012-12-21 22:16:36620 const QuadList& quadList = renderPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55621 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
622 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14623
[email protected]1bc93f62012-11-17 19:29:50624 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14625 return false;
626
[email protected]c22418b2012-11-20 23:06:26627 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id, frame);
[email protected]20062042012-12-21 22:16:36628 if (contributingPass)
[email protected]94f206c12012-08-25 00:09:14629 return false;
630 }
631 return true;
632}
633
634// Defined for linking tests.
[email protected]52347c842012-11-02 21:06:20635template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
636template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14637
638// static
639template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55640void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14641{
642 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55643 const RenderPass* currentPass = frame.renderPasses[it];
[email protected]f57bbc02012-11-21 07:02:15644 const QuadList& quadList = currentPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55645 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14646
647 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55648 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14649
[email protected]1bc93f62012-11-17 19:29:50650 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14651 continue;
652
[email protected]96baf3e2012-10-22 23:09:55653 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14654 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
655 continue;
656
657 // We are changing the vector in the middle of iteration. Because we
658 // delete render passes that draw into the current pass, we are
659 // guaranteed that any data from the iterator to the end will not
660 // change. So, capture the iterator position from the end of the
661 // list, and restore it after the change.
662 int positionFromEnd = frame.renderPasses.size() - it;
[email protected]c22418b2012-11-20 23:06:26663 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame);
[email protected]94f206c12012-08-25 00:09:14664 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04665 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14666 }
667 }
668}
669
[email protected]96baf3e2012-10-22 23:09:55670bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14671{
[email protected]96baf3e2012-10-22 23:09:55672 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]94f206c12012-08-25 00:09:14673
[email protected]d142a47d2012-12-07 08:18:37674 if (m_tileManager)
675 m_tileManager->CheckForCompletedSetPixels();
676
[email protected]2e7ca422012-12-20 02:57:27677 activatePendingTreeIfNeeded();
[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]d142a47d2012-12-07 08:18:37725void LayerTreeHostImpl::ScheduleCheckForCompletedSetPixels()
[email protected]6edd39e2012-11-28 06:49:18726{
[email protected]d142a47d2012-12-07 08:18:37727 // CheckForCompletedSetPixels() should be called before we draw and
728 // preferably only once per vsync interval. For now just make sure
729 // a redraw is scheduled and call CheckForCompletedSetPixels() in
730 // prepareToDraw().
[email protected]6edd39e2012-11-28 06:49:18731 if (m_client)
732 m_client->setNeedsRedrawOnImplThread();
733}
734
[email protected]f35e2322012-12-15 21:45:52735bool LayerTreeHostImpl::shouldClearRootRenderPass() const
736{
737 return m_settings.shouldClearRootRenderPass;
738}
739
[email protected]96baf3e2012-10-22 23:09:55740void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14741{
[email protected]a0a00842012-10-22 22:50:28742 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14743 return;
[email protected]61de5812012-11-08 07:03:44744
[email protected]a0a00842012-10-22 22:50:28745 m_managedMemoryPolicy = policy;
[email protected]61de5812012-11-08 07:03:44746 if (!m_proxy->hasImplThread()) {
747 // FIXME: In single-thread mode, this can be called on the main thread
748 // by GLRenderer::onMemoryAllocationChanged.
749 DebugScopedSetImplThread implThread(m_proxy);
750 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
751 } else {
752 DCHECK(m_proxy->isImplThread());
753 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
754 }
[email protected]a0a00842012-10-22 22:50:28755 // We always need to commit after changing the memory policy because the new
756 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14757 m_client->setNeedsCommitOnImplThread();
758}
759
[email protected]a46f32932012-12-07 21:43:16760void LayerTreeHostImpl::OnVSyncParametersChanged(base::TimeTicks timebase, base::TimeDelta interval)
[email protected]94f206c12012-08-25 00:09:14761{
[email protected]30faac92012-10-29 00:06:29762 m_client->onVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14763}
764
[email protected]b6f3d7e2012-12-08 00:11:21765void LayerTreeHostImpl::OnSendFrameToParentCompositorAck(const CompositorFrameAck& ack)
[email protected]a46f32932012-12-07 21:43:16766{
[email protected]b6f3d7e2012-12-08 00:11:21767 if (!m_renderer)
768 return;
769
770 // TODO(piman): We may need to do some validation on this ack before processing it.
771 m_renderer->receiveCompositorFrameAck(ack);
[email protected]a46f32932012-12-07 21:43:16772}
773
[email protected]3b31c6ac2012-12-06 21:27:29774void LayerTreeHostImpl::OnCanDrawStateChangedForTree(LayerTreeImpl*)
775{
[email protected]a46f32932012-12-07 21:43:16776 m_client->onCanDrawStateChanged(canDraw());
[email protected]3b31c6ac2012-12-06 21:27:29777}
778
[email protected]bf189f62012-12-18 03:42:11779CompositorFrameMetadata LayerTreeHostImpl::makeCompositorFrameMetadata() const
780{
[email protected]f85c4972013-01-09 03:38:54781 if (!rootScrollLayer())
782 return CompositorFrameMetadata();
783
[email protected]bf189f62012-12-18 03:42:11784 CompositorFrameMetadata metadata;
[email protected]f85c4972013-01-09 03:38:54785 metadata.root_scroll_offset = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
786 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]a823df82013-01-10 02:38:17787 metadata.root_scroll_offset.Scale(1 / m_pinchZoomViewport.page_scale_factor());
788 metadata.page_scale_factor = m_pinchZoomViewport.total_page_scale_factor();
789 metadata.viewport_size = m_pinchZoomViewport.Bounds().size();
[email protected]f2b5a5be2013-01-08 00:34:36790 metadata.root_layer_size = contentSize();
[email protected]a823df82013-01-10 02:38:17791 metadata.min_page_scale_factor = m_pinchZoomViewport.min_page_scale_factor();
792 metadata.max_page_scale_factor = m_pinchZoomViewport.max_page_scale_factor();
[email protected]bf189f62012-12-18 03:42:11793
794 return metadata;
795}
796
[email protected]85167c72012-12-04 03:56:07797void LayerTreeHostImpl::drawLayers(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14798{
[email protected]96baf3e2012-10-22 23:09:55799 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04800 DCHECK(canDraw());
[email protected]ead39c52013-01-09 07:22:45801 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14802
803 // FIXME: use the frame begin time from the overall compositor scheduler.
804 // This value is currently inaccessible because it is up in Chromium's
805 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21806 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14807
[email protected]f511afb2012-11-30 01:55:20808 if (m_debugState.showHudRects())
[email protected]3b31c6ac2012-12-06 21:27:29809 m_debugRectHistory->saveDebugRectsForCurrentFrame(rootLayer(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenSpaceRects, m_debugState);
[email protected]94f206c12012-08-25 00:09:14810
811 // Because the contents of the HUD depend on everything else in the frame, the contents
812 // of its texture are updated as the last thing before the frame is drawn.
[email protected]3b31c6ac2012-12-06 21:27:29813 if (m_activeTree->hud_layer())
814 m_activeTree->hud_layer()->updateHudTexture(m_resourceProvider.get());
[email protected]94f206c12012-08-25 00:09:14815
[email protected]20062042012-12-21 22:16:36816 m_renderer->drawFrame(frame.renderPasses);
[email protected]85167c72012-12-04 03:56:07817 // The render passes should be consumed by the renderer.
[email protected]ead39c52013-01-09 07:22:45818 DCHECK(frame.renderPasses.empty());
[email protected]20062042012-12-21 22:16:36819 frame.renderPassesById.clear();
[email protected]94f206c12012-08-25 00:09:14820
821 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
822 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
823 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
[email protected]3b31c6ac2012-12-06 21:27:29824 rootLayer()->resetAllChangeTrackingForSubtree();
[email protected]94f206c12012-08-25 00:09:14825}
826
[email protected]96baf3e2012-10-22 23:09:55827void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14828{
829 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
830 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52831
832 // Once all layers have been drawn, pending texture uploads should no
833 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09834 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14835}
836
[email protected]96baf3e2012-10-22 23:09:55837void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14838{
839 if (m_renderer)
840 m_renderer->finish();
841}
842
[email protected]96baf3e2012-10-22 23:09:55843bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14844{
845 return m_renderer && m_renderer->isContextLost();
846}
847
[email protected]96baf3e2012-10-22 23:09:55848const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14849{
850 return m_renderer->capabilities();
851}
852
[email protected]96baf3e2012-10-22 23:09:55853bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14854{
[email protected]1d993172012-10-18 18:15:04855 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14856
857 m_fpsCounter->markEndOfFrame();
858 return m_renderer->swapBuffers();
859}
860
[email protected]aad0a0072012-11-01 18:15:58861const gfx::Size& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10862{
863 return m_deviceViewportSize;
864}
865
[email protected]96baf3e2012-10-22 23:09:55866const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10867{
868 return m_settings;
869}
870
[email protected]3be2171d2012-12-06 06:13:20871void LayerTreeHostImpl::didLoseOutputSurface()
[email protected]94f206c12012-08-25 00:09:14872{
[email protected]3be2171d2012-12-06 06:13:20873 m_client->didLoseOutputSurfaceOnImplThread();
[email protected]94f206c12012-08-25 00:09:14874}
875
[email protected]96baf3e2012-10-22 23:09:55876void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14877{
878 m_client->onSwapBuffersCompleteOnImplThread();
879}
880
[email protected]aad0a0072012-11-01 18:15:58881void LayerTreeHostImpl::readback(void* pixels, const gfx::Rect& rect)
[email protected]94f206c12012-08-25 00:09:14882{
[email protected]1d993172012-10-18 18:15:04883 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14884 m_renderer->getFramebufferPixels(pixels, rect);
885}
886
[email protected]8bef40572012-12-11 21:38:08887LayerImpl* LayerTreeHostImpl::rootLayer() const
888{
889 return m_activeTree->RootLayer();
890}
891
892LayerImpl* LayerTreeHostImpl::rootScrollLayer() const
893{
894 return m_activeTree->root_scroll_layer();
895}
896
897LayerImpl* LayerTreeHostImpl::currentlyScrollingLayer() const
898{
899 return m_activeTree->currently_scrolling_layer();
900}
901
[email protected]94f206c12012-08-25 00:09:14902// Content layers can be either directly scrollable or contained in an outer
903// scrolling layer which applies the scroll transform. Given a content layer,
904// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55905static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14906{
907 if (!layerImpl)
908 return 0;
909
910 if (layerImpl->scrollable())
911 return layerImpl;
912
913 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
914 return layerImpl->parent();
915
916 return 0;
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
927void LayerTreeHostImpl::activatePendingTreeIfNeeded()
928{
929 if (!pendingTree())
930 return;
931
932 int total_pending = m_tileManager->GetTilesInBinCount(NOW_BIN, PENDING_TREE);
[email protected]2e7ca422012-12-20 02:57:27933 int drawable_pending = m_tileManager->GetDrawableTilesInBinCount(NOW_BIN, PENDING_TREE);
[email protected]235c7b42013-01-06 05:08:17934 int total_active = m_tileManager->GetTilesInBinCount(NOW_BIN, ACTIVE_TREE);
[email protected]2e7ca422012-12-20 02:57:27935
[email protected]235c7b42013-01-06 05:08:17936 // It's always fine to activate to or from an empty tree. Otherwise, only
937 // activate once all high res visible tiles are ready on the pending tree.
938 if (total_pending && total_active && total_pending != drawable_pending)
939 return;
[email protected]2e7ca422012-12-20 02:57:27940
[email protected]2e7ca422012-12-20 02:57:27941 activatePendingTree();
942}
943
944void LayerTreeHostImpl::activatePendingTree()
945{
946 CHECK(m_pendingTree);
[email protected]1e0f8d62013-01-09 07:41:35947
948 m_activeTree->PushPersistedState(m_pendingTree.get());
[email protected]2e7ca422012-12-20 02:57:27949 m_activeTree.swap(m_pendingTree);
950 // TODO(enne): consider recycling this tree to prevent layer churn
951 m_pendingTree.reset();
952 m_client->onCanDrawStateChanged(canDraw());
953 m_client->onHasPendingTreeStateChanged(pendingTree());
[email protected]2e7ca422012-12-20 02:57:27954}
955
[email protected]96baf3e2012-10-22 23:09:55956void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14957{
[email protected]61de5812012-11-08 07:03:44958 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14959
960 if (m_visible == visible)
961 return;
962 m_visible = visible;
963 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:28964 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:14965
966 if (!m_renderer)
967 return;
968
969 m_renderer->setVisible(visible);
970
[email protected]de4afb5e2012-12-20 00:11:34971 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_animation_controllers().empty());
[email protected]94f206c12012-08-25 00:09:14972}
973
[email protected]3be2171d2012-12-06 06:13:20974bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<OutputSurface> outputSurface)
[email protected]94f206c12012-08-25 00:09:14975{
[email protected]be3181652012-09-25 13:02:13976 // Since we will create a new resource provider, we cannot continue to use
977 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
978 // before we destroy the old resource provider.
[email protected]3b31c6ac2012-12-06 21:27:29979 if (rootLayer()) {
[email protected]94f206c12012-08-25 00:09:14980 clearRenderSurfaces();
[email protected]3b31c6ac2012-12-06 21:27:29981 sendDidLoseOutputSurfaceRecursive(rootLayer());
[email protected]94f206c12012-08-25 00:09:14982 }
[email protected]be3181652012-09-25 13:02:13983 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47984 m_renderer.reset();
[email protected]8947cbe2012-11-28 05:27:43985 m_tileManager.reset();
[email protected]a7aa5562012-10-17 14:12:44986 m_resourceProvider.reset();
[email protected]3be2171d2012-12-06 06:13:20987 m_outputSurface.reset();
[email protected]94f206c12012-08-25 00:09:14988
[email protected]a46f32932012-12-07 21:43:16989 if (!outputSurface->BindToClient(this))
[email protected]be3181652012-09-25 13:02:13990 return false;
991
[email protected]3be2171d2012-12-06 06:13:20992 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(outputSurface.get());
[email protected]be3181652012-09-25 13:02:13993 if (!resourceProvider)
994 return false;
995
[email protected]8947cbe2012-11-28 05:27:43996 if (m_settings.implSidePainting)
[email protected]876e9e82012-12-04 20:12:14997 m_tileManager.reset(new TileManager(this, resourceProvider.get(), m_settings.numRasterThreads));
[email protected]8947cbe2012-11-28 05:27:43998
[email protected]ea9d8f22012-12-08 03:39:29999 if (outputSurface->Capabilities().has_parent_compositor)
[email protected]f85c4972013-01-09 03:38:541000 m_renderer = DelegatingRenderer::Create(this, resourceProvider.get());
[email protected]ea9d8f22012-12-08 03:39:291001 else if (outputSurface->Context3D())
[email protected]bf189f62012-12-18 03:42:111002 m_renderer = GLRenderer::create(this, outputSurface.get(), resourceProvider.get());
[email protected]a46f32932012-12-07 21:43:161003 else if (outputSurface->SoftwareDevice())
1004 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), outputSurface->SoftwareDevice());
[email protected]be3181652012-09-25 13:02:131005 if (!m_renderer)
1006 return false;
1007
[email protected]76ffd9e2012-12-20 19:12:471008 setNeedsUpdateDrawProperties();
[email protected]a7aa5562012-10-17 14:12:441009 m_resourceProvider = resourceProvider.Pass();
[email protected]3be2171d2012-12-06 06:13:201010 m_outputSurface = outputSurface.Pass();
[email protected]94f206c12012-08-25 00:09:141011
[email protected]be3181652012-09-25 13:02:131012 if (!m_visible)
1013 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:141014
[email protected]8db2213c2012-09-05 22:08:211015 m_client->onCanDrawStateChanged(canDraw());
1016
[email protected]be3181652012-09-25 13:02:131017 return true;
[email protected]94f206c12012-08-25 00:09:141018}
1019
[email protected]96baf3e2012-10-22 23:09:551020void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:091021{
1022 m_contentsTexturesPurged = true;
1023 m_client->onCanDrawStateChanged(canDraw());
1024}
1025
[email protected]96baf3e2012-10-22 23:09:551026void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:211027{
1028 m_contentsTexturesPurged = false;
1029 m_client->onCanDrawStateChanged(canDraw());
1030}
1031
[email protected]aad0a0072012-11-01 18:15:581032void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:141033{
1034 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
1035 return;
1036
1037 m_layoutViewportSize = layoutViewportSize;
1038 m_deviceViewportSize = deviceViewportSize;
1039
[email protected]a823df82013-01-10 02:38:171040 m_pinchZoomViewport.set_layout_viewport_size(layoutViewportSize);
[email protected]1c0c9bc2012-10-08 22:41:481041
[email protected]c9c1ebe2012-11-05 20:46:131042 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141043
1044 if (m_renderer)
1045 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:211046
1047 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:141048}
1049
[email protected]96baf3e2012-10-22 23:09:551050static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:141051{
1052 if (!layerImpl)
1053 return;
1054
1055 if (layerImpl->scrollable()) {
1056 // We need to convert impl-side scroll deltas to pageScale space.
[email protected]c9c1ebe2012-11-05 20:46:131057 gfx::Vector2dF scrollDelta = layerImpl->scrollDelta();
1058 scrollDelta.Scale(pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141059 layerImpl->setScrollDelta(scrollDelta);
1060 }
1061
1062 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031063 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141064}
1065
[email protected]96baf3e2012-10-22 23:09:551066void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:141067{
1068 if (deviceScaleFactor == m_deviceScaleFactor)
1069 return;
1070 m_deviceScaleFactor = deviceScaleFactor;
[email protected]a823df82013-01-10 02:38:171071 m_pinchZoomViewport.set_device_scale_factor(m_deviceScaleFactor);
[email protected]c0dd24c2012-08-30 23:25:271072
[email protected]c9c1ebe2012-11-05 20:46:131073 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141074}
1075
[email protected]96baf3e2012-10-22 23:09:551076float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:141077{
[email protected]a823df82013-01-10 02:38:171078 return m_pinchZoomViewport.page_scale_factor();
[email protected]1c0c9bc2012-10-08 22:41:481079}
[email protected]94f206c12012-08-25 00:09:141080
[email protected]96baf3e2012-10-22 23:09:551081void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:481082{
1083 if (!pageScaleFactor)
1084 return;
[email protected]94f206c12012-08-25 00:09:141085
[email protected]a823df82013-01-10 02:38:171086 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.page_scale_factor();
1087 m_pinchZoomViewport.SetPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:141088
[email protected]0ede3bb2012-12-09 09:14:391089 if (!m_settings.pageScalePinchZoomEnabled && pageScaleChange != 1)
1090 adjustScrollsForPageScaleChange(rootScrollLayer(), pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141091
1092 // Clamp delta to limits and refresh display matrix.
[email protected]a823df82013-01-10 02:38:171093 setPageScaleDelta(m_pinchZoomViewport.page_scale_delta() / m_pinchZoomViewport.sent_page_scale_delta());
1094 m_pinchZoomViewport.set_sent_page_scale_delta(1);
[email protected]94f206c12012-08-25 00:09:141095}
1096
[email protected]96baf3e2012-10-22 23:09:551097void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:141098{
[email protected]a823df82013-01-10 02:38:171099 m_pinchZoomViewport.set_page_scale_delta(delta);
[email protected]94f206c12012-08-25 00:09:141100
[email protected]c9c1ebe2012-11-05 20:46:131101 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141102}
1103
[email protected]c9c1ebe2012-11-05 20:46:131104void LayerTreeHostImpl::updateMaxScrollOffset()
[email protected]94f206c12012-08-25 00:09:141105{
[email protected]caa567d2012-12-20 07:56:161106 activeTree()->UpdateMaxScrollOffset();
1107 if (pendingTree())
1108 pendingTree()->UpdateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141109}
1110
[email protected]96baf3e2012-10-22 23:09:551111void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141112{
1113 m_client->setNeedsRedrawOnImplThread();
1114}
1115
[email protected]96baf3e2012-10-22 23:09:551116bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141117{
[email protected]0ede3bb2012-12-09 09:14:391118 updateDrawProperties();
[email protected]76ffd9e2012-12-20 19:12:471119 return activeTree()->RenderSurfaceLayerList().size();
[email protected]94f206c12012-08-25 00:09:141120}
1121
[email protected]c9c1ebe2012-11-05 20:46:131122InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141123{
[email protected]96baf3e2012-10-22 23:09:551124 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141125
[email protected]3b31c6ac2012-12-06 21:27:291126 DCHECK(!currentlyScrollingLayer());
[email protected]94f206c12012-08-25 00:09:141127 clearCurrentlyScrollingLayer();
1128
1129 if (!ensureRenderSurfaceLayerList())
1130 return ScrollIgnored;
1131
[email protected]faf56352012-11-09 21:44:131132 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141133
1134 // First find out which layer was hit from the saved list of visible layers
1135 // in the most recent frame.
[email protected]76ffd9e2012-12-20 19:12:471136 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, activeTree()->RenderSurfaceLayerList());
[email protected]94f206c12012-08-25 00:09:141137
1138 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551139 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141140 for (; layerImpl; layerImpl = layerImpl->parent()) {
1141 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271142 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1143 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141144 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271145 }
[email protected]94f206c12012-08-25 00:09:141146
[email protected]96baf3e2012-10-22 23:09:551147 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141148 if (!scrollLayerImpl)
1149 continue;
1150
[email protected]31bfe272012-10-19 18:49:521151 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141152
1153 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271154 if (status == ScrollOnMainThread) {
1155 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141156 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271157 }
[email protected]94f206c12012-08-25 00:09:141158
1159 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1160 potentiallyScrollingLayerImpl = scrollLayerImpl;
1161 }
1162
1163 if (potentiallyScrollingLayerImpl) {
[email protected]3b31c6ac2012-12-06 21:27:291164 m_activeTree->set_currently_scrolling_layer(potentiallyScrollingLayerImpl);
[email protected]31bfe272012-10-19 18:49:521165 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141166 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1167 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521168 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271169 m_numImplThreadScrolls++;
[email protected]0ede3bb2012-12-09 09:14:391170 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141171 return ScrollStarted;
1172 }
1173 return ScrollIgnored;
1174}
1175
[email protected]c9c1ebe2012-11-05 20:46:131176static gfx::Vector2dF scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::Vector2dF viewportDelta)
[email protected]94f206c12012-08-25 00:09:141177{
1178 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1179 // test in the first place.
[email protected]c8686a02012-11-27 08:29:001180 DCHECK(layerImpl.screenSpaceTransform().IsInvertible());
[email protected]bda41962013-01-07 18:46:171181 gfx::Transform inverseScreenSpaceTransform(gfx::Transform::kSkipInitialization);
1182 bool didInvert = layerImpl.screenSpaceTransform().GetInverse(&inverseScreenSpaceTransform);
1183 // TODO: With the advent of impl-side crolling for non-root layers, we may
1184 // need to explicitly handle uninvertible transforms here.
1185 DCHECK(didInvert);
[email protected]94f206c12012-08-25 00:09:141186
[email protected]faf56352012-11-09 21:44:131187 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521188
[email protected]c9c1ebe2012-11-05 20:46:131189 gfx::Vector2dF screenSpaceDelta = viewportDelta;
1190 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521191
[email protected]94f206c12012-08-25 00:09:141192 // First project the scroll start and end points to local layer space to find the scroll delta
1193 // in layer coordinates.
1194 bool startClipped, endClipped;
[email protected]d455d552012-11-02 00:19:061195 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1196 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1197 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141198
1199 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041200 DCHECK(!startClipped);
1201 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141202 if (startClipped || endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131203 return gfx::Vector2dF();
[email protected]94f206c12012-08-25 00:09:141204
[email protected]31bfe272012-10-19 18:49:521205 // 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:581206 float widthScale = 1 / layerImpl.contentsScaleX();
1207 float heightScale = 1 / layerImpl.contentsScaleY();
[email protected]faf56352012-11-09 21:44:131208 localStartPoint.Scale(widthScale, heightScale);
1209 localEndPoint.Scale(widthScale, heightScale);
[email protected]31bfe272012-10-19 18:49:521210
[email protected]94f206c12012-08-25 00:09:141211 // Apply the scroll delta.
[email protected]c9c1ebe2012-11-05 20:46:131212 gfx::Vector2dF previousDelta = layerImpl.scrollDelta();
1213 gfx::Vector2dF unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
[email protected]caa567d2012-12-20 07:56:161214 gfx::Vector2dF scrollAmount = localEndPoint - localStartPoint;
[email protected]1c0c9bc2012-10-08 22:41:481215
[email protected]aeaa50a2012-11-21 20:12:371216 gfx::Vector2dF viewportAppliedPan;
[email protected]1c0c9bc2012-10-08 22:41:481217 if (viewport)
[email protected]a823df82013-01-10 02:38:171218 viewportAppliedPan = unscrolled - viewport->ApplyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141219
[email protected]31bfe272012-10-19 18:49:521220 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]aeaa50a2012-11-21 20:12:371221 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() + viewportAppliedPan - previousDelta;
[email protected]faf56352012-11-09 21:44:131222 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint, 1 / widthScale, 1 / heightScale);
[email protected]31bfe272012-10-19 18:49:521223
1224 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]d455d552012-11-02 00:19:061225 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041226 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141227 if (endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131228 return gfx::Vector2dF();
[email protected]faf56352012-11-09 21:44:131229 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoint, 1 / scaleFromViewportToScreenSpace);
[email protected]c9c1ebe2012-11-05 20:46:131230 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141231}
1232
[email protected]c9c1ebe2012-11-05 20:46:131233static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vector2dF localDelta)
[email protected]94f206c12012-08-25 00:09:141234{
[email protected]c9c1ebe2012-11-05 20:46:131235 gfx::Vector2dF previousDelta(layerImpl.scrollDelta());
[email protected]94f206c12012-08-25 00:09:141236 layerImpl.scrollBy(localDelta);
1237 return layerImpl.scrollDelta() - previousDelta;
1238}
1239
[email protected]a9710962012-11-14 20:11:021240bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint,
1241 const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141242{
[email protected]96baf3e2012-10-22 23:09:551243 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]3b31c6ac2012-12-06 21:27:291244 if (!currentlyScrollingLayer())
[email protected]a9710962012-11-14 20:11:021245 return false;
[email protected]94f206c12012-08-25 00:09:141246
[email protected]c9c1ebe2012-11-05 20:46:131247 gfx::Vector2dF pendingDelta = scrollDelta;
[email protected]1ca52a3a2012-12-04 22:47:101248 bool didScroll = false;
[email protected]94f206c12012-08-25 00:09:141249
[email protected]3b31c6ac2012-12-06 21:27:291250 for (LayerImpl* layerImpl = currentlyScrollingLayer(); layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141251 if (!layerImpl->scrollable())
1252 continue;
1253
[email protected]dbed4272012-12-06 08:50:481254 PinchZoomViewport* viewport = NULL;
[email protected]3b31c6ac2012-12-06 21:27:291255 if (m_settings.pageScalePinchZoomEnabled && layerImpl == rootScrollLayer())
[email protected]dbed4272012-12-06 08:50:481256 viewport = &m_pinchZoomViewport;
[email protected]c9c1ebe2012-11-05 20:46:131257 gfx::Vector2dF appliedDelta;
[email protected]31bfe272012-10-19 18:49:521258 if (m_scrollDeltaIsInViewportSpace) {
1259 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1260 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1261 } else
[email protected]94f206c12012-08-25 00:09:141262 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1263
1264 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381265 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]c9c1ebe2012-11-05 20:46:131266 if (appliedDelta.LengthSquared() < moveThresholdSquared)
[email protected]94f206c12012-08-25 00:09:141267 continue;
[email protected]1ca52a3a2012-12-04 22:47:101268 didScroll = true;
[email protected]94f206c12012-08-25 00:09:141269
1270 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1271 // to scroll just one layer in one direction without affecting any of its parents.
1272 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551273 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]c9c1ebe2012-11-05 20:46:131274 pendingDelta = gfx::Vector2d();
[email protected]94f206c12012-08-25 00:09:141275 break;
1276 }
1277
1278 // Allow further movement only on an axis perpendicular to the direction in which the layer
1279 // moved.
[email protected]c9c1ebe2012-11-05 20:46:131280 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x());
[email protected]96baf3e2012-10-22 23:09:551281 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141282
[email protected]c9c1ebe2012-11-05 20:46:131283 if (gfx::ToFlooredVector2d(pendingDelta).IsZero())
[email protected]94f206c12012-08-25 00:09:141284 break;
1285 }
1286
[email protected]1ca52a3a2012-12-04 22:47:101287 if (didScroll) {
[email protected]94f206c12012-08-25 00:09:141288 m_client->setNeedsCommitOnImplThread();
1289 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391290 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141291 }
[email protected]1ca52a3a2012-12-04 22:47:101292 return didScroll;
[email protected]94f206c12012-08-25 00:09:141293}
1294
[email protected]96baf3e2012-10-22 23:09:551295void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141296{
[email protected]3b31c6ac2012-12-06 21:27:291297 m_activeTree->ClearCurrentlyScrollingLayer();
[email protected]94f206c12012-08-25 00:09:141298}
1299
[email protected]96baf3e2012-10-22 23:09:551300void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141301{
1302 clearCurrentlyScrollingLayer();
1303}
1304
[email protected]96baf3e2012-10-22 23:09:551305void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141306{
1307 m_pinchGestureActive = true;
[email protected]c9c1ebe2012-11-05 20:46:131308 m_previousPinchAnchor = gfx::Point();
[email protected]94f206c12012-08-25 00:09:141309
[email protected]3b31c6ac2012-12-06 21:27:291310 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1311 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureBegin();
[email protected]94f206c12012-08-25 00:09:141312}
1313
[email protected]c9c1ebe2012-11-05 20:46:131314void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor)
[email protected]94f206c12012-08-25 00:09:141315{
[email protected]96baf3e2012-10-22 23:09:551316 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141317
[email protected]3b31c6ac2012-12-06 21:27:291318 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141319 return;
1320
[email protected]94f206c12012-08-25 00:09:141321 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1322 // position over the course of the magnify.
[email protected]a823df82013-01-10 02:38:171323 float pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
[email protected]c77745d2012-11-20 04:11:571324 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:481325 setPageScaleDelta(pageScaleDelta * magnifyDelta);
[email protected]a823df82013-01-10 02:38:171326 pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
[email protected]faf56352012-11-09 21:44:131327 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:131328 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor;
[email protected]94f206c12012-08-25 00:09:141329
1330 m_previousPinchAnchor = anchor;
1331
[email protected]9bdcfd642012-11-14 21:24:261332 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481333 // Compute the application of the delta with respect to the current page zoom of the page.
[email protected]a823df82013-01-10 02:38:171334 move.Scale(1 / m_pinchZoomViewport.page_scale_factor());
[email protected]1c0c9bc2012-10-08 22:41:481335 }
1336
[email protected]a823df82013-01-10 02:38:171337 gfx::Vector2dF scrollOverflow = m_settings.pageScalePinchZoomEnabled ? m_pinchZoomViewport.ApplyScroll(move) : move;
[email protected]3b31c6ac2012-12-06 21:27:291338 rootScrollLayer()->scrollBy(scrollOverflow);
[email protected]94f206c12012-08-25 00:09:141339
[email protected]3b31c6ac2012-12-06 21:27:291340 if (rootScrollLayer()->scrollbarAnimationController())
1341 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureUpdate();
[email protected]94f206c12012-08-25 00:09:141342
1343 m_client->setNeedsCommitOnImplThread();
1344 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391345 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141346}
1347
[email protected]96baf3e2012-10-22 23:09:551348void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141349{
1350 m_pinchGestureActive = false;
1351
[email protected]3b31c6ac2012-12-06 21:27:291352 if (rootScrollLayer() && rootScrollLayer()->scrollbarAnimationController())
1353 rootScrollLayer()->scrollbarAnimationController()->didPinchGestureEnd();
[email protected]94f206c12012-08-25 00:09:141354
1355 m_client->setNeedsCommitOnImplThread();
1356}
1357
[email protected]96baf3e2012-10-22 23:09:551358void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141359{
[email protected]f6250742012-11-09 04:46:561360 gfx::Vector2dF scaledScrollOffset = m_pageScaleAnimation->targetScrollOffset();
[email protected]9bdcfd642012-11-14 21:24:261361 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]a823df82013-01-10 02:38:171362 scaledScrollOffset.Scale(m_pinchZoomViewport.page_scale_factor());
[email protected]f6250742012-11-09 04:46:561363 makeScrollAndScaleSet(scrollInfo, ToFlooredVector2d(scaledScrollOffset), m_pageScaleAnimation->targetPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141364}
1365
[email protected]96baf3e2012-10-22 23:09:551366void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141367{
[email protected]3b31c6ac2012-12-06 21:27:291368 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141369 return;
1370
1371 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1372 // significant amount. This also ensures only one fake delta set will be
1373 // sent.
[email protected]23bbb412012-08-30 20:03:381374 const float pinchZoomOutSensitivity = 0.95f;
[email protected]a823df82013-01-10 02:38:171375 if (m_pinchZoomViewport.page_scale_delta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141376 return;
1377
1378 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1379 // out from the anchor point.
[email protected]3b31c6ac2012-12-06 21:27:291380 gfx::Vector2dF scrollBegin = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]a823df82013-01-10 02:38:171381 scrollBegin.Scale(m_pinchZoomViewport.page_scale_delta());
1382 float scaleBegin = m_pinchZoomViewport.total_page_scale_factor();
1383 float pageScaleDeltaToSend = m_pinchZoomViewport.min_page_scale_factor() / m_pinchZoomViewport.page_scale_factor();
[email protected]01a15a72012-11-10 09:34:281384 gfx::SizeF scaledContentsSize = gfx::ScaleSize(contentSize(), pageScaleDeltaToSend);
[email protected]94f206c12012-08-25 00:09:141385
[email protected]c9c1ebe2012-11-05 20:46:131386 gfx::Vector2d anchorOffset = m_previousPinchAnchor.OffsetFromOrigin();
1387 gfx::Vector2dF scrollEnd = scrollBegin + anchorOffset;
[email protected]a823df82013-01-10 02:38:171388 scrollEnd.Scale(m_pinchZoomViewport.min_page_scale_factor() / scaleBegin);
[email protected]c9c1ebe2012-11-05 20:46:131389 scrollEnd -= anchorOffset;
[email protected]0eef4b882012-11-20 20:28:071390 scrollEnd.ClampToMax(gfx::RectF(scaledContentsSize).bottom_right() - gfx::Rect(m_deviceViewportSize).bottom_right());
[email protected]fe07b642012-11-10 00:07:591391 scrollEnd.ClampToMin(gfx::Vector2d());
[email protected]c9c1ebe2012-11-05 20:46:131392 scrollEnd.Scale(1 / pageScaleDeltaToSend);
1393 scrollEnd.Scale(m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141394
[email protected]a823df82013-01-10 02:38:171395 makeScrollAndScaleSet(scrollInfo, gfx::ToRoundedVector2d(scrollEnd), m_pinchZoomViewport.min_page_scale_factor());
[email protected]94f206c12012-08-25 00:09:141396}
1397
[email protected]c9c1ebe2012-11-05 20:46:131398void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141399{
[email protected]3b31c6ac2012-12-06 21:27:291400 if (!rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141401 return;
1402
[email protected]96baf3e2012-10-22 23:09:551403 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]3b31c6ac2012-12-06 21:27:291404 scroll.layerId = rootScrollLayer()->id();
1405 scroll.scrollDelta = scrollOffset - rootScrollLayer()->scrollOffset();
[email protected]787465c2012-10-29 01:12:271406 scrollInfo->scrolls.push_back(scroll);
[email protected]caa567d2012-12-20 07:56:161407 activeTree()->root_scroll_layer()->setSentScrollDelta(scroll.scrollDelta);
[email protected]a823df82013-01-10 02:38:171408 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.page_scale_factor();
1409 m_pinchZoomViewport.set_sent_page_scale_delta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141410}
1411
[email protected]96baf3e2012-10-22 23:09:551412static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141413{
1414 if (!layerImpl)
1415 return;
1416
[email protected]c9c1ebe2012-11-05 20:46:131417 if (!layerImpl->scrollDelta().IsZero()) {
1418 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551419 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141420 scroll.layerId = layerImpl->id();
1421 scroll.scrollDelta = scrollDelta;
[email protected]787465c2012-10-29 01:12:271422 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141423 layerImpl->setSentScrollDelta(scrollDelta);
1424 }
1425
1426 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031427 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141428}
1429
[email protected]96baf3e2012-10-22 23:09:551430scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141431{
[email protected]96baf3e2012-10-22 23:09:551432 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141433
1434 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481435 scrollInfo->pageScaleDelta = 1;
[email protected]a823df82013-01-10 02:38:171436 m_pinchZoomViewport.set_sent_page_scale_delta(1);
[email protected]f6250742012-11-09 04:46:561437 // FIXME(aelias): Make pinch-zoom painting optimization compatible with
[email protected]1c0c9bc2012-10-08 22:41:481438 // compositor-side scaling.
[email protected]9bdcfd642012-11-14 21:24:261439 if (!m_settings.pageScalePinchZoomEnabled && m_pinchGestureActive)
[email protected]f6250742012-11-09 04:46:561440 computePinchZoomDeltas(scrollInfo.get());
1441 else if (m_pageScaleAnimation.get())
1442 computeDoubleTapZoomDeltas(scrollInfo.get());
[email protected]a9f4bf22012-10-11 23:39:211443 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141444 }
1445
[email protected]3b31c6ac2012-12-06 21:27:291446 collectScrollDeltas(scrollInfo.get(), rootLayer());
[email protected]a823df82013-01-10 02:38:171447 scrollInfo->pageScaleDelta = m_pinchZoomViewport.page_scale_delta();
1448 m_pinchZoomViewport.set_sent_page_scale_delta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141449
[email protected]a9f4bf22012-10-11 23:39:211450 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141451}
1452
[email protected]c8686a02012-11-27 08:29:001453gfx::Transform LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481454{
[email protected]a823df82013-01-10 02:38:171455 return m_pinchZoomViewport.ImplTransform(m_settings.pageScalePinchZoomEnabled);
[email protected]1c0c9bc2012-10-08 22:41:481456}
1457
[email protected]96baf3e2012-10-22 23:09:551458void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141459{
[email protected]3b31c6ac2012-12-06 21:27:291460 if (rootLayer()) {
1461 RenderSurfaceImpl* renderSurface = rootLayer()->renderSurface();
[email protected]94f206c12012-08-25 00:09:141462 if (renderSurface)
1463 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1464 }
1465}
1466
[email protected]30faac92012-10-29 00:06:291467void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141468{
[email protected]3b31c6ac2012-12-06 21:27:291469 if (!m_pageScaleAnimation || !rootScrollLayer())
[email protected]94f206c12012-08-25 00:09:141470 return;
1471
[email protected]30faac92012-10-29 00:06:291472 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]3b31c6ac2012-12-06 21:27:291473 gfx::Vector2dF scrollTotal = rootScrollLayer()->scrollOffset() + rootScrollLayer()->scrollDelta();
[email protected]94f206c12012-08-25 00:09:141474
[email protected]a823df82013-01-10 02:38:171475 setPageScaleDelta(m_pageScaleAnimation->pageScaleFactorAtTime(monotonicTime) / m_pinchZoomViewport.page_scale_factor());
[email protected]c9c1ebe2012-11-05 20:46:131476 gfx::Vector2dF nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]f6250742012-11-09 04:46:561477
[email protected]9bdcfd642012-11-14 21:24:261478 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]a823df82013-01-10 02:38:171479 nextScroll.Scale(m_pinchZoomViewport.page_scale_factor());
[email protected]3b31c6ac2012-12-06 21:27:291480 rootScrollLayer()->scrollBy(nextScroll - scrollTotal);
[email protected]94f206c12012-08-25 00:09:141481 m_client->setNeedsRedrawOnImplThread();
[email protected]0ede3bb2012-12-09 09:14:391482 setNeedsUpdateDrawProperties();
[email protected]94f206c12012-08-25 00:09:141483
1484 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451485 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141486 m_client->setNeedsCommitOnImplThread();
1487 }
1488}
1489
[email protected]30faac92012-10-29 00:06:291490void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:141491{
[email protected]de4afb5e2012-12-20 00:11:341492 if (!m_settings.acceleratedAnimationEnabled || m_animationRegistrar->active_animation_controllers().empty() || !rootLayer())
[email protected]94f206c12012-08-25 00:09:141493 return;
1494
[email protected]96baf3e2012-10-22 23:09:551495 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141496
[email protected]de4afb5e2012-12-20 00:11:341497 double monotonicSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
[email protected]df1ec1a2012-12-08 17:01:181498
[email protected]de4afb5e2012-12-20 00:11:341499 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
1500 AnimationRegistrar::AnimationControllerMap copy = m_animationRegistrar->active_animation_controllers();
1501 for (AnimationRegistrar::AnimationControllerMap::iterator iter = copy.begin(); iter != copy.end(); ++iter)
1502 (*iter).second->animate(monotonicSeconds, events.get());
[email protected]94f206c12012-08-25 00:09:141503
[email protected]d3143c732012-10-05 19:17:591504 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571505 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141506
[email protected]de4afb5e2012-12-20 00:11:341507 m_client->setNeedsRedrawOnImplThread();
1508 setNeedsUpdateDrawProperties();
1509 setBackgroundTickingEnabled(!m_visible && !m_animationRegistrar->active_animation_controllers().empty());
[email protected]94f206c12012-08-25 00:09:141510}
1511
[email protected]96baf3e2012-10-22 23:09:551512base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141513{
[email protected]4481ddb622012-09-20 16:33:471514 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141515}
1516
[email protected]3be2171d2012-12-06 06:13:201517void LayerTreeHostImpl::sendDidLoseOutputSurfaceRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141518{
[email protected]1d993172012-10-18 18:15:041519 DCHECK(current);
[email protected]3be2171d2012-12-06 06:13:201520 current->didLoseOutputSurface();
[email protected]94f206c12012-08-25 00:09:141521 if (current->maskLayer())
[email protected]3be2171d2012-12-06 06:13:201522 sendDidLoseOutputSurfaceRecursive(current->maskLayer());
[email protected]94f206c12012-08-25 00:09:141523 if (current->replicaLayer())
[email protected]3be2171d2012-12-06 06:13:201524 sendDidLoseOutputSurfaceRecursive(current->replicaLayer());
[email protected]94f206c12012-08-25 00:09:141525 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]3be2171d2012-12-06 06:13:201526 sendDidLoseOutputSurfaceRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141527}
1528
[email protected]96baf3e2012-10-22 23:09:551529void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141530{
[email protected]76ffd9e2012-12-20 19:12:471531 activeTree()->ClearRenderSurfaces();
1532 if (pendingTree())
1533 pendingTree()->ClearRenderSurfaces();
[email protected]94f206c12012-08-25 00:09:141534}
1535
[email protected]96baf3e2012-10-22 23:09:551536std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141537{
[email protected]515e8d232012-09-10 19:15:271538 std::string str;
[email protected]3b31c6ac2012-12-06 21:27:291539 if (rootLayer()) {
1540 str = rootLayer()->layerTreeAsText();
[email protected]515e8d232012-09-10 19:15:271541 str += "RenderSurfaces:\n";
[email protected]3b31c6ac2012-12-06 21:27:291542 dumpRenderSurfaces(&str, 1, rootLayer());
[email protected]94f206c12012-08-25 00:09:141543 }
[email protected]515e8d232012-09-10 19:15:271544 return str;
[email protected]94f206c12012-08-25 00:09:141545}
1546
[email protected]4a23c374c2012-12-08 08:38:551547std::string LayerTreeHostImpl::layerTreeAsJson() const
1548{
1549 std::string str;
1550 if (rootLayer()) {
1551 scoped_ptr<base::Value> json(rootLayer()->layerTreeAsJson());
1552 base::JSONWriter::WriteWithOptions(
1553 json.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &str);
1554 }
1555 return str;
1556}
1557
[email protected]96baf3e2012-10-22 23:09:551558void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141559{
1560 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271561 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141562
1563 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031564 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141565}
1566
[email protected]96baf3e2012-10-22 23:09:551567int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141568{
1569 return fpsCounter()->currentFrameNumber();
1570}
1571
[email protected]96baf3e2012-10-22 23:09:551572void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141573{
[email protected]8b9af6b2012-09-27 00:36:361574 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1575 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271576 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1577 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]b2136f12012-11-30 02:45:531578 stats->numLayersDrawn = m_cumulativeNumLayersDrawn;
[email protected]f2bbb4e2012-12-07 21:40:491579 stats->numMissingTiles = m_cumulativeNumMissingTiles;
[email protected]4d3c5c912012-11-30 05:55:021580
1581 if (m_tileManager)
[email protected]ee371e02012-12-16 20:13:441582 m_tileManager->GetRenderingStats(stats);
[email protected]94f206c12012-08-25 00:09:141583}
1584
[email protected]d3afa112012-12-08 06:24:281585void LayerTreeHostImpl::sendManagedMemoryStats(
1586 size_t memoryVisibleBytes,
1587 size_t memoryVisibleAndNearbyBytes,
1588 size_t memoryUseBytes)
1589{
1590 if (!renderer())
1591 return;
1592
1593 // Round the numbers being sent up to the next 8MB, to throttle the rate
1594 // at which we spam the GPU process.
1595 static const size_t roundingStep = 8 * 1024 * 1024;
1596 memoryVisibleBytes = RoundUp(memoryVisibleBytes, roundingStep);
1597 memoryVisibleAndNearbyBytes = RoundUp(memoryVisibleAndNearbyBytes, roundingStep);
1598 memoryUseBytes = RoundUp(memoryUseBytes, roundingStep);
1599 if (m_lastSentMemoryVisibleBytes == memoryVisibleBytes &&
1600 m_lastSentMemoryVisibleAndNearbyBytes == memoryVisibleAndNearbyBytes &&
1601 m_lastSentMemoryUseBytes == memoryUseBytes) {
1602 return;
1603 }
1604 m_lastSentMemoryVisibleBytes = memoryVisibleBytes;
1605 m_lastSentMemoryVisibleAndNearbyBytes = memoryVisibleAndNearbyBytes;
1606 m_lastSentMemoryUseBytes = memoryUseBytes;
1607
1608 renderer()->sendManagedMemoryStats(m_lastSentMemoryVisibleBytes,
1609 m_lastSentMemoryVisibleAndNearbyBytes,
1610 m_lastSentMemoryUseBytes);
1611}
1612
[email protected]30faac92012-10-29 00:06:291613void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141614{
[email protected]3b31c6ac2012-12-06 21:27:291615 animateScrollbarsRecursive(rootLayer(), time);
[email protected]94f206c12012-08-25 00:09:141616}
1617
[email protected]30faac92012-10-29 00:06:291618void LayerTreeHostImpl::animateScrollbarsRecursive(LayerImpl* layer, base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141619{
1620 if (!layer)
1621 return;
1622
[email protected]96baf3e2012-10-22 23:09:551623 ScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]30faac92012-10-29 00:06:291624 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]94f206c12012-08-25 00:09:141625 if (scrollbarController && scrollbarController->animate(monotonicTime))
1626 m_client->setNeedsRedrawOnImplThread();
1627
1628 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]30faac92012-10-29 00:06:291629 animateScrollbarsRecursive(layer->children()[i], time);
[email protected]94f206c12012-08-25 00:09:141630}
1631
[email protected]b9dcf43a2013-01-09 00:15:291632// static
1633LayerImpl* LayerTreeHostImpl::getNonCompositedContentLayerRecursive(LayerImpl* layer)
1634{
1635 if (!layer)
1636 return NULL;
1637
1638 if (layer->drawsContent())
1639 return layer;
1640
1641 for (LayerImpl::LayerList::const_iterator it = layer->children().begin();
1642 it != layer->children().end(); ++it) {
1643 LayerImpl* nccr = getNonCompositedContentLayerRecursive(*it);
1644 if (nccr)
1645 return nccr;
1646 }
1647
1648 return NULL;
1649}
1650
1651skia::RefPtr<SkPicture> LayerTreeHostImpl::capturePicture()
1652{
1653 LayerTreeImpl* tree = pendingTree() ? pendingTree() : activeTree();
1654 LayerImpl* layer = getNonCompositedContentLayerRecursive(tree->RootLayer());
1655 return layer ? layer->getPicture() : skia::RefPtr<SkPicture>();
1656}
1657
[email protected]d3143c732012-10-05 19:17:591658} // namespace cc