From 23699318aa0796ab3d77829ac8f73fbdfbb2e879 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Mon, 10 Nov 2014 12:02:00 +0100 Subject: [PATCH] Bug 1094525 - Simplify touch resampling code in GeckoTouchDispatcher, r=kats --- widget/gonk/GeckoTouchDispatcher.cpp | 138 ++++++++++++--------------- widget/gonk/GeckoTouchDispatcher.h | 2 - 2 files changed, 59 insertions(+), 81 deletions(-) diff --git a/widget/gonk/GeckoTouchDispatcher.cpp b/widget/gonk/GeckoTouchDispatcher.cpp index 47ba24ebd915..46b038246cf8 100644 --- a/widget/gonk/GeckoTouchDispatcher.cpp +++ b/widget/gonk/GeckoTouchDispatcher.cpp @@ -47,7 +47,6 @@ namespace mozilla { // Amount of time in MS before an input is considered expired. static const uint64_t kInputExpirationThresholdMs = 1000; -static int32_t microsecToMillisec(int64_t microsec) { return microsec / 1000; } static StaticRefPtr sTouchDispatcher; @@ -207,9 +206,9 @@ GeckoTouchDispatcher::DispatchTouchMoveEvents(TimeStamp aVsyncTime) } static int -Interpolate(int start, int end, int64_t aFrameDiff, int64_t aTouchDiff) +Interpolate(int start, int end, TimeDuration aFrameDiff, TimeDuration aTouchDiff) { - return start + (((end - start) * aFrameDiff) / aTouchDiff); + return start + (((end - start) * aFrameDiff.ToMicroseconds()) / aTouchDiff.ToMicroseconds()); } static const SingleTouchData& @@ -230,115 +229,96 @@ GetTouchByID(const SingleTouchData& aCurrentTouch, MultiTouchInput& aOtherTouch) return aCurrentTouch; } + +// aTouchDiff is the duration between the base and current touch times +// aFrameDiff is the duration between the base and the time we're resampling to static void -ResampleTouch(MultiTouchInput& aOutTouch, MultiTouchInput& aCurrent, - MultiTouchInput& aOther, int64_t aFrameDiff, - int64_t aTouchDiff, bool aInterpolate) +ResampleTouch(MultiTouchInput& aOutTouch, + MultiTouchInput& aBase, MultiTouchInput& aCurrent, + TimeDuration aFrameDiff, TimeDuration aTouchDiff) { aOutTouch = aCurrent; // Make sure we only resample the correct finger. for (size_t i = 0; i < aOutTouch.mTouches.Length(); i++) { - const SingleTouchData& current = aCurrent.mTouches[i]; - const SingleTouchData& other = GetTouchByID(current, aOther); + const SingleTouchData& base = aBase.mTouches[i]; + const SingleTouchData& current = GetTouchByID(base, aCurrent); + const ScreenIntPoint& baseTouchPoint = base.mScreenPoint; const ScreenIntPoint& currentTouchPoint = current.mScreenPoint; - const ScreenIntPoint& otherTouchPoint = other.mScreenPoint; ScreenIntPoint newSamplePoint; - newSamplePoint.x = Interpolate(currentTouchPoint.x, otherTouchPoint.x, aFrameDiff, aTouchDiff); - newSamplePoint.y = Interpolate(currentTouchPoint.y, otherTouchPoint.y, aFrameDiff, aTouchDiff); + newSamplePoint.x = Interpolate(baseTouchPoint.x, currentTouchPoint.x, aFrameDiff, aTouchDiff); + newSamplePoint.y = Interpolate(baseTouchPoint.y, currentTouchPoint.y, aFrameDiff, aTouchDiff); aOutTouch.mTouches[i].mScreenPoint = newSamplePoint; #ifdef LOG_RESAMPLE_DATA const char* type = "extrapolate"; - if (aInterpolate) { + if (aFrameDiff < aTouchDiff) { type = "interpolate"; } - float alpha = (double) aFrameDiff / (double) aTouchDiff; - LOG("%s current (%d, %d), other (%d, %d) to (%d, %d) alpha %f, touch diff %llu, frame diff %lld\n", + float alpha = aFrameDiff / aTouchDiff; + LOG("%s base (%d, %d), current (%d, %d) to (%d, %d) alpha %f, touch diff %d, frame diff %d\n", type, + baseTouchPoint.x, baseTouchPoint.y, currentTouchPoint.x, currentTouchPoint.y, - otherTouchPoint.x, otherTouchPoint.y, newSamplePoint.x, newSamplePoint.y, - alpha, aTouchDiff, aFrameDiff); + alpha, (int)aTouchDiff.ToMilliseconds(), (int)aFrameDiff.ToMilliseconds()); #endif } } -// Interpolates with the touch event prior to SampleTime -// and with the future touch event past sample time -int32_t -GeckoTouchDispatcher::InterpolateTouch(MultiTouchInput& aOutTouch, TimeStamp aSampleTime) -{ - MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2); - mTouchQueueLock.AssertCurrentThreadOwns(); - - // currentTouch < SampleTime < futureTouch - MultiTouchInput futureTouch = mTouchMoveEvents.back(); - mTouchMoveEvents.pop_back(); - MultiTouchInput currentTouch = mTouchMoveEvents.back(); - - mTouchMoveEvents.clear(); - mTouchMoveEvents.push_back(futureTouch); - - TimeStamp currentTouchTime = mLastTouchTime - mTouchTimeDiff; - int64_t frameDiff = (aSampleTime - currentTouchTime).ToMicroseconds(); - ResampleTouch(aOutTouch, currentTouch, futureTouch, frameDiff, mTouchTimeDiff.ToMicroseconds(), true); - - return microsecToMillisec(frameDiff); -} - -// Extrapolates from the previous two touch events before sample time -// and extrapolates them to sample time. -int32_t -GeckoTouchDispatcher::ExtrapolateTouch(MultiTouchInput& aOutTouch, TimeStamp aSampleTime) -{ - MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2); - mTouchQueueLock.AssertCurrentThreadOwns(); - - // prevTouch < currentTouch < SampleTime - MultiTouchInput currentTouch = mTouchMoveEvents.back(); - mTouchMoveEvents.pop_back(); - MultiTouchInput prevTouch = mTouchMoveEvents.back(); - mTouchMoveEvents.clear(); - mTouchMoveEvents.push_back(currentTouch); - - TimeStamp currentTouchTime = mLastTouchTime; - TimeDuration maxResampleTime = TimeDuration::FromMicroseconds( - std::min(mTouchTimeDiff.ToMicroseconds() / 2, - mMaxPredict.ToMicroseconds())); - TimeStamp maxTimestamp = currentTouchTime + maxResampleTime; - - if (aSampleTime > maxTimestamp) { - aSampleTime = maxTimestamp; - #ifdef LOG_RESAMPLE_DATA - LOG("Overshot extrapolation time, adjusting sample time\n"); - #endif - } - - // This has to be signed int since it is negative - int64_t frameDiff = (currentTouchTime - aSampleTime).ToMicroseconds(); - ResampleTouch(aOutTouch, currentTouch, prevTouch, frameDiff, mTouchTimeDiff.ToMicroseconds(), false); - return -microsecToMillisec(frameDiff); -} +/* + * +> Base touch (The touch before current touch) + * | + * | +> Current touch (Latest touch) + * | | + * | | +> Maximum resample time + * | | | + * +-----+------+--------------------> Time + * ^ ^ + * | | + * +------+--> Potential vsync events which the touches are resampled to + * | | + * | +> Extrapolation + * | + * +> Interpolation + */ void GeckoTouchDispatcher::ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp aVsyncTime) { - TimeStamp sampleTime = aVsyncTime - mVsyncAdjust; - int32_t touchTimeAdjust = 0; + MOZ_RELEASE_ASSERT(mTouchMoveEvents.size() >= 2); + mTouchQueueLock.AssertCurrentThreadOwns(); - if (mLastTouchTime > sampleTime) { - touchTimeAdjust = InterpolateTouch(aOutTouch, sampleTime); - } else { - touchTimeAdjust = ExtrapolateTouch(aOutTouch, sampleTime); + MultiTouchInput currentTouch = mTouchMoveEvents.back(); + mTouchMoveEvents.pop_back(); + MultiTouchInput baseTouch = mTouchMoveEvents.back(); + mTouchMoveEvents.clear(); + mTouchMoveEvents.push_back(currentTouch); + + TimeStamp sampleTime = aVsyncTime - mVsyncAdjust; + + if (mLastTouchTime < sampleTime) { + TimeDuration maxResampleTime = std::min(mTouchTimeDiff / 2, mMaxPredict); + TimeStamp maxTimestamp = mLastTouchTime + maxResampleTime; + if (sampleTime > maxTimestamp) { + sampleTime = maxTimestamp; + #ifdef LOG_RESAMPLE_DATA + LOG("Overshot extrapolation time, adjusting sample time\n"); + #endif + } } + ResampleTouch(aOutTouch, baseTouch, currentTouch, sampleTime - (mLastTouchTime - mTouchTimeDiff), mTouchTimeDiff); + + // Both mTimeStamp and mTime are being updated to sampleTime here. + // mTime needs to be updated using a delta since TimeStamp doesn't + // provide a way to obtain a raw value. + aOutTouch.mTime += (sampleTime - aOutTouch.mTimeStamp).ToMilliseconds(); aOutTouch.mTimeStamp = sampleTime; - aOutTouch.mTime += touchTimeAdjust; } // Some touch events get sent as mouse events. If APZ doesn't capture the event diff --git a/widget/gonk/GeckoTouchDispatcher.h b/widget/gonk/GeckoTouchDispatcher.h index 1fc0e243e09b..d2766b91cd7d 100644 --- a/widget/gonk/GeckoTouchDispatcher.h +++ b/widget/gonk/GeckoTouchDispatcher.h @@ -50,8 +50,6 @@ public: static bool NotifyVsync(TimeStamp aVsyncTimestamp); private: - int32_t InterpolateTouch(MultiTouchInput& aOutTouch, TimeStamp aSampleTime); - int32_t ExtrapolateTouch(MultiTouchInput& aOutTouch, TimeStamp aSampleTime); void ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp vsyncTime); void SendTouchEvent(MultiTouchInput& aData); void DispatchMouseEvent(MultiTouchInput& aMultiTouch,