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

Commit 4bea01e7 authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Improve performance for certain queries/functions in REThreaded.

Some queries into RE were already thread safe, but now they are
documented as such and avoid jumping to another thread.

Additionally all void method in REThreaded are executed in an async
strategy.

Test: librenderengine_test
Bug: 184243497
Change-Id: Id04bcccf2c90acc3e6cb6f7716f9629639b757b7
parent 220e9018
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ public:
    // do any work.
    virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;

    // queries
    // queries that are required to be thread safe
    virtual size_t getMaxTextureSize() const = 0;
    virtual size_t getMaxViewportDims() const = 0;

@@ -149,8 +149,11 @@ public:

    // ----- BEGIN NEW INTERFACE -----

    // queries that are required to be thread safe
    virtual bool isProtected() const = 0;
    virtual bool supportsProtectedContent() const = 0;

    // Attempt to switch RenderEngine into and out of protectedContext mode
    virtual bool useProtectedContext(bool useProtectedContext) = 0;

    // Notify RenderEngine of changes to the dimensions of the primary display
@@ -197,7 +200,8 @@ public:
    virtual int getContextPriority() = 0;

    // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
    // also supports background blur.  If false, no blur will be applied when drawing layers.
    // also supports background blur.  If false, no blur will be applied when drawing layers. This
    // query is required to be thread safe.
    virtual bool supportsBackgroundBlur() = 0;

    // Returns the current type of RenderEngine instance that was created.
+3 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ TEST_F(RenderEngineThreadedTest, dump) {
TEST_F(RenderEngineThreadedTest, primeCache) {
    EXPECT_CALL(*mRenderEngine, primeCache());
    mThreadedRE->primeCache();
    // need to call ANY synchronous function after primeCache to ensure that primeCache has
    // completed asynchronously before the test completes execution.
    mThreadedRE->getContextPriority();
}

TEST_F(RenderEngineThreadedTest, genTextures) {
+33 −75
Original line number Diff line number Diff line
@@ -74,6 +74,12 @@ void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_S
    std::unique_lock<std::mutex> lock(mThreadMutex);
    pthread_setname_np(pthread_self(), mThreadName);

    {
        std::unique_lock<std::mutex> lock(mInitializedMutex);
        mIsInitialized = true;
    }
    mInitializedCondition.notify_all();

    while (mRunning) {
        if (!mFunctionCalls.empty()) {
            auto task = mFunctionCalls.front();
@@ -86,19 +92,22 @@ void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_S
    }
}

void RenderEngineThreaded::waitUntilInitialized() const {
    std::unique_lock<std::mutex> lock(mInitializedMutex);
    mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
}

void RenderEngineThreaded::primeCache() {
    std::promise<void> resultPromise;
    std::future<void> resultFuture = resultPromise.get_future();
    // This function is designed so it can run asynchronously, so we do not need to wait
    // for the futures.
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::primeCache");
            instance.primeCache();
            resultPromise.set_value();
        });
    }
    mCondition.notify_one();
    resultFuture.wait();
}

void RenderEngineThreaded::dump(std::string& result) {
@@ -175,63 +184,26 @@ void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) {
}

size_t RenderEngineThreaded::getMaxTextureSize() const {
    std::promise<size_t> resultPromise;
    std::future<size_t> resultFuture = resultPromise.get_future();
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::getMaxTextureSize");
            size_t size = instance.getMaxTextureSize();
            resultPromise.set_value(size);
        });
    }
    mCondition.notify_one();
    return resultFuture.get();
    waitUntilInitialized();
    return mRenderEngine->getMaxTextureSize();
}

size_t RenderEngineThreaded::getMaxViewportDims() const {
    std::promise<size_t> resultPromise;
    std::future<size_t> resultFuture = resultPromise.get_future();
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::getMaxViewportDims");
            size_t size = instance.getMaxViewportDims();
            resultPromise.set_value(size);
        });
    }
    mCondition.notify_one();
    return resultFuture.get();
    waitUntilInitialized();
    return mRenderEngine->getMaxViewportDims();
}

bool RenderEngineThreaded::isProtected() const {
    std::promise<bool> resultPromise;
    std::future<bool> resultFuture = resultPromise.get_future();
    {
    waitUntilInitialized();
    // ensure that useProtectedContext is not currently being changed by some
    // other thread.
    std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::isProtected");
            bool returnValue = instance.isProtected();
            resultPromise.set_value(returnValue);
        });
    }
    mCondition.notify_one();
    return resultFuture.get();
    return mRenderEngine->isProtected();
}

bool RenderEngineThreaded::supportsProtectedContent() const {
    std::promise<bool> resultPromise;
    std::future<bool> resultFuture = resultPromise.get_future();
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::supportsProtectedContent");
            bool returnValue = instance.supportsProtectedContent();
            resultPromise.set_value(returnValue);
        });
    }
    mCondition.notify_one();
    return resultFuture.get();
    waitUntilInitialized();
    return mRenderEngine->supportsProtectedContent();
}

bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
@@ -288,18 +260,16 @@ status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
}

void RenderEngineThreaded::cleanFramebufferCache() {
    std::promise<void> resultPromise;
    std::future<void> resultFuture = resultPromise.get_future();
    // This function is designed so it can run asynchronously, so we do not need to wait
    // for the futures.
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::cleanFramebufferCache");
            instance.cleanFramebufferCache();
            resultPromise.set_value();
        });
    }
    mCondition.notify_one();
    resultFuture.wait();
}

int RenderEngineThreaded::getContextPriority() {
@@ -318,33 +288,21 @@ int RenderEngineThreaded::getContextPriority() {
}

bool RenderEngineThreaded::supportsBackgroundBlur() {
    std::promise<bool> resultPromise;
    std::future<bool> resultFuture = resultPromise.get_future();
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::supportsBackgroundBlur");
            bool returnValue = instance.supportsBackgroundBlur();
            resultPromise.set_value(returnValue);
        });
    }
    mCondition.notify_one();
    return resultFuture.get();
    waitUntilInitialized();
    return mRenderEngine->supportsBackgroundBlur();
}

void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
    std::promise<void> resultPromise;
    std::future<void> resultFuture = resultPromise.get_future();
    // This function is designed so it can run asynchronously, so we do not need to wait
    // for the futures.
    {
        std::lock_guard lock(mThreadMutex);
        mFunctionCalls.push([&resultPromise, size](renderengine::RenderEngine& instance) {
        mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
            ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
            instance.onPrimaryDisplaySizeChanged(size);
            resultPromise.set_value();
        });
    }
    mCondition.notify_one();
    resultFuture.wait();
}

} // namespace threaded
+7 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ public:

private:
    void threadMain(CreateInstanceFactory factory);
    void waitUntilInitialized() const;

    /* ------------------------------------------------------------------------
     * Threading
@@ -83,6 +84,12 @@ private:
            GUARDED_BY(mThreadMutex);
    mutable std::condition_variable mCondition;

    // Used to allow select thread safe methods to be accessed without requiring the
    // method to be invoked on the RenderEngine thread
    bool mIsInitialized = false;
    mutable std::mutex mInitializedMutex;
    mutable std::condition_variable mInitializedCondition;

    /* ------------------------------------------------------------------------
     * Render Engine
     */