blob: 422fa65892f1b0e85f3409ff0418fdf7caa889e8 [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
5#include "config.h"
6
7#include "CCLayerTreeHostImpl.h"
8
[email protected]89228202012-08-29 03:20:309#include "CCAppendQuadsData.h"
[email protected]94f206c12012-08-25 00:09:1410#include "CCDamageTracker.h"
11#include "CCDebugRectHistory.h"
12#include "CCDelayBasedTimeSource.h"
13#include "CCFontAtlas.h"
14#include "CCFrameRateCounter.h"
15#include "CCHeadsUpDisplayLayerImpl.h"
16#include "CCLayerIterator.h"
17#include "CCLayerTreeHost.h"
18#include "CCLayerTreeHostCommon.h"
[email protected]1c0088f2012-10-17 00:29:3019#include "CCMathUtil.h"
[email protected]94f206c12012-08-25 00:09:1420#include "CCOverdrawMetrics.h"
21#include "CCPageScaleAnimation.h"
22#include "CCPrioritizedTextureManager.h"
23#include "CCRenderPassDrawQuad.h"
[email protected]ad5d1422012-10-19 13:40:2924#include "base/basictypes.h"
[email protected]4456eee22012-10-19 18:16:3825#include "base/debug/trace_event.h"
[email protected]c4040a522012-10-21 15:01:4026#include "cc/gl_renderer.h"
27#include "cc/rendering_stats.h"
28#include "cc/scrollbar_animation_controller.h"
29#include "cc/scrollbar_layer_impl.h"
30#include "cc/settings.h"
[email protected]4456eee22012-10-19 18:16:3831#include "cc/single_thread_proxy.h"
[email protected]c4040a522012-10-21 15:01:4032#include "cc/software_renderer.h"
[email protected]a8461d82012-10-16 21:11:1433#include "cc/texture_uploader.h"
[email protected]94f206c12012-08-25 00:09:1434#include <wtf/CurrentTime.h>
[email protected]f8ad8342012-09-27 20:07:0235#include <algorithm>
[email protected]94f206c12012-08-25 00:09:1436
37using WebKit::WebTransformationMatrix;
38
39namespace {
40
[email protected]c753e25a2012-10-19 21:22:4241void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1442{
43 if (visible) {
[email protected]c753e25a2012-10-19 21:22:4244 TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id);
[email protected]94f206c12012-08-25 00:09:1445 return;
46 }
47
[email protected]c753e25a2012-10-19 21:22:4248 TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::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]c753e25a2012-10-19 21:22:4255CCPinchZoomViewport::CCPinchZoomViewport()
[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)
61{
62}
63
[email protected]c753e25a2012-10-19 21:22:4264float CCPinchZoomViewport::totalPageScaleFactor() const
[email protected]1c0c9bc2012-10-08 22:41:4865{
66 return m_pageScaleFactor * m_pageScaleDelta;
67}
68
[email protected]c753e25a2012-10-19 21:22:4269void CCPinchZoomViewport::setPageScaleDelta(float delta)
[email protected]1c0c9bc2012-10-08 22:41:4870{
71 // Clamp to the current min/max limits.
72 float totalPageScaleFactor = m_pageScaleFactor * delta;
73 if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
74 delta = m_minPageScaleFactor / m_pageScaleFactor;
75 else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
76 delta = m_maxPageScaleFactor / m_pageScaleFactor;
77
78 if (delta == m_pageScaleDelta)
79 return;
80
81 m_pageScaleDelta = delta;
82}
83
[email protected]c753e25a2012-10-19 21:22:4284bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:4885{
[email protected]1d993172012-10-18 18:15:0486 DCHECK(pageScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:4887
88 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
89 return false;
90
91 m_minPageScaleFactor = minPageScaleFactor;
92 m_maxPageScaleFactor = maxPageScaleFactor;
93
94 m_pageScaleFactor = pageScaleFactor;
95 return true;
96}
97
[email protected]c753e25a2012-10-19 21:22:4298FloatRect CCPinchZoomViewport::bounds() const
[email protected]1c0c9bc2012-10-08 22:41:4899{
100 FloatSize scaledViewportSize = m_layoutViewportSize;
101 scaledViewportSize.scale(1 / totalPageScaleFactor());
102
103 FloatRect bounds(FloatPoint(0, 0), scaledViewportSize);
104 bounds.setLocation(m_pinchViewportScrollDelta);
105
106 return bounds;
107}
108
[email protected]c753e25a2012-10-19 21:22:42109FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta)
[email protected]1c0c9bc2012-10-08 22:41:48110{
111 FloatSize overflow;
112 FloatRect pinchedBounds = bounds();
113
114 pinchedBounds.move(delta);
115 if (pinchedBounds.x() < 0) {
116 overflow.setWidth(pinchedBounds.x());
117 pinchedBounds.setX(0);
118 }
119
120 if (pinchedBounds.y() < 0) {
121 overflow.setHeight(pinchedBounds.y());
122 pinchedBounds.setY(0);
123 }
124
125 if (pinchedBounds.maxX() > m_layoutViewportSize.width()) {
126 overflow.setWidth(
127 pinchedBounds.maxX() - m_layoutViewportSize.width());
128 pinchedBounds.move(
129 m_layoutViewportSize.width() - pinchedBounds.maxX(), 0);
130 }
131
132 if (pinchedBounds.maxY() > m_layoutViewportSize.height()) {
133 overflow.setHeight(
134 pinchedBounds.maxY() - m_layoutViewportSize.height());
135 pinchedBounds.move(
136 0, m_layoutViewportSize.height() - pinchedBounds.maxY());
137 }
138 m_pinchViewportScrollDelta = pinchedBounds.location();
139
140 return overflow;
141}
142
[email protected]c753e25a2012-10-19 21:22:42143WebTransformationMatrix CCPinchZoomViewport::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:48144{
145 WebTransformationMatrix transform;
146 transform.scale(m_pageScaleDelta);
147
148 // If the pinch state is applied in the impl, then push it to the
149 // impl transform, otherwise the scale is handled by WebCore.
[email protected]65bfd9972012-10-19 03:39:37150 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48151 transform.scale(m_pageScaleFactor);
152 transform.translate(-m_pinchViewportScrollDelta.x(),
153 -m_pinchViewportScrollDelta.y());
154 }
155
156 return transform;
157}
158
[email protected]c753e25a2012-10-19 21:22:42159class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14160public:
[email protected]c753e25a2012-10-19 21:22:42161 static scoped_ptr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<CCDelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14162 {
[email protected]c753e25a2012-10-19 21:22:42163 return make_scoped_ptr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
[email protected]94f206c12012-08-25 00:09:14164 }
[email protected]c753e25a2012-10-19 21:22:42165 virtual ~CCLayerTreeHostImplTimeSourceAdapter()
[email protected]94f206c12012-08-25 00:09:14166 {
167 m_timeSource->setClient(0);
168 m_timeSource->setActive(false);
169 }
170
171 virtual void onTimerTick() OVERRIDE
172 {
173 // FIXME: We require that animate be called on the impl thread. This
174 // avoids asserts in single threaded mode. Ideally background ticking
175 // would be handled by the proxy/scheduler and this could be removed.
176 DebugScopedSetImplThread impl;
177
178 m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
179 }
180
181 void setActive(bool active)
182 {
183 if (active != m_timeSource->active())
184 m_timeSource->setActive(active);
185 }
186
187private:
[email protected]c753e25a2012-10-19 21:22:42188 CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, scoped_refptr<CCDelayBasedTimeSource> timeSource)
[email protected]94f206c12012-08-25 00:09:14189 : m_layerTreeHostImpl(layerTreeHostImpl)
190 , m_timeSource(timeSource)
191 {
192 m_timeSource->setClient(this);
193 }
194
[email protected]c753e25a2012-10-19 21:22:42195 CCLayerTreeHostImpl* m_layerTreeHostImpl;
196 scoped_refptr<CCDelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20197
[email protected]c753e25a2012-10-19 21:22:42198 DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14199};
200
[email protected]c753e25a2012-10-19 21:22:42201CCLayerTreeHostImpl::FrameData::FrameData()
[email protected]493067512012-09-19 23:34:10202{
203}
204
[email protected]c753e25a2012-10-19 21:22:42205CCLayerTreeHostImpl::FrameData::~FrameData()
[email protected]493067512012-09-19 23:34:10206{
207}
208
[email protected]c753e25a2012-10-19 21:22:42209scoped_ptr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
[email protected]94f206c12012-08-25 00:09:14210{
[email protected]c753e25a2012-10-19 21:22:42211 return make_scoped_ptr(new CCLayerTreeHostImpl(settings, client));
[email protected]94f206c12012-08-25 00:09:14212}
213
[email protected]c753e25a2012-10-19 21:22:42214CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
[email protected]94f206c12012-08-25 00:09:14215 : m_client(client)
216 , m_sourceFrameNumber(-1)
217 , m_rootScrollLayerImpl(0)
218 , m_currentlyScrollingLayerImpl(0)
219 , m_hudLayerImpl(0)
220 , m_scrollingLayerIdFromPreviousTree(-1)
[email protected]31bfe272012-10-19 18:49:52221 , m_scrollDeltaIsInViewportSpace(false)
[email protected]94f206c12012-08-25 00:09:14222 , m_settings(settings)
223 , m_deviceScaleFactor(1)
224 , m_visible(true)
225 , m_contentsTexturesPurged(false)
[email protected]c753e25a2012-10-19 21:22:42226 , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit())
[email protected]94f206c12012-08-25 00:09:14227 , m_backgroundColor(0)
228 , m_hasTransparentBackground(false)
229 , m_needsAnimateLayers(false)
230 , m_pinchGestureActive(false)
[email protected]c753e25a2012-10-19 21:22:42231 , m_fpsCounter(CCFrameRateCounter::create())
232 , m_debugRectHistory(CCDebugRectHistory::create())
[email protected]5c6fe1f82012-10-03 18:00:27233 , m_numImplThreadScrolls(0)
234 , m_numMainThreadScrolls(0)
[email protected]94f206c12012-08-25 00:09:14235{
[email protected]c753e25a2012-10-19 21:22:42236 DCHECK(CCProxy::isImplThread());
[email protected]94f206c12012-08-25 00:09:14237 didVisibilityChange(this, m_visible);
238}
239
[email protected]c753e25a2012-10-19 21:22:42240CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
[email protected]94f206c12012-08-25 00:09:14241{
[email protected]c753e25a2012-10-19 21:22:42242 DCHECK(CCProxy::isImplThread());
243 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
[email protected]94f206c12012-08-25 00:09:14244
245 if (m_rootLayerImpl)
246 clearRenderSurfaces();
247}
248
[email protected]c753e25a2012-10-19 21:22:42249void CCLayerTreeHostImpl::beginCommit()
[email protected]94f206c12012-08-25 00:09:14250{
251}
252
[email protected]c753e25a2012-10-19 21:22:42253void CCLayerTreeHostImpl::commitComplete()
[email protected]94f206c12012-08-25 00:09:14254{
[email protected]c753e25a2012-10-19 21:22:42255 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete");
[email protected]94f206c12012-08-25 00:09:14256 // Recompute max scroll position; must be after layer content bounds are
257 // updated.
258 updateMaxScrollPosition();
259}
260
[email protected]c753e25a2012-10-19 21:22:42261bool CCLayerTreeHostImpl::canDraw()
[email protected]94f206c12012-08-25 00:09:14262{
[email protected]8db2213c2012-09-05 22:08:21263 // Note: If you are changing this function or any other function that might
264 // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
265 // in the proper places and update the notifyIfCanDrawChanged test.
266
[email protected]94f206c12012-08-25 00:09:14267 if (!m_rootLayerImpl) {
[email protected]c753e25a2012-10-19 21:22:42268 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer");
[email protected]94f206c12012-08-25 00:09:14269 return false;
270 }
271 if (deviceViewportSize().isEmpty()) {
[email protected]c753e25a2012-10-19 21:22:42272 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport");
[email protected]94f206c12012-08-25 00:09:14273 return false;
274 }
275 if (!m_renderer) {
[email protected]c753e25a2012-10-19 21:22:42276 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no renderer");
[email protected]94f206c12012-08-25 00:09:14277 return false;
278 }
279 if (m_contentsTexturesPurged) {
[email protected]c753e25a2012-10-19 21:22:42280 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged");
[email protected]94f206c12012-08-25 00:09:14281 return false;
282 }
283 return true;
284}
285
[email protected]c753e25a2012-10-19 21:22:42286CCGraphicsContext* CCLayerTreeHostImpl::context() const
[email protected]94f206c12012-08-25 00:09:14287{
288 return m_context.get();
289}
290
[email protected]c753e25a2012-10-19 21:22:42291void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
[email protected]94f206c12012-08-25 00:09:14292{
293 animatePageScale(monotonicTime);
294 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14295 animateScrollbars(monotonicTime);
296}
297
[email protected]c753e25a2012-10-19 21:22:42298void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
[email protected]94f206c12012-08-25 00:09:14299{
300 if (!m_rootScrollLayerImpl)
301 return;
302
303 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:48304 scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta());
305 float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor();
[email protected]94f206c12012-08-25 00:09:14306 IntSize scaledContentSize = contentSize();
[email protected]1c0c9bc2012-10-08 22:41:48307 scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta());
[email protected]94f206c12012-08-25 00:09:14308
[email protected]c753e25a2012-10-19 21:22:42309 m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime);
[email protected]94f206c12012-08-25 00:09:14310
311 if (anchorPoint) {
312 IntSize windowAnchor(targetPosition);
313 windowAnchor.scale(scaleTotal / pageScale);
314 windowAnchor -= scrollTotal;
315 m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
316 } else
317 m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
318
319 m_client->setNeedsRedrawOnImplThread();
320 m_client->setNeedsCommitOnImplThread();
321}
322
[email protected]c753e25a2012-10-19 21:22:42323void CCLayerTreeHostImpl::scheduleAnimation()
[email protected]94f206c12012-08-25 00:09:14324{
325 m_client->setNeedsRedrawOnImplThread();
326}
327
[email protected]c753e25a2012-10-19 21:22:42328void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14329{
330 // For now, we use damage tracking to compute a global scissor. To do this, we must
331 // compute all damage tracking before drawing anything, so that we know the root
332 // damage rect. The root damage rect is then used to scissor each surface.
333
334 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]c753e25a2012-10-19 21:22:42335 CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
336 CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
[email protected]1d993172012-10-18 18:15:04337 DCHECK(renderSurface);
[email protected]94f206c12012-08-25 00:09:14338 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
339 }
340}
341
[email protected]c753e25a2012-10-19 21:22:42342void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
[email protected]1c0c9bc2012-10-08 22:41:48343{
344 if (m_rootScrollLayerImpl) {
345 m_rootScrollLayerImpl->setImplTransform(implTransform());
346 }
347}
348
[email protected]c753e25a2012-10-19 21:22:42349void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
[email protected]94f206c12012-08-25 00:09:14350{
[email protected]1d993172012-10-18 18:15:04351 DCHECK(renderSurfaceLayerList.empty());
352 DCHECK(m_rootLayerImpl);
353 DCHECK(m_renderer); // For maxTextureSize.
[email protected]94f206c12012-08-25 00:09:14354
355 {
[email protected]1c0c9bc2012-10-08 22:41:48356 updateRootScrollLayerImplTransform();
357
[email protected]c753e25a2012-10-19 21:22:42358 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
359 CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:14360
361 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
362 }
363}
364
[email protected]c753e25a2012-10-19 21:22:42365void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<CCRenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16366{
[email protected]c753e25a2012-10-19 21:22:42367 CCRenderPass* pass = renderPass.get();
[email protected]f8ad8342012-09-27 20:07:02368 renderPasses.push_back(pass);
[email protected]87cea5372012-09-26 18:59:56369 renderPassesById.set(pass->id(), renderPass.Pass());
[email protected]467b3612012-08-28 07:41:16370}
371
[email protected]c753e25a2012-10-19 21:22:42372bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14373{
[email protected]1d993172012-10-18 18:15:04374 DCHECK(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14375
376 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
377
[email protected]c753e25a2012-10-19 21:22:42378 TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
[email protected]94f206c12012-08-25 00:09:14379
380 // Create the render passes in dependency order.
[email protected]94f206c12012-08-25 00:09:14381 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
[email protected]c753e25a2012-10-19 21:22:42382 CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
[email protected]467b3612012-08-28 07:41:16383 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
[email protected]94f206c12012-08-25 00:09:14384 }
385
386 bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
[email protected]c753e25a2012-10-19 21:22:42387 CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
[email protected]94f206c12012-08-25 00:09:14388 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
389
390 if (settings().showOccludingRects)
391 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
392
393 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
[email protected]c753e25a2012-10-19 21:22:42394 typedef CCLayerIterator<CCLayerImpl, std::vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
[email protected]94f206c12012-08-25 00:09:14395
396 // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
397 // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
398 // in the future.
399 bool drawFrame = true;
400
[email protected]c753e25a2012-10-19 21:22:42401 CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList);
402 for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
403 CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
404 CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14405
406 occlusionTracker.enterLayer(it);
407
[email protected]c753e25a2012-10-19 21:22:42408 CCAppendQuadsData appendQuadsData(targetRenderPass->id());
[email protected]89228202012-08-29 03:20:30409
[email protected]94f206c12012-08-25 00:09:14410 if (it.representsContributingRenderSurface()) {
[email protected]c753e25a2012-10-19 21:22:42411 CCRenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
412 CCRenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]89228202012-08-29 03:20:30413 targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14414 } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) {
415 bool hasOcclusionFromOutsideTargetSurface;
[email protected]89228202012-08-29 03:20:30416 if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface))
417 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
418 else {
[email protected]94f206c12012-08-25 00:09:14419 it->willDraw(m_resourceProvider.get());
[email protected]d58499a2012-10-09 22:27:47420 frame.willDrawLayers.push_back(*it);
[email protected]7d929c02012-09-20 17:26:57421
422 if (it->hasContributingDelegatedRenderPasses()) {
[email protected]c753e25a2012-10-19 21:22:42423 CCRenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
[email protected]7d929c02012-09-20 17:26:57424 while (frame.renderPassesById.contains(contributingRenderPassId)) {
[email protected]c753e25a2012-10-19 21:22:42425 CCRenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
[email protected]7d929c02012-09-20 17:26:57426
[email protected]c753e25a2012-10-19 21:22:42427 CCAppendQuadsData appendQuadsData(renderPass->id());
[email protected]7d929c02012-09-20 17:26:57428 renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
429
430 contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
431 }
432 }
433
[email protected]89228202012-08-29 03:20:30434 targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
[email protected]94f206c12012-08-25 00:09:14435 }
436 }
437
[email protected]89228202012-08-29 03:20:30438 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
439 targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true);
440
441 if (appendQuadsData.hadMissingTiles) {
[email protected]94f206c12012-08-25 00:09:14442 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
[email protected]65bfd9972012-10-19 03:39:37443 if (layerHasAnimatingTransform || Settings::jankInsteadOfCheckerboard())
[email protected]94f206c12012-08-25 00:09:14444 drawFrame = false;
445 }
446
447 occlusionTracker.leaveLayer(it);
448 }
449
[email protected]1d993172012-10-18 18:15:04450#ifndef NDEBUG
[email protected]94f206c12012-08-25 00:09:14451 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
[email protected]1d993172012-10-18 18:15:04452 for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j)
453 DCHECK(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0);
454 DCHECK(frame.renderPassesById.contains(frame.renderPasses[i]->id()));
[email protected]94f206c12012-08-25 00:09:14455 }
456#endif
457
458 if (!m_hasTransparentBackground) {
[email protected]f8ad8342012-09-27 20:07:02459 frame.renderPasses.back()->setHasTransparentBackground(false);
460 frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
[email protected]94f206c12012-08-25 00:09:14461 }
462
463 if (drawFrame)
464 occlusionTracker.overdrawMetrics().recordMetrics(this);
465
466 removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
467 m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
468 removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
469
470 return drawFrame;
471}
472
[email protected]c753e25a2012-10-19 21:22:42473void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
[email protected]94f206c12012-08-25 00:09:14474{
475 bool subtreeNeedsAnimateLayers = false;
476
[email protected]c753e25a2012-10-19 21:22:42477 CCLayerAnimationController* currentController = current->layerAnimationController();
[email protected]94f206c12012-08-25 00:09:14478
479 bool hadActiveAnimation = currentController->hasActiveAnimation();
480 currentController->animate(monotonicTime, events);
481 bool startedAnimation = events->size() > 0;
482
483 // We animated if we either ticked a running animation, or started a new animation.
484 if (hadActiveAnimation || startedAnimation)
485 didAnimate = true;
486
487 // If the current controller still has an active animation, we must continue animating layers.
488 if (currentController->hasActiveAnimation())
489 subtreeNeedsAnimateLayers = true;
490
491 for (size_t i = 0; i < current->children().size(); ++i) {
492 bool childNeedsAnimateLayers = false;
[email protected]0920e24f2012-09-20 03:34:03493 animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
[email protected]94f206c12012-08-25 00:09:14494 if (childNeedsAnimateLayers)
495 subtreeNeedsAnimateLayers = true;
496 }
497
498 needsAnimateLayers = subtreeNeedsAnimateLayers;
499}
500
[email protected]c753e25a2012-10-19 21:22:42501void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
[email protected]94f206c12012-08-25 00:09:14502{
503 // Lazily create the timeSource adapter so that we can vary the interval for testing.
504 if (!m_timeSourceClientAdapter)
[email protected]c753e25a2012-10-19 21:22:42505 m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread()));
[email protected]94f206c12012-08-25 00:09:14506
507 m_timeSourceClientAdapter->setActive(enabled);
508}
509
[email protected]c753e25a2012-10-19 21:22:42510IntSize CCLayerTreeHostImpl::contentSize() const
[email protected]94f206c12012-08-25 00:09:14511{
512 // TODO(aelias): Hardcoding the first child here is weird. Think of
513 // a cleaner way to get the contentBounds on the Impl side.
514 if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
515 return IntSize();
516 return m_rootScrollLayerImpl->children()[0]->contentBounds();
517}
518
[email protected]c753e25a2012-10-19 21:22:42519static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, const CCLayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14520{
[email protected]c753e25a2012-10-19 21:22:42521 CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
[email protected]1d993172012-10-18 18:15:04522 DCHECK(it != frame.renderPassesById.end());
[email protected]87cea5372012-09-26 18:59:56523 return it->second;
[email protected]94f206c12012-08-25 00:09:14524}
525
[email protected]c753e25a2012-10-19 21:22:42526static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCLayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14527{
[email protected]c753e25a2012-10-19 21:22:42528 CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
529 CCRenderPassList& renderPasses = frame.renderPasses;
530 CCRenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
[email protected]94f206c12012-08-25 00:09:14531
532 // The pass was already removed by another quad - probably the original, and we are the replica.
[email protected]f8ad8342012-09-27 20:07:02533 if (toRemove == renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14534 return;
535
[email protected]c753e25a2012-10-19 21:22:42536 const CCRenderPass* removedPass = *toRemove;
[email protected]f8ad8342012-09-27 20:07:02537 frame.renderPasses.erase(toRemove);
[email protected]94f206c12012-08-25 00:09:14538
539 // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
[email protected]c753e25a2012-10-19 21:22:42540 const CCQuadList& quadList = removedPass->quadList();
541 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14542 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]c753e25a2012-10-19 21:22:42543 CCDrawQuad* currentQuad = (*quadListIterator);
544 if (currentQuad->material() != CCDrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14545 continue;
546
[email protected]c753e25a2012-10-19 21:22:42547 CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId();
[email protected]94f206c12012-08-25 00:09:14548 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
549 }
550}
551
[email protected]c753e25a2012-10-19 21:22:42552bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData&) const
[email protected]94f206c12012-08-25 00:09:14553{
[email protected]1fea8142012-10-20 04:12:41554 return quad.contentsChangedSinceLastFrame().IsEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
[email protected]94f206c12012-08-25 00:09:14555}
556
[email protected]c753e25a2012-10-19 21:22:42557bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData& frame) const
[email protected]94f206c12012-08-25 00:09:14558{
[email protected]c753e25a2012-10-19 21:22:42559 const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame);
560 const CCRenderPassList& renderPasses = frame.renderPasses;
561 CCRenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
[email protected]94f206c12012-08-25 00:09:14562
[email protected]f8ad8342012-09-27 20:07:02563 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
[email protected]94f206c12012-08-25 00:09:14564 if (renderPassAlreadyRemoved)
565 return false;
566
567 // If any quad or RenderPass draws into this RenderPass, then keep it.
[email protected]c753e25a2012-10-19 21:22:42568 const CCQuadList& quadList = (*foundPass)->quadList();
569 for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
570 CCDrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14571
[email protected]c753e25a2012-10-19 21:22:42572 if (currentQuad->material() != CCDrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14573 return false;
574
[email protected]c753e25a2012-10-19 21:22:42575 const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame);
576 CCRenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
[email protected]f8ad8342012-09-27 20:07:02577 if (foundContributingPass != renderPasses.end())
[email protected]94f206c12012-08-25 00:09:14578 return false;
579 }
580 return true;
581}
582
583// Defined for linking tests.
[email protected]c753e25a2012-10-19 21:22:42584template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
585template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
[email protected]94f206c12012-08-25 00:09:14586
587// static
588template<typename RenderPassCuller>
[email protected]c753e25a2012-10-19 21:22:42589void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14590{
591 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
[email protected]c753e25a2012-10-19 21:22:42592 const CCRenderPass* currentPass = frame.renderPasses[it];
593 const CCQuadList& quadList = currentPass->quadList();
594 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
[email protected]94f206c12012-08-25 00:09:14595
596 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]c753e25a2012-10-19 21:22:42597 CCDrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14598
[email protected]c753e25a2012-10-19 21:22:42599 if (currentQuad->material() != CCDrawQuad::RenderPass)
[email protected]94f206c12012-08-25 00:09:14600 continue;
601
[email protected]c753e25a2012-10-19 21:22:42602 CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
[email protected]94f206c12012-08-25 00:09:14603 if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
604 continue;
605
606 // We are changing the vector in the middle of iteration. Because we
607 // delete render passes that draw into the current pass, we are
608 // guaranteed that any data from the iterator to the end will not
609 // change. So, capture the iterator position from the end of the
610 // list, and restore it after the change.
611 int positionFromEnd = frame.renderPasses.size() - it;
612 removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame);
613 it = frame.renderPasses.size() - positionFromEnd;
[email protected]1d993172012-10-18 18:15:04614 DCHECK(it >= 0);
[email protected]94f206c12012-08-25 00:09:14615 }
616 }
617}
618
[email protected]c753e25a2012-10-19 21:22:42619bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14620{
[email protected]c753e25a2012-10-19 21:22:42621 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw");
[email protected]1d993172012-10-18 18:15:04622 DCHECK(canDraw());
[email protected]94f206c12012-08-25 00:09:14623
624 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
625 frame.renderPasses.clear();
626 frame.renderPassesById.clear();
627 frame.renderSurfaceLayerList->clear();
628 frame.willDrawLayers.clear();
629
630 if (!calculateRenderPasses(frame))
631 return false;
632
633 // If we return true, then we expect drawLayers() to be called before this function is called again.
634 return true;
635}
636
[email protected]c753e25a2012-10-19 21:22:42637void CCLayerTreeHostImpl::reduceContentsTextureMemoryOnImplThread(size_t limitBytes)
[email protected]94f206c12012-08-25 00:09:14638{
[email protected]b1969fa2012-10-17 20:16:29639 bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(limitBytes);
640 if (evictedResources) {
641 setContentsTexturesPurged();
642 m_client->setNeedsCommitOnImplThread();
643 m_client->onCanDrawStateChanged(canDraw());
644 }
[email protected]94f206c12012-08-25 00:09:14645}
646
[email protected]c753e25a2012-10-19 21:22:42647void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
[email protected]94f206c12012-08-25 00:09:14648{
[email protected]1d993172012-10-18 18:15:04649 DCHECK(bytes);
[email protected]94f206c12012-08-25 00:09:14650 if (m_memoryAllocationLimitBytes == bytes)
651 return;
652 m_memoryAllocationLimitBytes = bytes;
[email protected]b1969fa2012-10-17 20:16:29653 reduceContentsTextureMemoryOnImplThread(m_visible ? m_memoryAllocationLimitBytes : 0);
[email protected]94f206c12012-08-25 00:09:14654 m_client->setNeedsCommitOnImplThread();
655}
656
[email protected]c753e25a2012-10-19 21:22:42657void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
[email protected]94f206c12012-08-25 00:09:14658{
659 m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds);
660}
661
[email protected]c753e25a2012-10-19 21:22:42662void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14663{
[email protected]c753e25a2012-10-19 21:22:42664 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
[email protected]1d993172012-10-18 18:15:04665 DCHECK(canDraw());
666 DCHECK(!frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14667
668 // FIXME: use the frame begin time from the overall compositor scheduler.
669 // This value is currently inaccessible because it is up in Chromium's
670 // RenderWidget.
[email protected]6bea87c2012-10-13 00:15:21671 m_fpsCounter->markBeginningOfFrame(base::TimeTicks::Now());
[email protected]94f206c12012-08-25 00:09:14672
673 if (m_settings.showDebugRects())
674 m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
675
676 // Because the contents of the HUD depend on everything else in the frame, the contents
677 // of its texture are updated as the last thing before the frame is drawn.
678 if (m_hudLayerImpl)
679 m_hudLayerImpl->updateHudTexture(m_resourceProvider.get());
680
681 m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
682
683 // Once a RenderPass has been drawn, its damage should be cleared in
684 // case the RenderPass will be reused next frame.
685 for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
686 frame.renderPasses[i]->setDamageRect(FloatRect());
687
688 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
689 for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
690 (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
691 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
692}
693
[email protected]c753e25a2012-10-19 21:22:42694void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14695{
696 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
697 frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
[email protected]b914e102012-10-02 08:11:52698
699 // Once all layers have been drawn, pending texture uploads should no
700 // longer block future uploads.
[email protected]e2249592012-10-19 06:59:09701 m_resourceProvider->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14702}
703
[email protected]c753e25a2012-10-19 21:22:42704void CCLayerTreeHostImpl::finishAllRendering()
[email protected]94f206c12012-08-25 00:09:14705{
706 if (m_renderer)
707 m_renderer->finish();
708}
709
[email protected]c753e25a2012-10-19 21:22:42710bool CCLayerTreeHostImpl::isContextLost()
[email protected]94f206c12012-08-25 00:09:14711{
712 return m_renderer && m_renderer->isContextLost();
713}
714
[email protected]c753e25a2012-10-19 21:22:42715const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const
[email protected]94f206c12012-08-25 00:09:14716{
717 return m_renderer->capabilities();
718}
719
[email protected]c753e25a2012-10-19 21:22:42720bool CCLayerTreeHostImpl::swapBuffers()
[email protected]94f206c12012-08-25 00:09:14721{
[email protected]1d993172012-10-18 18:15:04722 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14723
724 m_fpsCounter->markEndOfFrame();
725 return m_renderer->swapBuffers();
726}
727
[email protected]c753e25a2012-10-19 21:22:42728const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const
[email protected]493067512012-09-19 23:34:10729{
730 return m_deviceViewportSize;
731}
732
[email protected]c753e25a2012-10-19 21:22:42733const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const
[email protected]493067512012-09-19 23:34:10734{
735 return m_settings;
736}
737
[email protected]c753e25a2012-10-19 21:22:42738void CCLayerTreeHostImpl::didLoseContext()
[email protected]94f206c12012-08-25 00:09:14739{
740 m_client->didLoseContextOnImplThread();
741}
742
[email protected]c753e25a2012-10-19 21:22:42743void CCLayerTreeHostImpl::onSwapBuffersComplete()
[email protected]94f206c12012-08-25 00:09:14744{
745 m_client->onSwapBuffersCompleteOnImplThread();
746}
747
[email protected]c753e25a2012-10-19 21:22:42748void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
[email protected]94f206c12012-08-25 00:09:14749{
[email protected]1d993172012-10-18 18:15:04750 DCHECK(m_renderer);
[email protected]94f206c12012-08-25 00:09:14751 m_renderer->getFramebufferPixels(pixels, rect);
752}
753
[email protected]c753e25a2012-10-19 21:22:42754static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
[email protected]94f206c12012-08-25 00:09:14755{
756 if (!layer)
757 return 0;
758
759 if (layer->scrollable())
760 return layer;
761
762 for (size_t i = 0; i < layer->children().size(); ++i) {
[email protected]c753e25a2012-10-19 21:22:42763 CCLayerImpl* found = findRootScrollLayer(layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:14764 if (found)
765 return found;
766 }
767
768 return 0;
769}
770
771// Content layers can be either directly scrollable or contained in an outer
772// scrolling layer which applies the scroll transform. Given a content layer,
773// this function returns the associated scroll layer if any.
[email protected]c753e25a2012-10-19 21:22:42774static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:14775{
776 if (!layerImpl)
777 return 0;
778
779 if (layerImpl->scrollable())
780 return layerImpl;
781
782 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
783 return layerImpl->parent();
784
785 return 0;
786}
787
[email protected]c753e25a2012-10-19 21:22:42788void CCLayerTreeHostImpl::setRootLayer(scoped_ptr<CCLayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:14789{
[email protected]e0bd43a2012-10-12 16:54:21790 m_rootLayerImpl = layer.Pass();
[email protected]94f206c12012-08-25 00:09:14791 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
792 m_currentlyScrollingLayerImpl = 0;
793
794 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
[email protected]c753e25a2012-10-19 21:22:42795 m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
[email protected]94f206c12012-08-25 00:09:14796
797 m_scrollingLayerIdFromPreviousTree = -1;
[email protected]8db2213c2012-09-05 22:08:21798
799 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14800}
801
[email protected]c753e25a2012-10-19 21:22:42802scoped_ptr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
[email protected]94f206c12012-08-25 00:09:14803{
804 // Clear all data structures that have direct references to the layer tree.
805 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
806 m_currentlyScrollingLayerImpl = 0;
807 m_renderSurfaceLayerList.clear();
808
[email protected]e0bd43a2012-10-12 16:54:21809 return m_rootLayerImpl.Pass();
[email protected]94f206c12012-08-25 00:09:14810}
811
[email protected]c753e25a2012-10-19 21:22:42812void CCLayerTreeHostImpl::setVisible(bool visible)
[email protected]94f206c12012-08-25 00:09:14813{
[email protected]c753e25a2012-10-19 21:22:42814 DCHECK(CCProxy::isImplThread());
[email protected]94f206c12012-08-25 00:09:14815
816 if (m_visible == visible)
817 return;
818 m_visible = visible;
819 didVisibilityChange(this, m_visible);
[email protected]b1969fa2012-10-17 20:16:29820 reduceContentsTextureMemoryOnImplThread(m_visible ? m_memoryAllocationLimitBytes : 0);
[email protected]94f206c12012-08-25 00:09:14821
822 if (!m_renderer)
823 return;
824
825 m_renderer->setVisible(visible);
826
827 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
828}
829
[email protected]c753e25a2012-10-19 21:22:42830bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr<CCGraphicsContext> context)
[email protected]94f206c12012-08-25 00:09:14831{
[email protected]be3181652012-09-25 13:02:13832 // Since we will create a new resource provider, we cannot continue to use
833 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
834 // before we destroy the old resource provider.
[email protected]94f206c12012-08-25 00:09:14835 if (m_rootLayerImpl) {
836 clearRenderSurfaces();
837 sendDidLoseContextRecursive(m_rootLayerImpl.get());
838 }
[email protected]be3181652012-09-25 13:02:13839 // Note: order is important here.
[email protected]0704caf2012-10-16 03:39:47840 m_renderer.reset();
[email protected]a7aa5562012-10-17 14:12:44841 m_resourceProvider.reset();
[email protected]e28efacd2012-10-06 17:07:49842 m_context.reset();
[email protected]94f206c12012-08-25 00:09:14843
[email protected]be3181652012-09-25 13:02:13844 if (!context->bindToClient(this))
845 return false;
846
[email protected]c753e25a2012-10-19 21:22:42847 scoped_ptr<CCResourceProvider> resourceProvider = CCResourceProvider::create(context.get());
[email protected]be3181652012-09-25 13:02:13848 if (!resourceProvider)
849 return false;
850
851 if (context->context3D())
[email protected]c753e25a2012-10-19 21:22:42852 m_renderer = CCRendererGL::create(this, resourceProvider.get());
[email protected]be3181652012-09-25 13:02:13853 else if (context->softwareDevice())
[email protected]c753e25a2012-10-19 21:22:42854 m_renderer = CCRendererSoftware::create(this, resourceProvider.get(), context->softwareDevice());
[email protected]be3181652012-09-25 13:02:13855 if (!m_renderer)
856 return false;
857
[email protected]a7aa5562012-10-17 14:12:44858 m_resourceProvider = resourceProvider.Pass();
[email protected]e28efacd2012-10-06 17:07:49859 m_context = context.Pass();
[email protected]94f206c12012-08-25 00:09:14860
[email protected]be3181652012-09-25 13:02:13861 if (!m_visible)
862 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:14863
[email protected]8db2213c2012-09-05 22:08:21864 m_client->onCanDrawStateChanged(canDraw());
865
[email protected]be3181652012-09-25 13:02:13866 return true;
[email protected]94f206c12012-08-25 00:09:14867}
868
[email protected]c753e25a2012-10-19 21:22:42869void CCLayerTreeHostImpl::setContentsTexturesPurged()
[email protected]e1fc8b32012-09-18 20:29:09870{
871 m_contentsTexturesPurged = true;
872 m_client->onCanDrawStateChanged(canDraw());
873}
874
[email protected]c753e25a2012-10-19 21:22:42875void CCLayerTreeHostImpl::resetContentsTexturesPurged()
[email protected]8db2213c2012-09-05 22:08:21876{
877 m_contentsTexturesPurged = false;
878 m_client->onCanDrawStateChanged(canDraw());
879}
880
[email protected]c753e25a2012-10-19 21:22:42881void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
[email protected]94f206c12012-08-25 00:09:14882{
883 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
884 return;
885
886 m_layoutViewportSize = layoutViewportSize;
887 m_deviceViewportSize = deviceViewportSize;
888
[email protected]1c0c9bc2012-10-08 22:41:48889 m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
890
[email protected]94f206c12012-08-25 00:09:14891 updateMaxScrollPosition();
892
893 if (m_renderer)
894 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:21895
896 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14897}
898
[email protected]c753e25a2012-10-19 21:22:42899static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)
[email protected]94f206c12012-08-25 00:09:14900{
901 if (!layerImpl)
902 return;
903
904 if (layerImpl->scrollable()) {
905 // We need to convert impl-side scroll deltas to pageScale space.
906 FloatSize scrollDelta = layerImpl->scrollDelta();
907 scrollDelta.scale(pageScaleChange);
908 layerImpl->setScrollDelta(scrollDelta);
909 }
910
911 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:03912 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:14913}
914
[email protected]c753e25a2012-10-19 21:22:42915void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
[email protected]94f206c12012-08-25 00:09:14916{
917 if (deviceScaleFactor == m_deviceScaleFactor)
918 return;
919 m_deviceScaleFactor = deviceScaleFactor;
[email protected]c0dd24c2012-08-30 23:25:27920
921 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14922}
923
[email protected]c753e25a2012-10-19 21:22:42924float CCLayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:14925{
[email protected]1c0c9bc2012-10-08 22:41:48926 return m_pinchZoomViewport.pageScaleFactor();
927}
[email protected]94f206c12012-08-25 00:09:14928
[email protected]c753e25a2012-10-19 21:22:42929void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
[email protected]1c0c9bc2012-10-08 22:41:48930{
931 if (!pageScaleFactor)
932 return;
[email protected]94f206c12012-08-25 00:09:14933
[email protected]1c0c9bc2012-10-08 22:41:48934 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
935 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:14936
[email protected]65bfd9972012-10-19 03:39:37937 if (!Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48938 if (pageScaleChange != 1)
939 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
940 }
[email protected]94f206c12012-08-25 00:09:14941
942 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:48943 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
944 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:14945}
946
[email protected]c753e25a2012-10-19 21:22:42947void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
[email protected]94f206c12012-08-25 00:09:14948{
[email protected]1c0c9bc2012-10-08 22:41:48949 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:14950
951 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14952}
953
[email protected]c753e25a2012-10-19 21:22:42954void CCLayerTreeHostImpl::updateMaxScrollPosition()
[email protected]94f206c12012-08-25 00:09:14955{
956 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
957 return;
958
959 FloatSize viewBounds = m_deviceViewportSize;
[email protected]c753e25a2012-10-19 21:22:42960 if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:14961 // Compensate for non-overlay scrollbars.
962 if (clipLayer->masksToBounds()) {
963 viewBounds = clipLayer->bounds();
964 viewBounds.scale(m_deviceScaleFactor);
965 }
966 }
[email protected]94f206c12012-08-25 00:09:14967
[email protected]1c0c9bc2012-10-08 22:41:48968 IntSize contentBounds = contentSize();
[email protected]65bfd9972012-10-19 03:39:37969 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:48970 // Pinch with pageScale scrolls entirely in layout space. contentSize
971 // returns the bounds including the page scale factor, so calculate the
972 // pre page-scale layout size here.
973 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
974 contentBounds.setWidth(contentBounds.width() / pageScaleFactor);
975 contentBounds.setHeight(contentBounds.height() / pageScaleFactor);
976 } else {
977 viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta());
978 }
979
980 IntSize maxScroll = contentBounds - expandedIntSize(viewBounds);
[email protected]94f206c12012-08-25 00:09:14981 maxScroll.scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:48982
[email protected]94f206c12012-08-25 00:09:14983 // The viewport may be larger than the contents in some cases, such as
984 // having a vertical scrollbar but no horizontal overflow.
985 maxScroll.clampNegativeToZero();
986
987 m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
988}
989
[email protected]c753e25a2012-10-19 21:22:42990void CCLayerTreeHostImpl::setNeedsRedraw()
[email protected]94f206c12012-08-25 00:09:14991{
992 m_client->setNeedsRedrawOnImplThread();
993}
994
[email protected]c753e25a2012-10-19 21:22:42995bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList()
[email protected]94f206c12012-08-25 00:09:14996{
997 if (!m_rootLayerImpl)
998 return false;
999 if (!m_renderer)
1000 return false;
1001
1002 // We need both a non-empty render surface layer list and a root render
1003 // surface to be able to iterate over the visible layers.
1004 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
1005 return true;
1006
1007 // If we are called after setRootLayer() but before prepareToDraw(), we need
1008 // to recalculate the visible layers. This prevents being unable to scroll
1009 // during part of a commit.
1010 m_renderSurfaceLayerList.clear();
1011 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
1012
1013 return m_renderSurfaceLayerList.size();
1014}
1015
[email protected]c753e25a2012-10-19 21:22:421016CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
[email protected]94f206c12012-08-25 00:09:141017{
[email protected]c753e25a2012-10-19 21:22:421018 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin");
[email protected]94f206c12012-08-25 00:09:141019
[email protected]1d993172012-10-18 18:15:041020 DCHECK(!m_currentlyScrollingLayerImpl);
[email protected]94f206c12012-08-25 00:09:141021 clearCurrentlyScrollingLayer();
1022
1023 if (!ensureRenderSurfaceLayerList())
1024 return ScrollIgnored;
1025
1026 IntPoint deviceViewportPoint = viewportPoint;
1027 deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
1028
1029 // First find out which layer was hit from the saved list of visible layers
1030 // in the most recent frame.
[email protected]c753e25a2012-10-19 21:22:421031 CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(deviceViewportPoint, m_renderSurfaceLayerList);
[email protected]94f206c12012-08-25 00:09:141032
1033 // Walk up the hierarchy and look for a scrollable layer.
[email protected]c753e25a2012-10-19 21:22:421034 CCLayerImpl* potentiallyScrollingLayerImpl = 0;
[email protected]94f206c12012-08-25 00:09:141035 for (; layerImpl; layerImpl = layerImpl->parent()) {
1036 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271037 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1038 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141039 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271040 }
[email protected]94f206c12012-08-25 00:09:141041
[email protected]c753e25a2012-10-19 21:22:421042 CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
[email protected]94f206c12012-08-25 00:09:141043 if (!scrollLayerImpl)
1044 continue;
1045
[email protected]31bfe272012-10-19 18:49:521046 ScrollStatus status = scrollLayerImpl->tryScroll(deviceViewportPoint, type);
[email protected]94f206c12012-08-25 00:09:141047
1048 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271049 if (status == ScrollOnMainThread) {
1050 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141051 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271052 }
[email protected]94f206c12012-08-25 00:09:141053
1054 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1055 potentiallyScrollingLayerImpl = scrollLayerImpl;
1056 }
1057
1058 if (potentiallyScrollingLayerImpl) {
1059 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
[email protected]31bfe272012-10-19 18:49:521060 // Gesture events need to be transformed from viewport coordinates to local layer coordinates
[email protected]94f206c12012-08-25 00:09:141061 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1062 // events are already in local layer coordinates so we can just apply them directly.
[email protected]31bfe272012-10-19 18:49:521063 m_scrollDeltaIsInViewportSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271064 m_numImplThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141065 return ScrollStarted;
1066 }
1067 return ScrollIgnored;
1068}
1069
[email protected]c753e25a2012-10-19 21:22:421070static FloatSize scrollLayerWithViewportSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, float scaleFromViewportToScreenSpace, const FloatPoint& viewportPoint, const FloatSize& viewportDelta)
[email protected]94f206c12012-08-25 00:09:141071{
1072 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1073 // test in the first place.
[email protected]1d993172012-10-18 18:15:041074 DCHECK(layerImpl.screenSpaceTransform().isInvertible());
[email protected]94f206c12012-08-25 00:09:141075 WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse();
1076
[email protected]31bfe272012-10-19 18:49:521077 FloatPoint screenSpacePoint = viewportPoint;
1078 screenSpacePoint.scale(scaleFromViewportToScreenSpace, scaleFromViewportToScreenSpace);
1079
1080 FloatSize screenSpaceDelta = viewportDelta;
1081 screenSpaceDelta.scale(scaleFromViewportToScreenSpace, scaleFromViewportToScreenSpace);
1082
[email protected]94f206c12012-08-25 00:09:141083 // First project the scroll start and end points to local layer space to find the scroll delta
1084 // in layer coordinates.
1085 bool startClipped, endClipped;
1086 FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
[email protected]c753e25a2012-10-19 21:22:421087 FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1088 FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
[email protected]94f206c12012-08-25 00:09:141089
1090 // In general scroll point coordinates should not get clipped.
[email protected]1d993172012-10-18 18:15:041091 DCHECK(!startClipped);
1092 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141093 if (startClipped || endClipped)
1094 return FloatSize();
1095
[email protected]31bfe272012-10-19 18:49:521096 // localStartPoint and localEndPoint are in content space but we want to move them to layer space for scrolling.
1097 float widthScale = 1;
1098 float heightScale = 1;
1099 if (!layerImpl.contentBounds().isEmpty() && !layerImpl.bounds().isEmpty()) {
1100 widthScale = layerImpl.bounds().width() / static_cast<float>(layerImpl.contentBounds().width());
1101 heightScale = layerImpl.bounds().height() / static_cast<float>(layerImpl.contentBounds().height());
1102 }
1103 localStartPoint.scale(widthScale, heightScale);
1104 localEndPoint.scale(widthScale, heightScale);
1105
[email protected]94f206c12012-08-25 00:09:141106 // Apply the scroll delta.
1107 FloatSize previousDelta(layerImpl.scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481108 FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
1109
1110 if (viewport)
1111 viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141112
[email protected]31bfe272012-10-19 18:49:521113 // Get the end point in the layer's content space so we can apply its screenSpaceTransform.
[email protected]94f206c12012-08-25 00:09:141114 FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
[email protected]31bfe272012-10-19 18:49:521115 FloatPoint actualLocalContentEndPoint = actualLocalEndPoint;
1116 actualLocalContentEndPoint.scale(1 / widthScale, 1 / heightScale);
1117
1118 // Calculate the applied scroll delta in viewport space coordinates.
[email protected]c753e25a2012-10-19 21:22:421119 FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalContentEndPoint, endClipped);
[email protected]1d993172012-10-18 18:15:041120 DCHECK(!endClipped);
[email protected]94f206c12012-08-25 00:09:141121 if (endClipped)
1122 return FloatSize();
[email protected]31bfe272012-10-19 18:49:521123 FloatPoint actualViewportEndPoint = actualScreenSpaceEndPoint;
1124 actualViewportEndPoint.scale(1 / scaleFromViewportToScreenSpace, 1 / scaleFromViewportToScreenSpace);
1125 return actualViewportEndPoint - viewportPoint;
[email protected]94f206c12012-08-25 00:09:141126}
1127
[email protected]c753e25a2012-10-19 21:22:421128static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSize& localDelta)
[email protected]94f206c12012-08-25 00:09:141129{
1130 FloatSize previousDelta(layerImpl.scrollDelta());
1131 layerImpl.scrollBy(localDelta);
1132 return layerImpl.scrollDelta() - previousDelta;
1133}
1134
[email protected]c753e25a2012-10-19 21:22:421135void CCLayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta)
[email protected]94f206c12012-08-25 00:09:141136{
[email protected]c753e25a2012-10-19 21:22:421137 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy");
[email protected]94f206c12012-08-25 00:09:141138 if (!m_currentlyScrollingLayerImpl)
1139 return;
1140
1141 FloatSize pendingDelta(scrollDelta);
1142
[email protected]c753e25a2012-10-19 21:22:421143 for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
[email protected]94f206c12012-08-25 00:09:141144 if (!layerImpl->scrollable())
1145 continue;
1146
[email protected]c753e25a2012-10-19 21:22:421147 CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
[email protected]94f206c12012-08-25 00:09:141148 FloatSize appliedDelta;
[email protected]31bfe272012-10-19 18:49:521149 if (m_scrollDeltaIsInViewportSpace) {
1150 float scaleFromViewportToScreenSpace = m_deviceScaleFactor;
1151 appliedDelta = scrollLayerWithViewportSpaceDelta(viewport, *layerImpl, scaleFromViewportToScreenSpace, viewportPoint, pendingDelta);
1152 } else
[email protected]94f206c12012-08-25 00:09:141153 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1154
1155 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381156 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]94f206c12012-08-25 00:09:141157 if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared)
1158 continue;
1159
1160 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1161 // to scroll just one layer in one direction without affecting any of its parents.
1162 float angleThreshold = 45;
[email protected]c753e25a2012-10-19 21:22:421163 if (CCMathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
[email protected]94f206c12012-08-25 00:09:141164 pendingDelta = FloatSize();
1165 break;
1166 }
1167
1168 // Allow further movement only on an axis perpendicular to the direction in which the layer
1169 // moved.
1170 FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width());
[email protected]c753e25a2012-10-19 21:22:421171 pendingDelta = CCMathUtil::projectVector(pendingDelta, perpendicularAxis);
[email protected]94f206c12012-08-25 00:09:141172
1173 if (flooredIntSize(pendingDelta).isZero())
1174 break;
1175 }
1176
1177 if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) {
1178 m_client->setNeedsCommitOnImplThread();
1179 m_client->setNeedsRedrawOnImplThread();
1180 }
1181}
1182
[email protected]c753e25a2012-10-19 21:22:421183void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
[email protected]94f206c12012-08-25 00:09:141184{
1185 m_currentlyScrollingLayerImpl = 0;
1186 m_scrollingLayerIdFromPreviousTree = -1;
1187}
1188
[email protected]c753e25a2012-10-19 21:22:421189void CCLayerTreeHostImpl::scrollEnd()
[email protected]94f206c12012-08-25 00:09:141190{
1191 clearCurrentlyScrollingLayer();
1192}
1193
[email protected]c753e25a2012-10-19 21:22:421194void CCLayerTreeHostImpl::pinchGestureBegin()
[email protected]94f206c12012-08-25 00:09:141195{
1196 m_pinchGestureActive = true;
1197 m_previousPinchAnchor = IntPoint();
1198
1199 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1200 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
1201}
1202
[email protected]c753e25a2012-10-19 21:22:421203void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
[email protected]94f206c12012-08-25 00:09:141204 const IntPoint& anchor)
1205{
[email protected]c753e25a2012-10-19 21:22:421206 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate");
[email protected]94f206c12012-08-25 00:09:141207
1208 if (!m_rootScrollLayerImpl)
1209 return;
1210
1211 if (m_previousPinchAnchor == IntPoint::zero())
1212 m_previousPinchAnchor = anchor;
1213
1214 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1215 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481216 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1217 FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta,
1218 m_previousPinchAnchor.y() / pageScaleDelta);
1219 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1220 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1221 FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141222 FloatSize move = previousScaleAnchor - newScaleAnchor;
1223
1224 m_previousPinchAnchor = anchor;
1225
[email protected]65bfd9972012-10-19 03:39:371226 if (Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:481227 // Compute the application of the delta with respect to the current page zoom of the page.
1228 move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor));
1229 }
1230
[email protected]65bfd9972012-10-19 03:39:371231 FloatSize scrollOverflow = Settings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move;
[email protected]1c0c9bc2012-10-08 22:41:481232 m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow));
[email protected]94f206c12012-08-25 00:09:141233
1234 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1235 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
1236
1237 m_client->setNeedsCommitOnImplThread();
1238 m_client->setNeedsRedrawOnImplThread();
1239}
1240
[email protected]c753e25a2012-10-19 21:22:421241void CCLayerTreeHostImpl::pinchGestureEnd()
[email protected]94f206c12012-08-25 00:09:141242{
1243 m_pinchGestureActive = false;
1244
1245 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1246 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
1247
1248 m_client->setNeedsCommitOnImplThread();
1249}
1250
[email protected]c753e25a2012-10-19 21:22:421251void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141252{
1253 float pageScale = m_pageScaleAnimation->finalPageScale();
1254 IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
[email protected]1c0c9bc2012-10-08 22:41:481255 scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
[email protected]94f206c12012-08-25 00:09:141256 makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
1257}
1258
[email protected]c753e25a2012-10-19 21:22:421259void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
[email protected]94f206c12012-08-25 00:09:141260{
1261 if (!m_rootScrollLayerImpl)
1262 return;
1263
1264 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1265 // significant amount. This also ensures only one fake delta set will be
1266 // sent.
[email protected]23bbb412012-08-30 20:03:381267 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481268 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141269 return;
1270
1271 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1272 // out from the anchor point.
1273 IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481274 scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta());
1275 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1276 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]94f206c12012-08-25 00:09:141277 FloatSize scaledContentsSize = contentSize();
1278 scaledContentsSize.scale(pageScaleDeltaToSend);
1279
1280 FloatSize anchor = toSize(m_previousPinchAnchor);
1281 FloatSize scrollEnd = scrollBegin + anchor;
[email protected]1c0c9bc2012-10-08 22:41:481282 scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
[email protected]94f206c12012-08-25 00:09:141283 scrollEnd -= anchor;
1284 scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
1285 scrollEnd.scale(1 / pageScaleDeltaToSend);
1286 scrollEnd.scale(m_deviceScaleFactor);
1287
[email protected]1c0c9bc2012-10-08 22:41:481288 makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141289}
1290
[email protected]c753e25a2012-10-19 21:22:421291void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
[email protected]94f206c12012-08-25 00:09:141292{
1293 if (!m_rootScrollLayerImpl)
1294 return;
1295
[email protected]c753e25a2012-10-19 21:22:421296 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141297 scroll.layerId = m_rootScrollLayerImpl->id();
1298 scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
1299 scrollInfo->scrolls.append(scroll);
1300 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481301 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1302 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141303}
1304
[email protected]c753e25a2012-10-19 21:22:421305static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
[email protected]94f206c12012-08-25 00:09:141306{
1307 if (!layerImpl)
1308 return;
1309
1310 if (!layerImpl->scrollDelta().isZero()) {
1311 IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
[email protected]c753e25a2012-10-19 21:22:421312 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
[email protected]94f206c12012-08-25 00:09:141313 scroll.layerId = layerImpl->id();
1314 scroll.scrollDelta = scrollDelta;
1315 scrollInfo->scrolls.append(scroll);
1316 layerImpl->setSentScrollDelta(scrollDelta);
1317 }
1318
1319 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031320 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141321}
1322
[email protected]c753e25a2012-10-19 21:22:421323scoped_ptr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
[email protected]94f206c12012-08-25 00:09:141324{
[email protected]c753e25a2012-10-19 21:22:421325 scoped_ptr<CCScrollAndScaleSet> scrollInfo(new CCScrollAndScaleSet());
[email protected]94f206c12012-08-25 00:09:141326
1327 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481328 scrollInfo->pageScaleDelta = 1;
1329 m_pinchZoomViewport.setSentPageScaleDelta(1);
1330 // FIXME(aelias): Make these painting optimizations compatible with
1331 // compositor-side scaling.
[email protected]65bfd9972012-10-19 03:39:371332 if (!Settings::pageScalePinchZoomEnabled()) {
[email protected]1c0c9bc2012-10-08 22:41:481333 if (m_pinchGestureActive)
1334 computePinchZoomDeltas(scrollInfo.get());
1335 else if (m_pageScaleAnimation.get())
1336 computeDoubleTapZoomDeltas(scrollInfo.get());
1337 }
[email protected]a9f4bf22012-10-11 23:39:211338 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141339 }
1340
1341 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
[email protected]1c0c9bc2012-10-08 22:41:481342 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1343 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141344
[email protected]a9f4bf22012-10-11 23:39:211345 return scrollInfo.Pass();
[email protected]94f206c12012-08-25 00:09:141346}
1347
[email protected]c753e25a2012-10-19 21:22:421348WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const
[email protected]1c0c9bc2012-10-08 22:41:481349{
1350 return m_pinchZoomViewport.implTransform();
1351}
1352
[email protected]c753e25a2012-10-19 21:22:421353void CCLayerTreeHostImpl::setFullRootLayerDamage()
[email protected]94f206c12012-08-25 00:09:141354{
1355 if (m_rootLayerImpl) {
[email protected]c753e25a2012-10-19 21:22:421356 CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
[email protected]94f206c12012-08-25 00:09:141357 if (renderSurface)
1358 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1359 }
1360}
1361
[email protected]c753e25a2012-10-19 21:22:421362void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141363{
1364 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1365 return;
1366
1367 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
1368
[email protected]1c0c9bc2012-10-08 22:41:481369 setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141370 IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]1c0c9bc2012-10-08 22:41:481371 nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]94f206c12012-08-25 00:09:141372 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1373 m_client->setNeedsRedrawOnImplThread();
1374
1375 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
[email protected]0023e8b2012-10-15 12:52:451376 m_pageScaleAnimation.reset();
[email protected]94f206c12012-08-25 00:09:141377 m_client->setNeedsCommitOnImplThread();
1378 }
1379}
1380
[email protected]c753e25a2012-10-19 21:22:421381void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
[email protected]94f206c12012-08-25 00:09:141382{
[email protected]65bfd9972012-10-19 03:39:371383 if (!Settings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
[email protected]94f206c12012-08-25 00:09:141384 return;
1385
[email protected]c753e25a2012-10-19 21:22:421386 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
[email protected]94f206c12012-08-25 00:09:141387
[email protected]c753e25a2012-10-19 21:22:421388 scoped_ptr<CCAnimationEventsVector> events(make_scoped_ptr(new CCAnimationEventsVector));
[email protected]94f206c12012-08-25 00:09:141389
1390 bool didAnimate = false;
1391 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1392
[email protected]d3143c732012-10-05 19:17:591393 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571394 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141395
1396 if (didAnimate)
1397 m_client->setNeedsRedrawOnImplThread();
1398
1399 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1400}
1401
[email protected]c753e25a2012-10-19 21:22:421402base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141403{
[email protected]4481ddb622012-09-20 16:33:471404 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141405}
1406
[email protected]c753e25a2012-10-19 21:22:421407void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141408{
[email protected]1d993172012-10-18 18:15:041409 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141410 current->didLoseContext();
1411 if (current->maskLayer())
1412 sendDidLoseContextRecursive(current->maskLayer());
1413 if (current->replicaLayer())
1414 sendDidLoseContextRecursive(current->replicaLayer());
1415 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031416 sendDidLoseContextRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141417}
1418
[email protected]c753e25a2012-10-19 21:22:421419static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
[email protected]94f206c12012-08-25 00:09:141420{
[email protected]1d993172012-10-18 18:15:041421 DCHECK(current);
[email protected]94f206c12012-08-25 00:09:141422 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]c753e25a2012-10-19 21:22:421423 clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141424 current->clearRenderSurface();
1425}
1426
[email protected]c753e25a2012-10-19 21:22:421427void CCLayerTreeHostImpl::clearRenderSurfaces()
[email protected]94f206c12012-08-25 00:09:141428{
[email protected]c753e25a2012-10-19 21:22:421429 clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141430 m_renderSurfaceLayerList.clear();
1431}
1432
[email protected]c753e25a2012-10-19 21:22:421433std::string CCLayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141434{
[email protected]515e8d232012-09-10 19:15:271435 std::string str;
[email protected]94f206c12012-08-25 00:09:141436 if (m_rootLayerImpl) {
[email protected]515e8d232012-09-10 19:15:271437 str = m_rootLayerImpl->layerTreeAsText();
1438 str += "RenderSurfaces:\n";
1439 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141440 }
[email protected]515e8d232012-09-10 19:15:271441 return str;
[email protected]94f206c12012-08-25 00:09:141442}
1443
[email protected]c753e25a2012-10-19 21:22:421444void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141445{
1446 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271447 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141448
1449 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031450 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141451}
1452
[email protected]c753e25a2012-10-19 21:22:421453int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const
[email protected]94f206c12012-08-25 00:09:141454{
1455 return fpsCounter()->currentFrameNumber();
1456}
1457
[email protected]c753e25a2012-10-19 21:22:421458void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141459{
[email protected]8b9af6b2012-09-27 00:36:361460 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1461 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271462 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1463 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]94f206c12012-08-25 00:09:141464}
1465
[email protected]c753e25a2012-10-19 21:22:421466void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141467{
1468 animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime);
1469}
1470
[email protected]c753e25a2012-10-19 21:22:421471void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime)
[email protected]94f206c12012-08-25 00:09:141472{
1473 if (!layer)
1474 return;
1475
[email protected]c753e25a2012-10-19 21:22:421476 CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
[email protected]94f206c12012-08-25 00:09:141477 if (scrollbarController && scrollbarController->animate(monotonicTime))
1478 m_client->setNeedsRedrawOnImplThread();
1479
1480 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031481 animateScrollbarsRecursive(layer->children()[i], monotonicTime);
[email protected]94f206c12012-08-25 00:09:141482}
1483
[email protected]d3143c732012-10-05 19:17:591484} // namespace cc