Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d23203e authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Per-pointer processing in VelocityTracker

We would like to skip resampled data in VelocityTracker when the
velocity is being computed. To make this happen, we need to first
process the data per-pointer. This will then allow us to skip individual
data points.

To minimize the impact to older VT strategies that are largely untested,
the main change here is to make 'mMovements' and 'mIndex' become
per-pointer, rather than converting to a vector.

Also, use std::array instead of [] because [] cannot be used inside a
std::map easily.

There should be no functional change in this CL. The actual skipping of
resampled values will be done in a separate CL.

Bug: 167946721
Test: m libinput_tests && $ANDROID_HOST_OUT/nativetest64/libinput_tests/libinput_tests

Change-Id: I1c3c845bca0d4bb7d2c3973bfe84462139ac36f3
parent 657a1732
Loading
Loading
Loading
Loading
+24 −44
Original line number Diff line number Diff line
@@ -103,19 +103,13 @@ public:
    // Resets the velocity tracker state.
    void clear();

    // Resets the velocity tracker state for specific pointers.
    // Resets the velocity tracker state for a specific pointer.
    // Call this method when some pointers have changed and may be reusing
    // an id that was assigned to a different pointer earlier.
    void clearPointers(BitSet32 idBits);
    void clearPointer(int32_t pointerId);

    // Adds movement information for a set of pointers.
    // The idBits bitfield specifies the pointer ids of the pointers whose data points
    // are included in the movement.
    // The positions map contains a mapping of an axis to positions array.
    // The positions arrays contain information for each pointer in order by increasing id.
    // Each array's size should be equal to the number of one bits in idBits.
    void addMovement(nsecs_t eventTime, BitSet32 idBits,
                     const std::map<int32_t, std::vector<float>>& positions);
    // Adds movement information for a pointer for a specific axis
    void addMovement(nsecs_t eventTime, int32_t pointerId, int32_t axis, float position);

    // Adds movement information for all pointers in a MotionEvent, including historical samples.
    void addMovement(const MotionEvent* event);
@@ -173,9 +167,8 @@ protected:
public:
    virtual ~VelocityTrackerStrategy() { }

    virtual void clearPointers(BitSet32 idBits) = 0;
    virtual void addMovement(nsecs_t eventTime, BitSet32 idBits,
                             const std::vector<float>& positions) = 0;
    virtual void clearPointer(int32_t pointerId) = 0;
    virtual void addMovement(nsecs_t eventTime, int32_t pointerId, float position) = 0;
    virtual std::optional<VelocityTracker::Estimator> getEstimator(int32_t pointerId) const = 0;
};

@@ -204,9 +197,8 @@ public:
    LeastSquaresVelocityTrackerStrategy(uint32_t degree, Weighting weighting = Weighting::NONE);
    ~LeastSquaresVelocityTrackerStrategy() override;

    void clearPointers(BitSet32 idBits) override;
    void addMovement(nsecs_t eventTime, BitSet32 idBits,
                     const std::vector<float>& positions) override;
    void clearPointer(int32_t pointerId) override;
    void addMovement(nsecs_t eventTime, int32_t pointerId, float position) override;
    std::optional<VelocityTracker::Estimator> getEstimator(int32_t pointerId) const override;

private:
@@ -220,18 +212,15 @@ private:

    struct Movement {
        nsecs_t eventTime;
        BitSet32 idBits;
        float positions[MAX_POINTERS];

        inline float getPosition(int32_t id) const { return positions[idBits.getIndexOfBit(id)]; }
        float position;
    };

    float chooseWeight(uint32_t index) const;
    float chooseWeight(int32_t pointerId, uint32_t index) const;

    const uint32_t mDegree;
    const Weighting mWeighting;
    uint32_t mIndex;
    Movement mMovements[HISTORY_SIZE];
    std::map<int32_t /*pointerId*/, size_t /*positionInArray*/> mIndex;
    std::map<int32_t /*pointerId*/, std::array<Movement, HISTORY_SIZE>> mMovements;
};


@@ -244,9 +233,8 @@ public:
    IntegratingVelocityTrackerStrategy(uint32_t degree);
    ~IntegratingVelocityTrackerStrategy() override;

    void clearPointers(BitSet32 idBits) override;
    void addMovement(nsecs_t eventTime, BitSet32 idBits,
                     const std::vector<float>& positions) override;
    void clearPointer(int32_t pointerId) override;
    void addMovement(nsecs_t eventTime, int32_t pointerId, float positions) override;
    std::optional<VelocityTracker::Estimator> getEstimator(int32_t pointerId) const override;

private:
@@ -276,9 +264,8 @@ public:
    LegacyVelocityTrackerStrategy();
    ~LegacyVelocityTrackerStrategy() override;

    void clearPointers(BitSet32 idBits) override;
    void addMovement(nsecs_t eventTime, BitSet32 idBits,
                     const std::vector<float>& positions) override;
    void clearPointer(int32_t pointerId) override;
    void addMovement(nsecs_t eventTime, int32_t pointerId, float position) override;
    std::optional<VelocityTracker::Estimator> getEstimator(int32_t pointerId) const override;

private:
@@ -293,14 +280,11 @@ private:

    struct Movement {
        nsecs_t eventTime;
        BitSet32 idBits;
        float positions[MAX_POINTERS];

        inline float getPosition(int32_t id) const { return positions[idBits.getIndexOfBit(id)]; }
        float position;
    };

    uint32_t mIndex;
    Movement mMovements[HISTORY_SIZE];
    std::map<int32_t /*pointerId*/, size_t /*positionInArray*/> mIndex;
    std::map<int32_t /*pointerId*/, std::array<Movement, HISTORY_SIZE>> mMovements;
};

class ImpulseVelocityTrackerStrategy : public VelocityTrackerStrategy {
@@ -308,9 +292,8 @@ public:
    ImpulseVelocityTrackerStrategy(bool deltaValues);
    ~ImpulseVelocityTrackerStrategy() override;

    void clearPointers(BitSet32 idBits) override;
    void addMovement(nsecs_t eventTime, BitSet32 idBits,
                     const std::vector<float>& positions) override;
    void clearPointer(int32_t pointerId) override;
    void addMovement(nsecs_t eventTime, int32_t pointerId, float position) override;
    std::optional<VelocityTracker::Estimator> getEstimator(int32_t pointerId) const override;

private:
@@ -324,10 +307,7 @@ private:

    struct Movement {
        nsecs_t eventTime;
        BitSet32 idBits;
        float positions[MAX_POINTERS];

        inline float getPosition(int32_t id) const { return positions[idBits.getIndexOfBit(id)]; }
        float position;
    };

    // Whether or not the input movement values for the strategy come in the form of delta values.
@@ -335,8 +315,8 @@ private:
    // velocity calculation.
    const bool mDeltaValues;

    size_t mIndex;
    Movement mMovements[HISTORY_SIZE];
    std::map<int32_t /*pointerId*/, size_t /*positionInArray*/> mIndex;
    std::map<int32_t /*pointerId*/, std::array<Movement, HISTORY_SIZE>> mMovements;
};

} // namespace android
+4 −3
Original line number Diff line number Diff line
@@ -70,9 +70,10 @@ void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
        if (deltaY) {
            mRawPositionY += *deltaY;
        }
        mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)),
                                     {{AMOTION_EVENT_AXIS_X, {mRawPositionX}},
                                      {AMOTION_EVENT_AXIS_Y, {mRawPositionY}}});
        mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_X,
                                     mRawPositionX);
        mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_Y,
                                     mRawPositionY);

        std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0);
        std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0);
+174 −177

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -431,7 +431,7 @@ TEST_F(VelocityTrackerTest, TestApiInteractionsWithNoMotionEvents) {
    EXPECT_EQ(-1, vt.getActivePointerId());

    // Make sure that the clearing functions execute without an issue.
    vt.clearPointers(BitSet32(7U));
    vt.clearPointer(7U);
    vt.clear();
}

+4 −7
Original line number Diff line number Diff line
@@ -2703,18 +2703,15 @@ bool TouchInputMapper::preparePointerGestures(nsecs_t when, bool* outCancelPrevi

    // Update the velocity tracker.
    {
        std::vector<float> positionsX;
        std::vector<float> positionsY;
        for (BitSet32 idBits(mCurrentCookedState.fingerIdBits); !idBits.isEmpty();) {
            uint32_t id = idBits.clearFirstMarkedBit();
            const RawPointerData::Pointer& pointer =
                    mCurrentRawState.rawPointerData.pointerForId(id);
            positionsX.push_back(pointer.x * mPointerXMovementScale);
            positionsY.push_back(pointer.y * mPointerYMovementScale);
            const float x = pointer.x * mPointerXMovementScale;
            const float y = pointer.y * mPointerYMovementScale;
            mPointerGesture.velocityTracker.addMovement(when, id, AMOTION_EVENT_AXIS_X, x);
            mPointerGesture.velocityTracker.addMovement(when, id, AMOTION_EVENT_AXIS_Y, y);
        }
        mPointerGesture.velocityTracker.addMovement(when, mCurrentCookedState.fingerIdBits,
                                                    {{AMOTION_EVENT_AXIS_X, positionsX},
                                                     {AMOTION_EVENT_AXIS_Y, positionsY}});
    }

    // If the gesture ever enters a mode other than TAP, HOVER or TAP_DRAG, without first returning