diff options
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2.cpp | 7 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 27 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/Effects/Daltonizer.cpp | 35 | ||||
| -rw-r--r-- | services/surfaceflinger/Effects/Daltonizer.h | 39 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 70 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 16 |
9 files changed, 131 insertions, 76 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index ae6ba98bd5..87a0e9a13a 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -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 diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 68781da2c3..beb7bc6689 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -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; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 133e5f1f6d..199848f767 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -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]; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index aa233df1db..17676ae5f0 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -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); diff --git a/services/surfaceflinger/Effects/Daltonizer.cpp b/services/surfaceflinger/Effects/Daltonizer.cpp index feb8936cdf..a104e8f780 100644 --- a/services/surfaceflinger/Effects/Daltonizer.cpp +++ b/services/surfaceflinger/Effects/Daltonizer.cpp @@ -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 * diff --git a/services/surfaceflinger/Effects/Daltonizer.h b/services/surfaceflinger/Effects/Daltonizer.h index e81643747d..d21b155f85 100644 --- a/services/surfaceflinger/Effects/Daltonizer.h +++ b/services/surfaceflinger/Effects/Daltonizer.h @@ -21,27 +21,22 @@ namespace android { +enum class ColorBlindnessType { + None, // Disables the Daltonizer + Protanomaly, // L (red) cone deficient + Deuteranomaly, // M (green) cone deficient (most common) + Tritanomaly // S (blue) cone deficient +}; + +enum class ColorBlindnessMode { + Simulation, + Correction +}; + class Daltonizer { public: - enum ColorBlindnessTypes { - protanopia, // L (red) cone missing - deuteranopia, // M (green) cone missing - tritanopia, // S (blue) cone missing - protanomaly, // L (red) cone deficient - deuteranomaly, // M (green) cone deficient (most common) - tritanomaly // S (blue) cone deficient - }; - - enum Mode { - simulation, - correction - }; - - Daltonizer(); - ~Daltonizer(); - - void setType(ColorBlindnessTypes type); - void setMode(Mode mode); + void setType(ColorBlindnessType type); + void setMode(ColorBlindnessMode mode); // returns the color transform to apply in the shader const mat4& operator()(); @@ -49,9 +44,9 @@ public: private: void update(); - ColorBlindnessTypes mType; - Mode mMode; - bool mDirty; + ColorBlindnessType mType = ColorBlindnessType::None; + ColorBlindnessMode mMode = ColorBlindnessMode::Simulation; + bool mDirty = true; mat4 mColorTransform; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5c7db2b32f..f298399ac5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -152,7 +152,6 @@ SurfaceFlinger::SurfaceFlinger() mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), mHWVsyncAvailable(false), - mDaltonize(false), mHasColorMatrix(false), mHasPoweredOff(false), mFrameBuckets(), @@ -1224,8 +1223,7 @@ void SurfaceFlinger::setUpHWComposer() { } layer->setGeometry(displayDevice); - if (mDebugDisableHWC || mDebugRegion || mDaltonize || - mHasColorMatrix) { + if (mDebugDisableHWC || mDebugRegion) { layer->forceClientComposition(hwcId); } } @@ -1233,6 +1231,9 @@ void SurfaceFlinger::setUpHWComposer() { } } + + mat4 colorMatrix = mColorMatrix * mDaltonizer(); + // Set the per-frame data for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; @@ -1240,11 +1241,18 @@ void SurfaceFlinger::setUpHWComposer() { if (hwcId < 0) { continue; } + if (colorMatrix != mPreviousColorMatrix) { + status_t result = mHwc->setColorTransform(hwcId, colorMatrix); + ALOGE_IF(result != NO_ERROR, "Failed to set color transform on " + "display %zd: %d", displayId, result); + } for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { layer->setPerFrameData(displayDevice); } } + mPreviousColorMatrix = colorMatrix; + for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; if (!displayDevice->isDisplayOn()) { @@ -1926,18 +1934,7 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw, } } - if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) { - if (!doComposeSurfaces(hw, dirtyRegion)) return; - } else { - RenderEngine& engine(getRenderEngine()); - mat4 colorMatrix = mColorMatrix; - if (mDaltonize) { - colorMatrix = colorMatrix * mDaltonizer(); - } - mat4 oldMatrix = engine.setupColorTransform(colorMatrix); - doComposeSurfaces(hw, dirtyRegion); - engine.setupColorTransform(oldMatrix); - } + if (!doComposeSurfaces(hw, dirtyRegion)) return; // update the swap region and clear the dirty region hw->swapRegion.orSelf(dirtyRegion); @@ -1952,6 +1949,15 @@ bool SurfaceFlinger::doComposeSurfaces( ALOGV("doComposeSurfaces"); const auto hwcId = displayDevice->getHwcDisplayId(); + + mat4 oldColorMatrix; + const bool applyColorMatrix = !mHwc->hasDeviceComposition(hwcId) && + !mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform); + if (applyColorMatrix) { + mat4 colorMatrix = mColorMatrix * mDaltonizer(); + oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix); + } + bool hasClientComposition = mHwc->hasClientComposition(hwcId); if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -2069,6 +2075,10 @@ bool SurfaceFlinger::doComposeSurfaces( } } + if (applyColorMatrix) { + getRenderEngine().setupColorTransform(oldColorMatrix); + } + // disable scissor at the end of the frame mRenderEngine->disableScissor(); return true; @@ -2944,8 +2954,7 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, colorizer.bold(result); result.append("h/w composer state:\n"); colorizer.reset(result); - bool hwcDisabled = mDebugDisableHWC || mDebugRegion || mDaltonize || - mHasColorMatrix; + bool hwcDisabled = mDebugDisableHWC || mDebugRegion; result.appendFormat(" h/w composer %s\n", hwcDisabled ? "disabled" : "enabled"); hwc.dump(result); @@ -3100,16 +3109,24 @@ status_t SurfaceFlinger::onTransact( // daltonize n = data.readInt32(); switch (n % 10) { - case 1: mDaltonizer.setType(Daltonizer::protanomaly); break; - case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break; - case 3: mDaltonizer.setType(Daltonizer::tritanomaly); break; + case 1: + mDaltonizer.setType(ColorBlindnessType::Protanomaly); + break; + case 2: + mDaltonizer.setType(ColorBlindnessType::Deuteranomaly); + break; + case 3: + mDaltonizer.setType(ColorBlindnessType::Tritanomaly); + break; + default: + mDaltonizer.setType(ColorBlindnessType::None); + break; } if (n >= 10) { - mDaltonizer.setMode(Daltonizer::correction); + mDaltonizer.setMode(ColorBlindnessMode::Correction); } else { - mDaltonizer.setMode(Daltonizer::simulation); + mDaltonizer.setMode(ColorBlindnessMode::Simulation); } - mDaltonize = n > 0; invalidateHwcGeometry(); repaintEverything(); return NO_ERROR; @@ -3117,15 +3134,14 @@ status_t SurfaceFlinger::onTransact( case 1015: { // apply a color matrix n = data.readInt32(); - mHasColorMatrix = n ? 1 : 0; if (n) { // color matrix is sent as mat3 matrix followed by vec3 // offset, then packed into a mat4 where the last row is // the offset and extra values are 0 for (size_t i = 0 ; i < 4; i++) { - for (size_t j = 0; j < 4; j++) { - mColorMatrix[i][j] = data.readFloat(); - } + for (size_t j = 0; j < 4; j++) { + mColorMatrix[i][j] = data.readFloat(); + } } } else { mColorMatrix = mat4(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0df39a45f0..f063aaf2c6 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -527,8 +527,11 @@ private: */ Daltonizer mDaltonizer; +#ifndef USE_HWC2 bool mDaltonize; +#endif + mat4 mPreviousColorMatrix; mat4 mColorMatrix; bool mHasColorMatrix; diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 69fb8c523d..7062ea2511 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -3080,14 +3080,20 @@ status_t SurfaceFlinger::onTransact( // daltonize n = data.readInt32(); switch (n % 10) { - case 1: mDaltonizer.setType(Daltonizer::protanomaly); break; - case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break; - case 3: mDaltonizer.setType(Daltonizer::tritanomaly); break; + case 1: + mDaltonizer.setType(ColorBlindnessType::Protanomaly); + break; + case 2: + mDaltonizer.setType(ColorBlindnessType::Deuteranomaly); + break; + case 3: + mDaltonizer.setType(ColorBlindnessType::Tritanomaly); + break; } if (n >= 10) { - mDaltonizer.setMode(Daltonizer::correction); + mDaltonizer.setMode(ColorBlindnessMode::Correction); } else { - mDaltonizer.setMode(Daltonizer::simulation); + mDaltonizer.setMode(ColorBlindnessMode::Simulation); } mDaltonize = n > 0; invalidateHwcGeometry(); |