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

Commit 9f26a9c8 authored by Dan Stoza's avatar Dan Stoza
Browse files

SF/HWC2: Add support for color transforms

Adds support for color transforms using the setColorTransform method
of HWC2.

This means that instead of always falling back to client composition
when applying a transform, SurfaceFlinger will allow the device to
make that decision. If all layers fall back to client composition, the
SKIP_CLIENT_COLOR_TRANSFORM capability allows the device greater
control over whether SF should apply the transform or whether it
should allow the device to apply it to the client target buffer.

Bug: 19539930
Change-Id: I47a3d5453a3c47a8dd105ab77cce7f9c9687e925
parent d47c07fe
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -317,9 +317,12 @@ void Device::loadCapabilities()
            "Capability size has changed");
    uint32_t numCapabilities = 0;
    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
    mCapabilities.resize(numCapabilities);
    auto asInt = reinterpret_cast<int32_t*>(mCapabilities.data());
    std::vector<Capability> capabilities(numCapabilities);
    auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
    for (auto capability : capabilities) {
        mCapabilities.emplace(capability);
    }
}

bool Device::hasCapability(HWC2::Capability capability) const
+3 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <functional>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace android {
@@ -66,7 +67,7 @@ public:

    std::string dump() const;

    const std::vector<Capability>& getCapabilities() const {
    const std::unordered_set<Capability>& getCapabilities() const {
        return mCapabilities;
    };

@@ -181,7 +182,7 @@ private:
    HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
    HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;

    std::vector<Capability> mCapabilities;
    std::unordered_set<Capability> mCapabilities;
    std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;

    HotplugCallback mHotplug;
+27 −0
Original line number Diff line number Diff line
@@ -144,6 +144,11 @@ void HWComposer::loadHwcModule()
    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}

bool HWComposer::hasCapability(HWC2::Capability capability) const
{
    return mHwcDevice->getCapabilities().count(capability) > 0;
}

bool HWComposer::isValidDisplay(int32_t displayId) const {
    return static_cast<size_t>(displayId) < mDisplayData.size() &&
            mDisplayData[displayId].hwcDisplay;
@@ -692,6 +697,28 @@ status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) {
    return NO_ERROR;
}

status_t HWComposer::setColorTransform(int32_t displayId,
        const mat4& transform) {
    if (!isValidDisplay(displayId)) {
        ALOGE("setColorTransform: Display %d is not valid", displayId);
        return BAD_INDEX;
    }

    auto& displayData = mDisplayData[displayId];
    bool isIdentity = transform == mat4();
    auto error = displayData.hwcDisplay->setColorTransform(transform,
            isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY :
            HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX);
    if (error != HWC2::Error::None) {
        ALOGE("setColorTransform: Failed to set transform on display %d: "
                "%s (%d)", displayId, to_string(error).c_str(),
                static_cast<int32_t>(error));
        return UNKNOWN_ERROR;
    }

    return NO_ERROR;
}

void HWComposer::disconnectDisplay(int displayId) {
    LOG_ALWAYS_FATAL_IF(displayId < 0);
    auto& displayData = mDisplayData[displayId];
+5 −0
Original line number Diff line number Diff line
@@ -81,6 +81,8 @@ public:

    void setEventHandler(EventHandler* handler);

    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,
@@ -104,6 +106,9 @@ public:
    // set active config
    status_t setActiveConfig(int32_t 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);

    // reset state when an external, non-virtual display is disconnected
    void disconnectDisplay(int32_t displayId);

+17 −18
Original line number Diff line number Diff line
@@ -19,21 +19,14 @@

namespace android {

Daltonizer::Daltonizer() :
    mType(deuteranomaly), mMode(simulation), mDirty(true) {
}

Daltonizer::~Daltonizer() {
}

void Daltonizer::setType(Daltonizer::ColorBlindnessTypes type) {
void Daltonizer::setType(ColorBlindnessType type) {
    if (type != mType) {
        mDirty = true;
        mType = type;
    }
}

void Daltonizer::setMode(Daltonizer::Mode mode) {
void Daltonizer::setMode(ColorBlindnessMode mode) {
    if (mode != mMode) {
        mDirty = true;
        mMode = mode;
@@ -49,6 +42,11 @@ const mat4& Daltonizer::operator()() {
}

void Daltonizer::update() {
    if (mType == ColorBlindnessType::None) {
        mColorTransform = mat4();
        return;
    }

    // converts a linear RGB color to the XYZ space
    const mat4 rgb2xyz( 0.4124, 0.2126, 0.0193, 0,
                        0.3576, 0.7152, 0.1192, 0,
@@ -149,24 +147,25 @@ void Daltonizer::update() {
    mat4 correction(0);

    switch (mType) {
        case protanopia:
        case protanomaly:
        case ColorBlindnessType::Protanomaly:
            simulation = lms2lmsp;
            if (mMode == Daltonizer::correction)
            if (mMode == ColorBlindnessMode::Correction)
                correction = errp;
            break;
        case deuteranopia:
        case deuteranomaly:
        case ColorBlindnessType::Deuteranomaly:
            simulation = lms2lmsd;
            if (mMode == Daltonizer::correction)
            if (mMode == ColorBlindnessMode::Correction)
                correction = errd;
            break;
        case tritanopia:
        case tritanomaly:
        case ColorBlindnessType::Tritanomaly:
            simulation = lms2lmst;
            if (mMode == Daltonizer::correction)
            if (mMode == ColorBlindnessMode::Correction)
                correction = errt;
            break;
        case ColorBlindnessType::None:
            // We already caught this at the beginning of the method, but the
            // compiler doesn't know that
            break;
    }

    mColorTransform = lms2rgb *
Loading