SF: Unify data types for display modes
Remove the RefreshRateConfigs::RefreshRate wrapper around DisplayMode.
Store DisplayModes as a SmallMap, so that RefreshRateConfigs uses the
same data structure for lookup by ID. Use iterators into that map for
all bookkeeping in RefreshRateConfigs.
Bug: 182939859
Bug: 185535769
Test: libsurfaceflinger_unittest
Change-Id: I7708fa997089802c45d906b17b7a073f5c82105e
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 94b16b4..0ee3121 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1044,15 +1044,13 @@
const auto& supportedModes = display->getSupportedModes();
info->supportedDisplayModes.clear();
info->supportedDisplayModes.reserve(supportedModes.size());
- for (const auto& mode : supportedModes) {
+
+ for (const auto& [id, mode] : supportedModes) {
ui::DisplayMode outMode;
- outMode.id = static_cast<int32_t>(mode->getId().value());
+ outMode.id = static_cast<int32_t>(id.value());
- auto width = mode->getWidth();
- auto height = mode->getHeight();
-
- auto xDpi = mode->getDpiX();
- auto yDpi = mode->getDpiY();
+ auto [width, height] = mode->getResolution();
+ auto [xDpi, yDpi] = mode->getDpi();
if (display->isPrimary() &&
(internalDisplayOrientation == ui::ROTATION_90 ||
@@ -1146,7 +1144,7 @@
// Start receiving vsync samples now, so that we can detect a period
// switch.
- mScheduler->resyncToHardwareVsync(true, info.mode->getVsyncPeriod());
+ mScheduler->resyncToHardwareVsync(true, info.mode->getFps());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
@@ -1212,7 +1210,7 @@
return;
}
- if (display->getActiveMode()->getSize() != upcomingModeInfo.mode->getSize()) {
+ if (display->getActiveMode()->getResolution() != upcomingModeInfo.mode->getResolution()) {
auto& state = mCurrentState.displays.editValueFor(display->getDisplayToken());
// We need to generate new sequenceId in order to recreate the display (and this
// way the framebuffer).
@@ -1248,7 +1246,7 @@
void SurfaceFlinger::desiredActiveModeChangeDone(const sp<DisplayDevice>& display) {
const auto refreshRate = display->getDesiredActiveMode()->mode->getFps();
clearDesiredActiveModeState(display);
- mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs());
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
updatePhaseConfiguration(refreshRate);
}
@@ -2680,11 +2678,11 @@
mDebugInTransaction = 0;
}
-void SurfaceFlinger::loadDisplayModes(PhysicalDisplayId displayId, DisplayModes& outModes,
- DisplayModePtr& outActiveMode) const {
+std::pair<DisplayModes, DisplayModePtr> SurfaceFlinger::loadDisplayModes(
+ PhysicalDisplayId displayId) const {
std::vector<HWComposer::HWCDisplayMode> hwcModes;
std::optional<hal::HWDisplayId> activeModeHwcId;
- bool activeModeIsSupported;
+
int attempt = 0;
constexpr int kMaxAttempts = 3;
do {
@@ -2692,63 +2690,60 @@
activeModeHwcId = getHwComposer().getActiveMode(displayId);
LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode");
- activeModeIsSupported =
- std::any_of(hwcModes.begin(), hwcModes.end(),
- [activeModeHwcId](const HWComposer::HWCDisplayMode& mode) {
- return mode.hwcId == *activeModeHwcId;
- });
- } while (!activeModeIsSupported && ++attempt < kMaxAttempts);
- LOG_ALWAYS_FATAL_IF(!activeModeIsSupported,
+ const auto isActiveMode = [activeModeHwcId](const HWComposer::HWCDisplayMode& mode) {
+ return mode.hwcId == *activeModeHwcId;
+ };
+
+ if (std::any_of(hwcModes.begin(), hwcModes.end(), isActiveMode)) {
+ break;
+ }
+ } while (++attempt < kMaxAttempts);
+
+ LOG_ALWAYS_FATAL_IF(attempt == kMaxAttempts,
"After %d attempts HWC still returns an active mode which is not"
- " supported. Active mode ID = %" PRIu64 " . Supported modes = %s",
+ " supported. Active mode ID = %" PRIu64 ". Supported modes = %s",
kMaxAttempts, *activeModeHwcId, base::Join(hwcModes, ", ").c_str());
DisplayModes oldModes;
-
if (const auto token = getPhysicalDisplayTokenLocked(displayId)) {
oldModes = getDisplayDeviceLocked(token)->getSupportedModes();
}
- int largestUsedModeId = -1; // Use int instead of DisplayModeId for signedness
- for (const auto& mode : oldModes) {
- const auto id = static_cast<int>(mode->getId().value());
- if (id > largestUsedModeId) {
- largestUsedModeId = id;
- }
- }
+ ui::DisplayModeId nextModeId = 1 +
+ std::accumulate(oldModes.begin(), oldModes.end(), static_cast<ui::DisplayModeId>(-1),
+ [](ui::DisplayModeId max, const auto& pair) {
+ return std::max(max, pair.first.value());
+ });
DisplayModes newModes;
- int32_t nextModeId = largestUsedModeId + 1;
for (const auto& hwcMode : hwcModes) {
- newModes.push_back(DisplayMode::Builder(hwcMode.hwcId)
- .setId(DisplayModeId{nextModeId++})
- .setPhysicalDisplayId(displayId)
- .setWidth(hwcMode.width)
- .setHeight(hwcMode.height)
- .setVsyncPeriod(hwcMode.vsyncPeriod)
- .setDpiX(hwcMode.dpiX)
- .setDpiY(hwcMode.dpiY)
- .setGroup(hwcMode.configGroup)
- .build());
+ const DisplayModeId id{nextModeId++};
+ newModes.try_emplace(id,
+ DisplayMode::Builder(hwcMode.hwcId)
+ .setId(id)
+ .setPhysicalDisplayId(displayId)
+ .setResolution({hwcMode.width, hwcMode.height})
+ .setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setDpiX(hwcMode.dpiX)
+ .setDpiY(hwcMode.dpiY)
+ .setGroup(hwcMode.configGroup)
+ .build());
}
- const bool modesAreSame =
+ const bool sameModes =
std::equal(newModes.begin(), newModes.end(), oldModes.begin(), oldModes.end(),
- [](DisplayModePtr left, DisplayModePtr right) {
- return left->equalsExceptDisplayModeId(right);
+ [](const auto& lhs, const auto& rhs) {
+ return equalsExceptDisplayModeId(*lhs.second, *rhs.second);
});
- if (modesAreSame) {
- // The supported modes have not changed, keep the old IDs.
- outModes = oldModes;
- } else {
- outModes = newModes;
- }
+ // Keep IDs if modes have not changed.
+ const auto& modes = sameModes ? oldModes : newModes;
+ const DisplayModePtr activeMode =
+ std::find_if(modes.begin(), modes.end(), [activeModeHwcId](const auto& pair) {
+ return pair.second->getHwcId() == activeModeHwcId;
+ })->second;
- outActiveMode = *std::find_if(outModes.begin(), outModes.end(),
- [activeModeHwcId](const DisplayModePtr& mode) {
- return mode->getHwcId() == *activeModeHwcId;
- });
+ return {modes, activeMode};
}
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
@@ -2764,9 +2759,7 @@
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
- DisplayModes supportedModes;
- DisplayModePtr activeMode;
- loadDisplayModes(displayId, supportedModes, activeMode);
+ auto [supportedModes, activeMode] = loadDisplayModes(displayId);
if (it == mPhysicalDisplayTokens.end()) {
ALOGV("Creating display %s", to_string(displayId).c_str());
@@ -2777,7 +2770,7 @@
.hwcDisplayId = event.hwcDisplayId,
.deviceProductInfo = std::move(info->deviceProductInfo),
.supportedModes = std::move(supportedModes),
- .activeMode = activeMode};
+ .activeMode = std::move(activeMode)};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = std::move(info->name);
@@ -2792,7 +2785,7 @@
auto& state = mCurrentState.displays.editValueFor(token);
state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId
state.physical->supportedModes = std::move(supportedModes);
- state.physical->activeMode = activeMode;
+ state.physical->activeMode = std::move(activeMode);
if (getHwComposer().updatesDeviceProductInfoOnHotplugReconnect()) {
state.physical->deviceProductInfo = std::move(info->deviceProductInfo);
}
@@ -2925,7 +2918,7 @@
ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
- resolution = state.physical->activeMode->getSize();
+ resolution = state.physical->activeMode->getResolution();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
@@ -2979,7 +2972,7 @@
LOG_FATAL_IF(!displayId);
displaySurface =
sp<FramebufferSurface>::make(getHwComposer(), *displayId, bqConsumer,
- state.physical->activeMode->getSize(),
+ state.physical->activeMode->getResolution(),
ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -3092,7 +3085,7 @@
}
void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
mVsyncConfiguration->reset();
- const Fps refreshRate = activeDisplay->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ const Fps refreshRate = activeDisplay->refreshRateConfigs().getActiveMode()->getFps();
updatePhaseConfiguration(refreshRate);
mRefreshRateStats->setRefreshRate(refreshRate);
}
@@ -3354,7 +3347,7 @@
mCompositionEngine->updateCursorAsync(refreshArgs);
}
-void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, DisplayModeEvent event) {
+void SurfaceFlinger::requestDisplayMode(DisplayModePtr mode, DisplayModeEvent event) {
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Scheduler::chooseRefreshRateForContent
@@ -3367,14 +3360,12 @@
}
ATRACE_CALL();
- // Don't do any updating if the current fps is the same as the new one.
- if (!display->refreshRateConfigs().isModeAllowed(refreshRate.getModeId())) {
- ALOGV("Skipping mode %d as it is not part of allowed modes",
- refreshRate.getModeId().value());
+ if (!display->refreshRateConfigs().isModeAllowed(mode->getId())) {
+ ALOGV("Skipping disallowed mode %d", mode->getId().value());
return;
}
- setDesiredActiveMode({refreshRate.getMode(), event});
+ setDesiredActiveMode({std::move(mode), event});
}
void SurfaceFlinger::triggerOnFrameRateOverridesChanged() {
@@ -4802,8 +4793,7 @@
{}, mPid, getuid(), transactionId);
setPowerModeInternal(display, hal::PowerMode::ON);
- const nsecs_t vsyncPeriod =
- display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
+ const nsecs_t vsyncPeriod = display->refreshRateConfigs().getActiveMode()->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
mActiveDisplayTransformHint = display->getTransformHint();
// Use phase of 0 since phase is not known.
@@ -4842,7 +4832,7 @@
if (mInterceptor->isEnabled()) {
mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
- const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
+ const auto refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
if (currentMode == hal::PowerMode::OFF) {
// Turn on the display
if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
@@ -4860,7 +4850,7 @@
if (isDisplayActiveLocked(display) && mode != hal::PowerMode::DOZE_SUSPEND) {
setHWCVsyncEnabled(displayId, mHWCVsyncPendingState);
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
}
mVisibleRegionsDirty = true;
@@ -4890,7 +4880,7 @@
getHwComposer().setPowerMode(displayId, mode);
if (isDisplayActiveLocked(display) && currentMode == hal::PowerMode::DOZE_SUSPEND) {
mScheduler->onScreenAcquired(mAppConnectionHandle);
- mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+ mScheduler->resyncToHardwareVsync(true, refreshRate);
}
} else if (mode == hal::PowerMode::DOZE_SUSPEND) {
// Leave display going to doze
@@ -5376,8 +5366,10 @@
std::string fps, xDpi, yDpi;
if (const auto activeMode = display->getActiveMode()) {
fps = to_string(activeMode->getFps());
- xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
- yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
+
+ const auto dpi = activeMode->getDpi();
+ xDpi = base::StringPrintf("%.2f", dpi.x);
+ yDpi = base::StringPrintf("%.2f", dpi.y);
} else {
fps = "unknown";
xDpi = "unknown";
@@ -6137,7 +6129,7 @@
if (!updateOverlay) return;
// Update the overlay on the main thread to avoid race conditions with
- // mRefreshRateConfigs->getCurrentRefreshRate()
+ // mRefreshRateConfigs->getActiveMode()
static_cast<void>(mScheduler->schedule([=] {
const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
if (!display) {
@@ -7181,7 +7173,7 @@
refreshRate = *frameRateOverride;
} else if (!getHwComposer().isHeadless()) {
if (const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked())) {
- refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
}
}