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

Commit 70280e7e authored by Alec Mouri's avatar Alec Mouri Committed by Automerger Merge Worker
Browse files

Merge "Resolve subtle but severe flickering in layer caching" into sc-dev am: 3cca8559

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14441371

Change-Id: I26f8341f0c25f99b7408dc411121d8d0808869d7
parents a912ad7c 3cca8559
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -78,9 +78,10 @@ private:
    void writeSidebandStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
    void writeBufferStateToHWC(HWC2::Layer*, const LayerFECompositionState&);
    void writeCompositionTypeToHWC(HWC2::Layer*, Hwc2::IComposerClient::Composition,
                                   bool isPeekingThrough);
                                   bool isPeekingThrough, bool skipLayer);
    void detectDisallowedCompositionTypeChange(Hwc2::IComposerClient::Composition from,
                                               Hwc2::IComposerClient::Composition to) const;
    bool isClientCompositionForced(bool isPeekingThrough) const;
};

// This template factory function standardizes the implementation details of the
+3 −0
Original line number Diff line number Diff line
@@ -125,6 +125,9 @@ struct OutputLayerCompositionState {

        // Set to true when overridden info has been sent to HW composer
        bool stateOverridden = false;

        // True when this layer was skipped as part of SF-side layer caching.
        bool layerSkipped = false;
    };

    // The HWC state is optional, and is only set up if there is any potential
+24 −8
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

#include <DisplayHardware/Hal.h>
#include <android-base/stringprintf.h>
#include <compositionengine/DisplayColorProfile.h>
#include <compositionengine/LayerFECompositionState.h>
@@ -350,12 +351,14 @@ void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t
    writeOutputDependentPerFrameStateToHWC(hwcLayer.get());
    writeOutputIndependentPerFrameStateToHWC(hwcLayer.get(), *outputIndependentState);

    writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough);
    writeCompositionTypeToHWC(hwcLayer.get(), requestedCompositionType, isPeekingThrough,
                              skipLayer);

    // Always set the layer color after setting the composition type.
    writeSolidColorStateToHWC(hwcLayer.get(), *outputIndependentState);

    editState().hwc->stateOverridden = isOverridden;
    editState().hwc->layerSkipped = skipLayer;
}

void OutputLayer::writeOutputDependentGeometryStateToHWC(HWC2::Layer* hwcLayer,
@@ -482,7 +485,8 @@ void OutputLayer::writeOutputIndependentPerFrameStateToHWC(

    const Region& surfaceDamage = getState().overrideInfo.buffer
            ? getState().overrideInfo.damageRegion
            : outputIndependentState.surfaceDamage;
            : (getState().hwc->stateOverridden ? Region::INVALID_REGION
                                               : outputIndependentState.surfaceDamage);

    if (auto error = hwcLayer->setSurfaceDamage(surfaceDamage); error != hal::Error::NONE) {
        ALOGE("[%s] Failed to set surface damage: %s (%d)", getLayerFE().getDebugName(),
@@ -573,17 +577,19 @@ void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer,

void OutputLayer::writeCompositionTypeToHWC(HWC2::Layer* hwcLayer,
                                            hal::Composition requestedCompositionType,
                                            bool isPeekingThrough) {
                                            bool isPeekingThrough, bool skipLayer) {
    auto& outputDependentState = editState();

    if (isClientCompositionForced(isPeekingThrough)) {
        // If we are forcing client composition, we need to tell the HWC
    if (outputDependentState.forceClientComposition ||
        (!isPeekingThrough && getLayerFE().hasRoundedCorners())) {
        requestedCompositionType = hal::Composition::CLIENT;
    }

    // Set the requested composition type with the HWC whenever it changes
    if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType) {
    // We also resend the composition type when this layer was previously skipped, to ensure that
    // the composition type is up-to-date.
    if (outputDependentState.hwc->hwcCompositionType != requestedCompositionType ||
        (outputDependentState.hwc->layerSkipped && !skipLayer)) {
        outputDependentState.hwc->hwcCompositionType = requestedCompositionType;

        if (auto error = hwcLayer->setCompositionType(requestedCompositionType);
@@ -663,12 +669,22 @@ void OutputLayer::detectDisallowedCompositionTypeChange(hal::Composition from,
    }
}

bool OutputLayer::isClientCompositionForced(bool isPeekingThrough) const {
    return getState().forceClientComposition ||
            (!isPeekingThrough && getLayerFE().hasRoundedCorners());
}

void OutputLayer::applyDeviceCompositionTypeChange(hal::Composition compositionType) {
    auto& state = editState();
    LOG_FATAL_IF(!state.hwc);
    auto& hwcState = *state.hwc;

    // Only detected disallowed changes if this was not a skip layer, because the
    // validated composition type may be arbitrary (usually DEVICE, to reflect that there were
    // fewer GPU layers)
    if (!hwcState.layerSkipped) {
        detectDisallowedCompositionTypeChange(hwcState.hwcCompositionType, compositionType);
    }

    hwcState.hwcCompositionType = compositionType;
}
+50 −0
Original line number Diff line number Diff line
@@ -1065,12 +1065,62 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) {
                              kOverrideSurfaceDamage);
    expectSetHdrMetadataAndBufferCalls(kOverrideHwcSlot, kOverrideBuffer, kOverrideFence);
    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));

    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}

TEST_F(OutputLayerWriteStateToHWCTest, previousOverriddenLayerSendsSurfaceDamage) {
    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
    mOutputLayer.editState().hwc->stateOverridden = true;

    expectGeometryCommonCalls();
    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                              Region::INVALID_REGION);
    expectSetHdrMetadataAndBufferCalls();
    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));

    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}

TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedDeviceCompositionInfo) {
    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
    mOutputLayer.editState().hwc->stateOverridden = true;
    mOutputLayer.editState().hwc->layerSkipped = true;
    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::DEVICE;

    expectGeometryCommonCalls();
    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                              Region::INVALID_REGION);
    expectSetHdrMetadataAndBufferCalls();
    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE);
    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillOnce(Return(false));

    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}

TEST_F(OutputLayerWriteStateToHWCTest, previousSkipLayerSendsUpdatedClientCompositionInfo) {
    mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE;
    mOutputLayer.editState().forceClientComposition = true;
    mOutputLayer.editState().hwc->stateOverridden = true;
    mOutputLayer.editState().hwc->layerSkipped = true;
    mOutputLayer.editState().hwc->hwcCompositionType = Hwc2::IComposerClient::Composition::CLIENT;

    expectGeometryCommonCalls();
    expectPerFrameCommonCalls(SimulateUnsupported::None, kDataspace, kOutputSpaceVisibleRegion,
                              Region::INVALID_REGION);
    expectSetHdrMetadataAndBufferCalls();
    expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::CLIENT);
    EXPECT_CALL(*mLayerFE, hasRoundedCorners()).WillRepeatedly(Return(false));

    mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0,
                                 /*zIsOverridden*/ false, /*isPeekingThrough*/ false);
}

TEST_F(OutputLayerWriteStateToHWCTest, peekThroughChangesBlendMode) {
    auto peekThroughLayerFE = sp<compositionengine::mock::LayerFE>::make();
    OutputLayer peekThroughLayer{mOutput, peekThroughLayerFE};