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

Commit fa9b2af4 authored by David Sodman's avatar David Sodman
Browse files

SF: Make message refresh loop over displays

Update message refresh handling to loop over the displays
at the top level and have each sub-function operate on the
passed in display.  This will facilitate later updates that
allow for an SFBE per display.

Bug: 112259502
Test: cts -m CtsViewTestCases
      SurfaceFlinger_test
      vrflinger_test

Change-Id: I0284540563e532aa33a635c1642212eeb3f78bf4
parent b7c5f345
Loading
Loading
Loading
Loading
+90 −104
Original line number Diff line number Diff line
@@ -259,8 +259,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag)
        mDebugDDMS(0),
        mDebugDisableHWC(0),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mForceFullDamage(false),
@@ -1444,25 +1442,26 @@ bool SurfaceFlinger::handleMessageTransaction() {
    return false;
}

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    return handlePageFlip();
}

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();

    mRefreshPending = false;

    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    preComposition();
    rebuildLayerStacks();
    calculateWorkingSet();
    beginFrame();
    prepareFrame();
    doDebugFlashRegions();
    for (const auto& [token, display] : mDisplays) {
        beginFrame(display);
        prepareFrame(display);
        doDebugFlashRegions(display, repaintEverything);
        doComposition(display, repaintEverything);
    }

    doTracing("handleRefresh");
    logLayerStats();
    doComposition();

    postFrame();
    postComposition();

    mHadClientComposition = false;
@@ -1470,11 +1469,18 @@ void SurfaceFlinger::handleMessageRefresh() {
        mHadClientComposition = mHadClientComposition ||
                getBE().mHwc->hasClientComposition(display->getId());
    }

    mVsyncModulator.onRefreshed(mHadClientComposition);

    mLayersWithQueuedFrames.clear();
}


bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    return handlePageFlip();
}

void SurfaceFlinger::calculateWorkingSet() {
    ATRACE_CALL();
    ALOGV(__FUNCTION__);
@@ -1553,17 +1559,15 @@ void SurfaceFlinger::calculateWorkingSet() {
    mDrawingState.colorMatrixChanged = false;
}

void SurfaceFlinger::doDebugFlashRegions()
void SurfaceFlinger::doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything)
{
    // is debugging enabled
    if (CC_LIKELY(!mDebugRegion))
        return;

    const bool repaintEverything = mRepaintEverything;
    for (const auto& [token, display] : mDisplays) {
    if (display->isPoweredOn()) {
        // transform the dirty region into this screen's coordinate space
            const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
        const Region dirtyRegion(display->getDirtyRegion(repaintEverything));
        if (!dirtyRegion.isEmpty()) {
            // redraw the whole screen
            doComposeSurfaces(display);
@@ -1576,21 +1580,18 @@ void SurfaceFlinger::doDebugFlashRegions()
            display->swapBuffers(getHwComposer());
        }
    }
    }

    postFramebuffer();
    postFramebuffer(display);

    if (mDebugRegion > 1) {
        usleep(mDebugRegion * 1000);
    }

    for (const auto& [token, display] : mDisplays) {
        if (!display->isPoweredOn()) {
            continue;
        }

    if (display->isPoweredOn()) {
        status_t result = display->prepareFrame(*getBE().mHwc);
        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
        ALOGE_IF(result != NO_ERROR,
                 "prepareFrame for display %d failed:"
                 " %d (%s)",
                 display->getId(), result, strerror(-result));
    }
}
@@ -1954,10 +1955,9 @@ void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode*
    display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
}

void SurfaceFlinger::beginFrame()
void SurfaceFlinger::beginFrame(const sp<DisplayDevice>& display)
{
    for (const auto& [token, display] : mDisplays) {
        bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
    bool dirty = !display->getDirtyRegion(false).isEmpty();
    bool empty = display->getVisibleLayersSortedByZ().size() == 0;
    bool wasEmpty = !display->lastCompositionHadVisibleLayers;

@@ -1971,9 +1971,12 @@ void SurfaceFlinger::beginFrame()
    //   emit any black frames until a layer is added to the layer stack.
    bool mustRecompose = dirty && !(empty && wasEmpty);

        ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
                 display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
                 empty ? "+" : "-", wasEmpty ? "+" : "-");
    ALOGV_IF(displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
            "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
            mustRecompose ? "doing" : "skipping",
            dirty ? "+" : "-",
            empty ? "+" : "-",
            wasEmpty ? "+" : "-");

    display->beginFrame(mustRecompose);

@@ -1981,30 +1984,27 @@ void SurfaceFlinger::beginFrame()
        display->lastCompositionHadVisibleLayers = !empty;
    }
}
}

void SurfaceFlinger::prepareFrame()
void SurfaceFlinger::prepareFrame(const sp<DisplayDevice>& display)
{
    for (const auto& [token, display] : mDisplays) {
    if (!display->isPoweredOn()) {
            continue;
        return;
    }

    status_t result = display->prepareFrame(*getBE().mHwc);
        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
    ALOGE_IF(result != NO_ERROR,
             "prepareFrame for display %d failed:"
             " %d (%s)",
             display->getId(), result, strerror(-result));
}
}

void SurfaceFlinger::doComposition() {
void SurfaceFlinger::doComposition(const sp<DisplayDevice>& display, bool repaintEverything) {
    ATRACE_CALL();
    ALOGV("doComposition");

    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
    for (const auto& [token, display] : mDisplays) {
    if (display->isPoweredOn()) {
        // transform the dirty region into this screen's coordinate space
            const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
        const Region dirtyRegion(display->getDirtyRegion(repaintEverything));

        // repaint the framebuffer (if needed)
        doDisplayComposition(display, dirtyRegion);
@@ -2012,22 +2012,28 @@ void SurfaceFlinger::doComposition() {
        display->dirtyRegion.clear();
        display->flip();
    }
    postFramebuffer(display);
}

void SurfaceFlinger::postFrame()
{
    // |mStateLock| not needed as we are on the main thread
    if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
        uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
            logFrameStats();
        }
    }
    postFramebuffer();
}

void SurfaceFlinger::postFramebuffer()
void SurfaceFlinger::postFramebuffer(const sp<DisplayDevice>& display)
{
    ATRACE_CALL();
    ALOGV("postFramebuffer");

    const nsecs_t now = systemTime();
    mDebugInSwapBuffers = now;
    mPostFramebufferTime = systemTime();

    for (const auto& [token, display] : mDisplays) {
        if (!display->isPoweredOn()) {
            continue;
        }
    if (display->isPoweredOn()) {
        const auto displayId = display->getId();
        if (displayId >= 0) {
            getBE().mHwc->presentAndGetReleaseFences(displayId);
@@ -2072,18 +2078,6 @@ void SurfaceFlinger::postFramebuffer()
            getBE().mHwc->clearReleaseFences(displayId);
        }
    }

    mLastSwapBufferTime = systemTime() - now;
    mDebugInSwapBuffers = 0;

    // |mStateLock| not needed as we are on the main thread
    const auto display = getDefaultDisplayDeviceLocked();
    if (display && getHwComposer().isConnected(display->getId())) {
        const uint32_t flipCount = display->getPageFlipCount();
        if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
            logFrameStats();
        }
    }
}

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
@@ -4210,9 +4204,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,

    // figure out if we're stuck somewhere
    const nsecs_t now = systemTime();
    const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
    const nsecs_t inTransaction(mDebugInTransaction);
    nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
    nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;

    /*
@@ -4320,11 +4312,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
        result.appendFormat("  orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
                            display->isPoweredOn());
    }
    result.appendFormat("  last eglSwapBuffers() time: %f us\n"
                        "  last transaction time     : %f us\n"
                        "  transaction-flags         : %08x\n"
    result.appendFormat("  transaction-flags         : %08x\n"
                        "  gpu_to_cpu_unsupported    : %d\n",
                        mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0,
                        mTransactionFlags, !mGpuToCpuSupported);

    if (display) {
@@ -4336,9 +4325,6 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
                            activeConfig->getDpiY());
    }

    result.appendFormat("  eglSwapBuffers time: %f us\n",
            inSwapBuffersDuration/1000.0);

    result.appendFormat("  transaction time: %f us\n",
            inTransactionDuration/1000.0);

+7 −6
Original line number Diff line number Diff line
@@ -673,14 +673,14 @@ private:
     * prior to any CompositionInfo handling and is not dependent on data in
     * CompositionInfo
     */
    void beginFrame();
    void beginFrame(const sp<DisplayDevice>& display);
    /* prepareFrame - This function will call into the DisplayDevice to prepare a
     * frame after CompositionInfo has been programmed.   This provides a mechanism
     * to prepare the hardware composer
     */
    void prepareFrame();
    void doComposition();
    void doDebugFlashRegions();
    void prepareFrame(const sp<DisplayDevice>& display);
    void doComposition(const sp<DisplayDevice>& display, bool repainEverything);
    void doDebugFlashRegions(const sp<DisplayDevice>& display, bool repaintEverything);
    void doTracing(const char* where);
    void logLayerStats();
    void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
@@ -688,7 +688,8 @@ private:
    // This fails if using GL and the surface has been destroyed.
    bool doComposeSurfaces(const sp<const DisplayDevice>& display);

    void postFramebuffer();
    void postFramebuffer(const sp<DisplayDevice>& display);
    void postFrame();
    void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const;

    /* ------------------------------------------------------------------------
@@ -844,9 +845,9 @@ private:
    int mDebugDisableHWC;
    int mDebugDisableTransformHint;
    volatile nsecs_t mDebugInSwapBuffers;
    nsecs_t mLastSwapBufferTime;
    volatile nsecs_t mDebugInTransaction;
    nsecs_t mLastTransactionTime;
    nsecs_t mPostFramebufferTime;
    bool mForceFullDamage;
    bool mPropagateBackpressure = true;
    std::unique_ptr<SurfaceInterceptor> mInterceptor =