SF: Generalize display management
This CL enables SF to manage an arbitrary number of physical displays.
Previously, displays were identified by 32-bit IDs, where 0 is the
internal display, 1 is the external display, [2, INT32_MAX] are HWC
virtual displays, and -1 represents an invalid display or a non-HWC
virtual display.
If the HWC provides display identification data, SF now allocates 64-bit
display IDs for physical and HWC virtual displays. The IDs are expressed
using an option type, where the null value represents an invalid display
or non-HWC virtual display. Without HWC support, SF falls back to legacy
behavior with at most two physical displays.
The dynamic display IDs are translated to the legacy constants at the
SF/DMS boundary, as a stopgap until the framework is generalized.
Bug: 74619554
Test: Connect 3 displays and create virtual displays on HWC 2.2 and 2.3
Test: libsurfaceflinger_unittest
Test: SurfaceFlinger_test
Change-Id: I0a4a57b6ab7de2dbcf719a4eb1a19a133694012e
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
index dcc4138..ec240f3 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -33,6 +33,9 @@
constexpr size_t kEdidHeaderLength = 5;
+constexpr uint16_t kFallbackEdidManufacturerId = 0;
+constexpr uint16_t kVirtualEdidManufacturerId = 0xffffu;
+
std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) {
if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) {
return {};
@@ -165,7 +168,8 @@
return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt;
}
-std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData& data) {
+std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
+ uint8_t port, const DisplayIdentificationData& data) {
if (!isEdid(data)) {
ALOGE("Display identification data has unknown format.");
return {};
@@ -179,7 +183,16 @@
// Hash display name instead of using product code or serial number, since the latter have been
// observed to change on some displays with multiple inputs.
const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName));
- return getEdidDisplayId(port, edid->manufacturerId, hash);
+ return DisplayIdentificationInfo{getEdidDisplayId(port, edid->manufacturerId, hash),
+ std::string(edid->displayName)};
+}
+
+DisplayId getFallbackDisplayId(uint8_t port) {
+ return getEdidDisplayId(port, kFallbackEdidManufacturerId, 0);
+}
+
+DisplayId getVirtualDisplayId(uint32_t id) {
+ return getEdidDisplayId(0, kVirtualEdidManufacturerId, id);
}
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
index 379f2d3..1f2e789 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -19,6 +19,7 @@
#include <array>
#include <cstdint>
#include <optional>
+#include <string>
#include <string_view>
#include <vector>
@@ -27,6 +28,11 @@
using DisplayId = uint64_t;
using DisplayIdentificationData = std::vector<uint8_t>;
+struct DisplayIdentificationInfo {
+ DisplayId id;
+ std::string name;
+};
+
// NUL-terminated plug and play ID.
using PnpId = std::array<char, 4>;
@@ -40,6 +46,10 @@
std::optional<Edid> parseEdid(const DisplayIdentificationData&);
std::optional<PnpId> getPnpId(uint16_t manufacturerId);
-std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData&);
+std::optional<DisplayIdentificationInfo> parseDisplayIdentificationData(
+ uint8_t port, const DisplayIdentificationData&);
+
+DisplayId getFallbackDisplayId(uint8_t port);
+DisplayId getVirtualDisplayId(uint32_t id);
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index e6d7834..f3f8d9d 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -52,26 +52,25 @@
*
*/
-FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
- const sp<IGraphicBufferConsumer>& consumer) :
- ConsumerBase(consumer),
- mDisplayType(disp),
- mCurrentBufferSlot(-1),
- mCurrentBuffer(),
- mCurrentFence(Fence::NO_FENCE),
- mHwc(hwc),
- mHasPendingRelease(false),
- mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mPreviousBuffer()
-{
- ALOGV("Creating for display %d", disp);
+FramebufferSurface::FramebufferSurface(HWComposer& hwc, DisplayId displayId,
+ const sp<IGraphicBufferConsumer>& consumer)
+ : ConsumerBase(consumer),
+ mDisplayId(displayId),
+ mCurrentBufferSlot(-1),
+ mCurrentBuffer(),
+ mCurrentFence(Fence::NO_FENCE),
+ mHwc(hwc),
+ mHasPendingRelease(false),
+ mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
+ mPreviousBuffer() {
+ ALOGV("Creating for display %" PRIu64, displayId);
mName = "FramebufferSurface";
mConsumer->setConsumerName(mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
- const auto& activeConfig = mHwc.getActiveConfig(disp);
+ const auto& activeConfig = mHwc.getActiveConfig(displayId);
mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
activeConfig->getHeight());
mConsumer->setMaxAcquiredBufferCount(
@@ -142,8 +141,7 @@
mHwcBufferCache.getHwcBuffer(mCurrentBufferSlot, mCurrentBuffer,
&outSlot, &outBuffer);
outDataspace = static_cast<Dataspace>(item.mDataSpace);
- status_t result =
- mHwc.setClientTarget(mDisplayType, outSlot, outFence, outBuffer, outDataspace);
+ status_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace);
if (result != NO_ERROR) {
ALOGE("error posting framebuffer: %d", result);
return result;
@@ -161,7 +159,7 @@
void FramebufferSurface::onFrameCommitted() {
if (mHasPendingRelease) {
- sp<Fence> fence = mHwc.getPresentFence(mDisplayType);
+ sp<Fence> fence = mHwc.getPresentFence(mDisplayId);
if (fence->isValid()) {
status_t result = addReleaseFence(mPreviousBufferSlot,
mPreviousBuffer, fence);
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 0fd8e9e..2431dfd 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_SF_FRAMEBUFFER_SURFACE_H
#define ANDROID_SF_FRAMEBUFFER_SURFACE_H
+#include "DisplayIdentification.h"
#include "DisplaySurface.h"
#include "HWComposerBufferCache.h"
@@ -38,7 +39,8 @@
class FramebufferSurface : public ConsumerBase,
public DisplaySurface {
public:
- FramebufferSurface(HWComposer& hwc, int disp, const sp<IGraphicBufferConsumer>& consumer);
+ FramebufferSurface(HWComposer& hwc, DisplayId displayId,
+ const sp<IGraphicBufferConsumer>& consumer);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -63,8 +65,7 @@
status_t nextBuffer(uint32_t& outSlot, sp<GraphicBuffer>& outBuffer,
sp<Fence>& outFence, ui::Dataspace& outDataspace);
- // mDisplayType must match one of the HWC display types
- int mDisplayType;
+ const DisplayId mDisplayId;
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index b1daf12..4c472b8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -58,15 +58,15 @@
ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
#define LOG_DISPLAY_ERROR(displayId, msg) \
- ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg)
+ ALOGE("%s failed for display %" PRIu64 ": %s", __FUNCTION__, displayId, msg)
-#define LOG_HWC_ERROR(what, error, displayId) \
- ALOGE("%s: %s failed for display %d: %s (%d)", __FUNCTION__, what, displayId, \
+#define LOG_HWC_ERROR(what, error, displayId) \
+ ALOGE("%s: %s failed for display %" PRIu64 ": %s (%d)", __FUNCTION__, what, displayId, \
to_string(error).c_str(), static_cast<int32_t>(error))
#define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
do { \
- if (!isValidDisplay(displayId)) { \
+ if (mDisplayData.count(displayId) == 0) { \
LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
return __VA_ARGS__; \
} \
@@ -118,11 +118,6 @@
return mHwcDevice->getCapabilities().count(capability) > 0;
}
-bool HWComposer::isValidDisplay(int32_t displayId) const {
- return static_cast<size_t>(displayId) < mDisplayData.size() &&
- mDisplayData[displayId].hwcDisplay;
-}
-
void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
bool valid = true;
switch (from) {
@@ -148,52 +143,50 @@
}
}
-std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
- HWC2::Connection connection) {
- if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
- ALOGE("Invalid display type of %d", displayType);
- return {};
- }
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
+ HWC2::Connection connection) {
+ std::optional<DisplayIdentificationInfo> info;
- ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId,
- displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
- to_string(connection).c_str());
- mHwcDevice->onHotplug(hwcDisplayId, connection);
-
- std::optional<DisplayId> displayId;
-
- if (connection == HWC2::Connection::Connected) {
- uint8_t port;
- DisplayIdentificationData data;
- if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
- displayId = generateDisplayId(port, data);
- ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+ if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
+ info = DisplayIdentificationInfo{*displayId, std::string()};
+ } else {
+ if (connection == HWC2::Connection::Disconnected) {
+ ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
+ return {};
}
+
+ info = onHotplugConnect(hwcDisplayId);
+ if (!info) return {};
}
+ ALOGV("%s: %s %s display %" PRIu64 " with HWC ID %" PRIu64, __FUNCTION__,
+ to_string(connection).c_str(),
+ hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external", info->id, hwcDisplayId);
+
+ mHwcDevice->onHotplug(hwcDisplayId, connection);
+
// Disconnect is handled through HWComposer::disconnectDisplay via
// SurfaceFlinger's onHotplugReceived callback handling
if (connection == HWC2::Connection::Connected) {
- mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
- mHwcDisplaySlots[hwcDisplayId] = displayType;
+ mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
+ mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
}
- return displayId;
+ return info;
}
-bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) {
- const auto it = mHwcDisplaySlots.find(hwcDisplayId);
- if (it == mHwcDisplaySlots.end()) {
- LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display");
+bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
+ const auto displayId = toPhysicalDisplayId(hwcDisplayId);
+ if (!displayId) {
+ LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
return false;
}
- const int32_t displayId = it->second;
- RETURN_IF_INVALID_DISPLAY(displayId, false);
+ RETURN_IF_INVALID_DISPLAY(*displayId, false);
- const auto& displayData = mDisplayData[displayId];
+ const auto& displayData = mDisplayData[*displayId];
if (displayData.isVirtual) {
- LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
+ LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
return false;
}
@@ -204,31 +197,26 @@
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
- if (timestamp == mLastHwVSync[displayId]) {
- ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
- timestamp);
+ if (timestamp == mLastHwVSync[*displayId]) {
+ ALOGW("Ignoring duplicate VSYNC event from HWC for display %" PRIu64 " (t=%" PRId64 ")",
+ *displayId, timestamp);
return false;
}
- mLastHwVSync[displayId] = timestamp;
+ mLastHwVSync[*displayId] = timestamp;
}
- if (outDisplayId) {
- *outDisplayId = displayId;
- }
-
- char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId);
- ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1);
+ const auto tag = "HW_VSYNC_" + std::to_string(*displayId);
+ ATRACE_INT(tag.c_str(), ++mVSyncCounts[*displayId] & 1);
return true;
}
-status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format, int32_t *outId) {
+std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
+ ui::PixelFormat* format) {
if (mRemainingHwcVirtualDisplays == 0) {
ALOGE("%s: No remaining virtual displays", __FUNCTION__);
- return NO_MEMORY;
+ return {};
}
if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
@@ -236,41 +224,33 @@
height > SurfaceFlinger::maxVirtualDisplaySize)) {
ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
height, SurfaceFlinger::maxVirtualDisplaySize);
- return INVALID_OPERATION;
+ return {};
}
-
HWC2::Display* display;
auto error = mHwcDevice->createVirtualDisplay(width, height, format,
&display);
if (error != HWC2::Error::None) {
ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
- return NO_MEMORY;
+ return {};
}
- size_t displaySlot = 0;
- if (!mFreeDisplaySlots.empty()) {
- displaySlot = *mFreeDisplaySlots.begin();
- mFreeDisplaySlots.erase(displaySlot);
- } else if (mDisplayData.size() < INT32_MAX) {
- // Don't bother allocating a slot larger than we can return
- displaySlot = mDisplayData.size();
- mDisplayData.resize(displaySlot + 1);
+ DisplayId displayId;
+ if (mFreeVirtualDisplayIds.empty()) {
+ displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
} else {
- ALOGE("%s: Unable to allocate a display slot", __FUNCTION__);
- return NO_MEMORY;
+ displayId = *mFreeVirtualDisplayIds.begin();
+ mFreeVirtualDisplayIds.erase(displayId);
}
- auto& displayData = mDisplayData[displaySlot];
+ auto& displayData = mDisplayData[displayId];
displayData.hwcDisplay = display;
displayData.isVirtual = true;
--mRemainingHwcVirtualDisplays;
- *outId = static_cast<int32_t>(displaySlot);
-
- return NO_ERROR;
+ return displayId;
}
-HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
+HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
auto display = mDisplayData[displayId].hwcDisplay;
@@ -280,7 +260,7 @@
return layer;
}
-void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) {
+void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto display = mDisplayData[displayId].hwcDisplay;
@@ -288,7 +268,8 @@
RETURN_IF_HWC_ERROR(error, displayId);
}
-nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const {
+nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, 0);
// this returns the last refresh timestamp.
// if the last one is not available, we estimate it based on
// the refresh period and whatever closest timestamp we have.
@@ -298,17 +279,17 @@
return now - ((now - mLastHwVSync[displayId]) % vsyncPeriod);
}
-bool HWComposer::isConnected(int32_t displayId) const {
+bool HWComposer::isConnected(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
- return mDisplayData[displayId].hwcDisplay->isConnected();
+ return mDisplayData.at(displayId).hwcDisplay->isConnected();
}
-std::vector<std::shared_ptr<const HWC2::Display::Config>>
- HWComposer::getConfigs(int32_t displayId) const {
+std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
+ DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
- auto& displayData = mDisplayData[displayId];
- auto configs = mDisplayData[displayId].hwcDisplay->getConfigs();
+ const auto& displayData = mDisplayData.at(displayId);
+ auto configs = displayData.hwcDisplay->getConfigs();
if (displayData.configMap.empty()) {
for (size_t i = 0; i < configs.size(); ++i) {
displayData.configMap[i] = configs[i];
@@ -317,12 +298,12 @@
return configs;
}
-std::shared_ptr<const HWC2::Display::Config>
- HWComposer::getActiveConfig(int32_t displayId) const {
+std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
+ DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
std::shared_ptr<const HWC2::Display::Config> config;
- auto error = mDisplayData[displayId].hwcDisplay->getActiveConfig(&config);
+ auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
if (error == HWC2::Error::BadConfig) {
LOG_DISPLAY_ERROR(displayId, "No active config");
return nullptr;
@@ -338,11 +319,11 @@
return config;
}
-int HWComposer::getActiveConfigIndex(int32_t displayId) const {
+int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, -1);
int index;
- auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index);
+ auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
if (error == HWC2::Error::BadConfig) {
LOG_DISPLAY_ERROR(displayId, "No active config");
return -1;
@@ -358,17 +339,17 @@
return index;
}
-std::vector<ui::ColorMode> HWComposer::getColorModes(int32_t displayId) const {
+std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
std::vector<ui::ColorMode> modes;
- auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes);
+ auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
RETURN_IF_HWC_ERROR(error, displayId, {});
return modes;
}
-status_t HWComposer::setActiveColorMode(int32_t displayId, ui::ColorMode mode,
- ui::RenderIntent renderIntent) {
+status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
+ ui::RenderIntent renderIntent) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
@@ -381,8 +362,7 @@
return NO_ERROR;
}
-
-void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) {
+void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
@@ -403,37 +383,30 @@
displayData.vsyncEnabled = enabled;
- char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", displayId);
- ATRACE_INT(tag, enabled == HWC2::Vsync::Enable ? 1 : 0);
+ const auto tag = "HW_VSYNC_ON_" + std::to_string(displayId);
+ ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
}
}
-status_t HWComposer::setClientTarget(int32_t displayId, uint32_t slot,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
- ui::Dataspace dataspace) {
+status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
+ const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
+ ui::Dataspace dataspace) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
- ALOGV("setClientTarget for display %d", displayId);
+ ALOGV("setClientTarget for display %" PRIu64, displayId);
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
return NO_ERROR;
}
-status_t HWComposer::prepare(DisplayDevice& display,
- std::vector<CompositionInfo>& compositionData) {
+status_t HWComposer::prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData) {
ATRACE_CALL();
- Mutex::Autolock _l(mDisplayLock);
- const auto displayId = display.getId();
- if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
- ALOGV("Skipping HWComposer prepare for non-HWC display");
- return NO_ERROR;
- }
-
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ Mutex::Autolock _l(mDisplayLock);
+
auto& displayData = mDisplayData[displayId];
auto& hwcDisplay = displayData.hwcDisplay;
if (!hwcDisplay->isConnected()) {
@@ -503,7 +476,8 @@
changedTypes[&*hwcLayer]);
compositionInfo.compositionType = changedTypes[&*hwcLayer];
compositionInfo.layer->mLayer->setCompositionType(displayId,
- compositionInfo.compositionType, false);
+ compositionInfo.compositionType,
+ false);
}
switch (compositionInfo.compositionType) {
@@ -542,49 +516,48 @@
return NO_ERROR;
}
-bool HWComposer::hasDeviceComposition(int32_t displayId) const {
- if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const {
+ if (!displayId) {
// Displays without a corresponding HWC display are never composed by
// the device
return false;
}
- RETURN_IF_INVALID_DISPLAY(displayId, false);
- return mDisplayData[displayId].hasDeviceComposition;
+ RETURN_IF_INVALID_DISPLAY(*displayId, false);
+ return mDisplayData.at(*displayId).hasDeviceComposition;
}
-bool HWComposer::hasFlipClientTargetRequest(int32_t displayId) const {
- if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const {
+ if (!displayId) {
// Displays without a corresponding HWC display are never composed by
// the device
return false;
}
- RETURN_IF_INVALID_DISPLAY(displayId, false);
- return ((static_cast<uint32_t>(mDisplayData[displayId].displayRequests) &
+ RETURN_IF_INVALID_DISPLAY(*displayId, false);
+ return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) &
static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0);
}
-bool HWComposer::hasClientComposition(int32_t displayId) const {
- if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
+bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const {
+ if (!displayId) {
// Displays without a corresponding HWC display are always composed by
// the client
return true;
}
- RETURN_IF_INVALID_DISPLAY(displayId, true);
- return mDisplayData[displayId].hasClientComposition;
+ RETURN_IF_INVALID_DISPLAY(*displayId, true);
+ return mDisplayData.at(*displayId).hasClientComposition;
}
-sp<Fence> HWComposer::getPresentFence(int32_t displayId) const {
+sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
- return mDisplayData[displayId].lastPresentFence;
+ return mDisplayData.at(displayId).lastPresentFence;
}
-sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
- HWC2::Layer* layer) const {
+sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
- auto displayFences = mDisplayData[displayId].releaseFences;
+ auto displayFences = mDisplayData.at(displayId).releaseFences;
if (displayFences.count(layer) == 0) {
ALOGV("getLayerReleaseFence: Release fence not found");
return Fence::NO_FENCE;
@@ -592,7 +565,7 @@
return displayFences[layer];
}
-status_t HWComposer::presentAndGetReleaseFences(int32_t displayId) {
+status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
ATRACE_CALL();
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
@@ -620,8 +593,7 @@
return NO_ERROR;
}
-status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) {
- ALOGV("setPowerMode(%d, %d)", displayId, intMode);
+status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto& displayData = mDisplayData[displayId];
@@ -677,7 +649,7 @@
return NO_ERROR;
}
-status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) {
+status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
@@ -691,8 +663,7 @@
return NO_ERROR;
}
-status_t HWComposer::setColorTransform(int32_t displayId,
- const mat4& transform) {
+status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& displayData = mDisplayData[displayId];
@@ -704,26 +675,34 @@
return NO_ERROR;
}
-void HWComposer::disconnectDisplay(int32_t displayId) {
+void HWComposer::disconnectDisplay(DisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
// If this was a virtual display, add its slot back for reuse by future
// virtual displays
if (displayData.isVirtual) {
- mFreeDisplaySlots.insert(displayId);
+ mFreeVirtualDisplayIds.insert(displayId);
++mRemainingHwcVirtualDisplays;
}
const auto hwcDisplayId = displayData.hwcDisplay->getId();
- mHwcDisplaySlots.erase(hwcDisplayId);
- displayData = DisplayData();
+ mPhysicalDisplayIdMap.erase(hwcDisplayId);
+ mDisplayData.erase(displayId);
+ mVSyncCounts.erase(displayId);
+
+ // TODO(b/74619554): Select internal/external display from remaining displays.
+ if (hwcDisplayId == mInternalHwcDisplayId) {
+ mInternalHwcDisplayId.reset();
+ } else if (hwcDisplayId == mExternalHwcDisplayId) {
+ mExternalHwcDisplayId.reset();
+ }
mHwcDevice->destroyDisplay(hwcDisplayId);
}
-status_t HWComposer::setOutputBuffer(int32_t displayId,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buffer) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
const auto& displayData = mDisplayData[displayId];
@@ -737,13 +716,12 @@
return NO_ERROR;
}
-void HWComposer::clearReleaseFences(int32_t displayId) {
+void HWComposer::clearReleaseFences(DisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId);
mDisplayData[displayId].releaseFences.clear();
}
-status_t HWComposer::getHdrCapabilities(
- int32_t displayId, HdrCapabilities* outCapabilities) {
+status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
@@ -752,22 +730,22 @@
return NO_ERROR;
}
-int32_t HWComposer::getSupportedPerFrameMetadata(int32_t displayId) const {
+int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
- return mDisplayData[displayId].hwcDisplay->getSupportedPerFrameMetadata();
+ return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
}
-std::vector<ui::RenderIntent> HWComposer::getRenderIntents(int32_t displayId,
- ui::ColorMode colorMode) const {
+std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
+ ui::ColorMode colorMode) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
std::vector<ui::RenderIntent> renderIntents;
- auto error = mDisplayData[displayId].hwcDisplay->getRenderIntents(colorMode, &renderIntents);
+ auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
RETURN_IF_HWC_ERROR(error, displayId, {});
return renderIntents;
}
-mat4 HWComposer::getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace) {
+mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
RETURN_IF_INVALID_DISPLAY(displayId, {});
mat4 matrix;
@@ -808,12 +786,67 @@
result.append(mHwcDevice->dump().c_str());
}
-std::optional<hwc2_display_t>
-HWComposer::getHwcDisplayId(int32_t displayId) const {
- if (!isValidDisplay(displayId)) {
+std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
+ if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
+ it != mPhysicalDisplayIdMap.end()) {
+ return it->second;
+ }
+ return {};
+}
+
+std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
+ if (const auto it = mDisplayData.find(displayId);
+ it != mDisplayData.end() && !it->second.isVirtual) {
+ return it->second.hwcDisplay->getId();
+ }
+ return {};
+}
+
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+ if (isUsingVrComposer() && mInternalHwcDisplayId) {
+ ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
return {};
}
- return mDisplayData[displayId].hwcDisplay->getId();
+
+ uint8_t port;
+ DisplayIdentificationData data;
+ const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data);
+
+ if (mPhysicalDisplayIdMap.empty()) {
+ mHasMultiDisplaySupport = hasMultiDisplaySupport;
+ ALOGI("Switching to %s multi-display mode",
+ hasMultiDisplaySupport ? "generalized" : "legacy");
+ } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) {
+ ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
+ hwcDisplayId);
+ return {};
+ }
+
+ std::optional<DisplayIdentificationInfo> info;
+
+ if (mHasMultiDisplaySupport) {
+ info = parseDisplayIdentificationData(port, data);
+ ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId);
+ } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) {
+ ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
+ return {};
+ } else {
+ ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64,
+ hwcDisplayId);
+ port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY;
+ }
+
+ if (!mInternalHwcDisplayId) {
+ mInternalHwcDisplayId = hwcDisplayId;
+ } else if (!mExternalHwcDisplayId) {
+ mExternalHwcDisplayId = hwcDisplayId;
+ }
+
+ if (info) return info;
+
+ return DisplayIdentificationInfo{getFallbackDisplayId(port),
+ hwcDisplayId == mInternalHwcDisplayId ? "Internal display"
+ : "External display"};
}
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5aa7185..5074c2c 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -34,7 +34,8 @@
#include <memory>
#include <optional>
-#include <set>
+#include <unordered_map>
+#include <unordered_set>
#include <vector>
#include "DisplayIdentification.h"
@@ -82,101 +83,94 @@
bool hasCapability(HWC2::Capability capability) const;
- // Attempts to allocate a virtual display. If the virtual display is created
- // on the HWC device, outId will contain its HWC ID.
- status_t allocateVirtualDisplay(uint32_t width, uint32_t height,
- ui::PixelFormat* format, int32_t* outId);
+ // Attempts to allocate a virtual display and returns its ID if created on the HWC device.
+ std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
+ ui::PixelFormat* format);
// Attempts to create a new layer on this display
- HWC2::Layer* createLayer(int32_t displayId);
+ HWC2::Layer* createLayer(DisplayId displayId);
// Destroy a previously created layer
- void destroyLayer(int32_t displayId, HWC2::Layer* layer);
+ void destroyLayer(DisplayId displayId, HWC2::Layer* layer);
// Asks the HAL what it can do
- status_t prepare(DisplayDevice& display,
- std::vector<CompositionInfo>& compositionData);
+ status_t prepare(DisplayId displayId, std::vector<CompositionInfo>& compositionData);
- status_t setClientTarget(int32_t displayId, uint32_t slot,
- const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& target, ui::Dataspace dataspace);
+ status_t setClientTarget(DisplayId displayId, uint32_t slot, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& target, ui::Dataspace dataspace);
// Present layers to the display and read releaseFences.
- status_t presentAndGetReleaseFences(int32_t displayId);
+ status_t presentAndGetReleaseFences(DisplayId displayId);
// set power mode
- status_t setPowerMode(int32_t displayId, int mode);
+ status_t setPowerMode(DisplayId displayId, int mode);
// set active config
- status_t setActiveConfig(int32_t displayId, size_t configId);
+ status_t setActiveConfig(DisplayId displayId, size_t configId);
// Sets a color transform to be applied to the result of composition
- status_t setColorTransform(int32_t displayId, const mat4& transform);
+ status_t setColorTransform(DisplayId displayId, const mat4& transform);
// reset state when an external, non-virtual display is disconnected
- void disconnectDisplay(int32_t displayId);
+ void disconnectDisplay(DisplayId displayId);
// does this display have layers handled by HWC
- bool hasDeviceComposition(int32_t displayId) const;
+ bool hasDeviceComposition(const std::optional<DisplayId>& displayId) const;
// does this display have pending request to flip client target
- bool hasFlipClientTargetRequest(int32_t displayId) const;
+ bool hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const;
// does this display have layers handled by GLES
- bool hasClientComposition(int32_t displayId) const;
+ bool hasClientComposition(const std::optional<DisplayId>& displayId) const;
// get the present fence received from the last call to present.
- sp<Fence> getPresentFence(int32_t displayId) const;
+ sp<Fence> getPresentFence(DisplayId displayId) const;
// Get last release fence for the given layer
- sp<Fence> getLayerReleaseFence(int32_t displayId,
- HWC2::Layer* layer) const;
+ sp<Fence> getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
- status_t setOutputBuffer(int32_t displayId, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& buf);
+ status_t setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
+ const sp<GraphicBuffer>& buffer);
// After SurfaceFlinger has retrieved the release fences for all the frames,
// it can call this to clear the shared pointers in the release fence map
- void clearReleaseFences(int32_t displayId);
+ void clearReleaseFences(DisplayId displayId);
// Fetches the HDR capabilities of the given display
- status_t getHdrCapabilities(int32_t displayId, HdrCapabilities* outCapabilities);
+ status_t getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities);
- int32_t getSupportedPerFrameMetadata(int32_t displayId) const;
+ int32_t getSupportedPerFrameMetadata(DisplayId displayId) const;
// Returns the available RenderIntent of the given display.
- std::vector<ui::RenderIntent> getRenderIntents(int32_t displayId, ui::ColorMode colorMode) const;
+ std::vector<ui::RenderIntent> getRenderIntents(DisplayId displayId,
+ ui::ColorMode colorMode) const;
- mat4 getDataspaceSaturationMatrix(int32_t displayId, ui::Dataspace dataspace);
+ mat4 getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace);
// Events handling ---------------------------------------------------------
- // Returns true if successful, false otherwise. The
- // DisplayDevice::DisplayType of the display is returned as an output param.
- bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay);
- std::optional<DisplayId> onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
- HWC2::Connection connection);
+ // Returns stable display ID (and display name on connection of new or previously disconnected
+ // display), or std::nullopt if hotplug event was ignored.
+ std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
+ HWC2::Connection connection);
- void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
+ bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp);
+ void setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled);
- // Query display parameters. Pass in a display index (e.g.
- // HWC_DISPLAY_PRIMARY).
- nsecs_t getRefreshTimestamp(int32_t displayId) const;
- bool isConnected(int32_t displayId) const;
+ nsecs_t getRefreshTimestamp(DisplayId displayId) const;
+ bool isConnected(DisplayId displayId) const;
// Non-const because it can update configMap inside of mDisplayData
- std::vector<std::shared_ptr<const HWC2::Display::Config>>
- getConfigs(int32_t displayId) const;
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> getConfigs(DisplayId displayId) const;
- std::shared_ptr<const HWC2::Display::Config>
- getActiveConfig(int32_t displayId) const;
- int getActiveConfigIndex(int32_t displayId) const;
+ std::shared_ptr<const HWC2::Display::Config> getActiveConfig(DisplayId displayId) const;
+ int getActiveConfigIndex(DisplayId displayId) const;
- std::vector<ui::ColorMode> getColorModes(int32_t displayId) const;
+ std::vector<ui::ColorMode> getColorModes(DisplayId displayId) const;
- status_t setActiveColorMode(int32_t displayId, ui::ColorMode mode,
- ui::RenderIntent renderIntent);
+ status_t setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
+ ui::RenderIntent renderIntent);
bool isUsingVrComposer() const;
@@ -185,12 +179,19 @@
android::Hwc2::Composer* getComposer() const { return mHwcDevice->getComposer(); }
- std::optional<hwc2_display_t> getHwcDisplayId(int32_t displayId) const;
+ // TODO(b/74619554): Remove special cases for internal/external display.
+ std::optional<hwc2_display_t> getInternalHwcDisplayId() const { return mInternalHwcDisplayId; }
+ std::optional<hwc2_display_t> getExternalHwcDisplayId() const { return mExternalHwcDisplayId; }
+
+ std::optional<DisplayId> toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const;
+ std::optional<hwc2_display_t> fromPhysicalDisplayId(DisplayId displayId) const;
+
private:
// For unit tests
friend TestableSurfaceFlinger;
- bool isValidDisplay(int32_t displayId) const;
+ std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
+
static void validateChange(HWC2::Composition from, HWC2::Composition to);
struct cb_context;
@@ -215,25 +216,30 @@
HWC2::Error presentError;
};
- std::vector<DisplayData> mDisplayData{HWC_NUM_PHYSICAL_DISPLAY_TYPES};
+ std::unordered_map<DisplayId, DisplayData> mDisplayData;
// This must be destroyed before mDisplayData, because destructor may call back into HWComposer
// and look up DisplayData.
std::unique_ptr<HWC2::Device> mHwcDevice;
- std::set<size_t> mFreeDisplaySlots;
- std::unordered_map<hwc2_display_t, int32_t> mHwcDisplaySlots;
+ std::unordered_map<hwc2_display_t, DisplayId> mPhysicalDisplayIdMap;
+ std::optional<hwc2_display_t> mInternalHwcDisplayId;
+ std::optional<hwc2_display_t> mExternalHwcDisplayId;
+ bool mHasMultiDisplaySupport = false;
+
// protect mDisplayData from races between prepare and dump
mutable Mutex mDisplayLock;
cb_context* mCBContext = nullptr;
- size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES]{0, 0};
+ std::unordered_map<DisplayId, size_t> mVSyncCounts;
+
+ std::unordered_set<uint32_t> mFreeVirtualDisplayIds;
+ uint32_t mNextVirtualDisplayId = 0;
uint32_t mRemainingHwcVirtualDisplays{mHwcDevice->getMaxVirtualDisplayCount()};
// protected by mLock
mutable Mutex mLock;
- mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync{
- {{HWC_DISPLAY_PRIMARY, 0}, {HWC_DISPLAY_EXTERNAL, 0}}};
+ mutable std::unordered_map<DisplayId, nsecs_t> mLastHwVSync;
// thread-safe
mutable Mutex mVsyncLock;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index c111a27..27d3dc5 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -48,34 +48,34 @@
}
}
-VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
- const sp<IGraphicBufferProducer>& sink,
- const sp<IGraphicBufferProducer>& bqProducer,
- const sp<IGraphicBufferConsumer>& bqConsumer,
- const std::string& name)
-: ConsumerBase(bqConsumer),
- mHwc(hwc),
- mDisplayId(dispId),
- mDisplayName(name),
- mSource{},
- mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
- mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
- mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
- mProducerSlotSource(0),
- mProducerBuffers(),
- mQueueBufferOutput(),
- mSinkBufferWidth(0),
- mSinkBufferHeight(0),
- mCompositionType(COMPOSITION_UNKNOWN),
- mFbFence(Fence::NO_FENCE),
- mOutputFence(Fence::NO_FENCE),
- mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
- mDbgState(DBG_STATE_IDLE),
- mDbgLastCompositionType(COMPOSITION_UNKNOWN),
- mMustRecompose(false),
- mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv)
-{
+VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc,
+ const std::optional<DisplayId>& displayId,
+ const sp<IGraphicBufferProducer>& sink,
+ const sp<IGraphicBufferProducer>& bqProducer,
+ const sp<IGraphicBufferConsumer>& bqConsumer,
+ const std::string& name)
+ : ConsumerBase(bqConsumer),
+ mHwc(hwc),
+ mDisplayId(displayId),
+ mDisplayName(name),
+ mSource{},
+ mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+ mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+ mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
+ mProducerSlotSource(0),
+ mProducerBuffers(),
+ mQueueBufferOutput(),
+ mSinkBufferWidth(0),
+ mSinkBufferHeight(0),
+ mCompositionType(COMPOSITION_UNKNOWN),
+ mFbFence(Fence::NO_FENCE),
+ mOutputFence(Fence::NO_FENCE),
+ mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
+ mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
+ mDbgState(DBG_STATE_IDLE),
+ mDbgLastCompositionType(COMPOSITION_UNKNOWN),
+ mMustRecompose(false),
+ mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
mSource[SOURCE_SINK] = sink;
mSource[SOURCE_SCRATCH] = bqProducer;
@@ -116,8 +116,9 @@
}
status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return NO_ERROR;
+ }
mMustRecompose = mustRecompose;
@@ -129,8 +130,9 @@
}
status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return NO_ERROR;
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN,
"Unexpected prepareFrame() in %s state", dbgStateStr());
@@ -177,8 +179,9 @@
}
status_t VirtualDisplaySurface::advanceFrame() {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return NO_ERROR;
+ }
if (mCompositionType == COMPOSITION_HWC) {
VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
@@ -211,7 +214,7 @@
// At this point we know the output buffer acquire fence,
// so update HWC state with it.
- mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer);
+ mHwc.setOutputBuffer(*mDisplayId, mOutputFence, outBuffer);
status_t result = NO_ERROR;
if (fbBuffer != nullptr) {
@@ -221,22 +224,23 @@
&hwcSlot, &hwcBuffer);
// TODO: Correctly propagate the dataspace from GL composition
- result = mHwc.setClientTarget(mDisplayId, hwcSlot, mFbFence,
- hwcBuffer, ui::Dataspace::UNKNOWN);
+ result = mHwc.setClientTarget(*mDisplayId, hwcSlot, mFbFence, hwcBuffer,
+ ui::Dataspace::UNKNOWN);
}
return result;
}
void VirtualDisplaySurface::onFrameCommitted() {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return;
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
"Unexpected onFrameCommitted() in %s state", dbgStateStr());
mDbgState = DBG_STATE_IDLE;
- sp<Fence> retireFence = mHwc.getPresentFence(mDisplayId);
+ sp<Fence> retireFence = mHwc.getPresentFence(*mDisplayId);
if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
// release the scratch buffer back to the pool
Mutex::Autolock lock(mMutex);
@@ -291,8 +295,9 @@
status_t VirtualDisplaySurface::requestBuffer(int pslot,
sp<GraphicBuffer>* outBuf) {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return mSource[SOURCE_SINK]->requestBuffer(pslot, outBuf);
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected requestBuffer pslot=%d in %s state",
@@ -313,7 +318,7 @@
status_t VirtualDisplaySurface::dequeueBuffer(Source source,
PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
- LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
+ LOG_FATAL_IF(!mDisplayId);
status_t result =
mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
@@ -359,7 +364,7 @@
PixelFormat format, uint64_t usage,
uint64_t* outBufferAge,
FrameEventHistoryDelta* outTimestamps) {
- if (mDisplayId < 0) {
+ if (!mDisplayId) {
return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage, outBufferAge,
outTimestamps);
}
@@ -446,8 +451,9 @@
status_t VirtualDisplaySurface::queueBuffer(int pslot,
const QueueBufferInput& input, QueueBufferOutput* output) {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return mSource[SOURCE_SINK]->queueBuffer(pslot, input, output);
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected queueBuffer(pslot=%d) in %s state", pslot,
@@ -504,8 +510,9 @@
status_t VirtualDisplaySurface::cancelBuffer(int pslot,
const sp<Fence>& fence) {
- if (mDisplayId < 0)
+ if (!mDisplayId) {
return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
+ }
VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
"Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
@@ -616,6 +623,8 @@
}
status_t VirtualDisplaySurface::refreshOutputBuffer() {
+ LOG_FATAL_IF(!mDisplayId);
+
if (mOutputProducerSlot >= 0) {
mSource[SOURCE_SINK]->cancelBuffer(
mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot),
@@ -633,8 +642,8 @@
// until after GLES calls queueBuffer(). So here we just set the buffer
// (for use in HWC prepare) but not the fence; we'll call this again with
// the proper fence once we have it.
- result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE,
- mProducerBuffers[mOutputProducerSlot]);
+ result = mHwc.setOutputBuffer(*mDisplayId, Fence::NO_FENCE,
+ mProducerBuffers[mOutputProducerSlot]);
return result;
}
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 4bd4d0f..33678df 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -17,8 +17,10 @@
#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+#include <optional>
#include <string>
+#include "DisplayIdentification.h"
#include "DisplaySurface.h"
#include "HWComposerBufferCache.h"
@@ -75,11 +77,10 @@
public BnGraphicBufferProducer,
private ConsumerBase {
public:
- VirtualDisplaySurface(HWComposer& hwc, int32_t dispId,
- const sp<IGraphicBufferProducer>& sink,
- const sp<IGraphicBufferProducer>& bqProducer,
- const sp<IGraphicBufferConsumer>& bqConsumer,
- const std::string& name);
+ VirtualDisplaySurface(HWComposer& hwc, const std::optional<DisplayId>& displayId,
+ const sp<IGraphicBufferProducer>& sink,
+ const sp<IGraphicBufferProducer>& bqProducer,
+ const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
//
// DisplaySurface interface
@@ -154,7 +155,7 @@
// Immutable after construction
//
HWComposer& mHwc;
- const int32_t mDisplayId;
+ const std::optional<DisplayId> mDisplayId;
const std::string mDisplayName;
sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
uint32_t mDefaultOutputFormat;