SF: Flatten display containers
Store displays and tokens in contiguous storage for cache-efficient
lookup and iteration, which also ensures that internal displays are
composited before external and virtual displays.
Bug: 182939859
Bug: 185536303
Test: simpleperf
Test: libsurfaceflinger_unittest
Change-Id: I1ae65c3e80567b65736bd189c263be5be34862e3
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 07da731..011aaef 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -27,6 +27,7 @@
#include <android/gui/DisplayState.h>
#include <cutils/atomic.h>
#include <cutils/compiler.h>
+#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
@@ -905,8 +906,8 @@
}
sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) {
- const auto it = mDisplays.find(displayToken);
- return it == mDisplays.end() ? nullptr : it->second;
+ const sp<DisplayDevice> nullDisplay;
+ return mDisplays.get(displayToken).value_or(std::cref(nullDisplay));
}
sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const
@@ -1051,8 +1052,8 @@
*/
sp<IBinder> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const
REQUIRES(mStateLock) {
- const auto it = mPhysicalDisplayTokens.find(displayId);
- return it != mPhysicalDisplayTokens.end() ? it->second : nullptr;
+ const sp<IBinder> nullToken;
+ return mPhysicalDisplayTokens.get(displayId).value_or(std::cref(nullToken));
}
std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked(
@@ -1247,10 +1248,14 @@
std::vector<HotplugEvent> mPendingHotplugEvents GUARDED_BY(mStateLock);
- // this may only be written from the main thread with mStateLock held
- // it may be read from other threads with mStateLock held
- std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays GUARDED_BY(mStateLock);
- std::unordered_map<PhysicalDisplayId, sp<IBinder>> mPhysicalDisplayTokens
+ // Displays are composited in `mDisplays` order. Internal displays are inserted at boot and
+ // never removed, so take precedence over external and virtual displays.
+ //
+ // The static capacities were chosen to exceed a typical number of physical/virtual displays.
+ //
+ // May be read from any thread, but must only be written from the main thread.
+ ftl::SmallMap<wp<IBinder>, const sp<DisplayDevice>, 5> mDisplays GUARDED_BY(mStateLock);
+ ftl::SmallMap<PhysicalDisplayId, const sp<IBinder>, 3> mPhysicalDisplayTokens
GUARDED_BY(mStateLock);
struct {
@@ -1423,10 +1428,8 @@
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) {
- return std::any_of(mDisplays.begin(), mDisplays.end(),
- [](std::pair<wp<IBinder>, sp<DisplayDevice>> display) {
- return display.second->isRefreshRateOverlayEnabled();
- });
+ return hasDisplay(
+ [](const auto& display) { return display.isRefreshRateOverlayEnabled(); });
}
wp<IBinder> mActiveDisplayToken GUARDED_BY(mStateLock);