blob: 48bc1fbaadad580dacccd740a4e2c4c3d8697a9a [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]55a124d02012-10-22 03:07:135#include "cc/layer_tree_host_impl.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]ac7c7f52012-11-08 06:26:507#include <algorithm>
8
[email protected]ad5d1422012-10-19 13:40:299#include "base/basictypes.h"
[email protected]4456eee22012-10-19 18:16:3810#include "base/debug/trace_event.h"
[email protected]aa0a9d32012-10-24 01:58:1011#include "cc/append_quads_data.h"
12#include "cc/damage_tracker.h"
13#include "cc/debug_rect_history.h"
14#include "cc/delay_based_time_source.h"
15#include "cc/font_atlas.h"
16#include "cc/frame_rate_counter.h"
[email protected]c4040a522012-10-21 15:01:4017#include "cc/gl_renderer.h"
[email protected]d50c6862012-10-23 02:08:3118#include "cc/heads_up_display_layer_impl.h"
19#include "cc/layer_iterator.h"
20#include "cc/layer_tree_host.h"
21#include "cc/layer_tree_host_common.h"
[email protected]55a124d02012-10-22 03:07:1322#include "cc/math_util.h"
23#include "cc/overdraw_metrics.h"
24#include "cc/page_scale_animation.h"
[email protected]3b10a302012-11-07 21:16:4025#include "cc/prioritized_resource_manager.h"
[email protected]f57bbc02012-11-21 07:02:1526#include "cc/quad_culler.h"
[email protected]55a124d02012-10-22 03:07:1327#include "cc/render_pass_draw_quad.h"
[email protected]c4040a522012-10-21 15:01:4028#include "cc/rendering_stats.h"
29#include "cc/scrollbar_animation_controller.h"
30#include "cc/scrollbar_layer_impl.h"
[email protected]f57bbc02012-11-21 07:02:1531#include "cc/shared_quad_state.h"
[email protected]4456eee22012-10-19 18:16:3832#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4033#include "cc/software_renderer.h"
[email protected]f57bbc02012-11-21 07:02:1534#include "cc/solid_color_draw_quad.h"
[email protected]a8461d82012-10-16 21:11:1435#include "cc/texture_uploader.h"
[email protected]d455d552012-11-02 00:19:0636#include "ui/gfx/size_conversions.h"
[email protected]c9c1ebe2012-11-05 20:46:1337#include "ui/gfx/vector2d_conversions.h"
[email protected]94f206c12012-08-25 00:09:1438
[email protected]94f206c12012-08-25 00:09:1439namespace {
40
[email protected]96baf3e2012-10-22 23:09:5541void didVisibilityChange(cc::LayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1442{
43 if (visible) {
[email protected]96baf3e2012-10-22 23:09:5544 TRACE_EVENT_ASYNC_BEGIN1("webkit", "LayerTreeHostImpl::setVisible", id, "LayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1445 return;
46 }
47
[email protected]96baf3e2012-10-22 23:09:5548 TRACE_EVENT_ASYNC_END0("webkit", "LayerTreeHostImpl::setVisible", id);
[email protected]94f206c12012-08-25 00:09:1449}
50
51} // namespace
52
[email protected]9c88e562012-09-14 22:21:3053namespace cc {
[email protected]94f206c12012-08-25 00:09:1454
[email protected]96baf3e2012-10-22 23:09:5555PinchZoomViewport::PinchZoomViewport()
[email protected]1c0c9bc2012-10-08 22:41:4856 : m_pageScaleFactor(1)
57 , m_pageScaleDelta(1)
58 , m_sentPageScaleDelta(1)
59 , m_minPageScaleFactor(0)
60 , m_maxPageScaleFactor(0)
[email protected]e39bf212012-11-22 21:04:0361 , m_deviceScaleFactor(1)
[email protected]1c0c9bc2012-10-08 22:41:4862{
63}
64
[email protected]96baf3e2012-10-22 23:09:5565float PinchZoomViewport::totalPageScaleFactor() const
[email protected]1c0c9bc2012-10-08 22:41:4866{
67 return m_pageScaleFactor * m_pageScaleDelta;
68}
69
[email protected]96baf3e2012-10-22 23:09:5570void PinchZoomViewport::setPageScaleDelta(float delta)
[email protected]1c0c9bc2012-10-08 22:41:4871{
72 // Clamp to the current min/max limits.
73 float totalPageScaleFactor = m_pageScaleFactor * delta;
74 if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
75 delta = m_minPageScaleFactor / m_pageScaleFactor;
76 else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
77 delta = m_maxPageScaleFactor / m_pageScaleFactor;
78
79 if (delta == m_pageScaleDelta)
80 return;
81
82 m_pageScaleDelta = delta;
83}
84
[email protected]96baf3e2012-10-22 23:09:5585bool PinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:4886{
[email protected]1d993172012-10-18 18:15:0487 DCHECK(pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:4888
89 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
90 return false;
91
92 m_minPageScaleFactor = minPageScaleFactor;
93 m_maxPageScaleFactor = maxPageScaleFactor;
94
95 m_pageScaleFactor = pageScaleFactor;
96 return true;
97}
98
[email protected]aad0a0072012-11-01 18:15:5899gfx::RectF PinchZoomViewport::bounds() const
[email protected]1c0c9bc2012-10-08 22:41:48100{
[email protected]2e6486012012-11-10 00:03:19101 gfx::RectF bounds(gfx::PointF(), m_layoutViewportSize);
102 bounds.Scale(1 / totalPageScaleFactor());
[email protected]e39bf212012-11-22 21:04:03103 bounds += m_zoomedViewportOffset;
[email protected]1c0c9bc2012-10-08 22:41:48104 return bounds;
105}
106
[email protected]c9c1ebe2012-11-05 20:46:13107gfx::Vector2dF PinchZoomViewport::applyScroll(const gfx::Vector2dF& delta)
[email protected]1c0c9bc2012-10-08 22:41:48108{
[email protected]d0f98362012-11-01 23:02:38109 gfx::Vector2dF overflow;
[email protected]2e6486012012-11-10 00:03:19110 gfx::RectF pinchedBounds = bounds() + delta;
[email protected]1c0c9bc2012-10-08 22:41:48111
[email protected]1c0c9bc2012-10-08 22:41:48112 if (pinchedBounds.x() < 0) {
[email protected]d0f98362012-11-01 23:02:38113 overflow.set_x(pinchedBounds.x());
114 pinchedBounds.set_x(0);
[email protected]1c0c9bc2012-10-08 22:41:48115 }
116
117 if (pinchedBounds.y() < 0) {
[email protected]d0f98362012-11-01 23:02:38118 overflow.set_y(pinchedBounds.y());
119 pinchedBounds.set_y(0);
[email protected]1c0c9bc2012-10-08 22:41:48120 }
121
[email protected]d0f98362012-11-01 23:02:38122 if (pinchedBounds.right() > m_layoutViewportSize.width()) {
123 overflow.set_x(pinchedBounds.right() - m_layoutViewportSize.width());
[email protected]2e6486012012-11-10 00:03:19124 pinchedBounds += gfx::Vector2dF(m_layoutViewportSize.width() - pinchedBounds.right(), 0);
[email protected]1c0c9bc2012-10-08 22:41:48125 }
126
[email protected]d0f98362012-11-01 23:02:38127 if (pinchedBounds.bottom() > m_layoutViewportSize.height()) {
128 overflow.set_y(pinchedBounds.bottom() - m_layoutViewportSize.height());
[email protected]2e6486012012-11-10 00:03:19129 pinchedBounds += gfx::Vector2dF(0, m_layoutViewportSize.height() - pinchedBounds.bottom());
[email protected]1c0c9bc2012-10-08 22:41:48130 }
[email protected]e39bf212012-11-22 21:04:03131 m_zoomedViewportOffset = pinchedBounds.OffsetFromOrigin();
[email protected]1c0c9bc2012-10-08 22:41:48132
[email protected]c9c1ebe2012-11-05 20:46:13133 return overflow;
[email protected]1c0c9bc2012-10-08 22:41:48134}
135
[email protected]c8686a02012-11-27 08:29:00136gfx::Transform PinchZoomViewport::implTransform(bool pageScalePinchZoomEnabled) const
[email protected]1c0c9bc2012-10-08 22:41:48137{
[email protected]c8686a02012-11-27 08:29:00138 gfx::Transform transform;
139 transform.Scale(m_pageScaleDelta, m_pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:48140
141 // If the pinch state is applied in the impl, then push it to the
142 // impl transform, otherwise the scale is handled by WebCore.
[email protected]9bdcfd642012-11-14 21:24:26143 if (pageScalePinchZoomEnabled) {
[email protected]c8686a02012-11-27 08:29:00144 transform.Scale(m_pageScaleFactor, m_pageScaleFactor);
[email protected]e39bf212012-11-22 21:04:03145 // The offset needs to be scaled by deviceScaleFactor as this transform
146 // needs to work with physical pixels.
147 gfx::Vector2dF zoomedDeviceViewportOffset = gfx::ScaleVector2d(m_zoomedViewportOffset, m_deviceScaleFactor);
[email protected]c8686a02012-11-27 08:29:00148 transform.Translate(-zoomedDeviceViewportOffset.x(), -zoomedDeviceViewportOffset.y());
[email protected]1c0c9bc2012-10-08 22:41:48149 }
150
151 return transform;
152}
153
[email protected]96baf3e2012-10-22 23:09:55154class LayerTreeHostImplTimeSourceAdapter : public TimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14155public:
[email protected]96baf3e2012-10-22 23:09:55156 static scoped_ptr<LayerTreeHostImplTimeSourceAdapter> create(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14157 {
[email protected]96baf3e2012-10-22 23:09:55158 return make_scoped_ptr(new LayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:14159 }
[email protected]96baf3e2012-10-22 23:09:55160 virtual ~LayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:14161 {
162 m_timeSource->setClient(0);
163 m_timeSource->setActive(false);
164 }
165
166 virtual void onTimerTick() OVERRIDE
167 {
[email protected]30faac92012-10-29 00:06:29168 m_layerTreeHostImpl->animate(base::TimeTicks::Now(), base::Time::Now());
[email protected]94f206c12012-08-25 00:09:14169 }
170
171 void setActive(bool active)
172 {
173 if (active != m_timeSource->active())
174 m_timeSource->setActive(active);
175 }
176
177private:
[email protected]96baf3e2012-10-22 23:09:55178 LayerTreeHostImplTimeSourceAdapter(LayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<DelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14179 : m_layerTreeHostImpl(layerTreeHostImpl)
180 , m_timeSource(timeSource)
181 {
182 m_timeSource->setClient(this);
183 }
184
[email protected]96baf3e2012-10-22 23:09:55185 LayerTreeHostImpl* m_layerTreeHostImpl;
186 scoped_refptr<DelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20187
[email protected]96baf3e2012-10-22 23:09:55188 DISALLOW_COPY_AND_ASSIGN(LayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14189};
190
[email protected]96baf3e2012-10-22 23:09:55191LayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10192{
193}
194
[email protected]96baf3e2012-10-22 23:09:55195LayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10196{
197}
198
[email protected]61de5812012-11-08 07:03:44199scoped_ptr<LayerTreeHostImpl> LayerTreeHostImpl::create(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14200{
[email protected]61de5812012-11-08 07:03:44201 return make_scoped_ptr(new LayerTreeHostImpl(settings, client, proxy));
[email protected]94f206c12012-08-25 00:09:14202}
203
[email protected]61de5812012-11-08 07:03:44204LayerTreeHostImpl::LayerTreeHostImpl(const LayerTreeSettings& settings, LayerTreeHostImplClient* client, Proxy* proxy)
[email protected]94f206c12012-08-25 00:09:14205 : m_client(client)
[email protected]61de5812012-11-08 07:03:44206 , m_proxy(proxy)
[email protected]94f206c12012-08-25 00:09:14207 , m_sourceFrameNumber(-1)
208 , m_rootScrollLayerImpl(0)
209 , m_currentlyScrollingLayerImpl(0)
210 , m_hudLayerImpl(0)
211 , m_scrollingLayerIdFromPreviousTree(-1)
[email protected]31bfe272012-10-19 18:49:52212 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14213 , m_settings(settings)
214 , m_deviceScaleFactor(1)
215 , m_visible(true)
216 , m_contentsTexturesPurged(false)
[email protected]3b10a302012-11-07 21:16:40217 , m_managedMemoryPolicy(PrioritizedResourceManager::defaultMemoryAllocationLimit(),
[email protected]96baf3e2012-10-22 23:09:55218 PriorityCalculator::allowEverythingCutoff(),
[email protected]a0a00842012-10-22 22:50:28219 0,
[email protected]96baf3e2012-10-22 23:09:55220 PriorityCalculator::allowNothingCutoff())
[email protected]94f206c12012-08-25 00:09:14221 , m_backgroundColor(0)
222 , m_hasTransparentBackground(false)
223 , m_needsAnimateLayers(false)
224 , m_pinchGestureActive(false)
[email protected]61de5812012-11-08 07:03:44225 , m_fpsCounter(FrameRateCounter::create(m_proxy->hasImplThread()))
[email protected]96baf3e2012-10-22 23:09:55226 , m_debugRectHistory(DebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27227 , m_numImplThreadScrolls(0)
228 , m_numMainThreadScrolls(0)
[email protected]9c2be6a2012-11-27 19:16:10229 , m_cumulativeNumLayersInLayerTree(0)
[email protected]94f206c12012-08-25 00:09:14230{
[email protected]61de5812012-11-08 07:03:44231 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14232 didVisibilityChange(this, m_visible);
233}
234
[email protected]96baf3e2012-10-22 23:09:55235LayerTreeHostImpl::~LayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14236{
[email protected]61de5812012-11-08 07:03:44237 DCHECK(m_proxy->isImplThread());
[email protected]96baf3e2012-10-22 23:09:55238 TRACE_EVENT0("cc", "LayerTreeHostImpl::~LayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14239
240 if (m_rootLayerImpl)
241 clearRenderSurfaces();
242}
243
[email protected]96baf3e2012-10-22 23:09:55244void LayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14245{
246}
247
[email protected]96baf3e2012-10-22 23:09:55248void LayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14249{
[email protected]96baf3e2012-10-22 23:09:55250 TRACE_EVENT0("cc", "LayerTreeHostImpl::commitComplete");
[email protected]94f206c12012-08-25 00:09:14251 // Recompute max scroll position; must be after layer content bounds are
252 // updated.
[email protected]c9c1ebe2012-11-05 20:46:13253 updateMaxScrollOffset();
[email protected]3d21e022012-10-25 20:03:08254 m_client->sendManagedMemoryStats();
[email protected]94f206c12012-08-25 00:09:14255}
256
[email protected]96baf3e2012-10-22 23:09:55257bool LayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14258{
[email protected]8db2213c2012-09-05 22:08:21259 // Note: If you are changing this function or any other function that might
260 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
261 // in the proper places and update the notifyIfCanDrawChanged test.
262
[email protected]94f206c12012-08-25 00:09:14263 if (!m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:55264 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14265 return false;
266 }
[email protected]aad0a0072012-11-01 18:15:58267 if (deviceViewportSize().IsEmpty()) {
[email protected]96baf3e2012-10-22 23:09:55268 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14269 return false;
270 }
271 if (!m_renderer) {
[email protected]96baf3e2012-10-22 23:09:55272 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14273 return false;
274 }
275 if (m_contentsTexturesPurged) {
[email protected]96baf3e2012-10-22 23:09:55276 TRACE_EVENT_INSTANT0("cc", "LayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14277 return false;
278 }
279 return true;
280}
281
[email protected]96baf3e2012-10-22 23:09:55282GraphicsContext* LayerTreeHostImpl::context() const
[email protected]94f206c12012-08-25 00:09:14283{
284 return m_context.get();
285}
286
[email protected]30faac92012-10-29 00:06:29287void LayerTreeHostImpl::animate(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:14288{
289 animatePageScale(monotonicTime);
290 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14291 animateScrollbars(monotonicTime);
292}
293
[email protected]8947cbe2012-11-28 05:27:43294void LayerTreeHostImpl::manageTiles()
295{
296 DCHECK(m_tileManager);
297 m_tileManager->ManageTiles();
298}
299
[email protected]69a2a5be2012-11-14 06:51:44300void LayerTreeHostImpl::startPageScaleAnimation(gfx::Vector2d targetOffset, bool anchorPoint, float pageScale, base::TimeTicks startTime, base::TimeDelta duration)
[email protected]94f206c12012-08-25 00:09:14301{
302 if (!m_rootScrollLayerImpl)
303 return;
304
[email protected]c9c1ebe2012-11-05 20:46:13305 gfx::Vector2dF scrollTotal = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
[email protected]f6250742012-11-09 04:46:56306 gfx::SizeF scaledContentSize = contentSize();
[email protected]9bdcfd642012-11-14 21:24:26307 if (!m_settings.pageScalePinchZoomEnabled) {
[email protected]f6250742012-11-09 04:46:56308 scrollTotal.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]01a15a72012-11-10 09:34:28309 scaledContentSize.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]f6250742012-11-09 04:46:56310 }
[email protected]01a15a72012-11-10 09:34:28311 gfx::SizeF viewportSize = gfx::ScaleSize(m_deviceViewportSize, 1 / m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:14312
[email protected]30faac92012-10-29 00:06:29313 double startTimeSeconds = (startTime - base::TimeTicks()).InSecondsF();
[email protected]f6250742012-11-09 04:46:56314 m_pageScaleAnimation = PageScaleAnimation::create(scrollTotal, m_pinchZoomViewport.totalPageScaleFactor(), viewportSize, scaledContentSize, startTimeSeconds);
[email protected]94f206c12012-08-25 00:09:14315
316 if (anchorPoint) {
[email protected]69a2a5be2012-11-14 06:51:44317 gfx::Vector2dF anchor(targetOffset);
[email protected]9bdcfd642012-11-14 21:24:26318 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:56319 anchor.Scale(1 / pageScale);
320 m_pageScaleAnimation->zoomWithAnchor(anchor, pageScale, duration.InSecondsF());
321 } else {
[email protected]69a2a5be2012-11-14 06:51:44322 gfx::Vector2dF scaledTargetOffset = targetOffset;
[email protected]9bdcfd642012-11-14 21:24:26323 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]69a2a5be2012-11-14 06:51:44324 scaledTargetOffset.Scale(1 / pageScale);
325 m_pageScaleAnimation->zoomTo(scaledTargetOffset, pageScale, duration.InSecondsF());
[email protected]f6250742012-11-09 04:46:56326 }
[email protected]94f206c12012-08-25 00:09:14327
328 m_client->setNeedsRedrawOnImplThread();
329 m_client->setNeedsCommitOnImplThread();
330}
331
[email protected]96baf3e2012-10-22 23:09:55332void LayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14333{
334 m_client->setNeedsRedrawOnImplThread();
335}
336
[email protected]2f1acc262012-11-16 21:42:22337bool LayerTreeHostImpl::haveTouchEventHandlersAt(const gfx::Point& viewportPoint)
338{
339
340 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
341
342 // First find out which layer was hit from the saved list of visible layers
343 // in the most recent frame.
344 LayerImpl* layerImplHitByPointInTouchHandlerRegion = LayerTreeHostCommon::findLayerThatIsHitByPointInTouchHandlerRegion(deviceViewportPoint, m_renderSurfaceLayerList);
345
346 if (layerImplHitByPointInTouchHandlerRegion)
347 return true;
348
349 return false;
350}
351
[email protected]96baf3e2012-10-22 23:09:55352void LayerTreeHostImpl::trackDamageForAllSurfaces(LayerImpl* rootDrawLayer, const LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14353{
354 // For now, we use damage tracking to compute a global scissor. To do this, we must
355 // compute all damage tracking before drawing anything, so that we know the root
356 // damage rect. The root damage rect is then used to scissor each surface.
357
358 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55359 LayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
360 RenderSurfaceImpl* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04361 DCHECK(renderSurface);
[email protected]4000abf2012-10-23 04:45:45362 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters(), renderSurfaceLayer->filter());
[email protected]94f206c12012-08-25 00:09:14363 }
364}
365
[email protected]96baf3e2012-10-22 23:09:55366void LayerTreeHostImpl::updateRootScrollLayerImplTransform()
[email protected]1c0c9bc2012-10-08 22:41:48367{
368 if (m_rootScrollLayerImpl) {
369 m_rootScrollLayerImpl->setImplTransform(implTransform());
370 }
371}
372
[email protected]96baf3e2012-10-22 23:09:55373void LayerTreeHostImpl::calculateRenderSurfaceLayerList(LayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14374{
[email protected]1d993172012-10-18 18:15:04375 DCHECK(renderSurfaceLayerList.empty());
376 DCHECK(m_rootLayerImpl);
377 DCHECK(m_renderer); // For maxTextureSize.
[email protected]94f206c12012-08-25 00:09:14378
379 {
[email protected]1c0c9bc2012-10-08 22:41:48380 updateRootScrollLayerImplTransform();
381
[email protected]96baf3e2012-10-22 23:09:55382 TRACE_EVENT0("cc", "LayerTreeHostImpl::calcDrawEtc");
[email protected]518ee582012-10-24 18:29:44383 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
384 LayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, pageScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14385
386 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
387 }
388}
389
[email protected]96baf3e2012-10-22 23:09:55390void LayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<RenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16391{
[email protected]96baf3e2012-10-22 23:09:55392 RenderPass* pass = renderPass.get();
[email protected]f8ad8342012-09-27 20:07:02393 renderPasses.push_back(pass);
[email protected]f57bbc02012-11-21 07:02:15394 renderPassesById.set(pass->id, renderPass.Pass());
395}
396
397static void appendQuadsForLayer(RenderPass* targetRenderPass, LayerImpl* layer, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
398{
399 bool forSurface = false;
400 QuadCuller quadCuller(targetRenderPass->quad_list,
401 targetRenderPass->shared_quad_state_list,
402 layer,
403 occlusionTracker,
404 layer->showDebugBorders(),
405 forSurface);
406 layer->appendQuads(quadCuller, appendQuadsData);
407}
408
409static void appendQuadsForRenderSurfaceLayer(RenderPass* targetRenderPass, LayerImpl* layer, const RenderPass* contributingRenderPass, OcclusionTrackerImpl& occlusionTracker, AppendQuadsData& appendQuadsData)
410{
411 bool forSurface = true;
412 QuadCuller quadCuller(targetRenderPass->quad_list,
413 targetRenderPass->shared_quad_state_list,
414 layer,
415 occlusionTracker,
416 layer->showDebugBorders(),
417 forSurface);
418
419 bool isReplica = false;
420 layer->renderSurface()->appendQuads(quadCuller,
421 appendQuadsData,
422 isReplica,
423 contributingRenderPass->id);
424
425 // Add replica after the surface so that it appears below the surface.
426 if (layer->hasReplica()) {
427 isReplica = true;
428 layer->renderSurface()->appendQuads(quadCuller,
429 appendQuadsData,
430 isReplica,
431 contributingRenderPass->id);
432 }
433}
434
435static void appendQuadsToFillScreen(RenderPass* targetRenderPass, LayerImpl* rootLayer, SkColor screenBackgroundColor, const OcclusionTrackerImpl& occlusionTracker)
436{
437 if (!rootLayer || !SkColorGetA(screenBackgroundColor))
438 return;
439
440 Region fillRegion = occlusionTracker.computeVisibleRegionInScreen();
441 if (fillRegion.IsEmpty())
442 return;
443
444 bool forSurface = false;
445 QuadCuller quadCuller(targetRenderPass->quad_list,
446 targetRenderPass->shared_quad_state_list,
447 rootLayer,
448 occlusionTracker,
449 rootLayer->showDebugBorders(),
450 forSurface);
451
452 // Manually create the quad state for the gutter quads, as the root layer
453 // doesn't have any bounds and so can't generate this itself.
454 // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
455
[email protected]c8686a02012-11-27 08:29:00456 DCHECK(rootLayer->screenSpaceTransform().IsInvertible());
[email protected]f57bbc02012-11-21 07:02:15457
458 gfx::Rect rootTargetRect = rootLayer->renderSurface()->contentRect();
459 float opacity = 1;
460 SharedQuadState* sharedQuadState = quadCuller.useSharedQuadState(SharedQuadState::Create());
461 sharedQuadState->SetAll(rootLayer->drawTransform(),
462 rootTargetRect,
463 rootTargetRect,
[email protected]dc462d782012-11-21 21:43:01464 rootTargetRect,
465 false,
[email protected]f57bbc02012-11-21 07:02:15466 opacity);
467
468 AppendQuadsData appendQuadsData;
[email protected]c8686a02012-11-27 08:29:00469 gfx::Transform transformToLayerSpace = MathUtil::inverse(rootLayer->screenSpaceTransform());
[email protected]f57bbc02012-11-21 07:02:15470 for (Region::Iterator fillRects(fillRegion); fillRects.has_rect(); fillRects.next()) {
471 // The root layer transform is composed of translations and scales only,
472 // no perspective, so mapping is sufficient.
473 gfx::Rect layerRect = MathUtil::mapClippedRect(transformToLayerSpace, fillRects.rect());
474 // Skip the quad culler and just append the quads directly to avoid
475 // occlusion checks.
476 scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
477 quad->SetNew(sharedQuadState, layerRect, screenBackgroundColor);
478 quadCuller.append(quad.PassAs<DrawQuad>(), appendQuadsData);
479 }
[email protected]467b3612012-08-28 07:41:16480}
481
[email protected]96baf3e2012-10-22 23:09:55482bool LayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14483{
[email protected]1d993172012-10-18 18:15:04484 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14485
486 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
487
[email protected]96baf3e2012-10-22 23:09:55488 TRACE_EVENT1("cc", "LayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14489
490 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14491 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]96baf3e2012-10-22 23:09:55492 LayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16493 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14494 }
495
[email protected]9bdcfd642012-11-14 21:24:26496 bool recordMetricsForFrame = m_settings.showOverdrawInTracing && base::debug::TraceLog::GetInstance() && base::debug::TraceLog::GetInstance()->IsEnabled();
[email protected]96baf3e2012-10-22 23:09:55497 OcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14498 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
499
500 if (settings().showOccludingRects)
501 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
[email protected]4d8804e2012-11-15 01:51:10502 if (settings().showNonOccludingRects)
503 occlusionTracker.setNonOccludingScreenSpaceRectsContainer(&frame.nonOccludingScreenSpaceRects);
[email protected]94f206c12012-08-25 00:09:14504
505 // 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:55506 typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> LayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14507
508 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
509 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
510 // in the future.
511 bool drawFrame = true;
512
[email protected]96baf3e2012-10-22 23:09:55513 LayerIteratorType end = LayerIteratorType::end(frame.renderSurfaceLayerList);
514 for (LayerIteratorType it = LayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
515 RenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
516 RenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14517
518 occlusionTracker.enterLayer(it);
519
[email protected]f57bbc02012-11-21 07:02:15520 AppendQuadsData appendQuadsData(targetRenderPass->id);
[email protected]89228202012-08-29 03:20:30521
[email protected]94f206c12012-08-25 00:09:14522 if (it.representsContributingRenderSurface()) {
[email protected]96baf3e2012-10-22 23:09:55523 RenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
524 RenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]f57bbc02012-11-21 07:02:15525 appendQuadsForRenderSurfaceLayer(targetRenderPass, *it, contributingRenderPass, occlusionTracker, appendQuadsData);
[email protected]aad0a0072012-11-01 18:15:58526 } else if (it.representsItself() && !it->visibleContentRect().IsEmpty()) {
[email protected]94f206c12012-08-25 00:09:14527 bool hasOcclusionFromOutsideTargetSurface;
[email protected]710ffc02012-10-30 21:42:02528 bool implDrawTransformIsUnknown = false;
529 if (occlusionTracker.occluded(it->renderTarget(), it->visibleContentRect(), it->drawTransform(), implDrawTransformIsUnknown, it->drawableContentRect(), &hasOcclusionFromOutsideTargetSurface))
[email protected]89228202012-08-29 03:20:30530 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
531 else {
[email protected]94f206c12012-08-25 00:09:14532 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47533 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57534
535 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]96baf3e2012-10-22 23:09:55536 RenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]7d929c02012-09-20 17:26:57537 while (frame.renderPassesById.contains(contributingRenderPassId)) {
[email protected]96baf3e2012-10-22 23:09:55538 RenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]7d929c02012-09-20 17:26:57539
[email protected]f57bbc02012-11-21 07:02:15540 AppendQuadsData appendQuadsData(renderPass->id);
541 appendQuadsForLayer(renderPass, *it, occlusionTracker, appendQuadsData);
[email protected]7d929c02012-09-20 17:26:57542
543 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
544 }
545 }
546
[email protected]f57bbc02012-11-21 07:02:15547 appendQuadsForLayer(targetRenderPass, *it, occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14548 }
[email protected]9c2be6a2012-11-27 19:16:10549
550 ++m_cumulativeNumLayersInLayerTree;
[email protected]94f206c12012-08-25 00:09:14551 }
552
[email protected]89228202012-08-29 03:20:30553 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
[email protected]f57bbc02012-11-21 07:02:15554 targetRenderPass->has_occlusion_from_outside_target_surface = true;
[email protected]89228202012-08-29 03:20:30555
556 if (appendQuadsData.hadMissingTiles) {
[email protected]94f206c12012-08-25 00:09:14557 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]22619922012-11-14 17:58:10558 if (layerHasAnimatingTransform)
[email protected]94f206c12012-08-25 00:09:14559 drawFrame = false;
560 }
561
562 occlusionTracker.leaveLayer(it);
563 }
564
[email protected]1d993172012-10-18 18:15:04565#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14566 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]f57bbc02012-11-21 07:02:15567 for (size_t j = 0; j < frame.renderPasses[i]->quad_list.size(); ++j)
568 DCHECK(frame.renderPasses[i]->quad_list[j]->shared_quad_state);
569 DCHECK(frame.renderPassesById.contains(frame.renderPasses[i]->id));
[email protected]94f206c12012-08-25 00:09:14570 }
571#endif
572
573 if (!m_hasTransparentBackground) {
[email protected]f57bbc02012-11-21 07:02:15574 frame.renderPasses.back()->has_transparent_background = false;
575 appendQuadsToFillScreen(frame.renderPasses.back(), m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14576 }
577
578 if (drawFrame)
579 occlusionTracker.overdrawMetrics().recordMetrics(this);
580
581 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
582 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
583 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
584
585 return drawFrame;
586}
587
[email protected]30faac92012-10-29 00:06:29588void LayerTreeHostImpl::animateLayersRecursive(LayerImpl* current, base::TimeTicks monotonicTime, base::Time wallClockTime, AnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
[email protected]94f206c12012-08-25 00:09:14589{
590 bool subtreeNeedsAnimateLayers = false;
591
[email protected]96baf3e2012-10-22 23:09:55592 LayerAnimationController* currentController = current->layerAnimationController();
[email protected]94f206c12012-08-25 00:09:14593
594 bool hadActiveAnimation = currentController->hasActiveAnimation();
[email protected]30faac92012-10-29 00:06:29595 double monotonicTimeSeconds = (monotonicTime - base::TimeTicks()).InSecondsF();
596 currentController->animate(monotonicTimeSeconds, events);
[email protected]94f206c12012-08-25 00:09:14597 bool startedAnimation = events->size() > 0;
598
599 // We animated if we either ticked a running animation, or started a new animation.
600 if (hadActiveAnimation || startedAnimation)
601 didAnimate = true;
602
603 // If the current controller still has an active animation, we must continue animating layers.
604 if (currentController->hasActiveAnimation())
605 subtreeNeedsAnimateLayers = true;
606
607 for (size_t i = 0; i < current->children().size(); ++i) {
608 bool childNeedsAnimateLayers = false;
[email protected]0920e24f2012-09-20 03:34:03609 animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:14610 if (childNeedsAnimateLayers)
611 subtreeNeedsAnimateLayers = true;
612 }
613
614 needsAnimateLayers = subtreeNeedsAnimateLayers;
615}
616
[email protected]96baf3e2012-10-22 23:09:55617void LayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14618{
619 // Lazily create the timeSource adapter so that we can vary the interval for testing.
620 if (!m_timeSourceClientAdapter)
[email protected]61de5812012-11-08 07:03:44621 m_timeSourceClientAdapter = LayerTreeHostImplTimeSourceAdapter::create(this, DelayBasedTimeSource::create(lowFrequencyAnimationInterval(), m_proxy->currentThread()));
[email protected]94f206c12012-08-25 00:09:14622
623 m_timeSourceClientAdapter->setActive(enabled);
624}
625
[email protected]aad0a0072012-11-01 18:15:58626gfx::Size LayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14627{
628 // TODO(aelias): Hardcoding the first child here is weird. Think of
629 // a cleaner way to get the contentBounds on the Impl side.
630 if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
[email protected]aad0a0072012-11-01 18:15:58631 return gfx::Size();
[email protected]94f206c12012-08-25 00:09:14632 return m_rootScrollLayerImpl->children()[0]->contentBounds();
633}
634
[email protected]96baf3e2012-10-22 23:09:55635static inline RenderPass* findRenderPassById(RenderPass::Id renderPassId, const LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14636{
[email protected]96baf3e2012-10-22 23:09:55637 RenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]1d993172012-10-18 18:15:04638 DCHECK(it != frame.renderPassesById.end());
[email protected]87cea5372012-09-26 18:59:56639 return it->second;
[email protected]94f206c12012-08-25 00:09:14640}
641
[email protected]96baf3e2012-10-22 23:09:55642static void removeRenderPassesRecursive(RenderPass::Id removeRenderPassId, LayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14643{
[email protected]96baf3e2012-10-22 23:09:55644 RenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
645 RenderPassList& renderPasses = frame.renderPasses;
646 RenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14647
648 // The pass was already removed by another quad - probably the original, and we are the replica.
[email protected]f8ad8342012-09-27 20:07:02649 if (toRemove == renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14650 return;
651
[email protected]96baf3e2012-10-22 23:09:55652 const RenderPass* removedPass = *toRemove;
[email protected]f8ad8342012-09-27 20:07:02653 frame.renderPasses.erase(toRemove);
[email protected]94f206c12012-08-25 00:09:14654
655 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]f57bbc02012-11-21 07:02:15656 const QuadList& quadList = removedPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55657 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14658 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55659 DrawQuad* currentQuad = (*quadListIterator);
[email protected]1bc93f62012-11-17 19:29:50660 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14661 continue;
662
[email protected]c22418b2012-11-20 23:06:26663 RenderPass::Id nextRemoveRenderPassId = RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id;
[email protected]94f206c12012-08-25 00:09:14664 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
665 }
666}
667
[email protected]96baf3e2012-10-22 23:09:55668bool LayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14669{
[email protected]c22418b2012-11-20 23:06:26670 return quad.contents_changed_since_last_frame.IsEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.render_pass_id);
[email protected]94f206c12012-08-25 00:09:14671}
672
[email protected]96baf3e2012-10-22 23:09:55673bool LayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const RenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14674{
[email protected]c22418b2012-11-20 23:06:26675 const RenderPass* renderPass = findRenderPassById(quad.render_pass_id, frame);
[email protected]96baf3e2012-10-22 23:09:55676 const RenderPassList& renderPasses = frame.renderPasses;
677 RenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
[email protected]94f206c12012-08-25 00:09:14678
[email protected]f8ad8342012-09-27 20:07:02679 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
[email protected]94f206c12012-08-25 00:09:14680 if (renderPassAlreadyRemoved)
681 return false;
682
683 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]f57bbc02012-11-21 07:02:15684 const QuadList& quadList = (*foundPass)->quad_list;
[email protected]96baf3e2012-10-22 23:09:55685 for (QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
686 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14687
[email protected]1bc93f62012-11-17 19:29:50688 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14689 return false;
690
[email protected]c22418b2012-11-20 23:06:26691 const RenderPass* contributingPass = findRenderPassById(RenderPassDrawQuad::MaterialCast(currentQuad)->render_pass_id, frame);
[email protected]96baf3e2012-10-22 23:09:55692 RenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
[email protected]f8ad8342012-09-27 20:07:02693 if (foundContributingPass != renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14694 return false;
695 }
696 return true;
697}
698
699// Defined for linking tests.
[email protected]52347c842012-11-02 21:06:20700template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
701template CC_EXPORT void LayerTreeHostImpl::removeRenderPasses<LayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14702
703// static
704template<typename RenderPassCuller>
[email protected]96baf3e2012-10-22 23:09:55705void LayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14706{
707 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]96baf3e2012-10-22 23:09:55708 const RenderPass* currentPass = frame.renderPasses[it];
[email protected]f57bbc02012-11-21 07:02:15709 const QuadList& quadList = currentPass->quad_list;
[email protected]96baf3e2012-10-22 23:09:55710 QuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14711
712 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]96baf3e2012-10-22 23:09:55713 DrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14714
[email protected]1bc93f62012-11-17 19:29:50715 if (currentQuad->material != DrawQuad::RENDER_PASS)
[email protected]94f206c12012-08-25 00:09:14716 continue;
717
[email protected]96baf3e2012-10-22 23:09:55718 RenderPassDrawQuad* renderPassQuad = static_cast<RenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14719 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
720 continue;
721
722 // We are changing the vector in the middle of iteration. Because we
723 // delete render passes that draw into the current pass, we are
724 // guaranteed that any data from the iterator to the end will not
725 // change. So, capture the iterator position from the end of the
726 // list, and restore it after the change.
727 int positionFromEnd = frame.renderPasses.size() - it;
[email protected]c22418b2012-11-20 23:06:26728 removeRenderPassesRecursive(renderPassQuad->render_pass_id, frame);
[email protected]94f206c12012-08-25 00:09:14729 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04730 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14731 }
732 }
733}
734
[email protected]96baf3e2012-10-22 23:09:55735bool LayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14736{
[email protected]96baf3e2012-10-22 23:09:55737 TRACE_EVENT0("cc", "LayerTreeHostImpl::prepareToDraw");
[email protected]1d993172012-10-18 18:15:04738 DCHECK(canDraw());
[email protected]94f206c12012-08-25 00:09:14739
740 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
741 frame.renderPasses.clear();
742 frame.renderPassesById.clear();
743 frame.renderSurfaceLayerList->clear();
744 frame.willDrawLayers.clear();
745
746 if (!calculateRenderPasses(frame))
747 return false;
748
749 // If we return true, then we expect drawLayers() to be called before this function is called again.
750 return true;
751}
752
[email protected]96baf3e2012-10-22 23:09:55753void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14754{
[email protected]a0a00842012-10-22 22:50:28755 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
756 m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
757 m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
[email protected]b1969fa2012-10-17 20:16:29758 if (evictedResources) {
759 setContentsTexturesPurged();
760 m_client->setNeedsCommitOnImplThread();
761 m_client->onCanDrawStateChanged(canDraw());
762 }
[email protected]3d21e022012-10-25 20:03:08763 m_client->sendManagedMemoryStats();
[email protected]8947cbe2012-11-28 05:27:43764
765 if (m_tileManager) {
766 // TODO(nduca): Pass something useful into the memory manager.
767 LOG(INFO) << "Setting up initial tile manager policy";
768 GlobalStateThatImpactsTilePriority new_state(m_tileManager->GlobalState());
769 new_state.memory_limit_in_bytes = PrioritizedResourceManager::defaultMemoryAllocationLimit();
770 new_state.memory_limit_policy = ALLOW_ANYTHING;
771 m_tileManager->SetGlobalState(new_state);
772 }
[email protected]94f206c12012-08-25 00:09:14773}
774
[email protected]61de5812012-11-08 07:03:44775bool LayerTreeHostImpl::hasImplThread() const
776{
777 return m_proxy->hasImplThread();
778}
779
[email protected]8947cbe2012-11-28 05:27:43780void LayerTreeHostImpl::ScheduleManageTiles()
781{
782 if (m_client)
783 m_client->setNeedsManageTilesOnImplThread();
784}
785
[email protected]96baf3e2012-10-22 23:09:55786void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
[email protected]94f206c12012-08-25 00:09:14787{
[email protected]a0a00842012-10-22 22:50:28788 if (m_managedMemoryPolicy == policy)
[email protected]94f206c12012-08-25 00:09:14789 return;
[email protected]61de5812012-11-08 07:03:44790
[email protected]a0a00842012-10-22 22:50:28791 m_managedMemoryPolicy = policy;
[email protected]61de5812012-11-08 07:03:44792 if (!m_proxy->hasImplThread()) {
793 // FIXME: In single-thread mode, this can be called on the main thread
794 // by GLRenderer::onMemoryAllocationChanged.
795 DebugScopedSetImplThread implThread(m_proxy);
796 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
797 } else {
798 DCHECK(m_proxy->isImplThread());
799 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
800 }
[email protected]a0a00842012-10-22 22:50:28801 // We always need to commit after changing the memory policy because the new
802 // limit can result in more or less content having texture allocated for it.
[email protected]94f206c12012-08-25 00:09:14803 m_client->setNeedsCommitOnImplThread();
804}
805
[email protected]96baf3e2012-10-22 23:09:55806void LayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
[email protected]94f206c12012-08-25 00:09:14807{
[email protected]30faac92012-10-29 00:06:29808 base::TimeTicks timebase = base::TimeTicks::FromInternalValue(monotonicTimebase * base::Time::kMicrosecondsPerSecond);
809 base::TimeDelta interval = base::TimeDelta::FromMicroseconds(intervalInSeconds * base::Time::kMicrosecondsPerSecond);
810 m_client->onVSyncParametersChanged(timebase, interval);
[email protected]94f206c12012-08-25 00:09:14811}
812
[email protected]96baf3e2012-10-22 23:09:55813void LayerTreeHostImpl::drawLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14814{
[email protected]96baf3e2012-10-22 23:09:55815 TRACE_EVENT0("cc", "LayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04816 DCHECK(canDraw());
817 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14818
819 // FIXME: use the frame begin time from the overall compositor scheduler.
820 // This value is currently inaccessible because it is up in Chromium's
821 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21822 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14823
824 if (m_settings.showDebugRects())
[email protected]4d8804e2012-11-15 01:51:10825 m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, frame.nonOccludingScreenSpaceRects, settings());
[email protected]94f206c12012-08-25 00:09:14826
827 // Because the contents of the HUD depend on everything else in the frame, the contents
828 // of its texture are updated as the last thing before the frame is drawn.
829 if (m_hudLayerImpl)
830 m_hudLayerImpl->updateHudTexture(m_resourceProvider.get());
831
832 m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
833
834 // Once a RenderPass has been drawn, its damage should be cleared in
835 // case the RenderPass will be reused next frame.
836 for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
[email protected]f57bbc02012-11-21 07:02:15837 frame.renderPasses[i]->damage_rect = gfx::RectF();
[email protected]94f206c12012-08-25 00:09:14838
839 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
840 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
841 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
842 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
843}
844
[email protected]96baf3e2012-10-22 23:09:55845void LayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14846{
847 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
848 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52849
850 // Once all layers have been drawn, pending texture uploads should no
851 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09852 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14853}
854
[email protected]96baf3e2012-10-22 23:09:55855void LayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14856{
857 if (m_renderer)
858 m_renderer->finish();
859}
860
[email protected]96baf3e2012-10-22 23:09:55861bool LayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14862{
863 return m_renderer && m_renderer->isContextLost();
864}
865
[email protected]96baf3e2012-10-22 23:09:55866const RendererCapabilities& LayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14867{
868 return m_renderer->capabilities();
869}
870
[email protected]96baf3e2012-10-22 23:09:55871bool LayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14872{
[email protected]1d993172012-10-18 18:15:04873 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14874
875 m_fpsCounter->markEndOfFrame();
876 return m_renderer->swapBuffers();
877}
878
[email protected]aad0a0072012-11-01 18:15:58879const gfx::Size& LayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10880{
881 return m_deviceViewportSize;
882}
883
[email protected]96baf3e2012-10-22 23:09:55884const LayerTreeSettings& LayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10885{
886 return m_settings;
887}
888
[email protected]96baf3e2012-10-22 23:09:55889void LayerTreeHostImpl::didLoseContext()
[email protected]94f206c12012-08-25 00:09:14890{
891 m_client->didLoseContextOnImplThread();
892}
893
[email protected]96baf3e2012-10-22 23:09:55894void LayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14895{
896 m_client->onSwapBuffersCompleteOnImplThread();
897}
898
[email protected]aad0a0072012-11-01 18:15:58899void LayerTreeHostImpl::readback(void* pixels, const gfx::Rect& rect)
[email protected]94f206c12012-08-25 00:09:14900{
[email protected]1d993172012-10-18 18:15:04901 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14902 m_renderer->getFramebufferPixels(pixels, rect);
903}
904
[email protected]96baf3e2012-10-22 23:09:55905static LayerImpl* findRootScrollLayer(LayerImpl* layer)
[email protected]94f206c12012-08-25 00:09:14906{
907 if (!layer)
908 return 0;
909
910 if (layer->scrollable())
911 return layer;
912
913 for (size_t i = 0; i < layer->children().size(); ++i) {
[email protected]96baf3e2012-10-22 23:09:55914 LayerImpl* found = findRootScrollLayer(layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:14915 if (found)
916 return found;
917 }
918
919 return 0;
920}
921
922// Content layers can be either directly scrollable or contained in an outer
923// scrolling layer which applies the scroll transform. Given a content layer,
924// this function returns the associated scroll layer if any.
[email protected]96baf3e2012-10-22 23:09:55925static LayerImpl* findScrollLayerForContentLayer(LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14926{
927 if (!layerImpl)
928 return 0;
929
930 if (layerImpl->scrollable())
931 return layerImpl;
932
933 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
934 return layerImpl->parent();
935
936 return 0;
937}
938
[email protected]96baf3e2012-10-22 23:09:55939void LayerTreeHostImpl::setRootLayer(scoped_ptr<LayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:14940{
[email protected]e0bd43a2012-10-12 16:54:21941 m_rootLayerImpl = layer.Pass();
[email protected]94f206c12012-08-25 00:09:14942 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
943 m_currentlyScrollingLayerImpl = 0;
944
945 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
[email protected]96baf3e2012-10-22 23:09:55946 m_currentlyScrollingLayerImpl = LayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
[email protected]94f206c12012-08-25 00:09:14947
948 m_scrollingLayerIdFromPreviousTree = -1;
[email protected]8db2213c2012-09-05 22:08:21949
950 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14951}
952
[email protected]96baf3e2012-10-22 23:09:55953scoped_ptr<LayerImpl> LayerTreeHostImpl::detachLayerTree()
[email protected]94f206c12012-08-25 00:09:14954{
955 // Clear all data structures that have direct references to the layer tree.
956 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
957 m_currentlyScrollingLayerImpl = 0;
958 m_renderSurfaceLayerList.clear();
959
[email protected]e0bd43a2012-10-12 16:54:21960 return m_rootLayerImpl.Pass();
[email protected]94f206c12012-08-25 00:09:14961}
962
[email protected]96baf3e2012-10-22 23:09:55963void LayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14964{
[email protected]61de5812012-11-08 07:03:44965 DCHECK(m_proxy->isImplThread());
[email protected]94f206c12012-08-25 00:09:14966
967 if (m_visible == visible)
968 return;
969 m_visible = visible;
970 didVisibilityChange(this, m_visible);
[email protected]a0a00842012-10-22 22:50:28971 enforceManagedMemoryPolicy(m_managedMemoryPolicy);
[email protected]94f206c12012-08-25 00:09:14972
973 if (!m_renderer)
974 return;
975
976 m_renderer->setVisible(visible);
977
978 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
979}
980
[email protected]96baf3e2012-10-22 23:09:55981bool LayerTreeHostImpl::initializeRenderer(scoped_ptr<GraphicsContext> context)
[email protected]94f206c12012-08-25 00:09:14982{
[email protected]be3181652012-09-25 13:02:13983 // Since we will create a new resource provider, we cannot continue to use
984 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
985 // before we destroy the old resource provider.
[email protected]94f206c12012-08-25 00:09:14986 if (m_rootLayerImpl) {
987 clearRenderSurfaces();
988 sendDidLoseContextRecursive(m_rootLayerImpl.get());
989 }
[email protected]be3181652012-09-25 13:02:13990 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47991 m_renderer.reset();
[email protected]8947cbe2012-11-28 05:27:43992 m_tileManager.reset();
[email protected]a7aa5562012-10-17 14:12:44993 m_resourceProvider.reset();
[email protected]e28efacd2012-10-06 17:07:49994 m_context.reset();
[email protected]94f206c12012-08-25 00:09:14995
[email protected]be3181652012-09-25 13:02:13996 if (!context->bindToClient(this))
997 return false;
998
[email protected]96baf3e2012-10-22 23:09:55999 scoped_ptr<ResourceProvider> resourceProvider = ResourceProvider::create(context.get());
[email protected]be3181652012-09-25 13:02:131000 if (!resourceProvider)
1001 return false;
1002
[email protected]8947cbe2012-11-28 05:27:431003 if (m_settings.implSidePainting)
1004 m_tileManager.reset(new TileManager(this, resourceProvider.get()));
1005
[email protected]be3181652012-09-25 13:02:131006 if (context->context3D())
[email protected]96baf3e2012-10-22 23:09:551007 m_renderer = GLRenderer::create(this, resourceProvider.get());
[email protected]be3181652012-09-25 13:02:131008 else if (context->softwareDevice())
[email protected]96baf3e2012-10-22 23:09:551009 m_renderer = SoftwareRenderer::create(this, resourceProvider.get(), context->softwareDevice());
[email protected]be3181652012-09-25 13:02:131010 if (!m_renderer)
1011 return false;
1012
[email protected]a7aa5562012-10-17 14:12:441013 m_resourceProvider = resourceProvider.Pass();
[email protected]e28efacd2012-10-06 17:07:491014 m_context = context.Pass();
[email protected]94f206c12012-08-25 00:09:141015
[email protected]be3181652012-09-25 13:02:131016 if (!m_visible)
1017 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:141018
[email protected]8db2213c2012-09-05 22:08:211019 m_client->onCanDrawStateChanged(canDraw());
1020
[email protected]be3181652012-09-25 13:02:131021 return true;
[email protected]94f206c12012-08-25 00:09:141022}
1023
[email protected]96baf3e2012-10-22 23:09:551024void LayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:091025{
1026 m_contentsTexturesPurged = true;
1027 m_client->onCanDrawStateChanged(canDraw());
1028}
1029
[email protected]96baf3e2012-10-22 23:09:551030void LayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:211031{
1032 m_contentsTexturesPurged = false;
1033 m_client->onCanDrawStateChanged(canDraw());
1034}
1035
[email protected]aad0a0072012-11-01 18:15:581036void LayerTreeHostImpl::setViewportSize(const gfx::Size& layoutViewportSize, const gfx::Size& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:141037{
1038 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
1039 return;
1040
1041 m_layoutViewportSize = layoutViewportSize;
1042 m_deviceViewportSize = deviceViewportSize;
1043
[email protected]c9c1ebe2012-11-05 20:46:131044 m_pinchZoomViewport.setLayoutViewportSize(layoutViewportSize);
[email protected]1c0c9bc2012-10-08 22:41:481045
[email protected]c9c1ebe2012-11-05 20:46:131046 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141047
1048 if (m_renderer)
1049 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:211050
1051 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:141052}
1053
[email protected]96baf3e2012-10-22 23:09:551054static void adjustScrollsForPageScaleChange(LayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:141055{
1056 if (!layerImpl)
1057 return;
1058
1059 if (layerImpl->scrollable()) {
1060 // We need to convert impl-side scroll deltas to pageScale space.
[email protected]c9c1ebe2012-11-05 20:46:131061 gfx::Vector2dF scrollDelta = layerImpl->scrollDelta();
1062 scrollDelta.Scale(pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141063 layerImpl->setScrollDelta(scrollDelta);
1064 }
1065
1066 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031067 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:141068}
1069
[email protected]96baf3e2012-10-22 23:09:551070void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:141071{
1072 if (deviceScaleFactor == m_deviceScaleFactor)
1073 return;
1074 m_deviceScaleFactor = deviceScaleFactor;
[email protected]e39bf212012-11-22 21:04:031075 m_pinchZoomViewport.setDeviceScaleFactor(m_deviceScaleFactor);
[email protected]c0dd24c2012-08-30 23:25:271076
[email protected]c9c1ebe2012-11-05 20:46:131077 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141078}
1079
[email protected]96baf3e2012-10-22 23:09:551080float LayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:141081{
[email protected]1c0c9bc2012-10-08 22:41:481082 return m_pinchZoomViewport.pageScaleFactor();
1083}
[email protected]94f206c12012-08-25 00:09:141084
[email protected]96baf3e2012-10-22 23:09:551085void LayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:481086{
1087 if (!pageScaleFactor)
1088 return;
[email protected]94f206c12012-08-25 00:09:141089
[email protected]1c0c9bc2012-10-08 22:41:481090 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
1091 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:141092
[email protected]9bdcfd642012-11-14 21:24:261093 if (!m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481094 if (pageScaleChange != 1)
1095 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
1096 }
[email protected]94f206c12012-08-25 00:09:141097
1098 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:481099 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
1100 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:141101}
1102
[email protected]96baf3e2012-10-22 23:09:551103void LayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:141104{
[email protected]1c0c9bc2012-10-08 22:41:481105 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:141106
[email protected]c9c1ebe2012-11-05 20:46:131107 updateMaxScrollOffset();
[email protected]94f206c12012-08-25 00:09:141108}
1109
[email protected]c9c1ebe2012-11-05 20:46:131110void LayerTreeHostImpl::updateMaxScrollOffset()
[email protected]94f206c12012-08-25 00:09:141111{
1112 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
1113 return;
1114
[email protected]aad0a0072012-11-01 18:15:581115 gfx::SizeF viewBounds = m_deviceViewportSize;
[email protected]96baf3e2012-10-22 23:09:551116 if (LayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141117 // Compensate for non-overlay scrollbars.
[email protected]01a15a72012-11-10 09:34:281118 if (clipLayer->masksToBounds())
1119 viewBounds = gfx::ScaleSize(clipLayer->bounds(), m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141120 }
[email protected]94f206c12012-08-25 00:09:141121
[email protected]aad0a0072012-11-01 18:15:581122 gfx::Size contentBounds = contentSize();
[email protected]9bdcfd642012-11-14 21:24:261123 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481124 // Pinch with pageScale scrolls entirely in layout space. contentSize
1125 // returns the bounds including the page scale factor, so calculate the
1126 // pre page-scale layout size here.
1127 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
[email protected]aad0a0072012-11-01 18:15:581128 contentBounds.set_width(contentBounds.width() / pageScaleFactor);
1129 contentBounds.set_height(contentBounds.height() / pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:481130 } else {
[email protected]01a15a72012-11-10 09:34:281131 viewBounds.Scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:481132 }
1133
[email protected]0eef4b882012-11-20 20:28:071134 gfx::Vector2dF maxScroll = gfx::Rect(contentBounds).bottom_right() - gfx::RectF(viewBounds).bottom_right();
[email protected]c9c1ebe2012-11-05 20:46:131135 maxScroll.Scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:481136
[email protected]94f206c12012-08-25 00:09:141137 // The viewport may be larger than the contents in some cases, such as
1138 // having a vertical scrollbar but no horizontal overflow.
[email protected]fe07b642012-11-10 00:07:591139 maxScroll.ClampToMin(gfx::Vector2dF());
[email protected]94f206c12012-08-25 00:09:141140
[email protected]c9c1ebe2012-11-05 20:46:131141 m_rootScrollLayerImpl->setMaxScrollOffset(gfx::ToFlooredVector2d(maxScroll));
[email protected]94f206c12012-08-25 00:09:141142}
1143
[email protected]96baf3e2012-10-22 23:09:551144void LayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:141145{
1146 m_client->setNeedsRedrawOnImplThread();
1147}
1148
[email protected]96baf3e2012-10-22 23:09:551149bool LayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:141150{
1151 if (!m_rootLayerImpl)
1152 return false;
1153 if (!m_renderer)
1154 return false;
1155
1156 // We need both a non-empty render surface layer list and a root render
1157 // surface to be able to iterate over the visible layers.
1158 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
1159 return true;
1160
1161 // If we are called after setRootLayer() but before prepareToDraw(), we need
1162 // to recalculate the visible layers. This prevents being unable to scroll
1163 // during part of a commit.
1164 m_renderSurfaceLayerList.clear();
1165 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
1166
1167 return m_renderSurfaceLayerList.size();
1168}
1169
[email protected]c9c1ebe2012-11-05 20:46:131170InputHandlerClient::ScrollStatus LayerTreeHostImpl::scrollBegin(gfx::Point viewportPoint, InputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141171{
[email protected]96baf3e2012-10-22 23:09:551172 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141173
[email protected]1d993172012-10-18 18:15:041174 DCHECK(!m_currentlyScrollingLayerImpl);
[email protected]94f206c12012-08-25 00:09:141175 clearCurrentlyScrollingLayer();
1176
1177 if (!ensureRenderSurfaceLayerList())
1178 return ScrollIgnored;
1179
[email protected]faf56352012-11-09 21:44:131180 gfx::PointF deviceViewportPoint = gfx::ScalePoint(viewportPoint, m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141181
1182 // First find out which layer was hit from the saved list of visible layers
1183 // in the most recent frame.
[email protected]96baf3e2012-10-22 23:09:551184 LayerImpl* layerImpl = LayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:141185
1186 // Walk up the hierarchy and look for a scrollable layer.
[email protected]96baf3e2012-10-22 23:09:551187 LayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141188 for (; layerImpl; layerImpl = layerImpl->parent()) {
1189 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271190 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1191 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141192 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271193 }
[email protected]94f206c12012-08-25 00:09:141194
[email protected]96baf3e2012-10-22 23:09:551195 LayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141196 if (!scrollLayerImpl)
1197 continue;
1198
[email protected]31bfe272012-10-19 18:49:521199 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141200
1201 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271202 if (status == ScrollOnMainThread) {
1203 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141204 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271205 }
[email protected]94f206c12012-08-25 00:09:141206
1207 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1208 potentiallyScrollingLayerImpl = scrollLayerImpl;
1209 }
1210
1211 if (potentiallyScrollingLayerImpl) {
1212 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
[email protected]31bfe272012-10-19 18:49:521213 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141214 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1215 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521216 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271217 m_numImplThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141218 return ScrollStarted;
1219 }
1220 return ScrollIgnored;
1221}
1222
[email protected]c9c1ebe2012-11-05 20:46:131223static gfx::Vector2dF scrollLayerWithViewportSpaceDelta(PinchZoomViewport* viewport, LayerImpl& layerImpl, float scaleFromViewportToScreenSpace, gfx::PointF viewportPoint, gfx::Vector2dF viewportDelta)
[email protected]94f206c12012-08-25 00:09:141224{
1225 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1226 // test in the first place.
[email protected]c8686a02012-11-27 08:29:001227 DCHECK(layerImpl.screenSpaceTransform().IsInvertible());
1228 gfx::Transform inverseScreenSpaceTransform = MathUtil::inverse(layerImpl.screenSpaceTransform());
[email protected]94f206c12012-08-25 00:09:141229
[email protected]faf56352012-11-09 21:44:131230 gfx::PointF screenSpacePoint = gfx::ScalePoint(viewportPoint, scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521231
[email protected]c9c1ebe2012-11-05 20:46:131232 gfx::Vector2dF screenSpaceDelta = viewportDelta;
1233 screenSpaceDelta.Scale(scaleFromViewportToScreenSpace);
[email protected]31bfe272012-10-19 18:49:521234
[email protected]94f206c12012-08-25 00:09:141235 // First project the scroll start and end points to local layer space to find the scroll delta
1236 // in layer coordinates.
1237 bool startClipped, endClipped;
[email protected]d455d552012-11-02 00:19:061238 gfx::PointF screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1239 gfx::PointF localStartPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1240 gfx::PointF localEndPoint = MathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141241
1242 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041243 DCHECK(!startClipped);
1244 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141245 if (startClipped || endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131246 return gfx::Vector2dF();
[email protected]94f206c12012-08-25 00:09:141247
[email protected]31bfe272012-10-19 18:49:521248 // 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:581249 float widthScale = 1 / layerImpl.contentsScaleX();
1250 float heightScale = 1 / layerImpl.contentsScaleY();
[email protected]faf56352012-11-09 21:44:131251 localStartPoint.Scale(widthScale, heightScale);
1252 localEndPoint.Scale(widthScale, heightScale);
[email protected]31bfe272012-10-19 18:49:521253
[email protected]94f206c12012-08-25 00:09:141254 // Apply the scroll delta.
[email protected]c9c1ebe2012-11-05 20:46:131255 gfx::Vector2dF previousDelta = layerImpl.scrollDelta();
1256 gfx::Vector2dF unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
[email protected]1c0c9bc2012-10-08 22:41:481257
[email protected]aeaa50a2012-11-21 20:12:371258 gfx::Vector2dF viewportAppliedPan;
[email protected]1c0c9bc2012-10-08 22:41:481259 if (viewport)
[email protected]aeaa50a2012-11-21 20:12:371260 viewportAppliedPan = unscrolled - viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141261
[email protected]31bfe272012-10-19 18:49:521262 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]aeaa50a2012-11-21 20:12:371263 gfx::PointF actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() + viewportAppliedPan - previousDelta;
[email protected]faf56352012-11-09 21:44:131264 gfx::PointF actualLocalContentEndPoint = gfx::ScalePoint(actualLocalEndPoint, 1 / widthScale, 1 / heightScale);
[email protected]31bfe272012-10-19 18:49:521265
1266 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]d455d552012-11-02 00:19:061267 gfx::PointF actualScreenSpaceEndPoint = MathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041268 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141269 if (endClipped)
[email protected]c9c1ebe2012-11-05 20:46:131270 return gfx::Vector2dF();
[email protected]faf56352012-11-09 21:44:131271 gfx::PointF actualViewportEndPoint = gfx::ScalePoint(actualScreenSpaceEndPoint, 1 / scaleFromViewportToScreenSpace);
[email protected]c9c1ebe2012-11-05 20:46:131272 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141273}
1274
[email protected]c9c1ebe2012-11-05 20:46:131275static gfx::Vector2dF scrollLayerWithLocalDelta(LayerImpl& layerImpl, gfx::Vector2dF localDelta)
[email protected]94f206c12012-08-25 00:09:141276{
[email protected]c9c1ebe2012-11-05 20:46:131277 gfx::Vector2dF previousDelta(layerImpl.scrollDelta());
[email protected]94f206c12012-08-25 00:09:141278 layerImpl.scrollBy(localDelta);
1279 return layerImpl.scrollDelta() - previousDelta;
1280}
1281
[email protected]a9710962012-11-14 20:11:021282bool LayerTreeHostImpl::scrollBy(const gfx::Point& viewportPoint,
1283 const gfx::Vector2d& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141284{
[email protected]96baf3e2012-10-22 23:09:551285 TRACE_EVENT0("cc", "LayerTreeHostImpl::scrollBy");
[email protected]94f206c12012-08-25 00:09:141286 if (!m_currentlyScrollingLayerImpl)
[email protected]a9710962012-11-14 20:11:021287 return false;
[email protected]94f206c12012-08-25 00:09:141288
[email protected]c9c1ebe2012-11-05 20:46:131289 gfx::Vector2dF pendingDelta = scrollDelta;
[email protected]94f206c12012-08-25 00:09:141290
[email protected]96baf3e2012-10-22 23:09:551291 for (LayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141292 if (!layerImpl->scrollable())
1293 continue;
1294
[email protected]96baf3e2012-10-22 23:09:551295 PinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
[email protected]c9c1ebe2012-11-05 20:46:131296 gfx::Vector2dF appliedDelta;
[email protected]31bfe272012-10-19 18:49:521297 if (m_scrollDeltaIsInViewportSpace) {
1298 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1299 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1300 } else
[email protected]94f206c12012-08-25 00:09:141301 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1302
1303 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381304 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]c9c1ebe2012-11-05 20:46:131305 if (appliedDelta.LengthSquared() < moveThresholdSquared)
[email protected]94f206c12012-08-25 00:09:141306 continue;
1307
1308 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1309 // to scroll just one layer in one direction without affecting any of its parents.
1310 float angleThreshold = 45;
[email protected]96baf3e2012-10-22 23:09:551311 if (MathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]c9c1ebe2012-11-05 20:46:131312 pendingDelta = gfx::Vector2d();
[email protected]94f206c12012-08-25 00:09:141313 break;
1314 }
1315
1316 // Allow further movement only on an axis perpendicular to the direction in which the layer
1317 // moved.
[email protected]c9c1ebe2012-11-05 20:46:131318 gfx::Vector2dF perpendicularAxis(-appliedDelta.y(), appliedDelta.x());
[email protected]96baf3e2012-10-22 23:09:551319 pendingDelta = MathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141320
[email protected]c9c1ebe2012-11-05 20:46:131321 if (gfx::ToFlooredVector2d(pendingDelta).IsZero())
[email protected]94f206c12012-08-25 00:09:141322 break;
1323 }
1324
[email protected]c9c1ebe2012-11-05 20:46:131325 if (!scrollDelta.IsZero() && gfx::ToFlooredVector2d(pendingDelta).IsZero()) {
[email protected]94f206c12012-08-25 00:09:141326 m_client->setNeedsCommitOnImplThread();
1327 m_client->setNeedsRedrawOnImplThread();
[email protected]a9710962012-11-14 20:11:021328 return true;
[email protected]94f206c12012-08-25 00:09:141329 }
[email protected]a9710962012-11-14 20:11:021330 return false;
[email protected]94f206c12012-08-25 00:09:141331}
1332
[email protected]96baf3e2012-10-22 23:09:551333void LayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141334{
1335 m_currentlyScrollingLayerImpl = 0;
1336 m_scrollingLayerIdFromPreviousTree = -1;
1337}
1338
[email protected]96baf3e2012-10-22 23:09:551339void LayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141340{
1341 clearCurrentlyScrollingLayer();
1342}
1343
[email protected]96baf3e2012-10-22 23:09:551344void LayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141345{
1346 m_pinchGestureActive = true;
[email protected]c9c1ebe2012-11-05 20:46:131347 m_previousPinchAnchor = gfx::Point();
[email protected]94f206c12012-08-25 00:09:141348
1349 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1350 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
1351}
1352
[email protected]c9c1ebe2012-11-05 20:46:131353void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor)
[email protected]94f206c12012-08-25 00:09:141354{
[email protected]96baf3e2012-10-22 23:09:551355 TRACE_EVENT0("cc", "LayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141356
1357 if (!m_rootScrollLayerImpl)
1358 return;
1359
[email protected]94f206c12012-08-25 00:09:141360 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1361 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481362 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]c77745d2012-11-20 04:11:571363 gfx::PointF previousScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]1c0c9bc2012-10-08 22:41:481364 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1365 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
[email protected]faf56352012-11-09 21:44:131366 gfx::PointF newScaleAnchor = gfx::ScalePoint(anchor, 1 / pageScaleDelta);
[email protected]c9c1ebe2012-11-05 20:46:131367 gfx::Vector2dF move = previousScaleAnchor - newScaleAnchor;
[email protected]94f206c12012-08-25 00:09:141368
1369 m_previousPinchAnchor = anchor;
1370
[email protected]9bdcfd642012-11-14 21:24:261371 if (m_settings.pageScalePinchZoomEnabled) {
[email protected]1c0c9bc2012-10-08 22:41:481372 // Compute the application of the delta with respect to the current page zoom of the page.
[email protected]e39bf212012-11-22 21:04:031373 move.Scale(1 / m_pinchZoomViewport.pageScaleFactor());
[email protected]1c0c9bc2012-10-08 22:41:481374 }
1375
[email protected]9bdcfd642012-11-14 21:24:261376 gfx::Vector2dF scrollOverflow = m_settings.pageScalePinchZoomEnabled ? m_pinchZoomViewport.applyScroll(move) : move;
[email protected]c9c1ebe2012-11-05 20:46:131377 m_rootScrollLayerImpl->scrollBy(scrollOverflow);
[email protected]94f206c12012-08-25 00:09:141378
1379 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1380 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
1381
1382 m_client->setNeedsCommitOnImplThread();
1383 m_client->setNeedsRedrawOnImplThread();
1384}
1385
[email protected]96baf3e2012-10-22 23:09:551386void LayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141387{
1388 m_pinchGestureActive = false;
1389
1390 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1391 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
1392
1393 m_client->setNeedsCommitOnImplThread();
1394}
1395
[email protected]96baf3e2012-10-22 23:09:551396void LayerTreeHostImpl::computeDoubleTapZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141397{
[email protected]f6250742012-11-09 04:46:561398 gfx::Vector2dF scaledScrollOffset = m_pageScaleAnimation->targetScrollOffset();
[email protected]9bdcfd642012-11-14 21:24:261399 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:561400 scaledScrollOffset.Scale(m_pinchZoomViewport.pageScaleFactor());
1401 makeScrollAndScaleSet(scrollInfo, ToFlooredVector2d(scaledScrollOffset), m_pageScaleAnimation->targetPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141402}
1403
[email protected]96baf3e2012-10-22 23:09:551404void LayerTreeHostImpl::computePinchZoomDeltas(ScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141405{
1406 if (!m_rootScrollLayerImpl)
1407 return;
1408
1409 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1410 // significant amount. This also ensures only one fake delta set will be
1411 // sent.
[email protected]23bbb412012-08-30 20:03:381412 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481413 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141414 return;
1415
1416 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1417 // out from the anchor point.
[email protected]c9c1ebe2012-11-05 20:46:131418 gfx::Vector2dF scrollBegin = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
1419 scrollBegin.Scale(m_pinchZoomViewport.pageScaleDelta());
[email protected]1c0c9bc2012-10-08 22:41:481420 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1421 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]01a15a72012-11-10 09:34:281422 gfx::SizeF scaledContentsSize = gfx::ScaleSize(contentSize(), pageScaleDeltaToSend);
[email protected]94f206c12012-08-25 00:09:141423
[email protected]c9c1ebe2012-11-05 20:46:131424 gfx::Vector2d anchorOffset = m_previousPinchAnchor.OffsetFromOrigin();
1425 gfx::Vector2dF scrollEnd = scrollBegin + anchorOffset;
1426 scrollEnd.Scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
1427 scrollEnd -= anchorOffset;
[email protected]0eef4b882012-11-20 20:28:071428 scrollEnd.ClampToMax(gfx::RectF(scaledContentsSize).bottom_right() - gfx::Rect(m_deviceViewportSize).bottom_right());
[email protected]fe07b642012-11-10 00:07:591429 scrollEnd.ClampToMin(gfx::Vector2d());
[email protected]c9c1ebe2012-11-05 20:46:131430 scrollEnd.Scale(1 / pageScaleDeltaToSend);
1431 scrollEnd.Scale(m_deviceScaleFactor);
[email protected]94f206c12012-08-25 00:09:141432
[email protected]c9c1ebe2012-11-05 20:46:131433 makeScrollAndScaleSet(scrollInfo, gfx::ToRoundedVector2d(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141434}
1435
[email protected]c9c1ebe2012-11-05 20:46:131436void LayerTreeHostImpl::makeScrollAndScaleSet(ScrollAndScaleSet* scrollInfo, gfx::Vector2d scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141437{
1438 if (!m_rootScrollLayerImpl)
1439 return;
1440
[email protected]96baf3e2012-10-22 23:09:551441 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141442 scroll.layerId = m_rootScrollLayerImpl->id();
[email protected]c9c1ebe2012-11-05 20:46:131443 scroll.scrollDelta = scrollOffset - m_rootScrollLayerImpl->scrollOffset();
[email protected]787465c2012-10-29 01:12:271444 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141445 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481446 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1447 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141448}
1449
[email protected]96baf3e2012-10-22 23:09:551450static void collectScrollDeltas(ScrollAndScaleSet* scrollInfo, LayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141451{
1452 if (!layerImpl)
1453 return;
1454
[email protected]c9c1ebe2012-11-05 20:46:131455 if (!layerImpl->scrollDelta().IsZero()) {
1456 gfx::Vector2d scrollDelta = gfx::ToFlooredVector2d(layerImpl->scrollDelta());
[email protected]96baf3e2012-10-22 23:09:551457 LayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141458 scroll.layerId = layerImpl->id();
1459 scroll.scrollDelta = scrollDelta;
[email protected]787465c2012-10-29 01:12:271460 scrollInfo->scrolls.push_back(scroll);
[email protected]94f206c12012-08-25 00:09:141461 layerImpl->setSentScrollDelta(scrollDelta);
1462 }
1463
1464 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031465 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141466}
1467
[email protected]96baf3e2012-10-22 23:09:551468scoped_ptr<ScrollAndScaleSet> LayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141469{
[email protected]96baf3e2012-10-22 23:09:551470 scoped_ptr<ScrollAndScaleSet> scrollInfo(new ScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141471
1472 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481473 scrollInfo->pageScaleDelta = 1;
1474 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]f6250742012-11-09 04:46:561475 // FIXME(aelias): Make pinch-zoom painting optimization compatible with
[email protected]1c0c9bc2012-10-08 22:41:481476 // compositor-side scaling.
[email protected]9bdcfd642012-11-14 21:24:261477 if (!m_settings.pageScalePinchZoomEnabled && m_pinchGestureActive)
[email protected]f6250742012-11-09 04:46:561478 computePinchZoomDeltas(scrollInfo.get());
1479 else if (m_pageScaleAnimation.get())
1480 computeDoubleTapZoomDeltas(scrollInfo.get());
[email protected]a9f4bf22012-10-11 23:39:211481 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141482 }
1483
1484 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
[email protected]1c0c9bc2012-10-08 22:41:481485 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1486 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141487
[email protected]a9f4bf22012-10-11 23:39:211488 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141489}
1490
[email protected]c8686a02012-11-27 08:29:001491gfx::Transform LayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481492{
[email protected]9bdcfd642012-11-14 21:24:261493 return m_pinchZoomViewport.implTransform(m_settings.pageScalePinchZoomEnabled);
[email protected]1c0c9bc2012-10-08 22:41:481494}
1495
[email protected]96baf3e2012-10-22 23:09:551496void LayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141497{
1498 if (m_rootLayerImpl) {
[email protected]96baf3e2012-10-22 23:09:551499 RenderSurfaceImpl* renderSurface = m_rootLayerImpl->renderSurface();
[email protected]94f206c12012-08-25 00:09:141500 if (renderSurface)
1501 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1502 }
1503}
1504
[email protected]30faac92012-10-29 00:06:291505void LayerTreeHostImpl::animatePageScale(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141506{
1507 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1508 return;
1509
[email protected]30faac92012-10-29 00:06:291510 double monotonicTime = (time - base::TimeTicks()).InSecondsF();
[email protected]c9c1ebe2012-11-05 20:46:131511 gfx::Vector2dF scrollTotal = m_rootScrollLayerImpl->scrollOffset() + m_rootScrollLayerImpl->scrollDelta();
[email protected]94f206c12012-08-25 00:09:141512
[email protected]f6250742012-11-09 04:46:561513 setPageScaleDelta(m_pageScaleAnimation->pageScaleFactorAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]c9c1ebe2012-11-05 20:46:131514 gfx::Vector2dF nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]f6250742012-11-09 04:46:561515
[email protected]9bdcfd642012-11-14 21:24:261516 if (!m_settings.pageScalePinchZoomEnabled)
[email protected]f6250742012-11-09 04:46:561517 nextScroll.Scale(m_pinchZoomViewport.pageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141518 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1519 m_client->setNeedsRedrawOnImplThread();
1520
1521 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451522 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141523 m_client->setNeedsCommitOnImplThread();
1524 }
1525}
1526
[email protected]30faac92012-10-29 00:06:291527void LayerTreeHostImpl::animateLayers(base::TimeTicks monotonicTime, base::Time wallClockTime)
[email protected]94f206c12012-08-25 00:09:141528{
[email protected]9bdcfd642012-11-14 21:24:261529 if (!m_settings.acceleratedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl)
[email protected]94f206c12012-08-25 00:09:141530 return;
1531
[email protected]96baf3e2012-10-22 23:09:551532 TRACE_EVENT0("cc", "LayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141533
[email protected]96baf3e2012-10-22 23:09:551534 scoped_ptr<AnimationEventsVector> events(make_scoped_ptr(new AnimationEventsVector));
[email protected]94f206c12012-08-25 00:09:141535
1536 bool didAnimate = false;
1537 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1538
[email protected]d3143c732012-10-05 19:17:591539 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571540 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141541
1542 if (didAnimate)
1543 m_client->setNeedsRedrawOnImplThread();
1544
1545 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1546}
1547
[email protected]96baf3e2012-10-22 23:09:551548base::TimeDelta LayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141549{
[email protected]4481ddb622012-09-20 16:33:471550 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141551}
1552
[email protected]96baf3e2012-10-22 23:09:551553void LayerTreeHostImpl::sendDidLoseContextRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141554{
[email protected]1d993172012-10-18 18:15:041555 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141556 current->didLoseContext();
1557 if (current->maskLayer())
1558 sendDidLoseContextRecursive(current->maskLayer());
1559 if (current->replicaLayer())
1560 sendDidLoseContextRecursive(current->replicaLayer());
1561 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031562 sendDidLoseContextRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141563}
1564
[email protected]96baf3e2012-10-22 23:09:551565static void clearRenderSurfacesOnLayerImplRecursive(LayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141566{
[email protected]1d993172012-10-18 18:15:041567 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141568 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]96baf3e2012-10-22 23:09:551569 clearRenderSurfacesOnLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141570 current->clearRenderSurface();
1571}
1572
[email protected]96baf3e2012-10-22 23:09:551573void LayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141574{
[email protected]96baf3e2012-10-22 23:09:551575 clearRenderSurfacesOnLayerImplRecursive(m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141576 m_renderSurfaceLayerList.clear();
1577}
1578
[email protected]96baf3e2012-10-22 23:09:551579std::string LayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141580{
[email protected]515e8d232012-09-10 19:15:271581 std::string str;
[email protected]94f206c12012-08-25 00:09:141582 if (m_rootLayerImpl) {
[email protected]515e8d232012-09-10 19:15:271583 str = m_rootLayerImpl->layerTreeAsText();
1584 str += "RenderSurfaces:\n";
1585 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141586 }
[email protected]515e8d232012-09-10 19:15:271587 return str;
[email protected]94f206c12012-08-25 00:09:141588}
1589
[email protected]96baf3e2012-10-22 23:09:551590void LayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const LayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141591{
1592 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271593 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141594
1595 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031596 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141597}
1598
[email protected]96baf3e2012-10-22 23:09:551599int LayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141600{
1601 return fpsCounter()->currentFrameNumber();
1602}
1603
[email protected]96baf3e2012-10-22 23:09:551604void LayerTreeHostImpl::renderingStats(RenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141605{
[email protected]8b9af6b2012-09-27 00:36:361606 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1607 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271608 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1609 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]9c2be6a2012-11-27 19:16:101610 stats->numLayersInLayerTree = m_cumulativeNumLayersInLayerTree;
[email protected]94f206c12012-08-25 00:09:141611}
1612
[email protected]30faac92012-10-29 00:06:291613void LayerTreeHostImpl::animateScrollbars(base::TimeTicks time)
[email protected]94f206c12012-08-25 00:09:141614{
[email protected]30faac92012-10-29 00:06:291615 animateScrollbarsRecursive(m_rootLayerImpl.get(), 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]d3143c732012-10-05 19:17:591632} // namespace cc