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/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 0ab9605..61a9a08 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -18,10 +18,10 @@
#include <cstddef>
#include <memory>
-#include <vector>
#include <android-base/stringprintf.h>
#include <android/configuration.h>
+#include <ftl/small_map.h>
#include <ui/DisplayId.h>
#include <ui/DisplayMode.h>
#include <ui/Size.h>
@@ -38,8 +38,17 @@
class DisplayMode;
using DisplayModePtr = std::shared_ptr<const DisplayMode>;
-using DisplayModes = std::vector<DisplayModePtr>;
-using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare, Hash>;
+
+// Prevent confusion with fps_approx_ops on the underlying Fps.
+bool operator<(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator>(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator<=(const DisplayModePtr&, const DisplayModePtr&) = delete;
+bool operator>=(const DisplayModePtr&, const DisplayModePtr&) = delete;
+
+using DisplayModeId = StrongTyping<ui::DisplayModeId, struct DisplayModeIdTag, Compare>;
+
+using DisplayModes = ftl::SmallMap<DisplayModeId, DisplayModePtr, 3>;
+using DisplayModeIterator = DisplayModes::const_iterator;
class DisplayMode {
public:
@@ -61,35 +70,30 @@
return *this;
}
- Builder& setWidth(int32_t width) {
- mDisplayMode->mWidth = width;
+ Builder& setResolution(ui::Size resolution) {
+ mDisplayMode->mResolution = resolution;
return *this;
}
- Builder& setHeight(int32_t height) {
- mDisplayMode->mHeight = height;
- return *this;
- }
-
- Builder& setVsyncPeriod(int32_t vsyncPeriod) {
+ Builder& setVsyncPeriod(nsecs_t vsyncPeriod) {
mDisplayMode->mFps = Fps::fromPeriodNsecs(vsyncPeriod);
return *this;
}
Builder& setDpiX(int32_t dpiX) {
if (dpiX == -1) {
- mDisplayMode->mDpiX = getDefaultDensity();
+ mDisplayMode->mDpi.x = getDefaultDensity();
} else {
- mDisplayMode->mDpiX = dpiX / 1000.0f;
+ mDisplayMode->mDpi.x = dpiX / 1000.f;
}
return *this;
}
Builder& setDpiY(int32_t dpiY) {
if (dpiY == -1) {
- mDisplayMode->mDpiY = getDefaultDensity();
+ mDisplayMode->mDpi.y = getDefaultDensity();
} else {
- mDisplayMode->mDpiY = dpiY / 1000.0f;
+ mDisplayMode->mDpi.y = dpiY / 1000.f;
}
return *this;
}
@@ -107,59 +111,76 @@
// information to begin with. This is also used for virtual displays and
// older HWC implementations, so be careful about orientation.
- auto longDimension = std::max(mDisplayMode->mWidth, mDisplayMode->mHeight);
- if (longDimension >= 1080) {
+ if (std::max(mDisplayMode->getWidth(), mDisplayMode->getHeight()) >= 1080) {
return ACONFIGURATION_DENSITY_XHIGH;
} else {
return ACONFIGURATION_DENSITY_TV;
}
}
+
std::shared_ptr<DisplayMode> mDisplayMode;
};
DisplayModeId getId() const { return mId; }
+
hal::HWConfigId getHwcId() const { return mHwcId; }
PhysicalDisplayId getPhysicalDisplayId() const { return mPhysicalDisplayId; }
- int32_t getWidth() const { return mWidth; }
- int32_t getHeight() const { return mHeight; }
- ui::Size getSize() const { return {mWidth, mHeight}; }
+ ui::Size getResolution() const { return mResolution; }
+ int32_t getWidth() const { return mResolution.getWidth(); }
+ int32_t getHeight() const { return mResolution.getHeight(); }
+
Fps getFps() const { return mFps; }
nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
- float getDpiX() const { return mDpiX; }
- float getDpiY() const { return mDpiY; }
+
+ struct Dpi {
+ float x = -1;
+ float y = -1;
+
+ bool operator==(Dpi other) const { return x == other.x && y == other.y; }
+ };
+
+ Dpi getDpi() const { return mDpi; }
// Switches between modes in the same group are seamless, i.e.
// without visual interruptions such as a black screen.
int32_t getGroup() const { return mGroup; }
- bool equalsExceptDisplayModeId(const DisplayModePtr& other) const {
- return mHwcId == other->mHwcId && mWidth == other->mWidth && mHeight == other->mHeight &&
- getVsyncPeriod() == other->getVsyncPeriod() && mDpiX == other->mDpiX &&
- mDpiY == other->mDpiY && mGroup == other->mGroup;
- }
-
private:
explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
- hal::HWConfigId mHwcId;
+ const hal::HWConfigId mHwcId;
DisplayModeId mId;
+
PhysicalDisplayId mPhysicalDisplayId;
- int32_t mWidth = -1;
- int32_t mHeight = -1;
+ ui::Size mResolution;
Fps mFps;
- float mDpiX = -1;
- float mDpiY = -1;
+ Dpi mDpi;
int32_t mGroup = -1;
};
+inline bool equalsExceptDisplayModeId(const DisplayMode& lhs, const DisplayMode& rhs) {
+ return lhs.getHwcId() == rhs.getHwcId() && lhs.getResolution() == rhs.getResolution() &&
+ lhs.getVsyncPeriod() == rhs.getVsyncPeriod() && lhs.getDpi() == rhs.getDpi() &&
+ lhs.getGroup() == rhs.getGroup();
+}
+
inline std::string to_string(const DisplayMode& mode) {
- return base::StringPrintf("{id=%d, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
- "dpiX=%.2f, dpiY=%.2f, group=%d}",
+ return base::StringPrintf("{id=%d, hwcId=%d, resolution=%dx%d, refreshRate=%s, "
+ "dpi=%.2fx%.2f, group=%d}",
mode.getId().value(), mode.getHwcId(), mode.getWidth(),
- mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
- mode.getDpiY(), mode.getGroup());
+ mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpi().x,
+ mode.getDpi().y, mode.getGroup());
+}
+
+template <typename... DisplayModePtrs>
+inline DisplayModes makeModes(const DisplayModePtrs&... modePtrs) {
+ DisplayModes modes;
+ // Note: The omission of std::move(modePtrs) is intentional, because order of evaluation for
+ // arguments is unspecified.
+ (modes.try_emplace(modePtrs->getId(), modePtrs), ...);
+ return modes;
}
} // namespace android