Toggle for RenderEngine to cleanup texture memory.
Currently RenderEngine does not rebind texture memory after it is done
drawing, so buffers may not be freed until the corresponding texture is
deleted. For SurfaceFlinger this is more acceptable since layers tend to
reuse buffers and they own their own texture name, so it's more natural
to implicitly tie memory lifecycle to layer lifecycle since the buffers
won't need to be free until the layer is deleted anyways.
But for mediaserver it's not acceptable, since thumbnail generation is
rare and texture generation is expensive, so if we don't clean up
texture resources properly then mediaserver hangs on to a video frame
until the next time a thumbnail is generated, which is very bad for HDR
frames since it's a multi-megabyte overhead.
This patch will solve this for mediaserver by adding a toggle to
cleanupPostRender. It's likely that SurfaceFlinger can benefit from this
as well since rebinding memory is fast, but more investigation would be
needed to see if that is the case, and this patch is less risky to be
applied to other branches.
Bug: 162202251
Test: librenderengine_test
Test: Launch custom apk with thumbnail generation
Test: adb shell dumpsys meminfo mediaserver
Change-Id: Iec7f65c4911b5cbf2189fa33929bbcfa97bb4c14
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 245bfd7..2c6eae2 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -75,7 +75,7 @@
const std::vector<const LayerSettings*>& layers,
const sp<GraphicBuffer>& buffer, const bool useFramebufferCache,
base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
- bool cleanupPostRender() override;
+ bool cleanupPostRender(CleanupMode mode) override;
EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
// Creates an output image for rendering to
@@ -86,6 +86,12 @@
// Test-only methods
// Returns true iff mImageCache contains an image keyed by bufferId
bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
+ // Returns true iff texName was previously generated by RenderEngine and was
+ // not destroyed.
+ bool isTextureNameKnownForTesting(uint32_t texName);
+ // Returns the buffer ID of the content bound to texName, or nullopt if no
+ // such mapping exists.
+ std::optional<uint64_t> getBufferIdForTextureNameForTesting(uint32_t texName);
// Returns true iff mFramebufferImageCache contains an image keyed by bufferId
bool isFramebufferImageCachedForTesting(uint64_t bufferId)
EXCLUDES(mFramebufferImageCacheMutex);
@@ -224,6 +230,8 @@
// Cache of GL images that we'll store per GraphicBuffer ID
std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex);
+ std::unordered_map<uint32_t, std::optional<uint64_t>> mTextureView;
+
// Mutex guarding rendering operations, so that:
// 1. GL operations aren't interleaved, and
// 2. Internal state related to rendering that is potentially modified by
@@ -237,6 +245,11 @@
// ensure that we align on a word. Allocating 16 bytes will provide a
// guarantee that we don't clobber memory.
uint32_t mPlaceholderDrawBuffer[4];
+ // Placeholder buffer and image, similar to mPlaceholderDrawBuffer, but
+ // instead these are intended for cleaning up texture memory with the
+ // GL_TEXTURE_EXTERNAL_OES target.
+ ANativeWindowBuffer* mPlaceholderBuffer = nullptr;
+ EGLImage mPlaceholderImage = EGL_NO_IMAGE_KHR;
sp<Fence> mLastDrawFence;
// Store a separate boolean checking if prior resources were cleaned up, as
// devices that don't support native sync fences can't rely on a last draw