diff options
| author | 2019-03-07 20:58:12 -0800 | |
|---|---|---|
| committer | 2019-08-29 12:16:36 -0700 | |
| commit | 6a3b44698f365cb608f43df6e45844b4e18d3064 (patch) | |
| tree | 6c7aa5da03d734c89c182b74f24b7a24f4e60c4a | |
| parent | d3d6988c925732192b5349fe2a4b5689df0d1abb (diff) | |
SF: Move pickColorMode and getBestDataspace to CompositionEngine
Test: atest libsurfaceflinger_unittest libcompositionengine_test
Bug: 121291683
Change-Id: I37c39f49bf0e1c851d0d5e4040dc3aa3e433e9f8
14 files changed, 248 insertions, 184 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h index b329f76445..1001cf7e02 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h @@ -21,6 +21,7 @@ #include <compositionengine/Display.h> #include <compositionengine/Layer.h> +#include <compositionengine/OutputColorSetting.h> namespace android::compositionengine { @@ -42,6 +43,15 @@ struct CompositionRefreshArgs { // If true, forces the entire display to be considered dirty and repainted bool repaintEverything{false}; + // Controls how the color mode is chosen for an output + OutputColorSetting outputColorSetting{OutputColorSetting::kEnhanced}; + + // If not Dataspace::UNKNOWN, overrides the dataspace on each output + ui::Dataspace colorSpaceAgnosticDataspace{ui::Dataspace::UNKNOWN}; + + // Forces a color mode on the outputs being refreshed + ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE}; + // If set, causes the dirty regions to flash with the delay std::optional<std::chrono::microseconds> devOptFlashDirtyRegionsDelay; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index fa2bb46f17..82cde4b82e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -63,6 +63,13 @@ public: std::unordered_map<HWC2::Layer*, sp<Fence>> layerFences; }; + struct ColorProfile { + ui::ColorMode mode{ui::ColorMode::NATIVE}; + ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; + ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC}; + ui::Dataspace colorSpaceAgnosticDataspace{ui::Dataspace::UNKNOWN}; + }; + virtual ~Output(); // Returns true if the output is valid. This is meant to be checked post- @@ -87,8 +94,7 @@ public: virtual void setColorTransform(const mat4&) = 0; // Sets the output color mode - virtual void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, - ui::Dataspace colorSpaceAgnosticDataspace) = 0; + virtual void setColorProfile(const ColorProfile&) = 0; // Outputs a string with a state dump virtual void dump(std::string&) const = 0; @@ -153,6 +159,9 @@ public: // Takes (moves) the set of layers being released this frame. virtual ReleasedLayers takeReleasedLayers() = 0; + // Updates the color mode used on this output + virtual void updateColorProfile(const CompositionRefreshArgs&) = 0; + // Signals that a frame is beginning on the output virtual void beginFrame() = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputColorSetting.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputColorSetting.h new file mode 100644 index 0000000000..6e798cea55 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputColorSetting.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace android::compositionengine { + +enum class OutputColorSetting : int32_t { + kManaged = 0, + kUnmanaged = 1, + kEnhanced = 2, +}; + +} // namespace android::compositionengine
\ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index bdc1291873..dba112eb4e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -41,7 +41,7 @@ public: // compositionengine::Output overrides void dump(std::string&) const override; void setColorTransform(const mat4&) override; - void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; + void setColorProfile(const ColorProfile&) override; void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index b854314381..904edc791c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -45,7 +45,7 @@ public: void setLayerStackFilter(uint32_t layerStackId, bool isInternal) override; void setColorTransform(const mat4&) override; - void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; + void setColorProfile(const ColorProfile&) override; void dump(std::string&) const override; @@ -75,6 +75,8 @@ public: void setReleasedLayers(ReleasedLayers&&) override; ReleasedLayers takeReleasedLayers() override; + void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override; + void beginFrame() override; void prepareFrame() override; void devOptRepaintFlash(const compositionengine::CompositionRefreshArgs&) override; @@ -100,6 +102,9 @@ protected: private: void dirtyEntireOutput(); + ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const; + compositionengine::Output::ColorProfile pickColorProfile( + const compositionengine::CompositionRefreshArgs&) const; const CompositionEngine& mCompositionEngine; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index ade745c4f9..44cd5e99de 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -42,7 +42,7 @@ public: MOCK_METHOD2(setLayerStackFilter, void(uint32_t, bool)); MOCK_METHOD1(setColorTransform, void(const mat4&)); - MOCK_METHOD4(setColorMode, void(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace)); + MOCK_METHOD1(setColorProfile, void(const ColorProfile&)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_CONST_METHOD0(getName, const std::string&()); @@ -74,6 +74,8 @@ public: MOCK_METHOD1(setReleasedLayers, void(ReleasedLayers&&)); MOCK_METHOD0(takeReleasedLayers, ReleasedLayers()); + MOCK_METHOD1(updateColorProfile, void(const compositionengine::CompositionRefreshArgs&)); + MOCK_METHOD0(beginFrame, void()); MOCK_METHOD0(prepareFrame, void()); MOCK_METHOD0(chooseCompositionStrategy, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index cabbc085c8..108720a52b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -78,15 +78,15 @@ void Display::setColorTransform(const mat4& transform) { mId ? to_string(*mId).c_str() : "", result); } -void Display::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, - ui::RenderIntent renderIntent, - ui::Dataspace colorSpaceAgnosticDataspace) { - ui::Dataspace targetDataspace = - getDisplayColorProfile()->getTargetDataspace(mode, dataspace, - colorSpaceAgnosticDataspace); - - if (mode == getState().colorMode && dataspace == getState().dataspace && - renderIntent == getState().renderIntent && targetDataspace == getState().targetDataspace) { +void Display::setColorProfile(const ColorProfile& colorProfile) { + const ui::Dataspace targetDataspace = + getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace, + colorProfile.colorSpaceAgnosticDataspace); + + if (colorProfile.mode == getState().colorMode && + colorProfile.dataspace == getState().dataspace && + colorProfile.renderIntent == getState().renderIntent && + targetDataspace == getState().targetDataspace) { return; } @@ -95,10 +95,10 @@ void Display::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, return; } - Output::setColorMode(mode, dataspace, renderIntent, colorSpaceAgnosticDataspace); + Output::setColorProfile(colorProfile); auto& hwc = getCompositionEngine().getHwComposer(); - hwc.setActiveColorMode(*mId, mode, renderIntent); + hwc.setActiveColorMode(*mId, colorProfile.mode, colorProfile.renderIntent); } void Display::dump(std::string& out) const { diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 8b156f8e09..cc7e4533f4 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -114,28 +114,27 @@ void Output::setColorTransform(const mat4& transform) { dirtyEntireOutput(); } -void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace, - ui::RenderIntent renderIntent, - ui::Dataspace colorSpaceAgnosticDataspace) { - ui::Dataspace targetDataspace = - getDisplayColorProfile()->getTargetDataspace(mode, dataspace, - colorSpaceAgnosticDataspace); - - if (mState.colorMode == mode && mState.dataspace == dataspace && - mState.renderIntent == renderIntent && mState.targetDataspace == targetDataspace) { +void Output::setColorProfile(const ColorProfile& colorProfile) { + const ui::Dataspace targetDataspace = + getDisplayColorProfile()->getTargetDataspace(colorProfile.mode, colorProfile.dataspace, + colorProfile.colorSpaceAgnosticDataspace); + + if (mState.colorMode == colorProfile.mode && mState.dataspace == colorProfile.dataspace && + mState.renderIntent == colorProfile.renderIntent && + mState.targetDataspace == targetDataspace) { return; } - mState.colorMode = mode; - mState.dataspace = dataspace; - mState.renderIntent = renderIntent; + mState.colorMode = colorProfile.mode; + mState.dataspace = colorProfile.dataspace; + mState.renderIntent = colorProfile.renderIntent; mState.targetDataspace = targetDataspace; - mRenderSurface->setBufferDataspace(dataspace); + mRenderSurface->setBufferDataspace(colorProfile.dataspace); ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)", - decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(), - renderIntent); + decodeColorMode(colorProfile.mode).c_str(), colorProfile.mode, + decodeRenderIntent(colorProfile.renderIntent).c_str(), colorProfile.renderIntent); dirtyEntireOutput(); } @@ -261,6 +260,116 @@ Output::ReleasedLayers Output::takeReleasedLayers() { return std::move(mReleasedLayers); } +void Output::updateColorProfile(const compositionengine::CompositionRefreshArgs& refreshArgs) { + setColorProfile(pickColorProfile(refreshArgs)); +} + +// Returns a data space that fits all visible layers. The returned data space +// can only be one of +// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced) +// - Dataspace::DISPLAY_P3 +// - Dataspace::DISPLAY_BT2020 +// The returned HDR data space is one of +// - Dataspace::UNKNOWN +// - Dataspace::BT2020_HLG +// - Dataspace::BT2020_PQ +ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, + bool* outIsHdrClientComposition) const { + ui::Dataspace bestDataSpace = ui::Dataspace::V0_SRGB; + *outHdrDataSpace = ui::Dataspace::UNKNOWN; + + for (const auto& layer : mOutputLayersOrderedByZ) { + switch (layer->getLayer().getState().frontEnd.dataspace) { + case ui::Dataspace::V0_SCRGB: + case ui::Dataspace::V0_SCRGB_LINEAR: + case ui::Dataspace::BT2020: + case ui::Dataspace::BT2020_ITU: + case ui::Dataspace::BT2020_LINEAR: + case ui::Dataspace::DISPLAY_BT2020: + bestDataSpace = ui::Dataspace::DISPLAY_BT2020; + break; + case ui::Dataspace::DISPLAY_P3: + bestDataSpace = ui::Dataspace::DISPLAY_P3; + break; + case ui::Dataspace::BT2020_PQ: + case ui::Dataspace::BT2020_ITU_PQ: + bestDataSpace = ui::Dataspace::DISPLAY_P3; + *outHdrDataSpace = ui::Dataspace::BT2020_PQ; + *outIsHdrClientComposition = + layer->getLayer().getState().frontEnd.forceClientComposition; + break; + case ui::Dataspace::BT2020_HLG: + case ui::Dataspace::BT2020_ITU_HLG: + bestDataSpace = ui::Dataspace::DISPLAY_P3; + // When there's mixed PQ content and HLG content, we set the HDR + // data space to be BT2020_PQ and convert HLG to PQ. + if (*outHdrDataSpace == ui::Dataspace::UNKNOWN) { + *outHdrDataSpace = ui::Dataspace::BT2020_HLG; + } + break; + default: + break; + } + } + + return bestDataSpace; +} + +compositionengine::Output::ColorProfile Output::pickColorProfile( + const compositionengine::CompositionRefreshArgs& refreshArgs) const { + if (refreshArgs.outputColorSetting == OutputColorSetting::kUnmanaged) { + return ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN, + ui::RenderIntent::COLORIMETRIC, + refreshArgs.colorSpaceAgnosticDataspace}; + } + + ui::Dataspace hdrDataSpace; + bool isHdrClientComposition = false; + ui::Dataspace bestDataSpace = getBestDataspace(&hdrDataSpace, &isHdrClientComposition); + + switch (refreshArgs.forceOutputColorMode) { + case ui::ColorMode::SRGB: + bestDataSpace = ui::Dataspace::V0_SRGB; + break; + case ui::ColorMode::DISPLAY_P3: + bestDataSpace = ui::Dataspace::DISPLAY_P3; + break; + default: + break; + } + + // respect hdrDataSpace only when there is no legacy HDR support + const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN && + !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition; + if (isHdr) { + bestDataSpace = hdrDataSpace; + } + + ui::RenderIntent intent; + switch (refreshArgs.outputColorSetting) { + case OutputColorSetting::kManaged: + case OutputColorSetting::kUnmanaged: + intent = isHdr ? ui::RenderIntent::TONE_MAP_COLORIMETRIC + : ui::RenderIntent::COLORIMETRIC; + break; + case OutputColorSetting::kEnhanced: + intent = isHdr ? ui::RenderIntent::TONE_MAP_ENHANCE : ui::RenderIntent::ENHANCE; + break; + default: // vendor display color setting + intent = static_cast<ui::RenderIntent>(refreshArgs.outputColorSetting); + break; + } + + ui::ColorMode outMode; + ui::Dataspace outDataSpace; + ui::RenderIntent outRenderIntent; + mDisplayColorProfile->getBestColorMode(bestDataSpace, intent, &outDataSpace, &outMode, + &outRenderIntent); + + return ColorProfile{outMode, outDataSpace, outRenderIntent, + refreshArgs.colorSpaceAgnosticDataspace}; +} + void Output::beginFrame() { const bool dirty = !getDirtyRegion(false).isEmpty(); const bool empty = mOutputLayersOrderedByZ.empty(); diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index e9752605d4..06e3a70665 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -162,6 +162,8 @@ TEST_F(DisplayTest, setColorTransformSetsTransform) { */ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { + using ColorProfile = Output::ColorProfile; + mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>(); mDisplay.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface)); mock::DisplayColorProfile* colorProfile = new StrictMock<mock::DisplayColorProfile>(); @@ -177,8 +179,8 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { ASSERT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().targetDataspace); // If the set values are unchanged, nothing happens - mDisplay.setColorMode(ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN, - ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN); + mDisplay.setColorProfile(ColorProfile{ui::ColorMode::NATIVE, ui::Dataspace::UNKNOWN, + ui::RenderIntent::COLORIMETRIC, ui::Dataspace::UNKNOWN}); EXPECT_EQ(ui::ColorMode::NATIVE, mDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::UNKNOWN, mDisplay.getState().dataspace); @@ -192,8 +194,9 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { ui::RenderIntent::TONE_MAP_COLORIMETRIC)) .Times(1); - mDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); + mDisplay.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::RenderIntent::TONE_MAP_COLORIMETRIC, + ui::Dataspace::UNKNOWN}); EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace); @@ -202,6 +205,8 @@ TEST_F(DisplayTest, setColorModeSetsModeUnlessNoChange) { } TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { + using ColorProfile = Output::ColorProfile; + impl::Display virtualDisplay{mCompositionEngine, DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}}; @@ -214,8 +219,9 @@ TEST_F(DisplayTest, setColorModeDoesNothingForVirtualDisplay) { ui::Dataspace::UNKNOWN)) .WillOnce(Return(ui::Dataspace::UNKNOWN)); - virtualDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); + virtualDisplay.setColorProfile( + ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN}); EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode); EXPECT_EQ(ui::Dataspace::UNKNOWN, virtualDisplay.getState().dataspace); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index eddb67f45b..dccad58dde 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -211,14 +211,17 @@ TEST_F(OutputTest, setColorTransformSetsTransform) { */ TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) { + using ColorProfile = Output::ColorProfile; + EXPECT_CALL(*mDisplayColorProfile, getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, ui::Dataspace::UNKNOWN)) .WillOnce(Return(ui::Dataspace::UNKNOWN)); EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1); - mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); + mOutput.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::RenderIntent::TONE_MAP_COLORIMETRIC, + ui::Dataspace::UNKNOWN}); EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode); EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace); @@ -229,6 +232,8 @@ TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) { } TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) { + using ColorProfile = Output::ColorProfile; + EXPECT_CALL(*mDisplayColorProfile, getTargetDataspace(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, ui::Dataspace::UNKNOWN)) @@ -239,8 +244,9 @@ TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) { mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC; mOutput.editState().targetDataspace = ui::Dataspace::UNKNOWN; - mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, - ui::RenderIntent::TONE_MAP_COLORIMETRIC, ui::Dataspace::UNKNOWN); + mOutput.setColorProfile(ColorProfile{ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3, + ui::RenderIntent::TONE_MAP_COLORIMETRIC, + ui::Dataspace::UNKNOWN}); EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region())); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1875151376..83f3b2cecd 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -239,11 +239,11 @@ bool useTrebleTestingOverride() { std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { switch(displayColorSetting) { - case DisplayColorSetting::MANAGED: + case DisplayColorSetting::kManaged: return std::string("Managed"); - case DisplayColorSetting::UNMANAGED: + case DisplayColorSetting::kUnmanaged: return std::string("Unmanaged"); - case DisplayColorSetting::ENHANCED: + case DisplayColorSetting::kEnhanced: return std::string("Enhanced"); default: return std::string("Unknown ") + @@ -1133,9 +1133,10 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col ALOGW("Attempt to set active color mode %s (%d) for virtual display", decodeColorMode(mode).c_str(), mode); } else { - display->getCompositionDisplay()->setColorMode(mode, Dataspace::UNKNOWN, - RenderIntent::COLORIMETRIC, - Dataspace::UNKNOWN); + display->getCompositionDisplay()->setColorProfile( + compositionengine::Output::ColorProfile{mode, Dataspace::UNKNOWN, + RenderIntent::COLORIMETRIC, + Dataspace::UNKNOWN}); } })); @@ -1788,6 +1789,11 @@ void SurfaceFlinger::handleMessageRefresh() { if (compositionLayer) refreshArgs.layers.push_back(compositionLayer); }); refreshArgs.repaintEverything = mRepaintEverything.exchange(false); + refreshArgs.outputColorSetting = useColorManagement + ? mDisplayColorSetting + : compositionengine::OutputColorSetting::kUnmanaged; + refreshArgs.colorSpaceAgnosticDataspace = mColorSpaceAgnosticDataspace; + refreshArgs.forceOutputColorMode = mForceColorMode; if (mDebugRegion != 0) { refreshArgs.devOptFlashDirtyRegionsDelay = std::chrono::milliseconds(mDebugRegion > 1 ? mDebugRegion : 0); @@ -1795,7 +1801,7 @@ void SurfaceFlinger::handleMessageRefresh() { mCompositionEngine->preComposition(refreshArgs); rebuildLayerStacks(); - calculateWorkingSet(); + calculateWorkingSet(refreshArgs); for (const auto& [token, displayDevice] : mDisplays) { auto display = displayDevice->getCompositionDisplay(); display->beginFrame(); @@ -1852,7 +1858,8 @@ bool SurfaceFlinger::handleMessageInvalidate() { return refreshNeeded; } -void SurfaceFlinger::calculateWorkingSet() { +void SurfaceFlinger::calculateWorkingSet( + const compositionengine::CompositionRefreshArgs& refreshArgs) { ATRACE_CALL(); ALOGV(__FUNCTION__); @@ -1884,14 +1891,7 @@ void SurfaceFlinger::calculateWorkingSet() { // Determine the color configuration of each output for (const auto& [token, displayDevice] : mDisplays) { auto display = displayDevice->getCompositionDisplay(); - - ColorMode colorMode = ColorMode::NATIVE; - Dataspace dataspace = Dataspace::UNKNOWN; - RenderIntent renderIntent = RenderIntent::COLORIMETRIC; - if (useColorManagement) { - pickColorMode(displayDevice, &colorMode, &dataspace, &renderIntent); - } - display->setColorMode(colorMode, dataspace, renderIntent, mColorSpaceAgnosticDataspace); + display->updateColorProfile(refreshArgs); } for (const auto& [token, displayDevice] : mDisplays) { @@ -2219,109 +2219,6 @@ void SurfaceFlinger::rebuildLayerStacks() { } } -// Returns a data space that fits all visible layers. The returned data space -// can only be one of -// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced) -// - Dataspace::DISPLAY_P3 -// - Dataspace::DISPLAY_BT2020 -// The returned HDR data space is one of -// - Dataspace::UNKNOWN -// - Dataspace::BT2020_HLG -// - Dataspace::BT2020_PQ -Dataspace SurfaceFlinger::getBestDataspace(const sp<DisplayDevice>& display, - Dataspace* outHdrDataSpace, - bool* outIsHdrClientComposition) const { - Dataspace bestDataSpace = Dataspace::V0_SRGB; - *outHdrDataSpace = Dataspace::UNKNOWN; - - for (const auto& layer : display->getVisibleLayersSortedByZ()) { - switch (layer->getDataSpace()) { - case Dataspace::V0_SCRGB: - case Dataspace::V0_SCRGB_LINEAR: - case Dataspace::BT2020: - case Dataspace::BT2020_ITU: - case Dataspace::BT2020_LINEAR: - case Dataspace::DISPLAY_BT2020: - bestDataSpace = Dataspace::DISPLAY_BT2020; - break; - case Dataspace::DISPLAY_P3: - bestDataSpace = Dataspace::DISPLAY_P3; - break; - case Dataspace::BT2020_PQ: - case Dataspace::BT2020_ITU_PQ: - bestDataSpace = Dataspace::DISPLAY_P3; - *outHdrDataSpace = Dataspace::BT2020_PQ; - *outIsHdrClientComposition = - layer->getCompositionLayer()->getState().frontEnd.forceClientComposition; - break; - case Dataspace::BT2020_HLG: - case Dataspace::BT2020_ITU_HLG: - bestDataSpace = Dataspace::DISPLAY_P3; - // When there's mixed PQ content and HLG content, we set the HDR - // data space to be BT2020_PQ and convert HLG to PQ. - if (*outHdrDataSpace == Dataspace::UNKNOWN) { - *outHdrDataSpace = Dataspace::BT2020_HLG; - } - break; - default: - break; - } - } - - return bestDataSpace; -} - -// Pick the ColorMode / Dataspace for the display device. -void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode* outMode, - Dataspace* outDataSpace, RenderIntent* outRenderIntent) const { - if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) { - *outMode = ColorMode::NATIVE; - *outDataSpace = Dataspace::UNKNOWN; - *outRenderIntent = RenderIntent::COLORIMETRIC; - return; - } - - Dataspace hdrDataSpace; - bool isHdrClientComposition = false; - Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace, &isHdrClientComposition); - - auto* profile = display->getCompositionDisplay()->getDisplayColorProfile(); - - switch (mForceColorMode) { - case ColorMode::SRGB: - bestDataSpace = Dataspace::V0_SRGB; - break; - case ColorMode::DISPLAY_P3: - bestDataSpace = Dataspace::DISPLAY_P3; - break; - default: - break; - } - - // respect hdrDataSpace only when there is no legacy HDR support - const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN && - !profile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition; - if (isHdr) { - bestDataSpace = hdrDataSpace; - } - - RenderIntent intent; - switch (mDisplayColorSetting) { - case DisplayColorSetting::MANAGED: - case DisplayColorSetting::UNMANAGED: - intent = isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC; - break; - case DisplayColorSetting::ENHANCED: - intent = isHdr ? RenderIntent::TONE_MAP_ENHANCE : RenderIntent::ENHANCE; - break; - default: // vendor display color setting - intent = static_cast<RenderIntent>(mDisplayColorSetting); - break; - } - - profile->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent); -} - void SurfaceFlinger::postFrame() { // |mStateLock| not needed as we are on the main thread @@ -2469,8 +2366,10 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( defaultColorMode = ColorMode::SRGB; defaultDataSpace = Dataspace::V0_SRGB; } - display->getCompositionDisplay()->setColorMode(defaultColorMode, defaultDataSpace, - RenderIntent::COLORIMETRIC, Dataspace::UNKNOWN); + display->getCompositionDisplay()->setColorProfile( + compositionengine::Output::ColorProfile{defaultColorMode, defaultDataSpace, + RenderIntent::COLORIMETRIC, + Dataspace::UNKNOWN}); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); @@ -5028,13 +4927,13 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r DisplayColorSetting setting = static_cast<DisplayColorSetting>(data.readInt32()); switch (setting) { - case DisplayColorSetting::MANAGED: + case DisplayColorSetting::kManaged: reply->writeBool(useColorManagement); break; - case DisplayColorSetting::UNMANAGED: + case DisplayColorSetting::kUnmanaged: reply->writeBool(true); break; - case DisplayColorSetting::ENHANCED: + case DisplayColorSetting::kEnhanced: reply->writeBool(display->hasRenderIntent(RenderIntent::ENHANCE)); break; default: // vendor display color setting diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9acd9750b7..1aa99fccfd 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -23,6 +23,7 @@ */ #include <android-base/thread_annotations.h> +#include <compositionengine/OutputColorSetting.h> #include <cutils/atomic.h> #include <cutils/compiler.h> #include <gui/BufferQueue.h> @@ -97,6 +98,8 @@ class TimeStats; namespace compositionengine { class DisplaySurface; + +struct CompositionRefreshArgs; } // namespace compositionengine namespace renderengine { @@ -116,11 +119,7 @@ enum { eTransactionMask = 0x1f, }; -enum class DisplayColorSetting : int32_t { - MANAGED = 0, - UNMANAGED = 1, - ENHANCED = 2, -}; +using DisplayColorSetting = compositionengine::OutputColorSetting; class SurfaceFlingerBE { @@ -752,16 +751,7 @@ private: nsecs_t compositeToPresentLatency); void rebuildLayerStacks(); - ui::Dataspace getBestDataspace(const sp<DisplayDevice>& display, ui::Dataspace* outHdrDataSpace, - bool* outIsHdrClientComposition) const; - - // Returns the appropriate ColorMode, Dataspace and RenderIntent for the - // DisplayDevice. The function only returns the supported ColorMode, - // Dataspace and RenderIntent. - void pickColorMode(const sp<DisplayDevice>& display, ui::ColorMode* outMode, - ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const; - - void calculateWorkingSet(); + void calculateWorkingSet(const compositionengine::CompositionRefreshArgs&); void postFrame(); @@ -1071,7 +1061,7 @@ private: static bool useVrFlinger; std::thread::id mMainThreadId = std::this_thread::get_id(); - DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED; + DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::kEnhanced; // Color mode forced by setting persist.sys.sf.color_mode, it must: // 1. not be NATIVE color mode, NATIVE color mode means no forced color mode; diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 57851bc850..3e290160b3 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -33,6 +33,7 @@ cc_test { "libutils", ], static_libs: [ + "libcompositionengine", "libgmock", "libperfetto_client_experimental", "librenderengine", diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index c858cc0b95..fcce57b382 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -149,7 +149,7 @@ DisplayTransactionTest::DisplayTransactionTest() { // Default to no wide color display support configured mFlinger.mutableHasWideColorDisplay() = false; mFlinger.mutableUseColorManagement() = false; - mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED; + mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; // Default to using HWC virtual displays mFlinger.mutableUseHwcVirtualDisplays() = true; @@ -598,7 +598,7 @@ struct WideColorSupportNotConfiguredVariant { static void injectConfigChange(DisplayTransactionTest* test) { test->mFlinger.mutableHasWideColorDisplay() = false; test->mFlinger.mutableUseColorManagement() = false; - test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED; + test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } static void setupComposerCallExpectations(DisplayTransactionTest* test) { @@ -618,7 +618,7 @@ struct WideColorP3ColorimetricSupportedVariant { static void injectConfigChange(DisplayTransactionTest* test) { test->mFlinger.mutableUseColorManagement() = true; test->mFlinger.mutableHasWideColorDisplay() = true; - test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::UNMANAGED; + test->mFlinger.mutableDisplayColorSetting() = DisplayColorSetting::kUnmanaged; } static void setupComposerCallExpectations(DisplayTransactionTest* test) { |