Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: cc/CCLayerTreeHostImpl.cpp

Issue 11122003: [cc] Rename all cc/ filenames to Chromium style (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « cc/CCLayerTreeHostImpl.h ('k') | cc/CCMathUtil.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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
9 #include "base/basictypes.h"
10 #include "CCAppendQuadsData.h"
11 #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"
26 #include "CCRendererSoftware.h"
27 #include "CCRenderingStats.h"
28 #include "CCScrollbarAnimationController.h"
29 #include "CCScrollbarLayerImpl.h"
30 #include "CCSettings.h"
31 #include "CCSingleThreadProxy.h"
32 #include "TextureUploader.h"
33 #include "TraceEvent.h"
34 #include <wtf/CurrentTime.h>
35 #include <algorithm>
36
37 using WebKit::WebTransformationMatrix;
38
39 namespace {
40
41 void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible)
42 {
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
53 namespace cc {
54
55 CCPinchZoomViewport::CCPinchZoomViewport()
56 : m_pageScaleFactor(1)
57 , m_pageScaleDelta(1)
58 , m_sentPageScaleDelta(1)
59 , m_minPageScaleFactor(0)
60 , m_maxPageScaleFactor(0)
61 {
62 }
63
64 float CCPinchZoomViewport::totalPageScaleFactor() const
65 {
66 return m_pageScaleFactor * m_pageScaleDelta;
67 }
68
69 void 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
84 bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, flo at minPageScaleFactor, float maxPageScaleFactor)
85 {
86 ASSERT(pageScaleFactor);
87
88 if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && min PageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleF actor)
89 return false;
90
91 m_minPageScaleFactor = minPageScaleFactor;
92 m_maxPageScaleFactor = maxPageScaleFactor;
93
94 m_pageScaleFactor = pageScaleFactor;
95 return true;
96 }
97
98 FloatRect 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
109 FloatSize 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
143 WebTransformationMatrix 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
159 class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
160 public:
161 static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHo stImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
162 {
163 return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostIm pl, 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
187 private:
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;
197
198 DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter);
199 };
200
201 CCLayerTreeHostImpl::FrameData::FrameData()
202 {
203 }
204
205 CCLayerTreeHostImpl::FrameData::~FrameData()
206 {
207 }
208
209 scoped_ptr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSet tings& settings, CCLayerTreeHostImplClient* client)
210 {
211 return make_scoped_ptr(new CCLayerTreeHostImpl(settings, client));
212 }
213
214 CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CC LayerTreeHostImplClient* 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::defaultMemoryAll ocationLimit())
227 , 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())
233 , m_numImplThreadScrolls(0)
234 , m_numMainThreadScrolls(0)
235 {
236 ASSERT(CCProxy::isImplThread());
237 didVisibilityChange(this, m_visible);
238 }
239
240 CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
241 {
242 ASSERT(CCProxy::isImplThread());
243 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
244
245 if (m_rootLayerImpl)
246 clearRenderSurfaces();
247 }
248
249 void CCLayerTreeHostImpl::beginCommit()
250 {
251 }
252
253 void 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
261 bool CCLayerTreeHostImpl::canDraw()
262 {
263 // 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->onCanDrawStateC hanged
265 // in the proper places and update the notifyIfCanDrawChanged test.
266
267 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 textur es purged");
281 return false;
282 }
283 return true;
284 }
285
286 CCGraphicsContext* CCLayerTreeHostImpl::context() const
287 {
288 return m_context.get();
289 }
290
291 void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
292 {
293 animatePageScale(monotonicTime);
294 animateLayers(monotonicTime, wallClockTime);
295 animateScrollbars(monotonicTime);
296 }
297
298 void 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());
304 scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta());
305 float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor();
306 IntSize scaledContentSize = contentSize();
307 scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta());
308
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
323 void CCLayerTreeHostImpl::scheduleAnimation()
324 {
325 m_client->setNeedsRedrawOnImplThread();
326 }
327
328 void 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->surfacePropertyChangedOnl yFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer() , renderSurfaceLayer->filters());
339 }
340 }
341
342 void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
343 {
344 if (m_rootScrollLayerImpl) {
345 m_rootScrollLayerImpl->setImplTransform(implTransform());
346 }
347 }
348
349 void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSur faceLayerList)
350 {
351 ASSERT(renderSurfaceLayerList.empty());
352 ASSERT(m_rootLayerImpl);
353 ASSERT(m_renderer); // For maxTextureSize.
354
355 {
356 updateRootScrollLayerImplTransform();
357
358 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
359 CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), de viceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities(). maxTextureSize, renderSurfaceLayerList);
360
361 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList) ;
362 }
363 }
364
365 void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<CCRenderPass> r enderPass)
366 {
367 CCRenderPass* pass = renderPass.get();
368 renderPasses.push_back(pass);
369 renderPassesById.set(pass->id(), renderPass.Pass());
370 }
371
372 bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
373 {
374 ASSERT(frame.renderPasses.empty());
375
376 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
377
378 TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurf aceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerLi st->size()));
379
380 // Create the render passes in dependency order.
381 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceInd ex >= 0 ; --surfaceIndex) {
382 CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfac eIndex];
383 renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
384 }
385
386 bool recordMetricsForFrame = true; // FIXME: In the future, disable this whe n about:tracing is off.
387 CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->co ntentRect(), recordMetricsForFrame);
388 occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingS ize);
389
390 if (settings().showOccludingRects)
391 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingS creenSpaceRects);
392
393 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
394 typedef CCLayerIterator<CCLayerImpl, std::vector<CCLayerImpl*>, CCRenderSurf ace, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
395
396 // Typically when we are missing a texture and use a checkerboard quad, we s till draw the frame. However when the layer being
397 // checkerboarded is moving due to an impl-animation, we drop the frame to a void flashing due to the texture suddenly appearing
398 // in the future.
399 bool drawFrame = true;
400
401 CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerL ist);
402 for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurface LayerList); it != end; ++it) {
403 CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->ren derSurface()->renderPassId();
404 CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRender PassId);
405
406 occlusionTracker.enterLayer(it);
407
408 CCAppendQuadsData appendQuadsData(targetRenderPass->id());
409
410 if (it.representsContributingRenderSurface()) {
411 CCRenderPass::Id contributingRenderPassId = it->renderSurface()->ren derPassId();
412 CCRenderPass* contributingRenderPass = frame.renderPassesById.get(co ntributingRenderPassId);
413 targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributing RenderPass, &occlusionTracker, appendQuadsData);
414 } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) {
415 bool hasOcclusionFromOutsideTargetSurface;
416 if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcc lusionFromOutsideTargetSurface))
417 appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclu sionFromOutsideTargetSurface;
418 else {
419 it->willDraw(m_resourceProvider.get());
420 frame.willDrawLayers.push_back(*it);
421
422 if (it->hasContributingDelegatedRenderPasses()) {
423 CCRenderPass::Id contributingRenderPassId = it->firstContrib utingRenderPassId();
424 while (frame.renderPassesById.contains(contributingRenderPas sId)) {
425 CCRenderPass* renderPass = frame.renderPassesById.get(co ntributingRenderPassId);
426
427 CCAppendQuadsData appendQuadsData(renderPass->id());
428 renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
429
430 contributingRenderPassId = it->nextContributingRenderPas sId(contributingRenderPassId);
431 }
432 }
433
434 targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, ap pendQuadsData);
435 }
436 }
437
438 if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
439 targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true);
440
441 if (appendQuadsData.hadMissingTiles) {
442 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimatin g() || it->drawTransformIsAnimating();
443 if (layerHasAnimatingTransform || CCSettings::jankInsteadOfCheckerbo ard())
444 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);
454 ASSERT(frame.renderPassesById.contains(frame.renderPasses[i]->id()));
455 }
456 #endif
457
458 if (!m_hasTransparentBackground) {
459 frame.renderPasses.back()->setHasTransparentBackground(false);
460 frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get() , m_backgroundColor, occlusionTracker);
461 }
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
473 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double mo notonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAni mate, bool& needsAnimateLayers)
474 {
475 bool subtreeNeedsAnimateLayers = false;
476
477 CCLayerAnimationController* currentController = current->layerAnimationContr oller();
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 ani mation.
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;
493 animateLayersRecursive(current->children()[i], monotonicTime, wallClockT ime, events, didAnimate, childNeedsAnimateLayers);
494 if (childNeedsAnimateLayers)
495 subtreeNeedsAnimateLayers = true;
496 }
497
498 needsAnimateLayers = subtreeNeedsAnimateLayers;
499 }
500
501 void 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
510 IntSize 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
519 static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, co nst CCLayerTreeHostImpl::FrameData& frame)
520 {
521 CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(rende rPassId);
522 ASSERT(it != frame.renderPassesById.end());
523 return it->second;
524 }
525
526 static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCL ayerTreeHostImpl::FrameData& frame)
527 {
528 CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, fram e);
529 CCRenderPassList& renderPasses = frame.renderPasses;
530 CCRenderPassList::iterator toRemove = std::find(renderPasses.begin(), render Passes.end(), removeRenderPass);
531
532 // The pass was already removed by another quad - probably the original, and we are the replica.
533 if (toRemove == renderPasses.end())
534 return;
535
536 const CCRenderPass* removedPass = *toRemove;
537 frame.renderPasses.erase(toRemove);
538
539 // Now follow up for all RenderPass quads and remove their RenderPasses recu rsively.
540 const CCQuadList& quadList = removedPass->quadList();
541 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFront Begin();
542 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
543 CCDrawQuad* currentQuad = (*quadListIterator);
544 if (currentQuad->material() != CCDrawQuad::RenderPass)
545 continue;
546
547 CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::material Cast(currentQuad)->renderPassId();
548 removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
549 }
550 }
551
552 bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRender Pass(const CCRenderPassDrawQuad& quad, const FrameData&) const
553 {
554 return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCach edResourcesForRenderPassId(quad.renderPassId());
555 }
556
557 bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(co nst CCRenderPassDrawQuad& quad, const FrameData& frame) const
558 {
559 const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), fra me);
560 const CCRenderPassList& renderPasses = frame.renderPasses;
561 CCRenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
562
563 bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
564 if (renderPassAlreadyRemoved)
565 return false;
566
567 // If any quad or RenderPass draws into this RenderPass, then keep it.
568 const CCQuadList& quadList = (*foundPass)->quadList();
569 for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backTo FrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
570 CCDrawQuad* currentQuad = *quadListIterator;
571
572 if (currentQuad->material() != CCDrawQuad::RenderPass)
573 return false;
574
575 const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDr awQuad::materialCast(currentQuad)->renderPassId(), frame);
576 CCRenderPassList::const_iterator foundContributingPass = std::find(rende rPasses.begin(), renderPasses.end(), contributingPass);
577 if (foundContributingPass != renderPasses.end())
578 return false;
579 }
580 return true;
581 }
582
583 // Defined for linking tests.
584 template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullR enderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
585 template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullR enderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
586
587 // static
588 template<typename RenderPassCuller>
589 void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
590 {
591 for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culle r.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.backToF rontBegin();
595
596 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator ) {
597 CCDrawQuad* currentQuad = *quadListIterator;
598
599 if (currentQuad->material() != CCDrawQuad::RenderPass)
600 continue;
601
602 CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQ uad*>(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
619 bool 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 f unction is called again.
634 return true;
635 }
636
637 void CCLayerTreeHostImpl::releaseContentsTextures()
638 {
639 if (m_contentsTexturesPurged)
640 return;
641 m_client->releaseContentsTexturesOnImplThread();
642 setContentsTexturesPurged();
643 m_client->setNeedsCommitOnImplThread();
644 m_client->onCanDrawStateChanged(canDraw());
645 }
646
647 void 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
657 void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, dou ble intervalInSeconds)
658 {
659 m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds);
660 }
661
662 void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
663 {
664 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
665 ASSERT(canDraw());
666 ASSERT(!frame.renderPasses.empty());
667
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, t he 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()->di dDrawDamagedArea();
691 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
692 }
693
694 void 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());
698
699 // Once all layers have been drawn, pending texture uploads should no
700 // longer block future uploads.
701 m_resourceProvider->textureUploader()->markPendingUploadsAsNonBlocking();
702 }
703
704 void CCLayerTreeHostImpl::finishAllRendering()
705 {
706 if (m_renderer)
707 m_renderer->finish();
708 }
709
710 bool CCLayerTreeHostImpl::isContextLost()
711 {
712 return m_renderer && m_renderer->isContextLost();
713 }
714
715 const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const
716 {
717 return m_renderer->capabilities();
718 }
719
720 bool CCLayerTreeHostImpl::swapBuffers()
721 {
722 ASSERT(m_renderer);
723
724 m_fpsCounter->markEndOfFrame();
725 return m_renderer->swapBuffers();
726 }
727
728 const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const
729 {
730 return m_deviceViewportSize;
731 }
732
733 const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const
734 {
735 return m_settings;
736 }
737
738 void CCLayerTreeHostImpl::didLoseContext()
739 {
740 m_client->didLoseContextOnImplThread();
741 }
742
743 void CCLayerTreeHostImpl::onSwapBuffersComplete()
744 {
745 m_client->onSwapBuffersCompleteOnImplThread();
746 }
747
748 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
749 {
750 ASSERT(m_renderer);
751 m_renderer->getFramebufferPixels(pixels, rect);
752 }
753
754 static 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) {
763 CCLayerImpl* found = findRootScrollLayer(layer->children()[i]);
764 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.
774 static 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
788 void CCLayerTreeHostImpl::setRootLayer(scoped_ptr<CCLayerImpl> layer)
789 {
790 m_rootLayerImpl = layer.Pass();
791 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
792 m_currentlyScrollingLayerImpl = 0;
793
794 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
795 m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtre e(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
796
797 m_scrollingLayerIdFromPreviousTree = -1;
798
799 m_client->onCanDrawStateChanged(canDraw());
800 }
801
802 scoped_ptr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
803 {
804 // Clear all data structures that have direct references to the layer tree.
805 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_curre ntlyScrollingLayerImpl->id() : -1;
806 m_currentlyScrollingLayerImpl = 0;
807 m_renderSurfaceLayerList.clear();
808
809 return m_rootLayerImpl.Pass();
810 }
811
812 void 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
829 bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr<CCGraphicsContext> conte xt)
830 {
831 // 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.
834 if (m_rootLayerImpl) {
835 clearRenderSurfaces();
836 sendDidLoseContextRecursive(m_rootLayerImpl.get());
837 }
838 // Note: order is important here.
839 m_renderer.clear();
840 m_resourceProvider.clear();
841 m_context.reset();
842
843 if (!context->bindToClient(this))
844 return false;
845
846 OwnPtr<CCResourceProvider> resourceProvider = CCResourceProvider::create(con text.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(), co ntext->softwareDevice());
854 if (!m_renderer)
855 return false;
856
857 m_resourceProvider = resourceProvider.release();
858 m_context = context.Pass();
859
860 if (!m_visible)
861 m_renderer->setVisible(m_visible);
862
863 m_client->onCanDrawStateChanged(canDraw());
864
865 return true;
866 }
867
868 void CCLayerTreeHostImpl::setContentsTexturesPurged()
869 {
870 m_contentsTexturesPurged = true;
871 m_client->onCanDrawStateChanged(canDraw());
872 }
873
874 void CCLayerTreeHostImpl::resetContentsTexturesPurged()
875 {
876 m_contentsTexturesPurged = false;
877 m_client->onCanDrawStateChanged(canDraw());
878 }
879
880 void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, con st IntSize& deviceViewportSize)
881 {
882 if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_de viceViewportSize)
883 return;
884
885 m_layoutViewportSize = layoutViewportSize;
886 m_deviceViewportSize = deviceViewportSize;
887
888 m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
889
890 updateMaxScrollPosition();
891
892 if (m_renderer)
893 m_renderer->viewportChanged();
894
895 m_client->onCanDrawStateChanged(canDraw());
896 }
897
898 static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageSc aleChange)
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)
911 adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChang e);
912 }
913
914 void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
915 {
916 if (deviceScaleFactor == m_deviceScaleFactor)
917 return;
918 m_deviceScaleFactor = deviceScaleFactor;
919
920 updateMaxScrollPosition();
921 }
922
923 float CCLayerTreeHostImpl::pageScaleFactor() const
924 {
925 return m_pinchZoomViewport.pageScaleFactor();
926 }
927
928 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, flo at minPageScaleFactor, float maxPageScaleFactor)
929 {
930 if (!pageScaleFactor)
931 return;
932
933 float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFacto r();
934 m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScal eFactor, maxPageScaleFactor);
935
936 if (!CCSettings::pageScalePinchZoomEnabled()) {
937 if (pageScaleChange != 1)
938 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChan ge);
939 }
940
941 // Clamp delta to limits and refresh display matrix.
942 setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport .sentPageScaleDelta());
943 m_pinchZoomViewport.setSentPageScaleDelta(1);
944 }
945
946 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
947 {
948 m_pinchZoomViewport.setPageScaleDelta(delta);
949
950 updateMaxScrollPosition();
951 }
952
953 void 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 }
966
967 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);
980 maxScroll.scale(1 / m_deviceScaleFactor);
981
982 // 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
989 void CCLayerTreeHostImpl::setNeedsRedraw()
990 {
991 m_client->setNeedsRedrawOnImplThread();
992 }
993
994 bool 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
1015 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoi nt& 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(vi ewportPoint, 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.
1036 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThrea d) {
1037 m_numMainThreadScrolls++;
1038 return ScrollOnMainThread;
1039 }
1040
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, abo rt.
1048 if (status == ScrollOnMainThread) {
1049 m_numMainThreadScrolls++;
1050 return ScrollOnMainThread;
1051 }
1052
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 loca l layer coordinates
1060 // so that the scrolling contents exactly follow the user's finger. In c ontrast, wheel
1061 // events are already in local layer coordinates so we can just apply th em directly.
1062 m_scrollDeltaIsInScreenSpace = (type == Gesture);
1063 m_numImplThreadScrolls++;
1064 return ScrollStarted;
1065 }
1066 return ScrollIgnored;
1067 }
1068
1069 static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& scr eenSpaceDelta)
1070 {
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.screenSpaceT ransform().inverse();
1075
1076 // First project the scroll start and end points to local layer space to fin d the scroll delta
1077 // in layer coordinates.
1078 bool startClipped, endClipped;
1079 FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
1080 FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTran sform, screenSpacePoint, startClipped);
1081 FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransf orm, 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());
1091 FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
1092
1093 if (viewport)
1094 viewport->applyScroll(unscrolled);
1095
1096 // Calculate the applied scroll delta in screen space coordinates.
1097 FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
1098 FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screen SpaceTransform(), actualLocalEndPoint, endClipped);
1099 ASSERT(!endClipped);
1100 if (endClipped)
1101 return FloatSize();
1102 return actualScreenSpaceEndPoint - screenSpacePoint;
1103 }
1104
1105 static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSi ze& localDelta)
1106 {
1107 FloatSize previousDelta(layerImpl.scrollDelta());
1108 layerImpl.scrollBy(localDelta);
1109 return layerImpl.scrollDelta() - previousDelta;
1110 }
1111
1112 void 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; laye rImpl = layerImpl->parent()) {
1123 if (!layerImpl->scrollable())
1124 continue;
1125
1126 CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_ pinchZoomViewport : 0;
1127 FloatSize appliedDelta;
1128 if (m_scrollDeltaIsInScreenSpace)
1129 appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta);
1130 else
1131 appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
1132
1133 // If the layer wasn't able to move, try the next one in the hierarchy.
1134 float moveThresholdSquared = 0.1f * 0.1f;
1135 if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared)
1136 continue;
1137
1138 // If the applied delta is within 45 degrees of the input delta, bail ou t to make it easier
1139 // to scroll just one layer in one direction without affecting any of it s 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
1161 void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
1162 {
1163 m_currentlyScrollingLayerImpl = 0;
1164 m_scrollingLayerIdFromPreviousTree = -1;
1165 }
1166
1167 void CCLayerTreeHostImpl::scrollEnd()
1168 {
1169 clearCurrentlyScrollingLayer();
1170 }
1171
1172 void CCLayerTreeHostImpl::pinchGestureBegin()
1173 {
1174 m_pinchGestureActive = true;
1175 m_previousPinchAnchor = IntPoint();
1176
1177 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationContro ller())
1178 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBe gin();
1179 }
1180
1181 void 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.
1194 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() / pageScal eDelta);
1200 FloatSize move = previousScaleAnchor - newScaleAnchor;
1201
1202 m_previousPinchAnchor = anchor;
1203
1204 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_deviceScaleFac tor));
1207 }
1208
1209 FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled() ? m_pinch ZoomViewport.applyScroll(move) : move;
1210 m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow));
1211
1212 if (m_rootScrollLayerImpl->scrollbarAnimationController())
1213 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUp date();
1214
1215 m_client->setNeedsCommitOnImplThread();
1216 m_client->setNeedsRedrawOnImplThread();
1217 }
1218
1219 void CCLayerTreeHostImpl::pinchGestureEnd()
1220 {
1221 m_pinchGestureActive = false;
1222
1223 if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationContro ller())
1224 m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEn d();
1225
1226 m_client->setNeedsCommitOnImplThread();
1227 }
1228
1229 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scroll Info)
1230 {
1231 float pageScale = m_pageScaleAnimation->finalPageScale();
1232 IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
1233 scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
1234 makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
1235 }
1236
1237 void 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.
1245 const float pinchZoomOutSensitivity = 0.95f;
1246 if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
1247 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());
1252 scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta());
1253 float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
1254 float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pi nchZoomViewport.pageScaleFactor();
1255 FloatSize scaledContentsSize = contentSize();
1256 scaledContentsSize.scale(pageScaleDeltaToSend);
1257
1258 FloatSize anchor = toSize(m_previousPinchAnchor);
1259 FloatSize scrollEnd = scrollBegin + anchor;
1260 scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
1261 scrollEnd -= anchor;
1262 scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceV iewportSize)).expandedTo(FloatSize(0, 0));
1263 scrollEnd.scale(1 / pageScaleDeltaToSend);
1264 scrollEnd.scale(m_deviceScaleFactor);
1265
1266 makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomView port.minPageScaleFactor());
1267 }
1268
1269 void 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->scrollPosi tion());
1277 scrollInfo->scrolls.append(scroll);
1278 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
1279 scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor ();
1280 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
1281 }
1282
1283 static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* la yerImpl)
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)
1298 collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
1299 }
1300
1301 scoped_ptr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
1302 {
1303 scoped_ptr<CCScrollAndScaleSet> scrollInfo(new CCScrollAndScaleSet());
1304
1305 if (m_pinchGestureActive || m_pageScaleAnimation) {
1306 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 }
1316 return scrollInfo.Pass();
1317 }
1318
1319 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
1320 scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
1321 m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
1322
1323 return scrollInfo.Pass();
1324 }
1325
1326 WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const
1327 {
1328 return m_pinchZoomViewport.implTransform();
1329 }
1330
1331 void CCLayerTreeHostImpl::setFullRootLayerDamage()
1332 {
1333 if (m_rootLayerImpl) {
1334 CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
1335 if (renderSurface)
1336 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1337 }
1338 }
1339
1340 void 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
1347 setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_p inchZoomViewport.pageScaleFactor());
1348 IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime) ;
1349 nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
1350 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
1359 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTi me)
1360 {
1361 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || ! m_rootLayerImpl)
1362 return;
1363
1364 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
1365
1366 scoped_ptr<CCAnimationEventsVector> events(make_scoped_ptr(new CCAnimationEv entsVector));
1367
1368 bool didAnimate = false;
1369 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1370
1371 if (!events->empty())
1372 m_client->postAnimationEventsToMainThreadOnImplThread(events.Pass(), wal lClockTime);
1373
1374 if (didAnimate)
1375 m_client->setNeedsRedrawOnImplThread();
1376
1377 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1378 }
1379
1380 base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
1381 {
1382 return base::TimeDelta::FromSeconds(1);
1383 }
1384
1385 void 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)
1394 sendDidLoseContextRecursive(current->children()[i]);
1395 }
1396
1397 static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
1398 {
1399 ASSERT(current);
1400 for (size_t i = 0; i < current->children().size(); ++i)
1401 clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]);
1402 current->clearRenderSurface();
1403 }
1404
1405 void CCLayerTreeHostImpl::clearRenderSurfaces()
1406 {
1407 clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
1408 m_renderSurfaceLayerList.clear();
1409 }
1410
1411 std::string CCLayerTreeHostImpl::layerTreeAsText() const
1412 {
1413 std::string str;
1414 if (m_rootLayerImpl) {
1415 str = m_rootLayerImpl->layerTreeAsText();
1416 str += "RenderSurfaces:\n";
1417 dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
1418 }
1419 return str;
1420 }
1421
1422 void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const
1423 {
1424 if (layer->renderSurface())
1425 layer->renderSurface()->dumpSurface(str, indent);
1426
1427 for (size_t i = 0; i < layer->children().size(); ++i)
1428 dumpRenderSurfaces(str, indent, layer->children()[i]);
1429 }
1430
1431 int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const
1432 {
1433 return fpsCounter()->currentFrameNumber();
1434 }
1435
1436 void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const
1437 {
1438 stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
1439 stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
1440 stats->numImplThreadScrolls = m_numImplThreadScrolls;
1441 stats->numMainThreadScrolls = m_numMainThreadScrolls;
1442 }
1443
1444 void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime)
1445 {
1446 animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime);
1447 }
1448
1449 void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime)
1450 {
1451 if (!layer)
1452 return;
1453
1454 CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimat ionController();
1455 if (scrollbarController && scrollbarController->animate(monotonicTime))
1456 m_client->setNeedsRedrawOnImplThread();
1457
1458 for (size_t i = 0; i < layer->children().size(); ++i)
1459 animateScrollbarsRecursive(layer->children()[i], monotonicTime);
1460 }
1461
1462 } // namespace cc
OLDNEW
« no previous file with comments | « cc/CCLayerTreeHostImpl.h ('k') | cc/CCMathUtil.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698