Merge "Defer deleting ExternalTextures that go out of scope during DrawLayers" into sc-dev am: d966a695b5
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14948686
Change-Id: Ib32b7171ddf0d45dc0c5520ddeca79b7ea8c17d3
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 18eb7b5..b5dd8ac 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -970,37 +970,17 @@
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-bool GLESRenderEngine::cleanupPostRender(CleanupMode mode) {
+bool GLESRenderEngine::canSkipPostRenderCleanup() const {
+ return mPriorResourcesCleaned ||
+ (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled);
+}
+
+void GLESRenderEngine::cleanupPostRender() {
ATRACE_CALL();
- if (mPriorResourcesCleaned ||
- (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) {
+ if (canSkipPostRenderCleanup()) {
// If we don't have a prior frame needing cleanup, then don't do anything.
- return false;
- }
-
- // This is a bit of a band-aid fix for FrameCaptureProcessor, as we should
- // not need to keep memory around if we don't need to do so.
- if (mode == CleanupMode::CLEAN_ALL) {
- // TODO: SurfaceFlinger memory utilization may benefit from resetting
- // texture bindings as well. Assess if it does and there's no performance regression
- // when rebinding the same image data to the same texture, and if so then its mode
- // behavior can be tweaked.
- if (mPlaceholderImage != EGL_NO_IMAGE_KHR) {
- for (auto [textureName, bufferId] : mTextureView) {
- if (bufferId && mPlaceholderImage != EGL_NO_IMAGE_KHR) {
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
- static_cast<GLeglImageOES>(mPlaceholderImage));
- mTextureView[textureName] = std::nullopt;
- checkErrors();
- }
- }
- }
- {
- std::lock_guard<std::mutex> lock(mRenderingMutex);
- mImageCache.clear();
- }
+ return;
}
// Bind the texture to placeholder so that backing image data can be freed.
@@ -1011,7 +991,6 @@
// we could no-op repeated calls of this method instead.
mLastDrawFence = nullptr;
mPriorResourcesCleaned = true;
- return true;
}
void GLESRenderEngine::cleanFramebufferCache() {
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 1ff3674..915dba3 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -68,7 +68,7 @@
const std::shared_ptr<ExternalTexture>& buffer,
const bool useFramebufferCache, base::unique_fd&& bufferFence,
base::unique_fd* drawFence) override;
- bool cleanupPostRender(CleanupMode mode) override;
+ void cleanupPostRender() override;
int getContextPriority() override;
bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; }
void onPrimaryDisplaySizeChanged(ui::Size size) override {}
@@ -106,6 +106,7 @@
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable)
EXCLUDES(mRenderingMutex);
void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) EXCLUDES(mRenderingMutex);
+ bool canSkipPostRenderCleanup() const override;
private:
friend class BindNativeBufferAsFramebuffer;
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 1da9adc..ac0affb 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -114,25 +114,6 @@
virtual void genTextures(size_t count, uint32_t* names) = 0;
virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
- enum class CleanupMode {
- CLEAN_OUTPUT_RESOURCES,
- CLEAN_ALL,
- };
- // Clean-up method that should be called on the main thread after the
- // drawFence returned by drawLayers fires. This method will free up
- // resources used by the most recently drawn frame. If the frame is still
- // being drawn, then this call is silently ignored.
- //
- // If mode is CLEAN_OUTPUT_RESOURCES, then only resources related to the
- // output framebuffer are cleaned up, including the sibling texture.
- //
- // If mode is CLEAN_ALL, then we also cleanup resources related to any input
- // buffers.
- //
- // Returns true if resources were cleaned up, and false if we didn't need to
- // do any work.
- virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;
-
// queries that are required to be thread safe
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
@@ -186,6 +167,13 @@
const std::shared_ptr<ExternalTexture>& buffer,
const bool useFramebufferCache, base::unique_fd&& bufferFence,
base::unique_fd* drawFence) = 0;
+
+ // Clean-up method that should be called on the main thread after the
+ // drawFence returned by drawLayers fires. This method will free up
+ // resources used by the most recently drawn frame. If the frame is still
+ // being drawn, then the implementation is free to silently ignore this call.
+ virtual void cleanupPostRender() = 0;
+
virtual void cleanFramebufferCache() = 0;
// Returns the priority this context was actually created with. Note: this may not be
// the same as specified at context creation time, due to implementation limits on the
@@ -234,8 +222,15 @@
// that's conflict serializable, i.e. unmap a buffer should never occur before binding the
// buffer if the caller called mapExternalTextureBuffer before calling unmap.
virtual void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) = 0;
+
+ // A thread safe query to determine if any post rendering cleanup is necessary. Returning true
+ // is a signal that calling the postRenderCleanup method would be a no-op and that callers can
+ // avoid any thread synchronization that may be required by directly calling postRenderCleanup.
+ virtual bool canSkipPostRenderCleanup() const = 0;
+
friend class ExternalTexture;
friend class threaded::RenderEngineThreaded;
+ friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test;
const RenderEngineType mRenderEngineType;
};
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index baa1305..0175af3 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -45,7 +45,8 @@
MOCK_CONST_METHOD0(isProtected, bool());
MOCK_CONST_METHOD0(supportsProtectedContent, bool());
MOCK_METHOD1(useProtectedContext, bool(bool));
- MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode));
+ MOCK_METHOD0(cleanupPostRender, void());
+ MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool());
MOCK_METHOD6(drawLayers,
status_t(const DisplaySettings&, const std::vector<const LayerSettings*>&,
const std::shared_ptr<ExternalTexture>&, const bool, base::unique_fd&&,
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
index 8356005..5c122d4 100644
--- a/libs/renderengine/skia/AutoBackendTexture.cpp
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -29,8 +29,8 @@
namespace skia {
AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer,
- bool isOutputBuffer)
- : mIsOutputBuffer(isOutputBuffer) {
+ bool isOutputBuffer, CleanupManager& cleanupMgr)
+ : mCleanupMgr(cleanupMgr), mIsOutputBuffer(isOutputBuffer) {
ATRACE_CALL();
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
@@ -49,6 +49,13 @@
this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format);
}
+AutoBackendTexture::~AutoBackendTexture() {
+ if (mBackendTexture.isValid()) {
+ mDeleteProc(mImageCtx);
+ mBackendTexture = {};
+ }
+}
+
void AutoBackendTexture::unref(bool releaseLocalResources) {
if (releaseLocalResources) {
mSurface = nullptr;
@@ -57,11 +64,7 @@
mUsageCount--;
if (mUsageCount <= 0) {
- if (mBackendTexture.isValid()) {
- mDeleteProc(mImageCtx);
- mBackendTexture = {};
- }
- delete this;
+ mCleanupMgr.add(this);
}
}
diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h
index a9e8430..00b901b 100644
--- a/libs/renderengine/skia/AutoBackendTexture.h
+++ b/libs/renderengine/skia/AutoBackendTexture.h
@@ -25,6 +25,9 @@
#include "android-base/macros.h"
+#include <mutex>
+#include <vector>
+
namespace android {
namespace renderengine {
namespace skia {
@@ -36,13 +39,50 @@
*/
class AutoBackendTexture {
public:
+ // Manager class that is responsible for the immediate or deferred cleanup
+ // of AutoBackendTextures. Clients of AutoBackendTexture are responsible for
+ // ensuring that access to this class is thread safe. Clients also control when
+ // the resources are reclaimed by setting the manager into deferred mode.
+ class CleanupManager {
+ public:
+ CleanupManager() = default;
+ void add(AutoBackendTexture* abt) {
+ if (mDeferCleanup) {
+ mCleanupList.push_back(abt);
+ } else {
+ delete abt;
+ }
+ }
+
+ void setDeferredStatus(bool enabled) { mDeferCleanup = enabled; }
+
+ bool isEmpty() const { return mCleanupList.empty(); }
+
+ // If any AutoBackedTextures were added while in deferred mode this method
+ // will ensure they are deleted before returning. It must only be called
+ // on the thread where the GPU context that created the AutoBackedTexture
+ // is active.
+ void cleanup() {
+ for (auto abt : mCleanupList) {
+ delete abt;
+ }
+ mCleanupList.clear();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CleanupManager);
+ bool mDeferCleanup = false;
+ std::vector<AutoBackendTexture*> mCleanupList;
+ };
+
// Local reference that supports RAII-style management of an AutoBackendTexture
// AutoBackendTexture by itself can't be managed in a similar fashion because
// of shared ownership with Skia objects, so we wrap it here instead.
class LocalRef {
public:
- LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer) {
- mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer);
+ LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer,
+ CleanupManager& cleanupMgr) {
+ mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr);
mTexture->ref();
}
@@ -75,10 +115,11 @@
private:
// Creates a GrBackendTexture whose contents come from the provided buffer.
- AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer);
+ AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer,
+ CleanupManager& cleanupMgr);
// The only way to invoke dtor is with unref, when mUsageCount is 0.
- ~AutoBackendTexture() {}
+ ~AutoBackendTexture();
void ref() { mUsageCount++; }
@@ -100,6 +141,8 @@
GrAHardwareBufferUtils::UpdateImageProc mUpdateProc;
GrAHardwareBufferUtils::TexImageCtx mImageCtx;
+ CleanupManager& mCleanupMgr;
+
static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext);
static void releaseImageProc(SkImage::ReleaseContext releaseContext);
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index f0986a3..d28d623 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -531,7 +531,7 @@
std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef =
std::make_shared<AutoBackendTexture::LocalRef>(grContext,
buffer->toAHardwareBuffer(),
- isRenderable);
+ isRenderable, mTextureCleanupMgr);
cache.insert({buffer->getId(), imageTextureRef});
}
}
@@ -559,6 +559,31 @@
}
}
+bool SkiaGLRenderEngine::canSkipPostRenderCleanup() const {
+ std::lock_guard<std::mutex> lock(mRenderingMutex);
+ return mTextureCleanupMgr.isEmpty();
+}
+
+void SkiaGLRenderEngine::cleanupPostRender() {
+ ATRACE_CALL();
+ std::lock_guard<std::mutex> lock(mRenderingMutex);
+ mTextureCleanupMgr.cleanup();
+}
+
+// Helper class intended to be used on the stack to ensure that texture cleanup
+// is deferred until after this class goes out of scope.
+class DeferTextureCleanup final {
+public:
+ DeferTextureCleanup(AutoBackendTexture::CleanupManager& mgr) : mMgr(mgr) {
+ mMgr.setDeferredStatus(true);
+ }
+ ~DeferTextureCleanup() { mMgr.setDeferredStatus(false); }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(DeferTextureCleanup);
+ AutoBackendTexture::CleanupManager& mMgr;
+};
+
sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(
sk_sp<SkShader> shader,
const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha,
@@ -707,6 +732,9 @@
auto grContext = getActiveGrContext();
auto& cache = mTextureCache;
+ // any AutoBackendTexture deletions will now be deferred until cleanupPostRender is called
+ DeferTextureCleanup dtc(mTextureCleanupMgr);
+
std::shared_ptr<AutoBackendTexture::LocalRef> surfaceTextureRef;
if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) {
surfaceTextureRef = it->second;
@@ -715,7 +743,7 @@
std::make_shared<AutoBackendTexture::LocalRef>(grContext,
buffer->getBuffer()
->toAHardwareBuffer(),
- true);
+ true, mTextureCleanupMgr);
}
const ui::Dataspace dstDataspace =
@@ -971,7 +999,7 @@
imageTextureRef = std::make_shared<
AutoBackendTexture::LocalRef>(grContext,
item.buffer->getBuffer()->toAHardwareBuffer(),
- false);
+ false, mTextureCleanupMgr);
}
// isOpaque means we need to ignore the alpha in the image,
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index b972c73..b30355b 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -59,7 +59,8 @@
const std::shared_ptr<ExternalTexture>& buffer,
const bool useFramebufferCache, base::unique_fd&& bufferFence,
base::unique_fd* drawFence) override;
- void cleanFramebufferCache() override {}
+ void cleanupPostRender() override;
+ void cleanFramebufferCache() override{};
int getContextPriority() override;
bool isProtected() const override { return mInProtectedContext; }
bool supportsProtectedContent() const override;
@@ -75,6 +76,7 @@
size_t getMaxViewportDims() const override;
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override;
+ bool canSkipPostRenderCleanup() const override;
private:
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
@@ -130,13 +132,14 @@
std::unordered_map<GraphicBufferId, std::shared_ptr<AutoBackendTexture::LocalRef>> mTextureCache
GUARDED_BY(mRenderingMutex);
std::unordered_map<LinearEffect, sk_sp<SkRuntimeEffect>, LinearEffectHasher> mRuntimeEffects;
+ AutoBackendTexture::CleanupManager mTextureCleanupMgr GUARDED_BY(mRenderingMutex);
StretchShaderFactory mStretchShaderFactory;
// Mutex guarding rendering operations, so that:
// 1. GL operations aren't interleaved, and
// 2. Internal state related to rendering that is potentially modified by
// multiple threads is guaranteed thread-safe.
- std::mutex mRenderingMutex;
+ mutable std::mutex mRenderingMutex;
sp<Fence> mLastDrawFence;
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index f098a86..31ad63e 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -53,7 +53,6 @@
base::unique_fd* /*drawFence*/) override {
return 0;
};
- virtual bool cleanupPostRender(CleanupMode) override { return true; };
virtual int getContextPriority() override { return 0; }
virtual void assertShadersCompiled(int numShaders) {}
virtual int reportShadersCompiled() { return 0; }
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index dfab6e8..e258741 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -43,6 +43,7 @@
constexpr bool WRITE_BUFFER_TO_FILE_ON_FAILURE = false;
namespace android {
+namespace renderengine {
class RenderEngineFactory {
public:
@@ -1779,13 +1780,6 @@
}
TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) {
- const auto& renderEngineFactory = GetParam();
-
- if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
- // GLES-specific test
- return;
- }
-
initializeRenderEngine();
renderengine::DisplaySettings settings;
@@ -1810,53 +1804,9 @@
sync_wait(fd, -1);
}
// Only cleanup the first time.
- EXPECT_TRUE(mRE->cleanupPostRender(
- renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
- EXPECT_FALSE(mRE->cleanupPostRender(
- renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
-}
-
-TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) {
- const auto& renderEngineFactory = GetParam();
-
- if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) {
- // GLES-specific test
- return;
- }
-
- initializeRenderEngine();
-
- renderengine::DisplaySettings settings;
- settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
- settings.physicalDisplay = fullscreenRect();
- settings.clip = fullscreenRect();
-
- std::vector<const renderengine::LayerSettings*> layers;
- renderengine::LayerSettings layer;
- layer.geometry.boundaries = fullscreenRect().toFloatRect();
- BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
- layer.alpha = 1.0;
- layers.push_back(&layer);
-
- base::unique_fd fence;
- mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence);
-
- const int fd = fence.get();
- if (fd >= 0) {
- sync_wait(fd, -1);
- }
-
- uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId();
- uint32_t texName = layer.source.buffer.textureName;
- EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId));
- EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName));
-
- EXPECT_TRUE(mRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL));
-
- // Now check that our view of memory is good.
- EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId));
- EXPECT_EQ(std::nullopt, mGLESRE->getBufferIdForTextureNameForTesting(bufferId));
- EXPECT_TRUE(mGLESRE->isTextureNameKnownForTesting(texName));
+ EXPECT_FALSE(mRE->canSkipPostRenderCleanup());
+ mRE->cleanupPostRender();
+ EXPECT_TRUE(mRE->canSkipPostRenderCleanup());
}
TEST_P(RenderEngineTest, testRoundedCornersCrop) {
@@ -2080,6 +2030,7 @@
expectBufferColor(rect, 0, 255, 0, 255);
}
}
+} // namespace renderengine
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index e3917cc..c65e731 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -130,22 +130,22 @@
ASSERT_EQ(true, result);
}
-TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsFalse) {
- EXPECT_CALL(*mRenderEngine,
- cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL))
- .WillOnce(Return(false));
- status_t result =
- mThreadedRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
- ASSERT_EQ(false, result);
+TEST_F(RenderEngineThreadedTest, PostRenderCleanup_skipped) {
+ EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(true));
+ EXPECT_CALL(*mRenderEngine, cleanupPostRender()).Times(0);
+ mThreadedRE->cleanupPostRender();
+
+ // call ANY synchronous function to ensure that cleanupPostRender has completed.
+ mThreadedRE->getContextPriority();
}
-TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsTrue) {
- EXPECT_CALL(*mRenderEngine,
- cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL))
- .WillOnce(Return(true));
- status_t result =
- mThreadedRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL);
- ASSERT_EQ(true, result);
+TEST_F(RenderEngineThreadedTest, PostRenderCleanup_notSkipped) {
+ EXPECT_CALL(*mRenderEngine, canSkipPostRenderCleanup()).WillOnce(Return(false));
+ EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return());
+ mThreadedRE->cleanupPostRender();
+
+ // call ANY synchronous function to ensure that cleanupPostRender has completed.
+ mThreadedRE->getContextPriority();
}
TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsFalse) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 2a65f2a..ea3871f 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -275,19 +275,26 @@
return resultFuture.get();
}
-bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) {
- std::promise<bool> resultPromise;
- std::future<bool> resultFuture = resultPromise.get_future();
+void RenderEngineThreaded::cleanupPostRender() {
+ if (canSkipPostRenderCleanup()) {
+ return;
+ }
+
+ // 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, mode](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::cleanupPostRender");
- bool returnValue = instance.cleanupPostRender(mode);
- resultPromise.set_value(returnValue);
+ mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
+ ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
+ instance.cleanupPostRender();
});
}
mCondition.notify_one();
- return resultFuture.get();
+}
+
+bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
+ waitUntilInitialized();
+ return mRenderEngine->canSkipPostRenderCleanup();
}
status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index c81f137..9b523b2 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -54,7 +54,7 @@
bool isProtected() const override;
bool supportsProtectedContent() const override;
bool useProtectedContext(bool useProtectedContext) override;
- bool cleanupPostRender(CleanupMode mode) override;
+ void cleanupPostRender() override;
status_t drawLayers(const DisplaySettings& display,
const std::vector<const LayerSettings*>& layers,
@@ -70,6 +70,7 @@
protected:
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override;
void unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) override;
+ bool canSkipPostRenderCleanup() const override;
private:
void threadMain(CreateInstanceFactory factory);