SF: Refactor display device creation
Move display device creation to its own function which handles all
initialization before creating a DisplayDevice instance, which now just
simply constructs an instance from the passed values.
Also introduces a factory to abstract creating libgui Surface instances,
so that can be replaced by the test.
Test: Builds
Bug: 74827900
Change-Id: Ia80c865dc96b300033c506cc3093e563bcab787b
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 92d5e21..fe0b30b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -57,9 +57,6 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
-static bool useTripleFramebuffer = getInt64< ISurfaceFlingerConfigs,
- &ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2) >= 3;
-
/*
* Initialize the display to the specified values.
*
@@ -74,72 +71,43 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
bool supportWideColor,
- bool supportHdr)
+ bool supportHdr,
+ int initialPowerMode)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
mHwcDisplayId(hwcId),
mDisplayToken(displayToken),
+ mNativeWindow(nativeWindow),
mDisplaySurface(displaySurface),
- mSurface{flinger->getRenderEngine().createSurface()},
- mDisplayWidth(),
- mDisplayHeight(),
- mPageFlipCount(),
+ mSurface{std::move(renderSurface)},
+ mDisplayWidth(displayWidth),
+ mDisplayHeight(displayHeight),
+ mPageFlipCount(0),
mIsSecure(isSecure),
mLayerStack(NO_LAYER_STACK),
mOrientation(),
- mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
+ mViewport(Rect::INVALID_RECT),
+ mFrame(Rect::INVALID_RECT),
+ mPowerMode(initialPowerMode),
+ mActiveConfig(0),
+ mActiveColorMode(ColorMode::NATIVE),
+ mDisplayHasWideColor(supportWideColor),
+ mDisplayHasHdr(supportHdr)
{
// clang-format on
- Surface* surface;
- mNativeWindow = surface = new Surface(producer, false);
- ANativeWindow* const window = mNativeWindow.get();
-
- mActiveColorMode = ColorMode::NATIVE;
- mDisplayHasWideColor = supportWideColor;
- mDisplayHasHdr = supportHdr;
-
- /*
- * Create our display's surface
- */
- mSurface->setCritical(mType == DisplayDevice::DISPLAY_PRIMARY);
- mSurface->setAsync(mType >= DisplayDevice::DISPLAY_VIRTUAL);
- mSurface->setNativeWindow(window);
- mDisplayWidth = mSurface->queryWidth();
- mDisplayHeight = mSurface->queryHeight();
-
- // Make sure that composition can never be stalled by a virtual display
- // consumer that isn't processing buffers fast enough. We have to do this
- // in two places:
- // * Here, in case the display is composed entirely by HWC.
- // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
- // window's swap interval in eglMakeCurrent, so they'll override the
- // interval we set here.
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- window->setSwapInterval(window, 0);
-
- mPageFlipCount = 0;
- mViewport.makeInvalid();
- mFrame.makeInvalid();
-
- // virtual displays are always considered enabled
- mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
- HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// initialize the display orientation transform.
setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
-
- if (useTripleFramebuffer) {
- surface->allocateBuffers();
- }
}
-DisplayDevice::~DisplayDevice() {
-}
+DisplayDevice::~DisplayDevice() = default;
void DisplayDevice::disconnect(HWComposer& hwc) {
if (mHwcDisplayId >= 0) {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 737971f..fbb0d46 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -77,9 +77,14 @@
int32_t hwcId,
bool isSecure,
const wp<IBinder>& displayToken,
+ const sp<ANativeWindow>& nativeWindow,
const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- bool supportWideColor, bool supportHdr);
+ std::unique_ptr<RE::Surface> renderSurface,
+ int displayWidth,
+ int displayHeight,
+ bool supportWideColor,
+ bool supportHdr,
+ int initialPowerMode);
// clang-format on
~DisplayDevice();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ecd09c5..a27cc3d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -154,6 +154,32 @@
return std::string(value) == "true";
}
+NativeWindowSurface::~NativeWindowSurface() = default;
+
+namespace impl {
+
+class NativeWindowSurface final : public android::NativeWindowSurface {
+public:
+ static std::unique_ptr<android::NativeWindowSurface> create(
+ const sp<IGraphicBufferProducer>& producer) {
+ return std::make_unique<NativeWindowSurface>(producer);
+ }
+
+ explicit NativeWindowSurface(const sp<IGraphicBufferProducer>& producer)
+ : surface(new Surface(producer, false)) {}
+
+ ~NativeWindowSurface() override = default;
+
+private:
+ sp<ANativeWindow> getNativeWindow() const override { return surface; }
+
+ void preallocateBuffers() override { surface->allocateBuffers(); }
+
+ sp<Surface> surface;
+};
+
+} // namespace impl
+
SurfaceFlingerBE::SurfaceFlingerBE()
: mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
@@ -194,7 +220,8 @@
mNumLayers(0),
mVrFlingerRequestsDisplay(false),
mMainThreadId(std::this_thread::get_id()),
- mCreateBufferQueue(&BufferQueue::createBufferQueue) {}
+ mCreateBufferQueue(&BufferQueue::createBufferQueue),
+ mCreateNativeWindowSurface(&impl::NativeWindowSurface::create) {}
SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
@@ -2113,7 +2140,7 @@
}
DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
- HWC2::Connection connection) const {
+ HWC2::Connection connection) const {
// Figure out whether the event is for the primary display or an
// external display by matching the Hwc display id against one for a
// connected display. If we did not find a match, we then check what
@@ -2182,6 +2209,84 @@
mPendingHotplugEvents.clear();
}
+sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
+ const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
+ bool hasWideColorSupport = false;
+ if (hasWideColorDisplay) {
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(state.type);
+ for (ColorMode colorMode : modes) {
+ switch (colorMode) {
+ case ColorMode::DISPLAY_P3:
+ case ColorMode::ADOBE_RGB:
+ case ColorMode::DCI_P3:
+ hasWideColorSupport = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ bool hasHdrSupport = false;
+ std::unique_ptr<HdrCapabilities> hdrCapabilities =
+ getHwComposer().getHdrCapabilities(state.type);
+ if (hdrCapabilities) {
+ const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
+ auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
+ hasHdrSupport = iter != types.cend();
+ }
+
+ auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
+ auto nativeWindow = nativeWindowSurface->getNativeWindow();
+
+ /*
+ * Create our display's surface
+ */
+ std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
+ renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
+ renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
+ renderSurface->setNativeWindow(nativeWindow.get());
+ const int displayWidth = renderSurface->queryWidth();
+ const int displayHeight = renderSurface->queryHeight();
+
+ // Make sure that composition can never be stalled by a virtual display
+ // consumer that isn't processing buffers fast enough. We have to do this
+ // in two places:
+ // * Here, in case the display is composed entirely by HWC.
+ // * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
+ // window's swap interval in eglMakeCurrent, so they'll override the
+ // interval we set here.
+ if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) {
+ nativeWindow->setSwapInterval(nativeWindow.get(), 0);
+ }
+
+ // virtual displays are always considered enabled
+ auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
+ : HWC_POWER_MODE_OFF;
+
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
+ dispSurface, std::move(renderSurface), displayWidth, displayHeight,
+ hasWideColorSupport, hasHdrSupport, initialPowerMode);
+
+ if (maxFrameBufferAcquiredBuffers >= 3) {
+ nativeWindowSurface->preallocateBuffers();
+ }
+
+ ColorMode defaultColorMode = ColorMode::NATIVE;
+ if (hasWideColorSupport) {
+ defaultColorMode = ColorMode::SRGB;
+ }
+ setActiveColorModeInternal(hw, defaultColorMode);
+ hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+ hw->setLayerStack(state.layerStack);
+ hw->setProjection(state.orientation, state.viewport, state.frame);
+ hw->setDisplayName(state.displayName);
+
+ return hw;
+}
+
void SurfaceFlinger::processDisplayChangesLocked() {
// here we take advantage of Vector's copy-on-write semantics to
// improve performance by skipping the transaction entirely when
@@ -2304,50 +2409,10 @@
}
const wp<IBinder>& display(curr.keyAt(i));
-
if (dispSurface != nullptr) {
- bool hasWideColorSupport = false;
- if (hasWideColorDisplay) {
- std::vector<ColorMode> modes =
- getHwComposer().getColorModes(state.type);
- for (ColorMode colorMode : modes) {
- switch (colorMode) {
- case ColorMode::DISPLAY_P3:
- case ColorMode::ADOBE_RGB:
- case ColorMode::DCI_P3:
- hasWideColorSupport = true;
- break;
- default:
- break;
- }
- }
- }
-
- bool hasHdrSupport = false;
- std::unique_ptr<HdrCapabilities> hdrCapabilities =
- getHwComposer().getHdrCapabilities(state.type);
- if (hdrCapabilities) {
- const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
- auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
- hasHdrSupport = iter != types.cend();
- }
-
- sp<DisplayDevice> hw =
- new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
- dispSurface, producer, hasWideColorSupport,
- hasHdrSupport);
-
- ColorMode defaultColorMode = ColorMode::NATIVE;
- if (hasWideColorSupport) {
- defaultColorMode = ColorMode::SRGB;
- }
- setActiveColorModeInternal(hw, defaultColorMode);
- hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation, state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
-
- mDisplays.add(display, hw);
+ mDisplays.add(display,
+ setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface,
+ producer));
if (!state.isVirtualDisplay()) {
mEventThread->onHotplugReceived(state.type, true);
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c7ffea7..b23a9b1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -121,6 +121,19 @@
eTransactionMask = 0x07
};
+// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
+// use as a NativeWindow.
+class NativeWindowSurface {
+public:
+ virtual ~NativeWindowSurface();
+
+ // Gets the NativeWindow to use for the surface.
+ virtual sp<ANativeWindow> getNativeWindow() const = 0;
+
+ // Indicates that the surface should allocate its buffers now.
+ virtual void preallocateBuffers() = 0;
+};
+
class SurfaceFlingerBE
{
public:
@@ -650,6 +663,10 @@
*/
DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
HWC2::Connection connection) const;
+ sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId,
+ const DisplayDeviceState& state,
+ const sp<DisplaySurface>& dispSurface,
+ const sp<IGraphicBufferProducer>& producer);
void processDisplayChangesLocked();
void processDisplayHotplugEventsLocked();
@@ -843,6 +860,10 @@
bool /* consumerIsSurfaceFlinger */)>;
CreateBufferQueueFunction mCreateBufferQueue;
+ using CreateNativeWindowSurfaceFunction =
+ std::function<std::unique_ptr<NativeWindowSurface>(const sp<IGraphicBufferProducer>&)>;
+ CreateNativeWindowSurfaceFunction mCreateNativeWindowSurface;
+
SurfaceFlingerBE mBE;
};
}; // namespace android