Loading services/surfaceflinger/DisplayHardware/HWC2.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ Device::Device(hwc2_device_t* device) mDestroyLayer(nullptr), mGetActiveConfig(nullptr), mGetChangedCompositionTypes(nullptr), mGetColorModes(nullptr), mGetDisplayAttribute(nullptr), mGetDisplayConfigs(nullptr), mGetDisplayName(nullptr), Loading @@ -107,6 +108,7 @@ Device::Device(hwc2_device_t* device) mPresentDisplay(nullptr), mSetActiveConfig(nullptr), mSetClientTarget(nullptr), mSetColorMode(nullptr), mSetColorTransform(nullptr), mSetOutputBuffer(nullptr), mSetPowerMode(nullptr), Loading Loading @@ -339,6 +341,8 @@ void Device::loadFunctionPointers() mGetActiveConfig)) return; if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes, mGetChangedCompositionTypes)) return; if (!loadFunctionPointer(FunctionDescriptor::GetColorModes, mGetColorModes)) return; if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute, mGetDisplayAttribute)) return; if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs, Loading @@ -361,6 +365,8 @@ void Device::loadFunctionPointers() mSetActiveConfig)) return; if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget, mSetClientTarget)) return; if (!loadFunctionPointer(FunctionDescriptor::SetColorMode, mSetColorMode)) return; if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform, mSetColorTransform)) return; if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer, Loading Loading @@ -557,6 +563,28 @@ Error Display::getChangedCompositionTypes( return Error::None; } Error Display::getColorModes(std::vector<int32_t>* outModes) const { uint32_t numModes = 0; int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes, nullptr); auto error = static_cast<Error>(intError); if (error != Error::None) { return error; } std::vector<int32_t> modes(numModes); intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes, modes.data()); error = static_cast<Error>(intError); if (error != Error::None) { return error; } std::swap(*outModes, modes); return Error::None; } std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const { std::vector<std::shared_ptr<const Config>> configs; Loading Loading @@ -758,6 +786,12 @@ Error Display::setClientTarget(buffer_handle_t target, return static_cast<Error>(intError); } Error Display::setColorMode(int32_t mode) { int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode); return static_cast<Error>(intError); } Error Display::setColorTransform(const android::mat4& matrix, android_color_transform_t hint) { Loading services/surfaceflinger/DisplayHardware/HWC2.h +5 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ private: HWC2_PFN_DESTROY_LAYER mDestroyLayer; HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig; HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes; HWC2_PFN_GET_COLOR_MODES mGetColorModes; HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute; HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs; HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName; Loading @@ -155,6 +156,7 @@ private: HWC2_PFN_PRESENT_DISPLAY mPresentDisplay; HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig; HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget; HWC2_PFN_SET_COLOR_MODE mSetColorMode; HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform; HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer; HWC2_PFN_SET_POWER_MODE mSetPowerMode; Loading Loading @@ -276,6 +278,8 @@ public: std::shared_ptr<const Config>* outConfig) const; [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector<int32_t>* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector<std::shared_ptr<const Config>> getConfigs() const; Loading @@ -300,6 +304,7 @@ public: buffer_handle_t target, const android::sp<android::Fence>& acquireFence, android_dataspace_t dataspace); [[clang::warn_unused_result]] Error setColorMode(int32_t mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( Loading services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp +323 −53 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ static hwc2_function_pointer_t asFP(T function) using namespace HWC2; static constexpr Attribute ColorTransform = static_cast<Attribute>(6); namespace android { void HWC2On1Adapter::DisplayContentsDeleter::operator()( Loading Loading @@ -214,6 +216,10 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( displayHook<decltype(&Display::getChangedCompositionTypes), &Display::getChangedCompositionTypes, uint32_t*, hwc2_layer_t*, int32_t*>); case FunctionDescriptor::GetColorModes: return asFP<HWC2_PFN_GET_COLOR_MODES>( displayHook<decltype(&Display::getColorModes), &Display::getColorModes, uint32_t*, int32_t*>); case FunctionDescriptor::GetDisplayAttribute: return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>( getDisplayAttributeHook); Loading Loading @@ -261,6 +267,10 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( displayHook<decltype(&Display::setClientTarget), &Display::setClientTarget, buffer_handle_t, int32_t, int32_t>); case FunctionDescriptor::SetColorMode: return asFP<HWC2_PFN_SET_COLOR_MODE>( displayHook<decltype(&Display::setColorMode), &Display::setColorMode, int32_t>); case FunctionDescriptor::SetColorTransform: return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook); case FunctionDescriptor::SetOutputBuffer: Loading Loading @@ -686,6 +696,22 @@ Error HWC2On1Adapter::Display::getChangedCompositionTypes( return Error::None; } Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, int32_t* outModes) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!outModes) { *outNumModes = mColorModes.size(); return Error::None; } uint32_t numModes = std::min(*outNumModes, static_cast<uint32_t>(mColorModes.size())); std::copy_n(mColorModes.cbegin(), numModes, outModes); *outNumModes = numModes; return Error::None; } Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigs) { Loading Loading @@ -832,14 +858,27 @@ Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) if (!config) { return Error::BadConfig; } mActiveConfig = config; if (config == mActiveConfig) { return Error::None; } if (mDevice.mHwc1MinorVersion >= 4) { int error = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, static_cast<int>(configId)); ALOGE_IF(error != 0, "setActiveConfig: Failed to set active config on HWC1 (%d)", error); uint32_t hwc1Id = 0; auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id); if (error != Error::None) { return error; } int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, static_cast<int>(hwc1Id)); if (intError != 0) { ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", intError); return Error::BadConfig; } mActiveConfig = config; } return Error::None; } Loading @@ -855,6 +894,38 @@ Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, return Error::None; } Error HWC2On1Adapter::Display::setColorMode(int32_t mode) { std::unique_lock<std::recursive_mutex> lock (mStateMutex); ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); if (mode == mActiveColorMode) { return Error::None; } if (mColorModes.count(mode) == 0) { ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode); return Error::Unsupported; } uint32_t hwc1Config = 0; auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config); if (error != Error::None) { return error; } ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config); int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, hwc1Config); if (intError != 0) { ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError); return Error::Unsupported; } mActiveColorMode = mode; return Error::None; } Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); Loading Loading @@ -1017,7 +1088,17 @@ Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) return Error::None; } static constexpr uint32_t ATTRIBUTES[] = { static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_DPI_X, HWC_DISPLAY_DPI_Y, HWC_DISPLAY_COLOR_TRANSFORM, HWC_DISPLAY_NO_ATTRIBUTE, }; static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, Loading @@ -1025,9 +1106,23 @@ static constexpr uint32_t ATTRIBUTES[] = { HWC_DISPLAY_DPI_Y, HWC_DISPLAY_NO_ATTRIBUTE, }; static constexpr size_t NUM_ATTRIBUTES = sizeof(ATTRIBUTES) / sizeof(uint32_t); static constexpr uint32_t ATTRIBUTE_MAP[] = { static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR = sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t); static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR), "Attribute tables have unexpected sizes"); static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = { 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, 1, // HWC_DISPLAY_WIDTH = 2, 2, // HWC_DISPLAY_HEIGHT = 3, 3, // HWC_DISPLAY_DPI_X = 4, 4, // HWC_DISPLAY_DPI_Y = 5, 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6, }; static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = { 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, 1, // HWC_DISPLAY_WIDTH = 2, Loading @@ -1039,7 +1134,14 @@ static constexpr uint32_t ATTRIBUTE_MAP[] = { template <uint32_t attribute> static constexpr bool attributesMatch() { return ATTRIBUTES[ATTRIBUTE_MAP[attribute]] == attribute; bool match = (attribute == ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]); if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) { return match; } return match && (attribute == ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]); } static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(), "Tables out of sync"); Loading @@ -1047,6 +1149,8 @@ static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(), "Tables out of sync"); void HWC2On1Adapter::Display::populateConfigs() { Loading @@ -1067,52 +1171,74 @@ void HWC2On1Adapter::Display::populateConfigs() for (size_t c = 0; c < numConfigs; ++c) { uint32_t hwc1ConfigId = configs[c]; hwc2_config_t id = static_cast<hwc2_config_t>(mConfigs.size()); mConfigs.emplace_back( std::make_shared<Config>(*this, id, hwc1ConfigId)); auto& config = mConfigs[id]; int32_t values[NUM_ATTRIBUTES] = {}; mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES, values); config->setAttribute(Attribute::VsyncPeriod, values[ATTRIBUTE_MAP[HWC_DISPLAY_VSYNC_PERIOD]]); config->setAttribute(Attribute::Width, values[ATTRIBUTE_MAP[HWC_DISPLAY_WIDTH]]); config->setAttribute(Attribute::Height, values[ATTRIBUTE_MAP[HWC_DISPLAY_HEIGHT]]); config->setAttribute(Attribute::DpiX, values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_X]]); config->setAttribute(Attribute::DpiY, values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_Y]]); ALOGV("Found config: %s", config->toString().c_str()); } ALOGV("Getting active config"); if (mDevice.mHwc1Device->getActiveConfig != nullptr) { auto activeConfig = mDevice.mHwc1Device->getActiveConfig( mDevice.mHwc1Device, mHwc1Id); if (activeConfig >= 0) { ALOGV("Setting active config to %d", activeConfig); mActiveConfig = mConfigs[activeConfig]; auto newConfig = std::make_shared<Config>(*this); int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {}; bool hasColor = true; auto result = mDevice.mHwc1Device->getDisplayAttributes( mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITH_COLOR, values); if (result != 0) { mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values); hasColor = false; } auto attributeMap = hasColor ? ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR; newConfig->setAttribute(Attribute::VsyncPeriod, values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]); newConfig->setAttribute(Attribute::Width, values[attributeMap[HWC_DISPLAY_WIDTH]]); newConfig->setAttribute(Attribute::Height, values[attributeMap[HWC_DISPLAY_HEIGHT]]); newConfig->setAttribute(Attribute::DpiX, values[attributeMap[HWC_DISPLAY_DPI_X]]); newConfig->setAttribute(Attribute::DpiY, values[attributeMap[HWC_DISPLAY_DPI_Y]]); if (hasColor) { newConfig->setAttribute(ColorTransform, values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); } // We can only do this after attempting to read the color transform newConfig->setHwc1Id(hwc1ConfigId); for (auto& existingConfig : mConfigs) { if (existingConfig->merge(*newConfig)) { ALOGV("Merged config %d with existing config %u: %s", hwc1ConfigId, existingConfig->getId(), existingConfig->toString().c_str()); newConfig.reset(); break; } } else { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; } // If it wasn't merged with any existing config, add it to the end if (newConfig) { newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size())); ALOGV("Found new config %u: %s", newConfig->getId(), newConfig->toString().c_str()); mConfigs.emplace_back(std::move(newConfig)); } } initializeActiveConfig(); populateColorModes(); } void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); mConfigs.emplace_back(std::make_shared<Config>(*this, 0, 0)); mConfigs.emplace_back(std::make_shared<Config>(*this)); auto& config = mConfigs[0]; config->setAttribute(Attribute::Width, static_cast<int32_t>(width)); config->setAttribute(Attribute::Height, static_cast<int32_t>(height)); config->setHwc1Id(0); config->setId(0); mActiveConfig = config; } Loading Loading @@ -1496,17 +1622,23 @@ std::string HWC2On1Adapter::Display::dump() const output << "Power mode: " << to_string(mPowerMode) << " "; output << "Vsync: " << to_string(mVsyncEnabled) << '\n'; output << " " << mConfigs.size() << " Config" << (mConfigs.size() == 1 ? "" : "s") << " (* Active)\n"; for (const auto& config : mConfigs) { if (config == mActiveConfig) { output << " * " << config->toString(); output << " Color modes [active]:"; for (const auto& mode : mColorModes) { if (mode == mActiveColorMode) { output << " [" << mode << ']'; } else { output << " " << config->toString(); output << " " << mode; } } output << '\n'; output << " " << mConfigs.size() << " Config" << (mConfigs.size() == 1 ? "" : "s") << " (* active)\n"; for (const auto& config : mConfigs) { output << (config == mActiveConfig ? " * " : " "); output << config->toString(true) << '\n'; } output << " " << mLayers.size() << " Layer" << (mLayers.size() == 1 ? "" : "s") << '\n'; for (const auto& layer : mLayers) { Loading Loading @@ -1544,15 +1676,85 @@ int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const return mAttributes.at(attribute); } std::string HWC2On1Adapter::Display::Config::toString() const void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { int32_t colorTransform = getAttribute(ColorTransform); mHwc1Ids.emplace(colorTransform, id); } bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { return true; } } return false; } int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( uint32_t id) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { return idPair.first; } } return -1; } Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode, uint32_t* outId) const { for (const auto& idPair : mHwc1Ids) { if (mode == idPair.first) { *outId = idPair.second; return Error::None; } } ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId); return Error::BadParameter; } bool HWC2On1Adapter::Display::Config::merge(const Config& other) { auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, HWC2::Attribute::DpiY}; for (auto attribute : attributes) { if (getAttribute(attribute) != other.getAttribute(attribute)) { return false; } } int32_t otherColorTransform = other.getAttribute(ColorTransform); if (mHwc1Ids.count(otherColorTransform) != 0) { ALOGE("Attempted to merge two configs (%u and %u) which appear to be " "identical", mHwc1Ids.at(otherColorTransform), other.mHwc1Ids.at(otherColorTransform)); return false; } mHwc1Ids.emplace(otherColorTransform, other.mHwc1Ids.at(otherColorTransform)); return true; } std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const { std::set<int32_t> colorTransforms; for (const auto& idPair : mHwc1Ids) { colorTransforms.emplace(idPair.first); } return colorTransforms; } std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { std::string output; const size_t BUFFER_SIZE = 100; char buffer[BUFFER_SIZE] = {}; auto writtenBytes = snprintf(buffer, BUFFER_SIZE, "[%u] %u x %u", mHwcId, mAttributes.at(HWC2::Attribute::Width), "%u x %u", mAttributes.at(HWC2::Attribute::Width), mAttributes.at(HWC2::Attribute::Height)); output.append(buffer, writtenBytes); Loading @@ -1573,6 +1775,31 @@ std::string HWC2On1Adapter::Display::Config::toString() const output.append(buffer, writtenBytes); } std::memset(buffer, 0, BUFFER_SIZE); if (splitLine) { writtenBytes = snprintf(buffer, BUFFER_SIZE, "\n HWC1 ID/Color transform:"); } else { writtenBytes = snprintf(buffer, BUFFER_SIZE, ", HWC1 ID/Color transform:"); } output.append(buffer, writtenBytes); for (const auto& id : mHwc1Ids) { int32_t colorTransform = id.first; uint32_t hwc1Id = id.second; std::memset(buffer, 0, BUFFER_SIZE); if (colorTransform == mDisplay.mActiveColorMode) { writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, colorTransform); } else { writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, colorTransform); } output.append(buffer, writtenBytes); } return output; } Loading @@ -1585,6 +1812,49 @@ std::shared_ptr<const HWC2On1Adapter::Display::Config> return mConfigs[configId]; } void HWC2On1Adapter::Display::populateColorModes() { mColorModes = mConfigs[0]->getColorTransforms(); for (const auto& config : mConfigs) { std::set<int32_t> intersection; auto configModes = config->getColorTransforms(); std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), configModes.cbegin(), configModes.cend(), std::inserter(intersection, intersection.begin())); std::swap(intersection, mColorModes); } } void HWC2On1Adapter::Display::initializeActiveConfig() { if (mDevice.mHwc1Device->getActiveConfig == nullptr) { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; mActiveColorMode = -1; return; } auto activeConfig = mDevice.mHwc1Device->getActiveConfig( mDevice.mHwc1Device, mHwc1Id); if (activeConfig >= 0) { for (const auto& config : mConfigs) { if (config->hasHwc1Id(activeConfig)) { ALOGV("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); mActiveConfig = config; mActiveColorMode = config->getColorModeForHwc1Id(activeConfig); break; } } if (!mActiveConfig) { ALOGV("Unable to find active HWC1 config %u, defaulting to " "config 0", activeConfig); mActiveConfig = mConfigs[0]; mActiveColorMode = -1; } } } void HWC2On1Adapter::Display::reallocateHwc1Contents() { // Allocate an additional layer for the framebuffer target Loading services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h +31 −9 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ private: HWC2::Attribute attribute, int32_t* outValue); HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes); HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); HWC2::Error getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigIds); HWC2::Error getDozeSupport(int32_t* outSupport); Loading @@ -208,6 +209,7 @@ private: HWC2::Error setActiveConfig(hwc2_config_t configId); HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace); HWC2::Error setColorMode(int32_t mode); HWC2::Error setColorTransform(android_color_transform_t hint); HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence); Loading Loading @@ -239,29 +241,43 @@ private: private: class Config { public: Config(Display& display, hwc2_config_t id, uint32_t hwcId) Config(Display& display) : mDisplay(display), mId(id), mHwcId(hwcId), mAttributes() {} bool isOnDisplay(const Display& display) const { return display.getId() == mDisplay.getId(); } hwc2_config_t getId() const { return mId; } uint32_t getHwcId() const { return mHwcId; } void setAttribute(HWC2::Attribute attribute, int32_t value); int32_t getAttribute(HWC2::Attribute attribute) const; std::string toString() const; void setHwc1Id(uint32_t id); bool hasHwc1Id(uint32_t id) const; int32_t getColorModeForHwc1Id(uint32_t id) const; HWC2::Error getHwc1IdForColorMode(int32_t mode, uint32_t* outId) const; void setId(hwc2_config_t id) { mId = id; } hwc2_config_t getId() const { return mId; } // Attempts to merge two configs that differ only in color // mode. Returns whether the merge was successful bool merge(const Config& other); std::set<int32_t> getColorTransforms() const; // splitLine divides the output into two lines suitable for // dumpsys SurfaceFlinger std::string toString(bool splitLine = false) const; private: Display& mDisplay; const hwc2_config_t mId; const uint32_t mHwcId; hwc2_config_t mId; std::unordered_map<HWC2::Attribute, int32_t> mAttributes; // Maps from color transform to HWC1 config ID std::unordered_map<int32_t, uint32_t> mHwc1Ids; }; class Changes { Loading Loading @@ -315,6 +331,9 @@ private: std::shared_ptr<const Config> getConfig(hwc2_config_t configId) const; void populateColorModes(); void initializeActiveConfig(); void reallocateHwc1Contents(); void assignHwc1LayerIds(); Loading Loading @@ -352,8 +371,11 @@ private: std::unique_ptr<Changes> mChanges; int32_t mHwc1Id; std::vector<std::shared_ptr<Config>> mConfigs; std::shared_ptr<const Config> mActiveConfig; std::set<int32_t> mColorModes; int32_t mActiveColorMode; std::string mName; HWC2::DisplayType mType; HWC2::PowerMode mPowerMode; Loading Loading
services/surfaceflinger/DisplayHardware/HWC2.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ Device::Device(hwc2_device_t* device) mDestroyLayer(nullptr), mGetActiveConfig(nullptr), mGetChangedCompositionTypes(nullptr), mGetColorModes(nullptr), mGetDisplayAttribute(nullptr), mGetDisplayConfigs(nullptr), mGetDisplayName(nullptr), Loading @@ -107,6 +108,7 @@ Device::Device(hwc2_device_t* device) mPresentDisplay(nullptr), mSetActiveConfig(nullptr), mSetClientTarget(nullptr), mSetColorMode(nullptr), mSetColorTransform(nullptr), mSetOutputBuffer(nullptr), mSetPowerMode(nullptr), Loading Loading @@ -339,6 +341,8 @@ void Device::loadFunctionPointers() mGetActiveConfig)) return; if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes, mGetChangedCompositionTypes)) return; if (!loadFunctionPointer(FunctionDescriptor::GetColorModes, mGetColorModes)) return; if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute, mGetDisplayAttribute)) return; if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs, Loading @@ -361,6 +365,8 @@ void Device::loadFunctionPointers() mSetActiveConfig)) return; if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget, mSetClientTarget)) return; if (!loadFunctionPointer(FunctionDescriptor::SetColorMode, mSetColorMode)) return; if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform, mSetColorTransform)) return; if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer, Loading Loading @@ -557,6 +563,28 @@ Error Display::getChangedCompositionTypes( return Error::None; } Error Display::getColorModes(std::vector<int32_t>* outModes) const { uint32_t numModes = 0; int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes, nullptr); auto error = static_cast<Error>(intError); if (error != Error::None) { return error; } std::vector<int32_t> modes(numModes); intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes, modes.data()); error = static_cast<Error>(intError); if (error != Error::None) { return error; } std::swap(*outModes, modes); return Error::None; } std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const { std::vector<std::shared_ptr<const Config>> configs; Loading Loading @@ -758,6 +786,12 @@ Error Display::setClientTarget(buffer_handle_t target, return static_cast<Error>(intError); } Error Display::setColorMode(int32_t mode) { int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode); return static_cast<Error>(intError); } Error Display::setColorTransform(const android::mat4& matrix, android_color_transform_t hint) { Loading
services/surfaceflinger/DisplayHardware/HWC2.h +5 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ private: HWC2_PFN_DESTROY_LAYER mDestroyLayer; HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig; HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes; HWC2_PFN_GET_COLOR_MODES mGetColorModes; HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute; HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs; HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName; Loading @@ -155,6 +156,7 @@ private: HWC2_PFN_PRESENT_DISPLAY mPresentDisplay; HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig; HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget; HWC2_PFN_SET_COLOR_MODE mSetColorMode; HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform; HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer; HWC2_PFN_SET_POWER_MODE mSetPowerMode; Loading Loading @@ -276,6 +278,8 @@ public: std::shared_ptr<const Config>* outConfig) const; [[clang::warn_unused_result]] Error getChangedCompositionTypes( std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes); [[clang::warn_unused_result]] Error getColorModes( std::vector<int32_t>* outModes) const; // Doesn't call into the HWC2 device, so no errors are possible std::vector<std::shared_ptr<const Config>> getConfigs() const; Loading @@ -300,6 +304,7 @@ public: buffer_handle_t target, const android::sp<android::Fence>& acquireFence, android_dataspace_t dataspace); [[clang::warn_unused_result]] Error setColorMode(int32_t mode); [[clang::warn_unused_result]] Error setColorTransform( const android::mat4& matrix, android_color_transform_t hint); [[clang::warn_unused_result]] Error setOutputBuffer( Loading
services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp +323 −53 Original line number Diff line number Diff line Loading @@ -75,6 +75,8 @@ static hwc2_function_pointer_t asFP(T function) using namespace HWC2; static constexpr Attribute ColorTransform = static_cast<Attribute>(6); namespace android { void HWC2On1Adapter::DisplayContentsDeleter::operator()( Loading Loading @@ -214,6 +216,10 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( displayHook<decltype(&Display::getChangedCompositionTypes), &Display::getChangedCompositionTypes, uint32_t*, hwc2_layer_t*, int32_t*>); case FunctionDescriptor::GetColorModes: return asFP<HWC2_PFN_GET_COLOR_MODES>( displayHook<decltype(&Display::getColorModes), &Display::getColorModes, uint32_t*, int32_t*>); case FunctionDescriptor::GetDisplayAttribute: return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>( getDisplayAttributeHook); Loading Loading @@ -261,6 +267,10 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( displayHook<decltype(&Display::setClientTarget), &Display::setClientTarget, buffer_handle_t, int32_t, int32_t>); case FunctionDescriptor::SetColorMode: return asFP<HWC2_PFN_SET_COLOR_MODE>( displayHook<decltype(&Display::setColorMode), &Display::setColorMode, int32_t>); case FunctionDescriptor::SetColorTransform: return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook); case FunctionDescriptor::SetOutputBuffer: Loading Loading @@ -686,6 +696,22 @@ Error HWC2On1Adapter::Display::getChangedCompositionTypes( return Error::None; } Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, int32_t* outModes) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!outModes) { *outNumModes = mColorModes.size(); return Error::None; } uint32_t numModes = std::min(*outNumModes, static_cast<uint32_t>(mColorModes.size())); std::copy_n(mColorModes.cbegin(), numModes, outModes); *outNumModes = numModes; return Error::None; } Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigs) { Loading Loading @@ -832,14 +858,27 @@ Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) if (!config) { return Error::BadConfig; } mActiveConfig = config; if (config == mActiveConfig) { return Error::None; } if (mDevice.mHwc1MinorVersion >= 4) { int error = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, static_cast<int>(configId)); ALOGE_IF(error != 0, "setActiveConfig: Failed to set active config on HWC1 (%d)", error); uint32_t hwc1Id = 0; auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id); if (error != Error::None) { return error; } int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, static_cast<int>(hwc1Id)); if (intError != 0) { ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", intError); return Error::BadConfig; } mActiveConfig = config; } return Error::None; } Loading @@ -855,6 +894,38 @@ Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, return Error::None; } Error HWC2On1Adapter::Display::setColorMode(int32_t mode) { std::unique_lock<std::recursive_mutex> lock (mStateMutex); ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); if (mode == mActiveColorMode) { return Error::None; } if (mColorModes.count(mode) == 0) { ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode); return Error::Unsupported; } uint32_t hwc1Config = 0; auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config); if (error != Error::None) { return error; } ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config); int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, hwc1Config); if (intError != 0) { ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError); return Error::Unsupported; } mActiveColorMode = mode; return Error::None; } Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); Loading Loading @@ -1017,7 +1088,17 @@ Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) return Error::None; } static constexpr uint32_t ATTRIBUTES[] = { static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, HWC_DISPLAY_DPI_X, HWC_DISPLAY_DPI_Y, HWC_DISPLAY_COLOR_TRANSFORM, HWC_DISPLAY_NO_ATTRIBUTE, }; static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = { HWC_DISPLAY_VSYNC_PERIOD, HWC_DISPLAY_WIDTH, HWC_DISPLAY_HEIGHT, Loading @@ -1025,9 +1106,23 @@ static constexpr uint32_t ATTRIBUTES[] = { HWC_DISPLAY_DPI_Y, HWC_DISPLAY_NO_ATTRIBUTE, }; static constexpr size_t NUM_ATTRIBUTES = sizeof(ATTRIBUTES) / sizeof(uint32_t); static constexpr uint32_t ATTRIBUTE_MAP[] = { static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR = sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t); static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR), "Attribute tables have unexpected sizes"); static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = { 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, 1, // HWC_DISPLAY_WIDTH = 2, 2, // HWC_DISPLAY_HEIGHT = 3, 3, // HWC_DISPLAY_DPI_X = 4, 4, // HWC_DISPLAY_DPI_Y = 5, 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6, }; static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = { 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, 1, // HWC_DISPLAY_WIDTH = 2, Loading @@ -1039,7 +1134,14 @@ static constexpr uint32_t ATTRIBUTE_MAP[] = { template <uint32_t attribute> static constexpr bool attributesMatch() { return ATTRIBUTES[ATTRIBUTE_MAP[attribute]] == attribute; bool match = (attribute == ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]); if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) { return match; } return match && (attribute == ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]); } static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(), "Tables out of sync"); Loading @@ -1047,6 +1149,8 @@ static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(), "Tables out of sync"); void HWC2On1Adapter::Display::populateConfigs() { Loading @@ -1067,52 +1171,74 @@ void HWC2On1Adapter::Display::populateConfigs() for (size_t c = 0; c < numConfigs; ++c) { uint32_t hwc1ConfigId = configs[c]; hwc2_config_t id = static_cast<hwc2_config_t>(mConfigs.size()); mConfigs.emplace_back( std::make_shared<Config>(*this, id, hwc1ConfigId)); auto& config = mConfigs[id]; int32_t values[NUM_ATTRIBUTES] = {}; mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES, values); config->setAttribute(Attribute::VsyncPeriod, values[ATTRIBUTE_MAP[HWC_DISPLAY_VSYNC_PERIOD]]); config->setAttribute(Attribute::Width, values[ATTRIBUTE_MAP[HWC_DISPLAY_WIDTH]]); config->setAttribute(Attribute::Height, values[ATTRIBUTE_MAP[HWC_DISPLAY_HEIGHT]]); config->setAttribute(Attribute::DpiX, values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_X]]); config->setAttribute(Attribute::DpiY, values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_Y]]); ALOGV("Found config: %s", config->toString().c_str()); } ALOGV("Getting active config"); if (mDevice.mHwc1Device->getActiveConfig != nullptr) { auto activeConfig = mDevice.mHwc1Device->getActiveConfig( mDevice.mHwc1Device, mHwc1Id); if (activeConfig >= 0) { ALOGV("Setting active config to %d", activeConfig); mActiveConfig = mConfigs[activeConfig]; auto newConfig = std::make_shared<Config>(*this); int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {}; bool hasColor = true; auto result = mDevice.mHwc1Device->getDisplayAttributes( mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITH_COLOR, values); if (result != 0) { mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values); hasColor = false; } auto attributeMap = hasColor ? ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR; newConfig->setAttribute(Attribute::VsyncPeriod, values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]); newConfig->setAttribute(Attribute::Width, values[attributeMap[HWC_DISPLAY_WIDTH]]); newConfig->setAttribute(Attribute::Height, values[attributeMap[HWC_DISPLAY_HEIGHT]]); newConfig->setAttribute(Attribute::DpiX, values[attributeMap[HWC_DISPLAY_DPI_X]]); newConfig->setAttribute(Attribute::DpiY, values[attributeMap[HWC_DISPLAY_DPI_Y]]); if (hasColor) { newConfig->setAttribute(ColorTransform, values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); } // We can only do this after attempting to read the color transform newConfig->setHwc1Id(hwc1ConfigId); for (auto& existingConfig : mConfigs) { if (existingConfig->merge(*newConfig)) { ALOGV("Merged config %d with existing config %u: %s", hwc1ConfigId, existingConfig->getId(), existingConfig->toString().c_str()); newConfig.reset(); break; } } else { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; } // If it wasn't merged with any existing config, add it to the end if (newConfig) { newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size())); ALOGV("Found new config %u: %s", newConfig->getId(), newConfig->toString().c_str()); mConfigs.emplace_back(std::move(newConfig)); } } initializeActiveConfig(); populateColorModes(); } void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); mConfigs.emplace_back(std::make_shared<Config>(*this, 0, 0)); mConfigs.emplace_back(std::make_shared<Config>(*this)); auto& config = mConfigs[0]; config->setAttribute(Attribute::Width, static_cast<int32_t>(width)); config->setAttribute(Attribute::Height, static_cast<int32_t>(height)); config->setHwc1Id(0); config->setId(0); mActiveConfig = config; } Loading Loading @@ -1496,17 +1622,23 @@ std::string HWC2On1Adapter::Display::dump() const output << "Power mode: " << to_string(mPowerMode) << " "; output << "Vsync: " << to_string(mVsyncEnabled) << '\n'; output << " " << mConfigs.size() << " Config" << (mConfigs.size() == 1 ? "" : "s") << " (* Active)\n"; for (const auto& config : mConfigs) { if (config == mActiveConfig) { output << " * " << config->toString(); output << " Color modes [active]:"; for (const auto& mode : mColorModes) { if (mode == mActiveColorMode) { output << " [" << mode << ']'; } else { output << " " << config->toString(); output << " " << mode; } } output << '\n'; output << " " << mConfigs.size() << " Config" << (mConfigs.size() == 1 ? "" : "s") << " (* active)\n"; for (const auto& config : mConfigs) { output << (config == mActiveConfig ? " * " : " "); output << config->toString(true) << '\n'; } output << " " << mLayers.size() << " Layer" << (mLayers.size() == 1 ? "" : "s") << '\n'; for (const auto& layer : mLayers) { Loading Loading @@ -1544,15 +1676,85 @@ int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const return mAttributes.at(attribute); } std::string HWC2On1Adapter::Display::Config::toString() const void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { int32_t colorTransform = getAttribute(ColorTransform); mHwc1Ids.emplace(colorTransform, id); } bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { return true; } } return false; } int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( uint32_t id) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { return idPair.first; } } return -1; } Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode, uint32_t* outId) const { for (const auto& idPair : mHwc1Ids) { if (mode == idPair.first) { *outId = idPair.second; return Error::None; } } ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId); return Error::BadParameter; } bool HWC2On1Adapter::Display::Config::merge(const Config& other) { auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, HWC2::Attribute::DpiY}; for (auto attribute : attributes) { if (getAttribute(attribute) != other.getAttribute(attribute)) { return false; } } int32_t otherColorTransform = other.getAttribute(ColorTransform); if (mHwc1Ids.count(otherColorTransform) != 0) { ALOGE("Attempted to merge two configs (%u and %u) which appear to be " "identical", mHwc1Ids.at(otherColorTransform), other.mHwc1Ids.at(otherColorTransform)); return false; } mHwc1Ids.emplace(otherColorTransform, other.mHwc1Ids.at(otherColorTransform)); return true; } std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const { std::set<int32_t> colorTransforms; for (const auto& idPair : mHwc1Ids) { colorTransforms.emplace(idPair.first); } return colorTransforms; } std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { std::string output; const size_t BUFFER_SIZE = 100; char buffer[BUFFER_SIZE] = {}; auto writtenBytes = snprintf(buffer, BUFFER_SIZE, "[%u] %u x %u", mHwcId, mAttributes.at(HWC2::Attribute::Width), "%u x %u", mAttributes.at(HWC2::Attribute::Width), mAttributes.at(HWC2::Attribute::Height)); output.append(buffer, writtenBytes); Loading @@ -1573,6 +1775,31 @@ std::string HWC2On1Adapter::Display::Config::toString() const output.append(buffer, writtenBytes); } std::memset(buffer, 0, BUFFER_SIZE); if (splitLine) { writtenBytes = snprintf(buffer, BUFFER_SIZE, "\n HWC1 ID/Color transform:"); } else { writtenBytes = snprintf(buffer, BUFFER_SIZE, ", HWC1 ID/Color transform:"); } output.append(buffer, writtenBytes); for (const auto& id : mHwc1Ids) { int32_t colorTransform = id.first; uint32_t hwc1Id = id.second; std::memset(buffer, 0, BUFFER_SIZE); if (colorTransform == mDisplay.mActiveColorMode) { writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, colorTransform); } else { writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, colorTransform); } output.append(buffer, writtenBytes); } return output; } Loading @@ -1585,6 +1812,49 @@ std::shared_ptr<const HWC2On1Adapter::Display::Config> return mConfigs[configId]; } void HWC2On1Adapter::Display::populateColorModes() { mColorModes = mConfigs[0]->getColorTransforms(); for (const auto& config : mConfigs) { std::set<int32_t> intersection; auto configModes = config->getColorTransforms(); std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), configModes.cbegin(), configModes.cend(), std::inserter(intersection, intersection.begin())); std::swap(intersection, mColorModes); } } void HWC2On1Adapter::Display::initializeActiveConfig() { if (mDevice.mHwc1Device->getActiveConfig == nullptr) { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; mActiveColorMode = -1; return; } auto activeConfig = mDevice.mHwc1Device->getActiveConfig( mDevice.mHwc1Device, mHwc1Id); if (activeConfig >= 0) { for (const auto& config : mConfigs) { if (config->hasHwc1Id(activeConfig)) { ALOGV("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); mActiveConfig = config; mActiveColorMode = config->getColorModeForHwc1Id(activeConfig); break; } } if (!mActiveConfig) { ALOGV("Unable to find active HWC1 config %u, defaulting to " "config 0", activeConfig); mActiveConfig = mConfigs[0]; mActiveColorMode = -1; } } } void HWC2On1Adapter::Display::reallocateHwc1Contents() { // Allocate an additional layer for the framebuffer target Loading
services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h +31 −9 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ private: HWC2::Attribute attribute, int32_t* outValue); HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes); HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); HWC2::Error getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigIds); HWC2::Error getDozeSupport(int32_t* outSupport); Loading @@ -208,6 +209,7 @@ private: HWC2::Error setActiveConfig(hwc2_config_t configId); HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace); HWC2::Error setColorMode(int32_t mode); HWC2::Error setColorTransform(android_color_transform_t hint); HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence); Loading Loading @@ -239,29 +241,43 @@ private: private: class Config { public: Config(Display& display, hwc2_config_t id, uint32_t hwcId) Config(Display& display) : mDisplay(display), mId(id), mHwcId(hwcId), mAttributes() {} bool isOnDisplay(const Display& display) const { return display.getId() == mDisplay.getId(); } hwc2_config_t getId() const { return mId; } uint32_t getHwcId() const { return mHwcId; } void setAttribute(HWC2::Attribute attribute, int32_t value); int32_t getAttribute(HWC2::Attribute attribute) const; std::string toString() const; void setHwc1Id(uint32_t id); bool hasHwc1Id(uint32_t id) const; int32_t getColorModeForHwc1Id(uint32_t id) const; HWC2::Error getHwc1IdForColorMode(int32_t mode, uint32_t* outId) const; void setId(hwc2_config_t id) { mId = id; } hwc2_config_t getId() const { return mId; } // Attempts to merge two configs that differ only in color // mode. Returns whether the merge was successful bool merge(const Config& other); std::set<int32_t> getColorTransforms() const; // splitLine divides the output into two lines suitable for // dumpsys SurfaceFlinger std::string toString(bool splitLine = false) const; private: Display& mDisplay; const hwc2_config_t mId; const uint32_t mHwcId; hwc2_config_t mId; std::unordered_map<HWC2::Attribute, int32_t> mAttributes; // Maps from color transform to HWC1 config ID std::unordered_map<int32_t, uint32_t> mHwc1Ids; }; class Changes { Loading Loading @@ -315,6 +331,9 @@ private: std::shared_ptr<const Config> getConfig(hwc2_config_t configId) const; void populateColorModes(); void initializeActiveConfig(); void reallocateHwc1Contents(); void assignHwc1LayerIds(); Loading Loading @@ -352,8 +371,11 @@ private: std::unique_ptr<Changes> mChanges; int32_t mHwc1Id; std::vector<std::shared_ptr<Config>> mConfigs; std::shared_ptr<const Config> mActiveConfig; std::set<int32_t> mColorModes; int32_t mActiveColorMode; std::string mName; HWC2::DisplayType mType; HWC2::PowerMode mPowerMode; Loading