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

Commit 0fc7af50 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SF: Commit created layers without using transactions

This solves a couple of issues:
1. This will remove the need to maintain a transaction
queue and a pending transaction queue. If we remove
one of the queues, we have to maintain transactions
by apply tokens and layer creation transactions will
create an order dependency between apply tokens.

2. For transaction tracing, layer creations are
tracked at the layer creation binder call. Tracking
internal layer creation transactions as well will
create an invalid state since the transaction is
a side effect not a client request.

Test: presubmit
Bug: 200284593
Change-Id: Ibfdf403dd0129801fcfb4c64229616d48f84fe9b
parent b8f2a2d5
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ struct layer_state_t {
        eLayerStackChanged = 0x00000080,
        /* unused 0x00000400, */
        eShadowRadiusChanged = 0x00000800,
        eLayerCreated = 0x00001000,
        /* unused 0x00001000, */
        eBufferCropChanged = 0x00002000,
        eRelativeLayerChanged = 0x00004000,
        eReparent = 0x00008000,
+40 −72
Original line number Diff line number Diff line
@@ -2136,7 +2136,8 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected

        bool needsTraversal = false;
        if (clearTransactionFlags(eTransactionFlushNeeded)) {
            needsTraversal = flushTransactionQueues(vsyncId);
            needsTraversal |= commitCreatedLayers();
            needsTraversal |= flushTransactionQueues(vsyncId);
        }

        const bool shouldCommit =
@@ -3602,7 +3603,7 @@ bool SurfaceFlinger::latchBuffers() {
}

status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
                                        const sp<Layer>& lbc, const wp<Layer>& parent,
                                        const sp<Layer>& layer, const wp<Layer>& parent,
                                        bool addToRoot, uint32_t* outTransformHint) {
    if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
        ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
@@ -3610,31 +3611,22 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBind
        return NO_MEMORY;
    }

    setLayerCreatedState(handle, lbc, parent, addToRoot);

    // Create a transaction includes the initial parent and producer.
    Vector<ComposerState> states;
    Vector<DisplayState> displays;

    ComposerState composerState;
    composerState.state.what = layer_state_t::eLayerCreated;
    composerState.state.surface = handle;
    states.add(composerState);
    {
        std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
        mCreatedLayers.emplace_back(layer, parent, addToRoot);
    }

    lbc->updateTransformHint(mActiveDisplayTransformHint);
    layer->updateTransformHint(mActiveDisplayTransformHint);
    if (outTransformHint) {
        *outTransformHint = mActiveDisplayTransformHint;
    }
    // attach this layer to the client
    if (client != nullptr) {
        client->attachLayer(handle, lbc);
        client->attachLayer(handle, layer);
    }

    int64_t transactionId = (((int64_t)mPid) << 32) | mUniqueTransactionId++;
    return setTransactionState(FrameTimelineInfo{}, states, displays, 0 /* flags */, nullptr,
                               InputWindowCommands{}, -1 /* desiredPresentTime */,
                               true /* isAutoTimestamp */, {}, false /* hasListenerCallbacks */, {},
                               transactionId);
    setTransactionFlags(eTransactionNeeded);
    return NO_ERROR;
}

uint32_t SurfaceFlinger::getTransactionFlags() const {
@@ -4219,15 +4211,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime
    uint32_t flags = 0;
    sp<Layer> layer = nullptr;
    if (s.surface) {
        if (what & layer_state_t::eLayerCreated) {
            layer = handleLayerCreatedLocked(s.surface);
            if (layer) {
                flags |= eTransactionNeeded | eTraversalNeeded;
                mLayersAdded = true;
            }
        } else {
        layer = fromHandle(s.surface).promote();
        }
    } else {
        // The client may provide us a null handle. Treat it as if the layer was removed.
        ALOGW("Attempt to set client state with a null layer handle");
@@ -4638,7 +4622,6 @@ status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp<IBinder>* outHa
        return result;
    }

    setTransactionFlags(eTransactionNeeded);
    *outLayerId = layer->sequence;
    return result;
}
@@ -7075,53 +7058,19 @@ void TransactionState::traverseStatesWithBuffers(
    }
}

void SurfaceFlinger::setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
                                          const wp<Layer> parent, bool addToRoot) {
    Mutex::Autolock lock(mCreatedLayersLock);
    mCreatedLayers[handle->localBinder()] =
            std::make_unique<LayerCreatedState>(layer, parent, addToRoot);
}

auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) {
    Mutex::Autolock lock(mCreatedLayersLock);
    BBinder* b = nullptr;
    if (handle) {
        b = handle->localBinder();
    }

    if (b == nullptr) {
        return std::unique_ptr<LayerCreatedState>(nullptr);
    }

    auto it = mCreatedLayers.find(b);
    if (it == mCreatedLayers.end()) {
        ALOGE("Can't find layer from handle %p", handle.get());
        return std::unique_ptr<LayerCreatedState>(nullptr);
    }

    auto state = std::move(it->second);
    mCreatedLayers.erase(it);
    return state;
}

sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle) {
    const auto& state = getLayerCreatedState(handle);
    if (!state) {
        return nullptr;
    }

    sp<Layer> layer = state->layer.promote();
void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state) {
    sp<Layer> layer = state.layer.promote();
    if (!layer) {
        ALOGE("Invalid layer %p", state->layer.unsafe_get());
        return nullptr;
        ALOGD("Layer was destroyed soon after creation %p", state.layer.unsafe_get());
        return;
    }

    sp<Layer> parent;
    bool addToRoot = state->addToRoot;
    if (state->initialParent != nullptr) {
        parent = state->initialParent.promote();
    bool addToRoot = state.addToRoot;
    if (state.initialParent != nullptr) {
        parent = state.initialParent.promote();
        if (parent == nullptr) {
            ALOGE("Invalid parent %p", state->initialParent.unsafe_get());
            ALOGD("Parent was destroyed soon after creation %p", state.initialParent.unsafe_get());
            addToRoot = false;
        }
    }
@@ -7141,7 +7090,6 @@ sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle) {
    layer->updateTransformHint(mActiveDisplayTransformHint);

    mInterceptor->saveSurfaceCreation(layer);
    return layer;
}

void SurfaceFlinger::sample() {
@@ -7223,6 +7171,26 @@ std::shared_ptr<renderengine::ExternalTexture> SurfaceFlinger::getExternalTextur
             layerName);
    return buffer;
}

bool SurfaceFlinger::commitCreatedLayers() {
    std::vector<LayerCreatedState> createdLayers;
    {
        std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
        createdLayers = std::move(mCreatedLayers);
        mCreatedLayers.clear();
        if (createdLayers.size() == 0) {
            return false;
        }
    }

    Mutex::Autolock _l(mStateLock);
    for (const auto& createdLayer : createdLayers) {
        handleLayerCreatedLocked(createdLayer);
    }
    createdLayers.clear();
    mLayersAdded = true;
    return true;
}
} // namespace android

#if defined(__gl_h_)
+4 −6
Original line number Diff line number Diff line
@@ -1325,7 +1325,7 @@ private:

    std::unordered_map<DisplayId, sp<HdrLayerInfoReporter>> mHdrLayerInfoListeners
            GUARDED_BY(mStateLock);
    mutable Mutex mCreatedLayersLock;
    mutable std::mutex mCreatedLayersLock;
    struct LayerCreatedState {
        LayerCreatedState(const wp<Layer>& layer, const wp<Layer> parent, bool addToRoot)
              : layer(layer), initialParent(parent), addToRoot(addToRoot) {}
@@ -1341,11 +1341,9 @@ private:

    // A temporay pool that store the created layers and will be added to current state in main
    // thread.
    std::unordered_map<BBinder*, std::unique_ptr<LayerCreatedState>> mCreatedLayers;
    void setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer,
                              const wp<Layer> parent, bool addToRoot);
    auto getLayerCreatedState(const sp<IBinder>& handle);
    sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle) REQUIRES(mStateLock);
    std::vector<LayerCreatedState> mCreatedLayers GUARDED_BY(mCreatedLayersLock);
    bool commitCreatedLayers();
    void handleLayerCreatedLocked(const LayerCreatedState& state) REQUIRES(mStateLock);

    std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;

+0 −1
Original line number Diff line number Diff line
@@ -89,7 +89,6 @@ message LayerState {
        eReleaseBufferListenerChanged = 0x00000400;
        eShadowRadiusChanged = 0x00000800;

        eLayerCreated = 0x00001000;
        eBufferCropChanged = 0x00002000;
        eRelativeLayerChanged = 0x00004000;
        eReparent = 0x00008000;