Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91ea3c08 authored by Dan Stoza's avatar Dan Stoza Committed by android-build-merger
Browse files

HWC2: Add support for color modes

am: 076ac670

* commit '076ac670':
  HWC2: Add support for color modes

Change-Id: I349c7bf51e6840fc69320f029a995b714a2d502f
parents 23df91dd 076ac670
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ Device::Device(hwc2_device_t* device)
    mDestroyLayer(nullptr),
    mGetActiveConfig(nullptr),
    mGetChangedCompositionTypes(nullptr),
    mGetColorModes(nullptr),
    mGetDisplayAttribute(nullptr),
    mGetDisplayConfigs(nullptr),
    mGetDisplayName(nullptr),
@@ -107,6 +108,7 @@ Device::Device(hwc2_device_t* device)
    mPresentDisplay(nullptr),
    mSetActiveConfig(nullptr),
    mSetClientTarget(nullptr),
    mSetColorMode(nullptr),
    mSetColorTransform(nullptr),
    mSetOutputBuffer(nullptr),
    mSetPowerMode(nullptr),
@@ -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,
@@ -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,
@@ -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;
@@ -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)
{
+5 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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(
+323 −53
Original line number Diff line number Diff line
@@ -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()(
@@ -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);
@@ -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:
@@ -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)
{
@@ -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;
}

@@ -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);
@@ -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,
@@ -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,
@@ -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");
@@ -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()
{
@@ -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;
}

@@ -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) {
@@ -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);

@@ -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;
}

@@ -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
+31 −9
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -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 {
@@ -315,6 +331,9 @@ private:
            std::shared_ptr<const Config>
                    getConfig(hwc2_config_t configId) const;

            void populateColorModes();
            void initializeActiveConfig();

            void reallocateHwc1Contents();
            void assignHwc1LayerIds();

@@ -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;