SF: Add GL texture pool
Adds a pool of GL texture names.
Prior to this change, Layer creation was forced to run on the SF main
thread because it would need to call into RenderEngine to generate a new
texture name.
By creating a pool of pre-generated texture names, this operation no
longer needs to run on the main thread, which unblocks the rest of the
system during operations such as fingerprint unlock.
Bug: 110477323
Test: SurfaceFlinger_test + manual: examine systrace and observe that
layer creation no longer blocks on access to the main thread
Change-Id: I9d68874d6c6f704c8884676454e84d916cd86507
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e39e623..196c6ea 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -501,6 +501,27 @@
postMessageAsync(new LambdaMessage([this] { readPersistentProperties(); }));
}
+uint32_t SurfaceFlinger::getNewTexture() {
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ if (!mTexturePool.empty()) {
+ uint32_t name = mTexturePool.back();
+ mTexturePool.pop_back();
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ return name;
+ }
+
+ // The pool was too small, so increase it for the future
+ ++mTexturePoolSize;
+ }
+
+ // The pool was empty, so we need to get a new texture name directly using a
+ // blocking call to the main thread
+ uint32_t name = 0;
+ postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); }));
+ return name;
+}
+
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
}
@@ -1758,6 +1779,17 @@
getBE().mTotalTime += elapsedTime;
}
getBE().mLastSwapTime = currentTime;
+
+ {
+ std::lock_guard lock(mTexturePoolMutex);
+ const size_t refillCount = mTexturePoolSize - mTexturePool.size();
+ if (refillCount > 0) {
+ const size_t offset = mTexturePool.size();
+ mTexturePool.resize(mTexturePoolSize);
+ getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset);
+ ATRACE_INT("TexturePoolSize", mTexturePool.size());
+ }
+ }
}
void SurfaceFlinger::rebuildLayerStacks() {
@@ -3515,10 +3547,13 @@
// Tack on our counter whether there is a hit or not, so everyone gets a tag
String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str());
+ // Grab the state lock since we're accessing mCurrentState
+ Mutex::Autolock lock(mStateLock);
+
// Loop over layers until we're sure there is no matching name
while (matchFound) {
matchFound = false;
- mDrawingState.traverseInZOrder([&](Layer* layer) {
+ mCurrentState.traverseInZOrder([&](Layer* layer) {
if (layer->getName() == uniqueName) {
matchFound = true;
uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str());