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

Commit 5a5e01eb authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Pull CompositorTiming constructor to libgui

Clean up the snapping logic and add tests.

Bug: 185535769
Test: libgui_test
Change-Id: I08302d7c08a0932787e66203873b6aa6ff9f7a78
parent 4376bd84
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ cc_library_shared {
        "BufferHubConsumer.cpp",
        "BufferHubProducer.cpp",
        "BufferItemConsumer.cpp",
        "CompositorTiming.cpp",
        "ConsumerBase.cpp",
        "CpuConsumer.cpp",
        "DebugEGLImageTracker.cpp",
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "CompositorTiming"

#include <cutils/compiler.h>
#include <gui/CompositorTiming.h>
#include <log/log.h>

namespace android::gui {

CompositorTiming::CompositorTiming(nsecs_t vsyncDeadline, nsecs_t vsyncPeriod, nsecs_t vsyncPhase,
                                   nsecs_t presentLatency) {
    if (CC_UNLIKELY(vsyncPeriod <= 0)) {
        ALOGE("Invalid VSYNC period");
        return;
    }

    const nsecs_t idealLatency = [=] {
        // Modulo rounds toward 0 not INT64_MIN, so treat signs separately.
        if (vsyncPhase < 0) return -vsyncPhase % vsyncPeriod;

        const nsecs_t latency = (vsyncPeriod - vsyncPhase) % vsyncPeriod;
        return latency > 0 ? latency : vsyncPeriod;
    }();

    // Snap the latency to a value that removes scheduling jitter from the composite and present
    // times, which often have >1ms of jitter. Reducing jitter is important if an app attempts to
    // extrapolate something like user input to an accurate present time. Snapping also allows an
    // app to precisely calculate vsyncPhase with (presentLatency % interval).
    const nsecs_t bias = vsyncPeriod / 2;
    const nsecs_t extraVsyncs = (presentLatency - idealLatency + bias) / vsyncPeriod;
    const nsecs_t snappedLatency =
            extraVsyncs > 0 ? idealLatency + extraVsyncs * vsyncPeriod : idealLatency;

    this->deadline = vsyncDeadline - idealLatency;
    this->interval = vsyncPeriod;
    this->presentLatency = snappedLatency;
}

} // namespace android::gui
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <utils/Timers.h>

namespace android::gui {

// Expected timing of the next composited frame, based on the timing of the latest frames.
struct CompositorTiming {
    static constexpr nsecs_t kDefaultVsyncPeriod = 16'666'667;

    CompositorTiming() = default;
    CompositorTiming(nsecs_t vsyncDeadline, nsecs_t vsyncPeriod, nsecs_t vsyncPhase,
                     nsecs_t presentLatency);

    // Time point when compositing is expected to start.
    nsecs_t deadline = 0;

    // Duration between consecutive frames. In other words, the VSYNC period.
    nsecs_t interval = kDefaultVsyncPeriod;

    // Duration between composite start and present. For missed frames, the extra latency is rounded
    // to a multiple of the VSYNC period, such that the remainder (presentLatency % interval) always
    // evaluates to the VSYNC phase offset.
    nsecs_t presentLatency = kDefaultVsyncPeriod;
};

} // namespace android::gui
+2 −6
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <android/gui/FrameEvent.h>

#include <gui/CompositorTiming.h>
#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
@@ -33,6 +34,7 @@ namespace android {
struct FrameEvents;
class FrameEventHistoryDelta;

using gui::CompositorTiming;
using gui::FrameEvent;

// A collection of timestamps corresponding to a single frame.
@@ -83,12 +85,6 @@ struct FrameEvents {
    std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
};

struct CompositorTiming {
    nsecs_t deadline{0};
    nsecs_t interval{16666667};
    nsecs_t presentLatency{16666667};
};

// A short history of frames that are synchronized between the consumer and
// producer via deltas.
class FrameEventHistory {
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ cc_test {
        "BLASTBufferQueue_test.cpp",
        "BufferItemConsumer_test.cpp",
        "BufferQueue_test.cpp",
        "CompositorTiming_test.cpp",
        "CpuConsumer_test.cpp",
        "EndToEndNativeInputTest.cpp",
        "DisplayInfo_test.cpp",
Loading