| Index: cc/CCLayerTreeHostImpl.cpp
|
| ===================================================================
|
| --- cc/CCLayerTreeHostImpl.cpp (revision 160422)
|
| +++ cc/CCLayerTreeHostImpl.cpp (working copy)
|
| @@ -52,6 +52,110 @@
|
|
|
| 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)
|
| @@ -120,11 +224,6 @@
|
| , m_visible(true)
|
| , m_contentsTexturesPurged(false)
|
| , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit())
|
| - , m_pageScale(1)
|
| - , m_pageScaleDelta(1)
|
| - , m_sentPageScaleDelta(1)
|
| - , m_minPageScale(0)
|
| - , m_maxPageScale(0)
|
| , m_backgroundColor(0)
|
| , m_hasTransparentBackground(false)
|
| , m_needsAnimateLayers(false)
|
| @@ -202,10 +301,10 @@
|
| return;
|
|
|
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
|
| - scrollTotal.scale(m_pageScaleDelta);
|
| - float scaleTotal = m_pageScale * m_pageScaleDelta;
|
| + scrollTotal.scale(m_pinchZoomViewport.pageScaleDelta());
|
| + float scaleTotal = m_pinchZoomViewport.totalPageScaleFactor();
|
| IntSize scaledContentSize = contentSize();
|
| - scaledContentSize.scale(m_pageScaleDelta);
|
| + scaledContentSize.scale(m_pinchZoomViewport.pageScaleDelta());
|
|
|
| m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_deviceViewportSize, scaledContentSize, startTime);
|
|
|
| @@ -240,6 +339,13 @@
|
| }
|
| }
|
|
|
| +void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
|
| +{
|
| + if (m_rootScrollLayerImpl) {
|
| + m_rootScrollLayerImpl->setImplTransform(implTransform());
|
| + }
|
| +}
|
| +
|
| void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
|
| {
|
| ASSERT(renderSurfaceLayerList.isEmpty());
|
| @@ -247,6 +353,8 @@
|
| ASSERT(m_renderer); // For maxTextureSize.
|
|
|
| {
|
| + updateRootScrollLayerImplTransform();
|
| +
|
| TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
|
| CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, rendererCapabilities().maxTextureSize, renderSurfaceLayerList);
|
| CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
|
| @@ -778,6 +886,8 @@
|
| m_layoutViewportSize = layoutViewportSize;
|
| m_deviceViewportSize = deviceViewportSize;
|
|
|
| + m_pinchZoomViewport.setLayoutViewportSize(FloatSize(layoutViewportSize));
|
| +
|
| updateMaxScrollPosition();
|
|
|
| if (m_renderer)
|
| @@ -811,48 +921,34 @@
|
| updateMaxScrollPosition();
|
| }
|
|
|
| +float CCLayerTreeHostImpl::pageScaleFactor() const
|
| +{
|
| + return m_pinchZoomViewport.pageScaleFactor();
|
| +}
|
|
|
| -void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale)
|
| +void CCLayerTreeHostImpl::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
|
| {
|
| - if (!pageScale)
|
| - return;
|
| + if (!pageScaleFactor)
|
| + return;
|
|
|
| - if (m_sentPageScaleDelta == 1 && pageScale == m_pageScale && minPageScale == m_minPageScale && maxPageScale == m_maxPageScale)
|
| - return;
|
| + float pageScaleChange = pageScaleFactor / m_pinchZoomViewport.pageScaleFactor();
|
| + m_pinchZoomViewport.setPageScaleFactorAndLimits(pageScaleFactor, minPageScaleFactor, maxPageScaleFactor);
|
|
|
| - m_minPageScale = minPageScale;
|
| - m_maxPageScale = maxPageScale;
|
| + if (!CCSettings::pageScalePinchZoomEnabled()) {
|
| + if (pageScaleChange != 1)
|
| + adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
|
| + }
|
|
|
| - float pageScaleChange = pageScale / m_pageScale;
|
| - m_pageScale = pageScale;
|
| -
|
| - if (pageScaleChange != 1)
|
| - adjustScrollsForPageScaleChange(m_rootScrollLayerImpl, pageScaleChange);
|
| -
|
| // Clamp delta to limits and refresh display matrix.
|
| - setPageScaleDelta(m_pageScaleDelta / m_sentPageScaleDelta);
|
| - m_sentPageScaleDelta = 1;
|
| - if (m_rootScrollLayerImpl)
|
| - m_rootScrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
|
| + setPageScaleDelta(m_pinchZoomViewport.pageScaleDelta() / m_pinchZoomViewport.sentPageScaleDelta());
|
| + m_pinchZoomViewport.setSentPageScaleDelta(1);
|
| }
|
|
|
| void CCLayerTreeHostImpl::setPageScaleDelta(float delta)
|
| {
|
| - // Clamp to the current min/max limits.
|
| - float finalMagnifyScale = m_pageScale * delta;
|
| - if (m_minPageScale && finalMagnifyScale < m_minPageScale)
|
| - delta = m_minPageScale / m_pageScale;
|
| - else if (m_maxPageScale && finalMagnifyScale > m_maxPageScale)
|
| - delta = m_maxPageScale / m_pageScale;
|
| + m_pinchZoomViewport.setPageScaleDelta(delta);
|
|
|
| - if (delta == m_pageScaleDelta)
|
| - return;
|
| -
|
| - m_pageScaleDelta = delta;
|
| -
|
| updateMaxScrollPosition();
|
| - if (m_rootScrollLayerImpl)
|
| - m_rootScrollLayerImpl->setPageScaleDelta(m_pageScaleDelta);
|
| }
|
|
|
| void CCLayerTreeHostImpl::updateMaxScrollPosition()
|
| @@ -868,11 +964,22 @@
|
| viewBounds.scale(m_deviceScaleFactor);
|
| }
|
| }
|
| - viewBounds.scale(1 / m_pageScaleDelta);
|
|
|
| - // maxScroll is computed in physical pixels, but scroll positions are in layout pixels.
|
| - IntSize maxScroll = contentSize() - expandedIntSize(viewBounds);
|
| + 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();
|
| @@ -960,7 +1067,7 @@
|
| return ScrollIgnored;
|
| }
|
|
|
| -static FloatSize scrollLayerWithScreenSpaceDelta(CCLayerImpl& layerImpl, const FloatPoint& screenSpacePoint, const FloatSize& screenSpaceDelta)
|
| +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.
|
| @@ -982,8 +1089,11 @@
|
|
|
| // Apply the scroll delta.
|
| FloatSize previousDelta(layerImpl.scrollDelta());
|
| - layerImpl.scrollBy(localEndPoint - localStartPoint);
|
| + 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);
|
| @@ -1014,9 +1124,10 @@
|
| if (!layerImpl->scrollable())
|
| continue;
|
|
|
| + CCPinchZoomViewport* viewport = layerImpl == m_rootScrollLayerImpl ? &m_pinchZoomViewport : 0;
|
| FloatSize appliedDelta;
|
| if (m_scrollDeltaIsInScreenSpace)
|
| - appliedDelta = scrollLayerWithScreenSpaceDelta(*layerImpl, viewportPoint, pendingDelta);
|
| + appliedDelta = scrollLayerWithScreenSpaceDelta(viewport, *layerImpl, viewportPoint, pendingDelta);
|
| else
|
| appliedDelta = scrollLayerWithLocalDelta(*layerImpl, pendingDelta);
|
|
|
| @@ -1081,15 +1192,24 @@
|
|
|
| // Keep the center-of-pinch anchor specified by (x, y) in a stable
|
| // position over the course of the magnify.
|
| - FloatPoint previousScaleAnchor(m_previousPinchAnchor.x() / m_pageScaleDelta, m_previousPinchAnchor.y() / m_pageScaleDelta);
|
| - setPageScaleDelta(m_pageScaleDelta * magnifyDelta);
|
| - FloatPoint newScaleAnchor(anchor.x() / m_pageScaleDelta, anchor.y() / m_pageScaleDelta);
|
| + 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;
|
|
|
| - m_rootScrollLayerImpl->scrollBy(roundedIntSize(move));
|
| + 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();
|
|
|
| @@ -1111,7 +1231,7 @@
|
| {
|
| float pageScale = m_pageScaleAnimation->finalPageScale();
|
| IntSize scrollOffset = m_pageScaleAnimation->finalScrollOffset();
|
| - scrollOffset.scale(m_pageScale / pageScale);
|
| + scrollOffset.scale(m_pinchZoomViewport.pageScaleFactor() / pageScale);
|
| makeScrollAndScaleSet(scrollInfo, scrollOffset, pageScale);
|
| }
|
|
|
| @@ -1124,27 +1244,27 @@
|
| // significant amount. This also ensures only one fake delta set will be
|
| // sent.
|
| const float pinchZoomOutSensitivity = 0.95f;
|
| - if (m_pageScaleDelta > pinchZoomOutSensitivity)
|
| + 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_pageScaleDelta);
|
| - float scaleBegin = m_pageScale * m_pageScaleDelta;
|
| - float pageScaleDeltaToSend = m_minPageScale / m_pageScale;
|
| + 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_minPageScale / scaleBegin);
|
| + 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_minPageScale);
|
| + makeScrollAndScaleSet(scrollInfo, roundedIntSize(scrollEnd), m_pinchZoomViewport.minPageScaleFactor());
|
| }
|
|
|
| void CCLayerTreeHostImpl::makeScrollAndScaleSet(CCScrollAndScaleSet* scrollInfo, const IntSize& scrollOffset, float pageScale)
|
| @@ -1157,7 +1277,8 @@
|
| scroll.scrollDelta = scrollOffset - toSize(m_rootScrollLayerImpl->scrollPosition());
|
| scrollInfo->scrolls.append(scroll);
|
| m_rootScrollLayerImpl->setSentScrollDelta(scroll.scrollDelta);
|
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = pageScale / m_pageScale;
|
| + scrollInfo->pageScaleDelta = pageScale / m_pinchZoomViewport.pageScaleFactor();
|
| + m_pinchZoomViewport.setSentPageScaleDelta(scrollInfo->pageScaleDelta);
|
| }
|
|
|
| static void collectScrollDeltas(CCScrollAndScaleSet* scrollInfo, CCLayerImpl* layerImpl)
|
| @@ -1183,20 +1304,31 @@
|
| OwnPtr<CCScrollAndScaleSet> scrollInfo = adoptPtr(new CCScrollAndScaleSet());
|
|
|
| if (m_pinchGestureActive || m_pageScaleAnimation) {
|
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = 1;
|
| - if (m_pinchGestureActive)
|
| - computePinchZoomDeltas(scrollInfo.get());
|
| - else if (m_pageScaleAnimation.get())
|
| - computeDoubleTapZoomDeltas(scrollInfo.get());
|
| + 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());
|
| - m_sentPageScaleDelta = scrollInfo->pageScaleDelta = m_pageScaleDelta;
|
| + 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) {
|
| @@ -1213,9 +1345,9 @@
|
|
|
| IntSize scrollTotal = flooredIntSize(m_rootScrollLayerImpl->scrollPosition() + m_rootScrollLayerImpl->scrollDelta());
|
|
|
| - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale);
|
| + setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pinchZoomViewport.pageScaleFactor());
|
| IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime);
|
| - nextScroll.scale(1 / m_pageScaleDelta);
|
| + nextScroll.scale(1 / m_pinchZoomViewport.pageScaleDelta());
|
| m_rootScrollLayerImpl->scrollBy(nextScroll - scrollTotal);
|
| m_client->setNeedsRedrawOnImplThread();
|
|
|
|
|