Bug 1094525 - Simplify touch resampling code in GeckoTouchDispatcher, r=kats

This commit is contained in:
Michael Wu 2014-11-10 12:02:00 +01:00
Родитель 083547dbdc
Коммит 23699318aa
2 изменённых файлов: 59 добавлений и 81 удалений

Просмотреть файл

@ -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<GeckoTouchDispatcher> 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

Просмотреть файл

@ -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,