| Index: cc/CCLayerTreeHostImpl.cpp
|
| diff --git a/cc/CCLayerTreeHostImpl.cpp b/cc/CCLayerTreeHostImpl.cpp
|
| deleted file mode 100644
|
| index 5f9e45ce4a68f003c37ce904b17fb8d4bbb95647..0000000000000000000000000000000000000000
|
| --- a/cc/CCLayerTreeHostImpl.cpp
|
| +++ /dev/null
|
| @@ -1,1462 +0,0 @@
|
| -// Copyright 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "config.h"
|
| -
|
| -#include "CCLayerTreeHostImpl.h"
|
| -
|
| -#include "base/basictypes.h"
|
| -#include "CCAppendQuadsData.h"
|
| -#include "CCDamageTracker.h"
|
| -#include "CCDebugRectHistory.h"
|
| -#include "CCDelayBasedTimeSource.h"
|
| -#include "CCFontAtlas.h"
|
| -#include "CCFrameRateCounter.h"
|
| -#include "CCHeadsUpDisplayLayerImpl.h"
|
| -#include "CCLayerIterator.h"
|
| -#include "CCLayerTreeHost.h"
|
| -#include "CCLayerTreeHostCommon.h"
|
| -#include "CCMathUtil.h"
|
| -#include "CCOverdrawMetrics.h"
|
| -#include "CCPageScaleAnimation.h"
|
| -#include "CCPrioritizedTextureManager.h"
|
| -#include "CCRenderPassDrawQuad.h"
|
| -#include "CCRendererGL.h"
|
| -#include "CCRendererSoftware.h"
|
| -#include "CCRenderingStats.h"
|
| -#include "CCScrollbarAnimationController.h"
|
| -#include "CCScrollbarLayerImpl.h"
|
| -#include "CCSettings.h"
|
| -#include "CCSingleThreadProxy.h"
|
| -#include "TextureUploader.h"
|
| -#include "TraceEvent.h"
|
| -#include <wtf/CurrentTime.h>
|
| -#include <algorithm>
|
| -
|
| -using WebKit::WebTransformationMatrix;
|
| -
|
| -namespace {
|
| -
|
| -void didVisibilityChange(cc::CCLayerTreeHostImpl* id, bool visible)
|
| -{
|
| - if (visible) {
|
| - TRACE_EVENT_ASYNC_BEGIN1("webkit", "CCLayerTreeHostImpl::setVisible", id, "CCLayerTreeHostImpl", id);
|
| - return;
|
| - }
|
| -
|
| - TRACE_EVENT_ASYNC_END0("webkit", "CCLayerTreeHostImpl::setVisible", id);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace cc {
|
| -
|
| -CCPinchZoomViewport::CCPinchZoomViewport()
|
| - : m_pageScaleFactor(1)
|
| - , m_pageScaleDelta(1)
|
| - , m_sentPageScaleDelta(1)
|
| - , m_minPageScaleFactor(0)
|
| - , m_maxPageScaleFactor(0)
|
| -{
|
| -}
|
| -
|
| -float CCPinchZoomViewport::totalPageScaleFactor() const
|
| -{
|
| - return m_pageScaleFactor * m_pageScaleDelta;
|
| -}
|
| -
|
| -void CCPinchZoomViewport::setPageScaleDelta(float delta)
|
| -{
|
| - // Clamp to the current min/max limits.
|
| - float totalPageScaleFactor = m_pageScaleFactor * delta;
|
| - if (m_minPageScaleFactor && totalPageScaleFactor < m_minPageScaleFactor)
|
| - delta = m_minPageScaleFactor / m_pageScaleFactor;
|
| - else if (m_maxPageScaleFactor && totalPageScaleFactor > m_maxPageScaleFactor)
|
| - delta = m_maxPageScaleFactor / m_pageScaleFactor;
|
| -
|
| - if (delta == m_pageScaleDelta)
|
| - return;
|
| -
|
| - m_pageScaleDelta = delta;
|
| -}
|
| -
|
| -bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
|
| -{
|
| - ASSERT(pageScaleFactor);
|
| -
|
| - if (m_sentPageScaleDelta == 1 && pageScaleFactor == m_pageScaleFactor && minPageScaleFactor == m_minPageScaleFactor && maxPageScaleFactor == m_maxPageScaleFactor)
|
| - return false;
|
| -
|
| - m_minPageScaleFactor = minPageScaleFactor;
|
| - m_maxPageScaleFactor = maxPageScaleFactor;
|
| -
|
| - m_pageScaleFactor = pageScaleFactor;
|
| - return true;
|
| -}
|
| -
|
| -FloatRect CCPinchZoomViewport::bounds() const
|
| -{
|
| - FloatSize scaledViewportSize = m_layoutViewportSize;
|
| - scaledViewportSize.scale(1 / totalPageScaleFactor());
|
| -
|
| - FloatRect bounds(FloatPoint(0, 0), scaledViewportSize);
|
| - bounds.setLocation(m_pinchViewportScrollDelta);
|
| -
|
| - return bounds;
|
| -}
|
| -
|
| -FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta)
|
| -{
|
| - FloatSize overflow;
|
| - FloatRect pinchedBounds = bounds();
|
| -
|
| - pinchedBounds.move(delta);
|
| - if (pinchedBounds.x() < 0) {
|
| - overflow.setWidth(pinchedBounds.x());
|
| - pinchedBounds.setX(0);
|
| - }
|
| -
|
| - if (pinchedBounds.y() < 0) {
|
| - overflow.setHeight(pinchedBounds.y());
|
| - pinchedBounds.setY(0);
|
| - }
|
| -
|
| - if (pinchedBounds.maxX() > m_layoutViewportSize.width()) {
|
| - overflow.setWidth(
|
| - pinchedBounds.maxX() - m_layoutViewportSize.width());
|
| - pinchedBounds.move(
|
| - m_layoutViewportSize.width() - pinchedBounds.maxX(), 0);
|
| - }
|
| -
|
| - if (pinchedBounds.maxY() > m_layoutViewportSize.height()) {
|
| - overflow.setHeight(
|
| - pinchedBounds.maxY() - m_layoutViewportSize.height());
|
| - pinchedBounds.move(
|
| - 0, m_layoutViewportSize.height() - pinchedBounds.maxY());
|
| - }
|
| - m_pinchViewportScrollDelta = pinchedBounds.location();
|
| -
|
| - return overflow;
|
| -}
|
| -
|
| -WebTransformationMatrix CCPinchZoomViewport::implTransform() const
|
| -{
|
| - WebTransformationMatrix transform;
|
| - transform.scale(m_pageScaleDelta);
|
| -
|
| - // If the pinch state is applied in the impl, then push it to the
|
| - // impl transform, otherwise the scale is handled by WebCore.
|
| - if (CCSettings::pageScalePinchZoomEnabled()) {
|
| - transform.scale(m_pageScaleFactor);
|
| - transform.translate(-m_pinchViewportScrollDelta.x(),
|
| - -m_pinchViewportScrollDelta.y());
|
| - }
|
| -
|
| - return transform;
|
| -}
|
| -
|
| -class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
|
| -public:
|
| - static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
|
| - {
|
| - return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource));
|
| - }
|
| - virtual ~CCLayerTreeHostImplTimeSourceAdapter()
|
| - {
|
| - m_timeSource->setClient(0);
|
| - m_timeSource->setActive(false);
|
| - }
|
| -
|
| - virtual void onTimerTick() OVERRIDE
|
| - {
|
| - // FIXME: We require that animate be called on the impl thread. This
|
| - // avoids asserts in single threaded mode. Ideally background ticking
|
| - // would be handled by the proxy/scheduler and this could be removed.
|
| - DebugScopedSetImplThread impl;
|
| -
|
| - m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime());
|
| - }
|
| -
|
| - void setActive(bool active)
|
| - {
|
| - if (active != m_timeSource->active())
|
| - m_timeSource->setActive(active);
|
| - }
|
| -
|
| -private:
|
| - CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource)
|
| - : m_layerTreeHostImpl(layerTreeHostImpl)
|
| - , m_timeSource(timeSource)
|
| - {
|
| - m_timeSource->setClient(this);
|
| - }
|
| -
|
| - CCLayerTreeHostImpl* m_layerTreeHostImpl;
|
| - RefPtr<CCDelayBasedTimeSource> m_timeSource;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(CCLayerTreeHostImplTimeSourceAdapter);
|
| -};
|
| -
|
| -CCLayerTreeHostImpl::FrameData::FrameData()
|
| -{
|
| -}
|
| -
|
| -CCLayerTreeHostImpl::FrameData::~FrameData()
|
| -{
|
| -}
|
| -
|
| -scoped_ptr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
|
| -{
|
| - return scoped_ptr<CCLayerTreeHostImpl>(new CCLayerTreeHostImpl(settings, client));
|
| -}
|
| -
|
| -CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CCLayerTreeHostImplClient* client)
|
| - : m_client(client)
|
| - , m_sourceFrameNumber(-1)
|
| - , m_rootScrollLayerImpl(0)
|
| - , m_currentlyScrollingLayerImpl(0)
|
| - , m_hudLayerImpl(0)
|
| - , m_scrollingLayerIdFromPreviousTree(-1)
|
| - , m_scrollDeltaIsInScreenSpace(false)
|
| - , m_settings(settings)
|
| - , m_deviceScaleFactor(1)
|
| - , m_visible(true)
|
| - , m_contentsTexturesPurged(false)
|
| - , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit())
|
| - , m_backgroundColor(0)
|
| - , m_hasTransparentBackground(false)
|
| - , m_needsAnimateLayers(false)
|
| - , m_pinchGestureActive(false)
|
| - , m_fpsCounter(CCFrameRateCounter::create())
|
| - , m_debugRectHistory(CCDebugRectHistory::create())
|
| - , m_numImplThreadScrolls(0)
|
| - , m_numMainThreadScrolls(0)
|
| -{
|
| - ASSERT(CCProxy::isImplThread());
|
| - didVisibilityChange(this, m_visible);
|
| -}
|
| -
|
| -CCLayerTreeHostImpl::~CCLayerTreeHostImpl()
|
| -{
|
| - ASSERT(CCProxy::isImplThread());
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::~CCLayerTreeHostImpl()");
|
| -
|
| - if (m_rootLayerImpl)
|
| - clearRenderSurfaces();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::beginCommit()
|
| -{
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::commitComplete()
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::commitComplete");
|
| - // Recompute max scroll position; must be after layer content bounds are
|
| - // updated.
|
| - updateMaxScrollPosition();
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::canDraw()
|
| -{
|
| - // Note: If you are changing this function or any other function that might
|
| - // affect the result of canDraw, make sure to call m_client->onCanDrawStateChanged
|
| - // in the proper places and update the notifyIfCanDrawChanged test.
|
| -
|
| - if (!m_rootLayerImpl) {
|
| - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no root layer");
|
| - return false;
|
| - }
|
| - if (deviceViewportSize().isEmpty()) {
|
| - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw empty viewport");
|
| - return false;
|
| - }
|
| - if (!m_renderer) {
|
| - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw no renderer");
|
| - return false;
|
| - }
|
| - if (m_contentsTexturesPurged) {
|
| - TRACE_EVENT_INSTANT0("cc", "CCLayerTreeHostImpl::canDraw contents textures purged");
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -CCGraphicsContext* CCLayerTreeHostImpl::context() const
|
| -{
|
| - return m_context.get();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime)
|
| -{
|
| - animatePageScale(monotonicTime);
|
| - animateLayers(monotonicTime, wallClockTime);
|
| - animateScrollbars(monotonicTime);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration)
|
| -{
|
| - if (!m_rootScrollLayerImpl)
|
| - return;
|
| -
|
| - IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
|
| - scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta());
|
| - float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor();
|
| - IntSize scaledContentSize = contentSize();
|
| - scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta());
|
| -
|
| - m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime);
|
| -
|
| - if (anchorPoint) {
|
| - IntSize windowAnchor(targetPosition);
|
| - windowAnchor.scale(scaleTotal / pageScale);
|
| - windowAnchor -= scrollTotal;
|
| - m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration);
|
| - } else
|
| - m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration);
|
| -
|
| - m_client->setNeedsRedrawOnImplThread();
|
| - m_client->setNeedsCommitOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::scheduleAnimation()
|
| -{
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList)
|
| -{
|
| - // For now, we use damage tracking to compute a global scissor. To do this, we must
|
| - // compute all damage tracking before drawing anything, so that we know the root
|
| - // damage rect. The root damage rect is then used to scissor each surface.
|
| -
|
| - for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
|
| - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex];
|
| - CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface();
|
| - ASSERT(renderSurface);
|
| - renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurface->surfacePropertyChangedOnlyFromDescendant(), renderSurface->contentRect(), renderSurfaceLayer->maskLayer(), renderSurfaceLayer->filters());
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
|
| -{
|
| - if (m_rootScrollLayerImpl) {
|
| - m_rootScrollLayerImpl->setImplTransform(implTransform());
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
|
| -{
|
| - ASSERT(renderSurfaceLayerList.isEmpty());
|
| - ASSERT(m_rootLayerImpl);
|
| - ASSERT(m_renderer); // For maxTextureSize.
|
| -
|
| - {
|
| - updateRootScrollLayerImplTransform();
|
| -
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
|
| - CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
|
| -
|
| - trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::FrameData::appendRenderPass(scoped_ptr<CCRenderPass> renderPass)
|
| -{
|
| - CCRenderPass* pass = renderPass.get();
|
| - renderPasses.push_back(pass);
|
| - renderPassesById.set(pass->id(), renderPass.Pass());
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
|
| -{
|
| - ASSERT(frame.renderPasses.empty());
|
| -
|
| - calculateRenderSurfaceLayerList(*frame.renderSurfaceLayerList);
|
| -
|
| - TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
|
| -
|
| - // Create the render passes in dependency order.
|
| - for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
|
| - CCLayerImpl* renderSurfaceLayer = (*frame.renderSurfaceLayerList)[surfaceIndex];
|
| - renderSurfaceLayer->renderSurface()->appendRenderPasses(frame);
|
| - }
|
| -
|
| - bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
|
| - CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
|
| - occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
|
| -
|
| - if (settings().showOccludingRects)
|
| - occlusionTracker.setOccludingScreenSpaceRectsContainer(&frame.occludingScreenSpaceRects);
|
| -
|
| - // Add quads to the Render passes in FrontToBack order to allow for testing occlusion and performing culling during the tree walk.
|
| - typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType;
|
| -
|
| - // Typically when we are missing a texture and use a checkerboard quad, we still draw the frame. However when the layer being
|
| - // checkerboarded is moving due to an impl-animation, we drop the frame to avoid flashing due to the texture suddenly appearing
|
| - // in the future.
|
| - bool drawFrame = true;
|
| -
|
| - CCLayerIteratorType end = CCLayerIteratorType::end(frame.renderSurfaceLayerList);
|
| - for (CCLayerIteratorType it = CCLayerIteratorType::begin(frame.renderSurfaceLayerList); it != end; ++it) {
|
| - CCRenderPass::Id targetRenderPassId = it.targetRenderSurfaceLayer()->renderSurface()->renderPassId();
|
| - CCRenderPass* targetRenderPass = frame.renderPassesById.get(targetRenderPassId);
|
| -
|
| - occlusionTracker.enterLayer(it);
|
| -
|
| - CCAppendQuadsData appendQuadsData(targetRenderPass->id());
|
| -
|
| - if (it.representsContributingRenderSurface()) {
|
| - CCRenderPass::Id contributingRenderPassId = it->renderSurface()->renderPassId();
|
| - CCRenderPass* contributingRenderPass = frame.renderPassesById.get(contributingRenderPassId);
|
| - targetRenderPass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker, appendQuadsData);
|
| - } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) {
|
| - bool hasOcclusionFromOutsideTargetSurface;
|
| - if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface))
|
| - appendQuadsData.hadOcclusionFromOutsideTargetSurface |= hasOcclusionFromOutsideTargetSurface;
|
| - else {
|
| - it->willDraw(m_resourceProvider.get());
|
| - frame.willDrawLayers.append(*it);
|
| -
|
| - if (it->hasContributingDelegatedRenderPasses()) {
|
| - CCRenderPass::Id contributingRenderPassId = it->firstContributingRenderPassId();
|
| - while (frame.renderPassesById.contains(contributingRenderPassId)) {
|
| - CCRenderPass* renderPass = frame.renderPassesById.get(contributingRenderPassId);
|
| -
|
| - CCAppendQuadsData appendQuadsData(renderPass->id());
|
| - renderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
|
| -
|
| - contributingRenderPassId = it->nextContributingRenderPassId(contributingRenderPassId);
|
| - }
|
| - }
|
| -
|
| - targetRenderPass->appendQuadsForLayer(*it, &occlusionTracker, appendQuadsData);
|
| - }
|
| - }
|
| -
|
| - if (appendQuadsData.hadOcclusionFromOutsideTargetSurface)
|
| - targetRenderPass->setHasOcclusionFromOutsideTargetSurface(true);
|
| -
|
| - if (appendQuadsData.hadMissingTiles) {
|
| - bool layerHasAnimatingTransform = it->screenSpaceTransformIsAnimating() || it->drawTransformIsAnimating();
|
| - if (layerHasAnimatingTransform || CCSettings::jankInsteadOfCheckerboard())
|
| - drawFrame = false;
|
| - }
|
| -
|
| - occlusionTracker.leaveLayer(it);
|
| - }
|
| -
|
| -#if !ASSERT_DISABLED
|
| - for (size_t i = 0; i < frame.renderPasses.size(); ++i) {
|
| - for (size_t j = 0; j < frame.renderPasses[i]->quadList().size(); ++j)
|
| - ASSERT(frame.renderPasses[i]->quadList()[j]->sharedQuadStateId() >= 0);
|
| - ASSERT(frame.renderPassesById.contains(frame.renderPasses[i]->id()));
|
| - }
|
| -#endif
|
| -
|
| - if (!m_hasTransparentBackground) {
|
| - frame.renderPasses.back()->setHasTransparentBackground(false);
|
| - frame.renderPasses.back()->appendQuadsToFillScreen(m_rootLayerImpl.get(), m_backgroundColor, occlusionTracker);
|
| - }
|
| -
|
| - if (drawFrame)
|
| - occlusionTracker.overdrawMetrics().recordMetrics(this);
|
| -
|
| - removeRenderPasses(CullRenderPassesWithNoQuads(), frame);
|
| - m_renderer->decideRenderPassAllocationsForFrame(frame.renderPasses);
|
| - removeRenderPasses(CullRenderPassesWithCachedTextures(*m_renderer), frame);
|
| -
|
| - return drawFrame;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector* events, bool& didAnimate, bool& needsAnimateLayers)
|
| -{
|
| - bool subtreeNeedsAnimateLayers = false;
|
| -
|
| - CCLayerAnimationController* currentController = current->layerAnimationController();
|
| -
|
| - bool hadActiveAnimation = currentController->hasActiveAnimation();
|
| - currentController->animate(monotonicTime, events);
|
| - bool startedAnimation = events->size() > 0;
|
| -
|
| - // We animated if we either ticked a running animation, or started a new animation.
|
| - if (hadActiveAnimation || startedAnimation)
|
| - didAnimate = true;
|
| -
|
| - // If the current controller still has an active animation, we must continue animating layers.
|
| - if (currentController->hasActiveAnimation())
|
| - subtreeNeedsAnimateLayers = true;
|
| -
|
| - for (size_t i = 0; i < current->children().size(); ++i) {
|
| - bool childNeedsAnimateLayers = false;
|
| - animateLayersRecursive(current->children()[i], monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers);
|
| - if (childNeedsAnimateLayers)
|
| - subtreeNeedsAnimateLayers = true;
|
| - }
|
| -
|
| - needsAnimateLayers = subtreeNeedsAnimateLayers;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setBackgroundTickingEnabled(bool enabled)
|
| -{
|
| - // Lazily create the timeSource adapter so that we can vary the interval for testing.
|
| - if (!m_timeSourceClientAdapter)
|
| - m_timeSourceClientAdapter = CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval(), CCProxy::currentThread()));
|
| -
|
| - m_timeSourceClientAdapter->setActive(enabled);
|
| -}
|
| -
|
| -IntSize CCLayerTreeHostImpl::contentSize() const
|
| -{
|
| - // TODO(aelias): Hardcoding the first child here is weird. Think of
|
| - // a cleaner way to get the contentBounds on the Impl side.
|
| - if (!m_rootScrollLayerImpl || m_rootScrollLayerImpl->children().isEmpty())
|
| - return IntSize();
|
| - return m_rootScrollLayerImpl->children()[0]->contentBounds();
|
| -}
|
| -
|
| -static inline CCRenderPass* findRenderPassById(CCRenderPass::Id renderPassId, const CCLayerTreeHostImpl::FrameData& frame)
|
| -{
|
| - CCRenderPassIdHashMap::const_iterator it = frame.renderPassesById.find(renderPassId);
|
| - ASSERT(it != frame.renderPassesById.end());
|
| - return it->second;
|
| -}
|
| -
|
| -static void removeRenderPassesRecursive(CCRenderPass::Id removeRenderPassId, CCLayerTreeHostImpl::FrameData& frame)
|
| -{
|
| - CCRenderPass* removeRenderPass = findRenderPassById(removeRenderPassId, frame);
|
| - CCRenderPassList& renderPasses = frame.renderPasses;
|
| - CCRenderPassList::iterator toRemove = std::find(renderPasses.begin(), renderPasses.end(), removeRenderPass);
|
| -
|
| - // The pass was already removed by another quad - probably the original, and we are the replica.
|
| - if (toRemove == renderPasses.end())
|
| - return;
|
| -
|
| - const CCRenderPass* removedPass = *toRemove;
|
| - frame.renderPasses.erase(toRemove);
|
| -
|
| - // Now follow up for all RenderPass quads and remove their RenderPasses recursively.
|
| - const CCQuadList& quadList = removedPass->quadList();
|
| - CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
|
| - for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
|
| - CCDrawQuad* currentQuad = (*quadListIterator);
|
| - if (currentQuad->material() != CCDrawQuad::RenderPass)
|
| - continue;
|
| -
|
| - CCRenderPass::Id nextRemoveRenderPassId = CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId();
|
| - removeRenderPassesRecursive(nextRemoveRenderPassId, frame);
|
| - }
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData&) const
|
| -{
|
| - return quad.contentsChangedSinceLastFrame().isEmpty() && m_renderer.haveCachedResourcesForRenderPassId(quad.renderPassId());
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::CullRenderPassesWithNoQuads::shouldRemoveRenderPass(const CCRenderPassDrawQuad& quad, const FrameData& frame) const
|
| -{
|
| - const CCRenderPass* renderPass = findRenderPassById(quad.renderPassId(), frame);
|
| - const CCRenderPassList& renderPasses = frame.renderPasses;
|
| - CCRenderPassList::const_iterator foundPass = std::find(renderPasses.begin(), renderPasses.end(), renderPass);
|
| -
|
| - bool renderPassAlreadyRemoved = foundPass == renderPasses.end();
|
| - if (renderPassAlreadyRemoved)
|
| - return false;
|
| -
|
| - // If any quad or RenderPass draws into this RenderPass, then keep it.
|
| - const CCQuadList& quadList = (*foundPass)->quadList();
|
| - for (CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin(); quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
|
| - CCDrawQuad* currentQuad = *quadListIterator;
|
| -
|
| - if (currentQuad->material() != CCDrawQuad::RenderPass)
|
| - return false;
|
| -
|
| - const CCRenderPass* contributingPass = findRenderPassById(CCRenderPassDrawQuad::materialCast(currentQuad)->renderPassId(), frame);
|
| - CCRenderPassList::const_iterator foundContributingPass = std::find(renderPasses.begin(), renderPasses.end(), contributingPass);
|
| - if (foundContributingPass != renderPasses.end())
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -// Defined for linking tests.
|
| -template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithCachedTextures>(CullRenderPassesWithCachedTextures, FrameData&);
|
| -template void CCLayerTreeHostImpl::removeRenderPasses<CCLayerTreeHostImpl::CullRenderPassesWithNoQuads>(CullRenderPassesWithNoQuads, FrameData&);
|
| -
|
| -// static
|
| -template<typename RenderPassCuller>
|
| -void CCLayerTreeHostImpl::removeRenderPasses(RenderPassCuller culler, FrameData& frame)
|
| -{
|
| - for (size_t it = culler.renderPassListBegin(frame.renderPasses); it != culler.renderPassListEnd(frame.renderPasses); it = culler.renderPassListNext(it)) {
|
| - const CCRenderPass* currentPass = frame.renderPasses[it];
|
| - const CCQuadList& quadList = currentPass->quadList();
|
| - CCQuadList::constBackToFrontIterator quadListIterator = quadList.backToFrontBegin();
|
| -
|
| - for (; quadListIterator != quadList.backToFrontEnd(); ++quadListIterator) {
|
| - CCDrawQuad* currentQuad = *quadListIterator;
|
| -
|
| - if (currentQuad->material() != CCDrawQuad::RenderPass)
|
| - continue;
|
| -
|
| - CCRenderPassDrawQuad* renderPassQuad = static_cast<CCRenderPassDrawQuad*>(currentQuad);
|
| - if (!culler.shouldRemoveRenderPass(*renderPassQuad, frame))
|
| - continue;
|
| -
|
| - // We are changing the vector in the middle of iteration. Because we
|
| - // delete render passes that draw into the current pass, we are
|
| - // guaranteed that any data from the iterator to the end will not
|
| - // change. So, capture the iterator position from the end of the
|
| - // list, and restore it after the change.
|
| - int positionFromEnd = frame.renderPasses.size() - it;
|
| - removeRenderPassesRecursive(renderPassQuad->renderPassId(), frame);
|
| - it = frame.renderPasses.size() - positionFromEnd;
|
| - ASSERT(it >= 0);
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::prepareToDraw");
|
| - ASSERT(canDraw());
|
| -
|
| - frame.renderSurfaceLayerList = &m_renderSurfaceLayerList;
|
| - frame.renderPasses.clear();
|
| - frame.renderPassesById.clear();
|
| - frame.renderSurfaceLayerList->clear();
|
| - frame.willDrawLayers.clear();
|
| -
|
| - if (!calculateRenderPasses(frame))
|
| - return false;
|
| -
|
| - // If we return true, then we expect drawLayers() to be called before this function is called again.
|
| - return true;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::releaseContentsTextures()
|
| -{
|
| - if (m_contentsTexturesPurged)
|
| - return;
|
| - m_client->releaseContentsTexturesOnImplThread();
|
| - setContentsTexturesPurged();
|
| - m_client->setNeedsCommitOnImplThread();
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
|
| -{
|
| - if (m_memoryAllocationLimitBytes == bytes)
|
| - return;
|
| - m_memoryAllocationLimitBytes = bytes;
|
| -
|
| - ASSERT(bytes);
|
| - m_client->setNeedsCommitOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds)
|
| -{
|
| - m_client->onVSyncParametersChanged(monotonicTimebase, intervalInSeconds);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::drawLayers");
|
| - ASSERT(canDraw());
|
| - ASSERT(!frame.renderPasses.empty());
|
| -
|
| - // FIXME: use the frame begin time from the overall compositor scheduler.
|
| - // This value is currently inaccessible because it is up in Chromium's
|
| - // RenderWidget.
|
| - m_fpsCounter->markBeginningOfFrame(currentTime());
|
| -
|
| - if (m_settings.showDebugRects())
|
| - m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
|
| -
|
| - // Because the contents of the HUD depend on everything else in the frame, the contents
|
| - // of its texture are updated as the last thing before the frame is drawn.
|
| - if (m_hudLayerImpl)
|
| - m_hudLayerImpl->updateHudTexture(m_resourceProvider.get());
|
| -
|
| - m_renderer->drawFrame(frame.renderPasses, frame.renderPassesById);
|
| -
|
| - // Once a RenderPass has been drawn, its damage should be cleared in
|
| - // case the RenderPass will be reused next frame.
|
| - for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
|
| - frame.renderPasses[i]->setDamageRect(FloatRect());
|
| -
|
| - // The next frame should start by assuming nothing has changed, and changes are noted as they occur.
|
| - for (unsigned int i = 0; i < frame.renderSurfaceLayerList->size(); i++)
|
| - (*frame.renderSurfaceLayerList)[i]->renderSurface()->damageTracker()->didDrawDamagedArea();
|
| - m_rootLayerImpl->resetAllChangeTrackingForSubtree();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::didDrawAllLayers(const FrameData& frame)
|
| -{
|
| - for (size_t i = 0; i < frame.willDrawLayers.size(); ++i)
|
| - frame.willDrawLayers[i]->didDraw(m_resourceProvider.get());
|
| -
|
| - // Once all layers have been drawn, pending texture uploads should no
|
| - // longer block future uploads.
|
| - m_resourceProvider->textureUploader()->markPendingUploadsAsNonBlocking();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::finishAllRendering()
|
| -{
|
| - if (m_renderer)
|
| - m_renderer->finish();
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::isContextLost()
|
| -{
|
| - return m_renderer && m_renderer->isContextLost();
|
| -}
|
| -
|
| -const RendererCapabilities& CCLayerTreeHostImpl::rendererCapabilities() const
|
| -{
|
| - return m_renderer->capabilities();
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::swapBuffers()
|
| -{
|
| - ASSERT(m_renderer);
|
| -
|
| - m_fpsCounter->markEndOfFrame();
|
| - return m_renderer->swapBuffers();
|
| -}
|
| -
|
| -const IntSize& CCLayerTreeHostImpl::deviceViewportSize() const
|
| -{
|
| - return m_deviceViewportSize;
|
| -}
|
| -
|
| -const CCLayerTreeSettings& CCLayerTreeHostImpl::settings() const
|
| -{
|
| - return m_settings;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::didLoseContext()
|
| -{
|
| - m_client->didLoseContextOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::onSwapBuffersComplete()
|
| -{
|
| - m_client->onSwapBuffersCompleteOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect)
|
| -{
|
| - ASSERT(m_renderer);
|
| - m_renderer->getFramebufferPixels(pixels, rect);
|
| -}
|
| -
|
| -static CCLayerImpl* findRootScrollLayer(CCLayerImpl* layer)
|
| -{
|
| - if (!layer)
|
| - return 0;
|
| -
|
| - if (layer->scrollable())
|
| - return layer;
|
| -
|
| - for (size_t i = 0; i < layer->children().size(); ++i) {
|
| - CCLayerImpl* found = findRootScrollLayer(layer->children()[i]);
|
| - if (found)
|
| - return found;
|
| - }
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -// Content layers can be either directly scrollable or contained in an outer
|
| -// scrolling layer which applies the scroll transform. Given a content layer,
|
| -// this function returns the associated scroll layer if any.
|
| -static CCLayerImpl* findScrollLayerForContentLayer(CCLayerImpl* layerImpl)
|
| -{
|
| - if (!layerImpl)
|
| - return 0;
|
| -
|
| - if (layerImpl->scrollable())
|
| - return layerImpl;
|
| -
|
| - if (layerImpl->drawsContent() && layerImpl->parent() && layerImpl->parent()->scrollable())
|
| - return layerImpl->parent();
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer)
|
| -{
|
| - m_rootLayerImpl = layer;
|
| - m_rootScrollLayerImpl = findRootScrollLayer(m_rootLayerImpl.get());
|
| - m_currentlyScrollingLayerImpl = 0;
|
| -
|
| - if (m_rootLayerImpl && m_scrollingLayerIdFromPreviousTree != -1)
|
| - m_currentlyScrollingLayerImpl = CCLayerTreeHostCommon::findLayerInSubtree(m_rootLayerImpl.get(), m_scrollingLayerIdFromPreviousTree);
|
| -
|
| - m_scrollingLayerIdFromPreviousTree = -1;
|
| -
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -}
|
| -
|
| -PassOwnPtr<CCLayerImpl> CCLayerTreeHostImpl::detachLayerTree()
|
| -{
|
| - // Clear all data structures that have direct references to the layer tree.
|
| - m_scrollingLayerIdFromPreviousTree = m_currentlyScrollingLayerImpl ? m_currentlyScrollingLayerImpl->id() : -1;
|
| - m_currentlyScrollingLayerImpl = 0;
|
| - m_renderSurfaceLayerList.clear();
|
| -
|
| - return m_rootLayerImpl.release();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setVisible(bool visible)
|
| -{
|
| - ASSERT(CCProxy::isImplThread());
|
| -
|
| - if (m_visible == visible)
|
| - return;
|
| - m_visible = visible;
|
| - didVisibilityChange(this, m_visible);
|
| -
|
| - if (!m_renderer)
|
| - return;
|
| -
|
| - m_renderer->setVisible(visible);
|
| -
|
| - setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::initializeRenderer(scoped_ptr<CCGraphicsContext> context)
|
| -{
|
| - // Since we will create a new resource provider, we cannot continue to use
|
| - // the old resources (i.e. renderSurfaces and texture IDs). Clear them
|
| - // before we destroy the old resource provider.
|
| - if (m_rootLayerImpl) {
|
| - clearRenderSurfaces();
|
| - sendDidLoseContextRecursive(m_rootLayerImpl.get());
|
| - }
|
| - // Note: order is important here.
|
| - m_renderer.clear();
|
| - m_resourceProvider.clear();
|
| - m_context.reset();
|
| -
|
| - if (!context->bindToClient(this))
|
| - return false;
|
| -
|
| - OwnPtr<CCResourceProvider> resourceProvider = CCResourceProvider::create(context.get());
|
| - if (!resourceProvider)
|
| - return false;
|
| -
|
| - if (context->context3D())
|
| - m_renderer = CCRendererGL::create(this, resourceProvider.get());
|
| - else if (context->softwareDevice())
|
| - m_renderer = CCRendererSoftware::create(this, resourceProvider.get(), context->softwareDevice());
|
| - if (!m_renderer)
|
| - return false;
|
| -
|
| - m_resourceProvider = resourceProvider.release();
|
| - m_context = context.Pass();
|
| -
|
| - if (!m_visible)
|
| - m_renderer->setVisible(m_visible);
|
| -
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -
|
| - return true;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setContentsTexturesPurged()
|
| -{
|
| - m_contentsTexturesPurged = true;
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::resetContentsTexturesPurged()
|
| -{
|
| - m_contentsTexturesPurged = false;
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize)
|
| -{
|
| - if (layoutViewportSize == m_layoutViewportSize && deviceViewportSize == m_deviceViewportSize)
|
| - return;
|
| -
|
| - m_layoutViewportSize = layoutViewportSize;
|
| - m_deviceViewportSize = deviceViewportSize;
|
| -
|
| - m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
|
| -
|
| - updateMaxScrollPosition();
|
| -
|
| - if (m_renderer)
|
| - m_renderer->viewportChanged();
|
| -
|
| - m_client->onCanDrawStateChanged(canDraw());
|
| -}
|
| -
|
| -static void adjustScrollsForPageScaleChange(CCLayerImpl* layerImpl, float pageScaleChange)
|
| -{
|
| - if (!layerImpl)
|
| - return;
|
| -
|
| - if (layerImpl->scrollable()) {
|
| - // We need to convert impl-side scroll deltas to pageScale space.
|
| - FloatSize scrollDelta = layerImpl->scrollDelta();
|
| - scrollDelta.scale(pageScaleChange);
|
| - layerImpl->setScrollDelta(scrollDelta);
|
| - }
|
| -
|
| - for (size_t i = 0; i < layerImpl->children().size(); ++i)
|
| - adjustScrollsForPageScaleChange(layerImpl->children()[i], pageScaleChange);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor)
|
| -{
|
| - if (deviceScaleFactor == m_deviceScaleFactor)
|
| - return;
|
| - m_deviceScaleFactor = deviceScaleFactor;
|
| -
|
| - updateMaxScrollPosition();
|
| -}
|
| -
|
| -float CCLayerTreeHostImpl::pageScaleFactor() const
|
| -{
|
| - return m_pinchZoomViewport.pageScaleFactor();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
|
| -{
|
| - if (!pageScaleFactor)
|
| - return;
|
| -
|
| - float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
|
| - m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
|
| -
|
| - if (!CCSettings::pageScalePinchZoomEnabled()) {
|
| - if (pageScaleChange != 1)
|
| - adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
|
| - }
|
| -
|
| - // Clamp delta to limits and refresh display matrix.
|
| - setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
|
| - m_pinchZoomViewport.setSentPageScaleDelta(1);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
|
| -{
|
| - m_pinchZoomViewport.setPageScaleDelta(delta);
|
| -
|
| - updateMaxScrollPosition();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::updateMaxScrollPosition()
|
| -{
|
| - if (!m_rootScrollLayerImpl || !m_rootScrollLayerImpl->children().size())
|
| - return;
|
| -
|
| - FloatSize viewBounds = m_deviceViewportSize;
|
| - if (CCLayerImpl* clipLayer = m_rootScrollLayerImpl->parent()) {
|
| - // Compensate for non-overlay scrollbars.
|
| - if (clipLayer->masksToBounds()) {
|
| - viewBounds = clipLayer->bounds();
|
| - viewBounds.scale(m_deviceScaleFactor);
|
| - }
|
| - }
|
| -
|
| - IntSize contentBounds = contentSize();
|
| - if (CCSettings::pageScalePinchZoomEnabled()) {
|
| - // Pinch with pageScale scrolls entirely in layout space. contentSize
|
| - // returns the bounds including the page scale factor, so calculate the
|
| - // pre page-scale layout size here.
|
| - float pageScaleFactor = m_pinchZoomViewport.pageScaleFactor();
|
| - contentBounds.setWidth(contentBounds.width() / pageScaleFactor);
|
| - contentBounds.setHeight(contentBounds.height() / pageScaleFactor);
|
| - } else {
|
| - viewBounds.scale(1 / m_pinchZoomViewport.pageScaleDelta());
|
| - }
|
| -
|
| - IntSize maxScroll = contentBounds - expandedIntSize(viewBounds);
|
| - maxScroll.scale(1 / m_deviceScaleFactor);
|
| -
|
| - // The viewport may be larger than the contents in some cases, such as
|
| - // having a vertical scrollbar but no horizontal overflow.
|
| - maxScroll.clampNegativeToZero();
|
| -
|
| - m_rootScrollLayerImpl->setMaxScrollPosition(maxScroll);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setNeedsRedraw()
|
| -{
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -}
|
| -
|
| -bool CCLayerTreeHostImpl::ensureRenderSurfaceLayerList()
|
| -{
|
| - if (!m_rootLayerImpl)
|
| - return false;
|
| - if (!m_renderer)
|
| - return false;
|
| -
|
| - // We need both a non-empty render surface layer list and a root render
|
| - // surface to be able to iterate over the visible layers.
|
| - if (m_renderSurfaceLayerList.size() && m_rootLayerImpl->renderSurface())
|
| - return true;
|
| -
|
| - // If we are called after setRootLayer() but before prepareToDraw(), we need
|
| - // to recalculate the visible layers. This prevents being unable to scroll
|
| - // during part of a commit.
|
| - m_renderSurfaceLayerList.clear();
|
| - calculateRenderSurfaceLayerList(m_renderSurfaceLayerList);
|
| -
|
| - return m_renderSurfaceLayerList.size();
|
| -}
|
| -
|
| -CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type)
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBegin");
|
| -
|
| - ASSERT(!m_currentlyScrollingLayerImpl);
|
| - clearCurrentlyScrollingLayer();
|
| -
|
| - if (!ensureRenderSurfaceLayerList())
|
| - return ScrollIgnored;
|
| -
|
| - IntPoint deviceViewportPoint = viewportPoint;
|
| - deviceViewportPoint.scale(m_deviceScaleFactor, m_deviceScaleFactor);
|
| -
|
| - // First find out which layer was hit from the saved list of visible layers
|
| - // in the most recent frame.
|
| - CCLayerImpl* layerImpl = CCLayerTreeHostCommon::findLayerThatIsHitByPoint(viewportPoint, m_renderSurfaceLayerList);
|
| -
|
| - // Walk up the hierarchy and look for a scrollable layer.
|
| - CCLayerImpl* potentiallyScrollingLayerImpl = 0;
|
| - for (; layerImpl; layerImpl = layerImpl->parent()) {
|
| - // The content layer can also block attempts to scroll outside the main thread.
|
| - if (layerImpl->tryScroll(deviceViewportPoint, type) == ScrollOnMainThread) {
|
| - m_numMainThreadScrolls++;
|
| - return ScrollOnMainThread;
|
| - }
|
| -
|
| - CCLayerImpl* scrollLayerImpl = findScrollLayerForContentLayer(layerImpl);
|
| - if (!scrollLayerImpl)
|
| - continue;
|
| -
|
| - ScrollStatus status = scrollLayerImpl->tryScroll(viewportPoint, type);
|
| -
|
| - // If any layer wants to divert the scroll event to the main thread, abort.
|
| - if (status == ScrollOnMainThread) {
|
| - m_numMainThreadScrolls++;
|
| - return ScrollOnMainThread;
|
| - }
|
| -
|
| - if (status == ScrollStarted && !potentiallyScrollingLayerImpl)
|
| - potentiallyScrollingLayerImpl = scrollLayerImpl;
|
| - }
|
| -
|
| - if (potentiallyScrollingLayerImpl) {
|
| - m_currentlyScrollingLayerImpl = potentiallyScrollingLayerImpl;
|
| - // Gesture events need to be transformed from screen coordinates to local layer coordinates
|
| - // so that the scrolling contents exactly follow the user's finger. In contrast, wheel
|
| - // events are already in local layer coordinates so we can just apply them directly.
|
| - m_scrollDeltaIsInScreenSpace = (type == Gesture);
|
| - m_numImplThreadScrolls++;
|
| - return ScrollStarted;
|
| - }
|
| - return ScrollIgnored;
|
| -}
|
| -
|
| -static FloatSize scrollLayerWithScreenSpaceDelta(CCPinchZoomViewport* viewport, CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta)
|
| -{
|
| - // Layers with non-invertible screen space transforms should not have passed the scroll hit
|
| - // test in the first place.
|
| - ASSERT(layerImpl.screenSpaceTransform().isInvertible());
|
| - WebTransformationMatrix inverseScreenSpaceTransform = layerImpl.screenSpaceTransform().inverse();
|
| -
|
| - // First project the scroll start and end points to local layer space to find the scroll delta
|
| - // in layer coordinates.
|
| - bool startClipped, endClipped;
|
| - FloatPoint screenSpaceEndPoint = screenSpacePoint + screenSpaceDelta;
|
| - FloatPoint localStartPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpacePoint, startClipped);
|
| - FloatPoint localEndPoint = CCMathUtil::projectPoint(inverseScreenSpaceTransform, screenSpaceEndPoint, endClipped);
|
| -
|
| - // In general scroll point coordinates should not get clipped.
|
| - ASSERT(!startClipped);
|
| - ASSERT(!endClipped);
|
| - if (startClipped || endClipped)
|
| - return FloatSize();
|
| -
|
| - // Apply the scroll delta.
|
| - FloatSize previousDelta(layerImpl.scrollDelta());
|
| - FloatSize unscrolled = layerImpl.scrollBy(localEndPoint - localStartPoint);
|
| -
|
| - if (viewport)
|
| - viewport->applyScroll(unscrolled);
|
| -
|
| - // Calculate the applied scroll delta in screen space coordinates.
|
| - FloatPoint actualLocalEndPoint = localStartPoint + layerImpl.scrollDelta() - previousDelta;
|
| - FloatPoint actualScreenSpaceEndPoint = CCMathUtil::mapPoint(layerImpl.screenSpaceTransform(), actualLocalEndPoint, endClipped);
|
| - ASSERT(!endClipped);
|
| - if (endClipped)
|
| - return FloatSize();
|
| - return actualScreenSpaceEndPoint - screenSpacePoint;
|
| -}
|
| -
|
| -static FloatSize scrollLayerWithLocalDelta(CCLayerImpl& layerImpl, const FloatSize& localDelta)
|
| -{
|
| - FloatSize previousDelta(layerImpl.scrollDelta());
|
| - layerImpl.scrollBy(localDelta);
|
| - return layerImpl.scrollDelta() - previousDelta;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::scrollBy(const IntPoint& viewportPoint, const IntSize& scrollDelta)
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::scrollBy");
|
| - if (!m_currentlyScrollingLayerImpl)
|
| - return;
|
| -
|
| - FloatSize pendingDelta(scrollDelta);
|
| -
|
| - pendingDelta.scale(m_deviceScaleFactor);
|
| -
|
| - for (CCLayerImpl* layerImpl = m_currentlyScrollingLayerImpl; layerImpl; layerImpl = layerImpl->parent()) {
|
| - if (!layerImpl->scrollable())
|
| - continue;
|
| -
|
| - CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
|
| - FloatSize appliedDelta;
|
| - if (m_scrollDeltaIsInScreenSpace)
|
| - appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta);
|
| - else
|
| - appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
|
| -
|
| - // If the layer wasn't able to move, try the next one in the hierarchy.
|
| - float moveThresholdSquared = 0.1f * 0.1f;
|
| - if (appliedDelta.diagonalLengthSquared() < moveThresholdSquared)
|
| - continue;
|
| -
|
| - // If the applied delta is within 45 degrees of the input delta, bail out to make it easier
|
| - // to scroll just one layer in one direction without affecting any of its parents.
|
| - float angleThreshold = 45;
|
| - if (CCMathUtil::smallestAngleBetweenVectors(appliedDelta, pendingDelta) < angleThreshold) {
|
| - pendingDelta = FloatSize();
|
| - break;
|
| - }
|
| -
|
| - // Allow further movement only on an axis perpendicular to the direction in which the layer
|
| - // moved.
|
| - FloatSize perpendicularAxis(-appliedDelta.height(), appliedDelta.width());
|
| - pendingDelta = CCMathUtil::projectVector(pendingDelta, perpendicularAxis);
|
| -
|
| - if (flooredIntSize(pendingDelta).isZero())
|
| - break;
|
| - }
|
| -
|
| - if (!scrollDelta.isZero() && flooredIntSize(pendingDelta).isEmpty()) {
|
| - m_client->setNeedsCommitOnImplThread();
|
| - m_client->setNeedsRedrawOnImplThread();
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::clearCurrentlyScrollingLayer()
|
| -{
|
| - m_currentlyScrollingLayerImpl = 0;
|
| - m_scrollingLayerIdFromPreviousTree = -1;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::scrollEnd()
|
| -{
|
| - clearCurrentlyScrollingLayer();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::pinchGestureBegin()
|
| -{
|
| - m_pinchGestureActive = true;
|
| - m_previousPinchAnchor = IntPoint();
|
| -
|
| - if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
|
| - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureBegin();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta,
|
| - const IntPoint& anchor)
|
| -{
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::pinchGestureUpdate");
|
| -
|
| - if (!m_rootScrollLayerImpl)
|
| - return;
|
| -
|
| - if (m_previousPinchAnchor == IntPoint::zero())
|
| - m_previousPinchAnchor = anchor;
|
| -
|
| - // Keep the center-of-pinch anchor specified by (x, y) in a stable
|
| - // position over the course of the magnify.
|
| - float pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
|
| - FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / pageScaleDelta,
|
| - m_previousPinchAnchor.y() / pageScaleDelta);
|
| - setPageScaleDelta(pageScaleDelta * magnifyDelta);
|
| - pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
|
| - FloatPoint newScaleAnchor(anchor.x() / pageScaleDelta, anchor.y() / pageScaleDelta);
|
| - FloatSize move = previousScaleAnchor - newScaleAnchor;
|
| -
|
| - m_previousPinchAnchor = anchor;
|
| -
|
| - if (CCSettings::pageScalePinchZoomEnabled()) {
|
| - // Compute the application of the delta with respect to the current page zoom of the page.
|
| - move.scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor));
|
| - }
|
| -
|
| - FloatSize scrollOverflow = CCSettings::pageScalePinchZoomEnabled() ? m_pinchZoomViewport.applyScroll(move) : move;
|
| - m_rootScrollLayerImpl->scrollBy(roundedIntSize(scrollOverflow));
|
| -
|
| - if (m_rootScrollLayerImpl->scrollbarAnimationController())
|
| - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureUpdate();
|
| -
|
| - m_client->setNeedsCommitOnImplThread();
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::pinchGestureEnd()
|
| -{
|
| - m_pinchGestureActive = false;
|
| -
|
| - if (m_rootScrollLayerImpl && m_rootScrollLayerImpl->scrollbarAnimationController())
|
| - m_rootScrollLayerImpl->scrollbarAnimationController()->didPinchGestureEnd();
|
| -
|
| - m_client->setNeedsCommitOnImplThread();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo)
|
| -{
|
| - float pageScale = m_pageScaleAnimation->finalPageScale();
|
| - IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
|
| - scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
|
| - makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo)
|
| -{
|
| - if (!m_rootScrollLayerImpl)
|
| - return;
|
| -
|
| - // Only send fake scroll/zoom deltas if we're pinch zooming out by a
|
| - // significant amount. This also ensures only one fake delta set will be
|
| - // sent.
|
| - const float pinchZoomOutSensitivity = 0.95f;
|
| - if (m_pinchZoomViewport.pageScaleDelta() > pinchZoomOutSensitivity)
|
| - return;
|
| -
|
| - // Compute where the scroll offset/page scale would be if fully pinch-zoomed
|
| - // out from the anchor point.
|
| - IntSize scrollBegin = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
|
| - scrollBegin.scale(m_pinchZoomViewport.pageScaleDelta());
|
| - float scaleBegin = m_pinchZoomViewport.totalPageScaleFactor();
|
| - float pageScaleDeltaToSend = m_pinchZoomViewport.minPageScaleFactor() / m_pinchZoomViewport.pageScaleFactor();
|
| - FloatSize scaledContentsSize = contentSize();
|
| - scaledContentsSize.scale(pageScaleDeltaToSend);
|
| -
|
| - FloatSize anchor = toSize(m_previousPinchAnchor);
|
| - FloatSize scrollEnd = scrollBegin + anchor;
|
| - scrollEnd.scale(m_pinchZoomViewport.minPageScaleFactor() / scaleBegin);
|
| - scrollEnd -= anchor;
|
| - scrollEnd = scrollEnd.shrunkTo(roundedIntSize(scaledContentsSize - m_deviceViewportSize)).expandedTo(FloatSize(0, 0));
|
| - scrollEnd.scale(1 / pageScaleDeltaToSend);
|
| - scrollEnd.scale(m_deviceScaleFactor);
|
| -
|
| - makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
|
| -{
|
| - if (!m_rootScrollLayerImpl)
|
| - return;
|
| -
|
| - CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
|
| - scroll.layerId = m_rootScrollLayerImpl->id();
|
| - scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
|
| - scrollInfo->scrolls.append(scroll);
|
| - m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
|
| - scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
|
| - m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
|
| -}
|
| -
|
| -static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
|
| -{
|
| - if (!layerImpl)
|
| - return;
|
| -
|
| - if (!layerImpl->scrollDelta().isZero()) {
|
| - IntSize scrollDelta = flooredIntSize(layerImpl->scrollDelta());
|
| - CCLayerTreeHostCommon::ScrollUpdateInfo scroll;
|
| - scroll.layerId = layerImpl->id();
|
| - scroll.scrollDelta = scrollDelta;
|
| - scrollInfo->scrolls.append(scroll);
|
| - layerImpl->setSentScrollDelta(scrollDelta);
|
| - }
|
| -
|
| - for (size_t i = 0; i < layerImpl->children().size(); ++i)
|
| - collectScrollDeltas(scrollInfo, layerImpl->children()[i]);
|
| -}
|
| -
|
| -PassOwnPtr<CCScrollAndScaleSet> CCLayerTreeHostImpl::processScrollDeltas()
|
| -{
|
| - OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
|
| -
|
| - if (m_pinchGestureActive || m_pageScaleAnimation) {
|
| - scrollInfo->pageScaleDelta = 1;
|
| - m_pinchZoomViewport.setSentPageScaleDelta(1);
|
| - // FIXME(aelias): Make these painting optimizations compatible with
|
| - // compositor-side scaling.
|
| - if (!CCSettings::pageScalePinchZoomEnabled()) {
|
| - if (m_pinchGestureActive)
|
| - computePinchZoomDeltas(scrollInfo.get());
|
| - else if (m_pageScaleAnimation.get())
|
| - computeDoubleTapZoomDeltas(scrollInfo.get());
|
| - }
|
| - return scrollInfo.release();
|
| - }
|
| -
|
| - collectScrollDeltas(scrollInfo.get(), m_rootLayerImpl.get());
|
| - scrollInfo->pageScaleDelta = m_pinchZoomViewport.pageScaleDelta();
|
| - m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
|
| -
|
| - return scrollInfo.release();
|
| -}
|
| -
|
| -WebTransformationMatrix CCLayerTreeHostImpl::implTransform() const
|
| -{
|
| - return m_pinchZoomViewport.implTransform();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::setFullRootLayerDamage()
|
| -{
|
| - if (m_rootLayerImpl) {
|
| - CCRenderSurface* renderSurface = m_rootLayerImpl->renderSurface();
|
| - if (renderSurface)
|
| - renderSurface->damageTracker()->forceFullDamageNextUpdate();
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animatePageScale(double monotonicTime)
|
| -{
|
| - if (!m_pageScaleAnimation || !m_rootScrollLayerImpl)
|
| - return;
|
| -
|
| - IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
|
| -
|
| - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
|
| - IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
|
| - nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
|
| - m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -
|
| - if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) {
|
| - m_pageScaleAnimation.clear();
|
| - m_client->setNeedsCommitOnImplThread();
|
| - }
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime)
|
| -{
|
| - if (!CCSettings::acceleratedAnimationEnabled() || !m_needsAnimateLayers || !m_rootLayerImpl)
|
| - return;
|
| -
|
| - TRACE_EVENT0("cc", "CCLayerTreeHostImpl::animateLayers");
|
| -
|
| - OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector));
|
| -
|
| - bool didAnimate = false;
|
| - animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, events.get(), didAnimate, m_needsAnimateLayers);
|
| -
|
| - if (!events->empty())
|
| - m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime);
|
| -
|
| - if (didAnimate)
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -
|
| - setBackgroundTickingEnabled(!m_visible && m_needsAnimateLayers);
|
| -}
|
| -
|
| -base::TimeDelta CCLayerTreeHostImpl::lowFrequencyAnimationInterval() const
|
| -{
|
| - return base::TimeDelta::FromSeconds(1);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current)
|
| -{
|
| - ASSERT(current);
|
| - current->didLoseContext();
|
| - if (current->maskLayer())
|
| - sendDidLoseContextRecursive(current->maskLayer());
|
| - if (current->replicaLayer())
|
| - sendDidLoseContextRecursive(current->replicaLayer());
|
| - for (size_t i = 0; i < current->children().size(); ++i)
|
| - sendDidLoseContextRecursive(current->children()[i]);
|
| -}
|
| -
|
| -static void clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* current)
|
| -{
|
| - ASSERT(current);
|
| - for (size_t i = 0; i < current->children().size(); ++i)
|
| - clearRenderSurfacesOnCCLayerImplRecursive(current->children()[i]);
|
| - current->clearRenderSurface();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::clearRenderSurfaces()
|
| -{
|
| - clearRenderSurfacesOnCCLayerImplRecursive(m_rootLayerImpl.get());
|
| - m_renderSurfaceLayerList.clear();
|
| -}
|
| -
|
| -std::string CCLayerTreeHostImpl::layerTreeAsText() const
|
| -{
|
| - std::string str;
|
| - if (m_rootLayerImpl) {
|
| - str = m_rootLayerImpl->layerTreeAsText();
|
| - str += "RenderSurfaces:\n";
|
| - dumpRenderSurfaces(&str, 1, m_rootLayerImpl.get());
|
| - }
|
| - return str;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::dumpRenderSurfaces(std::string* str, int indent, const CCLayerImpl* layer) const
|
| -{
|
| - if (layer->renderSurface())
|
| - layer->renderSurface()->dumpSurface(str, indent);
|
| -
|
| - for (size_t i = 0; i < layer->children().size(); ++i)
|
| - dumpRenderSurfaces(str, indent, layer->children()[i]);
|
| -}
|
| -
|
| -int CCLayerTreeHostImpl::sourceAnimationFrameNumber() const
|
| -{
|
| - return fpsCounter()->currentFrameNumber();
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::renderingStats(CCRenderingStats* stats) const
|
| -{
|
| - stats->numFramesSentToScreen = fpsCounter()->currentFrameNumber();
|
| - stats->droppedFrameCount = fpsCounter()->droppedFrameCount();
|
| - stats->numImplThreadScrolls = m_numImplThreadScrolls;
|
| - stats->numMainThreadScrolls = m_numMainThreadScrolls;
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animateScrollbars(double monotonicTime)
|
| -{
|
| - animateScrollbarsRecursive(m_rootLayerImpl.get(), monotonicTime);
|
| -}
|
| -
|
| -void CCLayerTreeHostImpl::animateScrollbarsRecursive(CCLayerImpl* layer, double monotonicTime)
|
| -{
|
| - if (!layer)
|
| - return;
|
| -
|
| - CCScrollbarAnimationController* scrollbarController = layer->scrollbarAnimationController();
|
| - if (scrollbarController && scrollbarController->animate(monotonicTime))
|
| - m_client->setNeedsRedrawOnImplThread();
|
| -
|
| - for (size_t i = 0; i < layer->children().size(); ++i)
|
| - animateScrollbarsRecursive(layer->children()[i], monotonicTime);
|
| -}
|
| -
|
| -} // namespace cc
|
|
|