Changeset 290121 in webkit


Ignore:
Timestamp:
Feb 18, 2022, 2:47:13 AM (4 years ago)
Author:
graouts@webkit.org
Message:

[frame-rate] animation with different but compatible frame rates should be aligned
https://bugs.webkit.org/show_bug.cgi?id=236778
<rdar://problem/89083932>

Reviewed by Simon Fraser.

Source/WebCore:

With bug 234202 we started accounting for the frameRate property of an animation when updating
animations and ensuring that animations with the same frameRate are sampled in the same frame.

We expand on this by aligning animations that use different frameRate but could share sample frames.
For instance, if we have animations running with frameRate set to 6, 12 and 18, and assuming no
frames are ever skipped, we should expect a sequence of frames where the following animations are
sampled:

  • frame 1: 12, 18, 6
  • frame 2: 18
  • frame 3: 12
  • frame 4: 18
  • frame 5: 12, 18, 6

and for that pattern to repeat.

To achieve this, we add a new "isNew" boolean flag on the FrameRateData struct. Then, in
FrameRateAligner::finishUpdate(), which is newly called from updateAnimationsAndSendEvents(),
we identify which frame rates have this flag, and analyze the other frame rates to determine
which frame rate it is most compatible with. If we find such a compatible frame rate, the new
frame rate adopts the same firstUpdateTime which ensures that they now have the same basis to
compute ideal times for sampling.

Within updateAnimationsAndSendEvents(), we also ensure that newly-added animations, regardless
of the output of FrameRateAligner::updateFrameRate(), are sampled right away so that there's no
delay for an animation to have visual output, letting them be synchronized with other animations
of that frame rate at the next opportunity.

Tests: webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates.html

webanimations/frame-rate/animation-frame-rate-alignment-started-together.html
webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation.html

  • animation/DocumentTimelinesController.cpp:

(WebCore::DocumentTimelinesController::updateAnimationsAndSendEvents):

  • animation/FrameRateAligner.cpp:

(WebCore::FrameRateAligner::beginUpdate):
(WebCore::FrameRateAligner::updateFrameRate):
(WebCore::frameRatesCanBeAligned):
(WebCore::FrameRateAligner::finishUpdate):

  • animation/FrameRateAligner.h:

LayoutTests:

Add new tests that check the behavior of alignment when:

  • two animations are started together with the same frame rate,
  • two animations are started one frame apart with the same frame rate,
  • three animations are each started one frame apart and with different, but compatible frame rates.
  • TestExpectations:
  • platform/ios-wk2/TestExpectations:
  • platform/mac-wk2/TestExpectations:
  • webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates-expected.txt: Added.
  • webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates.html: Added.
  • webanimations/frame-rate/animation-frame-rate-alignment-started-together-expected.txt: Added.
  • webanimations/frame-rate/animation-frame-rate-alignment-started-together.html: Added.
  • webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation-expected.txt: Added.
  • webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation.html: Added.
Location:
trunk
Files:
6 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r290120 r290121  
     12022-02-18  Antoine Quint  <graouts@webkit.org>
     2
     3        [frame-rate] animation with different but compatible frame rates should be aligned
     4        https://bugs.webkit.org/show_bug.cgi?id=236778
     5        <rdar://problem/89083932>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Add new tests that check the behavior of alignment when:
     10       
     11        - two animations are started together with the same frame rate,
     12        - two animations are started one frame apart with the same frame rate,
     13        - three animations are each started one frame apart and with different, but compatible frame rates.
     14
     15        * TestExpectations:
     16        * platform/ios-wk2/TestExpectations:
     17        * platform/mac-wk2/TestExpectations:
     18        * webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates-expected.txt: Added.
     19        * webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates.html: Added.
     20        * webanimations/frame-rate/animation-frame-rate-alignment-started-together-expected.txt: Added.
     21        * webanimations/frame-rate/animation-frame-rate-alignment-started-together.html: Added.
     22        * webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation-expected.txt: Added.
     23        * webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation.html: Added.
     24
    1252022-02-18  Jon Lee  <jonlee@apple.com>
    226
  • trunk/LayoutTests/TestExpectations

    r290116 r290121  
    11241124fast/css/accent-color/text.html [ ImageOnlyFailure ]
    11251125imported/w3c/web-platform-tests/css/css-ui/accent-color-checkbox-checked-001.tentative.html [ ImageOnlyFailure ]
     1126
     1127webanimations/frame-rate [ Skip ]
    11261128
    11271129#//////////////////////////////////////////////////////////////////////////////////////////
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r289965 r290121  
    148148imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Skip ]
    149149webkit.org/b/235072 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html [ Skip ]
     150
     151webanimations/frame-rate [ Pass ]
    150152
    151153#//////////////////////////////////////////////////////////////////////////////////////////
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r289871 r290121  
    126126
    127127webkit.org/b/235072 imported/w3c/web-platform-tests/video-rvfc/request-video-frame-callback-repeating.html [ Skip ]
     128
     129webanimations/frame-rate [ Pass ]
    128130
    129131#//////////////////////////////////////////////////////////////////////////////////////////
  • trunk/Source/WebCore/ChangeLog

    r290118 r290121  
     12022-02-18  Antoine Quint  <graouts@webkit.org>
     2
     3        [frame-rate] animation with different but compatible frame rates should be aligned
     4        https://bugs.webkit.org/show_bug.cgi?id=236778
     5        <rdar://problem/89083932>
     6
     7        Reviewed by Simon Fraser.
     8
     9        With bug 234202 we started accounting for the frameRate property of an animation when updating
     10        animations and ensuring that animations with the same frameRate are sampled in the same frame.
     11
     12        We expand on this by aligning animations that use different frameRate but could share sample frames.
     13        For instance, if we have animations running with frameRate set to 6, 12 and 18, and assuming no
     14        frames are ever skipped, we should expect a sequence of frames where the following animations are
     15        sampled:
     16       
     17        - frame 1: 12, 18, 6
     18        - frame 2: 18
     19        - frame 3: 12
     20        - frame 4: 18
     21        - frame 5: 12, 18, 6
     22
     23        and for that pattern to repeat.
     24
     25        To achieve this, we add a new "isNew" boolean flag on the FrameRateData struct. Then, in
     26        FrameRateAligner::finishUpdate(), which is newly called from updateAnimationsAndSendEvents(),
     27        we identify which frame rates have this flag, and analyze the other frame rates to determine
     28        which frame rate it is most compatible with. If we find such a compatible frame rate, the new
     29        frame rate adopts the same firstUpdateTime which ensures that they now have the same basis to
     30        compute ideal times for sampling.
     31
     32        Within updateAnimationsAndSendEvents(), we also ensure that newly-added animations, regardless
     33        of the output of FrameRateAligner::updateFrameRate(), are sampled right away so that there's no
     34        delay for an animation to have visual output, letting them be synchronized with other animations
     35        of that frame rate at the next opportunity.
     36
     37        Tests: webanimations/frame-rate/animation-frame-rate-alignment-compatible-frame-rates.html
     38               webanimations/frame-rate/animation-frame-rate-alignment-started-together.html
     39               webanimations/frame-rate/animation-frame-rate-alignment-started-with-one-frame-separation.html
     40
     41        * animation/DocumentTimelinesController.cpp:
     42        (WebCore::DocumentTimelinesController::updateAnimationsAndSendEvents):
     43        * animation/FrameRateAligner.cpp:
     44        (WebCore::FrameRateAligner::beginUpdate):
     45        (WebCore::FrameRateAligner::updateFrameRate):
     46        (WebCore::frameRatesCanBeAligned):
     47        (WebCore::FrameRateAligner::finishUpdate):
     48        * animation/FrameRateAligner.h:
     49
    1502022-02-18  Zan Dobersek  <zdobersek@igalia.com>
    251
  • trunk/Source/WebCore/animation/DocumentTimelinesController.cpp

    r290003 r290121  
    138138            if (animationFrameRate) {
    139139                ASSERT(*animationFrameRate > 0);
    140                 if (m_frameRateAligner.updateFrameRate(*animationFrameRate) == FrameRateAligner::ShouldUpdate::No)
     140                auto shouldUpdate = m_frameRateAligner.updateFrameRate(*animationFrameRate);
     141                // Even if we're told not to update, any newly-added animation should fire right away,
     142                // it will align with other animations of that frame rate at the next opportunity.
     143                if (shouldUpdate == FrameRateAligner::ShouldUpdate::No && !animation->pending())
    141144                    continue;
    142145            }
     
    156159        }
    157160    }
     161
     162    m_frameRateAligner.finishUpdate();
    158163
    159164    // If the maximum frame rate we've encountered is the same as the default frame rate,
  • trunk/Source/WebCore/animation/FrameRateAligner.cpp

    r290003 r290121  
    4949    const auto nextUpdateTimeEpsilon = 1_ms;
    5050    for (auto& [frameRate, data] : m_frameRates) {
     51        // We can reset isNew to false for all entries since they were already present
     52        // in the previous update.
     53        data.isNew = false;
     54
    5155        // If the timeline frame rate is the same as this animation frame rate, then
    5256        // we don't need to compute the next ideal sample time.
     
    7983
    8084    // We're dealing with a frame rate we didn't see in the previous update. In this case,
    81     // we'll allow animations to be sampled right away.
    82     // FIXME: We need make sure to reset the last update time to align this new frame rate
    83     // with other compatible frame rates.
     85    // we'll allow animations to be sampled right away. Later, in finishUpdate(), we'll
     86    // make sure to reset the last update time to align this new frame rate with other
     87    // compatible frame rates.
    8488    m_frameRates.set(frameRate, FrameRateData { m_timestamp, m_timestamp });
    8589    return ShouldUpdate::Yes;
     90}
     91
     92// For two frame rates to be aligned, one must be the multitple of the other, or vice versa.
     93static bool frameRatesCanBeAligned(FramesPerSecond a, FramesPerSecond b)
     94{
     95    return (a > b && a % b == 0) || (b > a && b % a == 0);
     96}
     97
     98void FrameRateAligner::finishUpdate()
     99{
     100    // Iterate through the frame rates to find new entries and set their first update time
     101    // in a way that future updates will be synchronized with other animations with that
     102    // frame rate.
     103    for (auto& [frameRate, data] : m_frameRates) {
     104        if (!data.isNew)
     105            continue;
     106
     107        // Look for the compatible frame rate with the highest value.
     108        std::optional<FramesPerSecond> highestCompatibleFrameRate;
     109        for (auto& [potentiallyCompatibleFrameRate, potentiallyCompatibleData] : m_frameRates) {
     110            if (potentiallyCompatibleData.isNew)
     111                continue;
     112
     113            if (frameRatesCanBeAligned(frameRate, potentiallyCompatibleFrameRate)) {
     114                if (!highestCompatibleFrameRate || *highestCompatibleFrameRate > potentiallyCompatibleFrameRate)
     115                    highestCompatibleFrameRate = potentiallyCompatibleFrameRate;
     116            }
     117        }
     118
     119        // If we don't find any compatible frame rate, we can leave the last update time as-is
     120        // and use the current timestamp as the basis from which we'll align animations for this
     121        // frame rate.
     122        if (highestCompatibleFrameRate)
     123            data.firstUpdateTime = m_frameRates.get(*highestCompatibleFrameRate).firstUpdateTime;
     124    }
    86125}
    87126
  • trunk/Source/WebCore/animation/FrameRateAligner.h

    r290013 r290121  
    4040
    4141    void beginUpdate(ReducedResolutionSeconds, std::optional<FramesPerSecond>);
     42    void finishUpdate();
    4243
    4344    enum class ShouldUpdate { Yes, No };
     
    5152        ReducedResolutionSeconds firstUpdateTime;
    5253        ReducedResolutionSeconds lastUpdateTime;
     54        bool isNew { true };
    5355    };
    5456
Note: See TracChangeset for help on using the changeset viewer.