Adding an image cache to be behind drawLayers.
This is intended to replace the shadow GLImage array in BufferQueueLayer, since
I think this is simpler, and I don't fully trust BufferLayerConsumer's locking
model so that we could safely hold a unique_ptr<GLImage> there while passing a
pointer to RenderEngine::drawLayers.
Also, putting RenderEngine behind a binderizable interface is a bit of
a stretch goal for profiling, so EGLImage operations will need to be
behind the interface.
Bug: 118461793
Change-Id: Ibde79abd722ecb48ddf1288bc27008e07e1dc0c4
Test: librenderengine_test
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 2915bb8..e92b6e7 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -608,7 +608,17 @@
}
status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
- sp<Fence> bufferFence) {
+ sp<Fence> bufferFence, bool readCache,
+ bool persistCache) {
+ if (readCache) {
+ auto cachedImage = mImageCache.find(buffer->getId());
+
+ if (cachedImage != mImageCache.end()) {
+ bindExternalTextureImage(texName, *cachedImage->second);
+ return NO_ERROR;
+ }
+ }
+
std::unique_ptr<Image> newImage = createImage();
bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
@@ -644,9 +654,35 @@
}
}
+ // We don't always want to persist to the cache, e.g. on older devices we
+ // might bind for synchronization purpoeses, but that might leak if we never
+ // call drawLayers again, so it's just better to recreate the image again
+ // if needed when we draw.
+ if (persistCache) {
+ mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
+ }
+
return NO_ERROR;
}
+void GLESRenderEngine::evictImages(const std::vector<LayerSettings>& layers) {
+ // destroy old image references that we're not going to draw with.
+ std::unordered_set<uint64_t> bufIds;
+ for (auto layer : layers) {
+ if (layer.source.buffer.buffer != nullptr) {
+ bufIds.emplace(layer.source.buffer.buffer->getId());
+ }
+ }
+
+ for (auto it = mImageCache.begin(); it != mImageCache.end();) {
+ if (bufIds.count(it->first) == 0) {
+ it = mImageCache.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
// Translate win by the rounded corners rect coordinates, to have all values in
// layer coordinate space.
@@ -748,6 +784,8 @@
return fbo.getStatus();
}
+ evictImages(layers);
+
setViewportAndProjection(display.physicalDisplay, display.clip);
setOutputDataSpace(display.outputDataspace);
@@ -781,8 +819,9 @@
sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
+ bool readCache = layer.source.buffer.cacheHint == Buffer::CachingHint::USE_CACHE;
bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf,
- layer.source.buffer.fence);
+ layer.source.buffer.fence, readCache, /*persistCache=*/true);
usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);