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

Side by Side Diff: ui/cc/cc/CCLayerTreeHostImpl.cpp

Issue 10701016: Initial import attempt, just to play with. Many things disabled/removed (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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 | « ui/cc/cc/CCLayerTreeHostImpl.h ('k') | ui/cc/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 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN Y
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN Y
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O N
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25 #include "config.h"
26
27 #include "cc/CCLayerTreeHostImpl.h"
28
29 #include "LayerRendererChromium.h"
30 #include "TextStream.h"
31 #include "TraceEvent.h"
32 #include "TrackingTextureAllocator.h"
33 #include "cc/CCActiveGestureAnimation.h"
34 #include "cc/CCDamageTracker.h"
35 #include "cc/CCDebugRectHistory.h"
36 #include "cc/CCDelayBasedTimeSource.h"
37 #include "cc/CCFontAtlas.h"
38 #include "cc/CCFrameRateCounter.h"
39 #include "cc/CCHeadsUpDisplay.h"
40 #include "cc/CCLayerIterator.h"
41 #include "cc/CCLayerTreeHost.h"
42 #include "cc/CCLayerTreeHostCommon.h"
43 #include "cc/CCOverdrawMetrics.h"
44 #include "cc/CCPageScaleAnimation.h"
45 #include "cc/CCRenderPassDrawQuad.h"
46 #include "cc/CCSettings.h"
47 #include "cc/CCSingleThreadProxy.h"
48 #include <wtf/CurrentTime.h>
49
50 using WebKit::WebTransformationMatrix;
51
52 namespace {
53
54 void didVisibilityChange(WebCore::CCLayerTreeHostImpl* id, bool visible)
55 {
56 if (visible) {
57 TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id , "CCLayerTreeHostImpl", id);
58 return;
59 }
60
61 TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id);
62 }
63
64 } // namespace
65
66 namespace WebCore {
67
68 class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
69 WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter);
70 public:
71 static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHo stImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
72 {
73 return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostIm pl, timeSource));
74 }
75 virtual ~CCLayerTreeHostImplTimeSourceAdapter()
76 {
77 m_timeSource->setClient(0);
78 m_timeSource->setActive(false);
79 }
80
81 virtual void onTimerTick() OVERRIDE
82 {
83 // FIXME: We require that animate be called on the impl thread. This
84 // avoids asserts in single threaded mode. Ideally background ticking
85 // would be handled by the proxy/scheduler and this could be removed.
86 DebugScopedSetImplThread impl;
87
88 m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime( ));
89 }
90
91 void setActive(bool active)
92 {
93 if (active != m_timeSource->active())
94 m_timeSource->setActive(active);
95 }
96
97 private:
98 CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
99 : m_layerTreeHostImpl(layerTreeHostImpl)
100 , m_timeSource(timeSource)
101 {
102 m_timeSource->setClient(this);
103 }
104
105 CCLayerTreeHostImpl* m_layerTreeHostImpl;
106 RefPtr<CCDelayBasedTimeSource> m_timeSource;
107 };
108
109 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSet tings& settings, CCLayerTreeHostImplClient* client)
110 {
111 return adoptPtr(new CCLayerTreeHostImpl(settings, client));
112 }
113
114 CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CC LayerTreeHostImplClient* client)
115 : m_client(client)
116 , m_sourceFrameNumber(-1)
117 , m_sourceAnimationFrameNumber(0)
118 , m_rootScrollLayerImpl(0)
119 , m_currentlyScrollingLayerImpl(0)
120 , m_scrollingLayerIdFromPreviousTree(-1)
121 , m_settings(settings)
122 , m_deviceScaleFactor(1)
123 , m_visible(true)
124 , m_contentsTexturesWerePurgedSinceLastCommit(false)
125 , m_memoryAllocationLimitBytes(TextureManager::highLimitBytes(viewportSize() ))
126 , m_headsUpDisplay(CCHeadsUpDisplay::create())
127 , m_pageScale(1)
128 , m_pageScaleDelta(1)
129 , m_sentPageScaleDelta(1)
130 , m_minPageScale(0)
131 , m_maxPageScale(0)
132 , m_backgroundColor(0)
133 , m_hasTransparentBackground(false)
134 , m_needsAnimateLayers(false)
135 , m_pinchGestureActive(false)
136 , m_fpsCounter(CCFrameRateCounter::create())
137 , m_debugRectHistory(CCDebugRectHistory::create())
138 {
139 ASSERT(CCProxy::isImplThread());
140 didVisibilityChange(this, m_visible);
141 }
142
143 CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
144 {
145 ASSERT(CCProxy::isImplThread());
146 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
147
148 if (m_rootLayerImpl)
149 clearRenderSurfaces();
150 }
151
152 void CCLayerTreeHostImpl::beginCommit()
153 {
154 }
155
156 void CCLayerTreeHostImpl::commitComplete()
157 {
158 // Recompute max scroll position; must be after layer content bounds are
159 // updated.
160 updateMaxScrollPosition();
161 m_contentsTexturesWerePurgedSinceLastCommit = false;
162 }
163
164 bool CCLayerTreeHostImpl::canDraw()
165 {
166 if (!m_rootLayerImpl)
167 return false;
168 if (viewportSize().isEmpty())
169 return false;
170 if (!m_layerRenderer)
171 return false;
172 if (m_contentsTexturesWerePurgedSinceLastCommit)
173 return false;
174 return true;
175 }
176
177 CCGraphicsContext* CCLayerTreeHostImpl::context() const
178 {
179 return m_context.get();
180 }
181
182 void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
183 {
184 animatePageScale(monotonicTime);
185 animateLayers(monotonicTime, wallClockTime);
186 animateGestures(monotonicTime);
187 }
188
189 void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
190 {
191 if (!m_rootScrollLayerImpl)
192 return;
193
194 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
195 scrollTotal.scale(m_pageScaleDelta);
196 float scaleTotal = m_pageScale * m_pageScaleDelta;
197 IntSize scaledContentSize = contentSize();
198 scaledContentSize.scale(m_pageScaleDelta);
199
200 m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTime);
201
202 if (anchorPoint) {
203 IntSize windowAnchor(targetPosition);
204 windowAnchor.scale(scaleTotal / pageScale);
205 windowAnchor -= scrollTotal;
206 m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
207 } else
208 m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
209
210 m_client->setNeedsRedrawOnImplThread();
211 m_client->setNeedsCommitOnImplThread();
212 }
213
214 void CCLayerTreeHostImpl::setActiveGestureAnimation(PassOwnPtr<CCActiveGestureAn imation> gestureAnimation)
215 {
216 m_activeGestureAnimation = gestureAnimation;
217
218 if (m_activeGestureAnimation)
219 m_client->setNeedsRedrawOnImplThread();
220 }
221
222 void CCLayerTreeHostImpl::scheduleAnimation()
223 {
224 m_client->setNeedsRedrawOnImplThread();
225 }
226
227 void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
228 {
229 // For now, we use damage tracking to compute a global scissor. To do this, we must
230 // compute all damage tracking before drawing anything, so that we know the root
231 // damage rect. The root damage rect is then used to scissor each surface.
232
233 for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
234 CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
235 CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
236 ASSERT(renderSurface);
237 renderSurface->damageTracker()->updateDamageTrackingState(renderSurface- >layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnl yFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer() , renderSurfaceLayer->filters());
238 }
239 }
240
241 void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSur faceLayerList)
242 {
243 ASSERT(renderSurfaceLayerList.isEmpty());
244 ASSERT(m_rootLayerImpl);
245
246 renderSurfaceLayerList.append(m_rootLayerImpl.get());
247
248 if (!m_rootLayerImpl->renderSurface())
249 m_rootLayerImpl->createRenderSurface();
250 m_rootLayerImpl->renderSurface()->clearLayerList();
251 m_rootLayerImpl->renderSurface()->setContentRect(IntRect(IntPoint(), deviceV iewportSize()));
252
253 m_rootLayerImpl->setClipRect(IntRect(IntPoint(), deviceViewportSize()));
254
255 {
256 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
257 WebTransformationMatrix identityMatrix;
258 WebTransformationMatrix deviceScaleTransform;
259 deviceScaleTransform.scale(m_deviceScaleFactor);
260 CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), m_ rootLayerImpl.get(), deviceScaleTransform, identityMatrix, renderSurfaceLayerLis t, m_rootLayerImpl->renderSurface()->layerList(), &m_layerSorter, layerRendererC apabilities().maxTextureSize);
261
262 trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList) ;
263
264 if (layerRendererCapabilities().usingPartialSwap)
265 m_rootScissorRect = m_rootLayerImpl->renderSurface()->damageTracker( )->currentDamageRect();
266 else
267 m_rootScissorRect = FloatRect(FloatPoint(0, 0), deviceViewportSize() );
268
269 CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLaye rList, m_rootScissorRect);
270 }
271 }
272
273 bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
274 {
275 ASSERT(frame.renderPasses.isEmpty());
276
277 calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
278
279 TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurf aceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerLi st->size()));
280
281 m_rootLayerImpl->setScissorRect(enclosingIntRect(m_rootScissorRect));
282
283 // Create the render passes in dependency order.
284 HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
285 for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceInd ex >= 0 ; --surfaceIndex) {
286 CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfac eIndex];
287 CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
288
289 OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface);
290 surfacePassMap.add(renderSurface, pass.get());
291 frame.renderPasses.append(pass.release());
292 }
293
294 bool recordMetricsForFrame = true; // FIXME: In the future, disable this whe n about:tracing is off.
295 CCOcclusionTrackerImpl occlusionTracker(enclosingIntRect(m_rootScissorRect), recordMetricsForFrame);
296 occlusionTracker.setMinimumTrackingSize(CCOcclusionTrackerImpl::preferredMin imumTrackingSize());
297
298 if (settings().showOccludingRects)
299 occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingS creenSpaceRects);
300
301 // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
302 typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
303
304 // Typically when we are missing a texture and use a checkerboard quad, we s till draw the frame. However when the layer being
305 // checkerboarded is moving due to an impl-animation, we drop the frame to a void flashing due to the texture suddenly appearing
306 // in the future.
307 bool drawFrame = true;
308
309 CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerL ist);
310 for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurface LayerList); it != end; ++it) {
311 CCRenderSurface* renderSurface = it.targetRenderSurfaceLayer()->renderSu rface();
312 CCRenderPass* pass = surfacePassMap.get(renderSurface);
313 bool hadMissingTiles = false;
314
315 occlusionTracker.enterLayer(it);
316
317 if (it.representsContributingRenderSurface() && !it->renderSurface()->sc issorRect().isEmpty()) {
318 CCRenderPass* contributingRenderPass = surfacePassMap.get(it->render Surface());
319 pass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker);
320 } else if (it.representsItself() && !occlusionTracker.occluded(*it, it-> visibleLayerRect()) && !it->visibleLayerRect().isEmpty() && !it->scissorRect().i sEmpty()) {
321 it->willDraw(m_layerRenderer.get(), context());
322 frame.willDrawLayers.append(*it);
323
324 pass->appendQuadsForLayer(*it, &occlusionTracker, hadMissingTiles);
325 }
326
327 if (hadMissingTiles) {
328 bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimatin g() || it->drawTransformIsAnimating();
329 if (layerHasAnimatingTransform)
330 drawFrame = false;
331 }
332
333 occlusionTracker.leaveLayer(it);
334 }
335
336 if (!m_hasTransparentBackground) {
337 frame.renderPasses.last()->setHasTransparentBackground(false);
338 frame.renderPasses.last()->appendQuadsToFillScreen(m_rootLayerImpl.get() , m_backgroundColor, occlusionTracker);
339 }
340
341 if (drawFrame)
342 occlusionTracker.overdrawMetrics().recordMetrics(this);
343
344 m_layerRenderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
345 removePassesWithCachedTextures(frame.renderPasses, frame.skippedPasses);
346
347 return drawFrame;
348 }
349
350 void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double mo notonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAni mate, bool& needsAnimateLayers)
351 {
352 bool subtreeNeedsAnimateLayers = false;
353
354 CCLayerAnimationController* currentController = current->layerAnimationContr oller();
355
356 bool hadActiveAnimation = currentController->hasActiveAnimation();
357 currentController->animate(monotonicTime, events);
358 bool startedAnimation = events->size() > 0;
359
360 // We animated if we either ticked a running animation, or started a new ani mation.
361 if (hadActiveAnimation || startedAnimation)
362 didAnimate = true;
363
364 // If the current controller still has an active animation, we must continue animating layers.
365 if (currentController->hasActiveAnimation())
366 subtreeNeedsAnimateLayers = true;
367
368 for (size_t i = 0; i < current->children().size(); ++i) {
369 bool childNeedsAnimateLayers = false;
370 animateLayersRecursive(current->children()[i].get(), monotonicTime, wall ClockTime, events, didAnimate, childNeedsAnimateLayers);
371 if (childNeedsAnimateLayers)
372 subtreeNeedsAnimateLayers = true;
373 }
374
375 needsAnimateLayers = subtreeNeedsAnimateLayers;
376 }
377
378 void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
379 {
380 // Lazily create the timeSource adapter so that we can vary the interval for testing.
381 if (!m_timeSourceClientAdapter)
382 m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create (this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy:: currentThread()));
383
384 m_timeSourceClientAdapter->setActive(enabled);
385 }
386
387 IntSize CCLayerTreeHostImpl::contentSize() const
388 {
389 // TODO(aelias): Hardcoding the first child here is weird. Think of
390 // a cleaner way to get the contentBounds on the Impl side.
391 if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
392 return IntSize();
393 return m_rootScrollLayerImpl->children()[0]->contentBounds();
394 }
395
396 void CCLayerTreeHostImpl::removeRenderPassesRecursive(CCRenderPassList& passes, size_t bottomPass, const CCRenderPass* firstToRemove, CCRenderPassList& skippedP asses)
397 {
398 size_t removeIndex = passes.find(firstToRemove);
399
400 // The pass was already removed by another quad - probably the original, and we are the replica.
401 if (removeIndex == notFound)
402 return;
403
404 OwnPtr<CCRenderPass> removedPass = passes[removeIndex].release();
405 passes.remove(removeIndex);
406
407 // Now follow up for all RenderPass quads and remove their render passes rec ursively.
408 const CCQuadList& quadList = removedPass->quadList();
409 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFront Begin();
410 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
411 CCDrawQuad* currentQuad = (*quadListIterator).get();
412 if (currentQuad->material() != CCDrawQuad::RenderPass)
413 continue;
414
415 CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad* >(currentQuad);
416 const CCRenderPass* nextRenderPass = renderPassQuad->renderPass();
417
418 // Our search is now limited up to the pass that we just removed.
419 // Substitute removeIndex for bottomPass now.
420 removeRenderPassesRecursive(passes, removeIndex, nextRenderPass, skipped Passes);
421 }
422 skippedPasses.append(removedPass.release());
423 }
424
425 void CCLayerTreeHostImpl::removePassesWithCachedTextures(CCRenderPassList& passe s, CCRenderPassList& skippedPasses)
426 {
427 for (int passIndex = passes.size() - 1; passIndex >= 0; --passIndex) {
428 CCRenderPass* currentPass = passes[passIndex].get();
429 const CCQuadList& quadList = currentPass->quadList();
430 CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToF rontBegin();
431
432 for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator ) {
433 CCDrawQuad* currentQuad = quadListIterator->get();
434
435 if (currentQuad->material() != CCDrawQuad::RenderPass)
436 continue;
437
438 CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQ uad*>(currentQuad);
439 CCRenderSurface* targetSurface = renderPassQuad->renderPass()->targe tSurface();
440
441 if (targetSurface->contentsChanged() || !targetSurface->hasCachedCon tentsTexture())
442 continue;
443
444 // Reserve the texture immediately. We do not need to pass in layer renderer
445 // since the texture already exists, just needs to be reserved.
446 if (!targetSurface->prepareContentsTexture(0))
447 continue;
448
449 // We are changing the vector in the middle of reverse iteration.
450 // We are guaranteed that any data from iterator to the end will not change.
451 // Capture the iterator position from the end, and restore it after the change.
452 int positionFromEnd = passes.size() - passIndex;
453 removeRenderPassesRecursive(passes, passIndex, renderPassQuad->rende rPass(), skippedPasses);
454 passIndex = passes.size() - positionFromEnd;
455 ASSERT(passIndex >= 0);
456 }
457 }
458 }
459
460 bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
461 {
462 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw");
463 ASSERT(canDraw());
464
465 frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
466 frame.renderPasses.clear();
467 frame.renderSurfaceLayerList->clear();
468 frame.willDrawLayers.clear();
469
470 if (!calculateRenderPasses(frame))
471 return false;
472
473 // If we return true, then we expect drawLayers() to be called before this f unction is called again.
474 return true;
475 }
476
477 void CCLayerTreeHostImpl::releaseContentsTextures()
478 {
479 contentsTextureAllocator()->deleteAllTextures();
480 m_contentsTexturesWerePurgedSinceLastCommit = true;
481 }
482
483 void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
484 {
485 if (m_memoryAllocationLimitBytes == bytes)
486 return;
487 m_memoryAllocationLimitBytes = bytes;
488
489 ASSERT(bytes);
490 m_client->setNeedsCommitOnImplThread();
491 }
492
493 void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
494 {
495 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
496 ASSERT(canDraw());
497 ASSERT(!frame.renderPasses.isEmpty());
498
499 // FIXME: use the frame begin time from the overall compositor scheduler.
500 // This value is currently inaccessible because it is up in Chromium's
501 // RenderWidget.
502
503 // The root RenderPass is the last one to be drawn.
504 CCRenderPass* rootRenderPass = frame.renderPasses.last().get();
505
506 m_fpsCounter->markBeginningOfFrame(currentTime());
507 m_layerRenderer->beginDrawingFrame(rootRenderPass);
508
509 for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
510 CCRenderPass* renderPass = frame.renderPasses[i].get();
511
512 FloatRect rootScissorRectInCurrentSurface = renderPass->targetSurface()- >computeRootScissorRectInCurrentSurface(m_rootScissorRect);
513 m_layerRenderer->drawRenderPass(renderPass, rootScissorRectInCurrentSurf ace);
514
515 renderPass->targetSurface()->damageTracker()->didDrawDamagedArea();
516 }
517
518 if (m_debugRectHistory->enabled(settings()))
519 m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
520
521 if (m_headsUpDisplay->enabled(settings()))
522 m_headsUpDisplay->draw(this);
523
524 m_layerRenderer->finishDrawingFrame();
525
526 ++m_sourceAnimationFrameNumber;
527
528 // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
529 m_rootLayerImpl->resetAllChangeTrackingForSubtree();
530 }
531
532 void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
533 {
534 for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
535 frame.willDrawLayers[i]->didDraw();
536 }
537
538 void CCLayerTreeHostImpl::finishAllRendering()
539 {
540 if (m_layerRenderer)
541 m_layerRenderer->finish();
542 }
543
544 bool CCLayerTreeHostImpl::isContextLost()
545 {
546 return m_layerRenderer && m_layerRenderer->isContextLost();
547 }
548
549 const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities( ) const
550 {
551 return m_layerRenderer->capabilities();
552 }
553
554 TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const
555 {
556 return m_layerRenderer ? m_layerRenderer->contentsTextureAllocator() : 0;
557 }
558
559 bool CCLayerTreeHostImpl::swapBuffers()
560 {
561 ASSERT(m_layerRenderer);
562
563 m_fpsCounter->markEndOfFrame();
564 return m_layerRenderer->swapBuffers(enclosingIntRect(m_rootScissorRect));
565 }
566
567 void CCLayerTreeHostImpl::didLoseContext()
568 {
569 m_client->didLoseContextOnImplThread();
570 }
571
572 void CCLayerTreeHostImpl::onSwapBuffersComplete()
573 {
574 m_client->onSwapBuffersCompleteOnImplThread();
575 }
576
577 void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
578 {
579 ASSERT(m_layerRenderer);
580 m_layerRenderer->getFramebufferPixels(pixels, rect);
581 }
582
583 static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
584 {
585 if (!layer)
586 return 0;
587
588 if (layer->scrollable())
589 return layer;
590
591 for (size_t i = 0; i < layer->children().size(); ++i) {
592 CCLayerImpl* found = findRootScrollLayer(layer->children()[i].get());
593 if (found)
594 return found;
595 }
596
597 return 0;
598 }
599
600 // Content layers can be either directly scrollable or contained in an outer
601 // scrolling layer which applies the scroll transform. Given a content layer,
602 // this function returns the associated scroll layer if any.
603 static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
604 {
605 if (!layerImpl)
606 return 0;
607
608 if (layerImpl->scrollable())
609 return layerImpl;
610
611 if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()- >scrollable())
612 return layerImpl->parent();
613
614 return 0;
615 }
616
617 void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
618 {
619 m_rootLayerImpl = layer;
620 m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
621 m_currentlyScrollingLayerImpl = 0;
622
623 if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
624 m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtre e(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
625
626 m_scrollingLayerIdFromPreviousTree = -1;
627 }
628
629 PassOwnPtr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
630 {
631 // Clear all data structures that have direct references to the layer tree.
632 m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_curre ntlyScrollingLayerImpl->id() : -1;
633 m_currentlyScrollingLayerImpl = 0;
634 m_renderSurfaceLayerList.clear();
635
636 return m_rootLayerImpl.release();
637 }
638
639 void CCLayerTreeHostImpl::setVisible(bool visible)
640 {
641 ASSERT(CCProxy::isImplThread());
642
643 if (m_visible == visible)
644 return;
645 m_visible = visible;
646 didVisibilityChange(this, m_visible);
647
648 if (!m_layerRenderer)
649 return;
650
651 m_layerRenderer->setVisible(visible);
652
653 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
654 }
655
656 bool CCLayerTreeHostImpl::initializeLayerRenderer(PassOwnPtr<CCGraphicsContext> context, TextureUploaderOption textureUploader)
657 {
658 WebKit::WebGraphicsContext3D* context3d = context->context3D();
659 if (!context3d) {
660 // FIXME: Implement this path for software compositing.
661 return false;
662 }
663
664 OwnPtr<LayerRendererChromium> layerRenderer;
665 layerRenderer = LayerRendererChromium::create(this, context3d, textureUpload er);
666
667 // Since we now have a new context/layerRenderer, we cannot continue to use the old
668 // resources (i.e. renderSurfaces and texture IDs).
669 if (m_rootLayerImpl) {
670 clearRenderSurfaces();
671 sendDidLoseContextRecursive(m_rootLayerImpl.get());
672 }
673
674 m_layerRenderer = layerRenderer.release();
675 if (m_layerRenderer)
676 m_context = context;
677
678 if (!m_visible && m_layerRenderer)
679 m_layerRenderer->setVisible(m_visible);
680
681 return m_layerRenderer;
682 }
683
684 void CCLayerTreeHostImpl::setViewportSize(const IntSize& viewportSize)
685 {
686 if (viewportSize == m_viewportSize)
687 return;
688
689 m_viewportSize = viewportSize;
690
691 m_deviceViewportSize = viewportSize;
692 m_deviceViewportSize.scale(m_deviceScaleFactor);
693
694 updateMaxScrollPosition();
695
696 if (m_layerRenderer)
697 m_layerRenderer->viewportChanged();
698 }
699
700 static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageSc aleChange)
701 {
702 if (!layerImpl)
703 return;
704
705 if (layerImpl->scrollable()) {
706 // We need to convert impl-side scroll deltas to pageScale space.
707 FloatSize scrollDelta = layerImpl->scrollDelta();
708 scrollDelta.scale(pageScaleChange);
709 layerImpl->setScrollDelta(scrollDelta);
710 }
711
712 for (size_t i = 0; i < layerImpl->children().size(); ++i)
713 adjustScrollsForPageScaleChange(layerImpl->children()[i].get(), pageScal eChange);
714 }
715
716 static void applyPageScaleDeltaToScrollLayers(CCLayerImpl* layerImpl, float page ScaleDelta)
717 {
718 if (!layerImpl)
719 return;
720
721 if (layerImpl->scrollable())
722 layerImpl->setPageScaleDelta(pageScaleDelta);
723
724 for (size_t i = 0; i < layerImpl->children().size(); ++i)
725 applyPageScaleDeltaToScrollLayers(layerImpl->children()[i].get(), pageSc aleDelta);
726 }
727
728 void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
729 {
730 if (deviceScaleFactor == m_deviceScaleFactor)
731 return;
732 m_deviceScaleFactor = deviceScaleFactor;
733
734 m_deviceViewportSize = viewportSize();
735 m_deviceViewportSize.scale(m_deviceScaleFactor);
736 updateMaxScrollPosition();
737 if (m_layerRenderer)
738 m_layerRenderer->viewportChanged();
739 }
740
741
742 void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float min PageScale, float maxPageScale)
743 {
744 if (!pageScale)
745 return;
746
747 if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
748 return;
749
750 m_minPageScale = minPageScale;
751 m_maxPageScale = maxPageScale;
752
753 float pageScaleChange = pageScale / m_pageScale;
754 m_pageScale = pageScale;
755
756 if (pageScaleChange != 1)
757 adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
758
759 // Clamp delta to limits and refresh display matrix.
760 setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
761 m_sentPageScaleDelta = 1;
762 applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
763 }
764
765 void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
766 {
767 // Clamp to the current min/max limits.
768 float finalMagnifyScale = m_pageScale * delta;
769 if (m_minPageScale && finalMagnifyScale < m_minPageScale)
770 delta = m_minPageScale / m_pageScale;
771 else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
772 delta = m_maxPageScale / m_pageScale;
773
774 if (delta == m_pageScaleDelta)
775 return;
776
777 m_pageScaleDelta = delta;
778
779 updateMaxScrollPosition();
780 applyPageScaleDeltaToScrollLayers(m_rootScrollLayerImpl, m_pageScaleDelta);
781 }
782
783 void CCLayerTreeHostImpl::updateMaxScrollPosition()
784 {
785 if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
786 return;
787
788 FloatSize viewBounds = m_viewportSize;
789 if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
790 if (clipLayer->masksToBounds())
791 viewBounds = clipLayer->bounds();
792 }
793 viewBounds.scale(1 / m_pageScaleDelta);
794 viewBounds.scale(m_deviceScaleFactor);
795
796 // maxScroll is computed in physical pixels, but scroll positions are in lay out pixels.
797 IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
798 maxScroll.scale(1 / m_deviceScaleFactor);
799 // The viewport may be larger than the contents in some cases, such as
800 // having a vertical scrollbar but no horizontal overflow.
801 maxScroll.clampNegativeToZero();
802
803 m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
804 }
805
806 void CCLayerTreeHostImpl::setNeedsRedraw()
807 {
808 m_client->setNeedsRedrawOnImplThread();
809 }
810
811 bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList()
812 {
813 if (!m_rootLayerImpl)
814 return false;
815
816 // We need both a non-empty render surface layer list and a root render
817 // surface to be able to iterate over the visible layers.
818 if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
819 return true;
820
821 // If we are called after setRootLayer() but before prepareToDraw(), we need
822 // to recalculate the visible layers. This prevents being unable to scroll
823 // during part of a commit.
824 m_renderSurfaceLayerList.clear();
825 calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
826
827 return m_renderSurfaceLayerList.size();
828 }
829
830 CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoi nt& viewportPoint, CCInputHandlerClient::ScrollInputType type)
831 {
832 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin");
833
834 ASSERT(!m_currentlyScrollingLayerImpl);
835 clearCurrentlyScrollingLayer();
836
837 if (!ensureRenderSurfaceLayerList())
838 return ScrollIgnored;
839
840 IntPoint deviceViewportPoint = viewportPoint;
841 deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
842
843 // First find out which layer was hit from the saved list of visible layers
844 // in the most recent frame.
845 CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(vi ewportPoint, m_renderSurfaceLayerList);
846
847 // Walk up the hierarchy and look for a scrollable layer.
848 CCLayerImpl* potentiallyScrollingLayerImpl = 0;
849 for (; layerImpl; layerImpl = layerImpl->parent()) {
850 // The content layer can also block attempts to scroll outside the main thread.
851 if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThrea d)
852 return ScrollOnMainThread;
853
854 CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl) ;
855 if (!scrollLayerImpl)
856 continue;
857
858 ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type);
859
860 // If any layer wants to divert the scroll event to the main thread, abo rt.
861 if (status == ScrollOnMainThread)
862 return ScrollOnMainThread;
863
864 if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
865 potentiallyScrollingLayerImpl = scrollLayerImpl;
866 }
867
868 if (potentiallyScrollingLayerImpl) {
869 m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
870 return ScrollStarted;
871 }
872 return ScrollIgnored;
873 }
874
875 void CCLayerTreeHostImpl::scrollBy(const IntSize& scrollDelta)
876 {
877 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy");
878 if (!m_currentlyScrollingLayerImpl)
879 return;
880
881 FloatSize pendingDelta(scrollDelta);
882 pendingDelta.scale(1 / m_pageScaleDelta);
883
884 for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl && !p endingDelta.isZero(); layerImpl = layerImpl->parent()) {
885 if (!layerImpl->scrollable())
886 continue;
887 FloatSize previousDelta(layerImpl->scrollDelta());
888 layerImpl->scrollBy(pendingDelta);
889 // Reset the pending scroll delta to zero if the layer was able to move along the requested
890 // axis. This is to ensure it is possible to scroll exactly to the begin ning or end of a
891 // scroll area regardless of the scroll step. For diagonal scrolls this also avoids applying
892 // the scroll on one axis to multiple layers.
893 if (previousDelta.width() != layerImpl->scrollDelta().width())
894 pendingDelta.setWidth(0);
895 if (previousDelta.height() != layerImpl->scrollDelta().height())
896 pendingDelta.setHeight(0);
897 }
898
899 if (!scrollDelta.isZero() && pendingDelta.isEmpty()) {
900 m_client->setNeedsCommitOnImplThread();
901 m_client->setNeedsRedrawOnImplThread();
902 }
903 }
904
905 void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
906 {
907 m_currentlyScrollingLayerImpl = 0;
908 m_scrollingLayerIdFromPreviousTree = -1;
909 }
910
911 void CCLayerTreeHostImpl::scrollEnd()
912 {
913 clearCurrentlyScrollingLayer();
914 }
915
916 void CCLayerTreeHostImpl::pinchGestureBegin()
917 {
918 m_pinchGestureActive = true;
919 m_previousPinchAnchor = IntPoint();
920 }
921
922 void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
923 const IntPoint& anchor)
924 {
925 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate");
926
927 if (!m_rootScrollLayerImpl)
928 return;
929
930 if (m_previousPinchAnchor == IntPoint::zero())
931 m_previousPinchAnchor = anchor;
932
933 // Keep the center-of-pinch anchor specified by (x, y) in a stable
934 // position over the course of the magnify.
935 FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
936 setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
937 FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_page ScaleDelta);
938 FloatSize move = previousScaleAnchor - newScaleAnchor;
939
940 m_previousPinchAnchor = anchor;
941
942 m_rootScrollLayerImpl->scrollBy(roundedIntSize(move));
943 m_client->setNeedsCommitOnImplThread();
944 m_client->setNeedsRedrawOnImplThread();
945 }
946
947 void CCLayerTreeHostImpl::pinchGestureEnd()
948 {
949 m_pinchGestureActive = false;
950
951 m_client->setNeedsCommitOnImplThread();
952 }
953
954 void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scroll Info)
955 {
956 float pageScale = m_pageScaleAnimation->finalPageScale();
957 IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
958 scrollOffset.scale(m_pageScale / pageScale);
959 makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
960 }
961
962 void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo )
963 {
964 if (!m_rootScrollLayerImpl)
965 return;
966
967 // Only send fake scroll/zoom deltas if we're pinch zooming out by a
968 // significant amount. This also ensures only one fake delta set will be
969 // sent.
970 const float pinchZoomOutSensitivity = 0.95;
971 if (m_pageScaleDelta > pinchZoomOutSensitivity)
972 return;
973
974 // Compute where the scroll offset/page scale would be if fully pinch-zoomed
975 // out from the anchor point.
976 IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
977 scrollBegin.scale(m_pageScaleDelta);
978 float scaleBegin = m_pageScale * m_pageScaleDelta;
979 float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
980 FloatSize scaledContentsSize = contentSize();
981 scaledContentsSize.scale(pageScaleDeltaToSend);
982
983 FloatSize anchor = toSize(m_previousPinchAnchor);
984 FloatSize scrollEnd = scrollBegin + anchor;
985 scrollEnd.scale(m_minPageScale / scaleBegin);
986 scrollEnd -= anchor;
987 scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceV iewportSize)).expandedTo(FloatSize(0, 0));
988 scrollEnd.scale(1 / pageScaleDeltaToSend);
989 scrollEnd.scale(m_deviceScaleFactor);
990
991 makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_minPageScale) ;
992 }
993
994 void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
995 {
996 if (!m_rootScrollLayerImpl)
997 return;
998
999 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
1000 scroll.layerId = m_rootScrollLayerImpl->id();
1001 scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosi tion());
1002 scrollInfo->scrolls.append(scroll);
1003 m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
1004 m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
1005 }
1006
1007 static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* la yerImpl)
1008 {
1009 if (!layerImpl)
1010 return;
1011
1012 if (!layerImpl->scrollDelta().isZero()) {
1013 IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
1014 CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
1015 scroll.layerId = layerImpl->id();
1016 scroll.scrollDelta = scrollDelta;
1017 scrollInfo->scrolls.append(scroll);
1018 layerImpl->setSentScrollDelta(scrollDelta);
1019 }
1020
1021 for (size_t i = 0; i < layerImpl->children().size(); ++i)
1022 collectScrollDeltas(scrollInfo, layerImpl->children()[i].get());
1023 }
1024
1025 PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
1026 {
1027 OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet()) ;
1028
1029 if (m_pinchGestureActive || m_pageScaleAnimation) {
1030 m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
1031 if (m_pinchGestureActive)
1032 computePinchZoomDeltas(scrollInfo.get());
1033 else if (m_pageScaleAnimation.get())
1034 computeDoubleTapZoomDeltas(scrollInfo.get());
1035 return scrollInfo.release();
1036 }
1037
1038 collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
1039 m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
1040
1041 return scrollInfo.release();
1042 }
1043
1044 void CCLayerTreeHostImpl::setFullRootLayerDamage()
1045 {
1046 if (m_rootLayerImpl) {
1047 CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
1048 if (renderSurface)
1049 renderSurface->damageTracker()->forceFullDamageNextUpdate();
1050 }
1051 }
1052
1053 void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
1054 {
1055 if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
1056 return;
1057
1058 IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
1059
1060 setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_p ageScale);
1061 IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime) ;
1062 nextScroll.scale(1 / m_pageScaleDelta);
1063 m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
1064 m_client->setNeedsRedrawOnImplThread();
1065
1066 if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
1067 m_pageScaleAnimation.clear();
1068 m_client->setNeedsCommitOnImplThread();
1069 }
1070 }
1071
1072 void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTi me)
1073 {
1074 if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || ! m_rootLayerImpl)
1075 return;
1076
1077 TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
1078
1079 OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector) );
1080
1081 bool didAnimate = false;
1082 animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
1083
1084 if (!events->isEmpty())
1085 m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
1086
1087 if (didAnimate)
1088 m_client->setNeedsRedrawOnImplThread();
1089
1090 setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
1091 }
1092
1093 double CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
1094 {
1095 return 1;
1096 }
1097
1098 void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
1099 {
1100 ASSERT(current);
1101 current->didLoseContext();
1102 if (current->maskLayer())
1103 sendDidLoseContextRecursive(current->maskLayer());
1104 if (current->replicaLayer())
1105 sendDidLoseContextRecursive(current->replicaLayer());
1106 for (size_t i = 0; i < current->children().size(); ++i)
1107 sendDidLoseContextRecursive(current->children()[i].get());
1108 }
1109
1110 static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
1111 {
1112 ASSERT(current);
1113 for (size_t i = 0; i < current->children().size(); ++i)
1114 clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i].get());
1115 current->clearRenderSurface();
1116 }
1117
1118 void CCLayerTreeHostImpl::clearRenderSurfaces()
1119 {
1120 clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
1121 m_renderSurfaceLayerList.clear();
1122 }
1123
1124 String CCLayerTreeHostImpl::layerTreeAsText() const
1125 {
1126 TextStream ts;
1127 if (m_rootLayerImpl) {
1128 ts << m_rootLayerImpl->layerTreeAsText();
1129 ts << "RenderSurfaces:\n";
1130 dumpRenderSurfaces(ts, 1, m_rootLayerImpl.get());
1131 }
1132 return ts.release();
1133 }
1134
1135 void CCLayerTreeHostImpl::setFontAtlas(PassOwnPtr<CCFontAtlas> fontAtlas)
1136 {
1137 m_headsUpDisplay->setFontAtlas(fontAtlas);
1138 }
1139
1140 void CCLayerTreeHostImpl::dumpRenderSurfaces(TextStream& ts, int indent, const C CLayerImpl* layer) const
1141 {
1142 if (layer->renderSurface())
1143 layer->renderSurface()->dumpSurface(ts, indent);
1144
1145 for (size_t i = 0; i < layer->children().size(); ++i)
1146 dumpRenderSurfaces(ts, indent, layer->children()[i].get());
1147 }
1148
1149
1150 void CCLayerTreeHostImpl::animateGestures(double monotonicTime)
1151 {
1152 if (!m_activeGestureAnimation)
1153 return;
1154
1155 bool isContinuing = m_activeGestureAnimation->animate(monotonicTime);
1156 if (isContinuing)
1157 m_client->setNeedsRedrawOnImplThread();
1158 else
1159 m_activeGestureAnimation.clear();
1160 }
1161
1162 } // namespace WebCore
OLDNEW
« no previous file with comments | « ui/cc/cc/CCLayerTreeHostImpl.h ('k') | ui/cc/cc/CCMathUtil.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698