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

Commit 69f9522d authored by Arthur Hung's avatar Arthur Hung Committed by Yong Zhang
Browse files

Change small area detection to support new front end design

This will still use legacy layer to calculate the small dirty, and
update the info to the LayerSnapshot.

Also fix some issues in setIsSmallDirty() for
1. Set mSmallDirty flag as false if the surface damage region is
   invalid.
2. Apply the scaling to the damage region before dirty area
   calculations.

Bug: 295062543
Bug: 303258910
Bug: 303609027
Test: atest LayerHistoryTest
Test: atest SmallAreaDetectionTest
Change-Id: Ib0e3737e63b5653422b5b5054b893578dc63f768
parent 761221db
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -122,6 +122,8 @@ struct LayerSnapshot : public compositionengine::LayerFECompositionState {
        ReachableByRelativeParent
    };
    Reachablilty reachablilty;
    // True when the surfaceDamage is recognized as a small area update.
    bool isSmallDirty = false;

    static bool isOpaqueFormat(PixelFormat format);
    static bool isTransformValid(const ui::Transform& t);
+14 −3
Original line number Diff line number Diff line
@@ -3369,7 +3369,7 @@ bool Layer::setSurfaceDamageRegion(const Region& surfaceDamage) {
    mDrawingState.surfaceDamageRegion = surfaceDamage;
    mDrawingState.modified = true;
    setTransactionFlags(eTransactionNeeded);
    setIsSmallDirty();
    setIsSmallDirty(surfaceDamage, getTransform());
    return true;
}

@@ -4416,7 +4416,9 @@ void Layer::updateLastLatchTime(nsecs_t latchTime) {
    mLastLatchTime = latchTime;
}

void Layer::setIsSmallDirty() {
void Layer::setIsSmallDirty(const Region& damageRegion,
                            const ui::Transform& layerToDisplayTransform) {
    mSmallDirty = false;
    if (!mFlinger->mScheduler->supportSmallDirtyDetection()) {
        return;
    }
@@ -4425,17 +4427,26 @@ void Layer::setIsSmallDirty() {
        mWindowType != WindowInfo::Type::BASE_APPLICATION) {
        return;
    }
    Rect bounds = mDrawingState.surfaceDamageRegion.getBounds();

    Rect bounds = damageRegion.getBounds();
    if (!bounds.isValid()) {
        return;
    }

    // Transform to screen space.
    bounds = layerToDisplayTransform.transform(bounds);

    // If the damage region is a small dirty, this could give the hint for the layer history that
    // it could suppress the heuristic rate when calculating.
    mSmallDirty = mFlinger->mScheduler->isSmallDirtyArea(mOwnerAppId,
                                                         bounds.getWidth() * bounds.getHeight());
}

void Layer::setIsSmallDirty(frontend::LayerSnapshot* snapshot) {
    setIsSmallDirty(snapshot->surfaceDamage, snapshot->localTransform);
    snapshot->isSmallDirty = mSmallDirty;
}

} // namespace android

#if defined(__gl_h_)
+2 −1
Original line number Diff line number Diff line
@@ -937,7 +937,8 @@ public:
    const sp<SurfaceFlinger> mFlinger;

    // Check if the damage region is a small dirty.
    void setIsSmallDirty();
    void setIsSmallDirty(const Region& damageRegion, const ui::Transform& layerToDisplayTransform);
    void setIsSmallDirty(frontend::LayerSnapshot* snapshot);

protected:
    // For unit tests
+24 −15
Original line number Diff line number Diff line
@@ -2211,8 +2211,29 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) {
            continue;
        }

        if (!snapshot->changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) &&
            (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) == 0) {
        const bool updateSmallDirty = mScheduler->supportSmallDirtyDetection() &&
                ((snapshot->clientChanges & layer_state_t::eSurfaceDamageRegionChanged) ||
                 snapshot->changes.any(Changes::Geometry));

        const bool hasChanges =
                snapshot->changes.any(Changes::FrameRate | Changes::Buffer | Changes::Animation) ||
                (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) !=
                        0;

        if (!updateSmallDirty && !hasChanges) {
            continue;
        }

        auto it = mLegacyLayers.find(snapshot->sequence);
        LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldn't find layer object for %s",
                            snapshot->getDebugString().c_str());

        if (updateSmallDirty) {
            // Update small dirty flag while surface damage region or geometry changed
            it->second->setIsSmallDirty(snapshot.get());
        }

        if (!hasChanges) {
            continue;
        }

@@ -2222,12 +2243,9 @@ void SurfaceFlinger::updateLayerHistory(nsecs_t now) {
                .transform = snapshot->geomLayerTransform,
                .setFrameRateVote = snapshot->frameRate,
                .frameRateSelectionPriority = snapshot->frameRateSelectionPriority,
                .isSmallDirty = snapshot->isSmallDirty,
        };

        auto it = mLegacyLayers.find(snapshot->sequence);
        LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s",
                            snapshot->getDebugString().c_str());

        if (snapshot->clientChanges & layer_state_t::eDefaultFrameRateCompatibilityChanged) {
            mScheduler->setDefaultFrameRateCompatibility(snapshot->sequence,
                                                         snapshot->defaultFrameRateCompatibility);
@@ -8492,15 +8510,6 @@ void SurfaceFlinger::sample() {
void SurfaceFlinger::onActiveDisplaySizeChanged(const DisplayDevice& activeDisplay) {
    mScheduler->onActiveDisplayAreaChanged(activeDisplay.getWidth() * activeDisplay.getHeight());
    getRenderEngine().onActiveDisplaySizeChanged(activeDisplay.getSize());

    // Notify layers to update small dirty flag.
    if (mScheduler->supportSmallDirtyDetection()) {
        mCurrentState.traverse([&](Layer* layer) {
            if (layer->getLayerStack() == activeDisplay.getLayerStack()) {
                layer->setIsSmallDirty();
            }
        });
    }
}

sp<DisplayDevice> SurfaceFlinger::getActivatableDisplay() const {
+24 −0
Original line number Diff line number Diff line
@@ -421,6 +421,17 @@ protected:
        mLifecycleManager.applyTransactions(transactions);
    }

    void setDamageRegion(uint32_t id, const Region& damageRegion) {
        std::vector<TransactionState> transactions;
        transactions.emplace_back();
        transactions.back().states.push_back({});

        transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged;
        transactions.back().states.front().layerId = id;
        transactions.back().states.front().state.surfaceDamageRegion = damageRegion;
        mLifecycleManager.applyTransactions(transactions);
    }

    void setDataspace(uint32_t id, ui::Dataspace dataspace) {
        std::vector<TransactionState> transactions;
        transactions.emplace_back();
@@ -432,6 +443,19 @@ protected:
        mLifecycleManager.applyTransactions(transactions);
    }

    void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) {
        layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy};

        std::vector<TransactionState> transactions;
        transactions.emplace_back();
        transactions.back().states.push_back({});

        transactions.back().states.front().state.what = layer_state_t::eMatrixChanged;
        transactions.back().states.front().layerId = id;
        transactions.back().states.front().state.matrix = matrix;
        mLifecycleManager.applyTransactions(transactions);
    }

    void setShadowRadius(uint32_t id, float shadowRadius) {
        std::vector<TransactionState> transactions;
        transactions.emplace_back();
Loading