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

Unified Diff: cc/CCLayerTreeHostImpl.cpp

Issue 10916279: Chromium compositor change implementing page-scale driven pinch-zoom. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Remove dependency on content_common from cc for access to kEnablePinchZoomInCompositor. Created 8 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: cc/CCLayerTreeHostImpl.cpp
===================================================================
--- cc/CCLayerTreeHostImpl.cpp (revision 158825)
+++ cc/CCLayerTreeHostImpl.cpp (working copy)
@@ -49,6 +49,85 @@
namespace cc {
+float CCPinchZoomViewport::totalPageScaleFactor() const
+{
+ return m_pageScaleFactor * m_pageScaleDelta;
+}
+
+void CCPinchZoomViewport::setPageScaleDelta(float delta)
+{
+ // Clamp to the current min/max limits.
+ float finalMagnifyScale = m_pageScaleFactor * delta;
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Rename "finalMagnifyScale" to "totalPageScaleFacto
Jeff Timanus 2012/10/01 21:42:36 Done.
+ if (m_minPageScaleFactor && finalMagnifyScale < m_minPageScaleFactor)
+ delta = m_minPageScaleFactor / m_pageScaleFactor;
+ else if (m_maxPageScaleFactor && finalMagnifyScale > m_maxPageScaleFactor)
+ delta = m_maxPageScaleFactor / m_pageScaleFactor;
+
+ if (delta == m_pageScaleDelta)
+ return;
+
+ m_pageScaleDelta = delta;
+}
+
+bool CCPinchZoomViewport::setPageScaleFactorAndLimits(float pageScaleFactor, float minPageScaleFactor, float maxPageScaleFactor)
+{
+ if (!pageScaleFactor)
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Replace this with ASSERT(pageScaleFactor); since i
Jeff Timanus 2012/10/01 21:42:36 Done.
+ return false;
+
+ 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 scaledBounds = m_unpinchedBounds;
+ float totalScale = totalPageScaleFactor();
aelias_OOO_until_Jul13 2012/09/26 23:15:09 No need for this local variable.
Jeff Timanus 2012/10/01 21:42:36 Done.
+ if (totalScale > 1)
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Remove this if(). It's correct in the == 1 or < 1
aelias_OOO_until_Jul13 2012/09/26 23:19:04 Actually, maybe it's not. As I suggested in my co
+ scaledBounds.scale(1 / totalScale);
+
+ FloatRect bounds;
+ bounds.setSize(scaledBounds);
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Use the FloatRect constructor instead.
Jeff Timanus 2012/10/01 21:42:36 Done.
+ bounds.setLocation(m_pinchViewportScrollDelta);
+
+ return bounds;
+}
+
+FloatSize CCPinchZoomViewport::applyScroll(FloatSize& delta)
+{
+ FloatSize overflow;
+ FloatRect pinchedBounds = bounds();
+
+ pinchedBounds.move(delta);
+ if (pinchedBounds.x() < 0) {
+ pinchedBounds.setX(0);
+ overflow.setWidth(pinchedBounds.x());
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Looks like a bug here. Seems overflow values shou
Jeff Timanus 2012/10/01 21:42:36 Good catch. I'm surprised that this wasn't causin
Jeff Timanus 2012/10/01 21:42:36 Good catch. Fixed.
+ }
+
+ if (pinchedBounds.y() < 0) {
+ pinchedBounds.setY(0);
+ overflow.setHeight(pinchedBounds.y());
+ }
+
+ if (pinchedBounds.maxX() > m_unpinchedBounds.width()) {
+ pinchedBounds.move(m_unpinchedBounds.width() - pinchedBounds.maxX(), 0);
+ overflow.setWidth(pinchedBounds.maxX() - m_unpinchedBounds.width());
+ }
+
+ if (pinchedBounds.maxY() > m_unpinchedBounds.height()) {
+ pinchedBounds.move(0, m_unpinchedBounds.height() - pinchedBounds.maxY());
+ overflow.setHeight(pinchedBounds.maxY() - m_unpinchedBounds.height());
+ }
+ m_pinchViewportScrollDelta = pinchedBounds.location();
+
+ return overflow;
+}
+
class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient {
WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter);
public:
@@ -116,11 +195,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)
@@ -196,10 +270,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);
@@ -234,6 +308,13 @@
}
}
+void CCLayerTreeHostImpl::updateRootScrollLayerImplTransform()
+{
+ if (m_rootScrollLayerImpl) {
+ m_rootScrollLayerImpl->setImplTransform(implTransform());
+ }
+}
+
void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSurfaceLayerList)
{
ASSERT(renderSurfaceLayerList.isEmpty());
@@ -241,6 +322,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);
@@ -769,6 +852,8 @@
m_layoutViewportSize = layoutViewportSize;
m_deviceViewportSize = deviceViewportSize;
+ m_pinchZoomViewport.setUnpinchedBounds(FloatSize(layoutViewportSize));
+
updateMaxScrollPosition();
if (m_renderer)
@@ -802,48 +887,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()
@@ -859,11 +930,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();
@@ -946,7 +1028,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.
@@ -968,8 +1050,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);
@@ -1000,9 +1085,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);
@@ -1067,15 +1153,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();
@@ -1097,7 +1192,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);
}
@@ -1110,27 +1205,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)
@@ -1143,7 +1238,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)
@@ -1169,20 +1265,42 @@
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);
+ // If pinch zoom is applied in the impl thread, then there is no need to
aelias_OOO_until_Jul13 2012/09/26 23:15:09 There is still a need for this in some form. It's
Jeff Timanus 2012/10/01 21:42:36 Done.
+ // calculate these intermediate scale deltas.
+ 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
aelias_OOO_until_Jul13 2012/09/26 23:15:09 Move this method into CCPinchZoomViewport.
Jeff Timanus 2012/10/01 21:42:36 Done.
+{
+ WebTransformationMatrix transform;
+ transform.scale(m_pinchZoomViewport.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_pinchZoomViewport.pageScaleFactor());
+ transform.translate(-m_pinchZoomViewport.scrollDelta().x(),
+ -m_pinchZoomViewport.scrollDelta().y());
+ }
+
+ return transform;
+}
+
void CCLayerTreeHostImpl::setFullRootLayerDamage()
{
if (m_rootLayerImpl) {
@@ -1199,9 +1317,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();

Powered by Google App Engine
This is Rietveld 408576698