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

Commit 44af8ccd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "systrace: monitor GPU completion fence and HWC release fence"

parents 6fc38dc1 9e919eb8
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -20,6 +20,11 @@

#include <gui/Surface.h>

#include <condition_variable>
#include <deque>
#include <mutex>
#include <thread>

#include <inttypes.h>

#include <android/native_window.h>
@@ -450,6 +455,74 @@ int Surface::setSwapInterval(int interval) {
    return NO_ERROR;
}

class FenceMonitor {
public:
    explicit FenceMonitor(const char* name) : mName(name), mFencesQueued(0), mFencesSignaled(0) {
        std::thread thread(&FenceMonitor::loop, this);
        pthread_setname_np(thread.native_handle(), mName);
        thread.detach();
    }

    void queueFence(const sp<Fence>& fence) {
        char message[64];

        std::lock_guard<std::mutex> lock(mMutex);
        snprintf(message, sizeof(message), "Trace fence %u", mFencesQueued);
        ATRACE_NAME(message);

        mQueue.push_back(fence);
        mCondition.notify_one();
        mFencesQueued++;
        ATRACE_INT(mName, int32_t(mQueue.size()));
    }

private:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmissing-noreturn"
    void loop() {
        while (true) {
            threadLoop();
        }
    }
#pragma clang diagnostic pop

    void threadLoop() {
        sp<Fence> fence;
        uint32_t fenceNum;
        {
            std::unique_lock<std::mutex> lock(mMutex);
            while (mQueue.empty()) {
                mCondition.wait(lock);
            }
            fence = mQueue[0];
            fenceNum = mFencesSignaled;
        }
        {
            char message[64];
            snprintf(message, sizeof(message), "waiting for %s %u", mName, fenceNum);
            ATRACE_NAME(message);

            status_t result = fence->waitForever(message);
            if (result != OK) {
                ALOGE("Error waiting for fence: %d", result);
            }
        }
        {
            std::lock_guard<std::mutex> lock(mMutex);
            mQueue.pop_front();
            mFencesSignaled++;
            ATRACE_INT(mName, int32_t(mQueue.size()));
        }
    }

    const char* mName;
    uint32_t mFencesQueued;
    uint32_t mFencesSignaled;
    std::deque<sp<Fence>> mQueue;
    std::condition_variable mCondition;
    std::mutex mMutex;
};

int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    ATRACE_CALL();
    ALOGV("Surface::dequeueBuffer");
@@ -519,6 +592,11 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    // this should never happen
    ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);

    if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
        static FenceMonitor hwcReleaseThread("HWC release");
        hwcReleaseThread.queueFence(fence);
    }

    if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
        freeAllBuffers();
    }
@@ -761,6 +839,11 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {

    mQueueBufferCondition.broadcast();

    if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
        static FenceMonitor gpuCompletionThread("GPU completion");
        gpuCompletionThread.queueFence(fence);
    }

    return err;
}