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

Commit 6a0382d6 authored by Robert Carr's avatar Robert Carr
Browse files

Optimize mirror layer management

We currently have to traverse the whole hierarchy twice to
update mirror layer info. While a long term rearchitecture may avoid
this entirely, we can optimize the hotpath by avoiding both traversals
when there are no mirror layers in existence.

Bug: 186200583
Test: Existing tests pass
Change-Id: I63f1fb239aa51e6db4fb1f4cb3cd3a87113d35d9
parent 06c3b638
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -177,6 +177,9 @@ Layer::~Layer() {
    if (mDrawingState.sidebandStream != nullptr) {
        mFlinger->mTunnelModeEnabledReporter->decrementTunnelModeCount();
    }
    if (mHadClonedChild) {
        mFlinger->mNumClones--;
    }
}

LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
@@ -2535,6 +2538,12 @@ bool Layer::getPrimaryDisplayOnly() const {
    return parent == nullptr ? false : parent->getPrimaryDisplayOnly();
}

void Layer::setClonedChild(const sp<Layer>& clonedChild) {
    mClonedChild = clonedChild;
    mHadClonedChild = true;
    mFlinger->mNumClones++;
}

// ---------------------------------------------------------------------------

std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
+2 −0
Original line number Diff line number Diff line
@@ -863,6 +863,8 @@ public:
    // The layers in the cloned hierarchy will match the lifetime of the real layers. That is
    // if the real layer is destroyed, then the clone layer will also be destroyed.
    sp<Layer> mClonedChild;
    bool mHadClonedChild = false;
    void setClonedChild(const sp<Layer>& mClonedChild);

    mutable bool contentDirty{false};
    Region surfaceDamageRegion;
+7 −3
Original line number Diff line number Diff line
@@ -3266,8 +3266,10 @@ void SurfaceFlinger::commitTransactionLocked() {
    }

    commitOffscreenLayers();
    if (mNumClones > 0) {
        mDrawingState.traverse([&](Layer* layer) { layer->updateMirrorInfo(); });
    }
}

void SurfaceFlinger::commitOffscreenLayers() {
    for (Layer* offscreenLayer : mOffscreenLayers) {
@@ -3372,7 +3374,9 @@ bool SurfaceFlinger::handlePageFlip() {
        mBootStage = BootStage::BOOTANIMATION;
    }

    if (mNumClones > 0) {
        mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); });
    }

    // Only continue with the refresh if there is actually new work to do
    return !mLayersWithQueuedFrames.empty() && newDataLatched;
@@ -4257,7 +4261,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>
            return result;
        }

        mirrorLayer->mClonedChild = mirrorFrom->createClone();
        mirrorLayer->setClonedChild(mirrorFrom->createClone());
    }

    *outLayerId = mirrorLayer->sequence;
+3 −0
Original line number Diff line number Diff line
@@ -315,6 +315,9 @@ public:

    void removeFromOffscreenLayers(Layer* layer);

    // TODO: Remove atomic if move dtor to main thread CL lands
    std::atomic<uint32_t> mNumClones;

    TransactionCallbackInvoker& getTransactionCallbackInvoker() {
        return mTransactionCallbackInvoker;
    }