blob: 02e3cd85ff3719f3320ebf77bf76a4e38bdce359 [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]fd2d4f22012-09-28 22:57:209#include "base/basictypes.h"
[email protected]89228202012-08-29 03:20:3010#include "CCAppendQuadsData.h"
[email protected]94f206c12012-08-25 00:09:1411#include "CCDamageTracker.h"
12#include "CCDebugRectHistory.h"
13#include "CCDelayBasedTimeSource.h"
14#include "CCFontAtlas.h"
15#include "CCFrameRateCounter.h"
16#include "CCHeadsUpDisplayLayerImpl.h"
17#include "CCLayerIterator.h"
18#include "CCLayerTreeHost.h"
19#include "CCLayerTreeHostCommon.h"
20#include "CCMathUtil.h"
21#include "CCOverdrawMetrics.h"
22#include "CCPageScaleAnimation.h"
23#include "CCPrioritizedTextureManager.h"
24#include "CCRenderPassDrawQuad.h"
25#include "CCRendererGL.h"
[email protected]d61675de42012-09-24 21:32:5726#include "CCRendererSoftware.h"
[email protected]94f206c12012-08-25 00:09:1427#include "CCRenderingStats.h"
28#include "CCScrollbarAnimationController.h"
29#include "CCScrollbarLayerImpl.h"
30#include "CCSettings.h"
31#include "CCSingleThreadProxy.h"
[email protected]b914e102012-10-02 08:11:5232#include "TextureUploader.h"
[email protected]94f206c12012-08-25 00:09:1433#include "TraceEvent.h"
34#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]9c88e562012-09-14 22:21:3041void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible)
[email protected]94f206c12012-08-25 00:09:1442{
43 if (visible) {
44 TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id);
45 return;
46 }
47
48 TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id);
49}
50
51} // namespace
52
[email protected]9c88e562012-09-14 22:21:3053namespace cc {
[email protected]94f206c12012-08-25 00:09:1454
[email protected]1c0c9bc2012-10-08 22:41:4855CCPinchZoomViewport::CCPinchZoomViewport()
56 : m_pageScaleFactor(1)
57 , m_pageScaleDelta(1)
58 , m_sentPageScaleDelta(1)
59 , m_minPageScaleFactor(0)
60 , m_maxPageScaleFactor(0)
61{
62}
63
64float CCPinchZoomViewport::totalPageScaleFactor() const
65{
66 return m_pageScaleFactor * m_pageScaleDelta;
67}
68
69void CCPinchZoomViewport::setPageScaleDelta(float delta)
70{
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
84bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
85{
86 ASSERT(pageScaleFactor);
87
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
98FloatRect CCPinchZoomViewport::bounds() const
99{
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
109FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta)
110{
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
143WebTransformationMatrix CCPinchZoomViewport::implTransform() const
144{
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.
150 if (CCSettings::pageScalePinchZoomEnabled()) {
151 transform.scale(m_pageScaleFactor);
152 transform.translate(-m_pinchViewportScrollDelta.x(),
153 -m_pinchViewportScrollDelta.y());
154 }
155
156 return transform;
157}
158
[email protected]94f206c12012-08-25 00:09:14159class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
[email protected]94f206c12012-08-25 00:09:14160public:
161 static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
162 {
163 return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
164 }
165 virtual ~CCLayerTreeHostImplTimeSourceAdapter()
166 {
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:
188 CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
189 : m_layerTreeHostImpl(layerTreeHostImpl)
190 , m_timeSource(timeSource)
191 {
192 m_timeSource->setClient(this);
193 }
194
195 CCLayerTreeHostImpl* m_layerTreeHostImpl;
196 RefPtr<CCDelayBasedTimeSource> m_timeSource;
[email protected]fd2d4f22012-09-28 22:57:20197
198 DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter);
[email protected]94f206c12012-08-25 00:09:14199};
200
[email protected]493067512012-09-19 23:34:10201CCLayerTreeHostImpl::FrameData::FrameData()
202{
203}
204
205CCLayerTreeHostImpl::FrameData::~FrameData()
206{
207}
208
[email protected]519281762012-10-06 20:06:39209scoped_ptr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
[email protected]94f206c12012-08-25 00:09:14210{
[email protected]db124002012-10-09 02:34:42211 return make_scoped_ptr(new CCLayerTreeHostImpl(settings, client));
[email protected]94f206c12012-08-25 00:09:14212}
213
214CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
215 : m_client(client)
216 , m_sourceFrameNumber(-1)
217 , m_rootScrollLayerImpl(0)
218 , m_currentlyScrollingLayerImpl(0)
219 , m_hudLayerImpl(0)
220 , m_scrollingLayerIdFromPreviousTree(-1)
221 , m_scrollDeltaIsInScreenSpace(false)
222 , m_settings(settings)
223 , m_deviceScaleFactor(1)
224 , m_visible(true)
225 , m_contentsTexturesPurged(false)
226 , 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)
231 , 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{
236 ASSERT(CCProxy::isImplThread());
237 didVisibilityChange(this, m_visible);
238}
239
240CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
241{
242 ASSERT(CCProxy::isImplThread());
243 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
244
245 if (m_rootLayerImpl)
246 clearRenderSurfaces();
247}
248
249void CCLayerTreeHostImpl::beginCommit()
250{
251}
252
253void CCLayerTreeHostImpl::commitComplete()
254{
255 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete");
256 // Recompute max scroll position; must be after layer content bounds are
257 // updated.
258 updateMaxScrollPosition();
259}
260
261bool CCLayerTreeHostImpl::canDraw()
262{
[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) {
268 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer");
269 return false;
270 }
271 if (deviceViewportSize().isEmpty()) {
272 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport");
273 return false;
274 }
275 if (!m_renderer) {
276 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no renderer");
277 return false;
278 }
279 if (m_contentsTexturesPurged) {
280 TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged");
281 return false;
282 }
283 return true;
284}
285
286CCGraphicsContext* CCLayerTreeHostImpl::context() const
287{
288 return m_context.get();
289}
290
291void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
292{
293 animatePageScale(monotonicTime);
294 animateLayers(monotonicTime, wallClockTime);
[email protected]94f206c12012-08-25 00:09:14295 animateScrollbars(monotonicTime);
296}
297
298void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
299{
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
309 m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime);
310
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]94f206c12012-08-25 00:09:14323void CCLayerTreeHostImpl::scheduleAnimation()
324{
325 m_client->setNeedsRedrawOnImplThread();
326}
327
328void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
329{
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) {
335 CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
336 CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
337 ASSERT(renderSurface);
338 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
339 }
340}
341
[email protected]1c0c9bc2012-10-08 22:41:48342void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
343{
344 if (m_rootScrollLayerImpl) {
345 m_rootScrollLayerImpl->setImplTransform(implTransform());
346 }
347}
348
[email protected]94f206c12012-08-25 00:09:14349void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
350{
[email protected]d58499a2012-10-09 22:27:47351 ASSERT(renderSurfaceLayerList.empty());
[email protected]94f206c12012-08-25 00:09:14352 ASSERT(m_rootLayerImpl);
353 ASSERT(m_renderer); // For maxTextureSize.
354
355 {
[email protected]1c0c9bc2012-10-08 22:41:48356 updateRootScrollLayerImplTransform();
357
[email protected]94f206c12012-08-25 00:09:14358 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]87cea5372012-09-26 18:59:56365void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<CCRenderPass> renderPass)
[email protected]467b3612012-08-28 07:41:16366{
367 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]94f206c12012-08-25 00:09:14372bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
373{
[email protected]0c2086b2012-10-05 19:10:34374 ASSERT(frame.renderPasses.empty());
[email protected]94f206c12012-08-25 00:09:14375
376 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
377
378 TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
379
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) {
382 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.
387 CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
388 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]d58499a2012-10-09 22:27:47394 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
401 CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList);
402 for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
[email protected]0f077a52012-09-08 01:45:24403 CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
[email protected]467b3612012-08-28 07:41:16404 CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
[email protected]94f206c12012-08-25 00:09:14405
406 occlusionTracker.enterLayer(it);
407
[email protected]7d929c02012-09-20 17:26:57408 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]0f077a52012-09-08 01:45:24411 CCRenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
[email protected]467b3612012-08-28 07:41:16412 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()) {
423 CCRenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
424 while (frame.renderPassesById.contains(contributingRenderPassId)) {
425 CCRenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
426
427 CCAppendQuadsData appendQuadsData(renderPass->id());
428 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]15dabb72012-10-04 20:07:29443 if (layerHasAnimatingTransform || CCSettings::jankInsteadOfCheckerboard())
[email protected]94f206c12012-08-25 00:09:14444 drawFrame = false;
445 }
446
447 occlusionTracker.leaveLayer(it);
448 }
449
450#if !ASSERT_DISABLED
451 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
452 for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j)
453 ASSERT(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0);
[email protected]467b3612012-08-28 07:41:16454 ASSERT(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
473void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
474{
475 bool subtreeNeedsAnimateLayers = false;
476
477 CCLayerAnimationController* currentController = current->layerAnimationController();
478
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
501void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
502{
503 // Lazily create the timeSource adapter so that we can vary the interval for testing.
504 if (!m_timeSourceClientAdapter)
505 m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread()));
506
507 m_timeSourceClientAdapter->setActive(enabled);
508}
509
510IntSize CCLayerTreeHostImpl::contentSize() const
511{
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]0f077a52012-09-08 01:45:24519static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, const CCLayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14520{
521 CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
522 ASSERT(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]0f077a52012-09-08 01:45:24526static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCLayerTreeHostImpl::FrameData& frame)
[email protected]94f206c12012-08-25 00:09:14527{
528 CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
[email protected]f8ad8342012-09-27 20:07:02529 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]f8ad8342012-09-27 20:07:02536 const CCRenderPass* removedPass = *toRemove;
537 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.
540 const CCQuadList& quadList = removedPass->quadList();
541 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
542 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]0920e24f2012-09-20 03:34:03543 CCDrawQuad* currentQuad = (*quadListIterator);
[email protected]94f206c12012-08-25 00:09:14544 if (currentQuad->material() != CCDrawQuad::RenderPass)
545 continue;
546
[email protected]0f077a52012-09-08 01:45:24547 CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId();
[email protected]94f206c12012-08-25 00:09:14548 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
549 }
550}
551
552bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData&) const
553{
554 return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
555}
556
557bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData& frame) const
558{
559 const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame);
[email protected]f8ad8342012-09-27 20:07:02560 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]f8ad8342012-09-27 20:07:02568 const CCQuadList& quadList = (*foundPass)->quadList();
[email protected]94f206c12012-08-25 00:09:14569 for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]0920e24f2012-09-20 03:34:03570 CCDrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14571
572 if (currentQuad->material() != CCDrawQuad::RenderPass)
573 return false;
574
575 const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame);
[email protected]f8ad8342012-09-27 20:07:02576 CCRenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
577 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.
584template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
585template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
586
587// static
588template<typename RenderPassCuller>
589void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
590{
591 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
592 const CCRenderPass* currentPass = frame.renderPasses[it];
593 const CCQuadList& quadList = currentPass->quadList();
594 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
595
596 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
[email protected]0920e24f2012-09-20 03:34:03597 CCDrawQuad* currentQuad = *quadListIterator;
[email protected]94f206c12012-08-25 00:09:14598
599 if (currentQuad->material() != CCDrawQuad::RenderPass)
600 continue;
601
602 CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
603 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;
614 ASSERT(it >= 0);
615 }
616 }
617}
618
619bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
620{
621 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw");
622 ASSERT(canDraw());
623
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
637void CCLayerTreeHostImpl::releaseContentsTextures()
638{
639 if (m_contentsTexturesPurged)
640 return;
[email protected]e1fc8b32012-09-18 20:29:09641 m_client->releaseContentsTexturesOnImplThread();
642 setContentsTexturesPurged();
[email protected]94f206c12012-08-25 00:09:14643 m_client->setNeedsCommitOnImplThread();
[email protected]8db2213c2012-09-05 22:08:21644 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14645}
646
647void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
648{
649 if (m_memoryAllocationLimitBytes == bytes)
650 return;
651 m_memoryAllocationLimitBytes = bytes;
652
653 ASSERT(bytes);
654 m_client->setNeedsCommitOnImplThread();
655}
656
657void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
658{
659 m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds);
660}
661
662void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
663{
664 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
665 ASSERT(canDraw());
[email protected]0c2086b2012-10-05 19:10:34666 ASSERT(!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.
671 m_fpsCounter->markBeginningOfFrame(currentTime());
672
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
694void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
695{
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.
701 m_resourceProvider->textureUploader()->markPendingUploadsAsNonBlocking();
[email protected]94f206c12012-08-25 00:09:14702}
703
704void CCLayerTreeHostImpl::finishAllRendering()
705{
706 if (m_renderer)
707 m_renderer->finish();
708}
709
710bool CCLayerTreeHostImpl::isContextLost()
711{
712 return m_renderer && m_renderer->isContextLost();
713}
714
715const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const
716{
717 return m_renderer->capabilities();
718}
719
720bool CCLayerTreeHostImpl::swapBuffers()
721{
722 ASSERT(m_renderer);
723
724 m_fpsCounter->markEndOfFrame();
725 return m_renderer->swapBuffers();
726}
727
[email protected]493067512012-09-19 23:34:10728const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const
729{
730 return m_deviceViewportSize;
731}
732
733const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const
734{
735 return m_settings;
736}
737
[email protected]94f206c12012-08-25 00:09:14738void CCLayerTreeHostImpl::didLoseContext()
739{
740 m_client->didLoseContextOnImplThread();
741}
742
743void CCLayerTreeHostImpl::onSwapBuffersComplete()
744{
745 m_client->onSwapBuffersCompleteOnImplThread();
746}
747
748void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
749{
750 ASSERT(m_renderer);
751 m_renderer->getFramebufferPixels(pixels, rect);
752}
753
754static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
755{
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]0920e24f2012-09-20 03:34:03763 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.
774static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
775{
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]a96abc2d2012-10-08 07:12:23788void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
[email protected]94f206c12012-08-25 00:09:14789{
[email protected]a96abc2d2012-10-08 07:12:23790 m_rootLayerImpl = layer;
[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)
795 m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
796
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]a96abc2d2012-10-08 07:12:23802PassOwnPtr<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]a96abc2d2012-10-08 07:12:23809 return m_rootLayerImpl.release();
[email protected]94f206c12012-08-25 00:09:14810}
811
812void CCLayerTreeHostImpl::setVisible(bool visible)
813{
814 ASSERT(CCProxy::isImplThread());
815
816 if (m_visible == visible)
817 return;
818 m_visible = visible;
819 didVisibilityChange(this, m_visible);
820
821 if (!m_renderer)
822 return;
823
824 m_renderer->setVisible(visible);
825
826 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
827}
828
[email protected]e28efacd2012-10-06 17:07:49829bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr<CCGraphicsContext> context)
[email protected]94f206c12012-08-25 00:09:14830{
[email protected]be3181652012-09-25 13:02:13831 // Since we will create a new resource provider, we cannot continue to use
832 // the old resources (i.e. renderSurfaces and texture IDs). Clear them
833 // before we destroy the old resource provider.
[email protected]94f206c12012-08-25 00:09:14834 if (m_rootLayerImpl) {
835 clearRenderSurfaces();
836 sendDidLoseContextRecursive(m_rootLayerImpl.get());
837 }
[email protected]be3181652012-09-25 13:02:13838 // Note: order is important here.
839 m_renderer.clear();
840 m_resourceProvider.clear();
[email protected]e28efacd2012-10-06 17:07:49841 m_context.reset();
[email protected]94f206c12012-08-25 00:09:14842
[email protected]be3181652012-09-25 13:02:13843 if (!context->bindToClient(this))
844 return false;
845
846 OwnPtr<CCResourceProvider> resourceProvider = CCResourceProvider::create(context.get());
847 if (!resourceProvider)
848 return false;
849
850 if (context->context3D())
851 m_renderer = CCRendererGL::create(this, resourceProvider.get());
852 else if (context->softwareDevice())
853 m_renderer = CCRendererSoftware::create(this, resourceProvider.get(), context->softwareDevice());
854 if (!m_renderer)
855 return false;
856
[email protected]94f206c12012-08-25 00:09:14857 m_resourceProvider = resourceProvider.release();
[email protected]e28efacd2012-10-06 17:07:49858 m_context = context.Pass();
[email protected]94f206c12012-08-25 00:09:14859
[email protected]be3181652012-09-25 13:02:13860 if (!m_visible)
861 m_renderer->setVisible(m_visible);
[email protected]94f206c12012-08-25 00:09:14862
[email protected]8db2213c2012-09-05 22:08:21863 m_client->onCanDrawStateChanged(canDraw());
864
[email protected]be3181652012-09-25 13:02:13865 return true;
[email protected]94f206c12012-08-25 00:09:14866}
867
[email protected]e1fc8b32012-09-18 20:29:09868void CCLayerTreeHostImpl::setContentsTexturesPurged()
869{
870 m_contentsTexturesPurged = true;
871 m_client->onCanDrawStateChanged(canDraw());
872}
873
[email protected]8db2213c2012-09-05 22:08:21874void CCLayerTreeHostImpl::resetContentsTexturesPurged()
875{
876 m_contentsTexturesPurged = false;
877 m_client->onCanDrawStateChanged(canDraw());
878}
879
[email protected]94f206c12012-08-25 00:09:14880void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
881{
882 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
883 return;
884
885 m_layoutViewportSize = layoutViewportSize;
886 m_deviceViewportSize = deviceViewportSize;
887
[email protected]1c0c9bc2012-10-08 22:41:48888 m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
889
[email protected]94f206c12012-08-25 00:09:14890 updateMaxScrollPosition();
891
892 if (m_renderer)
893 m_renderer->viewportChanged();
[email protected]8db2213c2012-09-05 22:08:21894
895 m_client->onCanDrawStateChanged(canDraw());
[email protected]94f206c12012-08-25 00:09:14896}
897
898static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)
899{
900 if (!layerImpl)
901 return;
902
903 if (layerImpl->scrollable()) {
904 // We need to convert impl-side scroll deltas to pageScale space.
905 FloatSize scrollDelta = layerImpl->scrollDelta();
906 scrollDelta.scale(pageScaleChange);
907 layerImpl->setScrollDelta(scrollDelta);
908 }
909
910 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:03911 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
[email protected]94f206c12012-08-25 00:09:14912}
913
914void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
915{
916 if (deviceScaleFactor == m_deviceScaleFactor)
917 return;
918 m_deviceScaleFactor = deviceScaleFactor;
[email protected]c0dd24c2012-08-30 23:25:27919
920 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14921}
922
[email protected]1c0c9bc2012-10-08 22:41:48923float CCLayerTreeHostImpl::pageScaleFactor() const
[email protected]94f206c12012-08-25 00:09:14924{
[email protected]1c0c9bc2012-10-08 22:41:48925 return m_pinchZoomViewport.pageScaleFactor();
926}
[email protected]94f206c12012-08-25 00:09:14927
[email protected]1c0c9bc2012-10-08 22:41:48928void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
929{
930 if (!pageScaleFactor)
931 return;
[email protected]94f206c12012-08-25 00:09:14932
[email protected]1c0c9bc2012-10-08 22:41:48933 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
934 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
[email protected]94f206c12012-08-25 00:09:14935
[email protected]1c0c9bc2012-10-08 22:41:48936 if (!CCSettings::pageScalePinchZoomEnabled()) {
937 if (pageScaleChange != 1)
938 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
939 }
[email protected]94f206c12012-08-25 00:09:14940
941 // Clamp delta to limits and refresh display matrix.
[email protected]1c0c9bc2012-10-08 22:41:48942 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
943 m_pinchZoomViewport.setSentPageScaleDelta(1);
[email protected]94f206c12012-08-25 00:09:14944}
945
946void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
947{
[email protected]1c0c9bc2012-10-08 22:41:48948 m_pinchZoomViewport.setPageScaleDelta(delta);
[email protected]94f206c12012-08-25 00:09:14949
950 updateMaxScrollPosition();
[email protected]94f206c12012-08-25 00:09:14951}
952
953void CCLayerTreeHostImpl::updateMaxScrollPosition()
954{
955 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
956 return;
957
958 FloatSize viewBounds = m_deviceViewportSize;
959 if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
960 // Compensate for non-overlay scrollbars.
961 if (clipLayer->masksToBounds()) {
962 viewBounds = clipLayer->bounds();
963 viewBounds.scale(m_deviceScaleFactor);
964 }
965 }
[email protected]94f206c12012-08-25 00:09:14966
[email protected]1c0c9bc2012-10-08 22:41:48967 IntSize contentBounds = contentSize();
968 if (CCSettings::pageScalePinchZoomEnabled()) {
969 // Pinch with pageScale scrolls entirely in layout space. contentSize
970 // returns the bounds including the page scale factor, so calculate the
971 // pre page-scale layout size here.
972 float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
973 contentBounds.setWidth(contentBounds.width() / pageScaleFactor);
974 contentBounds.setHeight(contentBounds.height() / pageScaleFactor);
975 } else {
976 viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta());
977 }
978
979 IntSize maxScroll = contentBounds - expandedIntSize(viewBounds);
[email protected]94f206c12012-08-25 00:09:14980 maxScroll.scale(1 / m_deviceScaleFactor);
[email protected]1c0c9bc2012-10-08 22:41:48981
[email protected]94f206c12012-08-25 00:09:14982 // The viewport may be larger than the contents in some cases, such as
983 // having a vertical scrollbar but no horizontal overflow.
984 maxScroll.clampNegativeToZero();
985
986 m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
987}
988
989void CCLayerTreeHostImpl::setNeedsRedraw()
990{
991 m_client->setNeedsRedrawOnImplThread();
992}
993
994bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList()
995{
996 if (!m_rootLayerImpl)
997 return false;
998 if (!m_renderer)
999 return false;
1000
1001 // We need both a non-empty render surface layer list and a root render
1002 // surface to be able to iterate over the visible layers.
1003 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
1004 return true;
1005
1006 // If we are called after setRootLayer() but before prepareToDraw(), we need
1007 // to recalculate the visible layers. This prevents being unable to scroll
1008 // during part of a commit.
1009 m_renderSurfaceLayerList.clear();
1010 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
1011
1012 return m_renderSurfaceLayerList.size();
1013}
1014
1015CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
1016{
1017 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin");
1018
1019 ASSERT(!m_currentlyScrollingLayerImpl);
1020 clearCurrentlyScrollingLayer();
1021
1022 if (!ensureRenderSurfaceLayerList())
1023 return ScrollIgnored;
1024
1025 IntPoint deviceViewportPoint = viewportPoint;
1026 deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
1027
1028 // First find out which layer was hit from the saved list of visible layers
1029 // in the most recent frame.
1030 CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(viewportPoint, m_renderSurfaceLayerList);
1031
1032 // Walk up the hierarchy and look for a scrollable layer.
1033 CCLayerImpl* potentiallyScrollingLayerImpl = 0;
1034 for (; layerImpl; layerImpl = layerImpl->parent()) {
1035 // The content layer can also block attempts to scroll outside the main thread.
[email protected]5c6fe1f82012-10-03 18:00:271036 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
1037 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141038 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271039 }
[email protected]94f206c12012-08-25 00:09:141040
1041 CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
1042 if (!scrollLayerImpl)
1043 continue;
1044
1045 ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type);
1046
1047 // If any layer wants to divert the scroll event to the main thread, abort.
[email protected]5c6fe1f82012-10-03 18:00:271048 if (status == ScrollOnMainThread) {
1049 m_numMainThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141050 return ScrollOnMainThread;
[email protected]5c6fe1f82012-10-03 18:00:271051 }
[email protected]94f206c12012-08-25 00:09:141052
1053 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
1054 potentiallyScrollingLayerImpl = scrollLayerImpl;
1055 }
1056
1057 if (potentiallyScrollingLayerImpl) {
1058 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
1059 // Gesture events need to be transformed from screen coordinates to local layer coordinates
1060 // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
1061 // events are already in local layer coordinates so we can just apply them directly.
1062 m_scrollDeltaIsInScreenSpace = (type == Gesture);
[email protected]5c6fe1f82012-10-03 18:00:271063 m_numImplThreadScrolls++;
[email protected]94f206c12012-08-25 00:09:141064 return ScrollStarted;
1065 }
1066 return ScrollIgnored;
1067}
1068
[email protected]1c0c9bc2012-10-08 22:41:481069static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta)
[email protected]94f206c12012-08-25 00:09:141070{
1071 // Layers with non-invertible screen space transforms should not have passed the scroll hit
1072 // test in the first place.
1073 ASSERT(layerImpl.screenSpaceTransform().isInvertible());
1074 WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse();
1075
1076 // First project the scroll start and end points to local layer space to find the scroll delta
1077 // in layer coordinates.
1078 bool startClipped, endClipped;
1079 FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1080 FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
1081 FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
1082
1083 // In general scroll point coordinates should not get clipped.
1084 ASSERT(!startClipped);
1085 ASSERT(!endClipped);
1086 if (startClipped || endClipped)
1087 return FloatSize();
1088
1089 // Apply the scroll delta.
1090 FloatSize previousDelta(layerImpl.scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481091 FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
1092
1093 if (viewport)
1094 viewport->applyScroll(unscrolled);
[email protected]94f206c12012-08-25 00:09:141095
1096 // Calculate the applied scroll delta in screen space coordinates.
1097 FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
1098 FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalEndPoint, endClipped);
1099 ASSERT(!endClipped);
1100 if (endClipped)
1101 return FloatSize();
1102 return actualScreenSpaceEndPoint - screenSpacePoint;
1103}
1104
1105static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSize& localDelta)
1106{
1107 FloatSize previousDelta(layerImpl.scrollDelta());
1108 layerImpl.scrollBy(localDelta);
1109 return layerImpl.scrollDelta() - previousDelta;
1110}
1111
1112void CCLayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta)
1113{
1114 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy");
1115 if (!m_currentlyScrollingLayerImpl)
1116 return;
1117
1118 FloatSize pendingDelta(scrollDelta);
1119
1120 pendingDelta.scale(m_deviceScaleFactor);
1121
1122 for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
1123 if (!layerImpl->scrollable())
1124 continue;
1125
[email protected]1c0c9bc2012-10-08 22:41:481126 CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
[email protected]94f206c12012-08-25 00:09:141127 FloatSize appliedDelta;
1128 if (m_scrollDeltaIsInScreenSpace)
[email protected]1c0c9bc2012-10-08 22:41:481129 appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta);
[email protected]94f206c12012-08-25 00:09:141130 else
1131 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1132
1133 // If the layer wasn't able to move, try the next one in the hierarchy.
[email protected]23bbb412012-08-30 20:03:381134 float moveThresholdSquared = 0.1f * 0.1f;
[email protected]94f206c12012-08-25 00:09:141135 if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared)
1136 continue;
1137
1138 // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
1139 // to scroll just one layer in one direction without affecting any of its parents.
1140 float angleThreshold = 45;
1141 if (CCMathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
1142 pendingDelta = FloatSize();
1143 break;
1144 }
1145
1146 // Allow further movement only on an axis perpendicular to the direction in which the layer
1147 // moved.
1148 FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width());
1149 pendingDelta = CCMathUtil::projectVector(pendingDelta, perpendicularAxis);
1150
1151 if (flooredIntSize(pendingDelta).isZero())
1152 break;
1153 }
1154
1155 if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) {
1156 m_client->setNeedsCommitOnImplThread();
1157 m_client->setNeedsRedrawOnImplThread();
1158 }
1159}
1160
1161void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
1162{
1163 m_currentlyScrollingLayerImpl = 0;
1164 m_scrollingLayerIdFromPreviousTree = -1;
1165}
1166
1167void CCLayerTreeHostImpl::scrollEnd()
1168{
1169 clearCurrentlyScrollingLayer();
1170}
1171
1172void CCLayerTreeHostImpl::pinchGestureBegin()
1173{
1174 m_pinchGestureActive = true;
1175 m_previousPinchAnchor = IntPoint();
1176
1177 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1178 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
1179}
1180
1181void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
1182 const IntPoint& anchor)
1183{
1184 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate");
1185
1186 if (!m_rootScrollLayerImpl)
1187 return;
1188
1189 if (m_previousPinchAnchor == IntPoint::zero())
1190 m_previousPinchAnchor = anchor;
1191
1192 // Keep the center-of-pinch anchor specified by (x, y) in a stable
1193 // position over the course of the magnify.
[email protected]1c0c9bc2012-10-08 22:41:481194 float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1195 FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta,
1196 m_previousPinchAnchor.y() / pageScaleDelta);
1197 setPageScaleDelta(pageScaleDelta * magnifyDelta);
1198 pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1199 FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141200 FloatSize move = previousScaleAnchor - newScaleAnchor;
1201
1202 m_previousPinchAnchor = anchor;
1203
[email protected]1c0c9bc2012-10-08 22:41:481204 if (CCSettings::pageScalePinchZoomEnabled()) {
1205 // Compute the application of the delta with respect to the current page zoom of the page.
1206 move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor));
1207 }
1208
1209 FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move;
1210 m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow));
[email protected]94f206c12012-08-25 00:09:141211
1212 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1213 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
1214
1215 m_client->setNeedsCommitOnImplThread();
1216 m_client->setNeedsRedrawOnImplThread();
1217}
1218
1219void CCLayerTreeHostImpl::pinchGestureEnd()
1220{
1221 m_pinchGestureActive = false;
1222
1223 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
1224 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
1225
1226 m_client->setNeedsCommitOnImplThread();
1227}
1228
1229void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
1230{
1231 float pageScale = m_pageScaleAnimation->finalPageScale();
1232 IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
[email protected]1c0c9bc2012-10-08 22:41:481233 scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
[email protected]94f206c12012-08-25 00:09:141234 makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
1235}
1236
1237void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
1238{
1239 if (!m_rootScrollLayerImpl)
1240 return;
1241
1242 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
1243 // significant amount. This also ensures only one fake delta set will be
1244 // sent.
[email protected]23bbb412012-08-30 20:03:381245 const float pinchZoomOutSensitivity = 0.95f;
[email protected]1c0c9bc2012-10-08 22:41:481246 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
[email protected]94f206c12012-08-25 00:09:141247 return;
1248
1249 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
1250 // out from the anchor point.
1251 IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
[email protected]1c0c9bc2012-10-08 22:41:481252 scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta());
1253 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1254 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
[email protected]94f206c12012-08-25 00:09:141255 FloatSize scaledContentsSize = contentSize();
1256 scaledContentsSize.scale(pageScaleDeltaToSend);
1257
1258 FloatSize anchor = toSize(m_previousPinchAnchor);
1259 FloatSize scrollEnd = scrollBegin + anchor;
[email protected]1c0c9bc2012-10-08 22:41:481260 scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
[email protected]94f206c12012-08-25 00:09:141261 scrollEnd -= anchor;
1262 scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
1263 scrollEnd.scale(1 / pageScaleDeltaToSend);
1264 scrollEnd.scale(m_deviceScaleFactor);
1265
[email protected]1c0c9bc2012-10-08 22:41:481266 makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141267}
1268
1269void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
1270{
1271 if (!m_rootScrollLayerImpl)
1272 return;
1273
1274 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
1275 scroll.layerId = m_rootScrollLayerImpl->id();
1276 scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
1277 scrollInfo->scrolls.append(scroll);
1278 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
[email protected]1c0c9bc2012-10-08 22:41:481279 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
1280 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141281}
1282
1283static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
1284{
1285 if (!layerImpl)
1286 return;
1287
1288 if (!layerImpl->scrollDelta().isZero()) {
1289 IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
1290 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
1291 scroll.layerId = layerImpl->id();
1292 scroll.scrollDelta = scrollDelta;
1293 scrollInfo->scrolls.append(scroll);
1294 layerImpl->setSentScrollDelta(scrollDelta);
1295 }
1296
1297 for (size_t i = 0; i < layerImpl->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031298 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
[email protected]94f206c12012-08-25 00:09:141299}
1300
1301PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
1302{
1303 OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
1304
1305 if (m_pinchGestureActive || m_pageScaleAnimation) {
[email protected]1c0c9bc2012-10-08 22:41:481306 scrollInfo->pageScaleDelta = 1;
1307 m_pinchZoomViewport.setSentPageScaleDelta(1);
1308 // FIXME(aelias): Make these painting optimizations compatible with
1309 // compositor-side scaling.
1310 if (!CCSettings::pageScalePinchZoomEnabled()) {
1311 if (m_pinchGestureActive)
1312 computePinchZoomDeltas(scrollInfo.get());
1313 else if (m_pageScaleAnimation.get())
1314 computeDoubleTapZoomDeltas(scrollInfo.get());
1315 }
[email protected]94f206c12012-08-25 00:09:141316 return scrollInfo.release();
1317 }
1318
1319 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
[email protected]1c0c9bc2012-10-08 22:41:481320 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1321 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
[email protected]94f206c12012-08-25 00:09:141322
1323 return scrollInfo.release();
1324}
1325
[email protected]1c0c9bc2012-10-08 22:41:481326WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const
1327{
1328 return m_pinchZoomViewport.implTransform();
1329}
1330
[email protected]94f206c12012-08-25 00:09:141331void CCLayerTreeHostImpl::setFullRootLayerDamage()
1332{
1333 if (m_rootLayerImpl) {
1334 CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
1335 if (renderSurface)
1336 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1337 }
1338}
1339
1340void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
1341{
1342 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1343 return;
1344
1345 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
1346
[email protected]1c0c9bc2012-10-08 22:41:481347 setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
[email protected]94f206c12012-08-25 00:09:141348 IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
[email protected]1c0c9bc2012-10-08 22:41:481349 nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
[email protected]94f206c12012-08-25 00:09:141350 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1351 m_client->setNeedsRedrawOnImplThread();
1352
1353 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
1354 m_pageScaleAnimation.clear();
1355 m_client->setNeedsCommitOnImplThread();
1356 }
1357}
1358
1359void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
1360{
1361 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
1362 return;
1363
1364 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
1365
[email protected]ec1d6d52012-10-10 01:28:571366 scoped_ptr<CCAnimationEventsVector> events(make_scoped_ptr(new CCAnimationEventsVector));
[email protected]94f206c12012-08-25 00:09:141367
1368 bool didAnimate = false;
1369 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1370
[email protected]d3143c732012-10-05 19:17:591371 if (!events->empty())
[email protected]ec1d6d52012-10-10 01:28:571372 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wallClockTime);
[email protected]94f206c12012-08-25 00:09:141373
1374 if (didAnimate)
1375 m_client->setNeedsRedrawOnImplThread();
1376
1377 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1378}
1379
[email protected]4481ddb622012-09-20 16:33:471380base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
[email protected]94f206c12012-08-25 00:09:141381{
[email protected]4481ddb622012-09-20 16:33:471382 return base::TimeDelta::FromSeconds(1);
[email protected]94f206c12012-08-25 00:09:141383}
1384
1385void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
1386{
1387 ASSERT(current);
1388 current->didLoseContext();
1389 if (current->maskLayer())
1390 sendDidLoseContextRecursive(current->maskLayer());
1391 if (current->replicaLayer())
1392 sendDidLoseContextRecursive(current->replicaLayer());
1393 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031394 sendDidLoseContextRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141395}
1396
1397static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
1398{
1399 ASSERT(current);
1400 for (size_t i = 0; i < current->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031401 clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]);
[email protected]94f206c12012-08-25 00:09:141402 current->clearRenderSurface();
1403}
1404
1405void CCLayerTreeHostImpl::clearRenderSurfaces()
1406{
1407 clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
1408 m_renderSurfaceLayerList.clear();
1409}
1410
[email protected]515e8d232012-09-10 19:15:271411std::string CCLayerTreeHostImpl::layerTreeAsText() const
[email protected]94f206c12012-08-25 00:09:141412{
[email protected]515e8d232012-09-10 19:15:271413 std::string str;
[email protected]94f206c12012-08-25 00:09:141414 if (m_rootLayerImpl) {
[email protected]515e8d232012-09-10 19:15:271415 str = m_rootLayerImpl->layerTreeAsText();
1416 str += "RenderSurfaces:\n";
1417 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
[email protected]94f206c12012-08-25 00:09:141418 }
[email protected]515e8d232012-09-10 19:15:271419 return str;
[email protected]94f206c12012-08-25 00:09:141420}
1421
[email protected]515e8d232012-09-10 19:15:271422void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const
[email protected]94f206c12012-08-25 00:09:141423{
1424 if (layer->renderSurface())
[email protected]515e8d232012-09-10 19:15:271425 layer->renderSurface()->dumpSurface(str, indent);
[email protected]94f206c12012-08-25 00:09:141426
1427 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031428 dumpRenderSurfaces(str, indent, layer->children()[i]);
[email protected]94f206c12012-08-25 00:09:141429}
1430
[email protected]94f206c12012-08-25 00:09:141431int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const
1432{
1433 return fpsCounter()->currentFrameNumber();
1434}
1435
[email protected]8b9af6b2012-09-27 00:36:361436void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const
[email protected]94f206c12012-08-25 00:09:141437{
[email protected]8b9af6b2012-09-27 00:36:361438 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1439 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
[email protected]5c6fe1f82012-10-03 18:00:271440 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1441 stats->numMainThreadScrolls = m_numMainThreadScrolls;
[email protected]94f206c12012-08-25 00:09:141442}
1443
1444void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime)
1445{
1446 animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime);
1447}
1448
1449void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime)
1450{
1451 if (!layer)
1452 return;
1453
1454 CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
1455 if (scrollbarController && scrollbarController->animate(monotonicTime))
1456 m_client->setNeedsRedrawOnImplThread();
1457
1458 for (size_t i = 0; i < layer->children().size(); ++i)
[email protected]0920e24f2012-09-20 03:34:031459 animateScrollbarsRecursive(layer->children()[i], monotonicTime);
[email protected]94f206c12012-08-25 00:09:141460}
1461
[email protected]d3143c732012-10-05 19:17:591462} // namespace cc